]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.cc] all: merge default (e4ab8f908aac) into dev.cc
authorRuss Cox <rsc@golang.org>
Thu, 20 Nov 2014 16:48:08 +0000 (11:48 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 20 Nov 2014 16:48:08 +0000 (11:48 -0500)
TBR=austin
CC=golang-codereviews
https://golang.org/cl/179040044

533 files changed:
.hgignore
dev.cc [new file with mode: 0644]
include/link.h
lib/codereview/codereview.cfg
lib/codereview/codereview.py
src/cmd/5a/a.h
src/cmd/5a/a.y
src/cmd/5a/y.tab.c
src/cmd/5a/y.tab.h
src/cmd/5c/cgen.c [deleted file]
src/cmd/5c/doc.go [deleted file]
src/cmd/5c/gc.h [deleted file]
src/cmd/5c/mul.c [deleted file]
src/cmd/5c/peep.c [deleted file]
src/cmd/5c/reg.c [deleted file]
src/cmd/5c/sgen.c [deleted file]
src/cmd/5c/swt.c [deleted file]
src/cmd/5c/txt.c [deleted file]
src/cmd/5g/gobj.c
src/cmd/5g/gsubr.c
src/cmd/5g/opt.h
src/cmd/5g/reg.c
src/cmd/5l/5.out.h
src/cmd/6a/a.h
src/cmd/6a/a.y
src/cmd/6a/y.tab.c
src/cmd/6c/Makefile [deleted file]
src/cmd/6c/cgen.c [deleted file]
src/cmd/6c/div.c [deleted file]
src/cmd/6c/doc.go [deleted file]
src/cmd/6c/gc.h [deleted file]
src/cmd/6c/list.c [deleted file]
src/cmd/6c/machcap.c [deleted file]
src/cmd/6c/mul.c [deleted file]
src/cmd/6c/peep.c [deleted file]
src/cmd/6c/reg.c [deleted file]
src/cmd/6c/sgen.c [deleted file]
src/cmd/6c/swt.c [deleted file]
src/cmd/6c/txt.c [deleted file]
src/cmd/6g/gobj.c
src/cmd/6g/opt.h
src/cmd/6g/reg.c
src/cmd/6l/6.out.h
src/cmd/8a/a.h
src/cmd/8a/a.y
src/cmd/8a/y.tab.c
src/cmd/8c/Makefile [deleted file]
src/cmd/8c/cgen.c [deleted file]
src/cmd/8c/cgen64.c [deleted file]
src/cmd/8c/div.c [deleted file]
src/cmd/8c/doc.go [deleted file]
src/cmd/8c/gc.h [deleted file]
src/cmd/8c/list.c [deleted file]
src/cmd/8c/machcap.c [deleted file]
src/cmd/8c/mul.c [deleted file]
src/cmd/8c/peep.c [deleted file]
src/cmd/8c/reg.c [deleted file]
src/cmd/8c/sgen.c [deleted file]
src/cmd/8c/swt.c [deleted file]
src/cmd/8c/txt.c [deleted file]
src/cmd/8g/gobj.c
src/cmd/8g/opt.h
src/cmd/8g/reg.c
src/cmd/8l/8.out.h
src/cmd/9a/Makefile [moved from src/cmd/cc/Makefile with 55% similarity]
src/cmd/9a/a.h [new file with mode: 0644]
src/cmd/9a/a.y [new file with mode: 0644]
src/cmd/9a/doc.go [new file with mode: 0644]
src/cmd/9a/lex.c [new file with mode: 0644]
src/cmd/9a/y.tab.c [new file with mode: 0644]
src/cmd/9a/y.tab.h [new file with mode: 0644]
src/cmd/9g/cgen.c [new file with mode: 0644]
src/cmd/9g/doc.go [new file with mode: 0644]
src/cmd/9g/galign.c [new file with mode: 0644]
src/cmd/9g/gg.h [new file with mode: 0644]
src/cmd/9g/ggen.c [new file with mode: 0644]
src/cmd/9g/gobj.c [new file with mode: 0644]
src/cmd/9g/gsubr.c [new file with mode: 0644]
src/cmd/9g/opt.h [new file with mode: 0644]
src/cmd/9g/peep.c [moved from src/cmd/cc/bits.c with 65% similarity]
src/cmd/9g/prog.c [new file with mode: 0644]
src/cmd/9g/reg.c [new file with mode: 0644]
src/cmd/9l/9.out.h [new file with mode: 0644]
src/cmd/9l/Makefile [moved from src/cmd/5c/Makefile with 100% similarity]
src/cmd/9l/asm.c [new file with mode: 0644]
src/cmd/9l/doc.go [moved from src/cmd/cc/doc.go with 55% similarity]
src/cmd/9l/l.h [new file with mode: 0644]
src/cmd/9l/list.c [moved from src/cmd/5c/list.c with 91% similarity]
src/cmd/9l/obj.c [new file with mode: 0644]
src/cmd/cc/acid.c [deleted file]
src/cmd/cc/cc.h [deleted file]
src/cmd/cc/cc.y [deleted file]
src/cmd/cc/com.c [deleted file]
src/cmd/cc/com64.c [deleted file]
src/cmd/cc/dcl.c [deleted file]
src/cmd/cc/dpchk.c [deleted file]
src/cmd/cc/funct.c [deleted file]
src/cmd/cc/godefs.c [deleted file]
src/cmd/cc/lex.c [deleted file]
src/cmd/cc/lexbody
src/cmd/cc/mac.c [deleted file]
src/cmd/cc/omachcap.c [deleted file]
src/cmd/cc/pgen.c [deleted file]
src/cmd/cc/pswt.c [deleted file]
src/cmd/cc/scon.c [deleted file]
src/cmd/cc/sub.c [deleted file]
src/cmd/cc/y.tab.c [deleted file]
src/cmd/cc/y.tab.h [deleted file]
src/cmd/cgo/main.go
src/cmd/cgo/out.go
src/cmd/dist/build.c
src/cmd/dist/buildgc.c
src/cmd/dist/buildruntime.c
src/cmd/dist/unix.c
src/cmd/gc/bits.c
src/cmd/gc/export.c
src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/obj.c
src/cmd/gc/pgen.c
src/cmd/gc/plive.c
src/cmd/gc/reflect.c
src/cmd/gc/subr.c
src/cmd/gc/walk.c
src/cmd/go/build.go
src/cmd/ld/data.c
src/cmd/ld/doc.go
src/cmd/ld/dwarf.c
src/cmd/ld/elf.c
src/cmd/ld/ldelf.c
src/cmd/ld/lib.c
src/cmd/ld/macho.c
src/cmd/ld/symtab.c
src/cmd/objdump/objdump_test.go
src/debug/elf/elf.go
src/debug/elf/file.go
src/debug/elf/file_test.go
src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj [new file with mode: 0644]
src/go/build/build.go
src/go/build/syslist.go
src/hash/crc32/crc32_generic.go
src/liblink/asm6.c
src/liblink/asm9.c [new file with mode: 0644]
src/liblink/list6.c
src/liblink/list9.c [new file with mode: 0644]
src/liblink/obj9.c [new file with mode: 0644]
src/liblink/objfile.c
src/liblink/sched9.c [new file with mode: 0644]
src/math/abs_power64x.s [new file with mode: 0644]
src/math/big/arith_power64x.s [new file with mode: 0644]
src/math/stubs_power64x.s [new file with mode: 0644]
src/os/signal/sig.s
src/reflect/all_test.go
src/reflect/asm_power64x.s [new file with mode: 0644]
src/reflect/type.go
src/run.bash
src/runtime/alg.go
src/runtime/arch1_386.go [new file with mode: 0644]
src/runtime/arch1_amd64.go [new file with mode: 0644]
src/runtime/arch1_arm.go [new file with mode: 0644]
src/runtime/arch1_power64.go [new file with mode: 0644]
src/runtime/arch1_power64le.go [new file with mode: 0644]
src/runtime/arch_386.h [deleted file]
src/runtime/arch_amd64.h [deleted file]
src/runtime/arch_arm.h [deleted file]
src/runtime/arch_power64.go [new file with mode: 0644]
src/runtime/arch_power64le.go [new file with mode: 0644]
src/runtime/asm.s
src/runtime/asm_386.s
src/runtime/asm_amd64.s
src/runtime/asm_amd64p32.s
src/runtime/asm_arm.s
src/runtime/asm_power64x.s [new file with mode: 0644]
src/runtime/atomic_386.c [deleted file]
src/runtime/atomic_386.go [new file with mode: 0644]
src/runtime/atomic_amd64x.c [deleted file]
src/runtime/atomic_amd64x.go [new file with mode: 0644]
src/runtime/atomic_arm.go
src/runtime/atomic_power64x.go [moved from src/runtime/atomic.go with 52% similarity]
src/runtime/atomic_power64x.s [new file with mode: 0644]
src/runtime/cgo.go [new file with mode: 0644]
src/runtime/cgo/callbacks.c [deleted file]
src/runtime/cgo/callbacks.go [new file with mode: 0644]
src/runtime/cgo/dragonfly.go [moved from src/runtime/cgo/dragonfly.c with 64% similarity]
src/runtime/cgo/freebsd.go [moved from src/runtime/cgo/freebsd.c with 58% similarity]
src/runtime/cgo/iscgo.go [moved from src/runtime/cgo/iscgo.c with 71% similarity]
src/runtime/cgo/netbsd.go [moved from src/runtime/cgo/netbsd.c with 64% similarity]
src/runtime/cgo/openbsd.go [moved from src/runtime/cgo/openbsd.c with 53% similarity]
src/runtime/cgo/setenv.c [deleted file]
src/runtime/cgo/setenv.go [new file with mode: 0644]
src/runtime/cgocall.go
src/runtime/chan.go
src/runtime/chan.h [deleted file]
src/runtime/chan1.go [new file with mode: 0644]
src/runtime/complex.go
src/runtime/cpuprof.go
src/runtime/cputicks.go [new file with mode: 0644]
src/runtime/debug.go
src/runtime/debug/stubs.s
src/runtime/defs.c [deleted file]
src/runtime/defs1_linux.go
src/runtime/defs1_netbsd_386.go [new file with mode: 0644]
src/runtime/defs1_netbsd_amd64.go [new file with mode: 0644]
src/runtime/defs1_netbsd_arm.go [new file with mode: 0644]
src/runtime/defs1_solaris_amd64.go [new file with mode: 0644]
src/runtime/defs3_linux.go [new file with mode: 0644]
src/runtime/defs_android_arm.h [deleted file]
src/runtime/defs_darwin_386.go [new file with mode: 0644]
src/runtime/defs_darwin_386.h [deleted file]
src/runtime/defs_darwin_amd64.go [new file with mode: 0644]
src/runtime/defs_darwin_amd64.h [deleted file]
src/runtime/defs_dragonfly_386.go [new file with mode: 0644]
src/runtime/defs_dragonfly_386.h [deleted file]
src/runtime/defs_dragonfly_amd64.go [new file with mode: 0644]
src/runtime/defs_dragonfly_amd64.h [deleted file]
src/runtime/defs_freebsd_386.go [new file with mode: 0644]
src/runtime/defs_freebsd_386.h [deleted file]
src/runtime/defs_freebsd_amd64.go [new file with mode: 0644]
src/runtime/defs_freebsd_amd64.h [deleted file]
src/runtime/defs_freebsd_arm.go [new file with mode: 0644]
src/runtime/defs_freebsd_arm.h [deleted file]
src/runtime/defs_linux.go
src/runtime/defs_linux_386.go [new file with mode: 0644]
src/runtime/defs_linux_386.h [deleted file]
src/runtime/defs_linux_amd64.go [new file with mode: 0644]
src/runtime/defs_linux_amd64.h [deleted file]
src/runtime/defs_linux_arm.go [new file with mode: 0644]
src/runtime/defs_linux_arm.h [deleted file]
src/runtime/defs_linux_power64.go [new file with mode: 0644]
src/runtime/defs_linux_power64le.go [new file with mode: 0644]
src/runtime/defs_nacl_386.go [new file with mode: 0644]
src/runtime/defs_nacl_386.h [deleted file]
src/runtime/defs_nacl_amd64p32.go [new file with mode: 0644]
src/runtime/defs_nacl_amd64p32.h [deleted file]
src/runtime/defs_nacl_arm.go [new file with mode: 0644]
src/runtime/defs_nacl_arm.h [deleted file]
src/runtime/defs_netbsd_386.h [deleted file]
src/runtime/defs_netbsd_amd64.h [deleted file]
src/runtime/defs_netbsd_arm.h [deleted file]
src/runtime/defs_openbsd_386.go [new file with mode: 0644]
src/runtime/defs_openbsd_386.h [deleted file]
src/runtime/defs_openbsd_amd64.go [new file with mode: 0644]
src/runtime/defs_openbsd_amd64.h [deleted file]
src/runtime/defs_plan9_386.go [new file with mode: 0644]
src/runtime/defs_plan9_386.h [deleted file]
src/runtime/defs_plan9_amd64.go [new file with mode: 0644]
src/runtime/defs_plan9_amd64.h [deleted file]
src/runtime/defs_solaris_amd64.h [deleted file]
src/runtime/defs_windows_386.go [new file with mode: 0644]
src/runtime/defs_windows_386.h [deleted file]
src/runtime/defs_windows_amd64.go [new file with mode: 0644]
src/runtime/defs_windows_amd64.h [deleted file]
src/runtime/env_posix.go
src/runtime/export_test.go
src/runtime/extern.go
src/runtime/float.c [deleted file]
src/runtime/funcdata.h
src/runtime/futex_test.go
src/runtime/gcinfo_test.go
src/runtime/gengoos.go [new file with mode: 0644]
src/runtime/go_tls.h [new file with mode: 0644]
src/runtime/heapdump.c [deleted file]
src/runtime/heapdump.go [new file with mode: 0644]
src/runtime/lfstack.c [deleted file]
src/runtime/lfstack.go [new file with mode: 0644]
src/runtime/lfstack_32bit.go [new file with mode: 0644]
src/runtime/lfstack_amd64.go [new file with mode: 0644]
src/runtime/lfstack_linux_power64x.go [new file with mode: 0644]
src/runtime/lock_futex.go
src/runtime/lock_sema.go
src/runtime/malloc.c [deleted file]
src/runtime/malloc.go
src/runtime/malloc.h [deleted file]
src/runtime/malloc1.go [new file with mode: 0644]
src/runtime/malloc2.go [new file with mode: 0644]
src/runtime/mcache.c [deleted file]
src/runtime/mcache.go [new file with mode: 0644]
src/runtime/mcentral.c [deleted file]
src/runtime/mcentral.go [new file with mode: 0644]
src/runtime/mem.go
src/runtime/mem_bsd.go [new file with mode: 0644]
src/runtime/mem_darwin.c [deleted file]
src/runtime/mem_darwin.go [new file with mode: 0644]
src/runtime/mem_dragonfly.c [deleted file]
src/runtime/mem_freebsd.c [deleted file]
src/runtime/mem_linux.c [deleted file]
src/runtime/mem_linux.go [new file with mode: 0644]
src/runtime/mem_netbsd.c [deleted file]
src/runtime/mem_openbsd.c [deleted file]
src/runtime/mem_solaris.c [deleted file]
src/runtime/mem_windows.c [deleted file]
src/runtime/mem_windows.go [new file with mode: 0644]
src/runtime/memclr_386.s
src/runtime/memclr_amd64.s
src/runtime/memclr_plan9_386.s
src/runtime/memclr_power64x.s [new file with mode: 0644]
src/runtime/memmove_power64x.s [new file with mode: 0644]
src/runtime/mfixalloc.c [deleted file]
src/runtime/mfixalloc.go [new file with mode: 0644]
src/runtime/mgc.go [new file with mode: 0644]
src/runtime/mgc0.c [deleted file]
src/runtime/mgc0.go
src/runtime/mgc0.h
src/runtime/mgc1.go [new file with mode: 0644]
src/runtime/mheap.c [deleted file]
src/runtime/mheap.go [new file with mode: 0644]
src/runtime/mprof.go
src/runtime/msize.c [deleted file]
src/runtime/msize.go [new file with mode: 0644]
src/runtime/netpoll.go
src/runtime/netpoll_solaris.go [moved from src/runtime/netpoll_solaris.c with 55% similarity]
src/runtime/netpoll_windows.c [deleted file]
src/runtime/netpoll_windows.go [new file with mode: 0644]
src/runtime/noasm.go [moved from src/runtime/noasm_arm.go with 96% similarity]
src/runtime/norace_test.go
src/runtime/os1_darwin.go [new file with mode: 0644]
src/runtime/os1_dragonfly.go [new file with mode: 0644]
src/runtime/os1_freebsd.go [new file with mode: 0644]
src/runtime/os1_linux.go [new file with mode: 0644]
src/runtime/os1_openbsd.go [new file with mode: 0644]
src/runtime/os1_windows.go [new file with mode: 0644]
src/runtime/os1_windows_386.go [new file with mode: 0644]
src/runtime/os1_windows_amd64.go [new file with mode: 0644]
src/runtime/os2_darwin.go [new file with mode: 0644]
src/runtime/os2_dragonfly.go [new file with mode: 0644]
src/runtime/os2_freebsd.go [new file with mode: 0644]
src/runtime/os2_linux.go [new file with mode: 0644]
src/runtime/os2_openbsd.go [new file with mode: 0644]
src/runtime/os2_solaris.go [new file with mode: 0644]
src/runtime/os2_windows.go [new file with mode: 0644]
src/runtime/os3_solaris.go [new file with mode: 0644]
src/runtime/os_darwin.c [deleted file]
src/runtime/os_darwin.go
src/runtime/os_darwin.h [deleted file]
src/runtime/os_dragonfly.c [deleted file]
src/runtime/os_dragonfly.go
src/runtime/os_dragonfly.h [deleted file]
src/runtime/os_freebsd.c [deleted file]
src/runtime/os_freebsd.go
src/runtime/os_freebsd.h [deleted file]
src/runtime/os_freebsd_arm.go [moved from src/runtime/os_freebsd_arm.c with 66% similarity]
src/runtime/os_linux.c [deleted file]
src/runtime/os_linux.go
src/runtime/os_linux.h [deleted file]
src/runtime/os_linux_386.c [deleted file]
src/runtime/os_linux_386.go [new file with mode: 0644]
src/runtime/os_linux_arm.c [deleted file]
src/runtime/os_linux_arm.go [new file with mode: 0644]
src/runtime/os_openbsd.c [deleted file]
src/runtime/os_openbsd.go
src/runtime/os_openbsd.h [deleted file]
src/runtime/os_solaris.c [deleted file]
src/runtime/os_solaris.go
src/runtime/os_solaris.h [deleted file]
src/runtime/os_windows.c [deleted file]
src/runtime/os_windows.go
src/runtime/os_windows.h [deleted file]
src/runtime/os_windows_386.c [deleted file]
src/runtime/os_windows_amd64.c [deleted file]
src/runtime/panic.c [deleted file]
src/runtime/panic.go
src/runtime/panic1.go [new file with mode: 0644]
src/runtime/parfor.c [deleted file]
src/runtime/parfor.go [new file with mode: 0644]
src/runtime/pprof/pprof_test.go
src/runtime/proc.c [deleted file]
src/runtime/proc.go
src/runtime/proc1.go [new file with mode: 0644]
src/runtime/race.c [deleted file]
src/runtime/race.go
src/runtime/race.h [deleted file]
src/runtime/race0.go
src/runtime/race1.go [new file with mode: 0644]
src/runtime/race_amd64.s
src/runtime/rdebug.go
src/runtime/rt0_linux_power64.s [new file with mode: 0644]
src/runtime/rt0_linux_power64le.s [new file with mode: 0644]
src/runtime/rt0_windows_amd64.s
src/runtime/runtime.c [deleted file]
src/runtime/runtime.h [deleted file]
src/runtime/runtime1.go [new file with mode: 0644]
src/runtime/runtime2.go [new file with mode: 0644]
src/runtime/runtime2_windows.go [new file with mode: 0644]
src/runtime/select.go
src/runtime/signal.c [deleted file]
src/runtime/signal1_unix.go [new file with mode: 0644]
src/runtime/signal_386.c [deleted file]
src/runtime/signal_386.go [new file with mode: 0644]
src/runtime/signal_amd64x.c [deleted file]
src/runtime/signal_amd64x.go [new file with mode: 0644]
src/runtime/signal_arm.c [deleted file]
src/runtime/signal_arm.go [new file with mode: 0644]
src/runtime/signal_darwin.go [new file with mode: 0644]
src/runtime/signal_darwin_386.go [new file with mode: 0644]
src/runtime/signal_darwin_386.h [deleted file]
src/runtime/signal_darwin_amd64.go [new file with mode: 0644]
src/runtime/signal_darwin_amd64.h [deleted file]
src/runtime/signal_dragonfly.go [new file with mode: 0644]
src/runtime/signal_dragonfly_amd64.go [new file with mode: 0644]
src/runtime/signal_dragonfly_amd64.h [deleted file]
src/runtime/signal_freebsd.go [new file with mode: 0644]
src/runtime/signal_freebsd_386.go [new file with mode: 0644]
src/runtime/signal_freebsd_386.h [deleted file]
src/runtime/signal_freebsd_amd64.go [new file with mode: 0644]
src/runtime/signal_freebsd_amd64.h [deleted file]
src/runtime/signal_freebsd_arm.go [new file with mode: 0644]
src/runtime/signal_freebsd_arm.h [deleted file]
src/runtime/signal_linux.go [new file with mode: 0644]
src/runtime/signal_linux_386.go [new file with mode: 0644]
src/runtime/signal_linux_386.h [deleted file]
src/runtime/signal_linux_amd64.go [new file with mode: 0644]
src/runtime/signal_linux_amd64.h [deleted file]
src/runtime/signal_linux_arm.go [new file with mode: 0644]
src/runtime/signal_linux_arm.h [deleted file]
src/runtime/signal_linux_power64x.go [new file with mode: 0644]
src/runtime/signal_openbsd.go [new file with mode: 0644]
src/runtime/signal_openbsd_386.go [new file with mode: 0644]
src/runtime/signal_openbsd_386.h [deleted file]
src/runtime/signal_openbsd_amd64.go [new file with mode: 0644]
src/runtime/signal_openbsd_amd64.h [deleted file]
src/runtime/signal_power64x.go [new file with mode: 0644]
src/runtime/signal_solaris.go [new file with mode: 0644]
src/runtime/signal_solaris_amd64.go [new file with mode: 0644]
src/runtime/signal_solaris_amd64.h [deleted file]
src/runtime/signal_unix.c [deleted file]
src/runtime/signal_unix.go
src/runtime/signals_darwin.h [deleted file]
src/runtime/signals_dragonfly.h [deleted file]
src/runtime/signals_freebsd.h [deleted file]
src/runtime/signals_linux.h [deleted file]
src/runtime/signals_openbsd.h [deleted file]
src/runtime/signals_solaris.h [deleted file]
src/runtime/sigpanic_unix.go
src/runtime/sigqueue.go
src/runtime/slice.go
src/runtime/softfloat64.go
src/runtime/softfloat64_test.go
src/runtime/softfloat_arm.c [deleted file]
src/runtime/softfloat_arm.go [new file with mode: 0644]
src/runtime/sqrt.go
src/runtime/stack.c [deleted file]
src/runtime/stack.go [deleted file]
src/runtime/stack.h
src/runtime/stack1.go [new file with mode: 0644]
src/runtime/stack2.go [new file with mode: 0644]
src/runtime/string.c [deleted file]
src/runtime/string.go
src/runtime/string1.go [new file with mode: 0644]
src/runtime/stubs.go
src/runtime/stubs2.go [new file with mode: 0644]
src/runtime/symtab.go
src/runtime/sys_arm.c [deleted file]
src/runtime/sys_arm.go [new file with mode: 0644]
src/runtime/sys_darwin_386.s
src/runtime/sys_darwin_amd64.s
src/runtime/sys_dragonfly_386.s
src/runtime/sys_dragonfly_amd64.s
src/runtime/sys_freebsd_386.s
src/runtime/sys_freebsd_amd64.s
src/runtime/sys_freebsd_arm.s
src/runtime/sys_linux_386.s
src/runtime/sys_linux_amd64.s
src/runtime/sys_linux_arm.s
src/runtime/sys_linux_power64x.s [new file with mode: 0644]
src/runtime/sys_nacl_386.s
src/runtime/sys_nacl_amd64p32.s
src/runtime/sys_nacl_arm.s
src/runtime/sys_netbsd_386.s
src/runtime/sys_netbsd_amd64.s
src/runtime/sys_netbsd_arm.s
src/runtime/sys_openbsd_386.s
src/runtime/sys_openbsd_amd64.s
src/runtime/sys_plan9_386.s
src/runtime/sys_plan9_amd64.s
src/runtime/sys_power64x.go [new file with mode: 0644]
src/runtime/sys_solaris_amd64.s
src/runtime/sys_windows_386.s
src/runtime/sys_windows_amd64.s
src/runtime/sys_x86.go [moved from src/runtime/sys_x86.c with 53% similarity]
src/runtime/syscall2_solaris.go [new file with mode: 0644]
src/runtime/syscall_solaris.c [deleted file]
src/runtime/syscall_solaris.go
src/runtime/syscall_windows.go
src/runtime/thunk.s
src/runtime/thunk_solaris_amd64.s [deleted file]
src/runtime/thunk_windows.s
src/runtime/tls_arm.s
src/runtime/traceback.go
src/runtime/type.go [new file with mode: 0644]
src/runtime/type.h [deleted file]
src/runtime/typekind.h
src/runtime/typekind1.go [new file with mode: 0644]
src/runtime/vdso_linux_amd64.c [deleted file]
src/runtime/vdso_linux_amd64.go [new file with mode: 0644]
src/runtime/vdso_none.go [new file with mode: 0644]
src/runtime/vlop_arm.s
src/runtime/vlrt.c [deleted file]
src/runtime/zgoarch_386.go [new file with mode: 0644]
src/runtime/zgoarch_amd64.go [new file with mode: 0644]
src/runtime/zgoarch_amd64p32.go [new file with mode: 0644]
src/runtime/zgoarch_arm.go [new file with mode: 0644]
src/runtime/zgoarch_power64.go [new file with mode: 0644]
src/runtime/zgoarch_power64le.go [new file with mode: 0644]
src/runtime/zgoos_android.go [new file with mode: 0644]
src/runtime/zgoos_darwin.go [new file with mode: 0644]
src/runtime/zgoos_dragonfly.go [new file with mode: 0644]
src/runtime/zgoos_freebsd.go [new file with mode: 0644]
src/runtime/zgoos_linux.go [new file with mode: 0644]
src/runtime/zgoos_nacl.go [new file with mode: 0644]
src/runtime/zgoos_netbsd.go [new file with mode: 0644]
src/runtime/zgoos_openbsd.go [new file with mode: 0644]
src/runtime/zgoos_plan9.go [new file with mode: 0644]
src/runtime/zgoos_solaris.go [new file with mode: 0644]
src/runtime/zgoos_windows.go [new file with mode: 0644]
src/sync/atomic/asm_power64x.s [new file with mode: 0644]
src/syscall/asm.s
src/syscall/asm_linux_power64x.s [new file with mode: 0644]
src/syscall/mkall.sh
src/syscall/mkerrors.sh
src/syscall/syscall_linux_power64x.go [new file with mode: 0644]
src/syscall/types_linux.go
src/syscall/zerrors_linux_power64.go [new file with mode: 0644]
src/syscall/zerrors_linux_power64le.go [new file with mode: 0644]
src/syscall/zsyscall_linux_power64.go [new file with mode: 0644]
src/syscall/zsyscall_linux_power64le.go [new file with mode: 0644]
src/syscall/zsysnum_linux_power64.go [new file with mode: 0644]
src/syscall/zsysnum_linux_power64le.go [new file with mode: 0644]
src/syscall/ztypes_linux_power64.go [new file with mode: 0644]
src/syscall/ztypes_linux_power64le.go [new file with mode: 0644]
test/clearfat.go [new file with mode: 0644]
test/live.go
test/nilptr3.go
test/nosplit.go

index 0071161139335b11fd083077f038ed0d34fabb45..a833065f2e4bd82090f343e3ee7bc8f84085496f 100644 (file)
--- a/.hgignore
+++ b/.hgignore
@@ -2,13 +2,13 @@ syntax:glob
 .DS_Store
 .git
 .gitignore
-*.[568ao]
-*.a[568o]
+*.[5689ao]
+*.a[5689o]
 *.so
 *.pyc
 ._*
 .nfs.*
-[568a].out
+[5689a].out
 *~
 *.orig
 *.rej
diff --git a/dev.cc b/dev.cc
new file mode 100644 (file)
index 0000000..e69de29
index 05e117c87ee0310a994aaf47d753161454ad7795..225c6f95dfc942eb55501aa8117d13100e901a42 100644 (file)
@@ -54,7 +54,7 @@ struct        Addr
        {
                char    sval[8];
                float64 dval;
-               Prog*   branch; // for 5g, 6g, 8g
+               Prog*   branch; // for 5g, 6g, 8g, 9g
        } u;
 
        LSym*   sym;
@@ -62,9 +62,9 @@ struct        Addr
        short   type;
        uint8   index;
        int8    scale;
-       int8    reg;    // for 5l
-       int8    name; // for 5l
-       int8    class;  // for 5l
+       int8    reg;    // for 5l, 9l
+       int8    name; // for 5l, 9l
+       int8    class;  // for 5l, 9l
        uint8   etype; // for 5g, 6g, 8g
        int32   offset2;        // for 5l, 8l
        struct Node*    node; // for 5g, 6g, 8g
@@ -89,9 +89,13 @@ struct       Prog
        int32   lineno;
        Prog*   link;
        short   as;
-       uchar   reg; // arm only
-       uchar   scond; // arm only
+       uchar   scond; // arm only; condition codes
+
+       // operands
        Addr    from;
+       uchar   reg; // arm, power64 only (e.g., ADD from, reg, to);
+                    // also used for ADATA width on arm, power64
+       Addr    from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
        Addr    to;
        
        // for 5g, 6g, 8g internal use
@@ -103,11 +107,11 @@ struct    Prog
        Prog*   comefrom;       // 6l, 8l
        Prog*   pcrel;  // 5l
        int32   spadj;
-       uchar   mark;
+       uint16  mark;
+       uint16  optab;  // 5l, 9l
        uchar   back;   // 6l, 8l
        uchar   ft;     /* 6l, 8l oclass cache */
        uchar   tt;     // 6l, 8l
-       uint16  optab;  // 5l
        uchar   isize;  // 6l, 8l
 
        char    width;  /* fake for DATA */
@@ -233,10 +237,12 @@ enum
 enum
 {
        R_ADDR = 1,
+       R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power
        R_SIZE,
        R_CALL, // relocation for direct PC-relative call
        R_CALLARM, // relocation for ARM direct call
        R_CALLIND, // marker for indirect call (no actual relocating necessary)
+       R_CALLPOWER, // relocation for Power direct call
        R_CONST,
        R_PCREL,
        R_TLS,
@@ -529,6 +535,9 @@ void        span6(Link *ctxt, LSym *s);
 // asm8.c
 void   span8(Link *ctxt, LSym *s);
 
+// asm9.c
+void   span9(Link *ctxt, LSym *s);
+
 // data.c
 vlong  addaddr(Link *ctxt, LSym *s, LSym *t);
 vlong  addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add);
@@ -576,10 +585,11 @@ Prog*     copyp(Link*, Prog*);
 Prog*  appendp(Link*, Prog*);
 vlong  atolwhex(char*);
 
-// list[568].c
+// list[5689].c
 void   listinit5(void);
 void   listinit6(void);
 void   listinit8(void);
+void   listinit9(void);
 
 // obj.c
 int    linklinefmt(Link *ctxt, Fmt *fp);
@@ -611,20 +621,29 @@ char*     headstr(int);
 extern char*   anames5[];
 extern char*   anames6[];
 extern char*   anames8[];
+extern char*   anames9[];
 
 extern char*   cnames5[];
+extern char*   cnames9[];
+
+extern char*   dnames5[];
+extern char*   dnames6[];
+extern char*   dnames8[];
+extern char*   dnames9[];
 
 extern LinkArch        link386;
 extern LinkArch        linkamd64;
 extern LinkArch        linkamd64p32;
 extern LinkArch        linkarm;
+extern LinkArch        linkpower64;
+extern LinkArch        linkpower64le;
 
 #pragma        varargck        type    "A"     int
 #pragma        varargck        type    "D"     Addr*
 #pragma        varargck        type    "lD"    Addr*
 #pragma        varargck        type    "P"     Prog*
 #pragma        varargck        type    "R"     int
-#pragma varargck       type    "^"     int
+#pragma        varargck        type    "^"     int // for 5l/9l, C_* classes (liblink internal)
 
 // TODO(ality): remove this workaround.
 //   It's here because Pconv in liblink/list?.c references %L.
index 2801ebf8d6ea0e5b4c9f3b8918dc91989ed96279..43dbf3ce3b817d7998070c0fe33078c4479a63d4 100644 (file)
@@ -1 +1,2 @@
 defaultcc: golang-codereviews@googlegroups.com
+contributors: http://go.googlecode.com/hg/CONTRIBUTORS
index 416702c634a895b48f164ff8ef9fabca438b3450..9181f1df3cde0eb8418bcd3e1cac40e70e1fd10a 100644 (file)
@@ -3604,11 +3604,17 @@ class MercurialVCS(VersionControlSystem):
                        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())
+                                try:
+                                        base_content = str(self.repo[base_rev][oldrelpath].data())
+                                except Exception:
+                                        pass
                        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
+                        try:
+                                new_content = open(relpath, "rb").read()
+                                is_binary = is_binary or "\0" in new_content
+                        except Exception:
+                                pass
                if is_binary and base_content and use_hg_shell:
                        # Fetch again without converting newlines
                        base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
index bb60fe7de2505ec8ad46b6c43180c71bb06dd68a..df9838ad37cea770abf54cd705e812f6f81b5814 100644 (file)
@@ -67,6 +67,7 @@ struct        Sym
        int32   value;
        ushort  type;
        char    *name;
+       char*   labelname;
        char    sym;
 };
 #define        S       ((Sym*)0)
@@ -136,6 +137,8 @@ void        newio(void);
 void   newfile(char*, int);
 Sym*   slookup(char*);
 Sym*   lookup(void);
+Sym*   labellookup(Sym*);
+void   settext(LSym*);
 void   syminit(Sym*);
 int32  yylex(void);
 int    getc(void);
index ad647606ef893dafae8ac173bdf2288dac57807e..d365c753433f1052d0b5d322e95f36d1750c0cef 100644 (file)
@@ -73,15 +73,11 @@ prog:
        line
 
 line:
-       LLAB ':'
-       {
-               if($1->value != pc)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = pc;
-       }
-       line
-|      LNAME ':'
+       LNAME ':'
        {
+               $1 = labellookup($1);
+               if($1->type == LLAB && $1->value != pc)
+                       yyerror("redeclaration of %s", $1->labelname);
                $1->type = LLAB;
                $1->value = pc;
        }
@@ -218,18 +214,21 @@ inst:
  */
 |      LTYPEB name ',' imm
        {
+               settext($2.sym);
                $4.type = D_CONST2;
                $4.offset2 = ArgsSizeUnknown;
                outcode($1, Always, &$2, 0, &$4);
        }
 |      LTYPEB name ',' con ',' imm
        {
+               settext($2.sym);
                $6.type = D_CONST2;
                $6.offset2 = ArgsSizeUnknown;
                outcode($1, Always, &$2, $4, &$6);
        }
 |      LTYPEB name ',' con ',' imm '-' con
        {
+               settext($2.sym);
                $6.type = D_CONST2;
                $6.offset2 = $8;
                outcode($1, Always, &$2, $4, &$6);
@@ -373,15 +372,10 @@ rel:
        }
 |      LNAME offset
        {
+               $1 = labellookup($1);
                $$ = nullgen;
-               if(pass == 2)
-                       yyerror("undefined label: %s", $1->name);
-               $$.type = D_BRANCH;
-               $$.offset = $2;
-       }
-|      LLAB offset
-       {
-               $$ = nullgen;
+               if(pass == 2 && $1->type != LLAB)
+                       yyerror("undefined label: %s", $1->labelname);
                $$.type = D_BRANCH;
                $$.offset = $1->value + $2;
        }
index a6251b83529296468f3d153ac92287d66bcd4181..ace80c7e0eb1325f90e60708ae1098569ad17ada 100644 (file)
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -26,7 +29,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -44,7 +47,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.7.12-4996"
+#define YYBISON_VERSION "2.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 /* Pure parsers.  */
 #define YYPURE 0
 
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-
-
-
-/* Copy the first part of user declarations.  */
-/* Line 371 of yacc.c  */
-#line 31 "a.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
+/* Using locations.  */
+#define YYLSP_NEEDED 0
 
-/* Line 371 of yacc.c  */
-#line 76 "y.tab.c"
 
-# ifndef YY_NULL
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
-#  else
-#   define YY_NULL 0
-#  endif
-# endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* In a future release of Bison, this section will be replaced
-   by #include "y.tab.h".  */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
@@ -210,49 +168,60 @@ extern int yydebug;
 
 
 
+
+/* Copy the first part of user declarations.  */
+#line 31 "a.y"
+
+#include <u.h>
+#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
+#include <libc.h>
+#include "a.h"
+#include "../../runtime/funcdata.h"
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-{
-/* Line 387 of yacc.c  */
 #line 39 "a.y"
-
+{
        Sym     *sym;
        int32   lval;
        double  dval;
        char    sval[8];
        Addr    addr;
-
-
-/* Line 387 of yacc.c  */
-#line 228 "y.tab.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 193 of yacc.c.  */
+#line 212 "y.tab.c"
+       YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
-extern YYSTYPE yylval;
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_Y_TAB_H_INCLUDED  */
 
 /* Copy the second part of user declarations.  */
 
-/* Line 390 of yacc.c  */
-#line 256 "y.tab.c"
+
+/* Line 216 of yacc.c.  */
+#line 225 "y.tab.c"
 
 #ifdef short
 # undef short
@@ -305,45 +274,36 @@ typedef short int yytype_int16;
 # if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later.  */
-# if (! defined __GNUC__ || __GNUC__ < 2 \
-      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
-#  define __attribute__(Spec) /* empty */
+#  define YY_(msgid) msgid
 # endif
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YYUSE(e) ((void) (e))
 #else
-# define YYUSE(E) /* empty */
+# define YYUSE(e) /* empty */
 #endif
 
-
 /* Identity function, used to suppress warnings about constant conditions.  */
 #ifndef lint
-# define YYID(N) (N)
+# define YYID(n) (n)
 #else
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int yyi)
+YYID (int i)
 #else
 static int
-YYID (yyi)
-    int yyi;
+YYID (i)
+    int i;
 #endif
 {
-  return yyi;
+  return i;
 }
 #endif
 
@@ -364,12 +324,11 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
 #     endif
 #    endif
 #   endif
@@ -392,24 +351,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
@@ -425,9 +384,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)
@@ -438,19 +397,35 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
       + YYSTACK_GAP_MAXIMUM)
 
-# define YYCOPY_NEEDED 1
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         YYSIZE_T yyi;                         \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (YYID (0))
+#  endif
+# endif
 
 /* Relocate STACK from its old location to the new one.  The
    local variables YYSIZE and YYSTACKSIZE give the old and new number of
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)                          \
+# define YYSTACK_RELOCATE(Stack)                                       \
     do                                                                 \
       {                                                                        \
        YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
-       Stack = &yyptr->Stack_alloc;                                    \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / sizeof (*yyptr);                          \
       }                                                                        \
@@ -458,39 +433,19 @@ 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   609
+#define YYLAST   640
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  71
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  35
+#define YYNNTS  34
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  133
+#define YYNRULES  130
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  339
+#define YYNSTATES  333
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -540,101 +495,100 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     4,     5,     9,    10,    15,    16,    21,
-      26,    31,    33,    36,    39,    47,    54,    60,    66,    72,
-      77,    82,    86,    90,    95,   102,   110,   118,   126,   133,
-     140,   144,   149,   156,   165,   172,   177,   181,   187,   193,
-     201,   208,   221,   229,   239,   242,   247,   252,   255,   256,
-     259,   262,   263,   266,   271,   274,   277,   280,   283,   288,
-     291,   293,   296,   300,   302,   306,   310,   312,   314,   316,
-     321,   323,   325,   327,   329,   331,   333,   335,   339,   341,
-     346,   348,   353,   355,   357,   359,   361,   364,   366,   372,
-     377,   382,   387,   392,   394,   396,   398,   400,   405,   407,
-     409,   411,   416,   418,   420,   422,   427,   432,   438,   446,
-     447,   450,   453,   455,   457,   459,   461,   463,   466,   469,
-     472,   476,   477,   480,   482,   486,   490,   494,   498,   502,
-     507,   512,   516,   520
+       0,     0,     3,     4,     5,     9,    10,    15,    20,    25,
+      27,    30,    33,    41,    48,    54,    60,    66,    71,    76,
+      80,    84,    89,    96,   104,   112,   120,   127,   134,   138,
+     143,   150,   159,   166,   171,   175,   181,   187,   195,   202,
+     215,   223,   233,   236,   241,   246,   249,   250,   253,   256,
+     257,   260,   265,   268,   271,   274,   279,   282,   284,   287,
+     291,   293,   297,   301,   303,   305,   307,   312,   314,   316,
+     318,   320,   322,   324,   326,   330,   332,   337,   339,   344,
+     346,   348,   350,   352,   355,   357,   363,   368,   373,   378,
+     383,   385,   387,   389,   391,   396,   398,   400,   402,   407,
+     409,   411,   413,   418,   423,   429,   437,   438,   441,   444,
+     446,   448,   450,   452,   454,   457,   460,   463,   467,   468,
+     471,   473,   477,   481,   485,   489,   493,   498,   503,   507,
+     511
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
       72,     0,    -1,    -1,    -1,    72,    73,    74,    -1,    -1,
-      59,    61,    75,    74,    -1,    -1,    58,    61,    76,    74,
-      -1,    58,    62,   105,    63,    -1,    60,    62,   105,    63,
-      -1,    63,    -1,    77,    63,    -1,     1,    63,    -1,    13,
-      78,    89,    64,    96,    64,    91,    -1,    13,    78,    89,
-      64,    96,    64,    -1,    13,    78,    89,    64,    91,    -1,
-      14,    78,    89,    64,    91,    -1,    15,    78,    84,    64,
-      84,    -1,    16,    78,    79,    80,    -1,    16,    78,    79,
-      85,    -1,    35,    79,    86,    -1,    17,    79,    80,    -1,
-      18,    78,    79,    84,    -1,    19,    78,    89,    64,    96,
-      79,    -1,    20,    78,    87,    64,    65,    83,    66,    -1,
-      20,    78,    65,    83,    66,    64,    87,    -1,    21,    78,
-      91,    64,    86,    64,    91,    -1,    21,    78,    91,    64,
-      86,    79,    -1,    21,    78,    79,    86,    64,    91,    -1,
-      22,    78,    79,    -1,    23,   100,    64,    90,    -1,    23,
-     100,    64,   103,    64,    90,    -1,    23,   100,    64,   103,
-      64,    90,     9,   103,    -1,    24,   100,    11,   103,    64,
-      81,    -1,    25,    78,    91,    79,    -1,    28,    79,    81,
-      -1,    29,    78,    99,    64,    99,    -1,    31,    78,    98,
-      64,    99,    -1,    31,    78,    98,    64,    48,    64,    99,
-      -1,    32,    78,    99,    64,    99,    79,    -1,    30,    78,
-     103,    64,   105,    64,    96,    64,    97,    64,    97,   104,
-      -1,    33,    78,    91,    64,    91,    64,    92,    -1,    34,
-      78,    91,    64,    91,    64,    91,    64,    96,    -1,    36,
-      88,    -1,    43,    84,    64,    84,    -1,    44,    84,    64,
-      84,    -1,    26,    79,    -1,    -1,    78,    53,    -1,    78,
-      54,    -1,    -1,    64,    79,    -1,   103,    67,    41,    68,
-      -1,    58,   101,    -1,    59,   101,    -1,    69,   103,    -1,
-      69,    88,    -1,    69,    10,    69,    88,    -1,    69,    57,
-      -1,    82,    -1,    69,    56,    -1,    69,     9,    56,    -1,
-      96,    -1,    96,     9,    96,    -1,    96,    79,    83,    -1,
-      91,    -1,    81,    -1,    93,    -1,    93,    67,    96,    68,
-      -1,    51,    -1,    52,    -1,   103,    -1,    88,    -1,    99,
-      -1,    86,    -1,   100,    -1,    67,    96,    68,    -1,    86,
-      -1,   103,    67,    95,    68,    -1,   100,    -1,   100,    67,
-      95,    68,    -1,    87,    -1,    91,    -1,    90,    -1,    93,
-      -1,    69,   103,    -1,    96,    -1,    67,    96,    64,    96,
-      68,    -1,    96,     6,     6,    94,    -1,    96,     7,     7,
-      94,    -1,    96,     9,     7,    94,    -1,    96,    55,     7,
-      94,    -1,    96,    -1,   103,    -1,    46,    -1,    41,    -1,
-      45,    67,   105,    68,    -1,    95,    -1,    38,    -1,    50,
-      -1,    49,    67,   105,    68,    -1,    99,    -1,    82,    -1,
-      48,    -1,    47,    67,   103,    68,    -1,   103,    67,   102,
-      68,    -1,    58,   101,    67,   102,    68,    -1,    58,     6,
-       7,   101,    67,    39,    68,    -1,    -1,     8,   103,    -1,
-       9,   103,    -1,    39,    -1,    38,    -1,    40,    -1,    37,
-      -1,    60,    -1,     9,   103,    -1,     8,   103,    -1,    70,
-     103,    -1,    67,   105,    68,    -1,    -1,    64,   105,    -1,
-     103,    -1,   105,     8,   105,    -1,   105,     9,   105,    -1,
-     105,    10,   105,    -1,   105,    11,   105,    -1,   105,    12,
-     105,    -1,   105,     6,     6,   105,    -1,   105,     7,     7,
-     105,    -1,   105,     5,   105,    -1,   105,     4,   105,    -1,
-     105,     3,   105,    -1
+      58,    61,    75,    74,    -1,    58,    62,   104,    63,    -1,
+      60,    62,   104,    63,    -1,    63,    -1,    76,    63,    -1,
+       1,    63,    -1,    13,    77,    88,    64,    95,    64,    90,
+      -1,    13,    77,    88,    64,    95,    64,    -1,    13,    77,
+      88,    64,    90,    -1,    14,    77,    88,    64,    90,    -1,
+      15,    77,    83,    64,    83,    -1,    16,    77,    78,    79,
+      -1,    16,    77,    78,    84,    -1,    35,    78,    85,    -1,
+      17,    78,    79,    -1,    18,    77,    78,    83,    -1,    19,
+      77,    88,    64,    95,    78,    -1,    20,    77,    86,    64,
+      65,    82,    66,    -1,    20,    77,    65,    82,    66,    64,
+      86,    -1,    21,    77,    90,    64,    85,    64,    90,    -1,
+      21,    77,    90,    64,    85,    78,    -1,    21,    77,    78,
+      85,    64,    90,    -1,    22,    77,    78,    -1,    23,    99,
+      64,    89,    -1,    23,    99,    64,   102,    64,    89,    -1,
+      23,    99,    64,   102,    64,    89,     9,   102,    -1,    24,
+      99,    11,   102,    64,    80,    -1,    25,    77,    90,    78,
+      -1,    28,    78,    80,    -1,    29,    77,    98,    64,    98,
+      -1,    31,    77,    97,    64,    98,    -1,    31,    77,    97,
+      64,    48,    64,    98,    -1,    32,    77,    98,    64,    98,
+      78,    -1,    30,    77,   102,    64,   104,    64,    95,    64,
+      96,    64,    96,   103,    -1,    33,    77,    90,    64,    90,
+      64,    91,    -1,    34,    77,    90,    64,    90,    64,    90,
+      64,    95,    -1,    36,    87,    -1,    43,    83,    64,    83,
+      -1,    44,    83,    64,    83,    -1,    26,    78,    -1,    -1,
+      77,    53,    -1,    77,    54,    -1,    -1,    64,    78,    -1,
+     102,    67,    41,    68,    -1,    58,   100,    -1,    69,   102,
+      -1,    69,    87,    -1,    69,    10,    69,    87,    -1,    69,
+      57,    -1,    81,    -1,    69,    56,    -1,    69,     9,    56,
+      -1,    95,    -1,    95,     9,    95,    -1,    95,    78,    82,
+      -1,    90,    -1,    80,    -1,    92,    -1,    92,    67,    95,
+      68,    -1,    51,    -1,    52,    -1,   102,    -1,    87,    -1,
+      98,    -1,    85,    -1,    99,    -1,    67,    95,    68,    -1,
+      85,    -1,   102,    67,    94,    68,    -1,    99,    -1,    99,
+      67,    94,    68,    -1,    86,    -1,    90,    -1,    89,    -1,
+      92,    -1,    69,   102,    -1,    95,    -1,    67,    95,    64,
+      95,    68,    -1,    95,     6,     6,    93,    -1,    95,     7,
+       7,    93,    -1,    95,     9,     7,    93,    -1,    95,    55,
+       7,    93,    -1,    95,    -1,   102,    -1,    46,    -1,    41,
+      -1,    45,    67,   104,    68,    -1,    94,    -1,    38,    -1,
+      50,    -1,    49,    67,   104,    68,    -1,    98,    -1,    81,
+      -1,    48,    -1,    47,    67,   102,    68,    -1,   102,    67,
+     101,    68,    -1,    58,   100,    67,   101,    68,    -1,    58,
+       6,     7,   100,    67,    39,    68,    -1,    -1,     8,   102,
+      -1,     9,   102,    -1,    39,    -1,    38,    -1,    40,    -1,
+      37,    -1,    60,    -1,     9,   102,    -1,     8,   102,    -1,
+      70,   102,    -1,    67,   104,    68,    -1,    -1,    64,   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.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    68,    68,    70,    69,    77,    76,    84,    83,    89,
-      94,   100,   101,   102,   108,   112,   116,   123,   130,   137,
-     141,   148,   155,   162,   169,   176,   185,   197,   201,   205,
-     212,   219,   225,   231,   240,   247,   254,   261,   265,   269,
-     273,   280,   302,   310,   319,   326,   335,   346,   352,   355,
-     359,   364,   365,   368,   374,   382,   389,   395,   400,   405,
-     411,   414,   420,   428,   432,   441,   447,   448,   449,   450,
-     455,   461,   467,   473,   474,   477,   478,   486,   495,   496,
-     505,   506,   512,   515,   516,   517,   519,   527,   535,   544,
-     550,   556,   562,   570,   576,   584,   585,   589,   597,   598,
-     604,   605,   613,   614,   617,   623,   631,   639,   647,   657,
-     660,   664,   670,   671,   672,   675,   676,   680,   684,   688,
-     692,   698,   701,   707,   708,   712,   716,   720,   724,   728,
-     732,   736,   740,   744
+       0,    68,    68,    70,    69,    77,    76,    85,    90,    96,
+      97,    98,   104,   108,   112,   119,   126,   133,   137,   144,
+     151,   158,   165,   172,   181,   193,   197,   201,   208,   215,
+     222,   229,   239,   246,   253,   260,   264,   268,   272,   279,
+     301,   309,   318,   325,   334,   345,   351,   354,   358,   363,
+     364,   367,   373,   383,   389,   394,   399,   405,   408,   414,
+     422,   426,   435,   441,   442,   443,   444,   449,   455,   461,
+     467,   468,   471,   472,   480,   489,   490,   499,   500,   506,
+     509,   510,   511,   513,   521,   529,   538,   544,   550,   556,
+     564,   570,   578,   579,   583,   591,   592,   598,   599,   607,
+     608,   611,   617,   625,   633,   641,   651,   654,   658,   664,
+     665,   666,   669,   670,   674,   678,   682,   686,   692,   695,
+     701,   702,   706,   710,   714,   718,   722,   726,   730,   734,
+     738
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
@@ -647,11 +601,11 @@ static const char *const yytname[] =
   "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LTYPEPC", "LTYPEF", "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", YY_NULL
+  "','", "'['", "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1",
+  "line", "@2", "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
 };
 #endif
 
@@ -674,279 +628,282 @@ static const yytype_uint16 yytoknum[] =
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    71,    72,    73,    72,    75,    74,    76,    74,    74,
-      74,    74,    74,    74,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    77,    77,    78,    78,
-      78,    79,    79,    80,    80,    80,    81,    81,    81,    81,
-      81,    82,    82,    83,    83,    83,    84,    84,    84,    84,
-      84,    84,    84,    84,    84,    85,    85,    86,    87,    87,
-      88,    88,    88,    89,    89,    89,    90,    91,    92,    93,
-      93,    93,    93,    94,    94,    95,    95,    95,    96,    96,
-      97,    97,    98,    98,    99,    99,   100,   100,   100,   101,
-     101,   101,   102,   102,   102,   103,   103,   103,   103,   103,
-     103,   104,   104,   105,   105,   105,   105,   105,   105,   105,
-     105,   105,   105,   105
+       0,    71,    72,    73,    72,    75,    74,    74,    74,    74,
+      74,    74,    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,    76,    76,    76,    77,    77,    77,    78,
+      78,    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.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     0,     0,     3,     0,     4,     0,     4,     4,
-       4,     1,     2,     2,     7,     6,     5,     5,     5,     4,
-       4,     3,     3,     4,     6,     7,     7,     7,     6,     6,
-       3,     4,     6,     8,     6,     4,     3,     5,     5,     7,
-       6,    12,     7,     9,     2,     4,     4,     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
+       0,     2,     0,     0,     3,     0,     4,     4,     4,     1,
+       2,     2,     7,     6,     5,     5,     5,     4,     4,     3,
+       3,     4,     6,     7,     7,     7,     6,     6,     3,     4,
+       6,     8,     6,     4,     3,     5,     5,     7,     6,    12,
+       7,     9,     2,     4,     4,     2,     0,     2,     2,     0,
+       2,     4,     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 reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     3,     1,     0,     0,    48,    48,    48,    48,    51,
-      48,    48,    48,    48,    48,     0,     0,    48,    51,    51,
-      48,    48,    48,    48,    48,    48,    51,     0,     0,     0,
-       0,     0,     0,    11,     4,     0,    13,     0,     0,     0,
-      51,    51,     0,    51,     0,     0,    51,    51,     0,     0,
-     115,   109,   116,     0,     0,     0,     0,     0,     0,    47,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    78,
-      82,    44,    80,     0,    99,    96,     0,    95,     0,   104,
-      70,    71,     0,    67,    60,     0,    73,    66,    68,    98,
-      87,    74,    72,     0,     7,     0,     5,     0,    12,    49,
-      50,     0,     0,    84,    83,    85,     0,     0,     0,    52,
-     109,   109,    22,     0,     0,     0,     0,     0,     0,     0,
-       0,    87,    30,   118,   117,     0,     0,     0,     0,   123,
-       0,   119,     0,     0,     0,    51,    36,     0,     0,     0,
-     103,     0,   102,     0,     0,     0,     0,    21,     0,     0,
-       0,     0,     0,     0,     0,    61,    59,    57,    56,     0,
+       2,     3,     1,     0,     0,    46,    46,    46,    46,    49,
+      46,    46,    46,    46,    46,     0,     0,    46,    49,    49,
+      46,    46,    46,    46,    46,    46,    49,     0,     0,     0,
+       0,     0,     9,     4,     0,    11,     0,     0,     0,    49,
+      49,     0,    49,     0,     0,    49,    49,     0,     0,   112,
+     106,   113,     0,     0,     0,     0,     0,     0,    45,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    75,    79,
+      42,    77,     0,    96,    93,     0,    92,     0,   101,    67,
+      68,     0,    64,    57,     0,    70,    63,    65,    95,    84,
+      71,    69,     0,     5,     0,     0,    10,    47,    48,     0,
+       0,    81,    80,    82,     0,     0,     0,    50,   106,    20,
+       0,     0,     0,     0,     0,     0,     0,     0,    84,    28,
+     115,   114,     0,     0,     0,     0,   120,     0,   116,     0,
+       0,     0,    49,    34,     0,     0,     0,   100,     0,    99,
+       0,     0,     0,     0,    19,     0,     0,     0,     0,     0,
+       0,     0,    58,    56,    54,    53,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    83,     0,     0,     0,
+     106,    17,    18,    72,    73,     0,    52,     0,    21,     0,
+       0,    49,     0,     0,     0,     0,   106,   107,   108,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      86,     0,     0,     0,   109,    19,    20,    75,    76,     0,
-      54,    55,     0,    23,     0,     0,    51,     0,     0,     0,
-       0,   109,   110,   111,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   120,    31,     0,   113,   112,
-     114,     0,     0,    35,     0,     0,     0,     0,     0,     0,
-       0,    77,     0,     0,     0,     0,    62,     0,    45,     0,
-       0,     0,     0,     0,    46,     8,     9,     6,    10,    16,
-      87,    17,    18,    54,     0,     0,    51,     0,     0,     0,
-       0,     0,    51,     0,     0,   133,   132,   131,     0,     0,
-     124,   125,   126,   127,   128,     0,   106,     0,    37,     0,
-     104,    38,    51,     0,     0,    81,    79,    97,   105,    58,
-      69,    89,    93,    94,    90,    91,    92,    15,    53,    24,
-       0,    64,    65,     0,    29,    51,    28,     0,   107,   129,
-     130,    32,    34,     0,     0,    40,     0,     0,    14,    26,
-      25,    27,     0,     0,     0,    39,     0,    42,     0,   108,
-      33,     0,     0,     0,     0,   100,     0,     0,    43,     0,
-       0,     0,     0,   121,    88,   101,     0,    41,   122
+     117,    29,     0,   110,   109,   111,     0,     0,    33,     0,
+       0,     0,     0,     0,     0,     0,    74,     0,     0,     0,
+       0,    59,     0,    43,     0,     0,     0,     0,     0,    44,
+       6,     7,     8,    14,    84,    15,    16,    52,     0,     0,
+      49,     0,     0,     0,     0,     0,    49,     0,     0,   130,
+     129,   128,     0,     0,   121,   122,   123,   124,   125,     0,
+     103,     0,    35,     0,   101,    36,    49,     0,     0,    78,
+      76,    94,   102,    55,    66,    86,    90,    91,    87,    88,
+      89,    13,    51,    22,     0,    61,    62,     0,    27,    49,
+      26,     0,   104,   126,   127,    30,    32,     0,     0,    38,
+       0,     0,    12,    24,    23,    25,     0,     0,     0,    37,
+       0,    40,     0,   105,    31,     0,     0,     0,     0,    97,
+       0,     0,    41,     0,     0,     0,     0,   118,    85,    98,
+       0,    39,   119
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     3,    34,   168,   166,    35,    37,   109,   112,
-      83,    84,   185,    85,   176,    69,    70,    86,   102,   103,
-      87,   317,    88,   281,    89,   121,   326,   141,    91,    72,
-     128,   211,   129,   337,   130
+      -1,     1,     3,    33,   163,    34,    36,   107,   109,    82,
+      83,   180,    84,   172,    68,    69,    85,   100,   101,    86,
+     311,    87,   275,    88,   118,   320,   138,    90,    71,   125,
+     206,   126,   331,   127
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -128
+#define YYPACT_NINF -125
 static const yytype_int16 yypact[] =
 {
-    -128,     4,  -128,   315,   -35,  -128,  -128,  -128,  -128,   -10,
-    -128,  -128,  -128,  -128,  -128,    44,    44,  -128,   -10,   -10,
-    -128,  -128,  -128,  -128,  -128,  -128,   -10,   416,   371,   371,
-     -49,     9,    32,  -128,  -128,    38,  -128,   487,   487,   344,
-      69,   -10,   391,    69,   487,   209,   489,    69,   317,   317,
-    -128,    49,  -128,   317,   317,    42,    48,   106,    67,  -128,
-      61,   191,    25,    93,   191,    67,    67,    68,   170,  -128,
-    -128,  -128,    72,    84,  -128,  -128,    86,  -128,   109,  -128,
-    -128,  -128,   233,  -128,  -128,    80,  -128,  -128,   115,  -128,
-     426,  -128,    84,   120,  -128,   317,  -128,   317,  -128,  -128,
-    -128,   317,   137,  -128,  -128,  -128,   148,   155,   397,  -128,
-      74,    74,  -128,   164,   371,   204,   240,   207,   206,    68,
-     223,  -128,  -128,  -128,  -128,   270,   317,   317,   227,  -128,
-     183,  -128,    90,   160,   317,   -10,  -128,   234,   237,    16,
-    -128,   254,  -128,   255,   256,   257,   240,  -128,   212,   168,
-     548,   317,   317,   428,   258,  -128,  -128,  -128,    84,   371,
-     240,   318,   316,   335,   348,   371,   315,   502,   315,   512,
-    -128,   240,   240,   371,    49,  -128,  -128,  -128,  -128,   289,
-    -128,  -128,   330,  -128,   240,   291,    11,   307,   168,   312,
-      68,    74,  -128,  -128,   160,   317,   317,   317,   377,   379,
-     317,   317,   317,   317,   317,  -128,  -128,   324,  -128,  -128,
-    -128,   325,   337,  -128,    77,   317,   338,   126,    77,   240,
-     240,  -128,   339,   342,   249,   347,  -128,   416,  -128,   352,
-     170,   170,   170,   170,  -128,  -128,  -128,  -128,  -128,  -128,
-     362,  -128,  -128,   227,    -2,   359,   -10,   366,   240,   240,
-     240,   240,   375,   336,   384,   562,   590,   597,   317,   317,
-     213,   213,  -128,  -128,  -128,   385,  -128,    61,  -128,   357,
-     395,  -128,   -10,   396,   398,  -128,  -128,  -128,  -128,  -128,
-    -128,  -128,  -128,  -128,  -128,  -128,  -128,   240,  -128,  -128,
-     434,  -128,  -128,   400,  -128,   432,  -128,   424,  -128,   436,
-     436,   459,  -128,   240,    77,  -128,   402,   240,  -128,  -128,
-    -128,  -128,   404,   317,   411,  -128,   240,  -128,   415,  -128,
-    -128,   216,   418,   240,   413,  -128,   421,   240,  -128,   317,
-     216,   419,   302,   425,  -128,  -128,   317,  -128,   573
+    -125,     7,  -125,   308,   -41,  -125,  -125,  -125,  -125,   -19,
+    -125,  -125,  -125,  -125,  -125,    80,    80,  -125,   -19,   -19,
+    -125,  -125,  -125,  -125,  -125,  -125,   -19,   405,   364,   364,
+     -31,   -15,  -125,  -125,    -2,  -125,   528,   528,   337,   -18,
+     -19,   409,   -18,   528,   230,   187,   -18,   448,   448,  -125,
+     257,  -125,   448,   448,    -6,    15,    94,   309,  -125,    49,
+      19,    44,    95,    19,   309,   309,    63,   391,  -125,  -125,
+    -125,    90,   137,  -125,  -125,   145,  -125,   146,  -125,  -125,
+    -125,    66,  -125,  -125,    52,  -125,  -125,   150,  -125,   147,
+    -125,   137,    57,  -125,   448,   448,  -125,  -125,  -125,   448,
+     167,  -125,  -125,  -125,   184,   200,   431,  -125,    47,  -125,
+     201,   364,   217,   189,   223,   221,    63,   228,  -125,  -125,
+    -125,  -125,   289,   448,   448,   231,  -125,   181,  -125,   411,
+      54,   448,   -19,  -125,   237,   238,    12,  -125,   240,  -125,
+     241,   244,   246,   189,  -125,   245,   114,   319,   448,   448,
+     417,   243,  -125,  -125,  -125,   137,   364,   189,   293,   312,
+     313,   341,   364,   308,   542,   552,  -125,   189,   189,   364,
+     257,  -125,  -125,  -125,  -125,   282,  -125,   315,  -125,   189,
+     287,    42,   296,   114,   303,    63,    47,  -125,  -125,    54,
+     448,   448,   448,   363,   369,   448,   448,   448,   448,   448,
+    -125,  -125,   306,  -125,  -125,  -125,   311,   316,  -125,    53,
+     448,   321,    65,    53,   189,   189,  -125,   318,   324,   250,
+     325,  -125,   405,  -125,   326,   391,   391,   391,   391,  -125,
+    -125,  -125,  -125,  -125,   317,  -125,  -125,   231,   130,   328,
+     -19,   323,   189,   189,   189,   189,   334,   336,   340,   602,
+     621,   628,   448,   448,   197,   197,  -125,  -125,  -125,   352,
+    -125,    49,  -125,   516,   359,  -125,   -19,   366,   371,  -125,
+    -125,  -125,  -125,  -125,  -125,  -125,  -125,  -125,  -125,  -125,
+    -125,   189,  -125,  -125,   474,  -125,  -125,   361,  -125,   165,
+    -125,   399,  -125,   235,   235,   432,  -125,   189,    53,  -125,
+     376,   189,  -125,  -125,  -125,  -125,   377,   448,   380,  -125,
+     189,  -125,   383,  -125,  -125,   112,   385,   189,   386,  -125,
+     388,   189,  -125,   448,   112,   382,   267,   395,  -125,  -125,
+     448,  -125,   613
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -128,  -128,  -128,   -77,  -128,  -128,  -128,   538,    50,   382,
-     -57,   429,    33,    -7,  -128,   -48,   -43,   -21,    36,  -127,
-     -23,  -128,    29,    17,  -101,   -28,   161,  -128,   -37,    -8,
-     -65,   299,     2,  -128,   -32
+    -125,  -125,  -125,   292,  -125,  -125,   578,    45,   354,   -56,
+     400,   -48,   -25,  -125,    -7,   -42,   -21,    -5,  -124,     5,
+    -125,   -10,    89,  -118,   -28,   140,  -125,   -46,     4,   -90,
+     277,    -4,  -125,   -16
 };
 
 /* 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 -64
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -61
 static const yytype_int16 yytable[] =
 {
-      90,    90,   117,   136,     2,   206,    71,    55,    57,    90,
-      90,    90,    94,    95,   104,   104,    90,    56,    56,   147,
-     248,   104,    93,   120,   137,   216,   142,   143,    36,    73,
-      92,    92,   107,    48,    49,   135,   208,   209,   210,   245,
-     148,    92,   144,   145,   113,   180,   181,   118,   222,   223,
-     123,   124,    48,    49,    41,   125,   131,   126,   127,    42,
-     177,   157,    50,   167,   138,   169,   105,   105,    59,    60,
-      96,   189,   155,   105,   106,    41,    67,   -63,    99,   100,
-     115,    50,   126,   127,   158,    52,    90,   223,   186,   235,
-     108,   237,    53,   114,    97,    54,   119,   122,    48,    49,
-     178,    98,    51,   170,    52,    74,   132,   183,    75,   243,
-     179,    53,    76,    77,    54,   133,    92,   134,   148,   224,
-      99,   100,    99,   100,    78,    79,   253,    50,   192,   193,
-      82,    90,   229,    41,   207,   146,   212,    90,   301,   149,
-      78,    79,   252,   240,   159,    90,    99,   100,   239,   241,
-      52,   150,   228,   151,   225,   124,   246,    53,   234,   101,
-      54,    92,   139,   255,   256,   257,   242,    92,   260,   261,
-     262,   263,   264,    78,   270,    92,   152,   268,    48,    49,
-     271,   272,   160,   269,   165,   213,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   273,   274,   208,   209,
-     210,   171,   282,   282,   282,   282,   279,    50,    74,    75,
-     302,    75,   172,    76,    77,    76,    77,    48,    49,   173,
-     291,   186,   186,   202,   203,   204,   299,   300,   294,    73,
-      52,   182,   283,   283,   283,   283,   249,    53,    78,    79,
-      54,    48,   153,   154,    99,   100,    50,   309,   284,   285,
-     286,   205,   195,   196,   197,   198,   199,   200,   201,   202,
-     203,   204,    99,   100,   308,   324,   325,   315,   184,    52,
-      50,   187,   311,   188,   116,   314,    68,   191,    74,    54,
-     221,    75,   292,   293,   318,    76,    77,   190,   322,   155,
-     156,    51,   118,    52,   194,   328,   289,   332,   214,   331,
-      68,   215,   296,    54,   338,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   320,     4,   277,   217,   218,
-     219,   220,   305,   231,   230,    48,    49,   227,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,   232,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    48,    49,    50,   233,   244,   247,    28,    29,
-     195,   196,   197,   198,   199,   200,   201,   202,   203,   204,
-     335,   245,   250,    30,    31,    32,   251,    52,    33,    48,
-      49,    50,    74,   258,    53,    75,   259,    54,   265,    76,
-      77,    78,    79,   266,   226,    80,    81,    99,   100,    48,
-      49,   267,    51,   297,    52,    48,    49,   275,    50,    74,
-     276,    68,    75,    82,    54,   278,    76,    77,    78,    79,
-     280,   303,    80,    81,    48,    49,   287,   288,    50,    51,
-     290,    52,   161,   162,    50,   163,    48,    49,    68,   295,
-      82,    54,    48,    49,   200,   201,   202,   203,   204,   110,
-     111,    52,   298,    50,   101,   174,   111,    52,    53,   304,
-     306,    54,   307,   312,    68,    50,   310,    54,   313,   316,
-      74,    50,   319,    75,    51,   321,    52,    76,    77,   323,
-     329,   164,   327,    68,   226,   330,    54,   334,    52,   336,
-     175,   333,   140,   254,    52,    53,    41,     0,    54,     0,
-       0,    68,     0,     0,    54,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,    74,     0,    74,    75,     0,
-      75,     0,    76,    77,    76,    77,     0,     0,     0,     0,
-      99,   100,    99,   100,    38,    39,    40,     0,    43,    44,
-      45,    46,    47,    41,     0,    58,   101,     0,    61,    62,
-      63,    64,    65,    66,     0,   236,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   238,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   208,   209,   210,    75,
-       0,     0,     0,    76,    77,   197,   198,   199,   200,   201,
-     202,   203,   204,   198,   199,   200,   201,   202,   203,   204
+      89,    89,   114,   133,    92,   201,    70,     2,    89,    89,
+      89,    55,    55,   105,   134,    89,   139,   140,   176,    54,
+      56,   211,    35,    72,    91,    91,   103,   103,   217,   218,
+      93,    94,   104,   103,    91,    97,    98,   110,   112,   145,
+     115,   102,   102,   120,   121,    40,    40,    95,   102,   128,
+     117,   242,    47,    48,    41,   123,   124,   135,   129,   144,
+     154,    96,   132,    58,    59,   218,    77,    78,   152,   141,
+     142,    66,    97,    98,    47,   150,   151,   155,   164,   165,
+     237,    49,   130,    89,   106,   181,   178,   111,    47,    48,
+     116,   119,   203,   204,   205,   166,   247,    97,    98,   173,
+      77,    78,   175,    49,    51,   131,    40,    91,   -60,   184,
+     174,    52,    77,   264,    53,   145,   156,    49,    81,   187,
+     188,   162,   152,   153,    50,   202,    51,   207,    89,   224,
+     143,   223,   219,    67,    89,   295,    53,   229,    50,   234,
+      51,    89,    77,    78,   236,   220,   121,    52,    97,    98,
+      53,   240,    91,   158,   159,    74,   160,   146,    91,    75,
+      76,   318,   319,   262,   136,    91,   265,   266,   203,   204,
+     205,   239,   233,   235,   249,   250,   251,   208,   246,   254,
+     255,   256,   257,   258,   190,   191,   192,   193,   194,   195,
+     196,   197,   198,   199,   263,   286,   287,   276,   276,   276,
+     276,   273,   161,    73,   147,   296,    74,   197,   198,   199,
+      75,    76,   148,   149,   285,   181,   181,   157,    72,   267,
+     268,   277,   277,   277,   277,    73,   243,    73,    74,    40,
+      74,   167,    75,    76,    75,    76,   293,   294,    47,    48,
+      97,    98,   303,   195,   196,   197,   198,   199,   168,   200,
+     288,    40,   309,   190,   191,   192,   193,   194,   195,   196,
+     197,   198,   199,   122,   169,   123,   124,    49,   177,   308,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
+     115,   179,   316,    97,    98,   283,   302,   182,   183,   322,
+      51,   290,   185,   325,   305,   113,   186,    67,   189,   225,
+      53,   209,   210,   314,   212,   213,   312,   326,   214,     4,
+     215,   299,   222,   216,   332,   278,   279,   280,   271,   226,
+     227,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,   329,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    47,    48,    73,   228,   238,
+      74,    28,    29,   241,    75,    76,   239,   203,   204,   205,
+      74,   244,    97,    98,    75,    76,    30,   245,    31,   252,
+     259,    32,    47,    48,    49,    73,   253,   221,    74,   260,
+     261,   281,    75,    76,    77,    78,   269,   284,    79,    80,
+      97,    98,   270,   272,   274,    50,   282,    51,   289,    47,
+      48,    49,    73,   291,    67,    74,    81,    53,   292,    75,
+      76,    77,    78,    47,    48,    79,    80,    47,    48,    47,
+      48,    99,    50,   298,    51,    47,    48,   304,    49,    73,
+     300,    67,    74,    81,    53,   301,    75,    76,   306,    47,
+      48,   307,    49,   310,   315,   313,    49,   317,    49,   321,
+     328,    51,   324,   323,    49,   230,    47,    48,    52,   330,
+     171,    53,   137,    50,   327,    51,   248,   108,    49,    51,
+       0,    51,    67,   221,     0,    53,    52,    51,    52,    53,
+      99,    53,    47,    48,    52,    49,     0,    53,     0,   170,
+       0,    51,     0,     0,     0,     0,     0,     0,    67,     0,
+       0,    53,     0,     0,     0,     0,     0,     0,    51,     0,
+       0,    49,     0,     0,     0,    52,     0,     0,    53,   190,
+     191,   192,   193,   194,   195,   196,   197,   198,   199,     0,
+       0,     0,     0,     0,    51,     0,     0,     0,     0,     0,
+       0,    67,     0,     0,    53,   190,   191,   192,   193,   194,
+     195,   196,   197,   198,   199,   190,   191,   192,   193,   194,
+     195,   196,   197,   198,   199,     0,    73,     0,     0,    74,
+       0,     0,     0,    75,    76,     0,     0,     0,     0,     0,
+     297,    97,    98,     0,    37,    38,    39,     0,    42,    43,
+      44,    45,    46,     0,     0,    57,     0,    99,    60,    61,
+      62,    63,    64,    65,     0,   231,   191,   192,   193,   194,
+     195,   196,   197,   198,   199,   232,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   192,   193,   194,   195,
+     196,   197,   198,   199,   193,   194,   195,   196,   197,   198,
+     199
 };
 
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-128)))
-
-#define yytable_value_is_error(Yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
-      28,    29,    45,    60,     0,   132,    27,    15,    16,    37,
-      38,    39,    61,    62,    37,    38,    44,    15,    16,    67,
-       9,    44,    29,    46,    61,     9,    63,    64,    63,    27,
-      28,    29,    39,     8,     9,    58,    38,    39,    40,    41,
-      68,    39,    65,    66,    42,   110,   111,    45,   149,   150,
-      48,    49,     8,     9,    64,     6,    54,     8,     9,     9,
-     108,    82,    37,    95,    62,    97,    37,    38,    18,    19,
-      61,   119,    56,    44,    38,    64,    26,    66,    53,    54,
-      44,    37,     8,     9,    82,    60,   114,   188,   116,   166,
-      40,   168,    67,    43,    62,    70,    46,    47,     8,     9,
-     108,    63,    58,   101,    60,    38,    64,   114,    41,   174,
-     108,    67,    45,    46,    70,    67,   114,    11,   146,   151,
-      53,    54,    53,    54,    47,    48,   191,    37,   126,   127,
-      69,   159,   160,    64,   132,    67,   134,   165,   265,    67,
-      47,    48,   190,   171,    64,   173,    53,    54,   171,   172,
-      60,    67,   159,    67,   152,   153,   184,    67,   165,    69,
-      70,   159,    69,   195,   196,   197,   173,   165,   200,   201,
-     202,   203,   204,    47,    48,   173,    67,   214,     8,     9,
-     217,   218,    67,   215,    64,   135,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,   219,   220,    38,    39,
-      40,    64,   230,   231,   232,   233,   227,    37,    38,    41,
-     267,    41,    64,    45,    46,    45,    46,     8,     9,    64,
-     248,   249,   250,    10,    11,    12,   258,   259,   251,   227,
-      60,    67,   230,   231,   232,   233,   186,    67,    47,    48,
-      70,     8,     9,    10,    53,    54,    37,   290,   231,   232,
-     233,    68,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    53,    54,   287,    49,    50,   304,    64,    60,
-      37,    64,   295,    67,    65,   303,    67,     7,    38,    70,
-      68,    41,   249,   250,   307,    45,    46,    64,   316,    56,
-      57,    58,   290,    60,    67,   323,   246,   329,    64,   327,
-      67,    64,   252,    70,   336,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,   313,     1,    68,    64,    64,
-      64,    64,   272,     7,     6,     8,     9,    69,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,     7,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,     8,     9,    37,     7,    67,    66,    43,    44,
+      28,    29,    44,    59,    29,   129,    27,     0,    36,    37,
+      38,    15,    16,    38,    60,    43,    62,    63,   108,    15,
+      16,     9,    63,    27,    28,    29,    36,    37,   146,   147,
+      61,    62,    37,    43,    38,    53,    54,    41,    43,    67,
+      44,    36,    37,    47,    48,    64,    64,    62,    43,    53,
+      45,     9,     8,     9,     9,     8,     9,    61,    64,    66,
+      81,    63,    57,    18,    19,   183,    47,    48,    56,    64,
+      65,    26,    53,    54,     8,     9,    10,    81,    94,    95,
+     170,    37,    67,   111,    39,   113,   111,    42,     8,     9,
+      45,    46,    38,    39,    40,    99,   186,    53,    54,   106,
+      47,    48,   106,    37,    60,    11,    64,   111,    66,   116,
+     106,    67,    47,    48,    70,   143,    64,    37,    69,   123,
+     124,    64,    56,    57,    58,   129,    60,   131,   156,   157,
+      67,   156,   148,    67,   162,   259,    70,   162,    58,   167,
+      60,   169,    47,    48,   169,   149,   150,    67,    53,    54,
+      70,   179,   156,     6,     7,    41,     9,    67,   162,    45,
+      46,    49,    50,   209,    69,   169,   212,   213,    38,    39,
+      40,    41,   167,   168,   190,   191,   192,   132,   185,   195,
+     196,   197,   198,   199,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,   210,   243,   244,   225,   226,   227,
+     228,   222,    55,    38,    67,   261,    41,    10,    11,    12,
+      45,    46,    67,    67,   242,   243,   244,    67,   222,   214,
+     215,   225,   226,   227,   228,    38,   181,    38,    41,    64,
+      41,    64,    45,    46,    45,    46,   252,   253,     8,     9,
+      53,    54,   284,     8,     9,    10,    11,    12,    64,    68,
+     245,    64,   298,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,     6,    64,     8,     9,    37,    67,   297,
        3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      68,    41,    65,    58,    59,    60,    64,    60,    63,     8,
-       9,    37,    38,     6,    67,    41,     7,    70,    64,    45,
-      46,    47,    48,    68,    56,    51,    52,    53,    54,     8,
-       9,    64,    58,    67,    60,     8,     9,    68,    37,    38,
-      68,    67,    41,    69,    70,    68,    45,    46,    47,    48,
-      68,    64,    51,    52,     8,     9,    64,    68,    37,    58,
-      64,    60,     6,     7,    37,     9,     8,     9,    67,    64,
-      69,    70,     8,     9,     8,     9,    10,    11,    12,    58,
-      59,    60,    68,    37,    69,    58,    59,    60,    67,    64,
-      64,    70,    64,    39,    67,    37,    66,    70,     9,    67,
-      38,    37,    68,    41,    58,    64,    60,    45,    46,    64,
-      67,    55,    64,    67,    56,    64,    70,    68,    60,    64,
-     108,   330,    63,   194,    60,    67,    64,    -1,    70,    -1,
+     284,    64,   310,    53,    54,   240,   281,    64,    67,   317,
+      60,   246,    64,   321,   289,    65,     7,    67,    67,     6,
+      70,    64,    64,   307,    64,    64,   301,   323,    64,     1,
+      64,   266,    69,    68,   330,   226,   227,   228,    68,     7,
+       7,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    68,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,     8,     9,    38,     7,    67,
+      41,    43,    44,    66,    45,    46,    41,    38,    39,    40,
+      41,    65,    53,    54,    45,    46,    58,    64,    60,     6,
+      64,    63,     8,     9,    37,    38,     7,    56,    41,    68,
+      64,    64,    45,    46,    47,    48,    68,    64,    51,    52,
+      53,    54,    68,    68,    68,    58,    68,    60,    64,     8,
+       9,    37,    38,    67,    67,    41,    69,    70,    68,    45,
+      46,    47,    48,     8,     9,    51,    52,     8,     9,     8,
+       9,    69,    58,    64,    60,     8,     9,    66,    37,    38,
+      64,    67,    41,    69,    70,    64,    45,    46,    39,     8,
+       9,     9,    37,    67,    64,    68,    37,    64,    37,    64,
+      68,    60,    64,    67,    37,   163,     8,     9,    67,    64,
+     106,    70,    62,    58,   324,    60,   189,    58,    37,    60,
+      -1,    60,    67,    56,    -1,    70,    67,    60,    67,    70,
+      69,    70,     8,     9,    67,    37,    -1,    70,    -1,    58,
+      -1,    60,    -1,    -1,    -1,    -1,    -1,    -1,    67,    -1,
+      -1,    70,    -1,    -1,    -1,    -1,    -1,    -1,    60,    -1,
+      -1,    37,    -1,    -1,    -1,    67,    -1,    -1,    70,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    -1,
+      -1,    -1,    -1,    -1,    60,    -1,    -1,    -1,    -1,    -1,
       -1,    67,    -1,    -1,    70,     3,     4,     5,     6,     7,
        8,     9,    10,    11,    12,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    38,    -1,    38,    41,    -1,
-      41,    -1,    45,    46,    45,    46,    -1,    -1,    -1,    -1,
-      53,    54,    53,    54,     6,     7,     8,    -1,    10,    11,
-      12,    13,    14,    64,    -1,    17,    69,    -1,    20,    21,
+       8,     9,    10,    11,    12,    -1,    38,    -1,    -1,    41,
+      -1,    -1,    -1,    45,    46,    -1,    -1,    -1,    -1,    -1,
+      64,    53,    54,    -1,     6,     7,     8,    -1,    10,    11,
+      12,    13,    14,    -1,    -1,    17,    -1,    69,    20,    21,
       22,    23,    24,    25,    -1,    63,     4,     5,     6,     7,
        8,     9,    10,    11,    12,    63,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    38,    39,    40,    41,
-      -1,    -1,    -1,    45,    46,     5,     6,     7,     8,     9,
-      10,    11,    12,     6,     7,     8,     9,    10,    11,    12
+       7,     8,     9,    10,    11,    12,     5,     6,     7,     8,
+       9,    10,    11,    12,     6,     7,     8,     9,    10,    11,
+      12
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -956,37 +913,37 @@ static const yytype_uint8 yystos[] =
        0,    72,     0,    73,     1,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    28,
       29,    30,    31,    32,    33,    34,    35,    36,    43,    44,
-      58,    59,    60,    63,    74,    77,    63,    78,    78,    78,
-      78,    64,    79,    78,    78,    78,    78,    78,     8,     9,
-      37,    58,    60,    67,    70,   100,   103,   100,    78,    79,
-      79,    78,    78,    78,    78,    78,    78,    79,    67,    86,
-      87,    88,   100,   103,    38,    41,    45,    46,    47,    48,
-      51,    52,    69,    81,    82,    84,    88,    91,    93,    95,
-      96,    99,   103,    84,    61,    62,    61,    62,    63,    53,
-      54,    69,    89,    90,    91,    93,    89,    84,    79,    79,
-      58,    59,    80,   103,    79,    89,    65,    87,   103,    79,
-      91,    96,    79,   103,   103,     6,     8,     9,   101,   103,
-     105,   103,    64,    67,    11,    91,    81,    99,   103,    69,
-      82,    98,    99,    99,    91,    91,    67,    86,    96,    67,
-      67,    67,    67,     9,    10,    56,    57,    88,   103,    64,
-      67,     6,     7,     9,    55,    64,    76,   105,    75,   105,
-     103,    64,    64,    64,    58,    80,    85,    86,   100,   103,
-     101,   101,    67,    84,    64,    83,    96,    64,    67,    86,
-      64,     7,   103,   103,    67,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    68,    90,   103,    38,    39,
-      40,   102,   103,    79,    64,    64,     9,    64,    64,    64,
-      64,    68,    95,    95,   105,   103,    56,    69,    84,    96,
-       6,     7,     7,     7,    84,    74,    63,    74,    63,    91,
-      96,    91,    84,   101,    67,    41,    96,    66,     9,    79,
-      65,    64,    86,   101,   102,   105,   105,   105,     6,     7,
-     105,   105,   105,   105,   105,    64,    68,    64,    99,   105,
-      48,    99,    99,    91,    91,    68,    68,    68,    68,    88,
-      68,    94,    96,   103,    94,    94,    94,    64,    68,    79,
-      64,    96,    83,    83,    91,    64,    79,    67,    68,   105,
-     105,    90,    81,    64,    64,    79,    64,    64,    91,    87,
-      66,    91,    39,     9,    96,    99,    67,    92,    91,    68,
-     103,    64,    96,    64,    49,    50,    97,    64,    96,    67,
-      64,    96,   105,    97,    68,    68,    64,   104,   105
+      58,    60,    63,    74,    76,    63,    77,    77,    77,    77,
+      64,    78,    77,    77,    77,    77,    77,     8,     9,    37,
+      58,    60,    67,    70,    99,   102,    99,    77,    78,    78,
+      77,    77,    77,    77,    77,    77,    78,    67,    85,    86,
+      87,    99,   102,    38,    41,    45,    46,    47,    48,    51,
+      52,    69,    80,    81,    83,    87,    90,    92,    94,    95,
+      98,   102,    83,    61,    62,    62,    63,    53,    54,    69,
+      88,    89,    90,    92,    88,    83,    78,    78,    58,    79,
+     102,    78,    88,    65,    86,   102,    78,    90,    95,    78,
+     102,   102,     6,     8,     9,   100,   102,   104,   102,    64,
+      67,    11,    90,    80,    98,   102,    69,    81,    97,    98,
+      98,    90,    90,    67,    85,    95,    67,    67,    67,    67,
+       9,    10,    56,    57,    87,   102,    64,    67,     6,     7,
+       9,    55,    64,    75,   104,   104,   102,    64,    64,    64,
+      58,    79,    84,    85,    99,   102,   100,    67,    83,    64,
+      82,    95,    64,    67,    85,    64,     7,   102,   102,    67,
+       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      68,    89,   102,    38,    39,    40,   101,   102,    78,    64,
+      64,     9,    64,    64,    64,    64,    68,    94,    94,   104,
+     102,    56,    69,    83,    95,     6,     7,     7,     7,    83,
+      74,    63,    63,    90,    95,    90,    83,   100,    67,    41,
+      95,    66,     9,    78,    65,    64,    85,   100,   101,   104,
+     104,   104,     6,     7,   104,   104,   104,   104,   104,    64,
+      68,    64,    98,   104,    48,    98,    98,    90,    90,    68,
+      68,    68,    68,    87,    68,    93,    95,   102,    93,    93,
+      93,    64,    68,    78,    64,    95,    82,    82,    90,    64,
+      78,    67,    68,   104,   104,    89,    80,    64,    64,    78,
+      64,    64,    90,    86,    66,    90,    39,     9,    95,    98,
+      67,    91,    90,    68,   102,    64,    95,    64,    49,    50,
+      96,    64,    95,    67,    64,    95,   104,    96,    68,    68,
+      64,   103,   104
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1001,50 +958,78 @@ static const yytype_uint8 yystos[] =
 
 /* Like YYERROR except do call yyerror.  This remains here temporarily
    to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
+   Once GCC version 2 has supplanted version 1, this can go.  */
 
 #define YYFAIL         goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yytoken = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK (1);                                          \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
       yyerror (YY_("syntax error: cannot back up")); \
       YYERROR;                                                 \
     }                                                          \
 while (YYID (0))
 
-/* Error token number */
+
 #define YYTERROR       1
 #define YYERRCODE      256
 
 
-/* This macro is provided for backward compatibility. */
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
+    do                                                                 \
+      if (YYID (N))                                                    \
+       {                                                               \
+         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         (Current).first_line   = (Current).last_line   =              \
+           YYRHSLOC (Rhs, 0).last_line;                                \
+         (Current).first_column = (Current).last_column =              \
+           YYRHSLOC (Rhs, 0).last_column;                              \
+       }                                                               \
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
 #ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
 #endif
 
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
+
 #ifdef YYLEX_PARAM
 # define YYLEX yylex (YYLEX_PARAM)
 #else
@@ -1094,8 +1079,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
     YYSTYPE const * const yyvaluep;
 #endif
 {
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
   if (!yyvaluep)
     return;
 # ifdef YYPRINT
@@ -1104,7 +1087,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 # else
   YYUSE (yyoutput);
 # endif
-  YYUSE (yytype);
+  switch (yytype)
+    {
+      default:
+       break;
+    }
 }
 
 
@@ -1141,20 +1128,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");
 }
 
@@ -1188,11 +1172,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");
     }
 }
 
@@ -1229,6 +1213,7 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
+\f
 
 #if YYERROR_VERBOSE
 
@@ -1331,145 +1316,115 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
 {
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                    return 2;
-                  yysize = yysize1;
-                }
-              }
-        }
-    }
+  int yyn = yypact[yystate];
 
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+        constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+                   + sizeof yyexpecting - 1
+                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+                      * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+        YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+         {
+           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+             {
+               yycount = 1;
+               yysize = yysize0;
+               yyformat[sizeof yyunexpected - 1] = '\0';
+               break;
+             }
+           yyarg[yycount++] = yytname[yyx];
+           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+           yysize_overflow |= (yysize1 < yysize);
+           yysize = yysize1;
+           yyfmt = yystpcpy (yyfmt, yyprefix);
+           yyprefix = yyor;
+         }
 
-  {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-      return 2;
-    yysize = yysize1;
-  }
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
 
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
+      if (yysize_overflow)
+       return YYSIZE_MAXIMUM;
 
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
+      if (yyresult)
+       {
+         /* Avoid sprintf, as that infringes on the user's name space.
+            Don't have undefined behavior even if the translation
+            produced a string with the wrong number of "%s"s.  */
+         char *yyp = yyresult;
+         int yyi = 0;
+         while ((*yyp = *yyf) != '\0')
+           {
+             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+               {
+                 yyp += yytnamerr (yyp, yyarg[yyi++]);
+                 yyf += 2;
+               }
+             else
+               {
+                 yyp++;
+                 yyf++;
+               }
+           }
+       }
+      return yysize;
+    }
 }
 #endif /* YYERROR_VERBOSE */
+\f
 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -1494,31 +1449,44 @@ yydestruct (yymsg, yytype, yyvaluep)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
-  YYUSE (yytype);
-}
+  switch (yytype)
+    {
 
+      default:
+       break;
+    }
+}
+\f
 
+/* Prevent warnings from -Wmissing-prototypes.  */
 
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
 
-/* The lookahead symbol.  */
-int yychar;
 
 
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
+/* The look-ahead symbol.  */
+int yychar;
 
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
 int yynerrs;
 
 
+
 /*----------.
 | yyparse.  |
 `----------*/
@@ -1545,37 +1513,14 @@ yyparse ()
 #endif
 #endif
 {
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-
-       Refer to the stacks through separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
+  
+  int yystate;
   int yyn;
   int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
   int yytoken = 0;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
 #if YYERROR_VERBOSE
   /* Buffer for error messages, and its allocated size.  */
   char yymsgbuf[128];
@@ -1583,22 +1528,54 @@ yyparse ()
   YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
 #endif
 
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
 #define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yyssp = yyss = yyssa;
-  yyvsp = yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1625,6 +1602,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
@@ -1632,6 +1610,7 @@ yyparse ()
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
+
                    &yystacksize);
 
        yyss = yyss1;
@@ -1654,8 +1633,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);
@@ -1666,6 +1646,7 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
+
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long int) yystacksize));
 
@@ -1675,9 +1656,6 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
   goto yybackup;
 
 /*-----------.
@@ -1686,16 +1664,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: "));
@@ -1721,27 +1699,29 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
 
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
     yyerrstatus--;
 
-  /* Shift the lookahead token.  */
+  /* Shift the look-ahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
 
   yystate = yyn;
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1778,7 +1758,6 @@ yyreduce:
   switch (yyn)
     {
         case 3:
-/* Line 1787 of yacc.c  */
 #line 70 "a.y"
     {
                stmtline = lineno;
@@ -1786,36 +1765,26 @@ yyreduce:
     break;
 
   case 5:
-/* Line 1787 of yacc.c  */
 #line 77 "a.y"
     {
-               if((yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name);
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 7:
-/* Line 1787 of yacc.c  */
-#line 84 "a.y"
-    {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
+               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
+                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname);
                (yyvsp[(1) - (2)].sym)->type = LLAB;
                (yyvsp[(1) - (2)].sym)->value = pc;
        }
     break;
 
-  case 9:
-/* Line 1787 of yacc.c  */
-#line 90 "a.y"
+  case 7:
+#line 86 "a.y"
     {
                (yyvsp[(1) - (4)].sym)->type = LVAR;
                (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
        }
     break;
 
-  case 10:
-/* Line 1787 of yacc.c  */
-#line 95 "a.y"
+  case 8:
+#line 91 "a.y"
     {
                if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval))
                        yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name);
@@ -1823,97 +1792,85 @@ yyreduce:
        }
     break;
 
-  case 14:
-/* Line 1787 of yacc.c  */
-#line 109 "a.y"
+  case 12:
+#line 105 "a.y"
     {
                outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr));
        }
     break;
 
-  case 15:
-/* Line 1787 of yacc.c  */
-#line 113 "a.y"
+  case 13:
+#line 109 "a.y"
     {
                outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].lval), &nullgen);
        }
     break;
 
-  case 16:
-/* Line 1787 of yacc.c  */
-#line 117 "a.y"
+  case 14:
+#line 113 "a.y"
     {
                outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
        }
     break;
 
-  case 17:
-/* Line 1787 of yacc.c  */
-#line 124 "a.y"
+  case 15:
+#line 120 "a.y"
     {
                outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
        }
     break;
 
-  case 18:
-/* Line 1787 of yacc.c  */
-#line 131 "a.y"
+  case 16:
+#line 127 "a.y"
     {
                outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
        }
     break;
 
-  case 19:
-/* Line 1787 of yacc.c  */
-#line 138 "a.y"
+  case 17:
+#line 134 "a.y"
     {
                outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr));
        }
     break;
 
-  case 20:
-/* Line 1787 of yacc.c  */
-#line 142 "a.y"
+  case 18:
+#line 138 "a.y"
     {
                outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr));
        }
     break;
 
-  case 21:
-/* Line 1787 of yacc.c  */
-#line 149 "a.y"
+  case 19:
+#line 145 "a.y"
     {
                outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
        }
     break;
 
-  case 22:
-/* Line 1787 of yacc.c  */
-#line 156 "a.y"
+  case 20:
+#line 152 "a.y"
     {
                outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
        }
     break;
 
-  case 23:
-/* Line 1787 of yacc.c  */
-#line 163 "a.y"
+  case 21:
+#line 159 "a.y"
     {
                outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr));
        }
     break;
 
-  case 24:
-/* Line 1787 of yacc.c  */
-#line 170 "a.y"
+  case 22:
+#line 166 "a.y"
     {
                outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].lval), &nullgen);
        }
     break;
 
-  case 25:
-/* Line 1787 of yacc.c  */
-#line 177 "a.y"
+  case 23:
+#line 173 "a.y"
     {
                Addr g;
 
@@ -1924,9 +1881,8 @@ yyreduce:
        }
     break;
 
-  case 26:
-/* Line 1787 of yacc.c  */
-#line 186 "a.y"
+  case 24:
+#line 182 "a.y"
     {
                Addr g;
 
@@ -1937,127 +1893,115 @@ yyreduce:
        }
     break;
 
-  case 27:
-/* Line 1787 of yacc.c  */
-#line 198 "a.y"
+  case 25:
+#line 194 "a.y"
     {
                outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(5) - (7)].addr), (yyvsp[(3) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr));
        }
     break;
 
-  case 28:
-/* Line 1787 of yacc.c  */
-#line 202 "a.y"
+  case 26:
+#line 198 "a.y"
     {
                outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr), (yyvsp[(3) - (6)].addr).reg, &(yyvsp[(3) - (6)].addr));
        }
     break;
 
-  case 29:
-/* Line 1787 of yacc.c  */
-#line 206 "a.y"
+  case 27:
+#line 202 "a.y"
     {
                outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(4) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
        }
     break;
 
-  case 30:
-/* Line 1787 of yacc.c  */
-#line 213 "a.y"
+  case 28:
+#line 209 "a.y"
     {
                outcode((yyvsp[(1) - (3)].lval), (yyvsp[(2) - (3)].lval), &nullgen, NREG, &nullgen);
        }
     break;
 
-  case 31:
-/* Line 1787 of yacc.c  */
-#line 220 "a.y"
+  case 29:
+#line 216 "a.y"
     {
+               settext((yyvsp[(2) - (4)].addr).sym);
                (yyvsp[(4) - (4)].addr).type = D_CONST2;
                (yyvsp[(4) - (4)].addr).offset2 = ArgsSizeUnknown;
                outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
        }
     break;
 
-  case 32:
-/* Line 1787 of yacc.c  */
-#line 226 "a.y"
+  case 30:
+#line 223 "a.y"
     {
+               settext((yyvsp[(2) - (6)].addr).sym);
                (yyvsp[(6) - (6)].addr).type = D_CONST2;
                (yyvsp[(6) - (6)].addr).offset2 = ArgsSizeUnknown;
                outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
        }
     break;
 
-  case 33:
-/* Line 1787 of yacc.c  */
-#line 232 "a.y"
+  case 31:
+#line 230 "a.y"
     {
+               settext((yyvsp[(2) - (8)].addr).sym);
                (yyvsp[(6) - (8)].addr).type = D_CONST2;
                (yyvsp[(6) - (8)].addr).offset2 = (yyvsp[(8) - (8)].lval);
                outcode((yyvsp[(1) - (8)].lval), Always, &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr));
        }
     break;
 
-  case 34:
-/* Line 1787 of yacc.c  */
-#line 241 "a.y"
+  case 32:
+#line 240 "a.y"
     {
                outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
        }
     break;
 
-  case 35:
-/* Line 1787 of yacc.c  */
-#line 248 "a.y"
+  case 33:
+#line 247 "a.y"
     {
                outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &(yyvsp[(3) - (4)].addr), NREG, &nullgen);
        }
     break;
 
-  case 36:
-/* Line 1787 of yacc.c  */
-#line 255 "a.y"
+  case 34:
+#line 254 "a.y"
     {
                outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
        }
     break;
 
-  case 37:
-/* Line 1787 of yacc.c  */
-#line 262 "a.y"
+  case 35:
+#line 261 "a.y"
     {
                outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
        }
     break;
 
-  case 38:
-/* Line 1787 of yacc.c  */
-#line 266 "a.y"
+  case 36:
+#line 265 "a.y"
     {
                outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr));
        }
     break;
 
-  case 39:
-/* Line 1787 of yacc.c  */
-#line 270 "a.y"
+  case 37:
+#line 269 "a.y"
     {
                outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr));
        }
     break;
 
-  case 40:
-/* Line 1787 of yacc.c  */
-#line 274 "a.y"
+  case 38:
+#line 273 "a.y"
     {
                outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr).reg, &nullgen);
        }
     break;
 
-  case 41:
-/* Line 1787 of yacc.c  */
-#line 281 "a.y"
+  case 39:
+#line 280 "a.y"
     {
                Addr g;
 
@@ -2078,17 +2022,15 @@ yyreduce:
        }
     break;
 
-  case 42:
-/* Line 1787 of yacc.c  */
-#line 303 "a.y"
+  case 40:
+#line 302 "a.y"
     {
                outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr));
        }
     break;
 
-  case 43:
-/* Line 1787 of yacc.c  */
-#line 311 "a.y"
+  case 41:
+#line 310 "a.y"
     {
                (yyvsp[(7) - (9)].addr).type = D_REGREG2;
                (yyvsp[(7) - (9)].addr).offset = (yyvsp[(9) - (9)].lval);
@@ -2096,17 +2038,15 @@ yyreduce:
        }
     break;
 
-  case 44:
-/* Line 1787 of yacc.c  */
-#line 320 "a.y"
+  case 42:
+#line 319 "a.y"
     {
                outcode((yyvsp[(1) - (2)].lval), Always, &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
        }
     break;
 
-  case 45:
-/* Line 1787 of yacc.c  */
-#line 327 "a.y"
+  case 43:
+#line 326 "a.y"
     {
                if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST)
                        yyerror("arguments to PCDATA must be integer constants");
@@ -2114,9 +2054,8 @@ yyreduce:
        }
     break;
 
-  case 46:
-/* Line 1787 of yacc.c  */
-#line 336 "a.y"
+  case 44:
+#line 335 "a.y"
     {
                if((yyvsp[(2) - (4)].addr).type != D_CONST)
                        yyerror("index for FUNCDATA must be integer constant");
@@ -2126,41 +2065,36 @@ yyreduce:
        }
     break;
 
-  case 47:
-/* Line 1787 of yacc.c  */
-#line 347 "a.y"
+  case 45:
+#line 346 "a.y"
     {
                outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, NREG, &nullgen);
        }
     break;
 
-  case 48:
-/* Line 1787 of yacc.c  */
-#line 352 "a.y"
+  case 46:
+#line 351 "a.y"
     {
                (yyval.lval) = Always;
        }
     break;
 
-  case 49:
-/* Line 1787 of yacc.c  */
-#line 356 "a.y"
+  case 47:
+#line 355 "a.y"
     {
                (yyval.lval) = ((yyvsp[(1) - (2)].lval) & ~C_SCOND) | (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 50:
-/* Line 1787 of yacc.c  */
-#line 360 "a.y"
+  case 48:
+#line 359 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (2)].lval) | (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 53:
-/* Line 1787 of yacc.c  */
-#line 369 "a.y"
+  case 51:
+#line 368 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_BRANCH;
@@ -2168,31 +2102,20 @@ yyreduce:
        }
     break;
 
-  case 54:
-/* Line 1787 of yacc.c  */
-#line 375 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               if(pass == 2)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name);
-               (yyval.addr).type = D_BRANCH;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 55:
-/* Line 1787 of yacc.c  */
-#line 383 "a.y"
+  case 52:
+#line 374 "a.y"
     {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
                (yyval.addr) = nullgen;
+               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
+                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
                (yyval.addr).type = D_BRANCH;
                (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 56:
-/* Line 1787 of yacc.c  */
-#line 390 "a.y"
+  case 53:
+#line 384 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_CONST;
@@ -2200,27 +2123,24 @@ yyreduce:
        }
     break;
 
-  case 57:
-/* Line 1787 of yacc.c  */
-#line 396 "a.y"
+  case 54:
+#line 390 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
                (yyval.addr).type = D_CONST;
        }
     break;
 
-  case 58:
-/* Line 1787 of yacc.c  */
-#line 401 "a.y"
+  case 55:
+#line 395 "a.y"
     {
                (yyval.addr) = (yyvsp[(4) - (4)].addr);
                (yyval.addr).type = D_OCONST;
        }
     break;
 
-  case 59:
-/* Line 1787 of yacc.c  */
-#line 406 "a.y"
+  case 56:
+#line 400 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SCONST;
@@ -2228,9 +2148,8 @@ yyreduce:
        }
     break;
 
-  case 61:
-/* Line 1787 of yacc.c  */
-#line 415 "a.y"
+  case 58:
+#line 409 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2238,9 +2157,8 @@ yyreduce:
        }
     break;
 
-  case 62:
-/* Line 1787 of yacc.c  */
-#line 421 "a.y"
+  case 59:
+#line 415 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2248,17 +2166,15 @@ yyreduce:
        }
     break;
 
-  case 63:
-/* Line 1787 of yacc.c  */
-#line 429 "a.y"
+  case 60:
+#line 423 "a.y"
     {
                (yyval.lval) = 1 << (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 64:
-/* Line 1787 of yacc.c  */
-#line 433 "a.y"
+  case 61:
+#line 427 "a.y"
     {
                int i;
                (yyval.lval)=0;
@@ -2269,26 +2185,23 @@ yyreduce:
        }
     break;
 
-  case 65:
-/* Line 1787 of yacc.c  */
-#line 442 "a.y"
+  case 62:
+#line 436 "a.y"
     {
                (yyval.lval) = (1<<(yyvsp[(1) - (3)].lval)) | (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 69:
-/* Line 1787 of yacc.c  */
-#line 451 "a.y"
+  case 66:
+#line 445 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (4)].addr);
                (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
        }
     break;
 
-  case 70:
-/* Line 1787 of yacc.c  */
-#line 456 "a.y"
+  case 67:
+#line 450 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_PSR;
@@ -2296,9 +2209,8 @@ yyreduce:
        }
     break;
 
-  case 71:
-/* Line 1787 of yacc.c  */
-#line 462 "a.y"
+  case 68:
+#line 456 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FPCR;
@@ -2306,9 +2218,8 @@ yyreduce:
        }
     break;
 
-  case 72:
-/* Line 1787 of yacc.c  */
-#line 468 "a.y"
+  case 69:
+#line 462 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_OREG;
@@ -2316,9 +2227,8 @@ yyreduce:
        }
     break;
 
-  case 76:
-/* Line 1787 of yacc.c  */
-#line 479 "a.y"
+  case 73:
+#line 473 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (1)].addr);
                if((yyvsp[(1) - (1)].addr).name != D_EXTERN && (yyvsp[(1) - (1)].addr).name != D_STATIC) {
@@ -2326,9 +2236,8 @@ yyreduce:
        }
     break;
 
-  case 77:
-/* Line 1787 of yacc.c  */
-#line 487 "a.y"
+  case 74:
+#line 481 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_OREG;
@@ -2337,9 +2246,8 @@ yyreduce:
        }
     break;
 
-  case 79:
-/* Line 1787 of yacc.c  */
-#line 497 "a.y"
+  case 76:
+#line 491 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_OREG;
@@ -2348,9 +2256,8 @@ yyreduce:
        }
     break;
 
-  case 81:
-/* Line 1787 of yacc.c  */
-#line 507 "a.y"
+  case 78:
+#line 501 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (4)].addr);
                (yyval.addr).type = D_OREG;
@@ -2358,9 +2265,8 @@ yyreduce:
        }
     break;
 
-  case 86:
-/* Line 1787 of yacc.c  */
-#line 520 "a.y"
+  case 83:
+#line 514 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_CONST;
@@ -2368,9 +2274,8 @@ yyreduce:
        }
     break;
 
-  case 87:
-/* Line 1787 of yacc.c  */
-#line 528 "a.y"
+  case 84:
+#line 522 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_REG;
@@ -2378,9 +2283,8 @@ yyreduce:
        }
     break;
 
-  case 88:
-/* Line 1787 of yacc.c  */
-#line 536 "a.y"
+  case 85:
+#line 530 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_REGREG;
@@ -2389,9 +2293,8 @@ yyreduce:
        }
     break;
 
-  case 89:
-/* Line 1787 of yacc.c  */
-#line 545 "a.y"
+  case 86:
+#line 539 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SHIFT;
@@ -2399,9 +2302,8 @@ yyreduce:
        }
     break;
 
-  case 90:
-/* Line 1787 of yacc.c  */
-#line 551 "a.y"
+  case 87:
+#line 545 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SHIFT;
@@ -2409,9 +2311,8 @@ yyreduce:
        }
     break;
 
-  case 91:
-/* Line 1787 of yacc.c  */
-#line 557 "a.y"
+  case 88:
+#line 551 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SHIFT;
@@ -2419,9 +2320,8 @@ yyreduce:
        }
     break;
 
-  case 92:
-/* Line 1787 of yacc.c  */
-#line 563 "a.y"
+  case 89:
+#line 557 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SHIFT;
@@ -2429,9 +2329,8 @@ yyreduce:
        }
     break;
 
-  case 93:
-/* Line 1787 of yacc.c  */
-#line 571 "a.y"
+  case 90:
+#line 565 "a.y"
     {
                if((yyval.lval) < 0 || (yyval.lval) >= 16)
                        print("register value out of range\n");
@@ -2439,9 +2338,8 @@ yyreduce:
        }
     break;
 
-  case 94:
-/* Line 1787 of yacc.c  */
-#line 577 "a.y"
+  case 91:
+#line 571 "a.y"
     {
                if((yyval.lval) < 0 || (yyval.lval) >= 32)
                        print("shift value out of range\n");
@@ -2449,17 +2347,15 @@ yyreduce:
        }
     break;
 
-  case 96:
-/* Line 1787 of yacc.c  */
-#line 586 "a.y"
+  case 93:
+#line 580 "a.y"
     {
                (yyval.lval) = REGPC;
        }
     break;
 
-  case 97:
-/* Line 1787 of yacc.c  */
-#line 590 "a.y"
+  case 94:
+#line 584 "a.y"
     {
                if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
                        print("register value out of range\n");
@@ -2467,17 +2363,15 @@ yyreduce:
        }
     break;
 
-  case 99:
-/* Line 1787 of yacc.c  */
-#line 599 "a.y"
+  case 96:
+#line 593 "a.y"
     {
                (yyval.lval) = REGSP;
        }
     break;
 
-  case 101:
-/* Line 1787 of yacc.c  */
-#line 606 "a.y"
+  case 98:
+#line 600 "a.y"
     {
                if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
                        print("register value out of range\n");
@@ -2485,9 +2379,8 @@ yyreduce:
        }
     break;
 
-  case 104:
-/* Line 1787 of yacc.c  */
-#line 618 "a.y"
+  case 101:
+#line 612 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FREG;
@@ -2495,9 +2388,8 @@ yyreduce:
        }
     break;
 
-  case 105:
-/* Line 1787 of yacc.c  */
-#line 624 "a.y"
+  case 102:
+#line 618 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FREG;
@@ -2505,9 +2397,8 @@ yyreduce:
        }
     break;
 
-  case 106:
-/* Line 1787 of yacc.c  */
-#line 632 "a.y"
+  case 103:
+#line 626 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_OREG;
@@ -2517,9 +2408,8 @@ yyreduce:
        }
     break;
 
-  case 107:
-/* Line 1787 of yacc.c  */
-#line 640 "a.y"
+  case 104:
+#line 634 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_OREG;
@@ -2529,9 +2419,8 @@ yyreduce:
        }
     break;
 
-  case 108:
-/* Line 1787 of yacc.c  */
-#line 648 "a.y"
+  case 105:
+#line 642 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_OREG;
@@ -2541,182 +2430,151 @@ yyreduce:
        }
     break;
 
-  case 109:
-/* Line 1787 of yacc.c  */
-#line 657 "a.y"
+  case 106:
+#line 651 "a.y"
     {
                (yyval.lval) = 0;
        }
     break;
 
-  case 110:
-/* Line 1787 of yacc.c  */
-#line 661 "a.y"
+  case 107:
+#line 655 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 111:
-/* Line 1787 of yacc.c  */
-#line 665 "a.y"
+  case 108:
+#line 659 "a.y"
     {
                (yyval.lval) = -(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 116:
-/* Line 1787 of yacc.c  */
-#line 677 "a.y"
+  case 113:
+#line 671 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
        }
     break;
 
-  case 117:
-/* Line 1787 of yacc.c  */
-#line 681 "a.y"
+  case 114:
+#line 675 "a.y"
     {
                (yyval.lval) = -(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 118:
-/* Line 1787 of yacc.c  */
-#line 685 "a.y"
+  case 115:
+#line 679 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 119:
-/* Line 1787 of yacc.c  */
-#line 689 "a.y"
+  case 116:
+#line 683 "a.y"
     {
                (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 120:
-/* Line 1787 of yacc.c  */
-#line 693 "a.y"
+  case 117:
+#line 687 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (3)].lval);
        }
     break;
 
-  case 121:
-/* Line 1787 of yacc.c  */
-#line 698 "a.y"
+  case 118:
+#line 692 "a.y"
     {
                (yyval.lval) = 0;
        }
     break;
 
-  case 122:
-/* Line 1787 of yacc.c  */
-#line 702 "a.y"
+  case 119:
+#line 696 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 124:
-/* Line 1787 of yacc.c  */
-#line 709 "a.y"
+  case 121:
+#line 703 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 125:
-/* Line 1787 of yacc.c  */
-#line 713 "a.y"
+  case 122:
+#line 707 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 126:
-/* Line 1787 of yacc.c  */
-#line 717 "a.y"
+  case 123:
+#line 711 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 127:
-/* Line 1787 of yacc.c  */
-#line 721 "a.y"
+  case 124:
+#line 715 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 128:
-/* Line 1787 of yacc.c  */
-#line 725 "a.y"
+  case 125:
+#line 719 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 129:
-/* Line 1787 of yacc.c  */
-#line 729 "a.y"
+  case 126:
+#line 723 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 130:
-/* Line 1787 of yacc.c  */
-#line 733 "a.y"
+  case 127:
+#line 727 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 131:
-/* Line 1787 of yacc.c  */
-#line 737 "a.y"
+  case 128:
+#line 731 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 132:
-/* Line 1787 of yacc.c  */
-#line 741 "a.y"
+  case 129:
+#line 735 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 133:
-/* Line 1787 of yacc.c  */
-#line 745 "a.y"
+  case 130:
+#line 739 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
        }
     break;
 
 
-/* Line 1787 of yacc.c  */
-#line 2707 "y.tab.c"
+/* Line 1267 of yacc.c.  */
+#line 2576 "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);
@@ -2725,6 +2583,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.  */
@@ -2744,10 +2603,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)
     {
@@ -2755,36 +2610,37 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (YY_("syntax error"));
 #else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
       {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
+       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+         {
+           YYSIZE_T yyalloc = 2 * yysize;
+           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+             yyalloc = YYSTACK_ALLOC_MAXIMUM;
+           if (yymsg != yymsgbuf)
+             YYSTACK_FREE (yymsg);
+           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+           if (yymsg)
+             yymsg_alloc = yyalloc;
+           else
+             {
+               yymsg = yymsgbuf;
+               yymsg_alloc = sizeof yymsgbuf;
+             }
+         }
+
+       if (0 < yysize && yysize <= yymsg_alloc)
+         {
+           (void) yysyntax_error (yymsg, yystate, yychar);
+           yyerror (yymsg);
+         }
+       else
+         {
+           yyerror (YY_("syntax error"));
+           if (yysize != 0)
+             goto yyexhaustedlab;
+         }
       }
-# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -2792,7 +2648,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)
@@ -2809,7 +2665,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;
 
@@ -2843,7 +2699,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)
@@ -2866,9 +2722,10 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
   *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -2892,7 +2749,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined yyoverflow || YYERROR_VERBOSE
+#ifndef yyoverflow
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2903,14 +2760,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);
@@ -2934,3 +2786,4 @@ yyreturn:
 }
 
 
+
index f11fb85c6a47ef83b2e40c06b165f96772d383cc..f75cb22a752b821354419b6f5811d1611dbed157 100644 (file)
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996.  */
+/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-   
-   This program is free software: you can redistribute it and/or modify
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -148,41 +141,24 @@ extern int yydebug;
 
 
 
+
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-{
-/* Line 2053 of yacc.c  */
 #line 39 "a.y"
-
+{
        Sym     *sym;
        int32   lval;
        double  dval;
        char    sval[8];
        Addr    addr;
-
-
-/* Line 2053 of yacc.c  */
-#line 166 "y.tab.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
+}
+/* Line 1529 of yacc.c.  */
+#line 157 "y.tab.h"
+       YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 extern YYSTYPE yylval;
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_Y_TAB_H_INCLUDED  */
diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c
deleted file mode 100644 (file)
index 5a049ae..0000000
+++ /dev/null
@@ -1,1213 +0,0 @@
-// Inferno utils/5c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/cgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-void
-_cgen(Node *n, Node *nn, int inrel)
-{
-       Node *l, *r;
-       Prog *p1;
-       Node nod, nod1, nod2, nod3, nod4;
-       int o, t;
-       int32 v, curs;
-
-       if(debug['g']) {
-               prtree(nn, "cgen lhs");
-               prtree(n, "cgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
-               sugen(n, nn, n->type->width);
-               return;
-       }
-       l = n->left;
-       r = n->right;
-       o = n->op;
-       if(n->addable >= INDEXED) {
-               if(nn == Z) {
-                       switch(o) {
-                       default:
-                               nullwarn(Z, Z);
-                               break;
-                       case OINDEX:
-                               nullwarn(l, r);
-                               break;
-                       }
-                       return;
-               }
-               gmove(n, nn);
-               return;
-       }
-       curs = cursafe;
-
-       if(n->complex >= FNX)
-       if(l->complex >= FNX)
-       if(r != Z && r->complex >= FNX)
-       switch(o) {
-       default:
-               regret(&nod, r, 0, 0);
-               cgen(r, &nod);
-
-               regsalloc(&nod1, r);
-               gopcode(OAS, &nod, Z, &nod1);
-
-               regfree(&nod);
-               nod = *n;
-               nod.right = &nod1;
-               cgen(&nod, nn);
-               return;
-
-       case OFUNC:
-       case OCOMMA:
-       case OANDAND:
-       case OOROR:
-       case OCOND:
-       case ODOT:
-               break;
-       }
-
-       switch(o) {
-       default:
-               diag(n, "unknown op in cgen: %O", o);
-               break;
-
-       case OAS:
-               if(l->op == OBIT)
-                       goto bitas;
-               if(l->addable >= INDEXED && l->complex < FNX) {
-                       if(nn != Z || r->addable < INDEXED) {
-                               if(r->complex >= FNX && nn == Z)
-                                       regret(&nod, r, 0, 0);
-                               else
-                                       regalloc(&nod, r, nn);
-                               cgen(r, &nod);
-                               gmove(&nod, l);
-                               if(nn != Z)
-                                       gmove(&nod, nn);
-                               regfree(&nod);
-                       } else
-                               gmove(r, l);
-                       break;
-               }
-               if(l->complex >= r->complex) {
-                       reglcgen(&nod1, l, Z);
-                       if(r->addable >= INDEXED) {
-                               gmove(r, &nod1);
-                               if(nn != Z)
-                                       gmove(r, nn);
-                               regfree(&nod1);
-                               break;
-                       }
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-                       reglcgen(&nod1, l, Z);
-               }
-               gmove(&nod, &nod1);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       bitas:
-               n = l->left;
-               regalloc(&nod, r, nn);
-               if(l->complex >= r->complex) {
-                       reglcgen(&nod1, n, Z);
-                       cgen(r, &nod);
-               } else {
-                       cgen(r, &nod);
-                       reglcgen(&nod1, n, Z);
-               }
-               regalloc(&nod2, n, Z);
-               gopcode(OAS, &nod1, Z, &nod2);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OBIT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               bitload(n, &nod, Z, Z, nn);
-               gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               break;
-
-       case ODIV:
-       case OMOD:
-               if(nn != Z)
-               if((t = vlog(r)) >= 0) {
-                       /* signed div/mod by constant power of 2 */
-                       cgen(l, nn);
-                       gopcode(OGE, nodconst(0), nn, Z);
-                       p1 = p;
-                       if(o == ODIV) {
-                               gopcode(OADD, nodconst((1<<t)-1), Z, nn);
-                               patch(p1, pc);
-                               gopcode(OASHR, nodconst(t), Z, nn);
-                       } else {
-                               gopcode(OSUB, nn, nodconst(0), nn);
-                               gopcode(OAND, nodconst((1<<t)-1), Z, nn);
-                               gopcode(OSUB, nn, nodconst(0), nn);
-                               gbranch(OGOTO);
-                               patch(p1, pc);
-                               p1 = p;
-                               gopcode(OAND, nodconst((1<<t)-1), Z, nn);
-                               patch(p1, pc);
-                       }
-                       break;
-               }
-               goto muldiv;
-
-       case OSUB:
-               if(nn != Z)
-               if(l->op == OCONST)
-               if(!typefd[n->type->etype]) {
-                       cgen(r, nn);
-                       gopcode(o, Z, l, nn);
-                       break;
-               }
-       case OADD:
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-               /*
-                * immediate operands
-                */
-               if(nn != Z)
-               if(r->op == OCONST)
-               if(!typefd[n->type->etype]) {
-                       cgen(l, nn);
-                       if(r->vconst == 0)
-                       if(o != OAND)
-                               break;
-                       if(nn != Z)
-                               gopcode(o, r, Z, nn);
-                       break;
-               }
-
-       case OLMUL:
-       case OLDIV:
-       case OLMOD:
-       case OMUL:
-       muldiv:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(o == OMUL || o == OLMUL) {
-                       if(mulcon(n, nn))
-                               break;
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       regalloc(&nod1, r, Z);
-                       cgen(r, &nod1);
-                       gopcode(o, &nod1, Z, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-                       regalloc(&nod1, l, Z);
-                       cgen(l, &nod1);
-                       gopcode(o, &nod, &nod1, &nod);
-               }
-               gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OASLSHR:
-       case OASASHL:
-       case OASASHR:
-       case OASAND:
-       case OASADD:
-       case OASSUB:
-       case OASXOR:
-       case OASOR:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(r->op == OCONST)
-               if(!typefd[r->type->etype])
-               if(!typefd[n->type->etype]) {
-                       if(l->addable < INDEXED)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       regalloc(&nod, r, nn);
-                       gopcode(OAS, &nod2, Z, &nod);
-                       gopcode(o, r, Z, &nod);
-                       gopcode(OAS, &nod, Z, &nod2);
-
-                       regfree(&nod);
-                       if(l->addable < INDEXED)
-                               regfree(&nod2);
-                       break;
-               }
-
-       case OASLMUL:
-       case OASLDIV:
-       case OASLMOD:
-       case OASMUL:
-       case OASDIV:
-       case OASMOD:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(l->complex >= r->complex) {
-                       if(l->addable < INDEXED)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       regalloc(&nod1, r, Z);
-                       cgen(r, &nod1);
-               } else {
-                       regalloc(&nod1, r, Z);
-                       cgen(r, &nod1);
-                       if(l->addable < INDEXED)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-               }
-
-               regalloc(&nod, n, nn);
-               gmove(&nod2, &nod);
-               gopcode(o, &nod1, Z, &nod);
-               gmove(&nod, &nod2);
-               if(nn != Z)
-                       gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               if(l->addable < INDEXED)
-                       regfree(&nod2);
-               break;
-
-       asbitop:
-               regalloc(&nod4, n, nn);
-               if(l->complex >= r->complex) {
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-               } else {
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-               }
-               gmove(&nod, &nod4);
-               gopcode(o, &nod3, Z, &nod4);
-               regfree(&nod3);
-               gmove(&nod4, &nod);
-               regfree(&nod4);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OADDR:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               lcgen(l, nn);
-               break;
-
-       case OFUNC:
-               if(l->complex >= FNX) {
-                       if(l->op != OIND)
-                               diag(n, "bad function call");
-
-                       regret(&nod, l->left, 0, 0);
-                       cgen(l->left, &nod);
-                       regsalloc(&nod1, l->left);
-                       gopcode(OAS, &nod, Z, &nod1);
-                       regfree(&nod);
-
-                       nod = *n;
-                       nod.left = &nod2;
-                       nod2 = *l;
-                       nod2.left = &nod1;
-                       nod2.complex = 1;
-                       cgen(&nod, nn);
-
-                       return;
-               }
-               if(REGARG >= 0)
-                       o = reg[REGARG];
-               gargs(r, &nod, &nod1);
-               if(l->addable < INDEXED) {
-                       reglcgen(&nod, l, Z);
-                       gopcode(OFUNC, Z, Z, &nod);
-                       regfree(&nod);
-               } else
-                       gopcode(OFUNC, Z, Z, l);
-               if(REGARG >= 0)
-                       if(o != reg[REGARG])
-                               reg[REGARG]--;
-               regret(&nod, n, l->type, 1);
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(nod.op == OREGISTER)
-                       regfree(&nod);
-               break;
-
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               regialloc(&nod, n, nn);
-               r = l;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       cgen(l, &nod);
-                       nod.xoffset += v;
-                       r->vconst = v;
-               } else
-                       cgen(l, &nod);
-               regind(&nod, n);
-               gopcode(OAS, &nod, Z, nn);
-               regfree(&nod);
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHI:
-       case OHS:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OANDAND:
-       case OOROR:
-               boolgen(n, 1, nn);
-               if(nn == Z)
-                       patch(p, pc);
-               break;
-
-       case ONOT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OCOMMA:
-               cgen(l, Z);
-               cgen(r, nn);
-               break;
-
-       case OCAST:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               /*
-                * convert from types l->n->nn
-                */
-               if(nocast(l->type, n->type)) {
-                       if(nocast(n->type, nn->type)) {
-                               cgen(l, nn);
-                               break;
-                       }
-               }
-               regalloc(&nod, l, nn);
-               cgen(l, &nod);
-               regalloc(&nod1, n, &nod);
-               if(inrel)
-                       gmover(&nod, &nod1);
-               else
-                       gopcode(OAS, &nod, Z, &nod1);
-               gopcode(OAS, &nod1, Z, nn);
-               regfree(&nod1);
-               regfree(&nod);
-               break;
-
-       case ODOT:
-               sugen(l, nodrat, l->type->width);
-               if(nn != Z) {
-                       warn(n, "non-interruptable temporary");
-                       nod = *nodrat;
-                       if(!r || r->op != OCONST) {
-                               diag(n, "DOT and no offset");
-                               break;
-                       }
-                       nod.xoffset += (int32)r->vconst;
-                       nod.type = n->type;
-                       cgen(&nod, nn);
-               }
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               cgen(r->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               cgen(r->right, nn);
-               patch(p1, pc);
-               break;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPOSTDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-               if(nn == Z)
-                       goto pre;
-
-               if(l->addable < INDEXED)
-                       reglcgen(&nod2, l, Z);
-               else
-                       nod2 = *l;
-
-               regalloc(&nod, l, nn);
-               gopcode(OAS, &nod2, Z, &nod);
-               regalloc(&nod1, l, Z);
-               if(typefd[l->type->etype]) {
-                       regalloc(&nod3, l, Z);
-                       if(v < 0) {
-                               gopcode(OAS, nodfconst(-v), Z, &nod3);
-                               gopcode(OSUB, &nod3, &nod, &nod1);
-                       } else {
-                               gopcode(OAS, nodfconst(v), Z, &nod3);
-                               gopcode(OADD, &nod3, &nod, &nod1);
-                       }
-                       regfree(&nod3);
-               } else
-                       gopcode(OADD, nodconst(v), &nod, &nod1);
-               gopcode(OAS, &nod1, Z, &nod2);
-
-               regfree(&nod);
-               regfree(&nod1);
-               if(l->addable < INDEXED)
-                       regfree(&nod2);
-               break;
-
-       case OPREINC:
-       case OPREDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPREDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-
-       pre:
-               if(l->addable < INDEXED)
-                       reglcgen(&nod2, l, Z);
-               else
-                       nod2 = *l;
-
-               regalloc(&nod, l, nn);
-               gopcode(OAS, &nod2, Z, &nod);
-               if(typefd[l->type->etype]) {
-                       regalloc(&nod3, l, Z);
-                       if(v < 0) {
-                               gopcode(OAS, nodfconst(-v), Z, &nod3);
-                               gopcode(OSUB, &nod3, Z, &nod);
-                       } else {
-                               gopcode(OAS, nodfconst(v), Z, &nod3);
-                               gopcode(OADD, &nod3, Z, &nod);
-                       }
-                       regfree(&nod3);
-               } else
-                       gopcode(OADD, nodconst(v), Z, &nod);
-               gopcode(OAS, &nod, Z, &nod2);
-
-               regfree(&nod);
-               if(l->addable < INDEXED)
-                       regfree(&nod2);
-               break;
-
-       bitinc:
-               if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
-                       bitload(l, &nod, &nod1, &nod2, Z);
-                       gopcode(OAS, &nod, Z, nn);
-                       gopcode(OADD, nodconst(v), Z, &nod);
-                       bitstore(l, &nod, &nod1, &nod2, Z);
-                       break;
-               }
-               bitload(l, &nod, &nod1, &nod2, nn);
-               gopcode(OADD, nodconst(v), Z, &nod);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-       }
-       cursafe = curs;
-       return;
-}
-
-void
-cgen(Node *n, Node *nn)
-{
-       _cgen(n, nn, 0);
-}
-
-void
-cgenrel(Node *n, Node *nn)
-{
-       _cgen(n, nn, 1);
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
-       Node *r;
-       int32 v;
-
-       regialloc(t, n, nn);
-       if(n->op == OIND) {
-               r = n->left;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       lcgen(n, t);
-                       t->xoffset += v;
-                       r->vconst = v;
-                       regind(t, n);
-                       return;
-               }
-       } else if(n->op == OINDREG) {
-               if((v = n->xoffset) > -4096 && v < 4096) {
-                       n->op = OREGISTER;
-                       cgen(n, t);
-                       t->xoffset += v;
-                       n->op = OINDREG;
-                       regind(t, n);
-                       return;
-               }
-       }
-       lcgen(n, t);
-       regind(t, n);
-}
-
-void
-reglpcgen(Node *n, Node *nn, int f)
-{
-       Type *t;
-
-       t = nn->type;
-       nn->type = types[TLONG];
-       if(f)
-               reglcgen(n, nn, Z);
-       else {
-               regialloc(n, nn, Z);
-               lcgen(nn, n);
-               regind(n, nn);
-       }
-       nn->type = t;
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
-       Prog *p1;
-       Node nod;
-
-       if(debug['g']) {
-               prtree(nn, "lcgen lhs");
-               prtree(n, "lcgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(nn == Z) {
-               nn = &nod;
-               regalloc(&nod, n, Z);
-       }
-       switch(n->op) {
-       default:
-               if(n->addable < INDEXED) {
-                       diag(n, "unknown op in lcgen: %O", n->op);
-                       break;
-               }
-               nod = *n;
-               nod.op = OADDR;
-               nod.left = n;
-               nod.right = Z;
-               nod.type = types[TIND];
-               gopcode(OAS, &nod, Z, nn);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, n->left);
-               lcgen(n->right, nn);
-               break;
-
-       case OIND:
-               cgen(n->left, nn);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               lcgen(n->right->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               lcgen(n->right->right, nn);
-               patch(p1, pc);
-               break;
-       }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
-       if(n->type == T)
-               gbranch(OGOTO);
-       else
-               boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
-       int o;
-       Prog *p1, *p2;
-       Node *l, *r, nod, nod1;
-       int32 curs;
-
-       if(debug['g']) {
-               prtree(nn, "boolgen lhs");
-               prtree(n, "boolgen");
-       }
-       curs = cursafe;
-       l = n->left;
-       r = n->right;
-       switch(n->op) {
-
-       default:
-               regalloc(&nod, n, nn);
-               cgen(n, &nod);
-               o = ONE;
-               if(true)
-                       o = comrel[relindex(o)];
-               if(typefd[n->type->etype]) {
-                       gopcode(o, nodfconst(0), &nod, Z);
-               } else
-                       gopcode(o, nodconst(0), &nod, Z);
-               regfree(&nod);
-               goto com;
-
-       case OCONST:
-               o = vconst(n);
-               if(!true)
-                       o = !o;
-               gbranch(OGOTO);
-               if(o) {
-                       p1 = p;
-                       gbranch(OGOTO);
-                       patch(p1, pc);
-               }
-               goto com;
-
-       case OCOMMA:
-               cgen(l, Z);
-               boolgen(r, true, nn);
-               break;
-
-       case ONOT:
-               boolgen(l, !true, nn);
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               bcgen(r->left, true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               bcgen(r->right, !true);
-               patch(p2, pc);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               bcgen(l, true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               patch(p1, pc);
-               gbranch(OGOTO);
-               patch(p2, pc);
-               goto com;
-
-       case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bcgen(l, !true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               o = n->op;
-               if(true)
-                       o = comrel[relindex(o)];
-               if(l->complex >= FNX && r->complex >= FNX) {
-                       regret(&nod, r, 0, 0);
-                       cgenrel(r, &nod);
-                       regsalloc(&nod1, r);
-                       gopcode(OAS, &nod, Z, &nod1);
-                       regfree(&nod);
-                       nod = *n;
-                       nod.right = &nod1;
-                       boolgen(&nod, true, nn);
-                       break;
-               }
-               if(sconst(l)) {
-                       regalloc(&nod, r, nn);
-                       cgenrel(r, &nod);
-                       o = invrel[relindex(o)];
-                       gopcode(o, l, &nod, Z);
-                       regfree(&nod);
-                       goto com;
-               }
-               if(sconst(r)) {
-                       regalloc(&nod, l, nn);
-                       cgenrel(l, &nod);
-                       gopcode(o, r, &nod, Z);
-                       regfree(&nod);
-                       goto com;
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod1, l, nn);
-                       cgenrel(l, &nod1);
-                       regalloc(&nod, r, Z);
-                       cgenrel(r, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgenrel(r, &nod);
-                       regalloc(&nod1, l, Z);
-                       cgenrel(l, &nod1);
-               }
-               gopcode(o, &nod, &nod1, Z);
-               regfree(&nod);
-               regfree(&nod1);
-
-       com:
-               if(nn != Z) {
-                       p1 = p;
-                       gopcode(OAS, nodconst(1), Z, nn);
-                       gbranch(OGOTO);
-                       p2 = p;
-                       patch(p1, pc);
-                       gopcode(OAS, nodconst(0), Z, nn);
-                       patch(p2, pc);
-               }
-               break;
-       }
-       cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
-       Prog *p1;
-       Node nod0, nod1, nod2, nod3, nod4, *l, *r;
-       Type *t;
-       int32 pc1;
-       int i, m, c;
-
-       if(n == Z || n->type == T)
-               return;
-       if(debug['g']) {
-               prtree(nn, "sugen lhs");
-               prtree(n, "sugen");
-       }
-       if(nn == nodrat)
-               if(w > nrathole)
-                       nrathole = w;
-       switch(n->op) {
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(n->left, Z);
-                       break;
-               }
-
-       default:
-               goto copy;
-
-       case OCONST:
-               if(n->type && typev[n->type->etype]) {
-                       if(nn == Z) {
-                               nullwarn(n->left, Z);
-                               break;
-                       }
-
-                       t = nn->type;
-                       nn->type = types[TLONG];
-                       reglcgen(&nod1, nn, Z);
-                       nn->type = t;
-
-                       if(isbigendian)
-                               gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
-                       else
-                               gopcode(OAS, nod32const(n->vconst), Z, &nod1);
-                       nod1.xoffset += SZ_LONG;
-                       if(isbigendian)
-                               gopcode(OAS, nod32const(n->vconst), Z, &nod1);
-                       else
-                               gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
-
-                       regfree(&nod1);
-                       break;
-               }
-               goto copy;
-
-       case ODOT:
-               l = n->left;
-               sugen(l, nodrat, l->type->width);
-               if(nn != Z) {
-                       warn(n, "non-interruptable temporary");
-                       nod1 = *nodrat;
-                       r = n->right;
-                       if(!r || r->op != OCONST) {
-                               diag(n, "DOT and no offset");
-                               break;
-                       }
-                       nod1.xoffset += (int32)r->vconst;
-                       nod1.type = n->type;
-                       sugen(&nod1, nn, w);
-               }
-               break;
-
-       case OSTRUCT:
-               /*
-                * rewrite so lhs has no side effect.
-                */
-               if(nn != Z && side(nn)) {
-                       nod1 = *n;
-                       nod1.type = typ(TIND, n->type);
-                       regret(&nod2, &nod1, 0, 0);
-                       lcgen(nn, &nod2);
-                       regsalloc(&nod0, &nod1);
-                       gopcode(OAS, &nod2, Z, &nod0);
-                       regfree(&nod2);
-
-                       nod1 = *n;
-                       nod1.op = OIND;
-                       nod1.left = &nod0;
-                       nod1.right = Z;
-                       nod1.complex = 1;
-
-                       sugen(n, &nod1, w);
-                       return;
-               }
-
-               r = n->left;
-               for(t = n->type->link; t != T; t = t->down) {
-                       l = r;
-                       if(r->op == OLIST) {
-                               l = r->left;
-                               r = r->right;
-                       }
-                       if(nn == Z) {
-                               cgen(l, nn);
-                               continue;
-                       }
-                       /*
-                        * hand craft *(&nn + o) = l
-                        */
-                       nod0 = znode;
-                       nod0.op = OAS;
-                       nod0.type = t;
-                       nod0.left = &nod1;
-                       nod0.right = l;
-
-                       nod1 = znode;
-                       nod1.op = OIND;
-                       nod1.type = t;
-                       nod1.left = &nod2;
-
-                       nod2 = znode;
-                       nod2.op = OADD;
-                       nod2.type = typ(TIND, t);
-                       nod2.left = &nod3;
-                       nod2.right = &nod4;
-
-                       nod3 = znode;
-                       nod3.op = OADDR;
-                       nod3.type = nod2.type;
-                       nod3.left = nn;
-
-                       nod4 = znode;
-                       nod4.op = OCONST;
-                       nod4.type = nod2.type;
-                       nod4.vconst = t->offset;
-
-                       ccom(&nod0);
-                       acom(&nod0);
-                       xcom(&nod0);
-                       nod0.addable = 0;
-
-                       cgen(&nod0, Z);
-               }
-               break;
-
-       case OAS:
-               if(nn == Z) {
-                       if(n->addable < INDEXED)
-                               sugen(n->right, n->left, w);
-                       break;
-               }
-               sugen(n->right, nodrat, w);
-               warn(n, "non-interruptable temporary");
-               sugen(nodrat, n->left, w);
-               sugen(nodrat, nn, w);
-               break;
-
-       case OFUNC:
-               if(!hasdotdotdot(n->left->type)) {
-                       cgen(n, Z);
-                       if(nn != Z) {
-                               curarg -= n->type->width;
-                               regret(&nod1, n, n->left->type, 1);
-                               if(nn->complex >= FNX) {
-                                       regsalloc(&nod2, n);
-                                       cgen(&nod1, &nod2);
-                                       nod1 = nod2;
-                               }
-                               cgen(&nod1, nn);
-                       }
-                       break;
-               }
-               if(nn == Z) {
-                       sugen(n, nodrat, w);
-                       break;
-               }
-               if(nn->op != OIND) {
-                       nn = new1(OADDR, nn, Z);
-                       nn->type = types[TIND];
-                       nn->addable = 0;
-               } else
-                       nn = nn->left;
-               n = new(OFUNC, n->left, new(OLIST, nn, n->right));
-               n->type = types[TVOID];
-               n->left->type = types[TVOID];
-               cgen(n, Z);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               sugen(n->right->left, nn, w);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               sugen(n->right->right, nn, w);
-               patch(p1, pc);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, Z);
-               sugen(n->right, nn, w);
-               break;
-       }
-       return;
-
-copy:
-       if(nn == Z)
-               return;
-       if(n->complex >= FNX && nn->complex >= FNX) {
-               t = nn->type;
-               nn->type = types[TLONG];
-               regialloc(&nod1, nn, Z);
-               lcgen(nn, &nod1);
-               regsalloc(&nod2, nn);
-               nn->type = t;
-
-               gopcode(OAS, &nod1, Z, &nod2);
-               regfree(&nod1);
-
-               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);
-               return;
-       }
-
-       w /= SZ_LONG;
-       if(w <= 2) {
-               if(n->complex > nn->complex) {
-                       reglpcgen(&nod1, n, 1);
-                       reglpcgen(&nod2, nn, 1);
-               } else {
-                       reglpcgen(&nod2, nn, 1);
-                       reglpcgen(&nod1, n, 1);
-               }
-               regalloc(&nod3, &regnode, Z);
-               regalloc(&nod4, &regnode, Z);
-               nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
-               if(w == 2 && nod1.xoffset == 0)
-                       gmovm(&nod1, &nod0, 0);
-               else {
-                       gmove(&nod1, &nod3);
-                       if(w == 2) {
-                               nod1.xoffset += SZ_LONG;
-                               gmove(&nod1, &nod4);
-                       }
-               }
-               if(w == 2 && nod2.xoffset == 0)
-                       gmovm(&nod0, &nod2, 0);
-               else {
-                       gmove(&nod3, &nod2);
-                       if(w == 2) {
-                               nod2.xoffset += SZ_LONG;
-                               gmove(&nod4, &nod2);
-                       }
-               }
-               regfree(&nod1);
-               regfree(&nod2);
-               regfree(&nod3);
-               regfree(&nod4);
-               return;
-       }
-
-       if(n->complex > nn->complex) {
-               reglpcgen(&nod1, n, 0);
-               reglpcgen(&nod2, nn, 0);
-       } else {
-               reglpcgen(&nod2, nn, 0);
-               reglpcgen(&nod1, n, 0);
-       }
-
-       m = 0;
-       for(c = 0; c < w && c < 4; c++) {
-               i = tmpreg();
-               if (i == 0)
-                       break;
-               reg[i]++;
-               m |= 1<<i;
-       }
-       nod4 = *(nodconst(m));
-       if(w < 3*c) {
-               for (; w>c; w-=c) {
-                       gmovm(&nod1, &nod4, 1);
-                       gmovm(&nod4, &nod2, 1);
-               }
-               goto out;
-       }
-
-       regalloc(&nod3, &regnode, Z);
-       gopcode(OAS, nodconst(w/c), Z, &nod3);
-       w %= c;
-
-       pc1 = pc;
-       gmovm(&nod1, &nod4, 1);
-       gmovm(&nod4, &nod2, 1);
-
-       gopcode(OSUB, nodconst(1), Z, &nod3);
-       gopcode(OEQ, nodconst(0), &nod3, Z);
-       p->as = ABGT;
-       patch(p, pc1);
-       regfree(&nod3);
-
-out:
-       if (w) {
-               i = 0;
-               while (c>w) {
-                       while ((m&(1<<i)) == 0)
-                               i++;
-                       m &= ~(1<<i);
-                       reg[i] = 0;
-                       c--;
-                       i++;
-               }
-               nod4.vconst = m;
-               gmovm(&nod1, &nod4, 0);
-               gmovm(&nod4, &nod2, 0);
-       }
-       i = 0;
-       do {
-               while ((m&(1<<i)) == 0)
-                       i++;
-               reg[i] = 0;
-               c--;
-               i++;
-       } while (c>0);
-       regfree(&nod1);
-       regfree(&nod2);
-}
diff --git a/src/cmd/5c/doc.go b/src/cmd/5c/doc.go
deleted file mode 100644 (file)
index 7291d45..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +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/8c
-
-Its target architecture is the ARM, referred to by these tools as arm.
-
-*/
-package main
diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h
deleted file mode 100644 (file)
index 7417b7d..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-// Inferno utils/5c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/gc.h
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "../cc/cc.h"
-#include       "../5l/5.out.h"
-
-/*
- * 5c/arm
- * Arm 7500
- */
-#define        SZ_CHAR         1
-#define        SZ_SHORT        2
-#define        SZ_INT          4
-#define        SZ_LONG         4
-#define        SZ_IND          4
-#define        SZ_FLOAT        4
-#define        SZ_VLONG        8
-#define        SZ_DOUBLE       8
-#define        FNX             100
-
-typedef        struct  Case    Case;
-typedef        struct  C1      C1;
-typedef        struct  Multab  Multab;
-typedef        struct  Hintab  Hintab;
-typedef        struct  Reg     Reg;
-typedef        struct  Rgn     Rgn;
-
-
-#define        R0ISZERO        0
-
-#define        A       ((Addr*)0)
-
-#define        INDEXED 9
-#define        P       ((Prog*)0)
-
-struct Case
-{
-       Case*   link;
-       int32   val;
-       int32   label;
-       char    def;
-       char    isv;
-};
-#define        C       ((Case*)0)
-
-struct C1
-{
-       int32   val;
-       int32   label;
-};
-
-struct Multab
-{
-       int32   val;
-       char    code[20];
-};
-
-struct Hintab
-{
-       ushort  val;
-       char    hint[10];
-};
-
-struct Reg
-{
-       int32   pc;
-       int32   rpo;            /* reverse post ordering */
-
-       Bits    set;
-       Bits    use1;
-       Bits    use2;
-
-       Bits    refbehind;
-       Bits    refahead;
-       Bits    calbehind;
-       Bits    calahead;
-       Bits    regdiff;
-       Bits    act;
-
-       int32   regu;
-       int32   loop;           /* could be shorter */
-
-
-       Reg*    log5;
-       int32   active;
-
-       Reg*    p1;
-       Reg*    p2;
-       Reg*    p2link;
-       Reg*    s1;
-       Reg*    s2;
-       Reg*    link;
-       Prog*   prog;
-};
-#define        R       ((Reg*)0)
-
-#define        NRGN    600
-struct Rgn
-{
-       Reg*    enter;
-       short   cost;
-       short   varno;
-       short   regno;
-};
-
-EXTERN int32   breakpc;
-EXTERN int32   nbreak;
-EXTERN Case*   cases;
-EXTERN Node    constnode;
-EXTERN Node    fconstnode;
-EXTERN int32   continpc;
-EXTERN int32   curarg;
-EXTERN int32   cursafe;
-EXTERN int32   isbigendian;
-EXTERN Prog*   lastp;
-EXTERN int32   maxargsafe;
-EXTERN int     mnstring;
-EXTERN Multab  multab[20];
-extern int     hintabsize;
-EXTERN Node*   nodrat;
-EXTERN Node*   nodret;
-EXTERN Node*   nodsafe;
-EXTERN int32   nrathole;
-EXTERN int32   nstring;
-EXTERN Prog*   p;
-EXTERN int32   pc;
-EXTERN Node    regnode;
-EXTERN char    string[NSNAME];
-EXTERN Sym*    symrathole;
-EXTERN Node    znode;
-EXTERN Prog    zprog;
-EXTERN char    reg[NREG+NFREG];
-EXTERN int32   exregoffset;
-EXTERN int32   exfregoffset;
-EXTERN int     suppress;
-
-#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])
-#define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define        bset(a,n)       ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define        CLOAD   4
-#define        CREF    5
-#define        CINF    1000
-#define        LOOP    3
-
-EXTERN Rgn     region[NRGN];
-EXTERN Rgn*    rgp;
-EXTERN int     nregion;
-EXTERN int     nvar;
-
-EXTERN Bits    externs;
-EXTERN Bits    params;
-EXTERN Bits    consts;
-EXTERN Bits    addrs;
-
-EXTERN int32   regbits;
-EXTERN int32   exregbits;
-
-EXTERN int     change;
-
-EXTERN Reg*    firstr;
-EXTERN Reg*    lastr;
-EXTERN Reg     zreg;
-EXTERN Reg*    freer;
-EXTERN int32*  idom;
-EXTERN Reg**   rpo2r;
-EXTERN int32   maxnr;
-
-extern char*   anames[];
-extern Hintab  hintab[];
-
-/*
- * sgen.c
- */
-void   codgen(Node*, Node*);
-void   gen(Node*);
-void   noretval(int);
-void   usedset(Node*, int);
-void   xcom(Node*);
-int    bcomplex(Node*, Node*);
-Prog*  gtext(Sym*, int32);
-vlong  argsize(int);
-
-/*
- * cgen.c
- */
-void   cgen(Node*, Node*);
-void   reglcgen(Node*, Node*, Node*);
-void   lcgen(Node*, Node*);
-void   bcgen(Node*, int);
-void   boolgen(Node*, int, Node*);
-void   sugen(Node*, Node*, int32);
-void   layout(Node*, Node*, int, int, Node*);
-void   cgenrel(Node*, Node*);
-
-/*
- * txt.c
- */
-void   ginit(void);
-void   gclean(void);
-void   nextpc(void);
-void   gargs(Node*, Node*, Node*);
-void   garg1(Node*, Node*, Node*, int, Node**);
-Node*  nodconst(int32);
-Node*  nod32const(vlong);
-Node*  nodfconst(double);
-void   nodreg(Node*, Node*, int);
-void   regret(Node*, Node*, Type*, int);
-int    tmpreg(void);
-void   regalloc(Node*, Node*, Node*);
-void   regfree(Node*);
-void   regialloc(Node*, Node*, Node*);
-void   regsalloc(Node*, Node*);
-void   regaalloc1(Node*, Node*);
-void   regaalloc(Node*, Node*);
-void   regind(Node*, Node*);
-void   gprep(Node*, Node*);
-void   raddr(Node*, Prog*);
-void   naddr(Node*, Addr*);
-void   gmovm(Node*, Node*, int);
-void   gmove(Node*, Node*);
-void   gmover(Node*, Node*);
-void   gins(int a, Node*, Node*);
-void   gopcode(int, Node*, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   gbranch(int);
-void   patch(Prog*, int32);
-int    sconst(Node*);
-int    sval(int32);
-void   gpseudo(int, Sym*, Node*);
-void   gprefetch(Node*);
-void   gpcdata(int, int);
-
-/*
- * swt.c
- */
-int    swcmp(const void*, const void*);
-void   doswit(Node*);
-void   swit1(C1*, int, int32, Node*);
-void   swit2(C1*, int, int32, Node*);
-void   newcase(void);
-void   bitload(Node*, Node*, Node*, Node*, Node*);
-void   bitstore(Node*, Node*, Node*, Node*, Node*);
-int    mulcon(Node*, Node*);
-Multab*        mulcon0(int32);
-void   nullwarn(Node*, Node*);
-void   outcode(void);
-
-/*
- * list
- */
-void   listinit(void);
-
-/*
- * reg.c
- */
-Reg*   rega(void);
-int    rcmp(const void*, const void*);
-void   regopt(Prog*);
-void   addmove(Reg*, int, int, int);
-Bits   mkvar(Addr*, int);
-void   prop(Reg*, Bits, Bits);
-void   loopit(Reg*, int32);
-void   synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
-void   addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void   peep(void);
-void   excise(Reg*);
-Reg*   uniqp(Reg*);
-Reg*   uniqs(Reg*);
-int    regtyp(Addr*);
-int    regzer(Addr*);
-int    anyvar(Addr*);
-int    subprop(Reg*);
-int    copyprop(Reg*);
-int    shiftprop(Reg*);
-void   constprop(Addr*, Addr*, Reg*);
-int    copy1(Addr*, Addr*, Reg*, int);
-int    copyu(Prog*, Addr*, Addr*);
-
-int    copyas(Addr*, Addr*);
-int    copyau(Addr*, Addr*);
-int    copyau1(Prog*, Addr*);
-int    copysub(Addr*, Addr*, Addr*, int);
-int    copysub1(Prog*, Addr*, Addr*, int);
-
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
-
-void   predicate(void);
-int    isbranch(Prog *);
-int    predicable(Prog *p);
-int    modifiescpsr(Prog *p);
diff --git a/src/cmd/5c/mul.c b/src/cmd/5c/mul.c
deleted file mode 100644 (file)
index ff50c48..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-// Inferno utils/5c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/mul.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-/*
- * code sequences for multiply by constant.
- * [a-l][0-3]
- *     lsl     $(A-'a'),r0,r1
- * [+][0-7]
- *     add     r0,r1,r2
- * [-][0-7]
- *     sub     r0,r1,r2
- */
-
-static  int    maxmulops = 3;  /* max # of ops to replace mul with */
-static int     multabp;
-static int32   mulval;
-static char*   mulcp;
-static int32   valmax;
-static int     shmax;
-
-static int     docode(char *hp, char *cp, int r0, int r1);
-static int     gen1(int len);
-static int     gen2(int len, int32 r1);
-static int     gen3(int len, int32 r0, int32 r1, int flag);
-enum
-{
-       SR1     = 1<<0,         /* r1 has been shifted */
-       SR0     = 1<<1,         /* r0 has been shifted */
-       UR1     = 1<<2,         /* r1 has not been used */
-       UR0     = 1<<3,         /* r0 has not been used */
-};
-
-Multab*
-mulcon0(int32 v)
-{
-       int a1, a2, g;
-       Multab *m, *m1;
-       char hint[10];
-
-       if(v < 0)
-               v = -v;
-
-       /*
-        * look in cache
-        */
-       m = multab;
-       for(g=0; g<nelem(multab); g++) {
-               if(m->val == v) {
-                       if(m->code[0] == 0)
-                               return 0;
-                       return m;
-               }
-               m++;
-       }
-
-       /*
-        * select a spot in cache to overwrite
-        */
-       multabp++;
-       if(multabp < 0 || multabp >= nelem(multab))
-               multabp = 0;
-       m = multab+multabp;
-       m->val = v;
-       mulval = v;
-
-       /*
-        * look in execption hint table
-        */
-       a1 = 0;
-       a2 = hintabsize;
-       for(;;) {
-               if(a1 >= a2)
-                       goto no;
-               g = (a2 + a1)/2;
-               if(v < hintab[g].val) {
-                       a2 = g;
-                       continue;
-               }
-               if(v > hintab[g].val) {
-                       a1 = g+1;
-                       continue;
-               }
-               break;
-       }
-
-       if(docode(hintab[g].hint, m->code, 1, 0))
-               return m;
-       print("multiply table failure %d\n", v);
-       m->code[0] = 0;
-       return 0;
-
-no:
-       /*
-        * try to search
-        */
-       hint[0] = 0;
-       for(g=1; g<=maxmulops; g++) {
-               if(g >= maxmulops && v >= 65535)
-                       break;
-               mulcp = hint+g;
-               *mulcp = 0;
-               if(gen1(g)) {
-                       if(docode(hint, m->code, 1, 0))
-                               return m;
-                       print("multiply table failure %d\n", v);
-                       break;
-               }
-       }
-
-       /*
-        * try a recur followed by a shift
-        */
-       g = 0;
-       while(!(v & 1)) {
-               g++;
-               v >>= 1;
-       }
-       if(g) {
-               m1 = mulcon0(v);
-               if(m1) {
-                       strcpy(m->code, m1->code);
-                       sprint(strchr(m->code, 0), "%c0", g+'a');
-                       return m;
-               }
-       }
-       m->code[0] = 0;
-       return 0;
-}
-
-static int
-docode(char *hp, char *cp, int r0, int r1)
-{
-       int c, i;
-
-       c = *hp++;
-       *cp = c;
-       cp += 2;
-       switch(c) {
-       default:
-               c -= 'a';
-               if(c < 1 || c >= 30)
-                       break;
-               for(i=0; i<4; i++) {
-                       switch(i) {
-                       case 0:
-                               if(docode(hp, cp, r0<<c, r1))
-                                       goto out;
-                               break;
-                       case 1:
-                               if(docode(hp, cp, r1<<c, r1))
-                                       goto out;
-                               break;
-                       case 2:
-                               if(docode(hp, cp, r0, r0<<c))
-                                       goto out;
-                               break;
-                       case 3:
-                               if(docode(hp, cp, r0, r1<<c))
-                                       goto out;
-                               break;
-                       }
-               }
-               break;
-
-       case '+':
-               for(i=0; i<8; i++) {
-                       cp[-1] = i+'0';
-                       switch(i) {
-                       case 1:
-                               if(docode(hp, cp, r0+r1, r1))
-                                       goto out;
-                               break;
-                       case 5:
-                               if(docode(hp, cp, r0, r0+r1))
-                                       goto out;
-                               break;
-                       }
-               }
-               break;
-
-       case '-':
-               for(i=0; i<8; i++) {
-                       cp[-1] = i+'0';
-                       switch(i) {
-                       case 1:
-                               if(docode(hp, cp, r0-r1, r1))
-                                       goto out;
-                               break;
-                       case 2:
-                               if(docode(hp, cp, r1-r0, r1))
-                                       goto out;
-                               break;
-                       case 5:
-                               if(docode(hp, cp, r0, r0-r1))
-                                       goto out;
-                               break;
-                       case 6:
-                               if(docode(hp, cp, r0, r1-r0))
-                                       goto out;
-                               break;
-                       }
-               }
-               break;
-
-       case 0:
-               if(r0 == mulval)
-                       return 1;
-       }
-       return 0;
-
-out:
-       cp[-1] = i+'0';
-       return 1;
-}
-
-static int
-gen1(int len)
-{
-       int i;
-
-       for(shmax=1; shmax<30; shmax++) {
-               valmax = 1<<shmax;
-               if(valmax >= mulval)
-                       break;
-       }
-       if(mulval == 1)
-               return 1;
-
-       len--;
-       for(i=1; i<=shmax; i++)
-               if(gen2(len, 1<<i)) {
-                       *--mulcp = 'a'+i;
-                       return 1;
-               }
-       return 0;
-}
-
-static int
-gen2(int len, int32 r1)
-{
-       int i;
-
-       if(len <= 0) {
-               if(r1 == mulval)
-                       return 1;
-               return 0;
-       }
-
-       len--;
-       if(len == 0)
-               goto calcr0;
-
-       if(gen3(len, r1, r1+1, UR1)) {
-               i = '+';
-               goto out;
-       }
-       if(gen3(len, r1-1, r1, UR0)) {
-               i = '-';
-               goto out;
-       }
-       if(gen3(len, 1, r1+1, UR1)) {
-               i = '+';
-               goto out;
-       }
-       if(gen3(len, 1, r1-1, UR1)) {
-               i = '-';
-               goto out;
-       }
-
-       return 0;
-
-calcr0:
-       if(mulval == r1+1) {
-               i = '+';
-               goto out;
-       }
-       if(mulval == r1-1) {
-               i = '-';
-               goto out;
-       }
-       return 0;
-
-out:
-       *--mulcp = i;
-       return 1;
-}
-
-static int
-gen3(int len, int32 r0, int32 r1, int flag)
-{
-       int i, f1, f2;
-       int32 x;
-
-       if(r0 <= 0 ||
-          r0 >= r1 ||
-          r1 > valmax)
-               return 0;
-
-       len--;
-       if(len == 0)
-               goto calcr0;
-
-       if(!(flag & UR1)) {
-               f1 = UR1|SR1;
-               for(i=1; i<=shmax; i++) {
-                       x = r0<<i;
-                       if(x > valmax)
-                               break;
-                       if(gen3(len, r0, x, f1)) {
-                               i += 'a';
-                               goto out;
-                       }
-               }
-       }
-
-       if(!(flag & UR0)) {
-               f1 = UR1|SR1;
-               for(i=1; i<=shmax; i++) {
-                       x = r1<<i;
-                       if(x > valmax)
-                               break;
-                       if(gen3(len, r1, x, f1)) {
-                               i += 'a';
-                               goto out;
-                       }
-               }
-       }
-
-       if(!(flag & SR1)) {
-               f1 = UR1|SR1|(flag&UR0);
-               for(i=1; i<=shmax; i++) {
-                       x = r1<<i;
-                       if(x > valmax)
-                               break;
-                       if(gen3(len, r0, x, f1)) {
-                               i += 'a';
-                               goto out;
-                       }
-               }
-       }
-
-       if(!(flag & SR0)) {
-               f1 = UR0|SR0|(flag&(SR1|UR1));
-
-               f2 = UR1|SR1;
-               if(flag & UR1)
-                       f2 |= UR0;
-               if(flag & SR1)
-                       f2 |= SR0;
-
-               for(i=1; i<=shmax; i++) {
-                       x = r0<<i;
-                       if(x > valmax)
-                               break;
-                       if(x > r1) {
-                               if(gen3(len, r1, x, f2)) {
-                                       i += 'a';
-                                       goto out;
-                               }
-                       } else
-                               if(gen3(len, x, r1, f1)) {
-                                       i += 'a';
-                                       goto out;
-                               }
-               }
-       }
-
-       x = r1+r0;
-       if(gen3(len, r0, x, UR1)) {
-               i = '+';
-               goto out;
-       }
-
-       if(gen3(len, r1, x, UR1)) {
-               i = '+';
-               goto out;
-       }
-
-       x = r1-r0;
-       if(gen3(len, x, r1, UR0)) {
-               i = '-';
-               goto out;
-       }
-
-       if(x > r0) {
-               if(gen3(len, r0, x, UR1)) {
-                       i = '-';
-                       goto out;
-               }
-       } else
-               if(gen3(len, x, r0, UR0)) {
-                       i = '-';
-                       goto out;
-               }
-
-       return 0;
-
-calcr0:
-       f1 = flag & (UR0|UR1);
-       if(f1 == UR1) {
-               for(i=1; i<=shmax; i++) {
-                       x = r1<<i;
-                       if(x >= mulval) {
-                               if(x == mulval) {
-                                       i += 'a';
-                                       goto out;
-                               }
-                               break;
-                       }
-               }
-       }
-
-       if(mulval == r1+r0) {
-               i = '+';
-               goto out;
-       }
-       if(mulval == r1-r0) {
-               i = '-';
-               goto out;
-       }
-
-       return 0;
-
-out:
-       *--mulcp = i;
-       return 1;
-}
-
-/*
- * hint table has numbers that
- * the search algorithm fails on.
- * <1000:
- *     all numbers
- * <5000:
- *     Ã· by 5
- * <10000:
- *     Ã· by 50
- * <65536:
- *     Ã· by 250
- */
-Hintab hintab[] =
-{
-       683,    "b++d+e+",
-       687,    "b+e++e-",
-       691,    "b++d+e+",
-       731,    "b++d+e+",
-       811,    "b++d+i+",
-       821,    "b++e+e+",
-       843,    "b+d++e+",
-       851,    "b+f-+e-",
-       853,    "b++e+e+",
-       877,    "c++++g-",
-       933,    "b+c++g-",
-       981,    "c-+e-d+",
-       1375,   "b+c+b+h-",
-       1675,   "d+b++h+",
-       2425,   "c++f-e+",
-       2675,   "c+d++f-",
-       2750,   "b+d-b+h-",
-       2775,   "c-+g-e-",
-       3125,   "b++e+g+",
-       3275,   "b+c+g+e+",
-       3350,   "c++++i+",
-       3475,   "c-+e-f-",
-       3525,   "c-+d+g-",
-       3625,   "c-+e-j+",
-       3675,   "b+d+d+e+",
-       3725,   "b+d-+h+",
-       3925,   "b+d+f-d-",
-       4275,   "b+g++e+",
-       4325,   "b+h-+d+",
-       4425,   "b+b+g-j-",
-       4525,   "b+d-d+f+",
-       4675,   "c++d-g+",
-       4775,   "b+d+b+g-",
-       4825,   "c+c-+i-",
-       4850,   "c++++i-",
-       4925,   "b++e-g-",
-       4975,   "c+f++e-",
-       5500,   "b+g-c+d+",
-       6700,   "d+b++i+",
-       9700,   "d++++j-",
-       11000,  "b+f-c-h-",
-       11750,  "b+d+g+j-",
-       12500,  "b+c+e-k+",
-       13250,  "b+d+e-f+",
-       13750,  "b+h-c-d+",
-       14250,  "b+g-c+e-",
-       14500,  "c+f+j-d-",
-       14750,  "d-g--f+",
-       16750,  "b+e-d-n+",
-       17750,  "c+h-b+e+",
-       18250,  "d+b+h-d+",
-       18750,  "b+g-++f+",
-       19250,  "b+e+b+h+",
-       19750,  "b++h--f-",
-       20250,  "b+e-l-c+",
-       20750,  "c++bi+e-",
-       21250,  "b+i+l+c+",
-       22000,  "b+e+d-g-",
-       22250,  "b+d-h+k-",
-       22750,  "b+d-e-g+",
-       23250,  "b+c+h+e-",
-       23500,  "b+g-c-g-",
-       23750,  "b+g-b+h-",
-       24250,  "c++g+m-",
-       24750,  "b+e+e+j-",
-       25000,  "b++dh+g+",
-       25250,  "b+e+d-g-",
-       25750,  "b+e+b+j+",
-       26250,  "b+h+c+e+",
-       26500,  "b+h+c+g+",
-       26750,  "b+d+e+g-",
-       27250,  "b+e+e+f+",
-       27500,  "c-i-c-d+",
-       27750,  "b+bd++j+",
-       28250,  "d-d-++i-",
-       28500,  "c+c-h-e-",
-       29000,  "b+g-d-f+",
-       29500,  "c+h+++e-",
-       29750,  "b+g+f-c+",
-       30250,  "b+f-g-c+",
-       33500,  "c-f-d-n+",
-       33750,  "b+d-b+j-",
-       34250,  "c+e+++i+",
-       35250,  "e+b+d+k+",
-       35500,  "c+e+d-g-",
-       35750,  "c+i-++e+",
-       36250,  "b+bh-d+e+",
-       36500,  "c+c-h-e-",
-       36750,  "d+e--i+",
-       37250,  "b+g+g+b+",
-       37500,  "b+h-b+f+",
-       37750,  "c+be++j-",
-       38500,  "b+e+b+i+",
-       38750,  "d+i-b+d+",
-       39250,  "b+g-l-+d+",
-       39500,  "b+g-c+g-",
-       39750,  "b+bh-c+f-",
-       40250,  "b+bf+d+g-",
-       40500,  "b+g-c+g+",
-       40750,  "c+b+i-e+",
-       41250,  "d++bf+h+",
-       41500,  "b+j+c+d-",
-       41750,  "c+f+b+h-",
-       42500,  "c+h++g+",
-       42750,  "b+g+d-f-",
-       43250,  "b+l-e+d-",
-       43750,  "c+bd+h+f-",
-       44000,  "b+f+g-d-",
-       44250,  "b+d-g--f+",
-       44500,  "c+e+c+h+",
-       44750,  "b+e+d-h-",
-       45250,  "b++g+j-g+",
-       45500,  "c+d+e-g+",
-       45750,  "b+d-h-e-",
-       46250,  "c+bd++j+",
-       46500,  "b+d-c-j-",
-       46750,  "e-e-b+g-",
-       47000,  "b+c+d-j-",
-       47250,  "b+e+e-g-",
-       47500,  "b+g-c-h-",
-       47750,  "b+f-c+h-",
-       48250,  "d--h+n-",
-       48500,  "b+c-g+m-",
-       48750,  "b+e+e-g+",
-       49500,  "c-f+e+j-",
-       49750,  "c+c+g++f-",
-       50000,  "b+e+e+k+",
-       50250,  "b++i++g+",
-       50500,  "c+g+f-i+",
-       50750,  "b+e+d+k-",
-       51500,  "b+i+c-f+",
-       51750,  "b+bd+g-e-",
-       52250,  "b+d+g-j+",
-       52500,  "c+c+f+g+",
-       52750,  "b+c+e+i+",
-       53000,  "b+i+c+g+",
-       53500,  "c+g+g-n+",
-       53750,  "b+j+d-c+",
-       54250,  "b+d-g-j-",
-       54500,  "c-f+e+f+",
-       54750,  "b+f-+c+g+",
-       55000,  "b+g-d-g-",
-       55250,  "b+e+e+g+",
-       55500,  "b+cd++j+",
-       55750,  "b+bh-d-f-",
-       56250,  "c+d-b+j-",
-       56500,  "c+d+c+i+",
-       56750,  "b+e+d++h-",
-       57000,  "b+d+g-f+",
-       57250,  "b+f-m+d-",
-       57750,  "b+i+c+e-",
-       58000,  "b+e+d+h+",
-       58250,  "c+b+g+g+",
-       58750,  "d-e-j--e+",
-       59000,  "d-i-+e+",
-       59250,  "e--h-m+",
-       59500,  "c+c-h+f-",
-       59750,  "b+bh-e+i-",
-       60250,  "b+bh-e-e-",
-       60500,  "c+c-g-g-",
-       60750,  "b+e-l-e-",
-       61250,  "b+g-g-c+",
-       61750,  "b+g-c+g+",
-       62250,  "f--+c-i-",
-       62750,  "e+f--+g+",
-       64750,  "b+f+d+p-",
-};
-int    hintabsize      = nelem(hintab);
diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c
deleted file mode 100644 (file)
index 1de56b5..0000000
+++ /dev/null
@@ -1,1478 +0,0 @@
-// Inferno utils/5c/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@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-int xtramodes(Reg*, Addr*);
-
-void
-peep(void)
-{
-       Reg *r, *r1, *r2;
-       Prog *p, *p1;
-       int t;
-/*
- * complete R structure
- */
-       t = 0;
-       for(r=firstr; r!=R; r=r1) {
-               r1 = r->link;
-               if(r1 == R)
-                       break;
-               p = r->prog->link;
-               while(p != r1->prog)
-               switch(p->as) {
-               default:
-                       r2 = rega();
-                       r->link = r2;
-                       r2->link = r1;
-
-                       r2->prog = p;
-                       r2->p1 = r;
-                       r->s1 = r2;
-                       r2->s1 = r1;
-                       r1->p1 = r2;
-
-                       r = r2;
-                       t++;
-
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-                       p = p->link;
-               }
-       }
-
-loop1:
-       t = 0;
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {
-                       /*
-                        * elide shift into D_SHIFT operand of subsequent instruction
-                        */
-                       if(shiftprop(r)) {
-                               excise(r);
-                               t++;
-                       }
-               }
-               if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
-               if(regtyp(&p->to)) {
-                       if(p->from.type == D_CONST)
-                               constprop(&p->from, &p->to, r->s1);
-                       else if(regtyp(&p->from))
-                       if(p->from.type == p->to.type) {
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-               }
-       }
-       if(t)
-               goto loop1;
-       /*
-        * look for MOVB x,R; MOVB R,R
-        */
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               default:
-                       continue;
-               case AEOR:
-                       /*
-                        * EOR -1,x,y => MVN x,y
-                        */
-                       if(p->from.type == D_CONST && 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;
-                       }
-                       continue;
-               case AMOVH:
-               case AMOVHS:
-               case AMOVHU:
-               case AMOVB:
-               case AMOVBS:
-               case AMOVBU:
-                       if(p->to.type != D_REG)
-                               continue;
-                       break;
-               }
-               r1 = r->link;
-               if(r1 == R)
-                       continue;
-               p1 = r1->prog;
-               if(p1->as != p->as)
-                       continue;
-               if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
-                       continue;
-               if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
-                       continue;
-               excise(r1);
-       }
-
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVW:
-               case AMOVB:
-               case AMOVBS:
-               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
-                        */
-                       if(p->from.type != D_CONST || p->from.offset != 0)
-                               continue;
-                       r2 = r->s1;
-                       if(r2 == R)
-                               continue;
-                       t = r2->prog->as;
-                       switch(t) {
-                       default:
-                               continue;
-                       case ABEQ:
-                       case ABNE:
-                       case ABMI:
-                       case ABPL:
-                               break;
-                       case ABGE:
-                               t = ABPL;
-                               break;
-                       case ABLT:
-                               t = ABMI;
-                               break;
-                       case ABHI:
-                               t = ABNE;
-                               break;
-                       case ABLS:
-                               t = ABEQ;
-                               break;
-                       }
-                       r1 = r;
-                       do
-                               r1 = uniqp(r1);
-                       while (r1 != R && r1->prog->as == ANOP);
-                       if(r1 == R)
-                               continue;
-                       p1 = r1->prog;
-                       if(p1->to.type != D_REG)
-                               continue;
-                       if(p1->to.reg != p->reg)
-                       if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
-                               continue;
-                       switch(p1->as) {
-                       default:
-                               continue;
-                       case AMOVW:
-                               if(p1->from.type != D_REG)
-                                       continue;
-                       case AAND:
-                       case AEOR:
-                       case AORR:
-                       case ABIC:
-                       case AMVN:
-                       case ASUB:
-                       case ARSB:
-                       case AADD:
-                       case AADC:
-                       case ASBC:
-                       case ARSC:
-                               break;
-                       }
-                       p1->scond |= C_SBIT;
-                       r2->prog->as = t;
-                       excise(r);
-                       continue;
-               }
-       }
-
-       predicate();
-}
-
-void
-excise(Reg *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       p->as = ANOP;
-       p->scond = zprog.scond;
-       p->from = zprog.from;
-       p->to = zprog.to;
-       p->reg = zprog.reg; /**/
-}
-
-Reg*
-uniqp(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->p1;
-       if(r1 == R) {
-               r1 = r->p2;
-               if(r1 == R || r1->p2link != R)
-                       return R;
-       } else
-               if(r->p2 != R)
-                       return R;
-       return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->s1;
-       if(r1 == R) {
-               r1 = r->s2;
-               if(r1 == R)
-                       return R;
-       } else
-               if(r->s2 != R)
-                       return R;
-       return r1;
-}
-
-int
-regtyp(Addr *a)
-{
-
-       if(a->type == D_REG)
-               return 1;
-       if(a->type == D_FREG)
-               return 1;
-       return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-       int t;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=R; r=uniqp(r)) {
-               if(uniqs(r) == R)
-                       break;
-               p = r->prog;
-               switch(p->as) {
-               case ABL:
-                       return 0;
-
-               case ACMP:
-               case ACMN:
-               case AADD:
-               case ASUB:
-               case ARSB:
-               case ASLL:
-               case ASRL:
-               case ASRA:
-               case AORR:
-               case AAND:
-               case AEOR:
-               case AMUL:
-               case ADIV:
-               case ADIVU:
-
-               case ACMPF:
-               case ACMPD:
-               case AADDD:
-               case AADDF:
-               case ASUBD:
-               case ASUBF:
-               case AMULD:
-               case AMULF:
-               case ADIVD:
-               case ADIVF:
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg) {
-                               if(p->reg == NREG)
-                                       p->reg = p->to.reg;
-                               goto gotit;
-                       }
-                       break;
-
-               case AMOVF:
-               case AMOVD:
-               case AMOVW:
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg)
-                               goto gotit;
-                       break;
-
-               case AMOVM:
-                       t = 1<<v2->reg;
-                       if((p->from.type == D_CONST && (p->from.offset&t)) ||
-                          (p->to.type == D_CONST && (p->to.offset&t)))
-                               return 0;
-                       break;
-               }
-               if(copyau(&p->from, v2) ||
-                  copyau1(p, v2) ||
-                  copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub1(p, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub1(p, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->reg;
-       v1->reg = v2->reg;
-       v2->reg = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-int
-copyprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       for(r=firstr; r!=R; r=r->link)
-               r->active = 0;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = 1;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != R; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == R) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, A);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %Drar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %Dset; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %Dused+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %Dused and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub%D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %Dused+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, A);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %Dset and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-/*
- * The idea is to remove redundant constants.
- *     $c1->v1
- *     ($c1->v2 s/$c1/v1)*
- *     set v1  return
- * The v1->v2 should be eliminated by copy propagation.
- */
-void
-constprop(Addr *c1, Addr *v1, Reg *r)
-{
-       Prog *p;
-
-       if(debug['C'])
-               print("constprop %D->%D\n", c1, v1);
-       for(; r != R; r = r->s1) {
-               p = r->prog;
-               if(debug['C'])
-                       print("%P", p);
-               if(uniqp(r) == R) {
-                       if(debug['C'])
-                               print("; merge; return\n");
-                       return;
-               }
-               if(p->as == AMOVW && copyas(&p->from, c1)) {
-                               if(debug['C'])
-                                       print("; sub%D/%D", &p->from, v1);
-                               p->from = *v1;
-               } else if(copyu(p, v1, A) > 1) {
-                       if(debug['C'])
-                               print("; %Dset; return\n", v1);
-                       return;
-               }
-               if(debug['C'])
-                       print("\n");
-               if(r->s2)
-                       constprop(c1, v1, r->s2);
-       }
-}
-
-/*
- * ASLL x,y,w
- * .. (not use w, not set x y w)
- * AXXX w,a,b (a != w)
- * .. (not use w)
- * (set w)
- * ----------- changed to
- * ..
- * AXXX (x<<y),a,b
- * ..
- */
-#define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
-int
-shiftprop(Reg *r)
-{
-       Reg *r1;
-       Prog *p, *p1, *p2;
-       int n, o;
-       Addr a;
-
-       p = r->prog;
-       if(p->to.type != D_REG)
-               FAIL("BOTCH: result not reg");
-       n = p->to.reg;
-       a = zprog.from;
-       if(p->reg != NREG && p->reg != p->to.reg) {
-               a.type = D_REG;
-               a.reg = p->reg;
-       }
-       if(debug['H'])
-               print("shiftprop\n%P", p);
-       r1 = r;
-       for(;;) {
-               /* find first use of shift result; abort if shift operands or result are changed */
-               r1 = uniqs(r1);
-               if(r1 == R)
-                       FAIL("branch");
-               if(uniqp(r1) == R)
-                       FAIL("merge");
-               p1 = r1->prog;
-               if(debug['H'])
-                       print("\n%P", p1);
-               switch(copyu(p1, &p->to, A)) {
-               case 0: /* not used or set */
-                       if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
-                          (a.type == D_REG && copyu(p1, &a, A) > 1))
-                               FAIL("args modified");
-                       continue;
-               case 3: /* set, not used */
-                       FAIL("BOTCH: noref");
-               }
-               break;
-       }
-       /* check whether substitution can be done */
-       switch(p1->as) {
-       default:
-               FAIL("non-dpi");
-       case AAND:
-       case AEOR:
-       case AADD:
-       case AADC:
-       case AORR:
-       case ASUB:
-       case ARSB:
-       case ASBC:
-       case ARSC:
-               if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
-                       if(p1->from.type != D_REG)
-                               FAIL("can't swap");
-                       p1->reg = p1->from.reg;
-                       p1->from.reg = n;
-                       switch(p1->as) {
-                       case ASUB:
-                               p1->as = ARSB;
-                               break;
-                       case ARSB:
-                               p1->as = ASUB;
-                               break;
-                       case ASBC:
-                               p1->as = ARSC;
-                               break;
-                       case ARSC:
-                               p1->as = ASBC;
-                               break;
-                       }
-                       if(debug['H'])
-                               print("\t=>%P", p1);
-               }
-       case ABIC:
-       case ACMP:
-       case ACMN:
-               if(p1->reg == n)
-                       FAIL("can't swap");
-               if(p1->reg == NREG && p1->to.reg == n)
-                       FAIL("shift result used twice");
-       case AMVN:
-               if(p1->from.type == D_SHIFT)
-                       FAIL("shift result used in shift");
-               if(p1->from.type != D_REG || p1->from.reg != n)
-                       FAIL("BOTCH: where is it used?");
-               break;
-       }
-       /* check whether shift result is used subsequently */
-       p2 = p1;
-       if(p1->to.reg != n)
-       for (;;) {
-               r1 = uniqs(r1);
-               if(r1 == R)
-                       FAIL("inconclusive");
-               p1 = r1->prog;
-               if(debug['H'])
-                       print("\n%P", p1);
-               switch(copyu(p1, &p->to, A)) {
-               case 0: /* not used or set */
-                       continue;
-               case 3: /* set, not used */
-                       break;
-               default:/* used */
-                       FAIL("reused");
-               }
-               break;
-       }
-       /* make the substitution */
-       p2->from.type = D_SHIFT;
-       p2->from.reg = NREG;
-       o = p->reg;
-       if(o == NREG)
-               o = p->to.reg;
-       switch(p->from.type){
-       case D_CONST:
-               o |= (p->from.offset&0x1f)<<7;
-               break;
-       case D_REG:
-               o |= (1<<4) | (p->from.reg<<8);
-               break;
-       }
-       switch(p->as){
-       case ASLL:
-               o |= 0<<5;
-               break;
-       case ASRL:
-               o |= 1<<5;
-               break;
-       case ASRA:
-               o |= 2<<5;
-               break;
-       }
-       p2->from.offset = o;
-       if(debug['H'])
-               print("\t=>%P\tSUCCEED\n", p2);
-       return 1;
-}
-
-Reg*
-findpre(Reg *r, Addr *v)
-{
-       Reg *r1;
-
-       for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
-               if(uniqs(r1) != r)
-                       return R;
-               switch(copyu(r1->prog, v, A)) {
-               case 1: /* used */
-               case 2: /* read-alter-rewrite */
-                       return R;
-               case 3: /* set */
-               case 4: /* set and used */
-                       return r1;
-               }
-       }
-       return R;
-}
-
-Reg*
-findinc(Reg *r, Reg *r2, Addr *v)
-{
-       Reg *r1;
-       Prog *p;
-
-
-       for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
-               if(uniqp(r1) != r)
-                       return R;
-               switch(copyu(r1->prog, v, A)) {
-               case 0: /* not touched */
-                       continue;
-               case 4: /* set and used */
-                       p = r1->prog;
-                       if(p->as == AADD)
-                       if(p->from.type == D_CONST)
-                       if(p->from.offset > -4096 && p->from.offset < 4096)
-                               return r1;
-               default:
-                       return R;
-               }
-       }
-       return R;
-}
-
-int
-nochange(Reg *r, Reg *r2, Prog *p)
-{
-       Addr a[3];
-       int i, n;
-
-       if(r == r2)
-               return 1;
-       n = 0;
-       if(p->reg != NREG && p->reg != p->to.reg) {
-               a[n].type = D_REG;
-               a[n++].reg = p->reg;
-       }
-       switch(p->from.type) {
-       case D_SHIFT:
-               a[n].type = D_REG;
-               a[n++].reg = p->from.offset&0xf;
-       case D_REG:
-               a[n].type = D_REG;
-               a[n++].reg = p->from.reg;
-       }
-       if(n == 0)
-               return 1;
-       for(; r!=R && r!=r2; r=uniqs(r)) {
-               p = r->prog;
-               for(i=0; i<n; i++)
-                       if(copyu(p, &a[i], A) > 1)
-                               return 0;
-       }
-       return 1;
-}
-
-int
-findu1(Reg *r, Addr *v)
-{
-       for(; r != R; r = r->s1) {
-               if(r->active)
-                       return 0;
-               r->active = 1;
-               switch(copyu(r->prog, v, A)) {
-               case 1: /* used */
-               case 2: /* read-alter-rewrite */
-               case 4: /* set and used */
-                       return 1;
-               case 3: /* set */
-                       return 0;
-               }
-               if(r->s2)
-                       if (findu1(r->s2, v))
-                               return 1;
-       }
-       return 0;
-}
-
-int
-finduse(Reg *r, Addr *v)
-{
-       Reg *r1;
-
-       for(r1=firstr; r1!=R; r1=r1->link)
-               r1->active = 0;
-       return findu1(r, v);
-}
-
-int
-xtramodes(Reg *r, Addr *a)
-{
-       Reg *r1, *r2, *r3;
-       Prog *p, *p1;
-       Addr v;
-
-       p = r->prog;
-       if((p->as == AMOVB || p->as == AMOVBS) && p->from.type == D_OREG)       /* byte load */
-               return 0;
-       v = *a;
-       v.type = D_REG;
-       r1 = findpre(r, &v);
-       if(r1 != R) {
-               p1 = r1->prog;
-               if(p1->to.type == D_REG && p1->to.reg == v.reg)
-               switch(p1->as) {
-               case AADD:
-                       if(p1->from.type == D_REG ||
-                          (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
-                           ((p->as != AMOVB && p->as != AMOVBS) || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
-                          (p1->from.type == D_CONST &&
-                           p1->from.offset > -4096 && p1->from.offset < 4096))
-                       if(nochange(uniqs(r1), r, p1)) {
-                               if(a != &p->from || v.reg != p->to.reg)
-                               if (finduse(r->s1, &v)) {
-                                       if(p1->reg == NREG || p1->reg == v.reg)
-                                               /* pre-indexing */
-                                               p->scond |= C_WBIT;
-                                       else return 0;
-                               }
-                               switch (p1->from.type) {
-                               case D_REG:
-                                       /* register offset */
-                                       if(nacl)
-                                               return 0;
-                                       a->type = D_SHIFT;
-                                       a->offset = p1->from.reg;
-                                       break;
-                               case D_SHIFT:
-                                       /* scaled register offset */
-                                       if(nacl)
-                                               return 0;
-                                       a->type = D_SHIFT;
-                               case D_CONST:
-                                       /* immediate offset */
-                                       a->offset = p1->from.offset;
-                                       break;
-                               }
-                               if(p1->reg != NREG)
-                                       a->reg = p1->reg;
-                               excise(r1);
-                               return 1;
-                       }
-                       break;
-               case AMOVW:
-                       if(p1->from.type == D_REG)
-                       if((r2 = findinc(r1, r, &p1->from)) != R) {
-                       for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
-                               ;
-                       if(r3 == r) {
-                               /* post-indexing */
-                               p1 = r2->prog;
-                               a->reg = p1->to.reg;
-                               a->offset = p1->from.offset;
-                               p->scond |= C_PBIT;
-                               if(!finduse(r, &r1->prog->to))
-                                       excise(r1);
-                               excise(r2);
-                               return 1;
-                       }
-                       }
-                       break;
-               }
-       }
-       if(a != &p->from || a->reg != p->to.reg)
-       if((r1 = findinc(r, R, &v)) != R) {
-               /* post-indexing */
-               p1 = r1->prog;
-               a->offset = p1->from.offset;
-               p->scond |= C_PBIT;
-               excise(r1);
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
-       switch(p->as) {
-
-       default:
-               if(debug['P'])
-                       print(" (?)");
-               return 2;
-
-       case AMOVM:
-               if(v->type != D_REG)
-                       return 0;
-               if(p->from.type == D_CONST) {   /* read reglist, read/rar */
-                       if(s != A) {
-                               if(p->from.offset&(1<<v->reg))
-                                       return 1;
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                               return 0;
-                       }
-                       if(copyau(&p->to, v)) {
-                               if(p->scond&C_WBIT)
-                                       return 2;
-                               return 1;
-                       }
-                       if(p->from.offset&(1<<v->reg))
-                               return 1;
-               } else {                        /* read/rar, write reglist */
-                       if(s != A) {
-                               if(p->to.offset&(1<<v->reg))
-                                       return 1;
-                               if(copysub(&p->from, v, s, 1))
-                                       return 1;
-                               return 0;
-                       }
-                       if(copyau(&p->from, v)) {
-                               if(p->scond&C_WBIT)
-                                       return 2;
-                               if(p->to.offset&(1<<v->reg))
-                                       return 4;
-                               return 1;
-                       }
-                       if(p->to.offset&(1<<v->reg))
-                               return 3;
-               }
-               return 0;
-
-       case ANOP:      /* read, write */
-       case AMOVW:
-       case AMOVF:
-       case AMOVD:
-       case AMOVH:
-       case AMOVHS:
-       case AMOVHU:
-       case AMOVB:
-       case AMOVBS:
-       case AMOVBU:
-       case AMOVDW:
-       case AMOVWD:
-       case AMOVFD:
-       case AMOVDF:
-               if(p->scond&(C_WBIT|C_PBIT))
-               if(v->type == D_REG) {
-                       if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
-                               if(p->from.reg == v->reg)
-                                       return 2;
-                       } else {
-                               if(p->to.reg == v->reg)
-                               return 2;
-                       }
-               }
-               if(s != A) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-
-       case AADD:      /* read, read, write */
-       case ASUB:
-       case ARSB:
-       case ASLL:
-       case ASRL:
-       case ASRA:
-       case AORR:
-       case AAND:
-       case AEOR:
-       case AMUL:
-       case ADIV:
-       case ADIVU:
-       case AADDF:
-       case AADDD:
-       case ASUBF:
-       case ASUBD:
-       case AMULF:
-       case AMULD:
-       case ADIVF:
-       case ADIVD:
-
-       case ACMPF:
-       case ACMPD:
-       case ACMP:
-       case ACMN:
-       case ACASE:
-               if(s != A) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(copysub1(p, v, s, 1))
-                               return 1;
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(p->reg == NREG)
-                               p->reg = p->to.reg;
-                       if(copyau(&p->from, v))
-                               return 4;
-                       if(copyau1(p, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau1(p, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ABEQ:      /* read, read */
-       case ABNE:
-       case ABCS:
-       case ABHS:
-       case ABCC:
-       case ABLO:
-       case ABMI:
-       case ABPL:
-       case ABVS:
-       case ABVC:
-       case ABHI:
-       case ABLS:
-       case ABGE:
-       case ABLT:
-       case ABGT:
-       case ABLE:
-       case APLD:
-               if(s != A) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub1(p, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau1(p, v))
-                       return 1;
-               return 0;
-
-       case AB:        /* funny */
-               if(s != A) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               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;
-
-       case ABL:       /* funny */
-               if(v->type == D_REG) {
-                       if(v->reg <= REGEXT && v->reg > exregoffset)
-                               return 2;
-                       if(v->reg == REGARG)
-                               return 2;
-               }
-               if(v->type == D_FREG)
-                       if(v->reg <= FREGEXT && v->reg > exfregoffset)
-                               return 2;
-
-               if(s != A) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-
-       case ATEXT:     /* funny */
-               if(v->type == D_REG)
-                       if(v->reg == REGARG)
-                               return 3;
-               return 0;
-       }
-}
-
-int
-a2type(Prog *p)
-{
-
-       switch(p->as) {
-
-       case ACMP:
-       case ACMN:
-
-       case AADD:
-       case ASUB:
-       case ARSB:
-       case ASLL:
-       case ASRL:
-       case ASRA:
-       case AORR:
-       case AAND:
-       case AEOR:
-       case AMUL:
-       case ADIV:
-       case ADIVU:
-               return D_REG;
-
-       case ACMPF:
-       case ACMPD:
-
-       case AADDF:
-       case AADDD:
-       case ASUBF:
-       case ASUBD:
-       case AMULF:
-       case AMULD:
-       case ADIVF:
-       case ADIVD:
-               return D_FREG;
-       }
-       return D_NONE;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
-
-       if(regtyp(v)) {
-               if(a->type == v->type)
-               if(a->reg == v->reg)
-                       return 1;
-       } else if(v->type == D_CONST) {         /* for constprop */
-               if(a->type == v->type)
-               if(a->name == v->name)
-               if(a->sym == v->sym)
-               if(a->reg == v->reg)
-               if(a->offset == v->offset)
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
-       if(copyas(a, v))
-               return 1;
-       if(v->type == D_REG) {
-               if(a->type == D_OREG) {
-                       if(v->reg == a->reg)
-                               return 1;
-               } else if(a->type == D_SHIFT) {
-                       if((a->offset&0xf) == v->reg)
-                               return 1;
-                       if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-int
-copyau1(Prog *p, Addr *v)
-{
-
-       if(regtyp(v)) {
-               if(a2type(p) == v->type)
-               if(p->reg == v->reg) {
-                       if(a2type(p) != v->type)
-                               print("botch a2type %P\n", p);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-
-       if(f)
-       if(copyau(a, v)) {
-               if(a->type == D_SHIFT) {
-                       if((a->offset&0xf) == v->reg)
-                               a->offset = (a->offset&~0xf)|s->reg;
-                       if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
-                               a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
-               } else
-                       a->reg = s->reg;
-       }
-       return 0;
-}
-
-int
-copysub1(Prog *p1, Addr *v, Addr *s, int f)
-{
-
-       if(f)
-       if(copyau1(p1, v))
-               p1->reg = s->reg;
-       return 0;
-}
-
-struct {
-       int opcode;
-       int notopcode;
-       int scond;
-       int notscond;
-} predinfo[]  = {
-       { ABEQ, ABNE,   0x0,    0x1, },
-       { ABNE, ABEQ,   0x1,    0x0, },
-       { ABCS, ABCC,   0x2,    0x3, },
-       { ABHS, ABLO,   0x2,    0x3, },
-       { ABCC, ABCS,   0x3,    0x2, },
-       { ABLO, ABHS,   0x3,    0x2, },
-       { ABMI, ABPL,   0x4,    0x5, },
-       { ABPL, ABMI,   0x5,    0x4, },
-       { ABVS, ABVC,   0x6,    0x7, },
-       { ABVC, ABVS,   0x7,    0x6, },
-       { ABHI, ABLS,   0x8,    0x9, },
-       { ABLS, ABHI,   0x9,    0x8, },
-       { ABGE, ABLT,   0xA,    0xB, },
-       { ABLT, ABGE,   0xB,    0xA, },
-       { ABGT, ABLE,   0xC,    0xD, },
-       { ABLE, ABGT,   0xD,    0xC, },
-};
-
-typedef struct {
-       Reg *start;
-       Reg *last;
-       Reg *end;
-       int len;
-} Joininfo;
-
-enum {
-       Join,
-       Split,
-       End,
-       Branch,
-       Setcond,
-       Toolong
-};
-
-enum {
-       Falsecond,
-       Truecond,
-       Delbranch,
-       Keepbranch
-};
-
-int
-isbranch(Prog *p)
-{
-       return (ABEQ <= p->as) && (p->as <= ABLE);
-}
-
-int
-predicable(Prog *p)
-{
-       if (isbranch(p)
-               || p->as == ANOP
-               || p->as == AXXX
-               || p->as == ADATA
-               || p->as == AGLOBL
-               || p->as == AGOK
-               || p->as == AHISTORY
-               || p->as == ANAME
-               || p->as == ASIGNAME
-               || p->as == ATEXT
-               || p->as == AWORD
-               || p->as == ABCASE
-               || p->as == ACASE)
-               return 0;
-       return 1;
-}
-
-/*
- * Depends on an analysis of the encodings performed by 5l.
- * These seem to be all of the opcodes that lead to the "S" bit
- * being set in the instruction encodings.
- *
- * C_SBIT may also have been set explicitly in p->scond.
- */
-int
-modifiescpsr(Prog *p)
-{
-       return (p->scond&C_SBIT)
-               || p->as == ATST
-               || p->as == ATEQ
-               || p->as == ACMN
-               || p->as == ACMP
-               || p->as == AMULU
-               || p->as == ADIVU
-               || p->as == AMUL
-               || p->as == ADIV
-               || p->as == AMOD
-               || p->as == AMODU
-               || p->as == ABL;
-}
-
-/*
- * Find the maximal chain of instructions starting with r which could
- * be executed conditionally
- */
-int
-joinsplit(Reg *r, Joininfo *j)
-{
-       j->start = r;
-       j->last = r;
-       j->len = 0;
-       do {
-               if (r->p2 && (r->p1 || r->p2->p2link)) {
-                       j->end = r;
-                       return Join;
-               }
-               if (r->s1 && r->s2) {
-                       j->end = r;
-                       return Split;
-               }
-               j->last = r;
-               if (r->prog->as != ANOP)
-                       j->len++;
-               if (!r->s1 && !r->s2) {
-                       j->end = r->link;
-                       return End;
-               }
-               if (r->s2) {
-                       j->end = r->s2;
-                       return Branch;
-               }
-               if (modifiescpsr(r->prog)) {
-                       j->end = r->s1;
-                       return Setcond;
-               }
-               r = r->s1;
-       } while (j->len < 4);
-       j->end = r;
-       return Toolong;
-}
-
-Reg *
-successor(Reg *r)
-{
-       if (r->s1)
-               return r->s1;
-       else
-               return r->s2;
-}
-
-void
-applypred(Reg *rstart, Joininfo *j, int cond, int branch)
-{
-       int pred;
-       Reg *r;
-
-       if(j->len == 0)
-               return;
-       if (cond == Truecond)
-               pred = predinfo[rstart->prog->as - ABEQ].scond;
-       else
-               pred = predinfo[rstart->prog->as - ABEQ].notscond;
-
-       for (r = j->start; ; r = successor(r)) {
-               if (r->prog->as == AB) {
-                       if (r != j->last || branch == Delbranch)
-                               excise(r);
-                       else {
-                         if (cond == Truecond)
-                               r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
-                         else
-                               r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
-                       }
-               }
-               else if (predicable(r->prog))
-                       r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
-               if (r->s1 != r->link) {
-                       r->s1 = r->link;
-                       r->link->p1 = r;
-               }
-               if (r == j->last)
-                       break;
-       }
-}
-
-void
-predicate(void)
-{
-       Reg *r;
-       int t1, t2;
-       Joininfo j1, j2;
-
-       for(r=firstr; r!=R; r=r->link) {
-               if (isbranch(r->prog)) {
-                       t1 = joinsplit(r->s1, &j1);
-                       t2 = joinsplit(r->s2, &j2);
-                       if(j1.last->link != j2.start)
-                               continue;
-                       if(j1.end == j2.end)
-                       if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
-                          (t2 == Join && (t1 == Join || t1 == Setcond))) {
-                               applypred(r, &j1, Falsecond, Delbranch);
-                               applypred(r, &j2, Truecond, Delbranch);
-                               excise(r);
-                               continue;
-                       }
-                       if(t1 == End || t1 == Branch) {
-                               applypred(r, &j1, Falsecond, Keepbranch);
-                               excise(r);
-                               continue;
-                       }
-               }
-       }
-}
diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c
deleted file mode 100644 (file)
index 9024d5f..0000000
+++ /dev/null
@@ -1,1210 +0,0 @@
-// Inferno utils/5c/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@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-void   addsplits(void);
-
-Reg*
-rega(void)
-{
-       Reg *r;
-
-       r = freer;
-       if(r == R) {
-               r = alloc(sizeof(*r));
-       } else
-               freer = r->link;
-
-       *r = zreg;
-       return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
-       Rgn *p1, *p2;
-       int c1, c2;
-
-       p1 = (Rgn*)a1;
-       p2 = (Rgn*)a2;
-       c1 = p2->cost;
-       c2 = p1->cost;
-       if(c1 -= c2)
-               return c1;
-       return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
-       Reg *r, *r1, *r2;
-       Prog *p1;
-       int i, z;
-       int32 initpc, val, npc;
-       uint32 vreg;
-       Bits bit;
-       struct
-       {
-               int32   m;
-               int32   c;
-               Reg*    p;
-       } log5[6], *lp;
-
-       firstr = R;
-       lastr = R;
-       nvar = 0;
-       regbits = 0;
-       for(z=0; z<BITS; z++) {
-               externs.b[z] = 0;
-               params.b[z] = 0;
-               consts.b[z] = 0;
-               addrs.b[z] = 0;
-       }
-
-       /*
-        * pass 1
-        * build aux data structure
-        * allocate pcs
-        * find use and set of variables
-        */
-       val = 5L * 5L * 5L * 5L * 5L;
-       lp = log5;
-       for(i=0; i<5; i++) {
-               lp->m = val;
-               lp->c = 0;
-               lp->p = R;
-               val /= 5L;
-               lp++;
-       }
-       val = 0;
-       for(; p != P; p = p->link) {
-               switch(p->as) {
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-               case AFUNCDATA:
-                       continue;
-               }
-               r = rega();
-               if(firstr == R) {
-                       firstr = r;
-                       lastr = r;
-               } else {
-                       lastr->link = r;
-                       r->p1 = lastr;
-                       lastr->s1 = r;
-                       lastr = r;
-               }
-               r->prog = p;
-               r->pc = val;
-               val++;
-
-               lp = log5;
-               for(i=0; i<5; i++) {
-                       lp->c--;
-                       if(lp->c <= 0) {
-                               lp->c = lp->m;
-                               if(lp->p != R)
-                                       lp->p->log5 = r;
-                               lp->p = r;
-                               (lp+1)->c = 0;
-                               break;
-                       }
-                       lp++;
-               }
-
-               r1 = r->p1;
-               if(r1 != R)
-               switch(r1->prog->as) {
-               case ARET:
-               case AB:
-               case ARFE:
-                       r->p1 = R;
-                       r1->s1 = R;
-               }
-
-               /*
-                * left side always read
-                */
-               bit = mkvar(&p->from, p->as==AMOVW);
-               for(z=0; z<BITS; z++)
-                       r->use1.b[z] |= bit.b[z];
-
-               /*
-                * right side depends on opcode
-                */
-               bit = mkvar(&p->to, 0);
-               if(bany(&bit))
-               switch(p->as) {
-               default:
-                       diag(Z, "reg: unknown asop: %A", p->as);
-                       break;
-
-               /*
-                * right side write
-                */
-               case ANOP:
-               case AMOVB:
-               case AMOVBS:
-               case AMOVBU:
-               case AMOVH:
-               case AMOVHS:
-               case AMOVHU:
-               case AMOVW:
-               case AMOVF:
-               case AMOVD:
-                       for(z=0; z<BITS; z++)
-                               r->set.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * right side read
-                */
-               case APLD:
-                       for(z=0; z<BITS; z++)
-                               r->use2.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * funny
-                */
-               case ABL:
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-                       break;
-               }
-
-               /* the mod/div runtime routines smash R12 */
-               switch(p->as) {
-               case AMOD:
-               case AMODU:
-               case ADIV:
-               case ADIVU:
-                       regbits |= RtoB(12);
-                       break;
-               }
-
-               if(p->as == AMOVM) {
-                       if(p->from.type == D_CONST)
-                               z = p->from.offset;
-                       else
-                               z = p->to.offset;
-                       for(i=0; z; i++) {
-                               if(z&1)
-                                       regbits |= RtoB(i);
-                               z >>= 1;
-                       }
-               }
-       }
-       if(firstr == R)
-               return;
-       initpc = pc - val;
-       npc = val;
-
-       /*
-        * pass 2
-        * turn branch references to pointers
-        * build back pointers
-        */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       val = p->to.offset - initpc;
-                       r1 = firstr;
-                       while(r1 != R) {
-                               r2 = r1->log5;
-                               if(r2 != R && val >= r2->pc) {
-                                       r1 = r2;
-                                       continue;
-                               }
-                               if(r1->pc == val)
-                                       break;
-                               r1 = r1->link;
-                       }
-                       if(r1 == R) {
-                               nearln = p->lineno;
-                               diag(Z, "ref not found\n%P", p);
-                               continue;
-                       }
-                       if(r1 == r) {
-                               nearln = p->lineno;
-                               diag(Z, "ref to self\n%P", p);
-                               continue;
-                       }
-                       r->s2 = r1;
-                       r->p2link = r1->p2;
-                       r1->p2 = r;
-               }
-       }
-       if(debug['R']) {
-               p = firstr->prog;
-               print("\n%L %D\n", p->lineno, &p->from);
-       }
-
-       /*
-        * pass 2.5
-        * find looping structure
-        */
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       change = 0;
-       loopit(firstr, npc);
-
-       /*
-        * pass 3
-        * iterate propagating usage
-        *      back until flow graph is complete
-        */
-loop1:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       for(r = firstr; r != R; r = r->link)
-               if(r->prog->as == ARET)
-                       prop(r, zbits, zbits);
-loop11:
-       /* pick up unreachable code */
-       i = 0;
-       for(r = firstr; r != R; r = r1) {
-               r1 = r->link;
-               if(r1 && r1->active && !r->active) {
-                       prop(r, zbits, zbits);
-                       i = 1;
-               }
-       }
-       if(i)
-               goto loop11;
-       if(change)
-               goto loop1;
-
-
-       /*
-        * pass 4
-        * iterate propagating register/variable synchrony
-        *      forward until graph is complete
-        */
-loop2:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       synch(firstr, zbits);
-       if(change)
-               goto loop2;
-
-       addsplits();
-
-       if(debug['R'] && debug['v']) {
-               print("\nprop structure:\n");
-               for(r = firstr; r != R; r = r->link) {
-                       print("%d:%P", r->loop, r->prog);
-                       for(z=0; z<BITS; z++)
-                               bit.b[z] = r->set.b[z] |
-                                       r->refahead.b[z] | r->calahead.b[z] |
-                                       r->refbehind.b[z] | r->calbehind.b[z] |
-                                       r->use1.b[z] | r->use2.b[z];
-                       if(bany(&bit)) {
-                               print("\t");
-                               if(bany(&r->use1))
-                                       print(" u1=%B", r->use1);
-                               if(bany(&r->use2))
-                                       print(" u2=%B", r->use2);
-                               if(bany(&r->set))
-                                       print(" st=%B", r->set);
-                               if(bany(&r->refahead))
-                                       print(" ra=%B", r->refahead);
-                               if(bany(&r->calahead))
-                                       print(" ca=%B", r->calahead);
-                               if(bany(&r->refbehind))
-                                       print(" rb=%B", r->refbehind);
-                               if(bany(&r->calbehind))
-                                       print(" cb=%B", r->calbehind);
-                       }
-                       print("\n");
-               }
-       }
-
-       /*
-        * pass 5
-        * isolate regions
-        * calculate costs (paint1)
-        */
-       r = firstr;
-       if(r) {
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
-                         ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "used and not set: %B", bit);
-                       if(debug['R'] && !debug['w'])
-                               print("used and not set: %B\n", bit);
-               }
-       }
-
-       for(r = firstr; r != R; r = r->link)
-               r->act = zbits;
-       rgp = region;
-       nregion = 0;
-       for(r = firstr; r != R; r = r->link) {
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = r->set.b[z] &
-                         ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "set and not used: %B", bit);
-                       if(debug['R'])
-                               print("set and not used: %B\n", bit);
-                       excise(r);
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
-               while(bany(&bit)) {
-                       i = bnum(bit);
-                       rgp->enter = r;
-                       rgp->varno = i;
-                       change = 0;
-                       if(debug['R'] && debug['v'])
-                               print("\n");
-                       paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
-                       if(change <= 0) {
-                               if(debug['R'])
-                                       print("%L $%d: %B\n",
-                                               r->prog->lineno, change, blsh(i));
-                               continue;
-                       }
-                       rgp->cost = change;
-                       nregion++;
-                       if(nregion >= NRGN) {
-                               fatal(Z, "too many regions");
-                               goto brk;
-                       }
-                       rgp++;
-               }
-       }
-brk:
-       qsort(region, nregion, sizeof(region[0]), rcmp);
-
-       /*
-        * pass 6
-        * determine used registers (paint2)
-        * replace code (paint3)
-        */
-       rgp = region;
-       for(i=0; i<nregion; i++) {
-               bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
-               vreg = allreg(vreg, rgp);
-               if(debug['R']) {
-                       if(rgp->regno >= NREG)
-                               print("%L $%d F%d: %B\n",
-                                       rgp->enter->prog->lineno,
-                                       rgp->cost,
-                                       rgp->regno-NREG,
-                                       bit);
-                       else
-                               print("%L $%d R%d: %B\n",
-                                       rgp->enter->prog->lineno,
-                                       rgp->cost,
-                                       rgp->regno,
-                                       bit);
-               }
-               if(rgp->regno != 0)
-                       paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
-               rgp++;
-       }
-       /*
-        * pass 7
-        * peep-hole on basic block
-        */
-       if(!debug['R'] || debug['P'])
-               peep();
-
-       /*
-        * pass 8
-        * recalculate pc
-        */
-       val = initpc;
-       for(r = firstr; r != R; r = r1) {
-               r->pc = val;
-               p = r->prog;
-               p1 = P;
-               r1 = r->link;
-               if(r1 != R)
-                       p1 = r1->prog;
-               for(; p != p1; p = p->link) {
-                       switch(p->as) {
-                       default:
-                               val++;
-                               break;
-
-                       case ANOP:
-                       case ADATA:
-                       case AGLOBL:
-                       case ANAME:
-                       case ASIGNAME:
-                       case AFUNCDATA:
-                               break;
-                       }
-               }
-       }
-       pc = val;
-
-       /*
-        * fix up branches
-        */
-       if(debug['R'])
-               if(bany(&addrs))
-                       print("addrs: %B\n", addrs);
-
-       r1 = 0; /* set */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       p->to.offset = r->s2->pc;
-                       p->to.u.branch = r->s2->prog;
-               }
-               r1 = r;
-       }
-
-       /*
-        * last pass
-        * eliminate nops
-        * free aux structures
-        */
-       for(p = firstr->prog; p != P; p = p->link){
-               while(p->link && p->link->as == ANOP)
-                       p->link = p->link->link;
-       }
-       if(r1 != R) {
-               r1->link = freer;
-               freer = firstr;
-       }
-}
-
-void
-addsplits(void)
-{
-       Reg *r, *r1;
-       int z, i;
-       Bits bit;
-
-       for(r = firstr; r != R; r = r->link) {
-               if(r->loop > 1)
-                       continue;
-               if(r->prog->as == ABL)
-                       continue;
-               for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
-                       if(r1->loop <= 1)
-                               continue;
-                       for(z=0; z<BITS; z++)
-                               bit.b[z] = r1->calbehind.b[z] &
-                                       (r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
-                                       ~(r->calahead.b[z] & addrs.b[z]);
-                       while(bany(&bit)) {
-                               i = bnum(bit);
-                               bit.b[i/32] &= ~(1L << (i%32));
-                       }
-               }
-       }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
-       Prog *p, *p1;
-       Addr *a;
-       Var *v;
-
-       p1 = alloc(sizeof(*p1));
-       *p1 = zprog;
-       p = r->prog;
-
-       p1->link = p->link;
-       p->link = p1;
-       p1->lineno = p->lineno;
-
-       v = var + bn;
-
-       a = &p1->to;
-       a->sym = v->sym;
-       a->name = v->name;
-       a->offset = v->offset;
-       a->etype = v->etype;
-       a->type = D_OREG;
-       if(a->etype == TARRAY || a->sym == nil)
-               a->type = D_CONST;
-
-       p1->as = AMOVW;
-       if(v->etype == TCHAR || v->etype == TUCHAR)
-               p1->as = AMOVBS;
-       if(v->etype == TSHORT || v->etype == TUSHORT)
-               p1->as = AMOVHS;
-       if(v->etype == TFLOAT)
-               p1->as = AMOVF;
-       if(v->etype == TDOUBLE)
-               p1->as = AMOVD;
-
-       p1->from.type = D_REG;
-       p1->from.reg = rn;
-       if(rn >= NREG) {
-               p1->from.type = D_FREG;
-               p1->from.reg = rn-NREG;
-       }
-       if(!f) {
-               p1->from = *a;
-               *a = zprog.from;
-               a->type = D_REG;
-               a->reg = rn;
-               if(rn >= NREG) {
-                       a->type = D_FREG;
-                       a->reg = rn-NREG;
-               }
-               if(v->etype == TUCHAR)
-                       p1->as = AMOVBU;
-               if(v->etype == TUSHORT)
-                       p1->as = AMOVHU;
-       }
-       if(debug['R'])
-               print("%P\t.a%P\n", p, p1);
-}
-
-Bits
-mkvar(Addr *a, int docon)
-{
-       Var *v;
-       int i, t, n, et, z;
-       int32 o;
-       Bits bit;
-       LSym *s;
-
-       t = a->type;
-       if(t == D_REG && a->reg != NREG)
-               regbits |= RtoB(a->reg);
-       if(t == D_FREG && a->reg != NREG)
-               regbits |= FtoB(a->reg);
-       s = a->sym;
-       o = a->offset;
-       et = a->etype;
-       if(s == nil) {
-               if(t != D_CONST || !docon || a->reg != NREG)
-                       goto none;
-               et = TLONG;
-       }
-       if(t == D_CONST) {
-               if(s == nil && sval(o))
-                       goto none;
-       }
-
-       n = a->name;
-       v = var;
-       for(i=0; i<nvar; i++) {
-               if(s == v->sym)
-               if(n == v->name)
-               if(o == v->offset)
-                       goto out;
-               v++;
-       }
-       if(s)
-               if(s->name[0] == '.')
-                       goto none;
-       if(nvar >= NVAR)
-               fatal(Z, "variable not optimized: %s", s->name);
-       i = nvar;
-       nvar++;
-       v = &var[i];
-       v->sym = s;
-       v->offset = o;
-       v->etype = et;
-       v->name = n;
-       if(debug['R'])
-               print("bit=%2d et=%2d %D\n", i, et, a);
-out:
-       bit = blsh(i);
-       if(n == D_EXTERN || n == D_STATIC)
-               for(z=0; z<BITS; z++)
-                       externs.b[z] |= bit.b[z];
-       if(n == D_PARAM)
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-       if(v->etype != et || !typechlpfd[et])   /* funny punning */
-               for(z=0; z<BITS; z++)
-                       addrs.b[z] |= bit.b[z];
-       if(t == D_CONST) {
-               if(s == nil) {
-                       for(z=0; z<BITS; z++)
-                               consts.b[z] |= bit.b[z];
-                       return bit;
-               }
-               if(et != TARRAY)
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-               return bit;
-       }
-       if(t == D_OREG)
-               return bit;
-
-none:
-       return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
-       Reg *r1, *r2;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->p1) {
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] |= r1->refahead.b[z];
-                       if(ref.b[z] != r1->refahead.b[z]) {
-                               r1->refahead.b[z] = ref.b[z];
-                               change++;
-                       }
-                       cal.b[z] |= r1->calahead.b[z];
-                       if(cal.b[z] != r1->calahead.b[z]) {
-                               r1->calahead.b[z] = cal.b[z];
-                               change++;
-                       }
-               }
-               switch(r1->prog->as) {
-               case ABL:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] |= ref.b[z] | externs.b[z];
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ATEXT:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = 0;
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ARET:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = externs.b[z];
-                               ref.b[z] = 0;
-                       }
-               }
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
-                               r1->use1.b[z] | r1->use2.b[z];
-                       cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
-                       r1->refbehind.b[z] = ref.b[z];
-                       r1->calbehind.b[z] = cal.b[z];
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-       }
-       for(; r != r1; r = r->p1)
-               for(r2 = r->p2; r2 != R; r2 = r2->p2link)
-                       prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- *     the actual dominators if the flow graph is reducible
- *     otherwise, dominators plus some other non-dominators.
- *     See Matthew S. Hecht and Jeffrey D. Ullman,
- *     "Analysis of a Simple Algorithm for Global Data Flow Problems",
- *     Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- *     Oct. 1-3, 1973, pp.  207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- *     such a node is a loop head.
- *     recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
-       Reg *r1;
-
-       r->rpo = 1;
-       r1 = r->s1;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       r1 = r->s2;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       rpo2r[n] = r;
-       n++;
-       return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
-       int32 t;
-
-       if(rpo1 == -1)
-               return rpo2;
-       while(rpo1 != rpo2){
-               if(rpo1 > rpo2){
-                       t = rpo2;
-                       rpo2 = rpo1;
-                       rpo1 = t;
-               }
-               while(rpo1 < rpo2){
-                       t = idom[rpo2];
-                       if(t >= rpo2)
-                               fatal(Z, "bad idom");
-                       rpo2 = t;
-               }
-       }
-       return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
-       while(s > r)
-               s = idom[s];
-       return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
-       int32 src;
-
-       src = r->rpo;
-       if(r->p1 != R && doms(idom, src, r->p1->rpo))
-               return 1;
-       for(r = r->p2; r != R; r = r->p2link)
-               if(doms(idom, src, r->rpo))
-                       return 1;
-       return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
-       if(r->rpo < head || r->active == head)
-               return;
-       r->active = head;
-       r->loop += LOOP;
-       if(r->p1 != R)
-               loopmark(rpo2r, head, r->p1);
-       for(r = r->p2; r != R; r = r->p2link)
-               loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
-       Reg *r1;
-       int32 i, d, me;
-
-       if(nr > maxnr) {
-               rpo2r = alloc(nr * sizeof(Reg*));
-               idom = alloc(nr * sizeof(int32));
-               maxnr = nr;
-       }
-       d = postorder(r, rpo2r, 0);
-       if(d > nr)
-               fatal(Z, "too many reg nodes");
-       nr = d;
-       for(i = 0; i < nr / 2; i++){
-               r1 = rpo2r[i];
-               rpo2r[i] = rpo2r[nr - 1 - i];
-               rpo2r[nr - 1 - i] = r1;
-       }
-       for(i = 0; i < nr; i++)
-               rpo2r[i]->rpo = i;
-
-       idom[0] = 0;
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               me = r1->rpo;
-               d = -1;
-               if(r1->p1 != R && r1->p1->rpo < me)
-                       d = r1->p1->rpo;
-               for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-                       if(r1->rpo < me)
-                               d = rpolca(idom, d, r1->rpo);
-               idom[i] = d;
-       }
-
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               r1->loop++;
-               if(r1->p2 != R && loophead(idom, r1))
-                       loopmark(rpo2r, i, r1);
-       }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
-       Reg *r1;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->s1) {
-               for(z=0; z<BITS; z++) {
-                       dif.b[z] = (dif.b[z] &
-                               ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
-                                       r1->set.b[z] | r1->regdiff.b[z];
-                       if(dif.b[z] != r1->regdiff.b[z]) {
-                               r1->regdiff.b[z] = dif.b[z];
-                               change++;
-                       }
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-               for(z=0; z<BITS; z++)
-                       dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
-               if(r1->s2 != R)
-                       synch(r1->s2, dif);
-       }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
-       Var *v;
-       int i;
-
-       v = var + r->varno;
-       r->regno = 0;
-       switch(v->etype) {
-
-       default:
-               diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
-               break;
-
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-       case TARRAY:
-               i = BtoR(~b);
-               if(i && r->cost >= 0) {
-                       r->regno = i;
-                       return RtoB(i);
-               }
-               break;
-
-       case TVLONG:
-       case TDOUBLE:
-       case TFLOAT:
-               i = BtoF(~b);
-               if(i && r->cost >= 0) {
-                       r->regno = i+NREG;
-                       return FtoB(i);
-               }
-               break;
-       }
-       return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L<<(bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
-               change -= CLOAD * r->loop;
-               if(debug['R'] && debug['v'])
-                       print("%d%P\td %B $%d\n", r->loop,
-                               r->prog, blsh(bn), change);
-       }
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       change += CREF * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tu1 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       change += CREF * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tu2 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb) {
-                       change -= CLOAD * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tst %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint1(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint1(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
-       Reg *r1;
-       int z;
-       uint32 bb, vreg;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       vreg = regbits;
-       if(!(r->act.b[z] & bb))
-               return vreg;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(!(r1->act.b[z] & bb))
-                       break;
-               r = r1;
-       }
-       for(;;) {
-               r->act.b[z] &= ~bb;
-
-               vreg |= r->regu;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(!(r->act.b[z] & bb))
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-       return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
-               addmove(r, bn, rn, 0);
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->from, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->to, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb)
-                       addmove(r, bn, rn, 1);
-               r->regu |= rb;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint3(r1, bn, rb, rn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint3(r1, bn, rb, rn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
-       a->sym = 0;
-       a->name = D_NONE;
-       a->type = D_REG;
-       a->reg = rn;
-       if(rn >= NREG) {
-               a->type = D_FREG;
-               a->reg = rn-NREG;
-       }
-}
-
-/*
- *     bit     reg
- *     0       R0
- *     1       R1
- *     ...     ...
- *     10      R10
- *     12  R12
- */
-int32
-RtoB(int r)
-{
-
-       if(r < 2 || (r >= REGTMP-2 && r != 12)) // excluded R9 and R10 for m and g, but not R12
-               return 0;
-       return 1L << r;
-}
-
-int
-BtoR(int32 b)
-{
-       b &= 0x11fcL;   // excluded R9 and R10 for m and g, but not R12
-       if(b == 0)
-               return 0;
-       return bitno(b);
-}
-
-/*
- *     bit     reg
- *     18      F2
- *     19      F3
- *     ...     ...
- *     31      F15
- */
-int32
-FtoB(int f)
-{
-
-       if(f < 2 || f > NFREG-1)
-               return 0;
-       return 1L << (f + 16);
-}
-
-int
-BtoF(int32 b)
-{
-
-       b &= 0xfffc0000L;
-       if(b == 0)
-               return 0;
-       return bitno(b) - 16;
-}
diff --git a/src/cmd/5c/sgen.c b/src/cmd/5c/sgen.c
deleted file mode 100644 (file)
index a36612c..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-// Inferno utils/5c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/sgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
-       int32 a;
-
-       a = argsize(1);
-       if((textflag & NOSPLIT) != 0 && stkoff >= 128)
-               yyerror("stack frame too large for NOSPLIT function");
-
-       gpseudo(ATEXT, s, nodconst(stkoff));
-       p->to.type = D_CONST2;
-       p->to.offset2 = a;
-       return p;
-}
-
-void
-noretval(int n)
-{
-
-       if(n & 1) {
-               gins(ANOP, Z, Z);
-               p->to.type = D_REG;
-               p->to.reg = REGRET;
-       }
-       if(n & 2) {
-               gins(ANOP, Z, Z);
-               p->to.type = D_FREG;
-               p->to.reg = FREGRET;
-       }
-}
-
-/*
- *     calculate addressability as follows
- *             CONST ==> 20            $value
- *             NAME ==> 10             name
- *             REGISTER ==> 11         register
- *             INDREG ==> 12           *[(reg)+offset]
- *             &10 ==> 2               $name
- *             ADD(2, 20) ==> 2        $name+offset
- *             ADD(3, 20) ==> 3        $(reg)+offset
- *             &12 ==> 3               $(reg)+offset
- *             *11 ==> 11              ??
- *             *2 ==> 10               name
- *             *3 ==> 12               *(reg)+offset
- *     calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
-       Node *l, *r;
-       int t;
-
-       if(n == Z)
-               return;
-       l = n->left;
-       r = n->right;
-       n->addable = 0;
-       n->complex = 0;
-       switch(n->op) {
-       case OCONST:
-               n->addable = 20;
-               return;
-
-       case OREGISTER:
-               n->addable = 11;
-               return;
-
-       case OINDREG:
-               n->addable = 12;
-               return;
-
-       case ONAME:
-               n->addable = 10;
-               return;
-
-       case OADDR:
-               xcom(l);
-               if(l->addable == 10)
-                       n->addable = 2;
-               if(l->addable == 12)
-                       n->addable = 3;
-               break;
-
-       case OIND:
-               xcom(l);
-               if(l->addable == 11)
-                       n->addable = 12;
-               if(l->addable == 3)
-                       n->addable = 12;
-               if(l->addable == 2)
-                       n->addable = 10;
-               break;
-
-       case OADD:
-               xcom(l);
-               xcom(r);
-               if(l->addable == 20) {
-                       if(r->addable == 2)
-                               n->addable = 2;
-                       if(r->addable == 3)
-                               n->addable = 3;
-               }
-               if(r->addable == 20) {
-                       if(l->addable == 2)
-                               n->addable = 2;
-                       if(l->addable == 3)
-                               n->addable = 3;
-               }
-               break;
-
-       case OASLMUL:
-       case OASMUL:
-               xcom(l);
-               xcom(r);
-               t = vlog(r);
-               if(t >= 0) {
-                       n->op = OASASHL;
-                       r->vconst = t;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OMUL:
-       case OLMUL:
-               xcom(l);
-               xcom(r);
-               t = vlog(r);
-               if(t >= 0) {
-                       n->op = OASHL;
-                       r->vconst = t;
-                       r->type = types[TINT];
-               }
-               t = vlog(l);
-               if(t >= 0) {
-                       n->op = OASHL;
-                       n->left = r;
-                       n->right = l;
-                       r = l;
-                       l = n->left;
-                       r->vconst = t;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OASLDIV:
-               xcom(l);
-               xcom(r);
-               t = vlog(r);
-               if(t >= 0) {
-                       n->op = OASLSHR;
-                       r->vconst = t;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OLDIV:
-               xcom(l);
-               xcom(r);
-               t = vlog(r);
-               if(t >= 0) {
-                       n->op = OLSHR;
-                       r->vconst = t;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OASLMOD:
-               xcom(l);
-               xcom(r);
-               t = vlog(r);
-               if(t >= 0) {
-                       n->op = OASAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OLMOD:
-               xcom(l);
-               xcom(r);
-               t = vlog(r);
-               if(t >= 0) {
-                       n->op = OAND;
-                       r->vconst--;
-               }
-               break;
-
-       default:
-               if(l != Z)
-                       xcom(l);
-               if(r != Z)
-                       xcom(r);
-               break;
-       }
-       if(n->addable >= 10)
-               return;
-
-       if(l != Z)
-               n->complex = l->complex;
-       if(r != Z) {
-               if(r->complex == n->complex)
-                       n->complex = r->complex+1;
-               else
-               if(r->complex > n->complex)
-                       n->complex = r->complex;
-       }
-       if(n->complex == 0)
-               n->complex++;
-
-       if(com64(n))
-               return;
-
-       switch(n->op) {
-       case OFUNC:
-               n->complex = FNX;
-               break;
-
-       case OADD:
-       case OXOR:
-       case OAND:
-       case OOR:
-       case OEQ:
-       case ONE:
-               /*
-                * immediate operators, make const on right
-                */
-               if(l->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-               }
-               break;
-       }
-}
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
deleted file mode 100644 (file)
index f39963b..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-// Inferno utils/5c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
-       Node nreg;
-
-       if(typev[n->type->etype]) {
-               regsalloc(&nreg, n);
-               nreg.type = types[TVLONG];
-               cgen(n, &nreg);
-               swit2(q, nc, def, &nreg);
-               return;
-       }
-
-       regalloc(&nreg, n, Z);
-       nreg.type = types[TLONG];
-       cgen(n, &nreg);
-       swit2(q, nc, def, &nreg);
-       regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
-       C1 *r;
-       int i;
-       int32 v;
-       Prog *sp;
-
-       if(nc >= 3) {
-               i = (q+nc-1)->val - (q+0)->val;
-               if(!nacl && i > 0 && i < nc*2)
-                       goto direct;
-       }
-       if(nc < 5) {
-               for(i=0; i<nc; i++) {
-                       if(debug['W'])
-                               print("case = %.8ux\n", q->val);
-                       gopcode(OEQ, nodconst(q->val), n, Z);
-                       patch(p, q->label);
-                       q++;
-               }
-               gbranch(OGOTO);
-               patch(p, def);
-               return;
-       }
-
-       i = nc / 2;
-       r = q+i;
-       if(debug['W'])
-               print("case > %.8ux\n", r->val);
-       gopcode(OGT, nodconst(r->val), n, Z);
-       sp = p;
-       gopcode(OEQ, nodconst(r->val), n, Z);   /* just gen the B.EQ */
-       patch(p, r->label);
-       swit2(q, i, def, n);
-
-       if(debug['W'])
-               print("case < %.8ux\n", r->val);
-       patch(sp, pc);
-       swit2(r+1, nc-i-1, def, n);
-       return;
-
-direct:
-       v = q->val;
-       if(v != 0)
-               gopcode(OSUB, nodconst(v), Z, n);
-       gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
-       patch(p, def);
-       for(i=0; i<nc; i++) {
-               if(debug['W'])
-                       print("case = %.8ux\n", q->val);
-               while(q->val != v) {
-                       nextpc();
-                       p->as = ABCASE;
-                       patch(p, def);
-                       v++;
-               }
-               nextpc();
-               p->as = ABCASE;
-               patch(p, q->label);
-               q++;
-               v++;
-       }
-       gbranch(OGOTO);         /* so that regopt() won't be confused */
-       patch(p, def);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int sh;
-       int32 v;
-       Node *l;
-
-       /*
-        * n1 gets adjusted/masked value
-        * n2 gets address of cell
-        * n3 gets contents of cell
-        */
-       l = b->left;
-       if(n2 != Z) {
-               regalloc(n1, l, nn);
-               reglcgen(n2, l, Z);
-               regalloc(n3, l, Z);
-               gopcode(OAS, n2, Z, n3);
-               gopcode(OAS, n3, Z, n1);
-       } else {
-               regalloc(n1, l, nn);
-               cgen(l, n1);
-       }
-       if(b->type->shift == 0 && typeu[b->type->etype]) {
-               v = ~0 + (1L << b->type->nbits);
-               gopcode(OAND, nodconst(v), Z, n1);
-       } else {
-               sh = 32 - b->type->shift - b->type->nbits;
-               if(sh > 0)
-                       gopcode(OASHL, nodconst(sh), Z, n1);
-               sh += b->type->shift;
-               if(sh > 0)
-                       if(typeu[b->type->etype])
-                               gopcode(OLSHR, nodconst(sh), Z, n1);
-                       else
-                               gopcode(OASHR, nodconst(sh), Z, n1);
-       }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int32 v;
-       Node nod, *l;
-       int sh;
-
-       /*
-        * n1 has adjusted/masked value
-        * n2 has address of cell
-        * n3 has contents of cell
-        */
-       l = b->left;
-       regalloc(&nod, l, Z);
-       v = ~0 + (1L << b->type->nbits);
-       gopcode(OAND, nodconst(v), Z, n1);
-       gopcode(OAS, n1, Z, &nod);
-       if(nn != Z)
-               gopcode(OAS, n1, Z, nn);
-       sh = b->type->shift;
-       if(sh > 0)
-               gopcode(OASHL, nodconst(sh), Z, &nod);
-       v <<= sh;
-       gopcode(OAND, nodconst(~v), Z, n3);
-       gopcode(OOR, n3, Z, &nod);
-       gopcode(OAS, &nod, Z, n2);
-
-       regfree(&nod);
-       regfree(n1);
-       regfree(n2);
-       regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
-       int32 r;
-
-       if(suppress)
-               return nstring;
-       r = nstring;
-       while(n) {
-               string[mnstring] = *s++;
-               mnstring++;
-               nstring++;
-               if(mnstring >= NSNAME) {
-                       gpseudo(ADATA, symstring, nodconst(0L));
-                       p->from.offset += nstring - NSNAME;
-                       p->reg = NSNAME;
-                       p->to.type = D_SCONST;
-                       memmove(p->to.u.sval, string, NSNAME);
-                       mnstring = 0;
-               }
-               n--;
-       }
-       return r;
-}
-
-int
-mulcon(Node *n, Node *nn)
-{
-       Node *l, *r, nod1, nod2;
-       Multab *m;
-       int32 v, vs;
-       int o;
-       char code[sizeof(m->code)+2], *p;
-
-       if(typefd[n->type->etype])
-               return 0;
-       l = n->left;
-       r = n->right;
-       if(l->op == OCONST) {
-               l = r;
-               r = n->left;
-       }
-       if(r->op != OCONST)
-               return 0;
-       v = convvtox(r->vconst, n->type->etype);
-       if(v != r->vconst) {
-               if(debug['M'])
-                       print("%L multiply conv: %lld\n", n->lineno, r->vconst);
-               return 0;
-       }
-       m = mulcon0(v);
-       if(!m) {
-               if(debug['M'])
-                       print("%L multiply table: %lld\n", n->lineno, r->vconst);
-               return 0;
-       }
-       if(debug['M'] && debug['v'])
-               print("%L multiply: %d\n", n->lineno, v);
-
-       memmove(code, m->code, sizeof(m->code));
-       code[sizeof(m->code)] = 0;
-
-       p = code;
-       if(p[1] == 'i')
-               p += 2;
-       regalloc(&nod1, n, nn);
-       cgen(l, &nod1);
-       vs = v;
-       regalloc(&nod2, n, Z);
-
-loop:
-       switch(*p) {
-       case 0:
-               regfree(&nod2);
-               if(vs < 0) {
-                       gopcode(OAS, &nod1, Z, &nod1);
-                       gopcode(OSUB, &nod1, nodconst(0), nn);
-               } else
-                       gopcode(OAS, &nod1, Z, nn);
-               regfree(&nod1);
-               return 1;
-       case '+':
-               o = OADD;
-               goto addsub;
-       case '-':
-               o = OSUB;
-       addsub: /* number is r,n,l */
-               v = p[1] - '0';
-               r = &nod1;
-               if(v&4)
-                       r = &nod2;
-               n = &nod1;
-               if(v&2)
-                       n = &nod2;
-               l = &nod1;
-               if(v&1)
-                       l = &nod2;
-               gopcode(o, l, n, r);
-               break;
-       default: /* op is shiftcount, number is r,l */
-               v = p[1] - '0';
-               r = &nod1;
-               if(v&2)
-                       r = &nod2;
-               l = &nod1;
-               if(v&1)
-                       l = &nod2;
-               v = *p - 'a';
-               if(v < 0 || v >= 32) {
-                       diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
-                       break;
-               }
-               gopcode(OASHL, nodconst(v), l, r);
-               break;
-       }
-       p += 2;
-       goto loop;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       int32 e, lw;
-
-       for(e=0; e<w; e+=NSNAME) {
-               lw = NSNAME;
-               if(w-e < lw)
-                       lw = w-e;
-               gpseudo(ADATA, s, nodconst(0));
-               p->from.offset += o+e;
-               p->reg = lw;
-               p->to.type = D_SCONST;
-               memmove(p->to.u.sval, a->cstring+e, lw);
-       }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
-
-       if(a->op == OCONST && typev[a->type->etype]) {
-               if(isbigendian)
-                       gpseudo(ADATA, s, nod32const(a->vconst>>32));
-               else
-                       gpseudo(ADATA, s, nod32const(a->vconst));
-               p->from.offset += o;
-               p->reg = 4;
-               if(isbigendian)
-                       gpseudo(ADATA, s, nod32const(a->vconst));
-               else
-                       gpseudo(ADATA, s, nod32const(a->vconst>>32));
-               p->from.offset += o + 4;
-               p->reg = 4;
-               return;
-       }
-       gpseudo(ADATA, s, a);
-       p->from.offset += o;
-       p->reg = w;
-       if(p->to.type == D_OREG)
-               p->to.type = D_CONST;
-}
-
-void
-outcode(void)
-{
-       Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       if(pragcgobuf.to > pragcgobuf.start) {
-               Bprint(&outbuf, "\n");
-               Bprint(&outbuf, "$$  // exports\n\n");
-               Bprint(&outbuf, "$$  // local types\n\n");
-               Bprint(&outbuf, "$$  // cgo\n");
-               Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
-               Bprint(&outbuf, "\n$$\n\n");
-       }
-       Bprint(&outbuf, "!\n");
-
-       writeobj(ctxt, &outbuf);
-       lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
-       int32 o;
-       Type *v;
-       int w, packw;
-
-       o = i;
-       w = 1;
-       packw = 0;
-       switch(op) {
-       default:
-               diag(Z, "unknown align opcode %d", op);
-               break;
-
-       case Asu2:      /* padding at end of a struct */
-               w = *maxalign;
-               if(w < 1)
-                       w = 1;
-               if(packflg)
-                       packw = packflg;
-               break;
-
-       case Ael1:      /* initial align of struct element */
-               for(v=t; v->etype==TARRAY; v=v->link)
-                       ;
-               if(v->etype == TSTRUCT || v->etype == TUNION)
-                       w = v->align;
-               else {
-                       w = ewidth[v->etype];
-                       if(w == 8)
-                               w = 4;
-               }
-               if(w < 1 || w > SZ_LONG)
-                       fatal(Z, "align");
-               if(packflg) 
-                       packw = packflg;
-               break;
-
-       case Ael2:      /* width of a struct element */
-               o += t->width;
-               break;
-
-       case Aarg0:     /* initial passbyptr argument in arg list */
-               if(typesuv[t->etype]) {
-                       o = align(o, types[TIND], Aarg1, nil);
-                       o = align(o, types[TIND], Aarg2, nil);
-               }
-               break;
-
-       case Aarg1:     /* initial align of parameter */
-               w = ewidth[t->etype];
-               if(w <= 0 || w >= SZ_LONG) {
-                       w = SZ_LONG;
-                       break;
-               }
-               w = 1;          /* little endian no adjustment */
-               break;
-
-       case Aarg2:     /* width of a parameter */
-               o += t->width;
-               w = t->width;
-               if(w > SZ_LONG)
-                       w = SZ_LONG;
-               break;
-
-       case Aaut3:     /* total align of automatic */
-               o = align(o, t, Ael2, nil);
-               o = align(o, t, Ael1, nil);
-               w = SZ_LONG;    /* because of a pun in cc/dcl.c:contig() */
-               break;
-       }
-       if(packw != 0 && xround(o, w) != xround(o, packw))
-               diag(Z, "#pragma pack changes offset of %T", t);
-       o = xround(o, w);
-       if(maxalign != nil && *maxalign < w)
-               *maxalign = w;
-       if(debug['A'])
-               print("align %s %d %T = %d\n", bnames[op], i, t, o);
-       return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
-       v = xround(v, SZ_LONG);
-       if(v > max)
-               return v;
-       return max;
-}
diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c
deleted file mode 100644 (file)
index af40220..0000000
+++ /dev/null
@@ -1,1361 +0,0 @@
-// Inferno utils/5c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-
-int thechar = '5';
-char *thestring = "arm";
-
-LinkArch       *thelinkarch = &linkarm;
-
-void
-linkarchinit(void)
-{
-}
-
-void
-ginit(void)
-{
-       Type *t;
-
-       exregoffset = REGEXT;
-       exfregoffset = FREGEXT;
-       listinit();
-       nstring = 0;
-       mnstring = 0;
-       nrathole = 0;
-       pc = 0;
-       breakpc = -1;
-       continpc = -1;
-       cases = C;
-       lastp = P;
-       tfield = types[TLONG];
-
-       zprog.link = P;
-       zprog.as = AGOK;
-       zprog.reg = NREG;
-       zprog.from.type = D_NONE;
-       zprog.from.name = D_NONE;
-       zprog.from.reg = NREG;
-       zprog.to = zprog.from;
-       zprog.scond = 0xE;
-
-       regnode.op = OREGISTER;
-       regnode.class = CEXREG;
-       regnode.reg = REGTMP;
-       regnode.complex = 0;
-       regnode.addable = 11;
-       regnode.type = types[TLONG];
-
-       constnode.op = OCONST;
-       constnode.class = CXXX;
-       constnode.complex = 0;
-       constnode.addable = 20;
-       constnode.type = types[TLONG];
-
-       fconstnode.op = OCONST;
-       fconstnode.class = CXXX;
-       fconstnode.complex = 0;
-       fconstnode.addable = 20;
-       fconstnode.type = types[TDOUBLE];
-
-       nodsafe = new(ONAME, Z, Z);
-       nodsafe->sym = slookup(".safe");
-       nodsafe->type = types[TINT];
-       nodsafe->etype = types[TINT]->etype;
-       nodsafe->class = CAUTO;
-       complex(nodsafe);
-
-       t = typ(TARRAY, types[TCHAR]);
-       symrathole = slookup(".rathole");
-       symrathole->class = CGLOBL;
-       symrathole->type = t;
-
-       nodrat = new(ONAME, Z, Z);
-       nodrat->sym = symrathole;
-       nodrat->type = types[TIND];
-       nodrat->etype = TVOID;
-       nodrat->class = CGLOBL;
-       complex(nodrat);
-       nodrat->type = t;
-
-       nodret = new(ONAME, Z, Z);
-       nodret->sym = slookup(".ret");
-       nodret->type = types[TIND];
-       nodret->etype = TIND;
-       nodret->class = CPARAM;
-       nodret = new(OIND, nodret, Z);
-       complex(nodret);
-
-       com64init();
-
-       memset(reg, 0, sizeof(reg));
-}
-
-void
-gclean(void)
-{
-       int i;
-       Sym *s;
-
-       for(i=0; i<NREG; i++)
-               if(reg[i])
-                       diag(Z, "reg %d left allocated", i);
-       for(i=NREG; i<NREG+NFREG; i++)
-               if(reg[i])
-                       diag(Z, "freg %d left allocated", i-NREG);
-       while(mnstring)
-               outstring("", 1L);
-       symstring->type->width = nstring;
-       symrathole->type->width = nrathole;
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->link) {
-               if(s->type == T)
-                       continue;
-               if(s->type->width == 0)
-                       continue;
-               if(s->class != CGLOBL && s->class != CSTATIC)
-                       continue;
-               if(s->type == types[TENUM])
-                       continue;
-               gpseudo(AGLOBL, s, nodconst(s->type->width));
-       }
-       nextpc();
-       p->as = AEND;
-       outcode();
-}
-
-void
-nextpc(void)
-{
-       Plist *pl;
-
-       p = alloc(sizeof(*p));
-       *p = zprog;
-       p->lineno = nearln;
-       pc++;
-       if(lastp == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastp->link = p;
-       lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
-       int32 regs;
-       Node fnxargs[20], *fnxp;
-
-       regs = cursafe;
-
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 0, &fnxp);   /* compile fns to temps */
-
-       curarg = 0;
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 1, &fnxp);   /* compile normal args and temps */
-
-       cursafe = regs;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
-       Node nod;
-
-       if(n == Z)
-               return;
-       if(n->op == OLIST) {
-               garg1(n->left, tn1, tn2, f, fnxp);
-               garg1(n->right, tn1, tn2, f, fnxp);
-               return;
-       }
-       if(f == 0) {
-               if(n->complex >= FNX) {
-                       regsalloc(*fnxp, n);
-                       nod = znode;
-                       nod.op = OAS;
-                       nod.left = *fnxp;
-                       nod.right = n;
-                       nod.type = n->type;
-                       cgen(&nod, Z);
-                       (*fnxp)++;
-               }
-               return;
-       }
-       if(typesuv[n->type->etype]) {
-               regaalloc(tn2, n);
-               if(n->complex >= FNX) {
-                       sugen(*fnxp, tn2, n->type->width);
-                       (*fnxp)++;
-               } else
-                       sugen(n, tn2, n->type->width);
-               return;
-       }
-       if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) {
-               regaalloc1(tn1, n);
-               if(n->complex >= FNX) {
-                       cgen(*fnxp, tn1);
-                       (*fnxp)++;
-               } else
-                       cgen(n, tn1);
-               return;
-       }
-       regalloc(tn1, n, Z);
-       if(n->complex >= FNX) {
-               cgen(*fnxp, tn1);
-               (*fnxp)++;
-       } else
-               cgen(n, tn1);
-       regaalloc(tn2, n);
-       gopcode(OAS, tn1, Z, tn2);
-       regfree(tn1);
-}
-
-Node*
-nodconst(int32 v)
-{
-       constnode.vconst = v;
-       return &constnode;
-}
-
-Node*
-nod32const(vlong v)
-{
-       constnode.vconst = v & MASK(32);
-       return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
-       fconstnode.fconst = d;
-       return &fconstnode;
-}
-
-void
-nodreg(Node *n, Node *nn, int reg)
-{
-       *n = regnode;
-       n->reg = reg;
-       n->type = nn->type;
-       n->lineno = nn->lineno;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
-       int r;
-
-       if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
-               r = REGRET;
-               if(typefd[nn->type->etype])
-                       r = FREGRET+NREG;
-               nodreg(n, nn, r);
-               reg[r]++;
-               return;
-       }
-       
-       if(mode == 1) {
-               // fetch returned value after call.
-               // already called gargs, so curarg is set.
-               curarg = (curarg+3) & ~3;
-               regaalloc(n, nn);
-               return;
-       }
-       
-       if(mode == 2) {
-               // store value to be returned.
-               // must compute arg offset.
-               if(t->etype != TFUNC)
-                       fatal(Z, "bad regret func %T", t);
-               *n = *nn;
-               n->op = ONAME;
-               n->class = CPARAM;
-               n->sym = slookup(".ret");
-               n->complex = nodret->complex;
-               n->xoffset = argsize(0);
-               n->addable = 20;
-               return;
-       }
-       
-       fatal(Z, "bad regret");
-}
-
-int
-tmpreg(void)
-{
-       int i;
-
-       for(i=REGRET+1; i<NREG; i++)
-               if(reg[i] == 0)
-                       return i;
-       diag(Z, "out of fixed registers");
-       return 0;
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
-       int i;
-
-       switch(tn->type->etype) {
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i >= 0 && i < NREG)
-                               goto out;
-               }
-               for(i=REGRET+1; i<=REGEXT-2; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               diag(tn, "out of fixed registers");
-               goto err;
-
-       case TFLOAT:
-       case TDOUBLE:
-       case TVLONG:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i >= NREG && i < NREG+NFREG)
-                               goto out;
-               }
-               for(i=NREG; i<NREG+NFREG; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               diag(tn, "out of float registers");
-               goto err;
-       }
-       diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
-       nodreg(n, tn, 0);
-       return;
-out:
-       reg[i]++;
-       nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
-       Node nod;
-
-       nod = *tn;
-       nod.type = types[TIND];
-       regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-
-       i = 0;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               goto err;
-       i = n->reg;
-       if(i < 0 || i >= nelem(reg))
-               goto err;
-       if(reg[i] <= 0)
-               goto err;
-       reg[i]--;
-       return;
-err:
-       diag(n, "error in regfree: %d", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
-       cursafe = align(cursafe, nn->type, Aaut3, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-       *n = *nodsafe;
-       n->xoffset = -(stkoff + cursafe);
-       n->type = nn->type;
-       n->etype = nn->type->etype;
-       n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
-       if(REGARG < 0) {
-               fatal(n, "regaalloc1 and REGARG<0");
-               return;
-       }
-       nodreg(n, nn, REGARG);
-       reg[REGARG]++;
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       *n = *nn;
-       n->op = OINDREG;
-       n->reg = REGSP;
-       n->xoffset = curarg + SZ_LONG;
-       n->complex = 0;
-       n->addable = 20;
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
-       if(n->op != OREGISTER) {
-               diag(n, "regind not OREGISTER");
-               return;
-       }
-       n->op = OINDREG;
-       n->type = nn->type;
-}
-
-void
-raddr(Node *n, Prog *p)
-{
-       Addr a;
-
-       naddr(n, &a);
-       if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
-               a.type = D_REG;
-               a.reg = 0;
-       }
-       if(a.type != D_REG && a.type != D_FREG) {
-               if(n)
-                       diag(n, "bad in raddr: %O", n->op);
-               else
-                       diag(n, "bad in raddr: <null>");
-               p->reg = NREG;
-       } else
-               p->reg = a.reg;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
-       int32 v;
-
-       a->type = D_NONE;
-       if(n == Z)
-               return;
-       switch(n->op) {
-       default:
-       bad:
-               diag(n, "bad in naddr: %O", n->op);
-               break;
-
-       case OREGISTER:
-               a->type = D_REG;
-               a->sym = nil;
-               a->reg = n->reg;
-               if(a->reg >= NREG) {
-                       a->type = D_FREG;
-                       a->reg -= NREG;
-               }
-               break;
-
-       case OIND:
-               naddr(n->left, a);
-               if(a->type == D_REG) {
-                       a->type = D_OREG;
-                       break;
-               }
-               if(a->type == D_CONST) {
-                       a->type = D_OREG;
-                       break;
-               }
-               goto bad;
-
-       case OINDREG:
-               a->type = D_OREG;
-               a->sym = nil;
-               a->offset = n->xoffset;
-               a->reg = n->reg;
-               break;
-
-       case ONAME:
-               a->etype = n->etype;
-               a->type = D_OREG;
-               a->name = D_STATIC;
-               a->sym = linksym(n->sym);
-               a->offset = n->xoffset;
-               if(n->class == CSTATIC)
-                       break;
-               if(n->class == CEXTERN || n->class == CGLOBL) {
-                       a->name = D_EXTERN;
-                       break;
-               }
-               if(n->class == CAUTO) {
-                       a->name = D_AUTO;
-                       break;
-               }
-               if(n->class == CPARAM) {
-                       a->name = D_PARAM;
-                       break;
-               }
-               goto bad;
-
-       case OCONST:
-               a->sym = nil;
-               a->reg = NREG;
-               if(typefd[n->type->etype]) {
-                       a->type = D_FCONST;
-                       a->u.dval = n->fconst;
-               } else {
-                       a->type = D_CONST;
-                       a->offset = n->vconst;
-               }
-               break;
-
-       case OADDR:
-               naddr(n->left, a);
-               if(a->type == D_OREG) {
-                       a->type = D_CONST;
-                       break;
-               }
-               goto bad;
-
-       case OADD:
-               if(n->left->op == OCONST) {
-                       naddr(n->left, a);
-                       v = a->offset;
-                       naddr(n->right, a);
-               } else {
-                       naddr(n->right, a);
-                       v = a->offset;
-                       naddr(n->left, a);
-               }
-               a->offset += v;
-               break;
-
-       }
-}
-
-void
-fop(int as, int f1, int f2, Node *t)
-{
-       Node nod1, nod2, nod3;
-
-       nodreg(&nod1, t, NREG+f1);
-       nodreg(&nod2, t, NREG+f2);
-       regalloc(&nod3, t, t);
-       gopcode(as, &nod1, &nod2, &nod3);
-       gmove(&nod3, t);
-       regfree(&nod3);
-}
-
-void
-gmovm(Node *f, Node *t, int w)
-{
-       gins(AMOVM, f, t);
-       p->scond |= C_UBIT;
-       if(w)
-               p->scond |= C_WBIT;
-}
-
-void
-gmove(Node *f, Node *t)
-{
-       int ft, tt, a;
-       Node nod, nod1;
-       Prog *p1;
-
-       ft = f->type->etype;
-       tt = t->type->etype;
-
-       if(ft == TDOUBLE && f->op == OCONST) {
-       }
-       if(ft == TFLOAT && f->op == OCONST) {
-       }
-
-       /*
-        * a load --
-        * put it into a register then
-        * worry what to do with it.
-        */
-       if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
-               switch(ft) {
-               default:
-                       a = AMOVW;
-                       break;
-               case TFLOAT:
-                       a = AMOVF;
-                       break;
-               case TDOUBLE:
-                       a = AMOVD;
-                       break;
-               case TCHAR:
-                       a = AMOVBS;
-                       break;
-               case TUCHAR:
-                       a = AMOVBU;
-                       break;
-               case TSHORT:
-                       a = AMOVHS;
-                       break;
-               case TUSHORT:
-                       a = AMOVHU;
-                       break;
-               }
-               if(typechlp[ft] && typeilp[tt])
-                       regalloc(&nod, t, t);
-               else
-                       regalloc(&nod, f, t);
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-       }
-
-       /*
-        * a store --
-        * put it into a register then
-        * store it.
-        */
-       if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
-               switch(tt) {
-               default:
-                       a = AMOVW;
-                       break;
-               case TUCHAR:
-                       a = AMOVBU;
-                       break;
-               case TCHAR:
-                       a = AMOVBS;
-                       break;
-               case TUSHORT:
-                       a = AMOVHU;
-                       break;
-               case TSHORT:
-                       a = AMOVHS;
-                       break;
-               case TFLOAT:
-                       a = AMOVF;
-                       break;
-               case TVLONG:
-               case TDOUBLE:
-                       a = AMOVD;
-                       break;
-               }
-               if(ft == tt)
-                       regalloc(&nod, t, f);
-               else
-                       regalloc(&nod, t, Z);
-               gmove(f, &nod);
-               gins(a, &nod, t);
-               regfree(&nod);
-               return;
-       }
-
-       /*
-        * type x type cross table
-        */
-       a = AGOK;
-       switch(ft) {
-       case TDOUBLE:
-       case TVLONG:
-       case TFLOAT:
-               switch(tt) {
-               case TDOUBLE:
-               case TVLONG:
-                       a = AMOVD;
-                       if(ft == TFLOAT)
-                               a = AMOVFD;
-                       break;
-               case TFLOAT:
-                       a = AMOVDF;
-                       if(ft == TFLOAT)
-                               a = AMOVF;
-                       break;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TIND:
-                       a = AMOVDW;
-                       if(ft == TFLOAT)
-                               a = AMOVFW;
-                       break;
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVDW;
-                       if(ft == TFLOAT)
-                               a = AMOVFW;
-                       break;
-               }
-               break;
-       case TUINT:
-       case TULONG:
-               if(tt == TFLOAT || tt == TDOUBLE) {
-                       // ugly and probably longer than necessary,
-                       // but vfp has a single instruction for this,
-                       // so hopefully it won't last long.
-                       //
-                       //      tmp = f
-                       //      tmp1 = tmp & 0x80000000
-                       //      tmp ^= tmp1
-                       //      t = float(int32(tmp))
-                       //      if(tmp1)
-                       //              t += 2147483648.
-                       //
-                       regalloc(&nod, f, Z);
-                       regalloc(&nod1, f, Z);
-                       gins(AMOVW, f, &nod);
-                       gins(AMOVW, &nod, &nod1);
-                       gins(AAND, nodconst(0x80000000), &nod1);
-                       gins(AEOR, &nod1, &nod);
-                       if(tt == TFLOAT)
-                               gins(AMOVWF, &nod, t);
-                       else
-                               gins(AMOVWD, &nod, t);
-                       gins(ACMP, nodconst(0), Z);
-                       raddr(&nod1, p);
-                       gins(ABEQ, Z, Z);
-                       regfree(&nod);
-                       regfree(&nod1);
-                       p1 = p;
-                       regalloc(&nod, t, Z);
-                       gins(AMOVF, nodfconst(2147483648.), &nod);
-                       gins(AADDF, &nod, t);
-                       regfree(&nod);
-                       patch(p1, pc);
-                       return;
-               }
-               // fall through
-       
-       case TINT:
-       case TLONG:
-       case TIND:
-               switch(tt) {
-               case TDOUBLE:
-                       gins(AMOVWD, f, t);
-                       return;
-               case TFLOAT:
-                       gins(AMOVWF, f, t);
-                       return;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVW;
-                       break;
-               }
-               break;
-       case TSHORT:
-               switch(tt) {
-               case TDOUBLE:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVHS, f, &nod);
-                       gins(AMOVWD, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TFLOAT:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVHS, f, &nod);
-                       gins(AMOVWF, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TUINT:
-               case TINT:
-               case TULONG:
-               case TLONG:
-               case TIND:
-                       a = AMOVHS;
-                       break;
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVW;
-                       break;
-               }
-               break;
-       case TUSHORT:
-               switch(tt) {
-               case TDOUBLE:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVHU, f, &nod);
-                       gins(AMOVWD, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TFLOAT:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVHU, f, &nod);
-                       gins(AMOVWF, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TIND:
-                       a = AMOVHU;
-                       break;
-               case TSHORT:
-               case TUSHORT:
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVW;
-                       break;
-               }
-               break;
-       case TCHAR:
-               switch(tt) {
-               case TDOUBLE:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVBS, f, &nod);
-                       gins(AMOVWD, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TFLOAT:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVBS, f, &nod);
-                       gins(AMOVWF, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-                       a = AMOVBS;
-                       break;
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVW;
-                       break;
-               }
-               break;
-       case TUCHAR:
-               switch(tt) {
-               case TDOUBLE:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVBU, f, &nod);
-                       gins(AMOVWD, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TFLOAT:
-                       regalloc(&nod, f, Z);
-                       gins(AMOVBU, f, &nod);
-                       gins(AMOVWF, &nod, t);
-                       regfree(&nod);
-                       return;
-               case TINT:
-               case TUINT:
-               case TLONG:
-               case TULONG:
-               case TIND:
-               case TSHORT:
-               case TUSHORT:
-                       a = AMOVBU;
-                       break;
-               case TCHAR:
-               case TUCHAR:
-                       a = AMOVW;
-                       break;
-               }
-               break;
-       }
-       if(a == AGOK)
-               diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
-       if(a == AMOVW || a == AMOVF || a == AMOVD)
-       if(samaddr(f, t))
-               return;
-       gins(a, f, t);
-}
-
-void
-gmover(Node *f, Node *t)
-{
-       int ft, tt, a;
-
-       ft = f->type->etype;
-       tt = t->type->etype;
-       a = AGOK;
-       if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){
-               switch(tt){
-               case TSHORT:
-                       a = AMOVHS;
-                       break;
-               case TUSHORT:
-                       a = AMOVHU;
-                       break;
-               case TCHAR:
-                       a = AMOVBS;
-                       break;
-               case TUCHAR:
-                       a = AMOVBU;
-                       break;
-               }
-       }
-       if(a == AGOK)
-               gmove(f, t);
-       else
-               gins(a, f, t);
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
-       nextpc();
-       p->as = a;
-       if(f != Z)
-               naddr(f, &p->from);
-       if(t != Z)
-               naddr(t, &p->to);
-       if(debug['g'])
-               print("%P\n", p);
-}
-
-void
-gopcode(int o, Node *f1, Node *f2, Node *t)
-{
-       int a, et;
-       Addr ta;
-
-       et = TLONG;
-       if(f1 != Z && f1->type != T)
-               et = f1->type->etype;
-       a = AGOK;
-       switch(o) {
-       case OAS:
-               gmove(f1, t);
-               return;
-
-       case OASADD:
-       case OADD:
-               a = AADD;
-               if(et == TFLOAT)
-                       a = AADDF;
-               else
-               if(et == TDOUBLE || et == TVLONG)
-                       a = AADDD;
-               break;
-
-       case OASSUB:
-       case OSUB:
-               if(f2 && f2->op == OCONST) {
-                       Node *t = f1;
-                       f1 = f2;
-                       f2 = t;
-                       a = ARSB;
-               } else
-                       a = ASUB;
-               if(et == TFLOAT)
-                       a = ASUBF;
-               else
-               if(et == TDOUBLE || et == TVLONG)
-                       a = ASUBD;
-               break;
-
-       case OASOR:
-       case OOR:
-               a = AORR;
-               break;
-
-       case OASAND:
-       case OAND:
-               a = AAND;
-               break;
-
-       case OASXOR:
-       case OXOR:
-               a = AEOR;
-               break;
-
-       case OASLSHR:
-       case OLSHR:
-               a = ASRL;
-               break;
-
-       case OASASHR:
-       case OASHR:
-               a = ASRA;
-               break;
-
-       case OASASHL:
-       case OASHL:
-               a = ASLL;
-               break;
-
-       case OFUNC:
-               a = ABL;
-               break;
-
-       case OASMUL:
-       case OMUL:
-               a = AMUL;
-               if(et == TFLOAT)
-                       a = AMULF;
-               else
-               if(et == TDOUBLE || et == TVLONG)
-                       a = AMULD;
-               break;
-
-       case OASDIV:
-       case ODIV:
-               a = ADIV;
-               if(et == TFLOAT)
-                       a = ADIVF;
-               else
-               if(et == TDOUBLE || et == TVLONG)
-                       a = ADIVD;
-               break;
-
-       case OASMOD:
-       case OMOD:
-               a = AMOD;
-               break;
-
-       case OASLMUL:
-       case OLMUL:
-               a = AMULU;
-               break;
-
-       case OASLMOD:
-       case OLMOD:
-               a = AMODU;
-               break;
-
-       case OASLDIV:
-       case OLDIV:
-               a = ADIVU;
-               break;
-
-       case OCASE:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHS:
-       case OHI:
-               a = ACMP;
-               if(et == TFLOAT)
-                       a = ACMPF;
-               else
-               if(et == TDOUBLE || et == TVLONG)
-                       a = ACMPD;
-               nextpc();
-               p->as = a;
-               naddr(f1, &p->from);
-               if(a == ACMP && f1->op == OCONST && p->from.offset < 0) {
-                       p->as = ACMN;
-                       p->from.offset = -p->from.offset;
-               }
-               raddr(f2, p);
-               switch(o) {
-               case OEQ:
-                       a = ABEQ;
-                       break;
-               case ONE:
-                       a = ABNE;
-                       break;
-               case OLT:
-                       a = ABLT;
-                       break;
-               case OLE:
-                       a = ABLE;
-                       break;
-               case OGE:
-                       a = ABGE;
-                       break;
-               case OGT:
-                       a = ABGT;
-                       break;
-               case OLO:
-                       a = ABLO;
-                       break;
-               case OLS:
-                       a = ABLS;
-                       break;
-               case OHS:
-                       a = ABHS;
-                       break;
-               case OHI:
-                       a = ABHI;
-                       break;
-               case OCASE:
-                       nextpc();
-                       p->as = ACASE;
-                       p->scond = 0x9;
-                       naddr(f2, &p->from);
-                       a = ABHI;
-                       break;
-               }
-               f1 = Z;
-               f2 = Z;
-               break;
-       }
-       if(a == AGOK)
-               diag(Z, "bad in gopcode %O", o);
-       nextpc();
-       p->as = a;
-       if(f1 != Z)
-               naddr(f1, &p->from);
-       if(f2 != Z) {
-               naddr(f2, &ta);
-               p->reg = ta.reg;
-       }
-       if(t != Z)
-               naddr(t, &p->to);
-       if(debug['g'])
-               print("%P\n", p);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
-       if(f->op != t->op)
-               return 0;
-       switch(f->op) {
-
-       case OREGISTER:
-               if(f->reg != t->reg)
-                       break;
-               return 1;
-       }
-       return 0;
-}
-
-void
-gbranch(int o)
-{
-       int a;
-
-       a = AGOK;
-       switch(o) {
-       case ORETURN:
-               a = ARET;
-               break;
-       case OGOTO:
-               a = AB;
-               break;
-       }
-       nextpc();
-       if(a == AGOK) {
-               diag(Z, "bad in gbranch %O",  o);
-               nextpc();
-       }
-       p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
-
-       op->to.offset = pc;
-       op->to.type = D_BRANCH;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-       nextpc();
-       p->as = a;
-       p->from.type = D_OREG;
-       p->from.sym = linksym(s);
-       p->from.name = D_EXTERN;
-
-       switch(a) {
-       case ATEXT:
-               p->reg = textflag;
-               textflag = 0;
-               break;
-       case AGLOBL:
-               p->reg = s->dataflag;
-               break;
-       }
-
-       if(s->class == CSTATIC)
-               p->from.name = D_STATIC;
-       naddr(n, &p->to);
-       if(a == ADATA || a == AGLOBL)
-               pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
-       Node n1;
-       
-       n1 = *nodconst(index);
-       gins(APCDATA, &n1, nodconst(value));
-}
-
-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)
-{
-       vlong vv;
-
-       if(n->op == OCONST) {
-               if(!typefd[n->type->etype]) {
-                       vv = n->vconst;
-                       if(vv >= (vlong)(-32766) && vv < (vlong)32766)
-                               return 1;
-                       /*
-                        * should be specialised for constant values which will
-                        * fit in different instructionsl; for now, let 5l
-                        * sort it out
-                        */
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-int
-sval(int32 v)
-{
-       int i;
-
-       for(i=0; i<16; i++) {
-               if((v & ~0xff) == 0)
-                       return 1;
-               if((~v & ~0xff) == 0)
-                       return 1;
-               v = (v<<2) | ((uint32)v>>30);
-       }
-       return 0;
-}
-
-int32
-exreg(Type *t)
-{
-       int32 o;
-
-       if(typechlp[t->etype]) {
-               if(exregoffset <= REGEXT-4)
-                       return 0;
-               o = exregoffset;
-               exregoffset--;
-               return o;
-       }
-       if(typefd[t->etype]) {
-               if(exfregoffset <= NFREG-1)
-                       return 0;
-               o = exfregoffset + NREG;
-               exfregoffset--;
-               return o;
-       }
-       return 0;
-}
-
-schar  ewidth[NTYPE] =
-{
-       -1,             /* [TXXX] */
-       SZ_CHAR,        /* [TCHAR] */
-       SZ_CHAR,        /* [TUCHAR] */
-       SZ_SHORT,       /* [TSHORT] */
-       SZ_SHORT,       /* [TUSHORT] */
-       SZ_INT,         /* [TINT] */
-       SZ_INT,         /* [TUINT] */
-       SZ_LONG,        /* [TLONG] */
-       SZ_LONG,        /* [TULONG] */
-       SZ_VLONG,       /* [TVLONG] */
-       SZ_VLONG,       /* [TUVLONG] */
-       SZ_FLOAT,       /* [TFLOAT] */
-       SZ_DOUBLE,      /* [TDOUBLE] */
-       SZ_IND,         /* [TIND] */
-       0,              /* [TFUNC] */
-       -1,             /* [TARRAY] */
-       0,              /* [TVOID] */
-       -1,             /* [TSTRUCT] */
-       -1,             /* [TUNION] */
-       SZ_INT,         /* [TENUM] */
-};
-
-int32  ncast[NTYPE] =
-{
-       0,                              /* [TXXX] */
-       BCHAR|BUCHAR,                   /* [TCHAR] */
-       BCHAR|BUCHAR,                   /* [TUCHAR] */
-       BSHORT|BUSHORT,                 /* [TSHORT] */
-       BSHORT|BUSHORT,                 /* [TUSHORT] */
-       BINT|BUINT|BLONG|BULONG|BIND,   /* [TINT] */
-       BINT|BUINT|BLONG|BULONG|BIND,   /* [TUINT] */
-       BINT|BUINT|BLONG|BULONG|BIND,   /* [TLONG] */
-       BINT|BUINT|BLONG|BULONG|BIND,   /* [TULONG] */
-       BVLONG|BUVLONG,                 /* [TVLONG] */
-       BVLONG|BUVLONG,                 /* [TUVLONG] */
-       BFLOAT,                         /* [TFLOAT] */
-       BDOUBLE,                        /* [TDOUBLE] */
-       BLONG|BULONG|BIND,              /* [TIND] */
-       0,                              /* [TFUNC] */
-       0,                              /* [TARRAY] */
-       0,                              /* [TVOID] */
-       BSTRUCT,                        /* [TSTRUCT] */
-       BUNION,                         /* [TUNION] */
-       0,                              /* [TENUM] */
-};
index 5e988878f7d58e4efe8f078fdbfea9be41501291..65f731685e6eac2ed129bcdf4a237740a7c40323 100644 (file)
@@ -86,7 +86,7 @@ datagostring(Strlit *sval, Addr *a)
        sym = stringsym(sval->s, sval->len);
        a->type = D_OREG;
        a->name = D_EXTERN;
-       a->etype = TINT32;
+       a->etype = TSTRING;
        a->offset = 0;  // header
        a->reg = NREG;
        a->sym = linksym(sym);
index 06e274e14da4e61cd0e7bf6346d867b3622a7c38..f09197963ca3e0215241520b8b9e7e98d059ce31 100644 (file)
@@ -1353,9 +1353,10 @@ naddr(Node *n, Addr *a, int canemitcode)
        case OITAB:
                // itable of interface value
                naddr(n->left, a, canemitcode);
-               a->etype = TINT32;
+               a->etype = simtype[tptr];
                if(a->type == D_CONST && a->offset == 0)
                        break;  // len(nil)
+               a->width = widthptr;
                break;
 
        case OSPTR:
index 1946c1d33cdb6c76cec641951cc53ced100c3202..a606f1d3105e969afc034d7cafe42f2fa09653c0 100644 (file)
@@ -63,8 +63,8 @@ enum
 
 uint32 BLOAD(Reg*);
 uint32 BSTORE(Reg*);
-uint32 LOAD(Reg*);
-uint32 STORE(Reg*);
+uint64 LOAD(Reg*);
+uint64 STORE(Reg*);
 */
 
 // A Reg is a wrapper around a single Prog (one instruction) that holds
@@ -75,12 +75,18 @@ struct      Reg
 {
        Flow    f;
 
-       Bits    set;            // variables written by this instruction.
-       Bits    use1;           // variables read by prog->from.
-       Bits    use2;           // variables read by prog->to.
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
 
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
        Bits    refbehind;
        Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
        Bits    calbehind;
        Bits    calahead;
        Bits    regdiff;
@@ -93,6 +99,16 @@ struct       Reg
 
 #define        NRGN    600
 /*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
 struct Rgn
 {
        Reg*    enter;
@@ -144,8 +160,8 @@ void        prop(Reg*, Bits, Bits);
 void   synch(Reg*, Bits);
 uint32 allreg(uint32, Rgn*);
 void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
+uint32 paint2(Reg*, int, int);
+void   paint3(Reg*, int, uint32, int);
 void   addreg(Adr*, int);
 void   dumpit(char *str, Flow *r0, int);
 
@@ -156,10 +172,10 @@ void      peep(Prog*);
 void   excise(Flow*);
 int    copyu(Prog*, Adr*, Adr*);
 
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
+uint32 RtoB(int);
+uint32 FtoB(int);
+int    BtoR(uint32);
+int    BtoF(uint32);
 
 /*
  * prog.c
@@ -187,16 +203,16 @@ enum
        SizeF = 1<<7, // float aka float32
        SizeD = 1<<8, // double aka float64
 
-       // Left side: address taken, read, write.
+       // Left side (Prog.from): address taken, read, write.
        LeftAddr = 1<<9,
        LeftRead = 1<<10,
        LeftWrite = 1<<11,
        
-       // Register in middle; never written.
+       // Register in middle (Prog.reg); only ever read.
        RegRead = 1<<12,
        CanRegRead = 1<<13,
        
-       // Right side: address taken, read, write.
+       // Right side (Prog.to): address taken, read, write.
        RightAddr = 1<<14,
        RightRead = 1<<15,
        RightWrite = 1<<16,
index b78c268df5bfdb6d78c6e7b5dd871886c47dea42..611310f124f75134dafddd93c7df0e245498deff 100644 (file)
@@ -35,7 +35,7 @@
 #include "opt.h"
 
 #define        NREGVAR 32
-#define        REGBITS ((uint32)0xffffffff)
+#define        REGBITS ((uint64)0xffffffffull)
 /*c2go enum {
        NREGVAR = 32,
        REGBITS = 0xffffffff,
@@ -86,7 +86,7 @@ setaddrs(Bits bit)
                i = bnum(bit);
                node = var[i].node;
                n = var[i].name;
-               bit.b[i/32] &= ~(1L<<(i%32));
+               biclr(&bit, i);
 
                // disable all pieces of that variable
                for(i=0; i<nvar; i++) {
@@ -393,7 +393,7 @@ loop2:
                for(z=0; z<BITS; z++)
                        bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
                          ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
-               if(bany(&bit) & !r->f.refset) {
+               if(bany(&bit) && !r->f.refset) {
                        // should never happen - all variables are preset
                        if(debug['w'])
                                print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
@@ -425,7 +425,7 @@ loop2:
                        if(debug['R'] > 1)
                                print("\n");
                        paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
+                       biclr(&bit, i);
                        if(change <= 0) {
                                if(debug['R'])
                                        print("%L $%d: %Q\n",
@@ -454,9 +454,13 @@ brk:
         * replace code (paint3)
         */
        rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
        for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
                bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
+               vreg = paint2(rgp->enter, rgp->varno, 0);
                vreg = allreg(vreg, rgp);
                if(debug['R']) {
                        if(rgp->regno >= NREG)
@@ -477,9 +481,6 @@ brk:
                rgp++;
        }
 
-       if(debug['R'] && debug['v'])
-               dumpit("pass6", &firstr->f, 1);
-
        /*
         * free aux structures. peep allocates new ones.
         */
@@ -488,6 +489,15 @@ brk:
        flowend(g);
        firstr = R;
 
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
        /*
         * pass 7
         * peep-hole on basic block
@@ -570,7 +580,7 @@ walkvardef(Node *n, Reg *r, int active)
                        break;
                for(v=n->opt; v!=nil; v=v->nextinnode) {
                        bn = v - var;
-                       r1->act.b[bn/32] |= 1L << (bn%32);
+                       biset(&r1->act, bn);
                }
                if(r1->f.prog->as == ABL)
                        break;
@@ -606,7 +616,7 @@ addsplits(void)
                                        ~(r->calahead.b[z] & addrs.b[z]);
                        while(bany(&bit)) {
                                i = bnum(bit);
-                               bit.b[i/32] &= ~(1L << (i%32));
+                               biclr(&bit, i);
                        }
                }
        }
@@ -972,10 +982,10 @@ prop(Reg *r, Bits ref, Bits cal)
                        for(z=0; z<BITS; z++) {
                                if(cal.b[z] == 0)
                                        continue;
-                               for(i=0; i<32; i++) {
-                                       if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
+                               for(i=0; i<64; i++) {
+                                       if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
                                                continue;
-                                       v = var+z*32+i;
+                                       v = var+z*64+i;
                                        if(v->node->opt == nil) // v represents fixed register, not Go variable
                                                continue;
 
@@ -991,10 +1001,10 @@ prop(Reg *r, Bits ref, Bits cal)
                                        // This will set the bits at most twice, keeping the overall loop linear.
                                        v1 = v->node->opt;
                                        j = v1 - var;
-                                       if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
+                                       if(v == v1 || !btest(&cal, j)) {
                                                for(; v1 != nil; v1 = v1->nextinnode) {
                                                        j = v1 - var;
-                                                       cal.b[j/32] |= 1<<(j&31);
+                                                       biset(&cal, j);
                                                }
                                        }
                                }
@@ -1115,10 +1125,10 @@ paint1(Reg *r, int bn)
        Reg *r1;
        Prog *p;
        int z;
-       uint32 bb;
+       uint64 bb;
 
-       z = bn/32;
-       bb = 1L<<(bn%32);
+       z = bn/64;
+       bb = 1LL<<(bn%64);
        if(r->act.b[z] & bb)
                return;
        for(;;) {
@@ -1189,14 +1199,14 @@ paint1(Reg *r, int bn)
 }
 
 uint32
-paint2(Reg *r, int bn)
+paint2(Reg *r, int bn, int depth)
 {
        Reg *r1;
        int z;
-       uint32 bb, vreg;
+       uint64 bb, vreg;
 
-       z = bn/32;
-       bb = 1L << (bn%32);
+       z = bn/64;
+       bb = 1LL << (bn%64);
        vreg = regbits;
        if(!(r->act.b[z] & bb))
                return vreg;
@@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
                r = r1;
        }
        for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
                r->act.b[z] &= ~bb;
 
                vreg |= r->regu;
@@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
                if(r->refbehind.b[z] & bb)
                        for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
                                if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
+                                       vreg |= paint2(r1, bn, depth+1);
 
                if(!(r->refahead.b[z] & bb))
                        break;
                r1 = (Reg*)r->f.s2;
                if(r1 != R)
                        if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
+                               vreg |= paint2(r1, bn, depth+1);
                r = (Reg*)r->f.s1;
                if(r == R)
                        break;
@@ -1240,15 +1253,15 @@ paint2(Reg *r, int bn)
 }
 
 void
-paint3(Reg *r, int bn, int32 rb, int rn)
+paint3(Reg *r, int bn, uint32 rb, int rn)
 {
        Reg *r1;
        Prog *p;
        int z;
-       uint32 bb;
+       uint64 bb;
 
-       z = bn/32;
-       bb = 1L << (bn%32);
+       z = bn/64;
+       bb = 1LL << (bn%64);
        if(r->act.b[z] & bb)
                return;
        for(;;) {
@@ -1333,7 +1346,7 @@ addreg(Adr *a, int rn)
  *     10      R10
  *     12  R12
  */
-int32
+uint32
 RtoB(int r)
 {
        if(r >= REGTMP-2 && r != 12)    // excluded R9 and R10 for m and g, but not R12
@@ -1342,8 +1355,10 @@ RtoB(int r)
 }
 
 int
-BtoR(int32 b)
+BtoR(uint32 b)
 {
+       // TODO Allow R0 and R1, but be careful with a 0 return
+       // TODO Allow R9. Only R10 is reserved now (just g, not m).
        b &= 0x11fcL;   // excluded R9 and R10 for m and g, but not R12
        if(b == 0)
                return 0;
@@ -1357,7 +1372,7 @@ BtoR(int32 b)
  *     ...     ...
  *     31      F15
  */
-int32
+uint32
 FtoB(int f)
 {
 
@@ -1367,7 +1382,7 @@ FtoB(int f)
 }
 
 int
-BtoF(int32 b)
+BtoF(uint32 b)
 {
 
        b &= 0xfffc0000L;
@@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" (only)");
                        print("\n");
                }
-//             r1 = r->s1;
-//             if(r1 != nil) {
-//                     print(" succ:");
-//                     for(; r1 != R; r1 = r1->s1)
-//                             print(" %.4ud", (int)r1->prog->pc);
-//                     print("\n");
-//             }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
        }
 }
index 7b16ac4468f87e2f9ee414a403626340610d78fe..38a33db6429dd7f3503d7b07fb65ba614bbdc48c 100644 (file)
@@ -338,6 +338,8 @@ enum
        D_STATIC = (D_NONE+4),
        D_AUTO = (D_NONE+5),
        D_PARAM = (D_NONE+6),
+
+       D_LAST = (D_NONE+26),
 };
 
 /*
index b3fb0bb19f3db7e5b372a9eb79902fc59889ac90..e1927b6d40e8505630a01af73157dddcc1b164f5 100644 (file)
@@ -70,6 +70,7 @@ struct        Sym
        vlong   value;
        ushort  type;
        char    *name;
+       char*   labelname;
        char    sym;
 };
 #define        S       ((Sym*)0)
@@ -148,6 +149,8 @@ void        newio(void);
 void   newfile(char*, int);
 Sym*   slookup(char*);
 Sym*   lookup(void);
+Sym*   labellookup(Sym*);
+void   settext(LSym*);
 void   syminit(Sym*);
 int32  yylex(void);
 int    getc(void);
index 1089d4061c5e5a0e248369154029439f502dcb70..29011c7ffb05e478fd875918bc51f584132d6fde 100644 (file)
@@ -71,15 +71,11 @@ prog:
        line
 
 line:
-       LLAB ':'
-       {
-               if($1->value != pc)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = pc;
-       }
-       line
-|      LNAME ':'
+       LNAME ':'
        {
+               $1 = labellookup($1);
+               if($1->type == LLAB && $1->value != pc)
+                       yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
                $1->type = LLAB;
                $1->value = pc;
        }
@@ -197,11 +193,13 @@ spec1:    /* DATA */
 spec2: /* TEXT */
        mem ',' imm2
        {
+               settext($1.sym);
                $$.from = $1;
                $$.to = $3;
        }
 |      mem ',' con ',' imm2
        {
+               settext($1.sym);
                $$.from = $1;
                $$.from.scale = $3;
                $$.to = $5;
@@ -363,15 +361,10 @@ rel:
        }
 |      LNAME offset
        {
+               $1 = labellookup($1);
                $$ = nullgen;
-               if(pass == 2)
-                       yyerror("undefined label: %s", $1->name);
-               $$.type = D_BRANCH;
-               $$.offset = $2;
-       }
-|      LLAB offset
-       {
-               $$ = nullgen;
+               if(pass == 2 && $1->type != LLAB)
+                       yyerror("undefined label: %s", $1->labelname);
                $$.type = D_BRANCH;
                $$.offset = $1->value + $2;
        }
index b69fd95b531b7a5399d92044762845e9452b43a4..a698079d23f7f8a02a358e4a868cf326a518ba6e 100644 (file)
@@ -411,16 +411,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   560
+#define YYLAST   549
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  56
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  42
+#define YYNNTS  41
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  137
+#define YYNRULES  134
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  277
+#define YYNSTATES  271
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -469,91 +469,91 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 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,
+       0,     0,     3,     4,     5,     9,    10,    15,    17,    20,
+      23,    27,    31,    34,    37,    40,    43,    46,    49,    52,
       55,    58,    61,    64,    67,    70,    73,    76,    79,    82,
-      85,    88,    91,    94,    95,    97,   101,   105,   108,   110,
-     113,   115,   118,   120,   124,   130,   134,   140,   143,   145,
-     147,   149,   153,   159,   163,   169,   172,   174,   178,   184,
-     190,   191,   193,   197,   203,   207,   211,   213,   215,   217,
-     219,   222,   225,   227,   229,   231,   233,   238,   241,   244,
-     246,   248,   250,   252,   254,   256,   258,   261,   264,   267,
-     270,   273,   278,   284,   288,   290,   292,   294,   299,   304,
-     309,   316,   326,   336,   340,   344,   350,   359,   361,   368,
-     374,   382,   383,   386,   389,   391,   393,   395,   397,   399,
-     402,   405,   408,   412,   414,   417,   421,   426,   428,   432,
-     436,   440,   444,   448,   453,   458,   462,   466
+      85,    88,    89,    91,    95,    99,   102,   104,   107,   109,
+     112,   114,   118,   124,   128,   134,   137,   139,   141,   143,
+     147,   153,   157,   163,   166,   168,   172,   178,   184,   185,
+     187,   191,   197,   201,   205,   207,   209,   211,   213,   216,
+     219,   221,   223,   225,   227,   232,   235,   237,   239,   241,
+     243,   245,   247,   249,   252,   255,   258,   261,   264,   269,
+     275,   279,   281,   283,   285,   290,   295,   300,   307,   317,
+     327,   331,   335,   341,   350,   352,   359,   365,   373,   374,
+     377,   380,   382,   384,   386,   388,   390,   393,   396,   399,
+     403,   405,   408,   412,   417,   419,   423,   427,   431,   435,
+     439,   444,   449,   453,   457
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
       57,     0,    -1,    -1,    -1,    57,    58,    59,    -1,    -1,
-      46,    48,    60,    59,    -1,    -1,    45,    48,    61,    59,
-      -1,    49,    -1,    62,    49,    -1,     1,    49,    -1,    45,
-      50,    97,    -1,    47,    50,    97,    -1,    13,    63,    -1,
-      14,    67,    -1,    15,    66,    -1,    16,    64,    -1,    17,
-      65,    -1,    21,    68,    -1,    19,    69,    -1,    22,    70,
-      -1,    18,    71,    -1,    20,    72,    -1,    25,    73,    -1,
-      26,    74,    -1,    27,    75,    -1,    28,    76,    -1,    29,
-      77,    -1,    30,    78,    -1,    23,    79,    -1,    24,    80,
-      -1,    31,    81,    -1,    -1,    51,    -1,    84,    51,    82,
-      -1,    82,    51,    84,    -1,    84,    51,    -1,    84,    -1,
-      51,    82,    -1,    82,    -1,    51,    85,    -1,    85,    -1,
-      88,    51,    85,    -1,    92,    11,    95,    51,    88,    -1,
-      89,    51,    87,    -1,    89,    51,    95,    51,    87,    -1,
-      51,    83,    -1,    83,    -1,    63,    -1,    67,    -1,    84,
-      51,    82,    -1,    84,    51,    82,    48,    37,    -1,    84,
-      51,    82,    -1,    84,    51,    82,    48,    38,    -1,    84,
-      51,    -1,    84,    -1,    84,    51,    82,    -1,    86,    51,
-      82,    51,    95,    -1,    88,    51,    82,    51,    86,    -1,
-      -1,    88,    -1,    89,    51,    88,    -1,    89,    51,    95,
-      51,    88,    -1,    84,    51,    84,    -1,    84,    51,    84,
-      -1,    86,    -1,    89,    -1,    85,    -1,    91,    -1,    10,
-      86,    -1,    10,    90,    -1,    86,    -1,    90,    -1,    82,
-      -1,    88,    -1,    95,    52,    34,    53,    -1,    45,    93,
-      -1,    46,    93,    -1,    36,    -1,    39,    -1,    37,    -1,
-      40,    -1,    44,    -1,    38,    -1,    41,    -1,    54,    96,
-      -1,    54,    95,    -1,    54,    92,    -1,    54,    43,    -1,
-      54,    42,    -1,    54,    52,    42,    53,    -1,    54,    52,
-       9,    42,    53,    -1,    54,     9,    42,    -1,    90,    -1,
-      91,    -1,    95,    -1,    95,    52,    37,    53,    -1,    95,
-      52,    44,    53,    -1,    95,    52,    38,    53,    -1,    95,
-      52,    37,    10,    95,    53,    -1,    95,    52,    37,    53,
-      52,    37,    10,    95,    53,    -1,    95,    52,    37,    53,
-      52,    38,    10,    95,    53,    -1,    52,    37,    53,    -1,
-      52,    44,    53,    -1,    52,    37,    10,    95,    53,    -1,
-      52,    37,    53,    52,    37,    10,    95,    53,    -1,    92,
-      -1,    92,    52,    37,    10,    95,    53,    -1,    45,    93,
-      52,    94,    53,    -1,    45,     6,     7,    93,    52,    35,
-      53,    -1,    -1,     8,    95,    -1,     9,    95,    -1,    35,
-      -1,    44,    -1,    33,    -1,    32,    -1,    47,    -1,     9,
-      95,    -1,     8,    95,    -1,    55,    95,    -1,    52,    97,
-      53,    -1,    32,    -1,     9,    32,    -1,    32,     9,    32,
-      -1,     9,    32,     9,    32,    -1,    95,    -1,    97,     8,
-      97,    -1,    97,     9,    97,    -1,    97,    10,    97,    -1,
-      97,    11,    97,    -1,    97,    12,    97,    -1,    97,     6,
-       6,    97,    -1,    97,     7,     7,    97,    -1,    97,     5,
-      97,    -1,    97,     4,    97,    -1,    97,     3,    97,    -1
+      45,    48,    60,    59,    -1,    49,    -1,    61,    49,    -1,
+       1,    49,    -1,    45,    50,    96,    -1,    47,    50,    96,
+      -1,    13,    62,    -1,    14,    66,    -1,    15,    65,    -1,
+      16,    63,    -1,    17,    64,    -1,    21,    67,    -1,    19,
+      68,    -1,    22,    69,    -1,    18,    70,    -1,    20,    71,
+      -1,    25,    72,    -1,    26,    73,    -1,    27,    74,    -1,
+      28,    75,    -1,    29,    76,    -1,    30,    77,    -1,    23,
+      78,    -1,    24,    79,    -1,    31,    80,    -1,    -1,    51,
+      -1,    83,    51,    81,    -1,    81,    51,    83,    -1,    83,
+      51,    -1,    83,    -1,    51,    81,    -1,    81,    -1,    51,
+      84,    -1,    84,    -1,    87,    51,    84,    -1,    91,    11,
+      94,    51,    87,    -1,    88,    51,    86,    -1,    88,    51,
+      94,    51,    86,    -1,    51,    82,    -1,    82,    -1,    62,
+      -1,    66,    -1,    83,    51,    81,    -1,    83,    51,    81,
+      48,    37,    -1,    83,    51,    81,    -1,    83,    51,    81,
+      48,    38,    -1,    83,    51,    -1,    83,    -1,    83,    51,
+      81,    -1,    85,    51,    81,    51,    94,    -1,    87,    51,
+      81,    51,    85,    -1,    -1,    87,    -1,    88,    51,    87,
+      -1,    88,    51,    94,    51,    87,    -1,    83,    51,    83,
+      -1,    83,    51,    83,    -1,    85,    -1,    88,    -1,    84,
+      -1,    90,    -1,    10,    85,    -1,    10,    89,    -1,    85,
+      -1,    89,    -1,    81,    -1,    87,    -1,    94,    52,    34,
+      53,    -1,    45,    92,    -1,    36,    -1,    39,    -1,    37,
+      -1,    40,    -1,    44,    -1,    38,    -1,    41,    -1,    54,
+      95,    -1,    54,    94,    -1,    54,    91,    -1,    54,    43,
+      -1,    54,    42,    -1,    54,    52,    42,    53,    -1,    54,
+      52,     9,    42,    53,    -1,    54,     9,    42,    -1,    89,
+      -1,    90,    -1,    94,    -1,    94,    52,    37,    53,    -1,
+      94,    52,    44,    53,    -1,    94,    52,    38,    53,    -1,
+      94,    52,    37,    10,    94,    53,    -1,    94,    52,    37,
+      53,    52,    37,    10,    94,    53,    -1,    94,    52,    37,
+      53,    52,    38,    10,    94,    53,    -1,    52,    37,    53,
+      -1,    52,    44,    53,    -1,    52,    37,    10,    94,    53,
+      -1,    52,    37,    53,    52,    37,    10,    94,    53,    -1,
+      91,    -1,    91,    52,    37,    10,    94,    53,    -1,    45,
+      92,    52,    93,    53,    -1,    45,     6,     7,    92,    52,
+      35,    53,    -1,    -1,     8,    94,    -1,     9,    94,    -1,
+      35,    -1,    44,    -1,    33,    -1,    32,    -1,    47,    -1,
+       9,    94,    -1,     8,    94,    -1,    55,    94,    -1,    52,
+      96,    53,    -1,    32,    -1,     9,    32,    -1,    32,     9,
+      32,    -1,     9,    32,     9,    32,    -1,    94,    -1,    96,
+       8,    96,    -1,    96,     9,    96,    -1,    96,    10,    96,
+      -1,    96,    11,    96,    -1,    96,    12,    96,    -1,    96,
+       6,     6,    96,    -1,    96,     7,     7,    96,    -1,    96,
+       5,    96,    -1,    96,     4,    96,    -1,    96,     3,    96,
+      -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    66,    66,    68,    67,    75,    74,    82,    81,    87,
-      88,    89,    92,    97,   103,   104,   105,   106,   107,   108,
-     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
-     119,   120,   121,   124,   128,   135,   142,   149,   154,   161,
-     166,   173,   178,   183,   190,   198,   203,   211,   216,   223,
-     224,   227,   232,   242,   247,   257,   262,   267,   274,   282,
-     292,   296,   303,   308,   316,   325,   336,   337,   340,   341,
-     342,   346,   350,   351,   354,   355,   358,   364,   372,   380,
-     385,   390,   395,   400,   405,   410,   416,   424,   430,   441,
-     447,   453,   459,   465,   473,   474,   477,   483,   489,   495,
-     501,   510,   519,   528,   533,   538,   546,   556,   560,   569,
-     576,   585,   588,   592,   598,   599,   603,   606,   607,   611,
-     615,   619,   623,   629,   634,   639,   644,   651,   652,   656,
-     660,   664,   668,   672,   676,   680,   684,   688
+       0,    66,    66,    68,    67,    75,    74,    83,    84,    85,
+      88,    93,    99,   100,   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,   179,   186,   194,   200,   209,   214,   221,   222,   225,
+     230,   240,   245,   255,   260,   265,   272,   280,   290,   294,
+     301,   306,   314,   323,   334,   335,   338,   339,   340,   344,
+     348,   349,   352,   353,   356,   362,   373,   378,   383,   388,
+     393,   398,   403,   409,   417,   423,   434,   440,   446,   452,
+     458,   466,   467,   470,   476,   482,   488,   494,   503,   512,
+     521,   526,   531,   539,   549,   553,   562,   569,   578,   581,
+     585,   591,   592,   596,   599,   600,   604,   608,   612,   616,
+     622,   627,   632,   637,   644,   645,   649,   653,   657,   661,
+     665,   669,   673,   677,   681
 };
 #endif
 
@@ -569,7 +569,7 @@ static const char *const yytname[] =
   "LTYPEF", "LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG",
   "LFREG", "LMREG", "LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB",
   "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'", "'~'",
-  "$accept", "prog", "@1", "line", "@2", "@3", "inst", "nonnon", "rimrem",
+  "$accept", "prog", "@1", "line", "@2", "inst", "nonnon", "rimrem",
   "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2", "spec3",
   "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "spec10", "spec11",
   "spec12", "spec13", "rem", "rom", "rim", "rel", "reg", "imm2", "imm",
@@ -594,39 +594,39 @@ static const yytype_uint16 yytoknum[] =
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    56,    57,    58,    57,    60,    59,    61,    59,    59,
-      59,    59,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    62,    62,    62,    62,    62,    62,    62,
-      62,    62,    62,    63,    63,    64,    65,    66,    66,    67,
-      67,    68,    68,    68,    69,    70,    70,    71,    71,    72,
-      72,    73,    73,    74,    74,    75,    75,    75,    76,    77,
-      78,    78,    79,    79,    80,    81,    82,    82,    83,    83,
-      83,    83,    83,    83,    84,    84,    85,    85,    85,    86,
-      86,    86,    86,    86,    86,    86,    87,    88,    88,    88,
-      88,    88,    88,    88,    89,    89,    90,    90,    90,    90,
-      90,    90,    90,    90,    90,    90,    90,    91,    91,    92,
-      92,    93,    93,    93,    94,    94,    94,    95,    95,    95,
-      95,    95,    95,    96,    96,    96,    96,    97,    97,    97,
-      97,    97,    97,    97,    97,    97,    97,    97
+       0,    56,    57,    58,    57,    60,    59,    59,    59,    59,
+      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
+      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
+      61,    62,    62,    63,    64,    65,    65,    66,    66,    67,
+      67,    67,    68,    69,    69,    70,    70,    71,    71,    72,
+      72,    73,    73,    74,    74,    74,    75,    76,    77,    77,
+      78,    78,    79,    80,    81,    81,    82,    82,    82,    82,
+      82,    82,    83,    83,    84,    84,    85,    85,    85,    85,
+      85,    85,    85,    86,    87,    87,    87,    87,    87,    87,
+      87,    88,    88,    89,    89,    89,    89,    89,    89,    89,
+      89,    89,    89,    89,    90,    90,    91,    91,    92,    92,
+      92,    93,    93,    93,    94,    94,    94,    94,    94,    94,
+      95,    95,    95,    95,    96,    96,    96,    96,    96,    96,
+      96,    96,    96,    96,    96
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 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,
+       0,     2,     0,     0,     3,     0,     4,     1,     2,     2,
+       3,     3,     2,     2,     2,     2,     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,     3,     5,     3,     5,     2,     1,     1,
-       1,     3,     5,     3,     5,     2,     1,     3,     5,     5,
-       0,     1,     3,     5,     3,     3,     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,     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
+       2,     0,     1,     3,     3,     2,     1,     2,     1,     2,
+       1,     3,     5,     3,     5,     2,     1,     1,     1,     3,
+       5,     3,     5,     2,     1,     3,     5,     5,     0,     1,
+       3,     5,     3,     3,     1,     1,     1,     1,     2,     2,
+       1,     1,     1,     1,     4,     2,     1,     1,     1,     1,
+       1,     1,     1,     2,     2,     2,     2,     2,     4,     5,
+       3,     1,     1,     1,     4,     4,     4,     6,     9,     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
@@ -634,89 +634,89 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     3,     1,     0,     0,    33,     0,     0,     0,     0,
-       0,     0,    33,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    60,     0,     0,     0,     0,     9,     4,     0,
-      11,    34,    14,     0,     0,   117,    79,    81,    84,    80,
-      82,    85,    83,   111,   118,     0,     0,     0,    15,    40,
-      66,    67,    94,    95,   107,    96,     0,    16,    74,    38,
-      75,    17,     0,    18,     0,     0,   111,   111,     0,    22,
-      48,    68,    72,    73,    69,    96,    20,     0,    34,    49,
-      50,    23,   111,     0,     0,    19,    42,     0,     0,    21,
-       0,    30,     0,    31,     0,    24,     0,    25,     0,    26,
-      56,    27,     0,    28,     0,    29,    61,    32,     0,     7,
-       0,     5,     0,    10,   120,   119,     0,     0,     0,     0,
-      39,     0,     0,   127,     0,   121,     0,     0,     0,    90,
-      89,     0,    88,    87,    37,     0,     0,    70,    71,    77,
-      78,    47,     0,     0,    77,    41,     0,     0,     0,     0,
-       0,     0,     0,    55,     0,     0,     0,     0,    12,     0,
-      13,   111,   112,   113,     0,     0,   103,   104,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   122,     0,
-       0,     0,     0,    93,     0,     0,    35,    36,     0,     0,
-      43,     0,    45,     0,    62,     0,    64,    51,    53,    57,
-       0,     0,    65,     8,     6,     0,   116,   114,   115,     0,
-       0,     0,   137,   136,   135,     0,     0,   128,   129,   130,
-     131,   132,     0,     0,    97,    99,    98,     0,    91,    76,
-       0,     0,   123,    86,     0,     0,     0,     0,     0,     0,
-       0,   109,   105,     0,   133,   134,     0,     0,     0,    92,
-      44,   124,     0,    46,    63,    52,    54,    58,    59,     0,
-       0,   108,   100,     0,     0,     0,   125,   110,     0,     0,
-       0,   126,   106,     0,     0,   101,   102
+       2,     3,     1,     0,     0,    31,     0,     0,     0,     0,
+       0,     0,    31,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    58,     0,     0,     0,     7,     4,     0,     9,
+      32,    12,     0,     0,   114,    76,    78,    81,    77,    79,
+      82,    80,   108,   115,     0,     0,     0,    13,    38,    64,
+      65,    91,    92,   104,    93,     0,    14,    72,    36,    73,
+      15,     0,    16,     0,     0,   108,     0,    20,    46,    66,
+      70,    71,    67,    93,    18,     0,    32,    47,    48,    21,
+     108,     0,     0,    17,    40,     0,     0,    19,     0,    28,
+       0,    29,     0,    22,     0,    23,     0,    24,    54,    25,
+       0,    26,     0,    27,    59,    30,     0,     5,     0,     0,
+       8,   117,   116,     0,     0,     0,     0,    37,     0,     0,
+     124,     0,   118,     0,     0,     0,    87,    86,     0,    85,
+      84,    35,     0,     0,    68,    69,    75,    45,     0,     0,
+      75,    39,     0,     0,     0,     0,     0,     0,     0,    53,
+       0,     0,     0,     0,    10,    11,   108,   109,   110,     0,
+       0,   100,   101,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   119,     0,     0,     0,     0,    90,     0,
+       0,    33,    34,     0,     0,    41,     0,    43,     0,    60,
+       0,    62,    49,    51,    55,     0,     0,    63,     6,     0,
+     113,   111,   112,     0,     0,     0,   134,   133,   132,     0,
+       0,   125,   126,   127,   128,   129,     0,     0,    94,    96,
+      95,     0,    88,    74,     0,     0,   120,    83,     0,     0,
+       0,     0,     0,     0,     0,   106,   102,     0,   130,   131,
+       0,     0,     0,    89,    42,   121,     0,    44,    61,    50,
+      52,    56,    57,     0,     0,   105,    97,     0,     0,     0,
+     122,   107,     0,     0,     0,   123,   103,     0,     0,    98,
+      99
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     3,    28,   159,   157,    29,    32,    61,    63,
-      57,    48,    85,    76,    89,    69,    81,    95,    97,    99,
-     101,   103,   105,    91,    93,   107,    58,    70,    59,    71,
-      50,   192,    60,    51,    52,    53,    54,   119,   209,    55,
-     233,   124
+      -1,     1,     3,    27,   153,    28,    31,    60,    62,    56,
+      47,    83,    74,    87,    67,    79,    93,    95,    97,    99,
+     101,   103,    89,    91,   105,    57,    68,    58,    69,    49,
+     187,    59,    50,    51,    52,    53,   116,   203,    54,   227,
+     121
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -94
+#define YYPACT_NINF -89
 static const yytype_int16 yypact[] =
 {
-     -94,    15,   -94,   218,   -28,   -25,   264,   285,   285,   340,
-     163,     2,   319,    97,   415,   415,   285,   285,   285,   285,
-     306,   -24,   -24,   285,   -17,   -14,     4,   -94,   -94,    48,
-     -94,   -94,   -94,   481,   481,   -94,   -94,   -94,   -94,   -94,
-     -94,   -94,   -94,    19,   -94,   340,   399,   481,   -94,   -94,
-     -94,   -94,   -94,   -94,    46,    47,   385,   -94,   -94,    52,
-     -94,   -94,    59,   -94,    60,   374,    19,    56,   243,   -94,
-     -94,   -94,   -94,   -94,   -94,    63,   -94,   106,   340,   -94,
-     -94,   -94,    56,   138,   481,   -94,   -94,    69,    72,   -94,
-      74,   -94,    76,   -94,    77,   -94,    79,   -94,    80,   -94,
-      81,   -94,    83,   -94,    89,   -94,   -94,   -94,    94,   -94,
-     481,   -94,   481,   -94,   -94,   -94,   119,   481,   481,    98,
-     -94,    -1,   100,   -94,    84,   -94,   117,    23,   426,   -94,
-     -94,   433,   -94,   -94,   -94,   340,   285,   -94,   -94,    98,
-     -94,   -94,    75,   481,   -94,   -94,   138,   122,   440,   444,
-     285,   340,   340,   340,   340,   340,   285,   218,   393,   218,
-     393,    56,   -94,   -94,   -15,   481,   105,   -94,   481,   481,
-     481,   156,   162,   481,   481,   481,   481,   481,   -94,   165,
-       0,   123,   133,   -94,   474,   134,   -94,   -94,   136,   140,
-     -94,     7,   -94,   141,   -94,   143,   -94,   148,   149,   -94,
-     147,   160,   -94,   -94,   -94,   164,   -94,   -94,   -94,   167,
-     168,   180,   533,   541,   548,   481,   481,    58,    58,   -94,
-     -94,   -94,   481,   481,   171,   -94,   -94,   172,   -94,   -94,
-     -24,   192,   217,   -94,   175,   -24,   219,   216,   481,   306,
-     220,   -94,   -94,   247,    33,    33,   205,   208,    41,   -94,
-     -94,   253,   234,   -94,   -94,   -94,   -94,   -94,   -94,   215,
-     481,   -94,   -94,   259,   260,   239,   -94,   -94,   221,   481,
-     481,   -94,   -94,   223,   224,   -94,   -94
+     -89,    18,   -89,   163,    -5,   -13,   219,   253,   253,   335,
+     194,    16,   274,   369,   418,   418,   253,   253,   253,   253,
+     240,     0,     0,   253,   -17,    19,   -89,   -89,    24,   -89,
+     -89,   -89,   479,   479,   -89,   -89,   -89,   -89,   -89,   -89,
+     -89,   -89,   111,   -89,   335,   397,   479,   -89,   -89,   -89,
+     -89,   -89,   -89,    33,    51,   390,   -89,   -89,    65,   -89,
+     -89,    72,   -89,    73,   356,   111,   314,   -89,   -89,   -89,
+     -89,   -89,   -89,    74,   -89,    30,   335,   -89,   -89,   -89,
+      70,   422,   479,   -89,   -89,    82,    86,   -89,    88,   -89,
+      89,   -89,    90,   -89,    91,   -89,    92,   -89,   101,   -89,
+     105,   -89,   114,   -89,   -89,   -89,   116,   -89,   479,   479,
+     -89,   -89,   -89,   118,   479,   479,   120,   -89,     5,   115,
+     -89,    83,   -89,   133,   -12,   404,   -89,   -89,   439,   -89,
+     -89,   -89,   335,   253,   -89,   -89,   120,   -89,     9,   479,
+     -89,   -89,   422,   141,   119,   452,   253,   335,   335,   335,
+     335,   335,   253,   163,   327,   327,    70,   -89,   -89,     4,
+     479,   143,   -89,   479,   479,   479,   190,   191,   479,   479,
+     479,   479,   479,   -89,   187,     6,   148,   152,   -89,   470,
+     156,   -89,   -89,   158,   162,   -89,     8,   -89,   164,   -89,
+     166,   -89,   170,   171,   -89,   169,   172,   -89,   -89,   173,
+     -89,   -89,   -89,   161,   176,   199,   102,   530,   537,   479,
+     479,    39,    39,   -89,   -89,   -89,   479,   479,   185,   -89,
+     -89,   189,   -89,   -89,     0,   208,   234,   -89,   193,     0,
+     211,   212,   479,   240,   217,   -89,   -89,   255,    55,    55,
+     214,   215,    59,   -89,   -89,   260,   241,   -89,   -89,   -89,
+     -89,   -89,   -89,   222,   479,   -89,   -89,   262,   276,   256,
+     -89,   -89,   242,   479,   479,   -89,   -89,   243,   246,   -89,
+     -89
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-     -94,   -94,   -94,   -43,   -94,   -94,   -94,   266,   -94,   -94,
-     -94,   273,   -94,   -94,   -94,   -94,   -94,   -94,   -94,   -94,
-     -94,   -94,   -94,   -94,   -94,   -94,    26,   229,    32,   -11,
-      -9,    57,    -8,    71,    -2,    -6,     1,   -60,   -94,   -10,
-     -94,   -93
+     -89,   -89,   -89,   134,   -89,   -89,   289,   -89,   -89,   -89,
+     290,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
+     -89,   -89,   -89,   -89,   -89,    -2,   237,    11,   -11,    -9,
+      76,    -8,    87,    -4,     2,    -3,   -56,   -89,   -10,   -89,
+     -88
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -726,124 +726,120 @@ static const yytype_int16 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint16 yytable[] =
 {
-      75,    72,    86,    88,    74,    87,   139,   140,    73,   165,
-     223,   102,    77,   104,   106,     2,   231,   158,   206,   160,
-     207,    30,   144,   114,   115,   116,    31,   117,   118,   208,
-      56,   109,    49,   110,   111,    64,   123,   125,    49,   232,
-      62,   173,   174,   175,   176,   177,   133,    43,    94,    96,
-      98,   100,   166,   224,   112,   108,   137,   132,    75,    72,
-     180,   181,    74,   138,   117,   118,    73,   182,   175,   176,
-     177,   120,   145,    88,   123,   212,   213,   214,   263,   264,
-     217,   218,   219,   220,   221,    90,    92,   168,   169,   170,
-     171,   172,   173,   174,   175,   176,   177,   113,   126,   127,
-     123,   205,   123,   134,   120,    33,    34,   162,   163,   188,
-     135,   136,   180,   181,   203,   142,   204,   143,   115,   182,
-     146,   123,   244,   245,   147,   148,   161,   149,   150,    35,
-     151,   152,   153,   189,   154,   190,    88,   178,   193,   195,
-     155,   194,    82,    67,    44,   156,    33,    34,    83,    84,
-     164,    56,    47,   167,   179,   210,   188,   211,   123,   123,
-     123,   186,   215,   123,   123,   123,   123,   123,   187,   216,
-      35,    33,    34,    65,   115,   222,   225,   197,   198,   199,
-     200,   201,   196,    82,    67,    44,   226,   228,   202,   229,
-      84,   230,   234,    47,   235,    35,   236,   237,   238,    36,
-      37,    38,    39,    40,    41,   123,   123,    42,    66,    67,
-      44,   239,   246,   247,    68,    46,   240,   243,    47,     4,
-     241,   242,   250,   248,   251,   249,   252,   254,   257,   191,
-     258,     5,     6,     7,     8,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-     268,    33,    34,    65,   256,   259,   255,   260,   261,   273,
-     274,   262,   265,    24,    25,    26,   266,    27,   267,   269,
-     270,   271,    33,    34,   272,    35,   275,   276,    79,    36,
-      37,    38,    39,    40,    41,    80,     0,    42,    66,    67,
-      44,   253,     0,    33,    34,    46,    35,   141,    47,     0,
-      36,    37,    38,    39,    40,    41,     0,     0,    42,    43,
-       0,    44,     0,     0,     0,    45,    46,    35,     0,    47,
-       0,    36,    37,    38,    39,    40,    41,    33,    34,    42,
-      43,     0,    44,     0,     0,     0,     0,    46,     0,    56,
-      47,     0,    36,    37,    38,    39,    40,    41,    33,    34,
-      42,    35,     0,     0,     0,    36,    37,    38,    39,    40,
-      41,     0,     0,    42,    43,     0,    44,     0,     0,     0,
-      78,    46,    35,     0,    47,     0,    36,    37,    38,    39,
-      40,    41,    33,    34,    42,    43,     0,    44,     0,     0,
-       0,     0,    46,    33,   128,    47,   168,   169,   170,   171,
-     172,   173,   174,   175,   176,   177,    35,    33,    34,     0,
-      36,    37,    38,    39,    40,    41,     0,    35,    42,     0,
-       0,    44,     0,    33,    34,     0,    46,   129,   130,    47,
-      43,    35,    44,     0,    33,    34,   121,   131,     0,     0,
-      47,    33,   184,   122,     0,     0,    44,    35,    33,    34,
-       0,    84,    33,    34,    47,     0,     0,     0,    35,     0,
-      43,     0,    44,     0,     0,    35,     0,    46,   183,     0,
-      47,     0,    35,    44,     0,   185,    35,     0,    84,     0,
-      44,    47,    33,    34,     0,    84,     0,    44,    47,    33,
-      34,    44,    84,     0,   191,    47,    84,     0,    56,    47,
-       0,     0,     0,     0,     0,     0,    35,     0,     0,     0,
-       0,     0,     0,    35,     0,     0,   227,     0,     0,     0,
-       0,    44,     0,     0,     0,     0,    84,     0,    44,    47,
-       0,     0,     0,    84,     0,     0,    47,   169,   170,   171,
-     172,   173,   174,   175,   176,   177,   170,   171,   172,   173,
-     174,   175,   176,   177,   171,   172,   173,   174,   175,   176,
-     177
+      73,    70,    84,    86,    48,    85,    71,    63,    75,   136,
+      48,   100,    72,   102,   104,   160,   217,   225,     2,    61,
+     154,   155,   111,   112,   140,   175,   176,    92,    94,    96,
+      98,   107,   177,   108,   106,   120,   122,   200,    30,   201,
+     226,   139,   117,   183,    29,   130,   175,   176,   202,   170,
+     171,   172,   129,   177,    55,   134,    73,    70,   161,   218,
+     135,    42,    71,   168,   169,   170,   171,   172,    72,   109,
+     141,    86,   120,   110,   117,   206,   207,   208,   114,   115,
+     211,   212,   213,   214,   215,   123,   163,   164,   165,   166,
+     167,   168,   169,   170,   171,   172,   257,   258,   120,   120,
+     199,    88,    90,   124,   157,   158,   164,   165,   166,   167,
+     168,   169,   170,   171,   172,   112,   131,   113,   120,   114,
+     115,   238,   239,   132,   133,   156,   138,    32,    33,   184,
+     181,   185,    86,   142,   188,   190,   173,   189,   143,   144,
+     145,   146,   147,   148,   182,   192,   193,   194,   195,   196,
+     204,    34,   149,   120,   120,   120,   150,   191,   120,   120,
+     120,   120,   120,   197,     4,   151,    43,   152,   162,   112,
+     174,    82,   159,   186,    46,   183,     5,     6,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,   205,   209,   216,   210,   120,
+     120,   219,    32,    33,    64,   220,   240,   241,    24,   222,
+      25,   223,    26,   224,   235,   228,   244,   229,   230,   231,
+     232,   248,   251,   233,   252,   234,    34,    32,    33,   236,
+      35,    36,    37,    38,    39,    40,   237,   242,    41,    65,
+     245,    43,   243,   246,   262,    66,    45,   186,   249,    46,
+     250,    34,   253,   267,   268,    35,    36,    37,    38,    39,
+      40,    32,    33,    41,    42,   254,    43,   255,   256,   259,
+      44,    45,   263,   260,    46,   261,    35,    36,    37,    38,
+      39,    40,    32,    33,    41,    34,   264,   198,   265,    35,
+      36,    37,    38,    39,    40,   266,   269,    41,    42,   270,
+      43,    77,    78,   137,   247,    45,    34,    55,    46,     0,
+      35,    36,    37,    38,    39,    40,     0,     0,    41,    42,
+       0,    43,    32,    33,    64,    76,    45,     0,     0,    46,
+     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
+       0,     0,     0,    32,    33,     0,    34,     0,     0,     0,
+      35,    36,    37,    38,    39,    40,     0,     0,    41,    65,
+       0,    43,     0,     0,    32,    33,    45,    34,     0,    46,
+       0,    35,    36,    37,    38,    39,    40,    32,    33,    41,
+      42,     0,    43,     0,     0,     0,     0,    45,    34,     0,
+      46,     0,    35,    36,    37,    38,    39,    40,    32,   125,
+      41,    34,     0,    43,     0,    32,    33,     0,    45,     0,
+       0,    46,    32,    33,    80,     0,    43,     0,     0,     0,
+      81,    82,    34,    55,    46,     0,    32,    33,     0,    34,
+      32,    33,   126,   127,   118,    42,    34,    43,     0,     0,
+       0,   119,   128,     0,    43,    46,   178,    32,   179,    82,
+      34,    43,    46,     0,    34,     0,    82,     0,     0,    46,
+      32,    33,     0,    42,     0,    43,     0,    80,     0,    43,
+      45,    34,     0,    46,    82,     0,     0,    46,    32,    33,
+       0,   180,     0,     0,    34,     0,    43,    32,    33,     0,
+       0,    82,     0,     0,    46,     0,     0,     0,     0,    43,
+       0,     0,    34,     0,    82,     0,    55,    46,     0,     0,
+       0,    34,   221,     0,     0,     0,     0,    43,     0,     0,
+       0,     0,    82,     0,     0,    46,    43,     0,     0,     0,
+       0,    82,     0,     0,    46,   165,   166,   167,   168,   169,
+     170,   171,   172,   166,   167,   168,   169,   170,   171,   172
 };
 
 static const yytype_int16 yycheck[] =
 {
-      10,    10,    13,    13,    10,    13,    66,    67,    10,    10,
-      10,    20,    11,    21,    22,     0,     9,   110,    33,   112,
-      35,    49,    82,    33,    34,     6,    51,     8,     9,    44,
-      54,    48,     6,    50,    48,     9,    46,    47,    12,    32,
-       8,     8,     9,    10,    11,    12,    56,    45,    16,    17,
-      18,    19,    53,    53,    50,    23,    65,    56,    68,    68,
-      37,    38,    68,    65,     8,     9,    68,    44,    10,    11,
-      12,    45,    83,    83,    84,   168,   169,   170,    37,    38,
-     173,   174,   175,   176,   177,    14,    15,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    49,    52,    52,
-     110,   161,   112,    51,    78,     8,     9,   117,   118,    34,
-      51,    51,    37,    38,   157,    52,   159,    11,   128,    44,
-      51,   131,   215,   216,    52,    51,     7,    51,    51,    32,
-      51,    51,    51,   143,    51,   146,   146,    53,   148,   149,
-      51,   149,    45,    46,    47,    51,     8,     9,    51,    52,
-      52,    54,    55,    53,    37,   165,    34,    52,   168,   169,
-     170,   135,     6,   173,   174,   175,   176,   177,   136,     7,
-      32,     8,     9,    10,   184,    10,    53,   151,   152,   153,
-     154,   155,   150,    45,    46,    47,    53,    53,   156,    53,
-      52,    51,    51,    55,    51,    32,    48,    48,    51,    36,
-      37,    38,    39,    40,    41,   215,   216,    44,    45,    46,
-      47,    51,   222,   223,    51,    52,    52,    37,    55,     1,
-      53,    53,   230,    52,    32,    53,     9,   235,   238,    54,
-     239,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-     260,     8,     9,    10,    38,    35,    37,    10,    53,   269,
-     270,    53,     9,    45,    46,    47,    32,    49,    53,    10,
-      10,    32,     8,     9,    53,    32,    53,    53,    12,    36,
-      37,    38,    39,    40,    41,    12,    -1,    44,    45,    46,
-      47,   234,    -1,     8,     9,    52,    32,    68,    55,    -1,
+      10,    10,    13,    13,     6,    13,    10,     9,    11,    65,
+      12,    20,    10,    21,    22,    10,    10,     9,     0,     8,
+     108,   109,    32,    33,    80,    37,    38,    16,    17,    18,
+      19,    48,    44,    50,    23,    45,    46,    33,    51,    35,
+      32,    11,    44,    34,    49,    55,    37,    38,    44,    10,
+      11,    12,    55,    44,    54,    64,    66,    66,    53,    53,
+      64,    45,    66,     8,     9,    10,    11,    12,    66,    50,
+      81,    81,    82,    49,    76,   163,   164,   165,     8,     9,
+     168,   169,   170,   171,   172,    52,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    37,    38,   108,   109,
+     156,    14,    15,    52,   114,   115,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,   125,    51,     6,   128,     8,
+       9,   209,   210,    51,    51,     7,    52,     8,     9,   139,
+     132,   142,   142,    51,   144,   145,    53,   145,    52,    51,
+      51,    51,    51,    51,   133,   147,   148,   149,   150,   151,
+     160,    32,    51,   163,   164,   165,    51,   146,   168,   169,
+     170,   171,   172,   152,     1,    51,    47,    51,    53,   179,
+      37,    52,    52,    54,    55,    34,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    52,     6,    10,     7,   209,
+     210,    53,     8,     9,    10,    53,   216,   217,    45,    53,
+      47,    53,    49,    51,    53,    51,   224,    51,    48,    48,
+      51,   229,   232,    51,   233,    52,    32,     8,     9,    53,
+      36,    37,    38,    39,    40,    41,    37,    52,    44,    45,
+      32,    47,    53,     9,   254,    51,    52,    54,    37,    55,
+      38,    32,    35,   263,   264,    36,    37,    38,    39,    40,
+      41,     8,     9,    44,    45,    10,    47,    53,    53,     9,
+      51,    52,    10,    32,    55,    53,    36,    37,    38,    39,
+      40,    41,     8,     9,    44,    32,    10,   153,    32,    36,
+      37,    38,    39,    40,    41,    53,    53,    44,    45,    53,
+      47,    12,    12,    66,   228,    52,    32,    54,    55,    -1,
       36,    37,    38,    39,    40,    41,    -1,    -1,    44,    45,
-      -1,    47,    -1,    -1,    -1,    51,    52,    32,    -1,    55,
+      -1,    47,     8,     9,    10,    51,    52,    -1,    -1,    55,
+       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      -1,    -1,    -1,     8,     9,    -1,    32,    -1,    -1,    -1,
+      36,    37,    38,    39,    40,    41,    -1,    -1,    44,    45,
+      -1,    47,    -1,    -1,     8,     9,    52,    32,    -1,    55,
       -1,    36,    37,    38,    39,    40,    41,     8,     9,    44,
-      45,    -1,    47,    -1,    -1,    -1,    -1,    52,    -1,    54,
+      45,    -1,    47,    -1,    -1,    -1,    -1,    52,    32,    -1,
       55,    -1,    36,    37,    38,    39,    40,    41,     8,     9,
-      44,    32,    -1,    -1,    -1,    36,    37,    38,    39,    40,
-      41,    -1,    -1,    44,    45,    -1,    47,    -1,    -1,    -1,
-      51,    52,    32,    -1,    55,    -1,    36,    37,    38,    39,
-      40,    41,     8,     9,    44,    45,    -1,    47,    -1,    -1,
-      -1,    -1,    52,     8,     9,    55,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    32,     8,     9,    -1,
-      36,    37,    38,    39,    40,    41,    -1,    32,    44,    -1,
-      -1,    47,    -1,     8,     9,    -1,    52,    42,    43,    55,
-      45,    32,    47,    -1,     8,     9,    37,    52,    -1,    -1,
-      55,     8,     9,    44,    -1,    -1,    47,    32,     8,     9,
-      -1,    52,     8,     9,    55,    -1,    -1,    -1,    32,    -1,
-      45,    -1,    47,    -1,    -1,    32,    -1,    52,    42,    -1,
-      55,    -1,    32,    47,    -1,    42,    32,    -1,    52,    -1,
-      47,    55,     8,     9,    -1,    52,    -1,    47,    55,     8,
-       9,    47,    52,    -1,    54,    55,    52,    -1,    54,    55,
-      -1,    -1,    -1,    -1,    -1,    -1,    32,    -1,    -1,    -1,
-      -1,    -1,    -1,    32,    -1,    -1,    42,    -1,    -1,    -1,
-      -1,    47,    -1,    -1,    -1,    -1,    52,    -1,    47,    55,
-      -1,    -1,    -1,    52,    -1,    -1,    55,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,     5,     6,     7,     8,
-       9,    10,    11,    12,     6,     7,     8,     9,    10,    11,
-      12
+      44,    32,    -1,    47,    -1,     8,     9,    -1,    52,    -1,
+      -1,    55,     8,     9,    45,    -1,    47,    -1,    -1,    -1,
+      51,    52,    32,    54,    55,    -1,     8,     9,    -1,    32,
+       8,     9,    42,    43,    37,    45,    32,    47,    -1,    -1,
+      -1,    44,    52,    -1,    47,    55,    42,     8,     9,    52,
+      32,    47,    55,    -1,    32,    -1,    52,    -1,    -1,    55,
+       8,     9,    -1,    45,    -1,    47,    -1,    45,    -1,    47,
+      52,    32,    -1,    55,    52,    -1,    -1,    55,     8,     9,
+      -1,    42,    -1,    -1,    32,    -1,    47,     8,     9,    -1,
+      -1,    52,    -1,    -1,    55,    -1,    -1,    -1,    -1,    47,
+      -1,    -1,    32,    -1,    52,    -1,    54,    55,    -1,    -1,
+      -1,    32,    42,    -1,    -1,    -1,    -1,    47,    -1,    -1,
+      -1,    -1,    52,    -1,    -1,    55,    47,    -1,    -1,    -1,
+      -1,    52,    -1,    -1,    55,     5,     6,     7,     8,     9,
+      10,    11,    12,     6,     7,     8,     9,    10,    11,    12
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -852,32 +848,32 @@ static const yytype_uint8 yystos[] =
 {
        0,    57,     0,    58,     1,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    45,    46,    47,    49,    59,    62,
-      49,    51,    63,     8,     9,    32,    36,    37,    38,    39,
-      40,    41,    44,    45,    47,    51,    52,    55,    67,    82,
-      86,    89,    90,    91,    92,    95,    54,    66,    82,    84,
-      88,    64,    84,    65,    82,    10,    45,    46,    51,    71,
-      83,    85,    86,    90,    91,    95,    69,    92,    51,    63,
-      67,    72,    45,    51,    52,    68,    85,    88,    95,    70,
-      89,    79,    89,    80,    84,    73,    84,    74,    84,    75,
-      84,    76,    86,    77,    88,    78,    88,    81,    84,    48,
-      50,    48,    50,    49,    95,    95,     6,     8,     9,    93,
-      82,    37,    44,    95,    97,    95,    52,    52,     9,    42,
-      43,    52,    92,    95,    51,    51,    51,    86,    90,    93,
-      93,    83,    52,    11,    93,    85,    51,    52,    51,    51,
-      51,    51,    51,    51,    51,    51,    51,    61,    97,    60,
-      97,     7,    95,    95,    52,    10,    53,    53,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    53,    37,
-      37,    38,    44,    42,     9,    42,    82,    84,    34,    95,
-      85,    54,    87,    95,    88,    95,    84,    82,    82,    82,
-      82,    82,    84,    59,    59,    93,    33,    35,    44,    94,
-      95,    52,    97,    97,    97,     6,     7,    97,    97,    97,
-      97,    97,    10,    10,    53,    53,    53,    42,    53,    53,
-      51,     9,    32,    96,    51,    51,    48,    48,    51,    51,
-      52,    53,    53,    37,    97,    97,    95,    95,    52,    53,
-      88,    32,     9,    87,    88,    37,    38,    95,    86,    35,
-      10,    53,    53,    37,    38,     9,    32,    53,    95,    10,
-      10,    32,    53,    95,    95,    53,    53
+      28,    29,    30,    31,    45,    47,    49,    59,    61,    49,
+      51,    62,     8,     9,    32,    36,    37,    38,    39,    40,
+      41,    44,    45,    47,    51,    52,    55,    66,    81,    85,
+      88,    89,    90,    91,    94,    54,    65,    81,    83,    87,
+      63,    83,    64,    81,    10,    45,    51,    70,    82,    84,
+      85,    89,    90,    94,    68,    91,    51,    62,    66,    71,
+      45,    51,    52,    67,    84,    87,    94,    69,    88,    78,
+      88,    79,    83,    72,    83,    73,    83,    74,    83,    75,
+      85,    76,    87,    77,    87,    80,    83,    48,    50,    50,
+      49,    94,    94,     6,     8,     9,    92,    81,    37,    44,
+      94,    96,    94,    52,    52,     9,    42,    43,    52,    91,
+      94,    51,    51,    51,    85,    89,    92,    82,    52,    11,
+      92,    84,    51,    52,    51,    51,    51,    51,    51,    51,
+      51,    51,    51,    60,    96,    96,     7,    94,    94,    52,
+      10,    53,    53,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    53,    37,    37,    38,    44,    42,     9,
+      42,    81,    83,    34,    94,    84,    54,    86,    94,    87,
+      94,    83,    81,    81,    81,    81,    81,    83,    59,    92,
+      33,    35,    44,    93,    94,    52,    96,    96,    96,     6,
+       7,    96,    96,    96,    96,    96,    10,    10,    53,    53,
+      53,    42,    53,    53,    51,     9,    32,    95,    51,    51,
+      48,    48,    51,    51,    52,    53,    53,    37,    96,    96,
+      94,    94,    52,    53,    87,    32,     9,    86,    87,    37,
+      38,    94,    85,    35,    10,    53,    53,    37,    38,     9,
+      32,    53,    94,    10,    10,    32,    53,    94,    94,    53,
+      53
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1701,30 +1697,24 @@ yyreduce:
   case 5:
 #line 75 "a.y"
     {
-               if((yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name);
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 7:
-#line 82 "a.y"
-    {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
+               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
+                       yyerror("redeclaration of %s (%s)", (yyvsp[(1) - (2)].sym)->labelname, (yyvsp[(1) - (2)].sym)->name);
                (yyvsp[(1) - (2)].sym)->type = LLAB;
                (yyvsp[(1) - (2)].sym)->value = pc;
        }
     break;
 
-  case 12:
-#line 93 "a.y"
+  case 10:
+#line 89 "a.y"
     {
                (yyvsp[(1) - (3)].sym)->type = LVAR;
                (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 13:
-#line 98 "a.y"
+  case 11:
+#line 94 "a.y"
     {
                if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
                        yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name);
@@ -1732,191 +1722,191 @@ yyreduce:
        }
     break;
 
+  case 12:
+#line 99 "a.y"
+    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
+    break;
+
+  case 13:
+#line 100 "a.y"
+    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
+    break;
+
   case 14:
-#line 103 "a.y"
+#line 101 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 15:
-#line 104 "a.y"
+#line 102 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 16:
-#line 105 "a.y"
+#line 103 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 17:
-#line 106 "a.y"
+#line 104 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 18:
-#line 107 "a.y"
+#line 105 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 19:
-#line 108 "a.y"
+#line 106 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 20:
-#line 109 "a.y"
+#line 107 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 21:
-#line 110 "a.y"
+#line 108 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 22:
-#line 111 "a.y"
+#line 109 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 23:
-#line 112 "a.y"
+#line 110 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 24:
-#line 113 "a.y"
+#line 111 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 25:
-#line 114 "a.y"
+#line 112 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 26:
-#line 115 "a.y"
+#line 113 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 27:
-#line 116 "a.y"
+#line 114 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 28:
-#line 117 "a.y"
+#line 115 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 29:
-#line 118 "a.y"
+#line 116 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 30:
-#line 119 "a.y"
+#line 117 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 31:
 #line 120 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 32:
-#line 121 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 33:
-#line 124 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 34:
-#line 129 "a.y"
+  case 32:
+#line 125 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 35:
-#line 136 "a.y"
+  case 33:
+#line 132 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 36:
-#line 143 "a.y"
+  case 34:
+#line 139 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 37:
-#line 150 "a.y"
+  case 35:
+#line 146 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 38:
-#line 155 "a.y"
+  case 36:
+#line 151 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 39:
-#line 162 "a.y"
+  case 37:
+#line 158 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 40:
-#line 167 "a.y"
+  case 38:
+#line 163 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 41:
-#line 174 "a.y"
+  case 39:
+#line 170 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 42:
-#line 179 "a.y"
+  case 40:
+#line 175 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 43:
-#line 184 "a.y"
+  case 41:
+#line 180 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 44:
-#line 191 "a.y"
+  case 42:
+#line 187 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1924,49 +1914,51 @@ yyreduce:
        }
     break;
 
-  case 45:
-#line 199 "a.y"
+  case 43:
+#line 195 "a.y"
     {
+               settext((yyvsp[(1) - (3)].addr).sym);
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 46:
-#line 204 "a.y"
+  case 44:
+#line 201 "a.y"
     {
+               settext((yyvsp[(1) - (5)].addr).sym);
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
                (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
        }
     break;
 
-  case 47:
-#line 212 "a.y"
+  case 45:
+#line 210 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 48:
-#line 217 "a.y"
+  case 46:
+#line 215 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 51:
-#line 228 "a.y"
+  case 49:
+#line 226 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 52:
-#line 233 "a.y"
+  case 50:
+#line 231 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
@@ -1976,16 +1968,16 @@ yyreduce:
        }
     break;
 
-  case 53:
-#line 243 "a.y"
+  case 51:
+#line 241 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 54:
-#line 248 "a.y"
+  case 52:
+#line 246 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
@@ -1995,32 +1987,32 @@ yyreduce:
        }
     break;
 
-  case 55:
-#line 258 "a.y"
+  case 53:
+#line 256 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 56:
-#line 263 "a.y"
+  case 54:
+#line 261 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 57:
-#line 268 "a.y"
+  case 55:
+#line 266 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 58:
-#line 275 "a.y"
+  case 56:
+#line 273 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
@@ -2028,8 +2020,8 @@ yyreduce:
        }
     break;
 
-  case 59:
-#line 283 "a.y"
+  case 57:
+#line 281 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(3) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
@@ -2039,32 +2031,32 @@ yyreduce:
        }
     break;
 
-  case 60:
-#line 292 "a.y"
+  case 58:
+#line 290 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 61:
-#line 297 "a.y"
+  case 59:
+#line 295 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 62:
-#line 304 "a.y"
+  case 60:
+#line 302 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 63:
-#line 309 "a.y"
+  case 61:
+#line 307 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -2072,8 +2064,8 @@ yyreduce:
        }
     break;
 
-  case 64:
-#line 317 "a.y"
+  case 62:
+#line 315 "a.y"
     {
                if((yyvsp[(1) - (3)].addr).type != D_CONST || (yyvsp[(3) - (3)].addr).type != D_CONST)
                        yyerror("arguments to PCDATA must be integer constants");
@@ -2082,8 +2074,8 @@ yyreduce:
        }
     break;
 
-  case 65:
-#line 326 "a.y"
+  case 63:
+#line 324 "a.y"
     {
                if((yyvsp[(1) - (3)].addr).type != D_CONST)
                        yyerror("index for FUNCDATA must be integer constant");
@@ -2094,22 +2086,22 @@ yyreduce:
        }
     break;
 
-  case 70:
-#line 343 "a.y"
+  case 68:
+#line 341 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 71:
-#line 347 "a.y"
+  case 69:
+#line 345 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 76:
-#line 359 "a.y"
+  case 74:
+#line 357 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_BRANCH;
@@ -2117,84 +2109,76 @@ yyreduce:
        }
     break;
 
-  case 77:
-#line 365 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               if(pass == 2)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name);
-               (yyval.addr).type = D_BRANCH;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 78:
-#line 373 "a.y"
+  case 75:
+#line 363 "a.y"
     {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
                (yyval.addr) = nullgen;
+               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
+                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
                (yyval.addr).type = D_BRANCH;
                (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 79:
-#line 381 "a.y"
+  case 76:
+#line 374 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 80:
-#line 386 "a.y"
+  case 77:
+#line 379 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 81:
-#line 391 "a.y"
+  case 78:
+#line 384 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 82:
-#line 396 "a.y"
+  case 79:
+#line 389 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 83:
-#line 401 "a.y"
+  case 80:
+#line 394 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SP;
        }
     break;
 
-  case 84:
-#line 406 "a.y"
+  case 81:
+#line 399 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 85:
-#line 411 "a.y"
+  case 82:
+#line 404 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 86:
-#line 417 "a.y"
+  case 83:
+#line 410 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_CONST;
@@ -2202,8 +2186,8 @@ yyreduce:
        }
     break;
 
-  case 87:
-#line 425 "a.y"
+  case 84:
+#line 418 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_CONST;
@@ -2211,8 +2195,8 @@ yyreduce:
        }
     break;
 
-  case 88:
-#line 431 "a.y"
+  case 85:
+#line 424 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
                (yyval.addr).index = (yyvsp[(2) - (2)].addr).type;
@@ -2225,8 +2209,8 @@ yyreduce:
        }
     break;
 
-  case 89:
-#line 442 "a.y"
+  case 86:
+#line 435 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SCONST;
@@ -2234,8 +2218,8 @@ yyreduce:
        }
     break;
 
-  case 90:
-#line 448 "a.y"
+  case 87:
+#line 441 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2243,8 +2227,8 @@ yyreduce:
        }
     break;
 
-  case 91:
-#line 454 "a.y"
+  case 88:
+#line 447 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2252,8 +2236,8 @@ yyreduce:
        }
     break;
 
-  case 92:
-#line 460 "a.y"
+  case 89:
+#line 453 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2261,8 +2245,8 @@ yyreduce:
        }
     break;
 
-  case 93:
-#line 466 "a.y"
+  case 90:
+#line 459 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2270,8 +2254,8 @@ yyreduce:
        }
     break;
 
-  case 96:
-#line 478 "a.y"
+  case 93:
+#line 471 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_NONE;
@@ -2279,8 +2263,8 @@ yyreduce:
        }
     break;
 
-  case 97:
-#line 484 "a.y"
+  case 94:
+#line 477 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2288,8 +2272,8 @@ yyreduce:
        }
     break;
 
-  case 98:
-#line 490 "a.y"
+  case 95:
+#line 483 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_SP;
@@ -2297,8 +2281,8 @@ yyreduce:
        }
     break;
 
-  case 99:
-#line 496 "a.y"
+  case 96:
+#line 489 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2306,8 +2290,8 @@ yyreduce:
        }
     break;
 
-  case 100:
-#line 502 "a.y"
+  case 97:
+#line 495 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_NONE;
@@ -2318,8 +2302,8 @@ yyreduce:
        }
     break;
 
-  case 101:
-#line 511 "a.y"
+  case 98:
+#line 504 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2330,8 +2314,8 @@ yyreduce:
        }
     break;
 
-  case 102:
-#line 520 "a.y"
+  case 99:
+#line 513 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2342,24 +2326,24 @@ yyreduce:
        }
     break;
 
-  case 103:
-#line 529 "a.y"
+  case 100:
+#line 522 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(2) - (3)].lval);
        }
     break;
 
-  case 104:
-#line 534 "a.y"
+  case 101:
+#line 527 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_SP;
        }
     break;
 
-  case 105:
-#line 539 "a.y"
+  case 102:
+#line 532 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_NONE;
@@ -2369,8 +2353,8 @@ yyreduce:
        }
     break;
 
-  case 106:
-#line 547 "a.y"
+  case 103:
+#line 540 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2380,15 +2364,15 @@ yyreduce:
        }
     break;
 
-  case 107:
-#line 557 "a.y"
+  case 104:
+#line 550 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 108:
-#line 561 "a.y"
+  case 105:
+#line 554 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (6)].addr);
                (yyval.addr).index = (yyvsp[(3) - (6)].lval);
@@ -2397,8 +2381,8 @@ yyreduce:
        }
     break;
 
-  case 109:
-#line 570 "a.y"
+  case 106:
+#line 563 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(4) - (5)].lval);
@@ -2407,8 +2391,8 @@ yyreduce:
        }
     break;
 
-  case 110:
-#line 577 "a.y"
+  case 107:
+#line 570 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_STATIC;
@@ -2417,166 +2401,166 @@ yyreduce:
        }
     break;
 
-  case 111:
-#line 585 "a.y"
+  case 108:
+#line 578 "a.y"
     {
                (yyval.lval) = 0;
        }
     break;
 
-  case 112:
-#line 589 "a.y"
+  case 109:
+#line 582 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 113:
-#line 593 "a.y"
+  case 110:
+#line 586 "a.y"
     {
                (yyval.lval) = -(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 115:
-#line 600 "a.y"
+  case 112:
+#line 593 "a.y"
     {
                (yyval.lval) = D_AUTO;
        }
     break;
 
-  case 118:
-#line 608 "a.y"
+  case 115:
+#line 601 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
        }
     break;
 
-  case 119:
-#line 612 "a.y"
+  case 116:
+#line 605 "a.y"
     {
                (yyval.lval) = -(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 120:
-#line 616 "a.y"
+  case 117:
+#line 609 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 121:
-#line 620 "a.y"
+  case 118:
+#line 613 "a.y"
     {
                (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 122:
-#line 624 "a.y"
+  case 119:
+#line 617 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (3)].lval);
        }
     break;
 
-  case 123:
-#line 630 "a.y"
+  case 120:
+#line 623 "a.y"
     {
                (yyval.lval) = ((yyvsp[(1) - (1)].lval) & 0xffffffffLL) +
                        ((vlong)ArgsSizeUnknown << 32);
        }
     break;
 
-  case 124:
-#line 635 "a.y"
+  case 121:
+#line 628 "a.y"
     {
                (yyval.lval) = (-(yyvsp[(2) - (2)].lval) & 0xffffffffLL) +
                        ((vlong)ArgsSizeUnknown << 32);
        }
     break;
 
-  case 125:
-#line 640 "a.y"
+  case 122:
+#line 633 "a.y"
     {
                (yyval.lval) = ((yyvsp[(1) - (3)].lval) & 0xffffffffLL) +
                        (((yyvsp[(3) - (3)].lval) & 0xffffLL) << 32);
        }
     break;
 
-  case 126:
-#line 645 "a.y"
+  case 123:
+#line 638 "a.y"
     {
                (yyval.lval) = (-(yyvsp[(2) - (4)].lval) & 0xffffffffLL) +
                        (((yyvsp[(4) - (4)].lval) & 0xffffLL) << 32);
        }
     break;
 
-  case 128:
-#line 653 "a.y"
+  case 125:
+#line 646 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 129:
-#line 657 "a.y"
+  case 126:
+#line 650 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 130:
-#line 661 "a.y"
+  case 127:
+#line 654 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 131:
-#line 665 "a.y"
+  case 128:
+#line 658 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 132:
-#line 669 "a.y"
+  case 129:
+#line 662 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 133:
-#line 673 "a.y"
+  case 130:
+#line 666 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 134:
-#line 677 "a.y"
+  case 131:
+#line 670 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 135:
-#line 681 "a.y"
+  case 132:
+#line 674 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 136:
-#line 685 "a.y"
+  case 133:
+#line 678 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 137:
-#line 689 "a.y"
+  case 134:
+#line 682 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
        }
@@ -2584,7 +2568,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 2588 "y.tab.c"
+#line 2572 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/src/cmd/6c/Makefile b/src/cmd/6c/Makefile
deleted file mode 100644 (file)
index 3f528d7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
deleted file mode 100644 (file)
index 68dd7bb..0000000
+++ /dev/null
@@ -1,2046 +0,0 @@
-// Inferno utils/6c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/cgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-/* ,x/^(print|prtree)\(/i/\/\/ */
-int castup(Type*, Type*);
-int vaddr(Node *n, int a);
-
-void
-cgen(Node *n, Node *nn)
-{
-       Node *l, *r, *t;
-       Prog *p1;
-       Node nod, nod1, nod2, nod3, nod4;
-       int o, hardleft;
-       int32 v, curs;
-       vlong c;
-
-       if(debug['g']) {
-               prtree(nn, "cgen lhs");
-               prtree(n, "cgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
-               sugen(n, nn, n->type->width);
-               return;
-       }
-       l = n->left;
-       r = n->right;
-       o = n->op;
-       
-       if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
-               gmove(n, nn);
-               return;
-       }
-
-       if(n->addable >= INDEXED) {
-               if(nn == Z) {
-                       switch(o) {
-                       default:
-                               nullwarn(Z, Z);
-                               break;
-                       case OINDEX:
-                               nullwarn(l, r);
-                               break;
-                       }
-                       return;
-               }
-               gmove(n, nn);
-               return;
-       }
-       curs = cursafe;
-
-       if(l->complex >= FNX)
-       if(r != Z && r->complex >= FNX)
-       switch(o) {
-       default:
-               if(cond(o) && typesu[l->type->etype])
-                       break;
-
-               regret(&nod, r, 0, 0);
-               cgen(r, &nod);
-
-               regsalloc(&nod1, r);
-               gmove(&nod, &nod1);
-
-               regfree(&nod);
-               nod = *n;
-               nod.right = &nod1;
-
-               cgen(&nod, nn);
-               return;
-
-       case OFUNC:
-       case OCOMMA:
-       case OANDAND:
-       case OOROR:
-       case OCOND:
-       case ODOT:
-               break;
-       }
-
-       hardleft = l->addable < INDEXED || l->complex >= FNX;
-       switch(o) {
-       default:
-               diag(n, "unknown op in cgen: %O", o);
-               break;
-
-       case ONEG:
-       case OCOM:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               regalloc(&nod, l, nn);
-               cgen(l, &nod);
-               gopcode(o, n->type, Z, &nod);
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       case OAS:
-               if(l->op == OBIT)
-                       goto bitas;
-               if(!hardleft) {
-                       if(nn != Z || r->addable < INDEXED || hardconst(r)) {
-                               if(r->complex >= FNX && nn == Z)
-                                       regret(&nod, r, 0, 0);
-                               else
-                                       regalloc(&nod, r, nn);
-                               cgen(r, &nod);
-                               gmove(&nod, l);
-                               if(nn != Z)
-                                       gmove(&nod, nn);
-                               regfree(&nod);
-                       } else
-                               gmove(r, l);
-                       break;
-               }
-               if(l->complex >= r->complex) {
-                       if(l->op == OINDEX && immconst(r)) {
-                               gmove(r, l);
-                               break;
-                       }
-                       reglcgen(&nod1, l, Z);
-                       if(r->addable >= INDEXED && !hardconst(r)) {
-                               gmove(r, &nod1);
-                               if(nn != Z)
-                                       gmove(r, nn);
-                               regfree(&nod1);
-                               break;
-                       }
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-                       reglcgen(&nod1, l, Z);
-               }
-               gmove(&nod, &nod1);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       bitas:
-               n = l->left;
-               regalloc(&nod, r, nn);
-               if(l->complex >= r->complex) {
-                       reglcgen(&nod1, n, Z);
-                       cgen(r, &nod);
-               } else {
-                       cgen(r, &nod);
-                       reglcgen(&nod1, n, Z);
-               }
-               regalloc(&nod2, n, Z);
-               gmove(&nod1, &nod2);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OBIT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               bitload(n, &nod, Z, Z, nn);
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(r->op == OCONST) {
-                       if(r->vconst == 0) {
-                               cgen(l, nn);
-                               break;
-                       }
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(o == OASHL && r->vconst == 1)
-                               gopcode(OADD, n->type, &nod, &nod);
-                       else
-                               gopcode(o, n->type, r, &nod);
-                       gmove(&nod, nn);
-                       regfree(&nod);
-                       break;
-               }
-
-               /*
-                * get nod to be D_CX
-                */
-               if(nodreg(&nod, nn, D_CX)) {
-                       regsalloc(&nod1, n);
-                       gmove(&nod, &nod1);
-                       cgen(n, &nod);          /* probably a bug */
-                       gmove(&nod, nn);
-                       gmove(&nod1, &nod);
-                       break;
-               }
-               reg[D_CX]++;
-               if(nn->op == OREGISTER && nn->reg == D_CX)
-                       regalloc(&nod1, l, Z);
-               else
-                       regalloc(&nod1, l, nn);
-               if(r->complex >= l->complex) {
-                       cgen(r, &nod);
-                       cgen(l, &nod1);
-               } else {
-                       cgen(l, &nod1);
-                       cgen(r, &nod);
-               }
-               gopcode(o, n->type, &nod, &nod1);
-               gmove(&nod1, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OADD:
-       case OSUB:
-       case OOR:
-       case OXOR:
-       case OAND:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(typefd[n->type->etype])
-                       goto fop;
-               if(r->op == OCONST) {
-                       if(r->vconst == 0 && o != OAND) {
-                               cgen(l, 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;
-                       if(c > 0 && c <= 3) {
-                               if(l->left->complex >= r->complex) {
-                                       regalloc(&nod, l->left, nn);
-                                       cgen(l->left, &nod);
-                                       if(r->addable < INDEXED) {
-                                               regalloc(&nod1, r, Z);
-                                               cgen(r, &nod1);
-                                               genmuladd(&nod, &nod, 1 << c, &nod1);
-                                               regfree(&nod1);
-                                       }
-                                       else
-                                               genmuladd(&nod, &nod, 1 << c, r);
-                               }
-                               else {
-                                       regalloc(&nod, r, nn);
-                                       cgen(r, &nod);
-                                       regalloc(&nod1, l->left, Z);
-                                       cgen(l->left, &nod1);
-                                       genmuladd(&nod, &nod1, 1 << c, &nod);
-                                       regfree(&nod1);
-                               }
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               break;
-                       }
-               }
-               if(r->addable >= INDEXED && !hardconst(r)) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       gopcode(o, n->type, r, &nod);
-                       gmove(&nod, nn);
-                       regfree(&nod);
-                       break;
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       regalloc(&nod1, r, Z);
-                       cgen(r, &nod1);
-                       gopcode(o, n->type, &nod1, &nod);
-               } else {
-                       regalloc(&nod1, r, nn);
-                       cgen(r, &nod1);
-                       regalloc(&nod, l, Z);
-                       cgen(l, &nod);
-                       gopcode(o, n->type, &nod1, &nod);
-               }
-               gmove(&nod, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OLMOD:
-       case OMOD:
-       case OLMUL:
-       case OLDIV:
-       case OMUL:
-       case ODIV:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(typefd[n->type->etype])
-                       goto fop;
-               if(r->op == OCONST && typechl[n->type->etype]) {        /* TO DO */
-                       SET(v);
-                       switch(o) {
-                       case ODIV:
-                       case OMOD:
-                               c = r->vconst;
-                               if(c < 0)
-                                       c = -c;
-                               v = xlog2(c);
-                               if(v < 0)
-                                       break;
-                               /* fall thru */
-                       case OMUL:
-                       case OLMUL:
-                               regalloc(&nod, l, nn);
-                               cgen(l, &nod);
-                               switch(o) {
-                               case OMUL:
-                               case OLMUL:
-                                       mulgen(n->type, r, &nod);
-                                       break;
-                               case ODIV:
-                                       sdiv2(r->vconst, v, l, &nod);
-                                       break;
-                               case OMOD:
-                                       smod2(r->vconst, v, l, &nod);
-                                       break;
-                               }
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               goto done;
-                       case OLDIV:
-                               c = r->vconst;
-                               if((c & 0x80000000) == 0)
-                                       break;
-                               regalloc(&nod1, l, Z);
-                               cgen(l, &nod1);
-                               regalloc(&nod, l, nn);
-                               zeroregm(&nod);
-                               gins(ACMPL, &nod1, nodconst(c));
-                               gins(ASBBL, nodconst(-1), &nod);
-                               regfree(&nod1);
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               goto done;
-                       }
-               }
-
-               if(o == OMUL || o == OLMUL) {
-                       if(l->addable >= INDEXED) {
-                               t = l;
-                               l = r;
-                               r = t;
-                       }
-                       reg[D_DX]++; // for gopcode case OMUL
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(r->addable < INDEXED || hardconst(r)) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               gopcode(OMUL, n->type, &nod1, &nod);
-                               regfree(&nod1);
-                       }else
-                               gopcode(OMUL, n->type, r, &nod);        /* addressible */
-                       gmove(&nod, nn);
-                       regfree(&nod);
-                       reg[D_DX]--;
-                       break;
-               }
-
-               /*
-                * get nod to be D_AX
-                * get nod1 to be D_DX
-                */
-               if(nodreg(&nod, nn, D_AX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod, &nod2);
-                       v = reg[D_AX];
-                       reg[D_AX] = 0;
-
-                       if(isreg(l, D_AX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_AX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod);
-                       reg[D_AX] = v;
-                       break;
-               }
-               if(nodreg(&nod1, nn, D_DX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod1, &nod2);
-                       v = reg[D_DX];
-                       reg[D_DX] = 0;
-
-                       if(isreg(l, D_DX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_DX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod1);
-                       reg[D_DX] = v;
-                       break;
-               }
-               reg[D_AX]++;
-
-               if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
-                       reg[D_DX]++;
-                       if(l->addable < INDEXED) {
-                               regalloc(&nod2, l, Z);
-                               cgen(l, &nod2);
-                               l = &nod2;
-                       }
-                       if(o == ODIV)
-                               sdivgen(l, r, &nod, &nod1);
-                       else
-                               udivgen(l, r, &nod, &nod1);
-                       gmove(&nod1, nn);
-                       if(l == &nod2)
-                               regfree(l);
-                       goto freeaxdx;
-               }
-
-               if(l->complex >= r->complex) {
-                       cgen(l, &nod);
-                       reg[D_DX]++;
-                       if(o == ODIV || o == OMOD)
-                               gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
-                       if(o == OLDIV || o == OLMOD)
-                               zeroregm(&nod1);
-                       if(r->addable < INDEXED || r->op == OCONST) {
-                               regsalloc(&nod3, r);
-                               cgen(r, &nod3);
-                               gopcode(o, n->type, &nod3, Z);
-                       } else
-                               gopcode(o, n->type, r, Z);
-               } else {
-                       regsalloc(&nod3, r);
-                       cgen(r, &nod3);
-                       cgen(l, &nod);
-                       reg[D_DX]++;
-                       if(o == ODIV || o == OMOD)
-                               gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
-                       if(o == OLDIV || o == OLMOD)
-                               zeroregm(&nod1);
-                       gopcode(o, n->type, &nod3, Z);
-               }
-               if(o == OMOD || o == OLMOD)
-                       gmove(&nod1, nn);
-               else
-                       gmove(&nod, nn);
-       freeaxdx:
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OASLSHR:
-       case OASASHL:
-       case OASASHR:
-               if(r->op == OCONST)
-                       goto asand;
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(typefd[n->type->etype])
-                       goto asand;     /* can this happen? */
-
-               /*
-                * get nod to be D_CX
-                */
-               if(nodreg(&nod, nn, D_CX)) {
-                       regsalloc(&nod1, n);
-                       gmove(&nod, &nod1);
-                       cgen(n, &nod);
-                       if(nn != Z)
-                               gmove(&nod, nn);
-                       gmove(&nod1, &nod);
-                       break;
-               }
-               reg[D_CX]++;
-
-               if(r->complex >= l->complex) {
-                       cgen(r, &nod);
-                       if(hardleft)
-                               reglcgen(&nod1, l, Z);
-                       else
-                               nod1 = *l;
-               } else {
-                       if(hardleft)
-                               reglcgen(&nod1, l, Z);
-                       else
-                               nod1 = *l;
-                       cgen(r, &nod);
-               }
-
-               gopcode(o, l->type, &nod, &nod1);
-               regfree(&nod);
-               if(nn != Z)
-                       gmove(&nod1, nn);
-               if(hardleft)
-                       regfree(&nod1);
-               break;
-
-       case OASAND:
-       case OASADD:
-       case OASSUB:
-       case OASXOR:
-       case OASOR:
-       asand:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(typefd[l->type->etype] || typefd[r->type->etype])
-                       goto asfop;
-               if(l->complex >= r->complex) {
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       if(!immconst(r)) {
-                               regalloc(&nod1, r, nn);
-                               cgen(r, &nod1);
-                               gopcode(o, l->type, &nod1, &nod);
-                               regfree(&nod1);
-                       } else
-                               gopcode(o, l->type, r, &nod);
-               } else {
-                       regalloc(&nod1, r, nn);
-                       cgen(r, &nod1);
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       gopcode(o, l->type, &nod1, &nod);
-                       regfree(&nod1);
-               }
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       asfop:
-               if(l->complex >= r->complex) {
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       if(r->addable < INDEXED){
-                               regalloc(&nod1, r, nn);
-                               cgen(r, &nod1);
-                       }else
-                               nod1 = *r;
-                       regalloc(&nod2, r, Z);
-                       gmove(&nod, &nod2);
-                       gopcode(o, r->type, &nod1, &nod2);
-                       gmove(&nod2, &nod);
-                       regfree(&nod2);
-                       if(r->addable < INDEXED)
-                               regfree(&nod1);
-               } else {
-                       regalloc(&nod1, r, nn);
-                       cgen(r, &nod1);
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       if(o != OASMUL && o != OASADD) {
-                               regalloc(&nod2, r, Z);
-                               gmove(&nod, &nod2);
-                               gopcode(o, r->type, &nod1, &nod2);
-                               regfree(&nod1);
-                               gmove(&nod2, &nod);
-                               regfree(&nod2);
-                       } else {
-                               gopcode(o, r->type, &nod, &nod1);
-                               gmove(&nod1, &nod);
-                               regfree(&nod1);
-                       }
-               }
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       case OASLMUL:
-       case OASLDIV:
-       case OASLMOD:
-       case OASMUL:
-       case OASDIV:
-       case OASMOD:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(typefd[n->type->etype] || typefd[r->type->etype])
-                       goto asfop;
-               if(r->op == OCONST && typechl[n->type->etype]) {
-                       SET(v);
-                       switch(o) {
-                       case OASDIV:
-                       case OASMOD:
-                               c = r->vconst;
-                               if(c < 0)
-                                       c = -c;
-                               v = xlog2(c);
-                               if(v < 0)
-                                       break;
-                               /* fall thru */
-                       case OASMUL:
-                       case OASLMUL:
-                               if(hardleft)
-                                       reglcgen(&nod2, l, Z);
-                               else
-                                       nod2 = *l;
-                               regalloc(&nod, l, nn);
-                               cgen(&nod2, &nod);
-                               switch(o) {
-                               case OASMUL:
-                               case OASLMUL:
-                                       mulgen(n->type, r, &nod);
-                                       break;
-                               case OASDIV:
-                                       sdiv2(r->vconst, v, l, &nod);
-                                       break;
-                               case OASMOD:
-                                       smod2(r->vconst, v, l, &nod);
-                                       break;
-                               }
-                       havev:
-                               gmove(&nod, &nod2);
-                               if(nn != Z)
-                                       gmove(&nod, nn);
-                               if(hardleft)
-                                       regfree(&nod2);
-                               regfree(&nod);
-                               goto done;
-                       case OASLDIV:
-                               c = r->vconst;
-                               if((c & 0x80000000) == 0)
-                                       break;
-                               if(hardleft)
-                                       reglcgen(&nod2, l, Z);
-                               else
-                                       nod2 = *l;
-                               regalloc(&nod1, l, nn);
-                               cgen(&nod2, &nod1);
-                               regalloc(&nod, l, nn);
-                               zeroregm(&nod);
-                               gins(ACMPL, &nod1, nodconst(c));
-                               gins(ASBBL, nodconst(-1), &nod);
-                               regfree(&nod1);
-                               goto havev;
-                       }
-               }
-
-               if(o == OASMUL) {
-                       /* should favour AX */
-                       regalloc(&nod, l, nn);
-                       if(r->complex >= FNX) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               r = &nod1;
-                       }
-                       if(hardleft)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       cgen(&nod2, &nod);
-                       if(r->addable < INDEXED || hardconst(r)) {
-                               if(r->complex < FNX) {
-                                       regalloc(&nod1, r, Z);
-                                       cgen(r, &nod1);
-                               }
-                               gopcode(OASMUL, n->type, &nod1, &nod);
-                               regfree(&nod1);
-                       }
-                       else
-                               gopcode(OASMUL, n->type, r, &nod);
-                       if(r == &nod1)
-                               regfree(r);
-                       gmove(&nod, &nod2);
-                       if(nn != Z)
-                               gmove(&nod, nn);
-                       regfree(&nod);
-                       if(hardleft)
-                               regfree(&nod2);
-                       break;
-               }
-
-               /*
-                * get nod to be D_AX
-                * get nod1 to be D_DX
-                */
-               if(nodreg(&nod, nn, D_AX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod, &nod2);
-                       v = reg[D_AX];
-                       reg[D_AX] = 0;
-
-                       if(isreg(l, D_AX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_AX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod);
-                       reg[D_AX] = v;
-                       break;
-               }
-               if(nodreg(&nod1, nn, D_DX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod1, &nod2);
-                       v = reg[D_DX];
-                       reg[D_DX] = 0;
-
-                       if(isreg(l, D_DX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_DX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod1);
-                       reg[D_DX] = v;
-                       break;
-               }
-               reg[D_AX]++;
-               reg[D_DX]++;
-
-               if(l->complex >= r->complex) {
-                       if(hardleft)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       cgen(&nod2, &nod);
-                       if(r->op == OCONST && typechl[r->type->etype]) {
-                               switch(o) {
-                               case OASDIV:
-                                       sdivgen(&nod2, r, &nod, &nod1);
-                                       goto divdone;
-                               case OASLDIV:
-                                       udivgen(&nod2, r, &nod, &nod1);
-                               divdone:
-                                       gmove(&nod1, &nod2);
-                                       if(nn != Z)
-                                               gmove(&nod1, nn);
-                                       goto freelxaxdx;
-                               }
-                       }
-                       if(o == OASDIV || o == OASMOD)
-                               gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
-                       if(o == OASLDIV || o == OASLMOD)
-                               zeroregm(&nod1);
-                       if(r->addable < INDEXED || r->op == OCONST ||
-                          !typeil[r->type->etype]) {
-                               regalloc(&nod3, r, Z);
-                               cgen(r, &nod3);
-                               gopcode(o, l->type, &nod3, Z);
-                               regfree(&nod3);
-                       } else
-                               gopcode(o, n->type, r, Z);
-               } else {
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-                       if(hardleft)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       cgen(&nod2, &nod);
-                       if(o == OASDIV || o == OASMOD)
-                               gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
-                       if(o == OASLDIV || o == OASLMOD)
-                               zeroregm(&nod1);
-                       gopcode(o, l->type, &nod3, Z);
-                       regfree(&nod3);
-               }
-               if(o == OASMOD || o == OASLMOD) {
-                       gmove(&nod1, &nod2);
-                       if(nn != Z)
-                               gmove(&nod1, nn);
-               } else {
-                       gmove(&nod, &nod2);
-                       if(nn != Z)
-                               gmove(&nod, nn);
-               }
-       freelxaxdx:
-               if(hardleft)
-                       regfree(&nod2);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       fop:
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(r->addable < INDEXED) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               gopcode(o, n->type, &nod1, &nod);
-                               regfree(&nod1);
-                       } else
-                               gopcode(o, n->type, r, &nod);
-               } else {
-                       /* TO DO: could do better with r->addable >= INDEXED */
-                       regalloc(&nod1, r, Z);
-                       cgen(r, &nod1);
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       gopcode(o, n->type, &nod1, &nod);
-                       regfree(&nod1);
-               }
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       asbitop:
-               regalloc(&nod4, n, nn);
-               if(l->complex >= r->complex) {
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-               } else {
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-               }
-               gmove(&nod, &nod4);
-
-               {       /* TO DO: check floating point source */
-                       Node onod;
-
-                       /* incredible grot ... */
-                       onod = nod3;
-                       onod.op = o;
-                       onod.complex = 2;
-                       onod.addable = 0;
-                       onod.type = tfield;
-                       onod.left = &nod4;
-                       onod.right = &nod3;
-                       cgen(&onod, Z);
-               }
-               regfree(&nod3);
-               gmove(&nod4, &nod);
-               regfree(&nod4);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OADDR:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               lcgen(l, nn);
-               break;
-
-       case OFUNC:
-               if(l->complex >= FNX) {
-                       if(l->op != OIND)
-                               diag(n, "bad function call");
-
-                       regret(&nod, l->left, 0, 0);
-                       cgen(l->left, &nod);
-                       regsalloc(&nod1, l->left);
-                       gmove(&nod, &nod1);
-                       regfree(&nod);
-
-                       nod = *n;
-                       nod.left = &nod2;
-                       nod2 = *l;
-                       nod2.left = &nod1;
-                       nod2.complex = 1;
-                       cgen(&nod, nn);
-
-                       return;
-               }
-               gargs(r, &nod, &nod1);
-               if(l->addable < INDEXED) {
-                       reglcgen(&nod, l, nn);
-                       nod.op = OREGISTER;
-                       gopcode(OFUNC, n->type, Z, &nod);
-                       regfree(&nod);
-               } else
-                       gopcode(OFUNC, n->type, Z, l);
-               if(REGARG >= 0 && reg[REGARG])
-                       reg[REGARG]--;
-               regret(&nod, n, l->type, 1); // update maxarg if nothing else
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(nod.op == OREGISTER)
-                       regfree(&nod);
-               break;
-
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               regialloc(&nod, n, nn);
-               r = l;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r)) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       cgen(l, &nod);
-                       nod.xoffset += v;
-                       r->vconst = v;
-               } else
-                       cgen(l, &nod);
-               regind(&nod, n);
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHI:
-       case OHS:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OANDAND:
-       case OOROR:
-               boolgen(n, 1, nn);
-               if(nn == Z)
-                       patch(p, pc);
-               break;
-
-       case ONOT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OCOMMA:
-               cgen(l, Z);
-               cgen(r, nn);
-               break;
-
-       case OCAST:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               /*
-                * convert from types l->n->nn
-                */
-               if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
-                       /* both null, gen l->nn */
-                       cgen(l, nn);
-                       break;
-               }
-               if(ewidth[n->type->etype] < ewidth[l->type->etype]){
-                       if(l->type->etype == TIND && typechlp[n->type->etype])
-                               warn(n, "conversion of pointer to shorter integer");
-               }else if(0){
-                       if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
-                               if(typefd[l->type->etype] != typefd[nn->type->etype])
-                                       regalloc(&nod, l, nn);
-                               else
-                                       regalloc(&nod, nn, nn);
-                               cgen(l, &nod);
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               break;
-                       }
-               }
-               regalloc(&nod, l, nn);
-               cgen(l, &nod);
-               regalloc(&nod1, n, &nod);
-               gmove(&nod, &nod1);
-               gmove(&nod1, nn);
-               regfree(&nod1);
-               regfree(&nod);
-               break;
-
-       case ODOT:
-               sugen(l, nodrat, l->type->width);
-               if(nn == Z)
-                       break;
-               warn(n, "non-interruptable temporary");
-               nod = *nodrat;
-               if(!r || r->op != OCONST) {
-                       diag(n, "DOT and no offset");
-                       break;
-               }
-               nod.xoffset += (int32)r->vconst;
-               nod.type = n->type;
-               cgen(&nod, nn);
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               cgen(r->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               cgen(r->right, nn);
-               patch(p1, pc);
-               break;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPOSTDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-               if(nn == Z)
-                       goto pre;
-
-               if(hardleft)
-                       reglcgen(&nod, l, Z);
-               else
-                       nod = *l;
-
-               gmove(&nod, nn);
-               if(typefd[n->type->etype]) {
-                       regalloc(&nod1, l, Z);
-                       gmove(&nod, &nod1);
-                       if(v < 0)
-                               gopcode(OSUB, n->type, nodfconst(-v), &nod1);
-                       else
-                               gopcode(OADD, n->type, nodfconst(v), &nod1);
-                       gmove(&nod1, &nod);
-                       regfree(&nod1);
-               } else
-                       gopcode(OADD, n->type, nodconst(v), &nod);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       case OPREINC:
-       case OPREDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPREDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-
-       pre:
-               if(hardleft)
-                       reglcgen(&nod, l, Z);
-               else
-                       nod = *l;
-               if(typefd[n->type->etype]) {
-                       regalloc(&nod1, l, Z);
-                       gmove(&nod, &nod1);
-                       if(v < 0)
-                               gopcode(OSUB, n->type, nodfconst(-v), &nod1);
-                       else
-                               gopcode(OADD, n->type, nodfconst(v), &nod1);
-                       gmove(&nod1, &nod);
-                       regfree(&nod1);
-               } else
-                       gopcode(OADD, n->type, nodconst(v), &nod);
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       bitinc:
-               if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
-                       bitload(l, &nod, &nod1, &nod2, Z);
-                       gmove(&nod, nn);
-                       gopcode(OADD, tfield, nodconst(v), &nod);
-                       bitstore(l, &nod, &nod1, &nod2, Z);
-                       break;
-               }
-               bitload(l, &nod, &nod1, &nod2, nn);
-               gopcode(OADD, tfield, nodconst(v), &nod);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-       }
-done:
-       cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
-       Node *r;
-       int32 v;
-
-       regialloc(t, n, nn);
-       if(n->op == OIND) {
-               r = n->left;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r)) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       lcgen(n, t);
-                       t->xoffset += v;
-                       r->vconst = v;
-                       regind(t, n);
-                       return;
-               }
-       }
-       lcgen(n, t);
-       regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
-       Prog *p1;
-       Node nod;
-
-       if(debug['g']) {
-               prtree(nn, "lcgen lhs");
-               prtree(n, "lcgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(nn == Z) {
-               nn = &nod;
-               regalloc(&nod, n, Z);
-       }
-       switch(n->op) {
-       default:
-               if(n->addable < INDEXED) {
-                       diag(n, "unknown op in lcgen: %O", n->op);
-                       break;
-               }
-               gopcode(OADDR, n->type, n, nn);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, n->left);
-               lcgen(n->right, nn);
-               break;
-
-       case OIND:
-               cgen(n->left, nn);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               lcgen(n->right->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               lcgen(n->right->right, nn);
-               patch(p1, pc);
-               break;
-       }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
-       if(n->type == T)
-               gbranch(OGOTO);
-       else
-               boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
-       int o;
-       Prog *p1, *p2, *p3;
-       Node *l, *r, nod, nod1;
-       int32 curs;
-
-       if(debug['g']) {
-               print("boolgen %d\n", true);
-               prtree(nn, "boolgen lhs");
-               prtree(n, "boolgen");
-       }
-       curs = cursafe;
-       l = n->left;
-       r = n->right;
-       switch(n->op) {
-
-       default:
-               o = ONE;
-               if(true)
-                       o = OEQ;
-               /* bad, 13 is address of external that becomes constant */
-               if(n->addable >= INDEXED && n->addable != 13) {
-                       if(typefd[n->type->etype]) {
-                               regalloc(&nod1, n, Z);
-                               gmove(nodfconst(0.0), &nod1);   /* TO DO: FREGZERO */
-                               gopcode(o, n->type, n, &nod1);
-                               regfree(&nod1);
-                       } else
-                               gopcode(o, n->type, n, nodconst(0));
-                       goto com;
-               }
-               regalloc(&nod, n, nn);
-               cgen(n, &nod);
-               if(typefd[n->type->etype]) {
-                       regalloc(&nod1, n, Z);
-                       gmove(nodfconst(0.0), &nod1);   /* TO DO: FREGZERO */
-                       gopcode(o, n->type, &nod, &nod1);
-                       regfree(&nod1);
-               } else
-                       gopcode(o, n->type, &nod, nodconst(0));
-               regfree(&nod);
-               goto com;
-
-       case OCONST:
-               o = vconst(n);
-               if(!true)
-                       o = !o;
-               gbranch(OGOTO);
-               if(o) {
-                       p1 = p;
-                       gbranch(OGOTO);
-                       patch(p1, pc);
-               }
-               goto com;
-
-       case OCOMMA:
-               cgen(l, Z);
-               boolgen(r, true, nn);
-               break;
-
-       case ONOT:
-               boolgen(l, !true, nn);
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               bcgen(r->left, true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               bcgen(r->right, !true);
-               patch(p2, pc);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               bcgen(l, true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               patch(p1, pc);
-               gbranch(OGOTO);
-               patch(p2, pc);
-               goto com;
-
-       case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bcgen(l, !true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               o = n->op;
-               if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
-                       // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
-                       // Jump around instead.
-                       boolgen(n, 0, Z);
-                       p1 = p;
-                       gbranch(OGOTO);
-                       patch(p1, pc);
-                       goto com;
-               }
-               if(true)
-                       o = comrel[relindex(o)];
-               if(l->complex >= FNX && r->complex >= FNX) {
-                       regret(&nod, r, 0, 0);
-                       cgen(r, &nod);
-                       regsalloc(&nod1, r);
-                       gmove(&nod, &nod1);
-                       regfree(&nod);
-                       nod = *n;
-                       nod.right = &nod1;
-                       boolgen(&nod, true, nn);
-                       break;
-               }
-               if(immconst(l)) {
-                       // NOTE: Reversing the comparison here is wrong
-                       // for floating point ordering comparisons involving NaN,
-                       // but we don't have any of those yet so we don't
-                       // bother worrying about it.
-                       o = invrel[relindex(o)];
-                       /* bad, 13 is address of external that becomes constant */
-                       if(r->addable < INDEXED || r->addable == 13) {
-                               regalloc(&nod, r, nn);
-                               cgen(r, &nod);
-                               gopcode(o, l->type, &nod, l);
-                               regfree(&nod);
-                       } else
-                               gopcode(o, l->type, r, l);
-                       goto com;
-               }
-               if(typefd[l->type->etype])
-                       o = invrel[relindex(logrel[relindex(o)])];
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(r->addable < INDEXED || hardconst(r) || typefd[l->type->etype]) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               gopcode(o, l->type, &nod, &nod1);
-                               regfree(&nod1);
-                       } else {
-                               gopcode(o, l->type, &nod, r);
-                       }
-                       regfree(&nod);
-                       goto fixfloat;
-               }
-               regalloc(&nod, r, nn);
-               cgen(r, &nod);
-               if(l->addable < INDEXED || l->addable == 13 || hardconst(l)) {
-                       regalloc(&nod1, l, Z);
-                       cgen(l, &nod1);
-                       if(typechl[l->type->etype] && ewidth[l->type->etype] <= ewidth[TINT])
-                               gopcode(o, types[TINT], &nod1, &nod);
-                       else
-                               gopcode(o, l->type, &nod1, &nod);
-                       regfree(&nod1);
-               } else
-                       gopcode(o, l->type, l, &nod);
-               regfree(&nod);
-       fixfloat:
-               if(typefd[l->type->etype]) {
-                       switch(o) {
-                       case OEQ:
-                               // Already emitted AJEQ; want AJEQ and AJPC.
-                               p1 = p;
-                               gbranch(OGOTO);
-                               p2 = p;
-                               patch(p1, pc);
-                               gins(AJPC, Z, Z);
-                               patch(p2, pc);
-                               break;
-
-                       case ONE:
-                               // Already emitted AJNE; want AJNE or AJPS.
-                               p1 = p;
-                               gins(AJPS, Z, Z);
-                               p2 = p;
-                               gbranch(OGOTO);
-                               p3 = p;
-                               patch(p1, pc);
-                               patch(p2, pc);
-                               gbranch(OGOTO);
-                               patch(p3, pc);
-                               break;
-                       }
-               }
-
-       com:
-               if(nn != Z) {
-                       p1 = p;
-                       gmove(nodconst(1L), nn);
-                       gbranch(OGOTO);
-                       p2 = p;
-                       patch(p1, pc);
-                       gmove(nodconst(0L), nn);
-                       patch(p2, pc);
-               }
-               break;
-       }
-       cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
-       Prog *p1;
-       Node nod0, nod1, nod2, nod3, nod4, *l, *r;
-       Type *t;
-       int c, mt, mo;
-       vlong o0, o1;
-
-       if(n == Z || n->type == T)
-               return;
-       if(debug['g']) {
-               prtree(nn, "sugen lhs");
-               prtree(n, "sugen");
-       }
-       if(nn == nodrat)
-               if(w > nrathole)
-                       nrathole = w;
-       switch(n->op) {
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(n->left, Z);
-                       break;
-               }
-
-       default:
-               goto copy;
-
-       case OCONST:
-               goto copy;
-
-       case ODOT:
-               l = n->left;
-               sugen(l, nodrat, l->type->width);
-               if(nn == Z)
-                       break;
-               warn(n, "non-interruptable temporary");
-               nod1 = *nodrat;
-               r = n->right;
-               if(!r || r->op != OCONST) {
-                       diag(n, "DOT and no offset");
-                       break;
-               }
-               nod1.xoffset += (int32)r->vconst;
-               nod1.type = n->type;
-               sugen(&nod1, nn, w);
-               break;
-
-       case OSTRUCT:
-               /*
-                * rewrite so lhs has no fn call
-                */
-               if(nn != Z && side(nn)) {
-                       nod1 = *n;
-                       nod1.type = typ(TIND, n->type);
-                       regret(&nod2, &nod1, 0, 0);
-                       lcgen(nn, &nod2);
-                       regsalloc(&nod0, &nod1);
-                       cgen(&nod2, &nod0);
-                       regfree(&nod2);
-
-                       nod1 = *n;
-                       nod1.op = OIND;
-                       nod1.left = &nod0;
-                       nod1.right = Z;
-                       nod1.complex = 1;
-
-                       sugen(n, &nod1, w);
-                       return;
-               }
-
-               r = n->left;
-               for(t = n->type->link; t != T; t = t->down) {
-                       l = r;
-                       if(r->op == OLIST) {
-                               l = r->left;
-                               r = r->right;
-                       }
-                       if(nn == Z) {
-                               cgen(l, nn);
-                               continue;
-                       }
-                       /*
-                        * hand craft *(&nn + o) = l
-                        */
-                       nod0 = znode;
-                       nod0.op = OAS;
-                       nod0.type = t;
-                       nod0.left = &nod1;
-                       nod0.right = nil;
-
-                       nod1 = znode;
-                       nod1.op = OIND;
-                       nod1.type = t;
-                       nod1.left = &nod2;
-
-                       nod2 = znode;
-                       nod2.op = OADD;
-                       nod2.type = typ(TIND, t);
-                       nod2.left = &nod3;
-                       nod2.right = &nod4;
-
-                       nod3 = znode;
-                       nod3.op = OADDR;
-                       nod3.type = nod2.type;
-                       nod3.left = nn;
-
-                       nod4 = znode;
-                       nod4.op = OCONST;
-                       nod4.type = nod2.type;
-                       nod4.vconst = t->offset;
-
-                       ccom(&nod0);
-                       acom(&nod0);
-                       xcom(&nod0);
-                       nod0.addable = 0;
-                       nod0.right = l;
-
-                       // prtree(&nod0, "hand craft");
-                       cgen(&nod0, Z);
-               }
-               break;
-
-       case OAS:
-               if(nn == Z) {
-                       if(n->addable < INDEXED)
-                               sugen(n->right, n->left, w);
-                       break;
-               }
-
-               sugen(n->right, nodrat, w);
-               warn(n, "non-interruptable temporary");
-               sugen(nodrat, n->left, w);
-               sugen(nodrat, nn, w);
-               break;
-
-       case OFUNC:
-               if(!hasdotdotdot(n->left->type)) {
-                       cgen(n, Z);
-                       if(nn != Z) {
-                               curarg -= n->type->width;
-                               regret(&nod1, n, n->left->type, 1);
-                               if(nn->complex >= FNX) {
-                                       regsalloc(&nod2, n);
-                                       cgen(&nod1, &nod2);
-                                       nod1 = nod2;
-                               }
-                               cgen(&nod1, nn);
-                       }
-                       break;
-               }
-               if(nn == Z) {
-                       sugen(n, nodrat, w);
-                       break;
-               }
-               if(nn->op != OIND) {
-                       nn = new1(OADDR, nn, Z);
-                       nn->type = types[TIND];
-                       nn->addable = 0;
-               } else
-                       nn = nn->left;
-               n = new(OFUNC, n->left, new(OLIST, nn, n->right));
-               n->type = types[TVOID];
-               n->left->type = types[TVOID];
-               cgen(n, Z);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               sugen(n->right->left, nn, w);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               sugen(n->right->right, nn, w);
-               patch(p1, pc);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, Z);
-               sugen(n->right, nn, w);
-               break;
-       }
-       return;
-
-copy:
-       if(nn == Z) {
-               switch(n->op) {
-               case OASADD:
-               case OASSUB:
-               case OASAND:
-               case OASOR:
-               case OASXOR:
-
-               case OASMUL:
-               case OASLMUL:
-
-
-               case OASASHL:
-               case OASASHR:
-               case OASLSHR:
-                       break;
-
-               case OPOSTINC:
-               case OPOSTDEC:
-               case OPREINC:
-               case OPREDEC:
-                       break;
-
-               default:
-                       return;
-               }
-       }
-
-       if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
-               t = nn->type;
-               nn->type = types[TIND];
-               regialloc(&nod1, nn, Z);
-               lcgen(nn, &nod1);
-               regsalloc(&nod2, nn);
-               nn->type = t;
-
-               gins(AMOVQ, &nod1, &nod2);
-               regfree(&nod1);
-
-               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);
-               return;
-       }
-
-       if(w <= 32) {
-               c = cursafe;
-               if(n->left != Z && n->left->complex >= FNX
-               && n->right != Z && n->right->complex >= FNX) {
-                       regsalloc(&nod1, n->right);
-                       cgen(n->right, &nod1);
-                       nod2 = *n;
-                       nod2.right = &nod1;
-                       cgen(&nod2, nn);
-                       cursafe = c;
-                       return;
-               }
-               if(w & 7) {
-                       mt = TLONG;
-                       mo = AMOVL;
-               } else {
-                       mt = TVLONG;
-                       mo = AMOVQ;
-               }
-               if(n->complex > nn->complex) {
-                       t = n->type;
-                       n->type = types[mt];
-                       regalloc(&nod0, n, Z);
-                       if(!vaddr(n, 0)) {
-                               reglcgen(&nod1, n, Z);
-                               n->type = t;
-                               n = &nod1;
-                       }
-                       else
-                               n->type = t;
-
-                       t = nn->type;
-                       nn->type = types[mt];
-                       if(!vaddr(nn, 0)) {
-                               reglcgen(&nod2, nn, Z);
-                               nn->type = t;
-                               nn = &nod2;
-                       }
-                       else
-                               nn->type = t;
-               } else {
-                       t = nn->type;
-                       nn->type = types[mt];
-                       regalloc(&nod0, nn, Z);
-                       if(!vaddr(nn, 0)) {
-                               reglcgen(&nod2, nn, Z);
-                               nn->type = t;
-                               nn = &nod2;
-                       }
-                       else
-                               nn->type = t;
-
-                       t = n->type;
-                       n->type = types[mt];
-                       if(!vaddr(n, 0)) {
-                               reglcgen(&nod1, n, Z);
-                               n->type = t;
-                               n = &nod1;
-                       }
-                       else
-                               n->type = t;
-               }
-               o0 = n->xoffset;
-               o1 = nn->xoffset;
-               w /= ewidth[mt];
-               while(--w >= 0) {
-                       gins(mo, n, &nod0);
-                       gins(mo, &nod0, nn);
-                       n->xoffset += ewidth[mt];
-                       nn->xoffset += ewidth[mt];
-               }
-               n->xoffset = o0;
-               nn->xoffset = o1;
-               if(nn == &nod2)
-                       regfree(&nod2);
-               if(n == &nod1)
-                       regfree(&nod1);
-               regfree(&nod0);
-               return;
-       }
-
-       /* botch, need to save in .safe */
-       c = 0;
-       if(n->complex > nn->complex) {
-               t = n->type;
-               n->type = types[TIND];
-               nodreg(&nod1, n, D_SI);
-               if(reg[D_SI]) {
-                       gins(APUSHQ, &nod1, Z);
-                       c |= 1;
-                       reg[D_SI]++;
-               }
-               lcgen(n, &nod1);
-               n->type = t;
-
-               t = nn->type;
-               nn->type = types[TIND];
-               nodreg(&nod2, nn, D_DI);
-               if(reg[D_DI]) {
-warn(Z, "DI botch");
-                       gins(APUSHQ, &nod2, Z);
-                       c |= 2;
-                       reg[D_DI]++;
-               }
-               lcgen(nn, &nod2);
-               nn->type = t;
-       } else {
-               t = nn->type;
-               nn->type = types[TIND];
-               nodreg(&nod2, nn, D_DI);
-               if(reg[D_DI]) {
-warn(Z, "DI botch");
-                       gins(APUSHQ, &nod2, Z);
-                       c |= 2;
-                       reg[D_DI]++;
-               }
-               lcgen(nn, &nod2);
-               nn->type = t;
-
-               t = n->type;
-               n->type = types[TIND];
-               nodreg(&nod1, n, D_SI);
-               if(reg[D_SI]) {
-                       gins(APUSHQ, &nod1, Z);
-                       c |= 1;
-                       reg[D_SI]++;
-               }
-               lcgen(n, &nod1);
-               n->type = t;
-       }
-       nodreg(&nod3, n, D_CX);
-       if(reg[D_CX]) {
-               gins(APUSHQ, &nod3, Z);
-               c |= 4;
-               reg[D_CX]++;
-       }
-       gins(AMOVL, nodconst(w/SZ_INT), &nod3);
-       gins(ACLD, Z, Z);
-       gins(AREP, Z, Z);
-       gins(AMOVSL, Z, Z);
-       if(c & 4) {
-               gins(APOPQ, Z, &nod3);
-               reg[D_CX]--;
-       }
-       if(c & 2) {
-               gins(APOPQ, Z, &nod2);
-               reg[nod2.reg]--;
-       }
-       if(c & 1) {
-               gins(APOPQ, Z, &nod1);
-               reg[nod1.reg]--;
-       }
-}
-
-/*
- * TO DO
- */
-void
-layout(Node *f, Node *t, int c, int cv, Node *cn)
-{
-       Node t1, t2;
-
-       while(c > 3) {
-               layout(f, t, 2, 0, Z);
-               c -= 2;
-       }
-
-       regalloc(&t1, &lregnode, Z);
-       regalloc(&t2, &lregnode, Z);
-       if(c > 0) {
-               gmove(f, &t1);
-               f->xoffset += SZ_INT;
-       }
-       if(cn != Z)
-               gmove(nodconst(cv), cn);
-       if(c > 1) {
-               gmove(f, &t2);
-               f->xoffset += SZ_INT;
-       }
-       if(c > 0) {
-               gmove(&t1, t);
-               t->xoffset += SZ_INT;
-       }
-       if(c > 2) {
-               gmove(f, &t1);
-               f->xoffset += SZ_INT;
-       }
-       if(c > 1) {
-               gmove(&t2, t);
-               t->xoffset += SZ_INT;
-       }
-       if(c > 2) {
-               gmove(&t1, t);
-               t->xoffset += SZ_INT;
-       }
-       regfree(&t1);
-       regfree(&t2);
-}
-
-/*
- * constant is not vlong or fits as 32-bit signed immediate
- */
-int
-immconst(Node *n)
-{
-       int32 v;
-
-       if(n->op != OCONST || !typechlpv[n->type->etype])
-               return 0;
-       if(typechl[n->type->etype])
-               return 1;
-       v = n->vconst;
-       return n->vconst == (vlong)v;
-}
-
-/*
- * if a constant and vlong, doesn't fit as 32-bit signed immediate
- */
-int
-hardconst(Node *n)
-{
-       return n->op == OCONST && !immconst(n);
-}
-
-/*
- * casting up to t2 covers an intermediate cast to t1
- */
-int
-castup(Type *t1, Type *t2)
-{
-       int ft;
-
-       if(!nilcast(t1, t2))
-               return 0;
-       /* known to be small to large */
-       ft = t1->etype;
-       switch(t2->etype){
-       case TINT:
-       case TLONG:
-               return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;
-       case TUINT:
-       case TULONG:
-               return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;
-       case TVLONG:
-               return ft == TLONG || ft == TINT || ft == TSHORT;
-       case TUVLONG:
-               return ft == TULONG || ft == TUINT || ft == TUSHORT;
-       }
-       return 0;
-}
-
-void
-zeroregm(Node *n)
-{
-       gins(AMOVL, nodconst(0), n);
-}
-
-/* do we need to load the address of a vlong? */
-int
-vaddr(Node *n, int a)
-{
-       switch(n->op) {
-       case ONAME:
-               if(a)
-                       return 1;
-               return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
-
-       case OCONST:
-       case OREGISTER:
-       case OINDREG:
-               return 1;
-       }
-       return 0;
-}
-
-int32
-hi64v(Node *n)
-{
-       if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
-               return (int32)(n->vconst) & ~0L;
-       else
-               return (int32)((uvlong)n->vconst>>32) & ~0L;
-}
-
-int32
-lo64v(Node *n)
-{
-       if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
-               return (int32)((uvlong)n->vconst>>32) & ~0L;
-       else
-               return (int32)(n->vconst) & ~0L;
-}
-
-Node *
-hi64(Node *n)
-{
-       return nodconst(hi64v(n));
-}
-
-Node *
-lo64(Node *n)
-{
-       return nodconst(lo64v(n));
-}
-
-int
-cond(int op)
-{
-       switch(op) {
-       case OANDAND:
-       case OOROR:
-       case ONOT:
-               return 1;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               return 1;
-       }
-       return 0;
-}
diff --git a/src/cmd/6c/div.c b/src/cmd/6c/div.c
deleted file mode 100644 (file)
index bad6c5e..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-// Inferno utils/6c/div.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/div.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
- * Based on: Granlund, T.; Montgomery, P.L.
- * "Division by Invariant Integers using Multiplication".
- * SIGPLAN Notices, Vol. 29, June 1994, page 61.
- */
-
-#define        TN(n)   ((uvlong)1 << (n))
-#define        T31     TN(31)
-#define        T32     TN(32)
-
-int
-multiplier(uint32 d, int p, uvlong *mp)
-{
-       int l;
-       uvlong mlo, mhi, tlo, thi;
-
-       l = topbit(d - 1) + 1;
-       mlo = (((TN(l) - d) << 32) / d) + T32;
-       if(l + p == 64)
-               mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
-       else
-               mhi = (TN(32 + l) + TN(32 + l - p)) / d;
-       /*assert(mlo < mhi);*/
-       while(l > 0) {
-               tlo = mlo >> 1;
-               thi = mhi >> 1;
-               if(tlo == thi)
-                       break;
-               mlo = tlo;
-               mhi = thi;
-               l--;
-       }
-       *mp = mhi;
-       return l;
-}
-
-int
-sdiv(uint32 d, uint32 *mp, int *sp)
-{
-       int s;
-       uvlong m;
-
-       s = multiplier(d, 32 - 1, &m);
-       *mp = m;
-       *sp = s;
-       if(m >= T31)
-               return 1;
-       else
-               return 0;
-}
-
-int
-udiv(uint32 d, uint32 *mp, int *sp, int *pp)
-{
-       int p, s;
-       uvlong m;
-
-       s = multiplier(d, 32, &m);
-       p = 0;
-       if(m >= T32) {
-               while((d & 1) == 0) {
-                       d >>= 1;
-                       p++;
-               }
-               s = multiplier(d, 32 - p, &m);
-       }
-       *mp = m;
-       *pp = p;
-       if(m >= T32) {
-               /*assert(p == 0);*/
-               *sp = s - 1;
-               return 1;
-       }
-       else {
-               *sp = s;
-               return 0;
-       }
-}
-
-void
-sdivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
-       int a, s;
-       uint32 m;
-       vlong c;
-
-       c = r->vconst;
-       if(c < 0)
-               c = -c;
-       a = sdiv(c, &m, &s);
-//print("a=%d i=%d s=%d m=%ux\n", a, (long)r->vconst, s, m);
-       gins(AMOVL, nodconst(m), ax);
-       gins(AIMULL, l, Z);
-       gins(AMOVL, l, ax);
-       if(a)
-               gins(AADDL, ax, dx);
-       gins(ASHRL, nodconst(31), ax);
-       gins(ASARL, nodconst(s), dx);
-       gins(AADDL, ax, dx);
-       if(r->vconst < 0)
-               gins(ANEGL, Z, dx);
-}
-
-void
-udivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
-       int a, s, t;
-       uint32 m;
-       Node nod;
-
-       a = udiv(r->vconst, &m, &s, &t);
-//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (long)r->vconst, t, s, m);
-       if(t != 0) {
-               gins(AMOVL, l, ax);
-               gins(ASHRL, nodconst(t), ax);
-               gins(AMOVL, nodconst(m), dx);
-               gins(AMULL, dx, Z);
-       }
-       else if(a) {
-               if(l->op != OREGISTER) {
-                       regalloc(&nod, l, Z);
-                       gins(AMOVL, l, &nod);
-                       l = &nod;
-               }
-               gins(AMOVL, nodconst(m), ax);
-               gins(AMULL, l, Z);
-               gins(AADDL, l, dx);
-               gins(ARCRL, nodconst(1), dx);
-               if(l == &nod)
-                       regfree(l);
-       }
-       else {
-               gins(AMOVL, nodconst(m), ax);
-               gins(AMULL, l, Z);
-       }
-       if(s != 0)
-               gins(ASHRL, nodconst(s), dx);
-}
-
-void
-sext(Node *d, Node *s, Node *l)
-{
-       if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
-               reg[D_DX]++;
-               gins(ACDQ, Z, Z);
-       }
-       else {
-               regalloc(d, l, Z);
-               gins(AMOVL, s, d);
-               gins(ASARL, nodconst(31), d);
-       }
-}
-
-void
-sdiv2(int32 c, int v, Node *l, Node *n)
-{
-       Node nod;
-
-       if(v > 0) {
-               if(v > 1) {
-                       sext(&nod, n, l);
-                       gins(AANDL, nodconst((1 << v) - 1), &nod);
-                       gins(AADDL, &nod, n);
-                       regfree(&nod);
-               }
-               else {
-                       gins(ACMPL, n, nodconst(0x80000000));
-                       gins(ASBBL, nodconst(-1), n);
-               }
-               gins(ASARL, nodconst(v), n);
-       }
-       if(c < 0)
-               gins(ANEGL, Z, n);
-}
-
-void
-smod2(int32 c, int v, Node *l, Node *n)
-{
-       Node nod;
-
-       if(c == 1) {
-               zeroregm(n);
-               return;
-       }
-
-       sext(&nod, n, l);
-       if(v == 0) {
-               zeroregm(n);
-               gins(AXORL, &nod, n);
-               gins(ASUBL, &nod, n);
-       }
-       else if(v > 1) {
-               gins(AANDL, nodconst((1 << v) - 1), &nod);
-               gins(AADDL, &nod, n);
-               gins(AANDL, nodconst((1 << v) - 1), n);
-               gins(ASUBL, &nod, n);
-       }
-       else {
-               gins(AANDL, nodconst(1), n);
-               gins(AXORL, &nod, n);
-               gins(ASUBL, &nod, n);
-       }
-       regfree(&nod);
-}
diff --git a/src/cmd/6c/doc.go b/src/cmd/6c/doc.go
deleted file mode 100644 (file)
index e0a22e7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +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/8c
-
-Its target architecture is the x86-64, referred to by these tools as amd64.
-
-*/
-package main
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
deleted file mode 100644 (file)
index aa9d95d..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-// Inferno utils/6c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "../cc/cc.h"
-#include       "../6l/6.out.h"
-
-/*
- * 6c/amd64
- * Intel 386 with AMD64 extensions
- */
-#define        SZ_CHAR         1
-#define        SZ_SHORT        2
-#define        SZ_INT          4
-#define        SZ_LONG         4
-#define        SZ_IND          8
-#define        SZ_FLOAT        4
-#define        SZ_VLONG        8
-#define        SZ_DOUBLE       8
-#define        FNX             100
-
-typedef        struct  Case    Case;
-typedef        struct  C1      C1;
-typedef        struct  Reg     Reg;
-typedef        struct  Rgn     Rgn;
-typedef        struct  Renv    Renv;
-
-EXTERN struct
-{
-       Node*   regtree;
-       Node*   basetree;
-       short   scale;
-       short   reg;
-       short   ptr;
-} idx;
-
-#define        INDEXED 9
-
-#define        A       ((Addr*)0)
-#define        P       ((Prog*)0)
-
-struct Case
-{
-       Case*   link;
-       vlong   val;
-       int32   label;
-       char    def;
-       char    isv;
-};
-#define        C       ((Case*)0)
-
-struct C1
-{
-       vlong   val;
-       int32   label;
-};
-
-struct Reg
-{
-       int32   pc;
-       int32   rpo;            /* reverse post ordering */
-
-       Bits    set;
-       Bits    use1;
-       Bits    use2;
-
-       Bits    refbehind;
-       Bits    refahead;
-       Bits    calbehind;
-       Bits    calahead;
-       Bits    regdiff;
-       Bits    act;
-
-       int32   regu;
-       int32   loop;           /* could be shorter */
-
-       Reg*    log5;
-       int32   active;
-
-       Reg*    p1;
-       Reg*    p2;
-       Reg*    p2link;
-       Reg*    s1;
-       Reg*    s2;
-       Reg*    link;
-       Prog*   prog;
-};
-#define        R       ((Reg*)0)
-
-struct Renv
-{
-       int     safe;
-       Node    base;
-       Node*   saved;
-       Node*   scope;
-};
-
-#define        NRGN    600
-struct Rgn
-{
-       Reg*    enter;
-       short   cost;
-       short   varno;
-       short   regno;
-};
-
-EXTERN int32   breakpc;
-EXTERN int32   nbreak;
-EXTERN Case*   cases;
-EXTERN Node    constnode;
-EXTERN Node    fconstnode;
-EXTERN Node    vconstnode;
-EXTERN int32   continpc;
-EXTERN int32   curarg;
-EXTERN int32   cursafe;
-EXTERN Prog*   lastp;
-EXTERN int32   maxargsafe;
-EXTERN int     mnstring;
-EXTERN Node*   nodrat;
-EXTERN Node*   nodret;
-EXTERN Node*   nodsafe;
-EXTERN int32   nrathole;
-EXTERN int32   nstring;
-EXTERN Prog*   p;
-EXTERN int32   pc;
-EXTERN Node    lregnode;
-EXTERN Node    qregnode;
-EXTERN char    string[NSNAME];
-EXTERN Sym*    symrathole;
-EXTERN Node    znode;
-EXTERN Prog    zprog;
-EXTERN int     reg[D_NONE];
-EXTERN int32   exregoffset;
-EXTERN int32   exfregoffset;
-EXTERN uchar   typechlpv[NTYPE];
-
-#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])
-#define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define        bset(a,n)       ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define        CLOAD   5
-#define        CREF    5
-#define        CINF    1000
-#define        LOOP    3
-
-EXTERN Rgn     region[NRGN];
-EXTERN Rgn*    rgp;
-EXTERN int     nregion;
-EXTERN int     nvar;
-
-EXTERN Bits    externs;
-EXTERN Bits    params;
-EXTERN Bits    consts;
-EXTERN Bits    addrs;
-
-EXTERN int32   regbits;
-EXTERN int32   exregbits;
-
-EXTERN int     change;
-EXTERN int     suppress;
-
-EXTERN Reg*    firstr;
-EXTERN Reg*    lastr;
-EXTERN Reg     zreg;
-EXTERN Reg*    freer;
-EXTERN int32*  idom;
-EXTERN Reg**   rpo2r;
-EXTERN int32   maxnr;
-
-extern char*   anames[];
-
-/*
- * sgen.c
- */
-void   codgen(Node*, Node*);
-void   gen(Node*);
-void   noretval(int);
-void   usedset(Node*, int);
-void   xcom(Node*);
-void   indx(Node*);
-int    bcomplex(Node*, Node*);
-Prog*  gtext(Sym*, int32);
-vlong  argsize(int);
-
-/*
- * cgen.c
- */
-void   zeroregm(Node*);
-void   cgen(Node*, Node*);
-void   reglcgen(Node*, Node*, Node*);
-void   lcgen(Node*, Node*);
-void   bcgen(Node*, int);
-void   boolgen(Node*, int, Node*);
-void   sugen(Node*, Node*, int32);
-int    needreg(Node*, int);
-int    hardconst(Node*);
-int    immconst(Node*);
-
-/*
- * txt.c
- */
-void   ginit(void);
-void   gclean(void);
-void   nextpc(void);
-void   gargs(Node*, Node*, Node*);
-void   garg1(Node*, Node*, Node*, int, Node**);
-Node*  nodconst(int32);
-Node*  nodfconst(double);
-Node*  nodgconst(vlong, Type*);
-int    nodreg(Node*, Node*, int);
-int    isreg(Node*, int);
-void   regret(Node*, Node*, Type*, int);
-void   regalloc(Node*, Node*, Node*);
-void   regfree(Node*);
-void   regialloc(Node*, Node*, Node*);
-void   regsalloc(Node*, Node*);
-void   regaalloc1(Node*, Node*);
-void   regaalloc(Node*, Node*);
-void   regind(Node*, Node*);
-void   gprep(Node*, Node*);
-void   naddr(Node*, Addr*);
-void   gcmp(int, Node*, vlong);
-void   gmove(Node*, Node*);
-void   gins(int a, Node*, Node*);
-void   gopcode(int, Type*, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   gbranch(int);
-void   patch(Prog*, int32);
-int    sconst(Node*);
-void   gpseudo(int, Sym*, Node*);
-void   gprefetch(Node*);
-void   gpcdata(int, int);
-
-/*
- * swt.c
- */
-int    swcmp(const void*, const void*);
-void   doswit(Node*);
-void   swit1(C1*, int, int32, Node*);
-void   swit2(C1*, int, int32, Node*);
-void   newcase(void);
-void   bitload(Node*, Node*, Node*, Node*, Node*);
-void   bitstore(Node*, Node*, Node*, Node*, Node*);
-int32  outstring(char*, int32);
-void   nullwarn(Node*, Node*);
-void   sextern(Sym*, Node*, int32, int32);
-void   gextern(Sym*, Node*, int32, int32);
-void   outcode(void);
-
-/*
- * list
- */
-void   listinit(void);
-
-/*
- * reg.c
- */
-Reg*   rega(void);
-int    rcmp(const void*, const void*);
-void   regopt(Prog*);
-void   addmove(Reg*, int, int, int);
-Bits   mkvar(Reg*, Addr*);
-void   prop(Reg*, Bits, Bits);
-void   loopit(Reg*, int32);
-void   synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
-void   addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void   peep(void);
-void   excise(Reg*);
-Reg*   uniqp(Reg*);
-Reg*   uniqs(Reg*);
-int    regtyp(Addr*);
-int    anyvar(Addr*);
-int    subprop(Reg*);
-int    copyprop(Reg*);
-int    copy1(Addr*, Addr*, Reg*, int);
-int    copyu(Prog*, Addr*, Addr*);
-
-int    copyas(Addr*, Addr*);
-int    copyau(Addr*, Addr*);
-int    copysub(Addr*, Addr*, Addr*, int);
-int    copysub1(Prog*, Addr*, Addr*, int);
-
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
-
-#define        D_HI    D_NONE
-#define        D_LO    D_NONE
-
-/*
- * bound
- */
-void   comtarg(void);
-
-/*
- * com64
- */
-int    cond(int);
-int    com64(Node*);
-void   com64init(void);
-void   bool64(Node*);
-int32  lo64v(Node*);
-int32  hi64v(Node*);
-Node*  lo64(Node*);
-Node*  hi64(Node*);
-
-/*
- * div/mul
- */
-void   sdivgen(Node*, Node*, Node*, Node*);
-void   udivgen(Node*, Node*, Node*, Node*);
-void   sdiv2(int32, int, Node*, Node*);
-void   smod2(int32, int, Node*, Node*);
-void   mulgen(Type*, Node*, Node*);
-void   genmuladd(Node*, Node*, int, Node*);
-void   shiftit(Type*, Node*, Node*);
-
-#define        D_X7    (D_X0+7)
-
-void   fgopcode(int, Node*, Node*, int, int);
diff --git a/src/cmd/6c/list.c b/src/cmd/6c/list.c
deleted file mode 100644 (file)
index 28f5b8d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Inferno utils/6c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
-       listinit6();
-}
diff --git a/src/cmd/6c/machcap.c b/src/cmd/6c/machcap.c
deleted file mode 100644 (file)
index 820d9a0..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Inferno utils/6c/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/machcap.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-machcap(Node *n)
-{
-
-       if(n == Z)
-               return 1;       /* test */
-
-       switch(n->op) {
-       case OMUL:
-       case OLMUL:
-       case OASMUL:
-       case OASLMUL:
-               if(typechl[n->type->etype])
-                       return 1;
-               if(typev[n->type->etype])
-                       return 1;
-               break;
-
-       case OCOM:
-       case ONEG:
-       case OADD:
-       case OAND:
-       case OOR:
-       case OSUB:
-       case OXOR:
-       case OASHL:
-       case OLSHR:
-       case OASHR:
-               if(typechlv[n->left->type->etype])
-                       return 1;
-               break;
-
-       case OCAST:
-               return 1;
-
-       case OCOND:
-       case OCOMMA:
-       case OLIST:
-       case OANDAND:
-       case OOROR:
-       case ONOT:
-               return 1;
-
-       case OASADD:
-       case OASSUB:
-       case OASAND:
-       case OASOR:
-       case OASXOR:
-               return 1;
-
-       case OASASHL:
-       case OASASHR:
-       case OASLSHR:
-               return 1;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-       case OPREINC:
-       case OPREDEC:
-               return 1;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OGT:
-       case OLT:
-       case OGE:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               return 1;
-       }
-       return 0;
-}
diff --git a/src/cmd/6c/mul.c b/src/cmd/6c/mul.c
deleted file mode 100644 (file)
index 510edc0..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-// Inferno utils/6c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/mul.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-typedef struct Malg    Malg;
-typedef struct Mparam  Mparam;
-
-struct Malg
-{
-       schar   vals[10];
-};
-
-struct Mparam
-{
-       uint32  value;
-       schar   alg;
-       char    neg;
-       char    shift;
-       char    arg;
-       schar   off;
-};
-
-static Mparam  multab[32];
-static int     mulptr;
-
-static Malg    malgs[] =
-{
-       {0, 100},
-       {-1, 1, 100},
-       {-9, -5, -3, 3, 5, 9, 100},
-       {6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
-       {-8, -4, -2, 2, 4, 8, 100},
-};
-
-/*
- * return position of lowest 1
- */
-int
-lowbit(uint32 v)
-{
-       int s, i;
-       uint32 m;
-
-       s = 0;
-       m = 0xFFFFFFFFUL;
-       for(i = 16; i > 0; i >>= 1) {
-               m >>= i;
-               if((v & m) == 0) {
-                       v >>= i;
-                       s += i;
-               }
-       }
-       return s;
-}
-
-void
-genmuladd(Node *d, Node *s, int m, Node *a)
-{
-       Node nod;
-
-       nod.op = OINDEX;
-       nod.left = a;
-       nod.right = s;
-       nod.scale = m;
-       nod.type = types[TIND];
-       nod.xoffset = 0;
-       xcom(&nod);
-       gopcode(OADDR, d->type, &nod, d);
-}
-
-void
-mulparam(uint32 m, Mparam *mp)
-{
-       int c, i, j, n, o, q, s;
-       int bc, bi, bn, bo, bq, bs, bt;
-       schar *p;
-       int32 u;
-       uint32 t;
-
-       bc = bq = 10;
-       bi = bn = bo = bs = bt = 0;
-       for(i = 0; i < nelem(malgs); i++) {
-               for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
-               for(s = 0; s < 2; s++) {
-                       c = 10;
-                       q = 10;
-                       u = m - o;
-                       if(u == 0)
-                               continue;
-                       if(s) {
-                               o = -o;
-                               if(o > 0)
-                                       continue;
-                               u = -u;
-                       }
-                       n = lowbit(u);
-                       t = (uint32)u >> n;
-                       switch(i) {
-                       case 0:
-                               if(t == 1) {
-                                       c = s + 1;
-                                       q = 0;
-                                       break;
-                               }
-                               switch(t) {
-                               case 3:
-                               case 5:
-                               case 9:
-                                       c = s + 1;
-                                       if(n)
-                                               c++;
-                                       q = 0;
-                                       break;
-                               }
-                               if(s)
-                                       break;
-                               switch(t) {
-                               case 15:
-                               case 25:
-                               case 27:
-                               case 45:
-                               case 81:
-                                       c = 2;
-                                       if(n)
-                                               c++;
-                                       q = 1;
-                                       break;
-                               }
-                               break;
-                       case 1:
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 3;
-                                       break;
-                               }
-                               switch(t) {
-                               case 3:
-                               case 5:
-                               case 9:
-                                       c = 3;
-                                       q = 2;
-                                       break;
-                               }
-                               break;
-                       case 2:
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 2;
-                                       break;
-                               }
-                               break;
-                       case 3:
-                               if(s)
-                                       break;
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 1;
-                                       break;
-                               }
-                               break;
-                       case 4:
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 0;
-                                       break;
-                               }
-                               break;
-                       }
-                       if(c < bc || (c == bc && q > bq)) {
-                               bc = c;
-                               bi = i;
-                               bn = n;
-                               bo = o;
-                               bq = q;
-                               bs = s;
-                               bt = t;
-                       }
-               }
-       }
-       mp->value = m;
-       if(bc <= 3) {
-               mp->alg = bi;
-               mp->shift = bn;
-               mp->off = bo;
-               mp->neg = bs;
-               mp->arg = bt;
-       }
-       else
-               mp->alg = -1;
-}
-
-int
-m0(int a)
-{
-       switch(a) {
-       case -2:
-       case 2:
-               return 2;
-       case -3:
-       case 3:
-               return 2;
-       case -4:
-       case 4:
-               return 4;
-       case -5:
-       case 5:
-               return 4;
-       case 6:
-               return 2;
-       case -8:
-       case 8:
-               return 8;
-       case -9:
-       case 9:
-               return 8;
-       case 10:
-               return 4;
-       case 12:
-               return 2;
-       case 15:
-               return 2;
-       case 18:
-               return 8;
-       case 20:
-               return 4;
-       case 24:
-               return 2;
-       case 25:
-               return 4;
-       case 27:
-               return 2;
-       case 36:
-               return 8;
-       case 40:
-               return 4;
-       case 45:
-               return 4;
-       case 72:
-               return 8;
-       case 81:
-               return 8;
-       }
-       diag(Z, "bad m0");
-       return 0;
-}
-
-int
-m1(int a)
-{
-       switch(a) {
-       case 15:
-               return 4;
-       case 25:
-               return 4;
-       case 27:
-               return 8;
-       case 45:
-               return 8;
-       case 81:
-               return 8;
-       }
-       diag(Z, "bad m1");
-       return 0;
-}
-
-int
-m2(int a)
-{
-       switch(a) {
-       case 6:
-               return 2;
-       case 10:
-               return 2;
-       case 12:
-               return 4;
-       case 18:
-               return 2;
-       case 20:
-               return 4;
-       case 24:
-               return 8;
-       case 36:
-               return 4;
-       case 40:
-               return 8;
-       case 72:
-               return 8;
-       }
-       diag(Z, "bad m2");
-       return 0;
-}
-
-void
-shiftit(Type *t, Node *s, Node *d)
-{
-       int32 c;
-
-       c = (int32)s->vconst & 31;
-       switch(c) {
-       case 0:
-               break;
-       case 1:
-               gopcode(OADD, t, d, d);
-               break;
-       default:
-               gopcode(OASHL, t, s, d);
-       }
-}
-
-static int
-mulgen1(uint32 v, Node *n)
-{
-       int i, o;
-       Mparam *p;
-       Node nod, nods;
-
-       for(i = 0; i < nelem(multab); i++) {
-               p = &multab[i];
-               if(p->value == v)
-                       goto found;
-       }
-
-       p = &multab[mulptr];
-       if(++mulptr == nelem(multab))
-               mulptr = 0;
-
-       mulparam(v, p);
-
-found:
-//     print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
-       if(p->alg < 0)
-               return 0;
-
-       nods = *nodconst(p->shift);
-
-       o = OADD;
-       if(p->alg > 0) {
-               regalloc(&nod, n, Z);
-               if(p->off < 0)
-                       o = OSUB;
-       }
-
-       switch(p->alg) {
-       case 0:
-               switch(p->arg) {
-               case 1:
-                       shiftit(n->type, &nods, n);
-                       break;
-               case 15:
-               case 25:
-               case 27:
-               case 45:
-               case 81:
-                       genmuladd(n, n, m1(p->arg), n);
-                       /* fall thru */
-               case 3:
-               case 5:
-               case 9:
-                       genmuladd(n, n, m0(p->arg), n);
-                       shiftit(n->type, &nods, n);
-                       break;
-               default:
-                       goto bad;
-               }
-               if(p->neg == 1)
-                       gins(ANEGL, Z, n);
-               break;
-       case 1:
-               switch(p->arg) {
-               case 1:
-                       gmove(n, &nod);
-                       shiftit(n->type, &nods, &nod);
-                       break;
-               case 3:
-               case 5:
-               case 9:
-                       genmuladd(&nod, n, m0(p->arg), n);
-                       shiftit(n->type, &nods, &nod);
-                       break;
-               default:
-                       goto bad;
-               }
-               if(p->neg)
-                       gopcode(o, n->type, &nod, n);
-               else {
-                       gopcode(o, n->type, n, &nod);
-                       gmove(&nod, n);
-               }
-               break;
-       case 2:
-               genmuladd(&nod, n, m0(p->off), n);
-               shiftit(n->type, &nods, n);
-               goto comop;
-       case 3:
-               genmuladd(&nod, n, m0(p->off), n);
-               shiftit(n->type, &nods, n);
-               genmuladd(n, &nod, m2(p->off), n);
-               break;
-       case 4:
-               genmuladd(&nod, n, m0(p->off), nodconst(0));
-               shiftit(n->type, &nods, n);
-               goto comop;
-       default:
-               diag(Z, "bad mul alg");
-               break;
-       comop:
-               if(p->neg) {
-                       gopcode(o, n->type, n, &nod);
-                       gmove(&nod, n);
-               }
-               else
-                       gopcode(o, n->type, &nod, n);
-       }
-
-       if(p->alg > 0)
-               regfree(&nod);
-
-       return 1;
-
-bad:
-       diag(Z, "mulgen botch");
-       return 1;
-}
-
-void
-mulgen(Type *t, Node *r, Node *n)
-{
-       if(!mulgen1(r->vconst, n))
-               gopcode(OMUL, t, r, n);
-}
diff --git a/src/cmd/6c/peep.c b/src/cmd/6c/peep.c
deleted file mode 100644 (file)
index a11067c..0000000
+++ /dev/null
@@ -1,902 +0,0 @@
-// Inferno utils/6c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static int
-needc(Prog *p)
-{
-       while(p != P) {
-               switch(p->as) {
-               case AADCL:
-               case AADCQ:
-               case ASBBL:
-               case ASBBQ:
-               case ARCRL:
-               case ARCRQ:
-                       return 1;
-               case AADDL:
-               case AADDQ:
-               case ASUBL:
-               case ASUBQ:
-               case AJMP:
-               case ARET:
-               case ACALL:
-                       return 0;
-               default:
-                       if(p->to.type == D_BRANCH)
-                               return 0;
-               }
-               p = p->link;
-       }
-       return 0;
-}
-
-static Reg*
-rnops(Reg *r)
-{
-       Prog *p;
-       Reg *r1;
-
-       if(r != R)
-       for(;;){
-               p = r->prog;
-               if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
-                       break;
-               r1 = uniqs(r);
-               if(r1 == R)
-                       break;
-               r = r1;
-       }
-       return r;
-}
-
-void
-peep(void)
-{
-       Reg *r, *r1, *r2;
-       Prog *p, *p1;
-       int t;
-
-       /*
-        * complete R structure
-        */
-       t = 0;
-       for(r=firstr; r!=R; r=r1) {
-               r1 = r->link;
-               if(r1 == R)
-                       break;
-               p = r->prog->link;
-               while(p != r1->prog)
-               switch(p->as) {
-               default:
-                       r2 = rega();
-                       r->link = r2;
-                       r2->link = r1;
-
-                       r2->prog = p;
-                       r2->p1 = r;
-                       r->s1 = r2;
-                       r2->s1 = r1;
-                       r1->p1 = r2;
-
-                       r = r2;
-                       t++;
-
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-                       p = p->link;
-               }
-       }
-
-       pc = 0; /* speculating it won't kill */
-
-loop1:
-
-       t = 0;
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVL:
-               case AMOVQ:
-               case AMOVSS:
-               case AMOVSD:
-                       if(regtyp(&p->to))
-                       if(regtyp(&p->from)) {
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-                       break;
-
-               case AMOVBLZX:
-               case AMOVWLZX:
-               case AMOVBLSX:
-               case AMOVWLSX:
-                       if(regtyp(&p->to)) {
-                               r1 = rnops(uniqs(r));
-                               if(r1 != R) {
-                                       p1 = r1->prog;
-                                       if(p->as == p1->as && p->to.type == p1->from.type){
-                                               p1->as = AMOVL;
-                                               t++;
-                                       }
-                               }
-                       }
-                       break;
-
-               case AMOVBQSX:
-               case AMOVBQZX:
-               case AMOVWQSX:
-               case AMOVWQZX:
-               case AMOVLQSX:
-               case AMOVLQZX:
-                       if(regtyp(&p->to)) {
-                               r1 = rnops(uniqs(r));
-                               if(r1 != R) {
-                                       p1 = r1->prog;
-                                       if(p->as == p1->as && p->to.type == p1->from.type){
-                                               p1->as = AMOVQ;
-                                               t++;
-                                       }
-                               }
-                       }
-                       break;
-
-               case AADDL:
-               case AADDQ:
-               case AADDW:
-                       if(p->from.type != D_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1){
-                               if(p->as == AADDQ)
-                                       p->as = ADECQ;
-                               else if(p->as == AADDL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                       }
-                       else if(p->from.offset == 1){
-                               if(p->as == AADDQ)
-                                       p->as = AINCQ;
-                               else if(p->as == AADDL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                       }
-                       break;
-
-               case ASUBL:
-               case ASUBQ:
-               case ASUBW:
-                       if(p->from.type != D_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1) {
-                               if(p->as == ASUBQ)
-                                       p->as = AINCQ;
-                               else if(p->as == ASUBL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                       }
-                       else if(p->from.offset == 1){
-                               if(p->as == ASUBQ)
-                                       p->as = ADECQ;
-                               else if(p->as == ASUBL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                       }
-                       break;
-               }
-       }
-       if(t)
-               goto loop1;
-}
-
-void
-excise(Reg *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       p->as = ANOP;
-       p->from = zprog.from;
-       p->to = zprog.to;
-}
-
-Reg*
-uniqp(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->p1;
-       if(r1 == R) {
-               r1 = r->p2;
-               if(r1 == R || r1->p2link != R)
-                       return R;
-       } else
-               if(r->p2 != R)
-                       return R;
-       return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->s1;
-       if(r1 == R) {
-               r1 = r->s2;
-               if(r1 == R)
-                       return R;
-       } else
-               if(r->s2 != R)
-                       return R;
-       return r1;
-}
-
-int
-regtyp(Addr *a)
-{
-       int t;
-
-       t = a->type;
-       if(t >= D_AX && t <= D_R15)
-               return 1;
-       if(t >= D_X0 && t <= D_X0+15)
-               return 1;
-       return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-       int t;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=R; r=uniqp(r)) {
-               if(uniqs(r) == R)
-                       break;
-               p = r->prog;
-               switch(p->as) {
-               case ACALL:
-                       return 0;
-
-               case AIMULL:
-               case AIMULQ:
-               case AIMULW:
-                       if(p->to.type != D_NONE)
-                               break;
-                       goto giveup;
-
-               case AROLB:
-               case AROLL:
-               case AROLQ:
-               case AROLW:
-               case ARORB:
-               case ARORL:
-               case ARORQ:
-               case ARORW:
-               case ASALB:
-               case ASALL:
-               case ASALQ:
-               case ASALW:
-               case ASARB:
-               case ASARL:
-               case ASARQ:
-               case ASARW:
-               case ASHLB:
-               case ASHLL:
-               case ASHLQ:
-               case ASHLW:
-               case ASHRB:
-               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:
-
-               case ACWD:
-               case ACDQ:
-               case ACQO:
-
-               case ASTOSB:
-               case ASTOSL:
-               case ASTOSQ:
-               case AMOVSB:
-               case AMOVSL:
-               case AMOVSQ:
-               case AMOVQL:
-               giveup:
-                       return 0;
-
-               case AMOVL:
-               case AMOVQ:
-                       if(p->to.type == v1->type)
-                               goto gotit;
-                       break;
-               }
-               if(copyau(&p->from, v2) ||
-                  copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->type;
-       v1->type = v2->type;
-       v2->type = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-int
-copyprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       for(r=firstr; r!=R; r=r->link)
-               r->active = 0;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = 1;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != R; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == R) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, A);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %D rar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %D set; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %D used+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %D used and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub %D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %D used+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, A);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %D set and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
-       switch(p->as) {
-
-       default:
-               if(debug['P'])
-                       print("unknown op %A\n", p->as);
-               /* SBBL; ADCL; FLD1; SAHF */
-               return 2;
-
-
-       case ANEGB:
-       case ANEGW:
-       case ANEGL:
-       case ANEGQ:
-       case ANOTB:
-       case ANOTW:
-       case ANOTL:
-       case ANOTQ:
-               if(copyas(&p->to, v))
-                       return 2;
-               break;
-
-       case ALEAL:     /* lhs addr, rhs store */
-       case ALEAQ:
-               if(copyas(&p->from, v))
-                       return 2;
-
-
-       case ANOP:      /* rhs store */
-       case AMOVL:
-       case AMOVQ:
-       case AMOVBLSX:
-       case AMOVBLZX:
-       case AMOVBQSX:
-       case AMOVBQZX:
-       case AMOVLQSX:
-       case AMOVLQZX:
-       case AMOVWLSX:
-       case AMOVWLZX:
-       case AMOVWQSX:
-       case AMOVWQZX:
-       case AMOVQL:
-
-       case AMOVSS:
-       case AMOVSD:
-       case ACVTSD2SL:
-       case ACVTSD2SQ:
-       case ACVTSD2SS:
-       case ACVTSL2SD:
-       case ACVTSL2SS:
-       case ACVTSQ2SD:
-       case ACVTSQ2SS:
-       case ACVTSS2SD:
-       case ACVTSS2SL:
-       case ACVTSS2SQ:
-       case ACVTTSD2SL:
-       case ACVTTSD2SQ:
-       case ACVTTSS2SL:
-       case ACVTTSS2SQ:
-               if(copyas(&p->to, v)) {
-                       if(s != A)
-                               return copysub(&p->from, v, s, 1);
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-               goto caseread;
-
-       case AROLB:
-       case AROLL:
-       case AROLQ:
-       case AROLW:
-       case ARORB:
-       case ARORL:
-       case ARORQ:
-       case ARORW:
-       case ASALB:
-       case ASALL:
-       case ASALQ:
-       case ASALW:
-       case ASARB:
-       case ASARL:
-       case ASARQ:
-       case ASARW:
-       case ASHLB:
-       case ASHLL:
-       case ASHLQ:
-       case ASHLW:
-       case ASHRB:
-       case ASHRL:
-       case ASHRQ:
-       case ASHRW:
-               if(copyas(&p->to, v))
-                       return 2;
-               if(copyas(&p->from, v))
-                       if(p->from.type == D_CX)
-                               return 2;
-               goto caseread;
-
-       case AADDB:     /* rhs rar */
-       case AADDL:
-       case AADDQ:
-       case AADDW:
-       case AANDB:
-       case AANDL:
-       case AANDQ:
-       case AANDW:
-       case ADECL:
-       case ADECQ:
-       case ADECW:
-       case AINCL:
-       case AINCQ:
-       case AINCW:
-       case ASUBB:
-       case ASUBL:
-       case ASUBQ:
-       case ASUBW:
-       case AORB:
-       case AORL:
-       case AORQ:
-       case AORW:
-       case AXORB:
-       case AXORL:
-       case AXORQ:
-       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;
-
-       case ACMPL:     /* read only */
-       case ACMPW:
-       case ACMPB:
-       case ACMPQ:
-
-       case APREFETCHT0:
-       case APREFETCHT1:
-       case APREFETCHT2:
-       case APREFETCHNTA:
-
-       case ACOMISD:
-       case ACOMISS:
-       case AUCOMISD:
-       case AUCOMISS:
-       caseread:
-               if(s != A) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub(&p->to, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               break;
-
-       case AJGE:      /* no reference */
-       case AJNE:
-       case AJLE:
-       case AJEQ:
-       case AJHI:
-       case AJLS:
-       case AJMI:
-       case AJPL:
-       case AJGT:
-       case AJLT:
-       case AJCC:
-       case AJCS:
-
-       case AADJSP:
-       case AWAIT:
-       case ACLD:
-               break;
-
-       case AIMULL:
-       case AIMULQ:
-       case AIMULW:
-               if(p->to.type != D_NONE) {
-                       if(copyas(&p->to, v))
-                               return 2;
-                       goto caseread;
-               }
-
-       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 ACWD:
-       case ACDQ:
-       case ACQO:
-               if(v->type == D_AX || v->type == D_DX)
-                       return 2;
-               goto caseread;
-
-       case AREP:
-       case AREPN:
-               if(v->type == D_CX)
-                       return 2;
-               goto caseread;
-
-       case AMOVSB:
-       case AMOVSL:
-       case AMOVSQ:
-               if(v->type == D_DI || v->type == D_SI)
-                       return 2;
-               goto caseread;
-
-       case ASTOSB:
-       case ASTOSL:
-       case ASTOSQ:
-               if(v->type == D_AX || v->type == D_DI)
-                       return 2;
-               goto caseread;
-
-       case AJMP:      /* funny */
-               if(s != A) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARET:      /* funny */
-               if(v->type == REGRET || v->type == FREGRET)
-                       return 2;
-               if(s != A)
-                       return 1;
-               return 3;
-
-       case ACALL:     /* funny */
-               if(REGARG >= 0 && v->type == (uchar)REGARG)
-                       return 2;
-
-               if(s != A) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-
-       case ATEXT:     /* funny */
-               if(REGARG >= 0 && v->type == (uchar)REGARG)
-                       return 3;
-               return 0;
-       }
-       return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
-       if(a->type != v->type)
-               return 0;
-       if(regtyp(v))
-               return 1;
-       if(v->type == D_AUTO || v->type == D_PARAM)
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
-       if(copyas(a, v))
-               return 1;
-       if(regtyp(v)) {
-               if(a->type-D_INDIR == v->type)
-                       return 1;
-               if(a->index == v->type)
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-       int t;
-
-       if(copyas(a, v)) {
-               t = s->type;
-               if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
-                       if(f)
-                               a->type = t;
-               }
-               return 0;
-       }
-       if(regtyp(v)) {
-               t = v->type;
-               if(a->type == t+D_INDIR) {
-                       if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
-                               return 1;       /* can't use BP-base with index */
-                       if(f)
-                               a->type = s->type+D_INDIR;
-//                     return 0;
-               }
-               if(a->index == t) {
-                       if(f)
-                               a->index = s->type;
-                       return 0;
-               }
-               return 0;
-       }
-       return 0;
-}
diff --git a/src/cmd/6c/reg.c b/src/cmd/6c/reg.c
deleted file mode 100644 (file)
index 6f8d3ce..0000000
+++ /dev/null
@@ -1,1523 +0,0 @@
-// Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static void    fixjmp(Reg*);
-
-Reg*
-rega(void)
-{
-       Reg *r;
-
-       r = freer;
-       if(r == R) {
-               r = alloc(sizeof(*r));
-       } else
-               freer = r->link;
-
-       *r = zreg;
-       return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
-       Rgn *p1, *p2;
-       int c1, c2;
-
-       p1 = (Rgn*)a1;
-       p2 = (Rgn*)a2;
-       c1 = p2->cost;
-       c2 = p1->cost;
-       if(c1 -= c2)
-               return c1;
-       return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
-       Reg *r, *r1, *r2;
-       Prog *p1;
-       int i, z;
-       int32 initpc, val, npc;
-       uint32 vreg;
-       Bits bit;
-       struct
-       {
-               int32   m;
-               int32   c;
-               Reg*    p;
-       } log5[6], *lp;
-
-       firstr = R;
-       lastr = R;
-       nvar = 0;
-       regbits = RtoB(D_SP) | RtoB(D_AX) | RtoB(D_X0);
-       for(z=0; z<BITS; z++) {
-               externs.b[z] = 0;
-               params.b[z] = 0;
-               consts.b[z] = 0;
-               addrs.b[z] = 0;
-       }
-
-       /*
-        * pass 1
-        * build aux data structure
-        * allocate pcs
-        * find use and set of variables
-        */
-       val = 5L * 5L * 5L * 5L * 5L;
-       lp = log5;
-       for(i=0; i<5; i++) {
-               lp->m = val;
-               lp->c = 0;
-               lp->p = R;
-               val /= 5L;
-               lp++;
-       }
-       val = 0;
-       for(; p != P; p = p->link) {
-               switch(p->as) {
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-               case AFUNCDATA:
-                       continue;
-               }
-               r = rega();
-               if(firstr == R) {
-                       firstr = r;
-                       lastr = r;
-               } else {
-                       lastr->link = r;
-                       r->p1 = lastr;
-                       lastr->s1 = r;
-                       lastr = r;
-               }
-               r->prog = p;
-               r->pc = val;
-               val++;
-
-               lp = log5;
-               for(i=0; i<5; i++) {
-                       lp->c--;
-                       if(lp->c <= 0) {
-                               lp->c = lp->m;
-                               if(lp->p != R)
-                                       lp->p->log5 = r;
-                               lp->p = r;
-                               (lp+1)->c = 0;
-                               break;
-                       }
-                       lp++;
-               }
-
-               r1 = r->p1;
-               if(r1 != R)
-               switch(r1->prog->as) {
-               case ARET:
-               case AJMP:
-               case AIRETL:
-               case AIRETQ:
-                       r->p1 = R;
-                       r1->s1 = R;
-               }
-
-               bit = mkvar(r, &p->from);
-               if(bany(&bit))
-               switch(p->as) {
-               /*
-                * funny
-                */
-               case ALEAL:
-               case ALEAQ:
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * left side read
-                */
-               default:
-                       for(z=0; z<BITS; z++)
-                               r->use1.b[z] |= bit.b[z];
-                       break;
-               }
-
-               bit = mkvar(r, &p->to);
-               if(bany(&bit))
-               switch(p->as) {
-               default:
-                       diag(Z, "reg: unknown op: %A", p->as);
-                       break;
-
-               /*
-                * right side read
-                */
-               case ACMPB:
-               case ACMPL:
-               case ACMPQ:
-               case ACMPW:
-               case APREFETCHT0:
-               case APREFETCHT1:
-               case APREFETCHT2:
-               case APREFETCHNTA:
-               case ACOMISS:
-               case ACOMISD:
-               case AUCOMISS:
-               case AUCOMISD:
-                       for(z=0; z<BITS; z++)
-                               r->use2.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * right side write
-                */
-               case ANOP:
-               case AMOVL:
-               case AMOVQ:
-               case AMOVB:
-               case AMOVW:
-               case AMOVBLSX:
-               case AMOVBLZX:
-               case AMOVBQSX:
-               case AMOVBQZX:
-               case AMOVLQSX:
-               case AMOVLQZX:
-               case AMOVWLSX:
-               case AMOVWLZX:
-               case AMOVWQSX:
-               case AMOVWQZX:
-               case AMOVQL:
-
-               case AMOVSS:
-               case AMOVSD:
-               case ACVTSD2SL:
-               case ACVTSD2SQ:
-               case ACVTSD2SS:
-               case ACVTSL2SD:
-               case ACVTSL2SS:
-               case ACVTSQ2SD:
-               case ACVTSQ2SS:
-               case ACVTSS2SD:
-               case ACVTSS2SL:
-               case ACVTSS2SQ:
-               case ACVTTSD2SL:
-               case ACVTTSD2SQ:
-               case ACVTTSS2SL:
-               case ACVTTSS2SQ:
-                       for(z=0; z<BITS; z++)
-                               r->set.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * right side read+write
-                */
-               case AADDB:
-               case AADDL:
-               case AADDQ:
-               case AADDW:
-               case AANDB:
-               case AANDL:
-               case AANDQ:
-               case AANDW:
-               case ASUBB:
-               case ASUBL:
-               case ASUBQ:
-               case ASUBW:
-               case AORB:
-               case AORL:
-               case AORQ:
-               case AORW:
-               case AXORB:
-               case AXORL:
-               case AXORQ:
-               case AXORW:
-               case ASALB:
-               case ASALL:
-               case ASALQ:
-               case ASALW:
-               case ASARB:
-               case ASARL:
-               case ASARQ:
-               case ASARW:
-               case AROLB:
-               case AROLL:
-               case AROLQ:
-               case AROLW:
-               case ARORB:
-               case ARORL:
-               case ARORQ:
-               case ARORW:
-               case ASHLB:
-               case ASHLL:
-               case ASHLQ:
-               case ASHLW:
-               case ASHRB:
-               case ASHRL:
-               case ASHRQ:
-               case ASHRW:
-               case AIMULL:
-               case AIMULQ:
-               case AIMULW:
-               case ANEGL:
-               case ANEGQ:
-               case ANOTL:
-               case ANOTQ:
-               case AADCL:
-               case AADCQ:
-               case ASBBL:
-               case ASBBQ:
-
-               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];
-                       }
-                       break;
-
-               /*
-                * funny
-                */
-               case ACALL:
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-                       break;
-               }
-
-               switch(p->as) {
-               case AIMULL:
-               case AIMULQ:
-               case AIMULW:
-                       if(p->to.type != D_NONE)
-                               break;
-
-               case AIDIVB:
-               case AIDIVL:
-               case AIDIVQ:
-               case AIDIVW:
-               case AIMULB:
-               case ADIVB:
-               case ADIVL:
-               case ADIVQ:
-               case ADIVW:
-               case AMULB:
-               case AMULL:
-               case AMULQ:
-               case AMULW:
-
-               case ACWD:
-               case ACDQ:
-               case ACQO:
-                       r->regu |= RtoB(D_AX) | RtoB(D_DX);
-                       break;
-
-               case AREP:
-               case AREPN:
-               case ALOOP:
-               case ALOOPEQ:
-               case ALOOPNE:
-                       r->regu |= RtoB(D_CX);
-                       break;
-
-               case AMOVSB:
-               case AMOVSL:
-               case AMOVSQ:
-               case AMOVSW:
-               case ACMPSB:
-               case ACMPSL:
-               case ACMPSQ:
-               case ACMPSW:
-                       r->regu |= RtoB(D_SI) | RtoB(D_DI);
-                       break;
-
-               case ASTOSB:
-               case ASTOSL:
-               case ASTOSQ:
-               case ASTOSW:
-               case ASCASB:
-               case ASCASL:
-               case ASCASQ:
-               case ASCASW:
-                       r->regu |= RtoB(D_AX) | RtoB(D_DI);
-                       break;
-
-               case AINSB:
-               case AINSL:
-               case AINSW:
-               case AOUTSB:
-               case AOUTSL:
-               case AOUTSW:
-                       r->regu |= RtoB(D_DI) | RtoB(D_DX);
-                       break;
-               }
-       }
-       if(firstr == R)
-               return;
-       initpc = pc - val;
-       npc = val;
-
-       /*
-        * pass 2
-        * turn branch references to pointers
-        * build back pointers
-        */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       val = p->to.offset - initpc;
-                       r1 = firstr;
-                       while(r1 != R) {
-                               r2 = r1->log5;
-                               if(r2 != R && val >= r2->pc) {
-                                       r1 = r2;
-                                       continue;
-                               }
-                               if(r1->pc == val)
-                                       break;
-                               r1 = r1->link;
-                       }
-                       if(r1 == R) {
-                               nearln = p->lineno;
-                               diag(Z, "ref not found\n%P", p);
-                               continue;
-                       }
-                       if(r1 == r) {
-                               nearln = p->lineno;
-                               diag(Z, "ref to self\n%P", p);
-                               continue;
-                       }
-                       r->s2 = r1;
-                       r->p2link = r1->p2;
-                       r1->p2 = r;
-               }
-       }
-       if(debug['R']) {
-               p = firstr->prog;
-               print("\n%L %D\n", p->lineno, &p->from);
-       }
-
-       /*
-        * pass 2.1
-        * fix jumps
-        */
-       fixjmp(firstr);
-
-       /*
-        * pass 2.5
-        * find looping structure
-        */
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       change = 0;
-       loopit(firstr, npc);
-       if(debug['R'] && debug['v']) {
-               print("\nlooping structure:\n");
-               for(r = firstr; r != R; r = r->link) {
-                       print("%d:%P", r->loop, r->prog);
-                       for(z=0; z<BITS; z++)
-                               bit.b[z] = r->use1.b[z] |
-                                          r->use2.b[z] |
-                                          r->set.b[z];
-                       if(bany(&bit)) {
-                               print("\t");
-                               if(bany(&r->use1))
-                                       print(" u1=%B", r->use1);
-                               if(bany(&r->use2))
-                                       print(" u2=%B", r->use2);
-                               if(bany(&r->set))
-                                       print(" st=%B", r->set);
-                       }
-                       print("\n");
-               }
-       }
-
-       /*
-        * pass 3
-        * iterate propagating usage
-        *      back until flow graph is complete
-        */
-loop1:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       for(r = firstr; r != R; r = r->link)
-               if(r->prog->as == ARET)
-                       prop(r, zbits, zbits);
-loop11:
-       /* pick up unreachable code */
-       i = 0;
-       for(r = firstr; r != R; r = r1) {
-               r1 = r->link;
-               if(r1 && r1->active && !r->active) {
-                       prop(r, zbits, zbits);
-                       i = 1;
-               }
-       }
-       if(i)
-               goto loop11;
-       if(change)
-               goto loop1;
-
-
-       /*
-        * pass 4
-        * iterate propagating register/variable synchrony
-        *      forward until graph is complete
-        */
-loop2:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       synch(firstr, zbits);
-       if(change)
-               goto loop2;
-
-
-       /*
-        * pass 5
-        * isolate regions
-        * calculate costs (paint1)
-        */
-       r = firstr;
-       if(r) {
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
-                         ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "used and not set: %B", bit);
-                       if(debug['R'] && !debug['w'])
-                               print("used and not set: %B\n", bit);
-               }
-       }
-       if(debug['R'] && debug['v'])
-               print("\nprop structure:\n");
-       for(r = firstr; r != R; r = r->link)
-               r->act = zbits;
-       rgp = region;
-       nregion = 0;
-       for(r = firstr; r != R; r = r->link) {
-               if(debug['R'] && debug['v']) {
-                       print("%P\t", r->prog);
-                       if(bany(&r->set))
-                               print("s:%B ", r->set);
-                       if(bany(&r->refahead))
-                               print("ra:%B ", r->refahead);
-                       if(bany(&r->calahead))
-                               print("ca:%B ", r->calahead);
-                       print("\n");
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = r->set.b[z] &
-                         ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "set and not used: %B", bit);
-                       if(debug['R'])
-                               print("set and not used: %B\n", bit);
-                       excise(r);
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
-               while(bany(&bit)) {
-                       i = bnum(bit);
-                       rgp->enter = r;
-                       rgp->varno = i;
-                       change = 0;
-                       if(debug['R'] && debug['v'])
-                               print("\n");
-                       paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
-                       if(change <= 0) {
-                               if(debug['R'])
-                                       print("%L$%d: %B\n",
-                                               r->prog->lineno, change, blsh(i));
-                               continue;
-                       }
-                       rgp->cost = change;
-                       nregion++;
-                       if(nregion >= NRGN)
-                               fatal(Z, "too many regions");
-                       rgp++;
-               }
-       }
-       qsort(region, nregion, sizeof(region[0]), rcmp);
-
-       /*
-        * pass 6
-        * determine used registers (paint2)
-        * replace code (paint3)
-        */
-       rgp = region;
-       for(i=0; i<nregion; i++) {
-               bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
-               vreg = allreg(vreg, rgp);
-               if(debug['R']) {
-                       print("%L$%d %R: %B\n",
-                               rgp->enter->prog->lineno,
-                               rgp->cost,
-                               rgp->regno,
-                               bit);
-               }
-               if(rgp->regno != 0)
-                       paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
-               rgp++;
-       }
-       /*
-        * pass 7
-        * peep-hole on basic block
-        */
-       if(!debug['R'] || debug['P'])
-               peep();
-
-       /*
-        * pass 8
-        * recalculate pc
-        */
-       val = initpc;
-       for(r = firstr; r != R; r = r1) {
-               r->pc = val;
-               p = r->prog;
-               p1 = P;
-               r1 = r->link;
-               if(r1 != R)
-                       p1 = r1->prog;
-               for(; p != p1; p = p->link) {
-                       switch(p->as) {
-                       default:
-                               val++;
-                               break;
-
-                       case ANOP:
-                       case ADATA:
-                       case AGLOBL:
-                       case ANAME:
-                       case ASIGNAME:
-                       case AFUNCDATA:
-                               break;
-                       }
-               }
-       }
-       pc = val;
-
-       /*
-        * fix up branches
-        */
-       if(debug['R'])
-               if(bany(&addrs))
-                       print("addrs: %B\n", addrs);
-
-       r1 = 0; /* set */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       p->to.offset = r->s2->pc;
-                       p->to.u.branch = r->s2->prog;
-               }
-               r1 = r;
-       }
-
-       /*
-        * last pass
-        * eliminate nops
-        * free aux structures
-        */
-       for(p = firstr->prog; p != P; p = p->link){
-               while(p->link && p->link->as == ANOP)
-                       p->link = p->link->link;
-       }
-       if(r1 != R) {
-               r1->link = freer;
-               freer = firstr;
-       }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
-       Prog *p, *p1;
-       Addr *a;
-       Var *v;
-
-       p1 = alloc(sizeof(*p1));
-       *p1 = zprog;
-       p = r->prog;
-
-       p1->link = p->link;
-       p->link = p1;
-       p1->lineno = p->lineno;
-
-       v = var + bn;
-
-       a = &p1->to;
-       a->sym = v->sym;
-       a->offset = v->offset;
-       a->etype = v->etype;
-       a->type = v->name;
-
-       p1->as = AMOVL;
-       if(v->etype == TCHAR || v->etype == TUCHAR)
-               p1->as = AMOVB;
-       if(v->etype == TSHORT || v->etype == TUSHORT)
-               p1->as = AMOVW;
-       if(v->etype == TVLONG || v->etype == TUVLONG || (v->etype == TIND && ewidth[TIND] == 8))
-               p1->as = AMOVQ;
-       if(v->etype == TFLOAT)
-               p1->as = AMOVSS;
-       if(v->etype == TDOUBLE)
-               p1->as = AMOVSD;
-
-       p1->from.type = rn;
-       if(!f) {
-               p1->from = *a;
-               *a = zprog.from;
-               a->type = rn;
-               if(v->etype == TUCHAR)
-                       p1->as = AMOVB;
-               if(v->etype == TUSHORT)
-                       p1->as = AMOVW;
-       }
-       if(debug['R'])
-               print("%P\t.a%P\n", p, p1);
-}
-
-uint32
-doregbits(int r)
-{
-       uint32 b;
-
-       b = 0;
-       if(r >= D_INDIR)
-               r -= D_INDIR;
-       if(r >= D_AX && r <= D_R15)
-               b |= RtoB(r);
-       else
-       if(r >= D_AL && r <= D_R15B)
-               b |= RtoB(r-D_AL+D_AX);
-       else
-       if(r >= D_AH && r <= D_BH)
-               b |= RtoB(r-D_AH+D_AX);
-       else
-       if(r >= D_X0 && r <= D_X0+15)
-               b |= FtoB(r);
-       return b;
-}
-
-Bits
-mkvar(Reg *r, Addr *a)
-{
-       Var *v;
-       int i, t, n, et, z;
-       int32 o;
-       Bits bit;
-       LSym *s;
-
-       /*
-        * mark registers used
-        */
-       t = a->type;
-       r->regu |= doregbits(t);
-       r->regu |= doregbits(a->index);
-
-       switch(t) {
-       default:
-               goto none;
-       case D_ADDR:
-               a->type = a->index;
-               bit = mkvar(r, a);
-               for(z=0; z<BITS; z++)
-                       addrs.b[z] |= bit.b[z];
-               a->type = t;
-               goto none;
-       case D_EXTERN:
-       case D_STATIC:
-       case D_PARAM:
-       case D_AUTO:
-               n = t;
-               break;
-       }
-       s = a->sym;
-       if(s == nil)
-               goto none;
-       if(s->name[0] == '.')
-               goto none;
-       et = a->etype;
-       o = a->offset;
-       v = var;
-       for(i=0; i<nvar; i++) {
-               if(s == v->sym)
-               if(n == v->name)
-               if(o == v->offset)
-                       goto out;
-               v++;
-       }
-       if(nvar >= NVAR)
-               fatal(Z, "variable not optimized: %s", s->name);
-       i = nvar;
-       nvar++;
-       v = &var[i];
-       v->sym = s;
-       v->offset = o;
-       v->name = n;
-       v->etype = et;
-       if(debug['R'])
-               print("bit=%2d et=%2d %D\n", i, et, a);
-
-out:
-       bit = blsh(i);
-       if(n == D_EXTERN || n == D_STATIC)
-               for(z=0; z<BITS; z++)
-                       externs.b[z] |= bit.b[z];
-       if(n == D_PARAM)
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-       if(v->etype != et || !(typechlpfd[et] || typev[et]))    /* funny punning */
-               for(z=0; z<BITS; z++)
-                       addrs.b[z] |= bit.b[z];
-       return bit;
-
-none:
-       return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
-       Reg *r1, *r2;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->p1) {
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] |= r1->refahead.b[z];
-                       if(ref.b[z] != r1->refahead.b[z]) {
-                               r1->refahead.b[z] = ref.b[z];
-                               change++;
-                       }
-                       cal.b[z] |= r1->calahead.b[z];
-                       if(cal.b[z] != r1->calahead.b[z]) {
-                               r1->calahead.b[z] = cal.b[z];
-                               change++;
-                       }
-               }
-               switch(r1->prog->as) {
-               case ACALL:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] |= ref.b[z] | externs.b[z];
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ATEXT:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = 0;
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ARET:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = externs.b[z];
-                               ref.b[z] = 0;
-                       }
-               }
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
-                               r1->use1.b[z] | r1->use2.b[z];
-                       cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
-                       r1->refbehind.b[z] = ref.b[z];
-                       r1->calbehind.b[z] = cal.b[z];
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-       }
-       for(; r != r1; r = r->p1)
-               for(r2 = r->p2; r2 != R; r2 = r2->p2link)
-                       prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- *     the actual dominators if the flow graph is reducible
- *     otherwise, dominators plus some other non-dominators.
- *     See Matthew S. Hecht and Jeffrey D. Ullman,
- *     "Analysis of a Simple Algorithm for Global Data Flow Problems",
- *     Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- *     Oct. 1-3, 1973, pp.  207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- *     such a node is a loop head.
- *     recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
-       Reg *r1;
-
-       r->rpo = 1;
-       r1 = r->s1;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       r1 = r->s2;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       rpo2r[n] = r;
-       n++;
-       return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
-       int32 t;
-
-       if(rpo1 == -1)
-               return rpo2;
-       while(rpo1 != rpo2){
-               if(rpo1 > rpo2){
-                       t = rpo2;
-                       rpo2 = rpo1;
-                       rpo1 = t;
-               }
-               while(rpo1 < rpo2){
-                       t = idom[rpo2];
-                       if(t >= rpo2)
-                               fatal(Z, "bad idom");
-                       rpo2 = t;
-               }
-       }
-       return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
-       while(s > r)
-               s = idom[s];
-       return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
-       int32 src;
-
-       src = r->rpo;
-       if(r->p1 != R && doms(idom, src, r->p1->rpo))
-               return 1;
-       for(r = r->p2; r != R; r = r->p2link)
-               if(doms(idom, src, r->rpo))
-                       return 1;
-       return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
-       if(r->rpo < head || r->active == head)
-               return;
-       r->active = head;
-       r->loop += LOOP;
-       if(r->p1 != R)
-               loopmark(rpo2r, head, r->p1);
-       for(r = r->p2; r != R; r = r->p2link)
-               loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
-       Reg *r1;
-       int32 i, d, me;
-
-       if(nr > maxnr) {
-               rpo2r = alloc(nr * sizeof(Reg*));
-               idom = alloc(nr * sizeof(int32));
-               maxnr = nr;
-       }
-
-       d = postorder(r, rpo2r, 0);
-       if(d > nr)
-               fatal(Z, "too many reg nodes");
-       nr = d;
-       for(i = 0; i < nr / 2; i++){
-               r1 = rpo2r[i];
-               rpo2r[i] = rpo2r[nr - 1 - i];
-               rpo2r[nr - 1 - i] = r1;
-       }
-       for(i = 0; i < nr; i++)
-               rpo2r[i]->rpo = i;
-
-       idom[0] = 0;
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               me = r1->rpo;
-               d = -1;
-               if(r1->p1 != R && r1->p1->rpo < me)
-                       d = r1->p1->rpo;
-               for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-                       if(r1->rpo < me)
-                               d = rpolca(idom, d, r1->rpo);
-               idom[i] = d;
-       }
-
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               r1->loop++;
-               if(r1->p2 != R && loophead(idom, r1))
-                       loopmark(rpo2r, i, r1);
-       }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
-       Reg *r1;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->s1) {
-               for(z=0; z<BITS; z++) {
-                       dif.b[z] = (dif.b[z] &
-                               ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
-                                       r1->set.b[z] | r1->regdiff.b[z];
-                       if(dif.b[z] != r1->regdiff.b[z]) {
-                               r1->regdiff.b[z] = dif.b[z];
-                               change++;
-                       }
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-               for(z=0; z<BITS; z++)
-                       dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
-               if(r1->s2 != R)
-                       synch(r1->s2, dif);
-       }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
-       Var *v;
-       int i;
-
-       v = var + r->varno;
-       r->regno = 0;
-       switch(v->etype) {
-
-       default:
-               diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
-               break;
-
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TIND:
-       case TARRAY:
-               i = BtoR(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i;
-                       return RtoB(i);
-               }
-               break;
-
-       case TDOUBLE:
-       case TFLOAT:
-               i = BtoF(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i;
-                       return FtoB(i);
-               }
-               break;
-       }
-       return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L<<(bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
-               change -= CLOAD * r->loop;
-               if(debug['R'] && debug['v'])
-                       print("%d%P\td %B $%d\n", r->loop,
-                               r->prog, blsh(bn), change);
-       }
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       change += CREF * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tu1 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       change += CREF * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tu2 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb) {
-                       change -= CLOAD * r->loop;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tst %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint1(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint1(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-uint32
-regset(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Addr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = b & 0xFFFF? BtoR(b): BtoF(b);
-               if(v.type == 0)
-                       diag(Z, "zero v.type for %#ux", b);
-               c = copyu(r->prog, &v, A);
-               if(c == 3)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Addr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = b & 0xFFFF? BtoR(b): BtoF(b);
-               c = copyu(r->prog, &v, A);
-               if(c == 1 || c == 2 || c == 4)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
-       Reg *r1;
-       int z;
-       uint32 bb, vreg, x;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       vreg = regbits;
-       if(!(r->act.b[z] & bb))
-               return vreg;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(!(r1->act.b[z] & bb))
-                       break;
-               r = r1;
-       }
-       for(;;) {
-               r->act.b[z] &= ~bb;
-
-               vreg |= r->regu;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(!(r->act.b[z] & bb))
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-
-       bb = vreg;
-       for(; r; r=r->s1) {
-               x = r->regu & ~bb;
-               if(x) {
-                       vreg |= reguse(r, x);
-                       bb |= regset(r, x);
-               }
-       }
-       return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
-               addmove(r, bn, rn, 0);
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->from, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->to, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb)
-                       addmove(r, bn, rn, 1);
-               r->regu |= rb;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint3(r1, bn, rb, rn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint3(r1, bn, rb, rn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
-       a->sym = 0;
-       a->offset = 0;
-       a->type = rn;
-}
-
-int32
-RtoB(int r)
-{
-
-       if(r < D_AX || r > D_R15)
-               return 0;
-       return 1L << (r-D_AX);
-}
-
-int
-BtoR(int32 b)
-{
-
-       b &= 0xffffL;
-       if(nacl)
-               b &= ~((1<<(D_BP-D_AX)) | (1<<(D_R15-D_AX)));
-       if(b == 0)
-               return 0;
-       return bitno(b) + D_AX;
-}
-
-/*
- *     bit     reg
- *     16      X5
- *     17      X6
- *     18      X7
- */
-int32
-FtoB(int f)
-{
-       if(f < FREGMIN || f > FREGEXT)
-               return 0;
-       return 1L << (f - FREGMIN + 16);
-}
-
-int
-BtoF(int32 b)
-{
-
-       b &= 0x70000L;
-       if(b == 0)
-               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", (int)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;
-                       p->to.u.branch = r->s2->prog;
-                       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", (int)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", (int)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", (int)r->pc, r->prog);
-               print("\n");
-       }
-}
-
diff --git a/src/cmd/6c/sgen.c b/src/cmd/6c/sgen.c
deleted file mode 100644 (file)
index fceb332..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-// Inferno utils/6c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
-       vlong v;
-
-       v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
-       if((textflag & NOSPLIT) && stkoff >= 128)
-               yyerror("stack frame too large for NOSPLIT function");
-
-       gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
-       return p;
-}
-
-void
-noretval(int n)
-{
-
-       if(n & 1) {
-               gins(ANOP, Z, Z);
-               p->to.type = REGRET;
-       }
-       if(n & 2) {
-               gins(ANOP, Z, Z);
-               p->to.type = FREGRET;
-       }
-}
-
-/* welcome to commute */
-static void
-commute(Node *n)
-{
-       Node *l, *r;
-
-       l = n->left;
-       r = n->right;
-       if(r->complex > l->complex) {
-               n->left = r;
-               n->right = l;
-       }
-}
-
-void
-indexshift(Node *n)
-{
-       int g;
-
-       if(!typechlpv[n->type->etype])
-               return;
-       simplifyshift(n);
-       if(n->op == OASHL && n->right->op == OCONST){
-               g = vconst(n->right);
-               if(g >= 0 && g <= 3)
-                       n->addable = 7;
-       }
-}
-
-/*
- *     calculate addressability as follows
- *             NAME ==> 10/11          name+value(SB/SP)
- *             REGISTER ==> 12         register
- *             CONST ==> 20            $value
- *             *(20) ==> 21            value
- *             &(10) ==> 13            $name+value(SB)
- *             &(11) ==> 1             $name+value(SP)
- *             (13) + (20) ==> 13      fold constants
- *             (1) + (20) ==> 1        fold constants
- *             *(13) ==> 10            back to name
- *             *(1) ==> 11             back to name
- *
- *             (20) * (X) ==> 7        multiplier in indexing
- *             (X,7) + (13,1) ==> 8    adder in indexing (addresses)
- *             (8) ==> &9(OINDEX)      index, almost addressable
- *
- *     calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
-       Node *l, *r;
-       int g;
-
-       if(n == Z)
-               return;
-       l = n->left;
-       r = n->right;
-       n->complex = 0;
-       n->addable = 0;
-       switch(n->op) {
-       case OCONST:
-               n->addable = 20;
-               break;
-
-       case ONAME:
-               n->addable = 9;
-               if(n->class == CPARAM || n->class == CAUTO)
-                       n->addable = 11;
-               break;
-
-       case OEXREG:
-               n->addable = 0;
-               break;
-
-       case OREGISTER:
-               n->addable = 12;
-               break;
-
-       case OINDREG:
-               n->addable = 12;
-               break;
-
-       case OADDR:
-               xcom(l);
-               if(l->addable == 10)
-                       n->addable = 13;
-               else
-               if(l->addable == 11)
-                       n->addable = 1;
-               break;
-
-       case OADD:
-               xcom(l);
-               xcom(r);
-               if(n->type->etype != TIND)
-                       break;
-
-               switch(r->addable) {
-               case 20:
-                       switch(l->addable) {
-                       case 1:
-                       case 13:
-                       commadd:
-                               l->type = n->type;
-                               *n = *l;
-                               l = new(0, Z, Z);
-                               *l = *(n->left);
-                               l->xoffset += r->vconst;
-                               n->left = l;
-                               r = n->right;
-                               goto brk;
-                       }
-                       break;
-
-               case 1:
-               case 13:
-               case 10:
-               case 11:
-                       /* l is the base, r is the index */
-                       if(l->addable != 20)
-                               n->addable = 8;
-                       break;
-               }
-               switch(l->addable) {
-               case 20:
-                       switch(r->addable) {
-                       case 13:
-                       case 1:
-                               r = n->left;
-                               l = n->right;
-                               n->left = l;
-                               n->right = r;
-                               goto commadd;
-                       }
-                       break;
-
-               case 13:
-               case 1:
-               case 10:
-               case 11:
-                       /* r is the base, l is the index */
-                       if(r->addable != 20)
-                               n->addable = 8;
-                       break;
-               }
-               if(n->addable == 8 && !side(n) && !nacl) {
-                       indx(n);
-                       l = new1(OINDEX, idx.basetree, idx.regtree);
-                       l->scale = idx.scale;
-                       l->addable = 9;
-                       l->complex = l->right->complex;
-                       l->type = l->left->type;
-                       n->op = OADDR;
-                       n->left = l;
-                       n->right = Z;
-                       n->addable = 8;
-                       break;
-               }
-               break;
-
-       case OINDEX:
-               xcom(l);
-               xcom(r);
-               n->addable = 9;
-               break;
-
-       case OIND:
-               xcom(l);
-               if(l->op == OADDR) {
-                       l = l->left;
-                       l->type = n->type;
-                       *n = *l;
-                       return;
-               }
-               switch(l->addable) {
-               case 20:
-                       n->addable = 21;
-                       break;
-               case 1:
-                       n->addable = 11;
-                       break;
-               case 13:
-                       n->addable = 10;
-                       break;
-               }
-               break;
-
-       case OASHL:
-               xcom(l);
-               xcom(r);
-               indexshift(n);
-               break;
-
-       case OMUL:
-       case OLMUL:
-               xcom(l);
-               xcom(r);
-               g = vlog(l);
-               if(g >= 0) {
-                       n->left = r;
-                       n->right = l;
-                       l = r;
-                       r = n->right;
-               }
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASHL;
-                       r->vconst = g;
-                       r->type = types[TINT];
-                       indexshift(n);
-                       break;
-               }
-               commute(n);
-               break;
-
-       case OASLDIV:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASLSHR;
-                       r->vconst = g;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OLDIV:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OLSHR;
-                       r->vconst = g;
-                       r->type = types[TINT];
-                       indexshift(n);
-                       break;
-               }
-               break;
-
-       case OASLMOD:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OLMOD:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OASMUL:
-       case OASLMUL:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASASHL;
-                       r->vconst = g;
-               }
-               break;
-
-       case OLSHR:
-       case OASHR:
-               xcom(l);
-               xcom(r);
-               indexshift(n);
-               break;
-
-       default:
-               if(l != Z)
-                       xcom(l);
-               if(r != Z)
-                       xcom(r);
-               break;
-       }
-brk:
-       if(n->addable >= 10)
-               return;
-       if(l != Z)
-               n->complex = l->complex;
-       if(r != Z) {
-               if(r->complex == n->complex)
-                       n->complex = r->complex+1;
-               else
-               if(r->complex > n->complex)
-                       n->complex = r->complex;
-       }
-       if(n->complex == 0)
-               n->complex++;
-
-       switch(n->op) {
-
-       case OFUNC:
-               n->complex = FNX;
-               break;
-
-       case OCAST:
-               if(l->type->etype == TUVLONG && typefd[n->type->etype])
-                       n->complex += 2;
-               break;
-
-       case OLMOD:
-       case OMOD:
-       case OLMUL:
-       case OLDIV:
-       case OMUL:
-       case ODIV:
-       case OASLMUL:
-       case OASLDIV:
-       case OASLMOD:
-       case OASMUL:
-       case OASDIV:
-       case OASMOD:
-               if(r->complex >= l->complex) {
-                       n->complex = l->complex + 3;
-                       if(r->complex > n->complex)
-                               n->complex = r->complex;
-               } else {
-                       n->complex = r->complex + 3;
-                       if(l->complex > n->complex)
-                               n->complex = l->complex;
-               }
-               break;
-
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-       case OASLSHR:
-       case OASASHL:
-       case OASASHR:
-               if(r->complex >= l->complex) {
-                       n->complex = l->complex + 2;
-                       if(r->complex > n->complex)
-                               n->complex = r->complex;
-               } else {
-                       n->complex = r->complex + 2;
-                       if(l->complex > n->complex)
-                               n->complex = l->complex;
-               }
-               break;
-
-       case OADD:
-       case OXOR:
-       case OAND:
-       case OOR:
-               /*
-                * immediate operators, make const on right
-                */
-               if(l->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-               }
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               /*
-                * compare operators, make const on left
-                */
-               if(r->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-                       n->op = invrel[relindex(n->op)];
-               }
-               break;
-       }
-}
-
-void
-indx(Node *n)
-{
-       Node *l, *r;
-
-       if(debug['x'])
-               prtree(n, "indx");
-
-       l = n->left;
-       r = n->right;
-       if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
-               n->right = l;
-               n->left = r;
-               l = r;
-               r = n->right;
-       }
-       if(l->addable != 7) {
-               idx.regtree = l;
-               idx.scale = 1;
-       } else
-       if(l->right->addable == 20) {
-               idx.regtree = l->left;
-               idx.scale = 1 << l->right->vconst;
-       } else
-       if(l->left->addable == 20) {
-               idx.regtree = l->right;
-               idx.scale = 1 << l->left->vconst;
-       } else
-               diag(n, "bad index");
-
-       idx.basetree = r;
-       if(debug['x']) {
-               print("scale = %d\n", idx.scale);
-               prtree(idx.regtree, "index");
-               prtree(idx.basetree, "base");
-       }
-}
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
deleted file mode 100644 (file)
index 6e918eb..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-// Inferno utils/6c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
-       Node nreg;
-
-       regalloc(&nreg, n, Z);
-       if(typev[n->type->etype])
-               nreg.type = types[TVLONG];
-       else
-               nreg.type = types[TLONG];
-       cgen(n, &nreg);
-       swit2(q, nc, def, &nreg);
-       regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
-       C1 *r;
-       int i;
-       Prog *sp;
-
-       if(nc < 5) {
-               for(i=0; i<nc; i++) {
-                       if(debug['W'])
-                               print("case = %.8llux\n", q->val);
-                       gcmp(OEQ, n, q->val);
-                       patch(p, q->label);
-                       q++;
-               }
-               gbranch(OGOTO);
-               patch(p, def);
-               return;
-       }
-       i = nc / 2;
-       r = q+i;
-       if(debug['W'])
-               print("case > %.8llux\n", r->val);
-       gcmp(OGT, n, r->val);
-       sp = p;
-       gbranch(OGOTO);
-       p->as = AJEQ;
-       patch(p, r->label);
-       swit2(q, i, def, n);
-
-       if(debug['W'])
-               print("case < %.8llux\n", r->val);
-       patch(sp, pc);
-       swit2(r+1, nc-i-1, def, n);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int sh;
-       int32 v;
-       Node *l;
-
-       /*
-        * n1 gets adjusted/masked value
-        * n2 gets address of cell
-        * n3 gets contents of cell
-        */
-       l = b->left;
-       if(n2 != Z) {
-               regalloc(n1, l, nn);
-               reglcgen(n2, l, Z);
-               regalloc(n3, l, Z);
-               gmove(n2, n3);
-               gmove(n3, n1);
-       } else {
-               regalloc(n1, l, nn);
-               cgen(l, n1);
-       }
-       if(b->type->shift == 0 && typeu[b->type->etype]) {
-               v = ~0 + (1L << b->type->nbits);
-               gopcode(OAND, tfield, nodconst(v), n1);
-       } else {
-               sh = 32 - b->type->shift - b->type->nbits;
-               if(sh > 0)
-                       gopcode(OASHL, tfield, nodconst(sh), n1);
-               sh += b->type->shift;
-               if(sh > 0)
-                       if(typeu[b->type->etype])
-                               gopcode(OLSHR, tfield, nodconst(sh), n1);
-                       else
-                               gopcode(OASHR, tfield, nodconst(sh), n1);
-       }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int32 v;
-       Node nod;
-       int sh;
-
-       regalloc(&nod, b->left, Z);
-       v = ~0 + (1L << b->type->nbits);
-       gopcode(OAND, types[TLONG], nodconst(v), n1);
-       gmove(n1, &nod);
-       if(nn != Z)
-               gmove(n1, nn);
-       sh = b->type->shift;
-       if(sh > 0)
-               gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
-       v <<= sh;
-       gopcode(OAND, types[TLONG], nodconst(~v), n3);
-       gopcode(OOR, types[TLONG], n3, &nod);
-       gmove(&nod, n2);
-
-       regfree(&nod);
-       regfree(n1);
-       regfree(n2);
-       regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
-       int32 r;
-
-       if(suppress)
-               return nstring;
-       r = nstring;
-       while(n) {
-               string[mnstring] = *s++;
-               mnstring++;
-               nstring++;
-               if(mnstring >= NSNAME) {
-                       gpseudo(ADATA, symstring, nodconst(0L));
-                       p->from.offset += nstring - NSNAME;
-                       p->from.scale = NSNAME;
-                       p->to.type = D_SCONST;
-                       memmove(p->to.u.sval, string, NSNAME);
-                       mnstring = 0;
-               }
-               n--;
-       }
-       return r;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       int32 e, lw;
-
-       for(e=0; e<w; e+=NSNAME) {
-               lw = NSNAME;
-               if(w-e < lw)
-                       lw = w-e;
-               gpseudo(ADATA, s, nodconst(0L));
-               p->from.offset += o+e;
-               p->from.scale = lw;
-               p->to.type = D_SCONST;
-               memmove(p->to.u.sval, a->cstring+e, lw);
-       }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       if(0 && a->op == OCONST && typev[a->type->etype]) {
-               gpseudo(ADATA, s, lo64(a));
-               p->from.offset += o;
-               p->from.scale = 4;
-               gpseudo(ADATA, s, hi64(a));
-               p->from.offset += o + 4;
-               p->from.scale = 4;
-               return;
-       }
-       gpseudo(ADATA, s, a);
-       p->from.offset += o;
-       p->from.scale = w;
-       switch(p->to.type) {
-       default:
-               p->to.index = p->to.type;
-               p->to.type = D_ADDR;
-       case D_CONST:
-       case D_FCONST:
-       case D_ADDR:
-               break;
-       }
-}
-
-void
-outcode(void)
-{
-       int f;
-       Biobuf b;
-
-       f = open(outfile, OWRITE);
-       if(f < 0) {
-               diag(Z, "cannot open %s", outfile);
-               return;
-       }
-       Binit(&b, f, OWRITE);
-
-       Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       if(pragcgobuf.to > pragcgobuf.start) {
-               Bprint(&b, "\n");
-               Bprint(&b, "$$  // exports\n\n");
-               Bprint(&b, "$$  // local types\n\n");
-               Bprint(&b, "$$  // cgo\n");
-               Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
-               Bprint(&b, "\n$$\n\n");
-       }
-       Bprint(&b, "!\n");
-
-       writeobj(ctxt, &b);
-       Bterm(&b);
-       close(f);
-       lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
-       int32 o;
-       Type *v;
-       int w, packw;
-
-       o = i;
-       w = 1;
-       packw = 0;
-       switch(op) {
-       default:
-               diag(Z, "unknown align opcode %d", op);
-               break;
-
-       case Asu2:      /* padding at end of a struct */
-               w = *maxalign;
-               if(w < 1)
-                       w = 1;
-               if(packflg)
-                       packw = packflg;
-               break;
-
-       case Ael1:      /* initial align of struct element */
-               for(v=t; v->etype==TARRAY; v=v->link)
-                       ;
-               if(v->etype == TSTRUCT || v->etype == TUNION)
-                       w = v->align;
-               else
-                       w = ewidth[v->etype];
-               if(w < 1 || w > SZ_VLONG)
-                       fatal(Z, "align");
-               if(packflg) 
-                       packw = packflg;
-               break;
-
-       case Ael2:      /* width of a struct element */
-               o += t->width;
-               break;
-
-       case Aarg0:     /* initial passbyptr argument in arg list */
-               if(typesu[t->etype]) {
-                       o = align(o, types[TIND], Aarg1, nil);
-                       o = align(o, types[TIND], Aarg2, nil);
-               }
-               break;
-
-       case Aarg1:     /* initial align of parameter */
-               if(ewidth[TIND] == 4) {
-                       if(typesu[t->etype]) {
-                               for(v = t->link; v != T; v = v->down)
-                                       o = align(o, v, Aarg1, maxalign);
-                               goto out;
-                       }
-                       w = ewidth[t->etype];
-                       if(typev[t->etype] || t->etype == TDOUBLE)
-                               w = 8;
-                       else if(w <= 0 || w >= 4)
-                               w = 4;
-                       else
-                               w = 1;
-                       break;
-               }
-               w = ewidth[t->etype];
-               if(w <= 0 || w >= SZ_VLONG) {
-                       w = SZ_VLONG;
-                       break;
-               }
-               w = 1;          /* little endian no adjustment */
-               break;
-
-       case Aarg2:     /* width of a parameter */
-               o += t->width;
-               if(ewidth[TIND] == 4) {
-                       o = align(o, t, Aarg1, maxalign);
-                       goto out;
-               }
-               w = t->width;
-               if(w > SZ_VLONG)
-                       w = SZ_VLONG;
-               break;
-
-       case Aaut3:     /* total align of automatic */
-               o = align(o, t, Ael1, nil);
-               o = align(o, t, Ael2, nil);
-               break;
-       }
-       if(packw != 0 && xround(o, w) != xround(o, packw))
-               diag(Z, "#pragma pack changes offset of %T", t);
-       o = xround(o, w);
-       if(maxalign && *maxalign < w)
-               *maxalign = w;
-out:
-       if(debug['A'])
-               print("align %s %d %T = %d\n", bnames[op], i, t, o);
-       return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
-       v = xround(v, SZ_VLONG);
-       if(v > max)
-               return v;
-       return max;
-}
diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c
deleted file mode 100644 (file)
index 3bdbf41..0000000
+++ /dev/null
@@ -1,1674 +0,0 @@
-// Inferno utils/6c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int thechar = '6';
-char *thestring = "amd64";
-
-LinkArch       *thelinkarch = &linkamd64;
-
-void
-linkarchinit(void)
-{
-       if(strcmp(getgoarch(), "amd64p32") == 0)
-               thelinkarch = &linkamd64p32;
-}
-
-void
-ginit(void)
-{
-       int i;
-       Type *t;
-
-       dodefine("_64BITREG");
-       if(ewidth[TIND] == 8)
-               dodefine("_64BIT");
-       listinit();
-       nstring = 0;
-       mnstring = 0;
-       nrathole = 0;
-       pc = 0;
-       breakpc = -1;
-       continpc = -1;
-       cases = C;
-       lastp = P;
-       tfield = types[TINT];
-
-       typeword = typechlvp;
-       typecmplx = typesu;
-
-       /* TO DO */
-       memmove(typechlpv, typechlp, sizeof(typechlpv));
-       typechlpv[TVLONG] = 1;
-       typechlpv[TUVLONG] = 1;
-
-       zprog.link = P;
-       zprog.as = AGOK;
-       zprog.from.type = D_NONE;
-       zprog.from.index = D_NONE;
-       zprog.from.scale = 0;
-       zprog.to = zprog.from;
-
-       lregnode.op = OREGISTER;
-       lregnode.class = CEXREG;
-       lregnode.reg = REGTMP;
-       lregnode.complex = 0;
-       lregnode.addable = 11;
-       lregnode.type = types[TLONG];
-
-       qregnode = lregnode;
-       qregnode.type = types[TVLONG];
-
-       constnode.op = OCONST;
-       constnode.class = CXXX;
-       constnode.complex = 0;
-       constnode.addable = 20;
-       constnode.type = types[TLONG];
-
-       vconstnode = constnode;
-       vconstnode.type = types[TVLONG];
-
-       fconstnode.op = OCONST;
-       fconstnode.class = CXXX;
-       fconstnode.complex = 0;
-       fconstnode.addable = 20;
-       fconstnode.type = types[TDOUBLE];
-
-       nodsafe = new(ONAME, Z, Z);
-       nodsafe->sym = slookup(".safe");
-       nodsafe->type = types[TINT];
-       nodsafe->etype = types[TINT]->etype;
-       nodsafe->class = CAUTO;
-       complex(nodsafe);
-
-       t = typ(TARRAY, types[TCHAR]);
-       symrathole = slookup(".rathole");
-       symrathole->class = CGLOBL;
-       symrathole->type = t;
-
-       nodrat = new(ONAME, Z, Z);
-       nodrat->sym = symrathole;
-       nodrat->type = types[TIND];
-       nodrat->etype = TVOID;
-       nodrat->class = CGLOBL;
-       complex(nodrat);
-       nodrat->type = t;
-
-       nodret = new(ONAME, Z, Z);
-       nodret->sym = slookup(".ret");
-       nodret->type = types[TIND];
-       nodret->etype = TIND;
-       nodret->class = CPARAM;
-       nodret = new(OIND, nodret, Z);
-       complex(nodret);
-
-       if(0)
-               com64init();
-
-       for(i=0; i<nelem(reg); i++) {
-               reg[i] = 1;
-               if(i >= D_AX && i <= D_R15 && i != D_SP)
-                       reg[i] = 0;
-               if(i >= D_X0 && i <= D_X7)
-                       reg[i] = 0;
-       }
-       if(nacl) {
-               reg[D_BP] = 1;
-               reg[D_R15] = 1;
-       }
-}
-
-void
-gclean(void)
-{
-       int i;
-       Sym *s;
-
-       reg[D_SP]--;
-       if(nacl) {
-               reg[D_BP]--;
-               reg[D_R15]--;
-       }
-       for(i=D_AX; i<=D_R15; i++)
-               if(reg[i])
-                       diag(Z, "reg %R left allocated", i);
-       for(i=D_X0; i<=D_X7; i++)
-               if(reg[i])
-                       diag(Z, "reg %R left allocated", i);
-       while(mnstring)
-               outstring("", 1L);
-       symstring->type->width = nstring;
-       symrathole->type->width = nrathole;
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->link) {
-               if(s->type == T)
-                       continue;
-               if(s->type->width == 0)
-                       continue;
-               if(s->class != CGLOBL && s->class != CSTATIC)
-                       continue;
-               if(s->type == types[TENUM])
-                       continue;
-               gpseudo(AGLOBL, s, nodconst(s->type->width));
-       }
-       nextpc();
-       p->as = AEND;
-       outcode();
-}
-
-void
-nextpc(void)
-{
-       Plist *pl;
-
-       p = alloc(sizeof(*p));
-       *p = zprog;
-       p->lineno = nearln;
-       p->pc = pc;
-       pc++;
-       if(lastp == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastp->link = p;
-       lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
-       int32 regs;
-       Node fnxargs[20], *fnxp;
-
-       regs = cursafe;
-
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 0, &fnxp);   /* compile fns to temps */
-
-       curarg = 0;
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 1, &fnxp);   /* compile normal args and temps */
-
-       cursafe = regs;
-}
-
-int
-nareg(void)
-{
-       int i, n;
-
-       n = 0;
-       for(i=D_AX; i<=D_R15; i++)
-               if(reg[i] == 0)
-                       n++;
-       return n;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
-       Node nod;
-
-       if(n == Z)
-               return;
-       if(n->op == OLIST) {
-               garg1(n->left, tn1, tn2, f, fnxp);
-               garg1(n->right, tn1, tn2, f, fnxp);
-               return;
-       }
-       if(f == 0) {
-               if(n->complex >= FNX) {
-                       regsalloc(*fnxp, n);
-                       nod = znode;
-                       nod.op = OAS;
-                       nod.left = *fnxp;
-                       nod.right = n;
-                       nod.type = n->type;
-                       cgen(&nod, Z);
-                       (*fnxp)++;
-               }
-               return;
-       }
-       if(typesu[n->type->etype]) {
-               regaalloc(tn2, n);
-               if(n->complex >= FNX) {
-                       sugen(*fnxp, tn2, n->type->width);
-                       (*fnxp)++;
-               } else
-                       sugen(n, tn2, n->type->width);
-               return;
-       }
-       if(REGARG >= 0 && curarg == 0 && typechlpv[n->type->etype]) {
-               regaalloc1(tn1, n);
-               if(n->complex >= FNX) {
-                       cgen(*fnxp, tn1);
-                       (*fnxp)++;
-               } else
-                       cgen(n, tn1);
-               return;
-       }
-       if(vconst(n) == 0) {
-               regaalloc(tn2, n);
-               gmove(n, tn2);
-               return;
-       }
-       regalloc(tn1, n, Z);
-       if(n->complex >= FNX) {
-               cgen(*fnxp, tn1);
-               (*fnxp)++;
-       } else
-               cgen(n, tn1);
-       regaalloc(tn2, n);
-       gmove(tn1, tn2);
-       regfree(tn1);
-}
-
-Node*
-nodgconst(vlong v, Type *t)
-{
-       if(!typev[t->etype])
-               return nodconst((int32)v);
-       vconstnode.vconst = v;
-       return &vconstnode;
-}
-
-Node*
-nodconst(int32 v)
-{
-       constnode.vconst = v;
-       return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
-       fconstnode.fconst = d;
-       return &fconstnode;
-}
-
-int
-isreg(Node *n, int r)
-{
-
-       if(n->op == OREGISTER)
-               if(n->reg == r)
-                       return 1;
-       return 0;
-}
-
-int
-nodreg(Node *n, Node *nn, int r)
-{
-       int et;
-
-       *n = qregnode;
-       n->reg = r;
-       if(nn != Z){
-               et = nn->type->etype;
-               if(!typefd[et] && nn->type->width <= SZ_LONG && 0)
-                       n->type = typeu[et]? types[TUINT]: types[TINT];
-               else
-                       n->type = nn->type;
-//print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]);
-               n->lineno = nn->lineno;
-       }
-       if(reg[r] == 0)
-               return 0;
-       if(nn != Z) {
-               if(nn->op == OREGISTER)
-               if(nn->reg == r)
-                       return 0;
-       }
-       return 1;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
-       int r;
-       
-       if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
-               r = REGRET;
-               if(typefd[nn->type->etype])
-                       r = FREGRET;
-               nodreg(n, nn, r);
-               reg[r]++;
-               return;
-       }
-       
-       if(mode == 1) {
-               // fetch returned value after call.
-               // already called gargs, so curarg is set.
-               curarg = (curarg+7) & ~7;
-               regaalloc(n, nn);
-               return;
-       }
-
-       if(mode == 2) {
-               // store value to be returned.
-               // must compute arg offset.
-               if(t->etype != TFUNC)
-                       fatal(Z, "bad regret func %T", t);
-               *n = *nn;
-               n->op = ONAME;
-               n->class = CPARAM;
-               n->sym = slookup(".ret");
-               n->complex = nodret->complex;
-               n->addable = 20;
-               n->xoffset = argsize(0);
-               return;
-       }
-       
-       fatal(Z, "bad regret"); 
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
-       int i;
-
-       switch(tn->type->etype) {
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TIND:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i >= D_AX && i <= D_R15)
-                               goto out;
-               }
-               for(i=D_AX; i<=D_R15; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               diag(tn, "out of fixed registers");
-               goto err;
-
-       case TFLOAT:
-       case TDOUBLE:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i >= D_X0 && i <= D_X7)
-                               goto out;
-               }
-               for(i=D_X0; i<=D_X7; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               diag(tn, "out of float registers");
-               goto out;
-       }
-       diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
-       i = 0;
-out:
-       if(i)
-               reg[i]++;
-       nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
-       Node nod;
-
-       nod = *tn;
-       nod.type = types[TIND];
-       regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-
-       i = 0;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               goto err;
-       i = n->reg;
-       if(i < 0 || i >= nelem(reg))
-               goto err;
-       if(reg[i] <= 0)
-               goto err;
-       reg[i]--;
-       return;
-err:
-       diag(n, "error in regfree: %R", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
-       cursafe = align(cursafe, nn->type, Aaut3, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-       *n = *nodsafe;
-       n->xoffset = -(stkoff + cursafe);
-       n->type = nn->type;
-       n->etype = nn->type->etype;
-       n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
-       if(REGARG < 0) {
-               fatal(n, "regaalloc1 and REGARG<0");
-               return;
-       }
-       nodreg(n, nn, REGARG);
-       reg[(uchar)REGARG]++;
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       *n = *nn;
-       n->op = OINDREG;
-       n->reg = REGSP;
-       n->xoffset = curarg;
-       n->complex = 0;
-       n->addable = 20;
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
-       if(n->op != OREGISTER) {
-               diag(n, "regind not OREGISTER");
-               return;
-       }
-       n->op = OINDREG;
-       n->type = nn->type;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
-       int32 v;
-
-       a->type = D_NONE;
-       if(n == Z)
-               return;
-       switch(n->op) {
-       default:
-       bad:
-               diag(n, "bad in naddr: %O %D", n->op, a);
-               break;
-
-       case OREGISTER:
-               a->type = n->reg;
-               a->sym = nil;
-               break;
-
-       case OEXREG:
-               a->type = D_INDIR + D_TLS;
-               a->offset = n->reg - 1;
-               break;
-
-       case OIND:
-               naddr(n->left, a);
-               if(a->type >= D_AX && a->type <= D_R15)
-                       a->type += D_INDIR;
-               else
-               if(a->type == D_CONST)
-                       a->type = D_NONE+D_INDIR;
-               else
-               if(a->type == D_ADDR) {
-                       a->type = a->index;
-                       a->index = D_NONE;
-               } else
-                       goto bad;
-               break;
-
-       case OINDEX:
-               a->type = idx.ptr;
-               if(n->left->op == OADDR || n->left->op == OCONST)
-                       naddr(n->left, a);
-               if(a->type >= D_AX && a->type <= D_R15)
-                       a->type += D_INDIR;
-               else
-               if(a->type == D_CONST)
-                       a->type = D_NONE+D_INDIR;
-               else
-               if(a->type == D_ADDR) {
-                       a->type = a->index;
-                       a->index = D_NONE;
-               } else
-                       goto bad;
-               a->index = idx.reg;
-               a->scale = n->scale;
-               a->offset += n->xoffset;
-               break;
-
-       case OINDREG:
-               a->type = n->reg+D_INDIR;
-               a->sym = nil;
-               a->offset = n->xoffset;
-               break;
-
-       case ONAME:
-               a->etype = n->etype;
-               a->type = D_STATIC;
-               a->sym = linksym(n->sym);
-               a->offset = n->xoffset;
-               if(n->class == CSTATIC)
-                       break;
-               if(n->class == CEXTERN || n->class == CGLOBL) {
-                       a->type = D_EXTERN;
-                       break;
-               }
-               if(n->class == CAUTO) {
-                       a->type = D_AUTO;
-                       break;
-               }
-               if(n->class == CPARAM) {
-                       a->type = D_PARAM;
-                       break;
-               }
-               goto bad;
-
-       case OCONST:
-               if(typefd[n->type->etype]) {
-                       a->type = D_FCONST;
-                       a->u.dval = n->fconst;
-                       break;
-               }
-               a->sym = nil;
-               a->type = D_CONST;
-               if(typev[n->type->etype] || (n->type->etype == TIND && ewidth[TIND] == 8))
-                       a->offset = n->vconst;
-               else
-                       a->offset = convvtox(n->vconst, typeu[n->type->etype]? TULONG: TLONG);
-               break;
-
-       case OADDR:
-               naddr(n->left, a);
-               if(a->type >= D_INDIR) {
-                       a->type -= D_INDIR;
-                       break;
-               }
-               if(a->type == D_EXTERN || a->type == D_STATIC ||
-                  a->type == D_AUTO || a->type == D_PARAM)
-                       if(a->index == D_NONE) {
-                               a->index = a->type;
-                               a->type = D_ADDR;
-                               break;
-                       }
-               goto bad;
-
-       case OADD:
-               if(n->right->op == OCONST) {
-                       v = n->right->vconst;
-                       naddr(n->left, a);
-               } else
-               if(n->left->op == OCONST) {
-                       v = n->left->vconst;
-                       naddr(n->right, a);
-               } else
-                       goto bad;
-               a->offset += v;
-               break;
-
-       }
-}
-
-void
-gcmp(int op, Node *n, vlong val)
-{
-       Node *cn, nod;
-
-       cn = nodgconst(val, n->type);
-       if(!immconst(cn)){
-               regalloc(&nod, n, Z);
-               gmove(cn, &nod);
-               gopcode(op, n->type, n, &nod);
-               regfree(&nod);
-       }else
-               gopcode(op, n->type, n, cn);
-}
-
-#define        CASE(a,b)       ((a<<8)|(b<<0))
-
-void
-gmove(Node *f, Node *t)
-{
-       int ft, tt, t64, a;
-       Node nod, nod1, nod2, nod3;
-       Prog *p1, *p2;
-
-       ft = f->type->etype;
-       tt = t->type->etype;
-       if(ewidth[TIND] == 4) {
-               if(ft == TIND)
-                       ft = TUINT;
-               if(tt == TIND)
-                       tt = TUINT;
-       }
-       t64 = tt == TVLONG || tt == TUVLONG || tt == TIND;
-       if(debug['M'])
-               print("gop: %O %O[%s],%O[%s]\n", OAS,
-                       f->op, tnames[ft], t->op, tnames[tt]);
-       if(typefd[ft] && f->op == OCONST) {
-               /* TO DO: pick up special constants, possibly preloaded */
-               if(f->fconst == 0.0){
-                       regalloc(&nod, t, t);
-                       gins(AXORPD, &nod, &nod);
-                       gmove(&nod, t);
-                       regfree(&nod);
-                       return;
-               }
-       }
-/*
- * load
- */
-       if(ft == TVLONG || ft == TUVLONG)
-       if(f->op == OCONST)
-       if(f->vconst > 0x7fffffffLL || f->vconst < -0x7fffffffLL)
-       if(t->op != OREGISTER) {
-               regalloc(&nod, f, Z);
-               gmove(f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-       }
-
-       if(f->op == ONAME || f->op == OINDREG ||
-          f->op == OIND || f->op == OINDEX)
-       switch(ft) {
-       case TCHAR:
-               a = AMOVBLSX;
-               if(t64)
-                       a = AMOVBQSX;
-               goto ld;
-       case TUCHAR:
-               a = AMOVBLZX;
-               if(t64)
-                       a = AMOVBQZX;
-               goto ld;
-       case TSHORT:
-               a = AMOVWLSX;
-               if(t64)
-                       a = AMOVWQSX;
-               goto ld;
-       case TUSHORT:
-               a = AMOVWLZX;
-               if(t64)
-                       a = AMOVWQZX;
-               goto ld;
-       case TINT:
-       case TLONG:
-               if(typefd[tt]) {
-                       regalloc(&nod, t, t);
-                       if(tt == TDOUBLE)
-                               a = ACVTSL2SD;
-                       else
-                               a = ACVTSL2SS;
-                       gins(a, f, &nod);
-                       gmove(&nod, t);
-                       regfree(&nod);
-                       return;
-               }
-               a = AMOVL;
-               if(t64)
-                       a = AMOVLQSX;
-               goto ld;
-       case TUINT:
-       case TULONG:
-               a = AMOVL;
-               if(t64)
-                       a = AMOVLQZX;   /* could probably use plain MOVL */
-               goto ld;
-       case TVLONG:
-               if(typefd[tt]) {
-                       regalloc(&nod, t, t);
-                       if(tt == TDOUBLE)
-                               a = ACVTSQ2SD;
-                       else
-                               a = ACVTSQ2SS;
-                       gins(a, f, &nod);
-                       gmove(&nod, t);
-                       regfree(&nod);
-                       return;
-               }
-       case TUVLONG:
-               a = AMOVQ;
-               goto ld;
-       case TIND:
-               a = AMOVQ;
-               if(ewidth[TIND] == 4)
-                       a = AMOVL;
-
-       ld:
-               regalloc(&nod, f, t);
-               nod.type = t64? types[TVLONG]: types[TINT];
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-
-       case TFLOAT:
-               a = AMOVSS;
-               goto fld;
-       case TDOUBLE:
-               a = AMOVSD;
-       fld:
-               regalloc(&nod, f, t);
-               if(tt != TDOUBLE && tt != TFLOAT){      /* TO DO: why is this here */
-                       prtree(f, "odd tree");
-                       nod.type = t64? types[TVLONG]: types[TINT];
-               }
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-       }
-
-/*
- * store
- */
-       if(t->op == ONAME || t->op == OINDREG ||
-          t->op == OIND || t->op == OINDEX)
-       switch(tt) {
-       case TCHAR:
-       case TUCHAR:
-               a = AMOVB;      goto st;
-       case TSHORT:
-       case TUSHORT:
-               a = AMOVW;      goto st;
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-               a = AMOVL;      goto st;
-       case TVLONG:
-       case TUVLONG:
-       case TIND:
-               a = AMOVQ;      goto st;
-
-       st:
-               if(f->op == OCONST) {
-                       gins(a, f, t);
-                       return;
-               }
-       fst:
-               regalloc(&nod, t, f);
-               gmove(f, &nod);
-               gins(a, &nod, t);
-               regfree(&nod);
-               return;
-
-       case TFLOAT:
-               a = AMOVSS;
-               goto fst;
-       case TDOUBLE:
-               a = AMOVSD;
-               goto fst;
-       }
-
-/*
- * convert
- */
-       switch(CASE(ft,tt)) {
-       default:
-/*
- * integer to integer
- ********
-               a = AGOK;       break;
-
-       case CASE(      TCHAR,  TCHAR):
-       case CASE(      TUCHAR, TCHAR):
-       case CASE(      TSHORT, TCHAR):
-       case CASE(      TUSHORT,TCHAR):
-       case CASE(      TINT,   TCHAR):
-       case CASE(      TUINT,  TCHAR):
-       case CASE(      TLONG,  TCHAR):
-       case CASE(      TULONG, TCHAR):
-
-       case CASE(      TCHAR,  TUCHAR):
-       case CASE(      TUCHAR, TUCHAR):
-       case CASE(      TSHORT, TUCHAR):
-       case CASE(      TUSHORT,TUCHAR):
-       case CASE(      TINT,   TUCHAR):
-       case CASE(      TUINT,  TUCHAR):
-       case CASE(      TLONG,  TUCHAR):
-       case CASE(      TULONG, TUCHAR):
-
-       case CASE(      TSHORT, TSHORT):
-       case CASE(      TUSHORT,TSHORT):
-       case CASE(      TINT,   TSHORT):
-       case CASE(      TUINT,  TSHORT):
-       case CASE(      TLONG,  TSHORT):
-       case CASE(      TULONG, TSHORT):
-
-       case CASE(      TSHORT, TUSHORT):
-       case CASE(      TUSHORT,TUSHORT):
-       case CASE(      TINT,   TUSHORT):
-       case CASE(      TUINT,  TUSHORT):
-       case CASE(      TLONG,  TUSHORT):
-       case CASE(      TULONG, TUSHORT):
-
-       case CASE(      TINT,   TINT):
-       case CASE(      TUINT,  TINT):
-       case CASE(      TLONG,  TINT):
-       case CASE(      TULONG, TINT):
-
-       case CASE(      TINT,   TUINT):
-       case CASE(      TUINT,  TUINT):
-       case CASE(      TLONG,  TUINT):
-       case CASE(      TULONG, TUINT):
- *****/
-               a = AMOVL;
-               break;
-
-       case CASE(      TINT,   TIND):
-       case CASE(      TINT,   TVLONG):
-       case CASE(      TINT,   TUVLONG):
-       case CASE(      TLONG,  TIND):
-       case CASE(      TLONG,  TVLONG):
-       case CASE(      TLONG,  TUVLONG):
-               a = AMOVLQSX;
-               if(f->op == OCONST) {
-                       f->vconst &= (uvlong)0xffffffffU;
-                       if(f->vconst & 0x80000000)
-                               f->vconst |= (vlong)0xffffffff << 32;
-                       a = AMOVQ;
-               }
-               break;
-
-       case CASE(      TUINT,  TIND):
-       case CASE(      TUINT,  TVLONG):
-       case CASE(      TUINT,  TUVLONG):
-       case CASE(      TULONG, TVLONG):
-       case CASE(      TULONG, TUVLONG):
-       case CASE(      TULONG, TIND):
-               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(      TIND,   TUVLONG):
-       case CASE(      TVLONG, TIND):
-       case CASE(      TVLONG, TVLONG):
-       case CASE(      TVLONG, TUVLONG):
-       case CASE(      TUVLONG,        TIND):
-       case CASE(      TUVLONG,        TVLONG):
-       case CASE(      TUVLONG,        TUVLONG):
-               a = AMOVQ;
-               break;
-
-       case CASE(      TSHORT, TINT):
-       case CASE(      TSHORT, TUINT):
-       case CASE(      TSHORT, TLONG):
-       case CASE(      TSHORT, TULONG):
-               a = AMOVWLSX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xffff;
-                       if(f->vconst & 0x8000)
-                               f->vconst |= 0xffff0000;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TSHORT, TVLONG):
-       case CASE(      TSHORT, TUVLONG):
-       case CASE(      TSHORT, TIND):
-               a = AMOVWQSX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xffff;
-                       if(f->vconst & 0x8000){
-                               f->vconst |= 0xffff0000;
-                               f->vconst |= (vlong)~0 << 32;
-                       }
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TUSHORT,TINT):
-       case CASE(      TUSHORT,TUINT):
-       case CASE(      TUSHORT,TLONG):
-       case CASE(      TUSHORT,TULONG):
-               a = AMOVWLZX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xffff;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TUSHORT,TVLONG):
-       case CASE(      TUSHORT,TUVLONG):
-       case CASE(      TUSHORT,TIND):
-               a = AMOVWQZX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xffff;
-                       a = AMOVL;      /* MOVL also zero-extends to 64 bits */
-               }
-               break;
-
-       case CASE(      TCHAR,  TSHORT):
-       case CASE(      TCHAR,  TUSHORT):
-       case CASE(      TCHAR,  TINT):
-       case CASE(      TCHAR,  TUINT):
-       case CASE(      TCHAR,  TLONG):
-       case CASE(      TCHAR,  TULONG):
-               a = AMOVBLSX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xff;
-                       if(f->vconst & 0x80)
-                               f->vconst |= 0xffffff00;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TCHAR,  TVLONG):
-       case CASE(      TCHAR,  TUVLONG):
-       case CASE(      TCHAR,  TIND):
-               a = AMOVBQSX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xff;
-                       if(f->vconst & 0x80){
-                               f->vconst |= 0xffffff00;
-                               f->vconst |= (vlong)~0 << 32;
-                       }
-                       a = AMOVQ;
-               }
-               break;
-
-       case CASE(      TUCHAR, TSHORT):
-       case CASE(      TUCHAR, TUSHORT):
-       case CASE(      TUCHAR, TINT):
-       case CASE(      TUCHAR, TUINT):
-       case CASE(      TUCHAR, TLONG):
-       case CASE(      TUCHAR, TULONG):
-               a = AMOVBLZX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xff;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TUCHAR, TVLONG):
-       case CASE(      TUCHAR, TUVLONG):
-       case CASE(      TUCHAR, TIND):
-               a = AMOVBQZX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xff;
-                       a = AMOVL;      /* zero-extends to 64-bits */
-               }
-               break;
-
-/*
- * float to fix
- */
-       case CASE(      TFLOAT, TCHAR):
-       case CASE(      TFLOAT, TUCHAR):
-       case CASE(      TFLOAT, TSHORT):
-       case CASE(      TFLOAT, TUSHORT):
-       case CASE(      TFLOAT, TINT):
-       case CASE(      TFLOAT, TUINT):
-       case CASE(      TFLOAT, TLONG):
-       case CASE(      TFLOAT, TULONG):
-       case CASE(      TFLOAT, TVLONG):
-       case CASE(      TFLOAT, TUVLONG):
-       case CASE(      TFLOAT, TIND):
-
-       case CASE(      TDOUBLE,TCHAR):
-       case CASE(      TDOUBLE,TUCHAR):
-       case CASE(      TDOUBLE,TSHORT):
-       case CASE(      TDOUBLE,TUSHORT):
-       case CASE(      TDOUBLE,TINT):
-       case CASE(      TDOUBLE,TUINT):
-       case CASE(      TDOUBLE,TLONG):
-       case CASE(      TDOUBLE,TULONG):
-       case CASE(      TDOUBLE,TVLONG):
-       case CASE(      TDOUBLE,TUVLONG):
-       case CASE(      TDOUBLE,TIND):
-               regalloc(&nod, t, Z);
-               if(ewidth[tt] == SZ_VLONG || typeu[tt] && ewidth[tt] == SZ_INT){
-                       if(ft == TFLOAT)
-                               a = ACVTTSS2SQ;
-                       else
-                               a = ACVTTSD2SQ;
-               }else{
-                       if(ft == TFLOAT)
-                               a = ACVTTSS2SL;
-                       else
-                               a = ACVTTSD2SL;
-               }
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-
-/*
- * uvlong to float
- */
-       case CASE(      TUVLONG,        TDOUBLE):
-       case CASE(      TUVLONG,        TFLOAT):
-               a = ACVTSQ2SS;
-               if(tt == TDOUBLE)
-                       a = ACVTSQ2SD;
-               regalloc(&nod, f, f);
-               gmove(f, &nod);
-               regalloc(&nod1, t, t);
-               gins(ACMPQ, &nod, nodconst(0));
-               gins(AJLT, Z, Z);
-               p1 = p;
-               gins(a, &nod, &nod1);
-               gins(AJMP, Z, Z);
-               p2 = p;
-               patch(p1, pc);
-               regalloc(&nod2, f, Z);
-               regalloc(&nod3, f, Z);
-               gmove(&nod, &nod2);
-               gins(ASHRQ, nodconst(1), &nod2);
-               gmove(&nod, &nod3);
-               gins(AANDL, nodconst(1), &nod3);
-               gins(AORQ, &nod3, &nod2);
-               gins(a, &nod2, &nod1);
-               gins(tt == TDOUBLE? AADDSD: AADDSS, &nod1, &nod1);
-               regfree(&nod2);
-               regfree(&nod3);
-               patch(p2, pc);
-               regfree(&nod);
-               regfree(&nod1);
-               return;
-
-       case CASE(      TULONG, TDOUBLE):
-       case CASE(      TUINT,  TDOUBLE):
-       case CASE(      TULONG, TFLOAT):
-       case CASE(      TUINT,  TFLOAT):
-               a = ACVTSQ2SS;
-               if(tt == TDOUBLE)
-                       a = ACVTSQ2SD;
-               regalloc(&nod, f, f);
-               gins(AMOVLQZX, f, &nod);
-               regalloc(&nod1, t, t);
-               gins(a, &nod, &nod1);
-               gmove(&nod1, t);
-               regfree(&nod);
-               regfree(&nod1);
-               return;
-
-/*
- * fix to float
- */
-       case CASE(      TCHAR,  TFLOAT):
-       case CASE(      TUCHAR, TFLOAT):
-       case CASE(      TSHORT, TFLOAT):
-       case CASE(      TUSHORT,TFLOAT):
-       case CASE(      TINT,   TFLOAT):
-       case CASE(      TLONG,  TFLOAT):
-       case    CASE(   TVLONG, TFLOAT):
-       case CASE(      TIND,   TFLOAT):
-
-       case CASE(      TCHAR,  TDOUBLE):
-       case CASE(      TUCHAR, TDOUBLE):
-       case CASE(      TSHORT, TDOUBLE):
-       case CASE(      TUSHORT,TDOUBLE):
-       case CASE(      TINT,   TDOUBLE):
-       case CASE(      TLONG,  TDOUBLE):
-       case CASE(      TVLONG, TDOUBLE):
-       case CASE(      TIND,   TDOUBLE):
-               regalloc(&nod, t, t);
-               if(ewidth[ft] == SZ_VLONG){
-                       if(tt == TFLOAT)
-                               a = ACVTSQ2SS;
-                       else
-                               a = ACVTSQ2SD;
-               }else{
-                       if(tt == TFLOAT)
-                               a = ACVTSL2SS;
-                       else
-                               a = ACVTSL2SD;
-               }
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-
-/*
- * float to float
- */
-       case CASE(      TFLOAT, TFLOAT):
-               a = AMOVSS;
-               break;
-       case CASE(      TDOUBLE,TFLOAT):
-               a = ACVTSD2SS;
-               break;
-       case CASE(      TFLOAT, TDOUBLE):
-               a = ACVTSS2SD;
-               break;
-       case CASE(      TDOUBLE,TDOUBLE):
-               a = AMOVSD;
-               break;
-       }
-       if(a == AMOVQ || a == AMOVSD || a == AMOVSS || a == AMOVL && ewidth[ft] == ewidth[tt])  /* TO DO: check AMOVL */
-       if(samaddr(f, t))
-               return;
-       gins(a, f, t);
-}
-
-void
-doindex(Node *n)
-{
-       Node nod, nod1;
-       int32 v;
-
-if(debug['Y'])
-prtree(n, "index");
-
-if(n->left->complex >= FNX)
-print("botch in doindex\n");
-
-       regalloc(&nod, &qregnode, Z);
-       v = constnode.vconst;
-       cgen(n->right, &nod);
-       idx.ptr = D_NONE;
-       if(n->left->op == OCONST)
-               idx.ptr = D_CONST;
-       else if(n->left->op == OREGISTER)
-               idx.ptr = n->left->reg;
-       else if(n->left->op != OADDR) {
-               reg[D_BP]++;    // can't be used as a base
-               regalloc(&nod1, &qregnode, Z);
-               cgen(n->left, &nod1);
-               idx.ptr = nod1.reg;
-               regfree(&nod1);
-               reg[D_BP]--;
-       }
-       idx.reg = nod.reg;
-       regfree(&nod);
-       constnode.vconst = v;
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
-       if(f != Z && f->op == OINDEX)
-               doindex(f);
-       if(t != Z && t->op == OINDEX)
-               doindex(t);
-       nextpc();
-       p->as = a;
-       if(f != Z)
-               naddr(f, &p->from);
-       if(t != Z)
-               naddr(t, &p->to);
-       if(debug['g'])
-               print("%P\n", p);
-}
-
-void
-gopcode(int o, Type *ty, Node *f, Node *t)
-{
-       int a, et;
-
-       et = TLONG;
-       if(ty != T)
-               et = ty->etype;
-       if(et == TIND && ewidth[TIND] == 4)
-               et = TUINT;
-       if(debug['M']) {
-               if(f != Z && f->type != T)
-                       print("gop: %O %O[%s],", o, f->op, tnames[et]);
-               else
-                       print("gop: %O Z,", o);
-               if(t != Z && t->type != T)
-                       print("%O[%s]\n", t->op, tnames[t->type->etype]);
-               else
-                       print("Z\n");
-       }
-       a = AGOK;
-       switch(o) {
-       case OCOM:
-               a = ANOTL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ANOTB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ANOTW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ANOTQ;
-               break;
-
-       case ONEG:
-               a = ANEGL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ANEGB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ANEGW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ANEGQ;
-               break;
-
-       case OADDR:
-               a = ALEAQ;
-               break;
-
-       case OASADD:
-       case OADD:
-               a = AADDL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AADDB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AADDW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AADDQ;
-               if(et == TFLOAT)
-                       a = AADDSS;
-               if(et == TDOUBLE)
-                       a = AADDSD;
-               break;
-
-       case OASSUB:
-       case OSUB:
-               a = ASUBL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASUBB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASUBW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ASUBQ;
-               if(et == TFLOAT)
-                       a = ASUBSS;
-               if(et == TDOUBLE)
-                       a = ASUBSD;
-               break;
-
-       case OASOR:
-       case OOR:
-               a = AORL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AORB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AORW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AORQ;
-               break;
-
-       case OASAND:
-       case OAND:
-               a = AANDL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AANDB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AANDW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AANDQ;
-               break;
-
-       case OASXOR:
-       case OXOR:
-               a = AXORL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AXORB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AXORW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AXORQ;
-               break;
-
-       case OASLSHR:
-       case OLSHR:
-               a = ASHRL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASHRB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASHRW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ASHRQ;
-               break;
-
-       case OASASHR:
-       case OASHR:
-               a = ASARL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASARB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASARW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ASARQ;
-               break;
-
-       case OASASHL:
-       case OASHL:
-               a = ASALL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASALB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASALW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       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;
-
-       case OASMUL:
-       case OMUL:
-               if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
-                       t = Z;
-               a = AIMULL;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AIMULQ;
-               if(et == TFLOAT)
-                       a = AMULSS;
-               if(et == TDOUBLE)
-                       a = AMULSD;
-               break;
-
-       case OASMOD:
-       case OMOD:
-       case OASDIV:
-       case ODIV:
-               a = AIDIVL;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AIDIVQ;
-               if(et == TFLOAT)
-                       a = ADIVSS;
-               if(et == TDOUBLE)
-                       a = ADIVSD;
-               break;
-
-       case OASLMUL:
-       case OLMUL:
-               a = AMULL;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = AMULQ;
-               break;
-
-       case OASLMOD:
-       case OLMOD:
-       case OASLDIV:
-       case OLDIV:
-               a = ADIVL;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ADIVQ;
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHS:
-       case OHI:
-               a = ACMPL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ACMPB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ACMPW;
-               if(et == TVLONG || et == TUVLONG || et == TIND)
-                       a = ACMPQ;
-               if(et == TFLOAT)
-                       a = AUCOMISS;
-               if(et == TDOUBLE)
-                       a = AUCOMISD;
-               gins(a, f, t);
-               switch(o) {
-               case OEQ:       a = AJEQ; break;
-               case ONE:       a = AJNE; break;
-               case OLT:       a = AJLT; break;
-               case OLE:       a = AJLE; break;
-               case OGE:       a = AJGE; break;
-               case OGT:       a = AJGT; break;
-               case OLO:       a = AJCS; break;
-               case OLS:       a = AJLS; break;
-               case OHS:       a = AJCC; break;
-               case OHI:       a = AJHI; break;
-               }
-               gins(a, Z, Z);
-               return;
-       }
-       if(a == AGOK)
-               diag(Z, "bad in gopcode %O", o);
-       gins(a, f, t);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-       return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
-}
-
-void
-gbranch(int o)
-{
-       int a;
-
-       a = AGOK;
-       switch(o) {
-       case ORETURN:
-               a = ARET;
-               break;
-       case OGOTO:
-               a = AJMP;
-               break;
-       }
-       nextpc();
-       if(a == AGOK) {
-               diag(Z, "bad in gbranch %O",  o);
-               nextpc();
-       }
-       p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
-       op->to.offset = pc;
-       op->to.type = D_BRANCH;
-       op->to.u.branch = nil;
-       op->pcond = nil;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
-       nextpc();
-       p->as = a;
-       p->from.type = D_EXTERN;
-       p->from.sym = linksym(s);
-
-       switch(a) {
-       case ATEXT:
-               p->from.scale = textflag;
-               textflag = 0;
-               break;
-       case AGLOBL:
-               p->from.scale = s->dataflag;
-               break;
-       }
-
-       if(s->class == CSTATIC)
-               p->from.type = D_STATIC;
-       naddr(n, &p->to);
-       if(a == ADATA || a == AGLOBL)
-               pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
-       Node n1;
-       
-       n1 = *nodconst(index);
-       gins(APCDATA, &n1, nodconst(value));
-}
-
-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)
-{
-       int32 v;
-
-       if(n->op == OCONST && !typefd[n->type->etype]) {
-               v = n->vconst;
-               if(v >= -32766L && v < 32766L)
-                       return 1;
-       }
-       return 0;
-}
-
-int32
-exreg(Type *t)
-{
-       int32 o;
-
-       if(typechlpv[t->etype]) {
-               if(exregoffset >= 64)
-                       return 0;
-               o = exregoffset;
-               exregoffset += ewidth[TIND];
-               return o+1;     // +1 to avoid 0 == failure; naddr's case OEXREG will subtract 1.
-       }
-       return 0;
-}
-
-schar  ewidth[NTYPE] =
-{
-       -1,             /*[TXXX]*/
-       SZ_CHAR,        /*[TCHAR]*/
-       SZ_CHAR,        /*[TUCHAR]*/
-       SZ_SHORT,       /*[TSHORT]*/
-       SZ_SHORT,       /*[TUSHORT]*/
-       SZ_INT,         /*[TINT]*/
-       SZ_INT,         /*[TUINT]*/
-       SZ_LONG,        /*[TLONG]*/
-       SZ_LONG,        /*[TULONG]*/
-       SZ_VLONG,       /*[TVLONG]*/
-       SZ_VLONG,       /*[TUVLONG]*/
-       SZ_FLOAT,       /*[TFLOAT]*/
-       SZ_DOUBLE,      /*[TDOUBLE]*/
-       SZ_IND,         /*[TIND]*/
-       0,              /*[TFUNC]*/
-       -1,             /*[TARRAY]*/
-       0,              /*[TVOID]*/
-       -1,             /*[TSTRUCT]*/
-       -1,             /*[TUNION]*/
-       SZ_INT,         /*[TENUM]*/
-};
-int32  ncast[NTYPE] =
-{
-       0,                              /*[TXXX]*/
-       BCHAR|BUCHAR,                   /*[TCHAR]*/
-       BCHAR|BUCHAR,                   /*[TUCHAR]*/
-       BSHORT|BUSHORT,                 /*[TSHORT]*/
-       BSHORT|BUSHORT,                 /*[TUSHORT]*/
-       BINT|BUINT|BLONG|BULONG,        /*[TINT]*/
-       BINT|BUINT|BLONG|BULONG,        /*[TUINT]*/
-       BINT|BUINT|BLONG|BULONG,        /*[TLONG]*/
-       BINT|BUINT|BLONG|BULONG,        /*[TULONG]*/
-       BVLONG|BUVLONG|BIND,                    /*[TVLONG]*/
-       BVLONG|BUVLONG|BIND,                    /*[TUVLONG]*/
-       BFLOAT,                         /*[TFLOAT]*/
-       BDOUBLE,                        /*[TDOUBLE]*/
-       BVLONG|BUVLONG|BIND,            /*[TIND]*/
-       0,                              /*[TFUNC]*/
-       0,                              /*[TARRAY]*/
-       0,                              /*[TVOID]*/
-       BSTRUCT,                        /*[TSTRUCT]*/
-       BUNION,                         /*[TUNION]*/
-       0,                              /*[TENUM]*/
-};
index 04e837b1384ac59105d6aece7123a0ca89f22529..dbb4ff62c488aad7b3d46ceecc91f77f04861ade 100644 (file)
@@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
        a->sym = linksym(sym);
        a->node = sym->def;
        a->offset = 0;  // header
-       a->etype = TINT32;
+       a->etype = TSTRING;
 }
 
 void
index dbd039d89f13cdad85759da2166649b0f9cd8f58..493171ef82db80ff7b6ba1bb8a9662ee06dce717 100644 (file)
@@ -63,8 +63,8 @@ enum
 
 uint32 BLOAD(Reg*);
 uint32 BSTORE(Reg*);
-uint32 LOAD(Reg*);
-uint32 STORE(Reg*);
+uint64 LOAD(Reg*);
+uint64 STORE(Reg*);
 */
 
 // A Reg is a wrapper around a single Prog (one instruction) that holds
@@ -75,12 +75,18 @@ struct      Reg
 {
        Flow    f;
 
-       Bits    set;            // variables written by this instruction.
-       Bits    use1;           // variables read by prog->from.
-       Bits    use2;           // variables read by prog->to.
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
 
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
        Bits    refbehind;
        Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
        Bits    calbehind;
        Bits    calahead;
        Bits    regdiff;
@@ -93,6 +99,16 @@ struct       Reg
 
 #define        NRGN    600
 /*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
 struct Rgn
 {
        Reg*    enter;
@@ -140,8 +156,8 @@ void        prop(Reg*, Bits, Bits);
 void   synch(Reg*, Bits);
 uint32 allreg(uint32, Rgn*);
 void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
+uint32 paint2(Reg*, int, int);
+void   paint3(Reg*, int, uint32, int);
 void   addreg(Adr*, int);
 void   dumpone(Flow*, int);
 void   dumpit(char*, Flow*, int);
@@ -153,10 +169,10 @@ void      peep(Prog*);
 void   excise(Flow*);
 int    copyu(Prog*, Adr*, Adr*);
 
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
+uint32 RtoB(int);
+uint32 FtoB(int);
+int    BtoR(uint32);
+int    BtoF(uint32);
 
 /*
  * prog.c
@@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
 struct ProgInfo
 {
        uint32 flags; // the bits below
-       uint32 reguse; // required registers used by this instruction
-       uint32 regset; // required registers set by this instruction
+       uint32 reguse; // registers implicitly used by this instruction
+       uint32 regset; // registers implicitly set by this instruction
        uint32 regindex; // registers used by addressing mode
 };
 
@@ -187,12 +203,12 @@ enum
        SizeF = 1<<7, // float aka float32
        SizeD = 1<<8, // double aka float64
 
-       // Left side: address taken, read, write.
+       // Left side (Prog.from): address taken, read, write.
        LeftAddr = 1<<9,
        LeftRead = 1<<10,
        LeftWrite = 1<<11,
        
-       // Right side: address taken, read, write.
+       // Right side (Prog.to): address taken, read, write.
        RightAddr = 1<<12,
        RightRead = 1<<13,
        RightWrite = 1<<14,
index 1f757e1972057fb989ab471a720cda33cebcbac0..75f9573b2e5d5572c18fd3799a70abee94dcdfcd 100644 (file)
@@ -34,7 +34,7 @@
 #include "opt.h"
 
 #define        NREGVAR 32      /* 16 general + 16 floating */
-#define        REGBITS ((uint32)0xffffffff)
+#define        REGBITS ((uint64)0xffffffffull)
 /*c2go enum {
        NREGVAR = 32,
        REGBITS = 0xffffffff,
@@ -71,7 +71,7 @@ setaddrs(Bits bit)
                i = bnum(bit);
                node = var[i].node;
                n = var[i].name;
-               bit.b[i/32] &= ~(1L<<(i%32));
+               biclr(&bit, i);
 
                // disable all pieces of that variable
                for(i=0; i<nvar; i++) {
@@ -364,7 +364,7 @@ loop2:
                        rgp->varno = i;
                        change = 0;
                        paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
+                       biclr(&bit, i);
                        if(change <= 0)
                                continue;
                        rgp->cost = change;
@@ -389,9 +389,13 @@ brk:
         * replace code (paint3)
         */
        rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
        for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
                bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
+               vreg = paint2(rgp->enter, rgp->varno, 0);
                vreg = allreg(vreg, rgp);
                if(rgp->regno != 0) {
                        if(debug['R'] && debug['v']) {
@@ -406,9 +410,6 @@ brk:
                rgp++;
        }
 
-       if(debug['R'] && debug['v'])
-               dumpit("pass6", &firstr->f, 1);
-       
        /*
         * free aux structures. peep allocates new ones.
         */
@@ -417,6 +418,15 @@ brk:
        flowend(g);
        firstr = R;
 
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
        /*
         * pass 7
         * peep-hole on basic block
@@ -477,7 +487,7 @@ walkvardef(Node *n, Reg *r, int active)
                        break;
                for(v=n->opt; v!=nil; v=v->nextinnode) {
                        bn = v - var;
-                       r1->act.b[bn/32] |= 1L << (bn%32);
+                       biset(&r1->act, bn);
                }
                if(r1->f.prog->as == ACALL)
                        break;
@@ -621,6 +631,9 @@ mkvar(Reg *r, Adr *a)
        if(r != R)
                r->use1.b[0] |= doregbits(a->index);
 
+       if(t >= D_INDIR && t < 2*D_INDIR)
+               goto none;
+
        switch(t) {
        default:
                regu = doregbits(t);
@@ -822,10 +835,10 @@ prop(Reg *r, Bits ref, Bits cal)
                        for(z=0; z<BITS; z++) {
                                if(cal.b[z] == 0)
                                        continue;
-                               for(i=0; i<32; i++) {
-                                       if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
+                               for(i=0; i<64; i++) {
+                                       if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
                                                continue;
-                                       v = var+z*32+i;
+                                       v = var+z*64+i;
                                        if(v->node->opt == nil) // v represents fixed register, not Go variable
                                                continue;
 
@@ -841,10 +854,10 @@ prop(Reg *r, Bits ref, Bits cal)
                                        // This will set the bits at most twice, keeping the overall loop linear.
                                        v1 = v->node->opt;
                                        j = v1 - var;
-                                       if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
+                                       if(v == v1 || !btest(&cal, j)) {
                                                for(; v1 != nil; v1 = v1->nextinnode) {
                                                        j = v1 - var;
-                                                       cal.b[j/32] |= 1UL<<(j&31);
+                                                       biset(&cal, j);
                                                }
                                        }
                                }
@@ -959,10 +972,10 @@ paint1(Reg *r, int bn)
 {
        Reg *r1;
        int z;
-       uint32 bb;
+       uint64 bb;
 
-       z = bn/32;
-       bb = 1L<<(bn%32);
+       z = bn/64;
+       bb = 1LL<<(bn%64);
        if(r->act.b[z] & bb)
                return;
        for(;;) {
@@ -1017,54 +1030,14 @@ paint1(Reg *r, int bn)
 }
 
 uint32
-regset(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Adr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = b & 0xFFFF? BtoR(b): BtoF(b);
-               if(v.type == 0)
-                       fatal("zero v.type for %#ux", b);
-               c = copyu(r->f.prog, &v, nil);
-               if(c == 3)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Adr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = b & 0xFFFF? BtoR(b): BtoF(b);
-               c = copyu(r->f.prog, &v, nil);
-               if(c == 1 || c == 2 || c == 4)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
+paint2(Reg *r, int bn, int depth)
 {
        Reg *r1;
        int z;
-       uint32 bb, vreg, x;
+       uint64 bb, vreg;
 
-       z = bn/32;
-       bb = 1L << (bn%32);
+       z = bn/64;
+       bb = 1LL << (bn%64);
        vreg = regbits;
        if(!(r->act.b[z] & bb))
                return vreg;
@@ -1081,6 +1054,9 @@ paint2(Reg *r, int bn)
                r = r1;
        }
        for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
                r->act.b[z] &= ~bb;
 
                vreg |= r->regu;
@@ -1088,14 +1064,14 @@ paint2(Reg *r, int bn)
                if(r->refbehind.b[z] & bb)
                        for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
                                if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
+                                       vreg |= paint2(r1, bn, depth+1);
 
                if(!(r->refahead.b[z] & bb))
                        break;
                r1 = (Reg*)r->f.s2;
                if(r1 != R)
                        if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
+                               vreg |= paint2(r1, bn, depth+1);
                r = (Reg*)r->f.s1;
                if(r == R)
                        break;
@@ -1105,27 +1081,19 @@ paint2(Reg *r, int bn)
                        break;
        }
 
-       bb = vreg;
-       for(; r; r=(Reg*)r->f.s1) {
-               x = r->regu & ~bb;
-               if(x) {
-                       vreg |= reguse(r, x);
-                       bb |= regset(r, x);
-               }
-       }
        return vreg;
 }
 
 void
-paint3(Reg *r, int bn, int32 rb, int rn)
+paint3(Reg *r, int bn, uint32 rb, int rn)
 {
        Reg *r1;
        Prog *p;
        int z;
-       uint32 bb;
+       uint64 bb;
 
-       z = bn/32;
-       bb = 1L << (bn%32);
+       z = bn/64;
+       bb = 1LL << (bn%64);
        if(r->act.b[z] & bb)
                return;
        for(;;) {
@@ -1198,7 +1166,7 @@ addreg(Adr *a, int rn)
        ostats.ncvtreg++;
 }
 
-int32
+uint32
 RtoB(int r)
 {
 
@@ -1208,7 +1176,7 @@ RtoB(int r)
 }
 
 int
-BtoR(int32 b)
+BtoR(uint32 b)
 {
        b &= 0xffffL;
        if(nacl)
@@ -1224,7 +1192,7 @@ BtoR(int32 b)
  *     ...
  *     31      X15
  */
-int32
+uint32
 FtoB(int f)
 {
        if(f < D_X0 || f > D_X15)
@@ -1233,7 +1201,7 @@ FtoB(int f)
 }
 
 int
-BtoF(int32 b)
+BtoF(uint32 b)
 {
 
        b &= 0xFFFF0000L;
@@ -1304,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" %.4ud", (int)r1->prog->pc);
                        print("\n");
                }
-//             r1 = r->s1;
-//             if(r1 != R) {
-//                     print(" succ:");
-//                     for(; r1 != R; r1 = r1->s1)
-//                             print(" %.4ud", (int)r1->prog->pc);
-//                     print("\n");
-//             }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
        }
 }
index af72784e84a13d19447b01ae5ecfe7cbeea33084..c09ac282424d543ca59dcaf91464dc189877e271 100644 (file)
@@ -865,6 +865,8 @@ enum
 
        D_INDIR,        /* additive */
 
+       D_LAST,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
index adc388ca9f4d0226fa76c8186930738636b6afc9..a1aca07aea7445458bcbed85d6f6c71d17925901 100644 (file)
@@ -70,6 +70,7 @@ struct        Sym
        int32   value;
        ushort  type;
        char    *name;
+       char*   labelname;
        char    sym;
 };
 #define        S       ((Sym*)0)
@@ -148,6 +149,8 @@ void        newio(void);
 void   newfile(char*, int);
 Sym*   slookup(char*);
 Sym*   lookup(void);
+Sym*   labellookup(Sym*);
+void   settext(LSym*);
 void   syminit(Sym*);
 int32  yylex(void);
 int    getc(void);
index 6bcf1313bf653548e2fd69699dac0f3fa1f0cf02..c810d385779d4ddb8ad4061688bff0c51bfe6434 100644 (file)
@@ -74,15 +74,11 @@ prog:
        line
 
 line:
-       LLAB ':'
-       {
-               if($1->value != pc)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = pc;
-       }
-       line
-|      LNAME ':'
+       LNAME ':'
        {
+               $1 = labellookup($1);
+               if($1->type == LLAB && $1->value != pc)
+                       yyerror("redeclaration of %s", $1->labelname);
                $1->type = LLAB;
                $1->value = pc;
        }
@@ -199,11 +195,13 @@ spec1:    /* DATA */
 spec2: /* TEXT */
        mem ',' imm2
        {
+               settext($1.sym);
                $$.from = $1;
                $$.to = $3;
        }
 |      mem ',' con ',' imm2
        {
+               settext($1.sym);
                $$.from = $1;
                $$.from.scale = $3;
                $$.to = $5;
@@ -362,15 +360,10 @@ rel:
        }
 |      LNAME offset
        {
+               $1 = labellookup($1);
                $$ = nullgen;
-               if(pass == 2)
-                       yyerror("undefined label: %s", $1->name);
-               $$.type = D_BRANCH;
-               $$.offset = $2;
-       }
-|      LLAB offset
-       {
-               $$ = nullgen;
+               if(pass == 2 && $1->type != LLAB)
+                       yyerror("undefined label: %s", $1->labelname);
                $$.type = D_BRANCH;
                $$.offset = $1->value + $2;
        }
index 85279c21f98d710fec90dd8358c6611657a201fc..f284d8ea2eca10f7cf7b97b22c61bdda5f9820a8 100644 (file)
@@ -411,16 +411,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   546
+#define YYLAST   561
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  54
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  41
+#define YYNNTS  40
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  135
+#define YYNRULES  132
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  276
+#define YYNSTATES  270
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -469,91 +469,90 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 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,
+       0,     0,     3,     4,     5,     9,    10,    15,    17,    20,
+      23,    27,    31,    34,    37,    40,    43,    46,    49,    52,
       55,    58,    61,    64,    67,    70,    73,    76,    79,    82,
-      85,    88,    91,    92,    94,    98,   102,   105,   107,   110,
-     112,   115,   117,   121,   127,   131,   137,   140,   142,   145,
-     147,   149,   153,   159,   163,   169,   172,   174,   178,   182,
-     188,   194,   200,   204,   208,   210,   212,   214,   216,   219,
-     222,   224,   226,   228,   230,   232,   237,   240,   243,   245,
-     247,   249,   251,   253,   255,   258,   261,   264,   267,   272,
-     278,   282,   285,   287,   290,   294,   299,   301,   303,   305,
-     310,   315,   322,   332,   342,   346,   350,   355,   361,   370,
-     372,   379,   385,   393,   394,   397,   400,   402,   404,   406,
-     408,   410,   413,   416,   419,   423,   425,   429,   433,   437,
-     441,   445,   450,   455,   459,   463
+      85,    86,    88,    92,    96,    99,   101,   104,   106,   109,
+     111,   115,   121,   125,   131,   134,   136,   139,   141,   143,
+     147,   153,   157,   163,   166,   168,   172,   176,   182,   188,
+     194,   198,   202,   204,   206,   208,   210,   213,   216,   218,
+     220,   222,   224,   226,   231,   234,   236,   238,   240,   242,
+     244,   246,   249,   252,   255,   258,   263,   269,   273,   276,
+     278,   281,   285,   290,   292,   294,   296,   301,   306,   313,
+     323,   333,   337,   341,   346,   352,   361,   363,   370,   376,
+     384,   385,   388,   391,   393,   395,   397,   399,   401,   404,
+     407,   410,   414,   416,   420,   424,   428,   432,   436,   441,
+     446,   450,   454
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
       55,     0,    -1,    -1,    -1,    55,    56,    57,    -1,    -1,
-      44,    46,    58,    57,    -1,    -1,    43,    46,    59,    57,
-      -1,    47,    -1,    60,    47,    -1,     1,    47,    -1,    43,
-      48,    94,    -1,    45,    48,    94,    -1,    13,    61,    -1,
-      14,    65,    -1,    15,    64,    -1,    16,    62,    -1,    17,
-      63,    -1,    21,    66,    -1,    19,    67,    -1,    22,    68,
-      -1,    18,    69,    -1,    20,    70,    -1,    23,    71,    -1,
-      24,    72,    -1,    25,    73,    -1,    26,    74,    -1,    27,
-      75,    -1,    28,    76,    -1,    29,    77,    -1,    30,    78,
-      -1,    -1,    49,    -1,    81,    49,    79,    -1,    79,    49,
-      81,    -1,    81,    49,    -1,    81,    -1,    49,    79,    -1,
-      79,    -1,    49,    82,    -1,    82,    -1,    84,    49,    82,
-      -1,    90,    11,    93,    49,    84,    -1,    87,    49,    85,
-      -1,    87,    49,    93,    49,    85,    -1,    49,    80,    -1,
-      80,    -1,    10,    90,    -1,    61,    -1,    65,    -1,    81,
-      49,    79,    -1,    81,    49,    79,    46,    36,    -1,    81,
-      49,    79,    -1,    81,    49,    79,    46,    37,    -1,    81,
-      49,    -1,    81,    -1,    81,    49,    79,    -1,    87,    49,
-      84,    -1,    87,    49,    93,    49,    84,    -1,    83,    49,
-      79,    49,    93,    -1,    84,    49,    79,    49,    83,    -1,
-      81,    49,    81,    -1,    81,    49,    81,    -1,    83,    -1,
-      87,    -1,    82,    -1,    89,    -1,    10,    83,    -1,    10,
-      88,    -1,    83,    -1,    88,    -1,    84,    -1,    79,    -1,
-      84,    -1,    93,    50,    33,    51,    -1,    43,    91,    -1,
-      44,    91,    -1,    35,    -1,    38,    -1,    36,    -1,    39,
-      -1,    42,    -1,    37,    -1,    52,    93,    -1,    52,    90,
-      -1,    52,    41,    -1,    52,    40,    -1,    52,    50,    40,
-      51,    -1,    52,    50,     9,    40,    51,    -1,    52,     9,
-      40,    -1,    52,    86,    -1,    31,    -1,     9,    31,    -1,
-      31,     9,    31,    -1,     9,    31,     9,    31,    -1,    88,
-      -1,    89,    -1,    93,    -1,    93,    50,    36,    51,    -1,
-      93,    50,    42,    51,    -1,    93,    50,    36,    10,    93,
-      51,    -1,    93,    50,    36,    51,    50,    36,    10,    93,
-      51,    -1,    93,    50,    36,    51,    50,    37,    10,    93,
-      51,    -1,    50,    36,    51,    -1,    50,    42,    51,    -1,
-      93,    50,    37,    51,    -1,    50,    36,    10,    93,    51,
-      -1,    50,    36,    51,    50,    36,    10,    93,    51,    -1,
-      90,    -1,    90,    50,    36,    10,    93,    51,    -1,    43,
-      91,    50,    92,    51,    -1,    43,     6,     7,    91,    50,
-      34,    51,    -1,    -1,     8,    93,    -1,     9,    93,    -1,
-      34,    -1,    42,    -1,    32,    -1,    31,    -1,    45,    -1,
-       9,    93,    -1,     8,    93,    -1,    53,    93,    -1,    50,
-      94,    51,    -1,    93,    -1,    94,     8,    94,    -1,    94,
-       9,    94,    -1,    94,    10,    94,    -1,    94,    11,    94,
-      -1,    94,    12,    94,    -1,    94,     6,     6,    94,    -1,
-      94,     7,     7,    94,    -1,    94,     5,    94,    -1,    94,
-       4,    94,    -1,    94,     3,    94,    -1
+      43,    46,    58,    57,    -1,    47,    -1,    59,    47,    -1,
+       1,    47,    -1,    43,    48,    93,    -1,    45,    48,    93,
+      -1,    13,    60,    -1,    14,    64,    -1,    15,    63,    -1,
+      16,    61,    -1,    17,    62,    -1,    21,    65,    -1,    19,
+      66,    -1,    22,    67,    -1,    18,    68,    -1,    20,    69,
+      -1,    23,    70,    -1,    24,    71,    -1,    25,    72,    -1,
+      26,    73,    -1,    27,    74,    -1,    28,    75,    -1,    29,
+      76,    -1,    30,    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,    83,    49,    81,    -1,    89,    11,    92,    49,    83,
+      -1,    86,    49,    84,    -1,    86,    49,    92,    49,    84,
+      -1,    49,    79,    -1,    79,    -1,    10,    89,    -1,    60,
+      -1,    64,    -1,    80,    49,    78,    -1,    80,    49,    78,
+      46,    36,    -1,    80,    49,    78,    -1,    80,    49,    78,
+      46,    37,    -1,    80,    49,    -1,    80,    -1,    80,    49,
+      78,    -1,    86,    49,    83,    -1,    86,    49,    92,    49,
+      83,    -1,    82,    49,    78,    49,    92,    -1,    83,    49,
+      78,    49,    82,    -1,    80,    49,    80,    -1,    80,    49,
+      80,    -1,    82,    -1,    86,    -1,    81,    -1,    88,    -1,
+      10,    82,    -1,    10,    87,    -1,    82,    -1,    87,    -1,
+      83,    -1,    78,    -1,    83,    -1,    92,    50,    33,    51,
+      -1,    43,    90,    -1,    35,    -1,    38,    -1,    36,    -1,
+      39,    -1,    42,    -1,    37,    -1,    52,    92,    -1,    52,
+      89,    -1,    52,    41,    -1,    52,    40,    -1,    52,    50,
+      40,    51,    -1,    52,    50,     9,    40,    51,    -1,    52,
+       9,    40,    -1,    52,    85,    -1,    31,    -1,     9,    31,
+      -1,    31,     9,    31,    -1,     9,    31,     9,    31,    -1,
+      87,    -1,    88,    -1,    92,    -1,    92,    50,    36,    51,
+      -1,    92,    50,    42,    51,    -1,    92,    50,    36,    10,
+      92,    51,    -1,    92,    50,    36,    51,    50,    36,    10,
+      92,    51,    -1,    92,    50,    36,    51,    50,    37,    10,
+      92,    51,    -1,    50,    36,    51,    -1,    50,    42,    51,
+      -1,    92,    50,    37,    51,    -1,    50,    36,    10,    92,
+      51,    -1,    50,    36,    51,    50,    36,    10,    92,    51,
+      -1,    89,    -1,    89,    50,    36,    10,    92,    51,    -1,
+      43,    90,    50,    91,    51,    -1,    43,     6,     7,    90,
+      50,    34,    51,    -1,    -1,     8,    92,    -1,     9,    92,
+      -1,    34,    -1,    42,    -1,    32,    -1,    31,    -1,    45,
+      -1,     9,    92,    -1,     8,    92,    -1,    53,    92,    -1,
+      50,    93,    51,    -1,    92,    -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.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    69,    69,    71,    70,    78,    77,    85,    84,    90,
-      91,    92,    95,   100,   106,   107,   108,   109,   110,   111,
-     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
-     122,   123,   126,   130,   137,   144,   151,   156,   163,   168,
-     175,   180,   185,   192,   200,   205,   213,   218,   223,   232,
-     233,   236,   241,   251,   256,   266,   271,   276,   283,   288,
-     296,   304,   314,   323,   334,   335,   338,   339,   340,   344,
-     348,   349,   350,   353,   354,   357,   363,   371,   379,   384,
-     389,   394,   399,   404,   411,   417,   428,   434,   440,   446,
-     452,   460,   469,   474,   479,   484,   491,   492,   495,   501,
-     507,   513,   522,   531,   540,   545,   550,   556,   564,   574,
-     578,   587,   594,   603,   606,   610,   616,   617,   621,   624,
-     625,   629,   633,   637,   641,   647,   648,   652,   656,   660,
-     664,   668,   672,   676,   680,   684
+       0,    69,    69,    71,    70,    78,    77,    86,    87,    88,
+      91,    96,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     122,   126,   133,   140,   147,   152,   159,   164,   171,   176,
+     181,   188,   196,   202,   211,   216,   221,   230,   231,   234,
+     239,   249,   254,   264,   269,   274,   281,   286,   294,   302,
+     312,   321,   332,   333,   336,   337,   338,   342,   346,   347,
+     348,   351,   352,   355,   361,   372,   377,   382,   387,   392,
+     397,   404,   410,   421,   427,   433,   439,   445,   453,   462,
+     467,   472,   477,   484,   485,   488,   494,   500,   506,   515,
+     524,   533,   538,   543,   549,   557,   567,   571,   580,   587,
+     596,   599,   603,   609,   610,   614,   617,   618,   622,   626,
+     630,   634,   640,   641,   645,   649,   653,   657,   661,   665,
+     669,   673,   677
 };
 #endif
 
@@ -569,10 +568,10 @@ static const char *const yytname[] =
   "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", "spec9", "spec10", "spec11", "spec12", "rem", "rom",
-  "rim", "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem", "nam",
+  "line", "@2", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem",
+  "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7",
+  "spec8", "spec9", "spec10", "spec11", "spec12", "rem", "rom", "rim",
+  "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem", "nam",
   "offset", "pointer", "con", "expr", 0
 };
 #endif
@@ -594,39 +593,39 @@ static const yytype_uint16 yytoknum[] =
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    54,    55,    56,    55,    58,    57,    59,    57,    57,
-      57,    57,    60,    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,    66,    67,    68,    68,    69,    69,    69,    70,
-      70,    71,    71,    72,    72,    73,    73,    73,    74,    74,
-      75,    76,    77,    78,    79,    79,    80,    80,    80,    80,
-      80,    80,    80,    81,    81,    82,    82,    82,    83,    83,
-      83,    83,    83,    83,    84,    84,    84,    84,    84,    84,
-      84,    85,    86,    86,    86,    86,    87,    87,    88,    88,
-      88,    88,    88,    88,    88,    88,    88,    88,    88,    89,
-      89,    90,    90,    91,    91,    91,    92,    92,    92,    93,
-      93,    93,    93,    93,    93,    94,    94,    94,    94,    94,
-      94,    94,    94,    94,    94,    94
+       0,    54,    55,    56,    55,    58,    57,    57,    57,    57,
+      59,    59,    59,    59,    59,    59,    59,    59,    59,    59,
+      59,    59,    59,    59,    59,    59,    59,    59,    59,    59,
+      60,    60,    61,    62,    63,    63,    64,    64,    65,    65,
+      65,    66,    67,    67,    68,    68,    68,    69,    69,    70,
+      70,    71,    71,    72,    72,    72,    73,    73,    74,    75,
+      76,    77,    78,    78,    79,    79,    79,    79,    79,    79,
+      79,    80,    80,    81,    81,    82,    82,    82,    82,    82,
+      82,    83,    83,    83,    83,    83,    83,    83,    84,    85,
+      85,    85,    85,    86,    86,    87,    87,    87,    87,    87,
+      87,    87,    87,    87,    87,    87,    88,    88,    89,    89,
+      90,    90,    90,    91,    91,    91,    92,    92,    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.  */
 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,
+       0,     2,     0,     0,     3,     0,     4,     1,     2,     2,
+       3,     3,     2,     2,     2,     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,     3,     5,     3,     5,     2,     1,     2,     1,
-       1,     3,     5,     3,     5,     2,     1,     3,     3,     5,
-       5,     5,     3,     3,     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,     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
+       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,     5,
+       3,     3,     1,     1,     1,     1,     2,     2,     1,     1,
+       1,     1,     1,     4,     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,
+       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
@@ -634,89 +633,85 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     3,     1,     0,     0,    32,     0,     0,     0,     0,
-       0,     0,    32,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     9,     4,     0,    11,
-      33,    14,     0,     0,   119,    78,    80,    83,    79,    81,
-      82,   113,   120,     0,     0,     0,    15,    39,    64,    65,
-      96,    97,   109,    98,     0,    16,    73,    37,    74,    17,
-       0,    18,     0,     0,   113,   113,     0,    22,    47,    66,
-      70,    72,    71,    67,    98,    20,     0,    33,    49,    50,
-      23,   113,     0,     0,    19,    41,     0,     0,    21,     0,
-      24,     0,    25,     0,    26,    56,    27,     0,    28,     0,
-      29,     0,    30,     0,    31,     0,     7,     0,     5,     0,
-      10,   122,   121,     0,     0,     0,     0,    38,     0,     0,
-     125,     0,   123,     0,     0,     0,    87,    86,     0,    85,
-      84,    36,     0,     0,    68,    69,    48,    76,    77,     0,
-      46,     0,     0,    76,    40,     0,     0,     0,     0,     0,
-      55,     0,     0,     0,     0,     0,     0,    12,     0,    13,
-     113,   114,   115,     0,     0,   104,   105,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   124,     0,     0,
-       0,     0,    90,     0,     0,    34,    35,     0,     0,    42,
-       0,    44,     0,    51,    53,    57,    58,     0,     0,     0,
-      62,    63,     8,     6,     0,   118,   116,   117,     0,     0,
-       0,   135,   134,   133,     0,     0,   126,   127,   128,   129,
-     130,     0,     0,    99,   106,   100,     0,    88,    75,     0,
-       0,    92,    91,     0,     0,     0,     0,     0,     0,     0,
-     111,   107,     0,   131,   132,     0,     0,     0,    89,    43,
-      93,     0,    45,    52,    54,    59,    60,    61,     0,     0,
-     110,   101,     0,     0,     0,    94,   112,     0,     0,     0,
-      95,   108,     0,     0,   102,   103
+       2,     3,     1,     0,     0,    30,     0,     0,     0,     0,
+       0,     0,    30,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     7,     4,     0,     9,    31,
+      12,     0,     0,   116,    75,    77,    80,    76,    78,    79,
+     110,   117,     0,     0,     0,    13,    37,    62,    63,    93,
+      94,   106,    95,     0,    14,    71,    35,    72,    15,     0,
+      16,     0,     0,   110,     0,    20,    45,    64,    68,    70,
+      69,    65,    95,    18,     0,    31,    47,    48,    21,   110,
+       0,     0,    17,    39,     0,     0,    19,     0,    22,     0,
+      23,     0,    24,    54,    25,     0,    26,     0,    27,     0,
+      28,     0,    29,     0,     5,     0,     0,     8,   119,   118,
+       0,     0,     0,     0,    36,     0,     0,   122,     0,   120,
+       0,     0,     0,    84,    83,     0,    82,    81,    34,     0,
+       0,    66,    67,    46,    74,     0,    44,     0,     0,    74,
+      38,     0,     0,     0,     0,     0,    53,     0,     0,     0,
+       0,     0,     0,    10,    11,   110,   111,   112,     0,     0,
+     101,   102,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   121,     0,     0,     0,     0,    87,     0,     0,
+      32,    33,     0,     0,    40,     0,    42,     0,    49,    51,
+      55,    56,     0,     0,     0,    60,    61,     6,     0,   115,
+     113,   114,     0,     0,     0,   132,   131,   130,     0,     0,
+     123,   124,   125,   126,   127,     0,     0,    96,   103,    97,
+       0,    85,    73,     0,     0,    89,    88,     0,     0,     0,
+       0,     0,     0,     0,   108,   104,     0,   128,   129,     0,
+       0,     0,    86,    41,    90,     0,    43,    50,    52,    57,
+      58,    59,     0,     0,   107,    98,     0,     0,     0,    91,
+     109,     0,     0,     0,    92,   105,     0,     0,    99,   100
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     3,    27,   158,   156,    28,    31,    59,    61,
-      55,    46,    84,    75,    88,    67,    80,    90,    92,    94,
-      96,    98,   100,   102,   104,    56,    68,    57,    69,    48,
-      58,   191,   232,    49,    50,    51,    52,   116,   208,    53,
-     121
+      -1,     1,     3,    26,   152,    27,    30,    58,    60,    54,
+      45,    82,    73,    86,    65,    78,    88,    90,    92,    94,
+      96,    98,   100,   102,    55,    66,    56,    67,    47,    57,
+     186,   226,    48,    49,    50,    51,   113,   202,    52,   118
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -104
+#define YYPACT_NINF -89
 static const yytype_int16 yypact[] =
 {
-    -104,     4,  -104,   173,   -26,   -25,   277,   297,   297,   349,
-     225,   -14,   329,   396,    18,   297,   297,   297,    18,   171,
-     -20,   297,   297,     2,    -4,    26,  -104,  -104,    43,  -104,
-    -104,  -104,   478,   478,  -104,  -104,  -104,  -104,  -104,  -104,
-    -104,   111,  -104,   349,   402,   478,  -104,  -104,  -104,  -104,
-    -104,  -104,   -12,    -5,    83,  -104,  -104,    44,  -104,  -104,
-      46,  -104,    49,   349,   111,   113,   245,  -104,  -104,  -104,
-    -104,  -104,  -104,  -104,    50,  -104,   100,   349,  -104,  -104,
-    -104,   113,   420,   478,  -104,  -104,    64,    66,  -104,    78,
-    -104,    80,  -104,    85,  -104,    89,  -104,    93,  -104,    98,
-    -104,   101,  -104,   112,  -104,   121,  -104,   478,  -104,   478,
-    -104,  -104,  -104,   153,   478,   478,   135,  -104,     8,   163,
-    -104,    74,  -104,   179,    52,   427,  -104,  -104,   445,  -104,
-    -104,  -104,   349,   297,  -104,  -104,  -104,   135,  -104,   381,
-    -104,    33,   478,  -104,  -104,   420,   186,   451,   349,   349,
-     349,   460,   349,   349,   297,   297,   173,   172,   173,   172,
-     113,  -104,  -104,     5,   478,   180,  -104,   478,   478,   478,
-     226,   224,   478,   478,   478,   478,   478,  -104,   235,    36,
-     195,   196,  -104,   466,   197,  -104,  -104,   199,   202,  -104,
-      21,  -104,   203,   211,   219,  -104,  -104,   217,   222,   223,
-    -104,  -104,  -104,  -104,   229,  -104,  -104,  -104,   240,   241,
-     237,   232,   527,   534,   478,   478,   134,   134,  -104,  -104,
-    -104,   478,   478,   243,  -104,  -104,   248,  -104,  -104,   -20,
-     263,   287,  -104,   249,   264,   265,   -20,   478,   171,   269,
-    -104,  -104,   294,   214,   214,   256,   258,   119,  -104,  -104,
-     301,   280,  -104,  -104,  -104,  -104,  -104,  -104,   266,   478,
-    -104,  -104,   308,   311,   292,  -104,  -104,   273,   478,   478,
-    -104,  -104,   274,   278,  -104,  -104
+     -89,     8,   -89,   211,   -33,   -23,   288,   308,   308,   360,
+     236,   -11,   340,    54,    41,   308,   308,   308,    41,   106,
+     -13,   308,   308,    62,    -4,   -89,   -89,    45,   -89,   -89,
+     -89,   484,   484,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
+      81,   -89,   360,   413,   484,   -89,   -89,   -89,   -89,   -89,
+     -89,    38,    48,   407,   -89,   -89,    -2,   -89,   -89,    64,
+     -89,    78,   360,    81,   256,   -89,   -89,   -89,   -89,   -89,
+     -89,   -89,    61,   -89,   107,   360,   -89,   -89,   -89,    59,
+     431,   484,   -89,   -89,    86,    79,   -89,    87,   -89,    89,
+     -89,    91,   -89,    97,   -89,   102,   -89,   116,   -89,   120,
+     -89,   148,   -89,   151,   -89,   484,   484,   -89,   -89,   -89,
+     123,   484,   484,   105,   -89,     1,   150,   -89,   169,   -89,
+     166,     9,    69,   -89,   -89,   456,   -89,   -89,   -89,   360,
+     308,   -89,   -89,   -89,   105,   392,   -89,   -17,   484,   -89,
+     -89,   431,   170,   460,   360,   360,   360,   469,   360,   360,
+     308,   308,   211,   179,   179,    59,   -89,   -89,     6,   484,
+     154,   -89,   484,   484,   484,   201,   149,   484,   484,   484,
+     484,   484,   -89,   198,    13,   158,   159,   -89,   480,   160,
+     -89,   -89,   162,   165,   -89,     0,   -89,   167,   171,   172,
+     -89,   -89,   193,   199,   200,   -89,   -89,   -89,   197,   -89,
+     -89,   -89,   168,   204,   214,   534,   542,   549,   484,   484,
+     113,   113,   -89,   -89,   -89,   484,   484,   207,   -89,   -89,
+     208,   -89,   -89,   -13,   220,   251,   -89,   209,   226,   231,
+     -13,   484,   106,   229,   -89,   -89,   259,   184,   184,   219,
+     225,    80,   -89,   -89,   268,   249,   -89,   -89,   -89,   -89,
+     -89,   -89,   232,   484,   -89,   -89,   272,   274,   269,   -89,
+     -89,   239,   484,   484,   -89,   -89,   252,   253,   -89,   -89
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -104,  -104,  -104,  -103,  -104,  -104,  -104,   319,  -104,  -104,
-    -104,   331,  -104,  -104,  -104,  -104,  -104,  -104,  -104,  -104,
-    -104,  -104,  -104,  -104,  -104,    19,   275,    -2,    -6,    -9,
-      -8,   115,  -104,    22,     1,    -1,    -3,   -48,  -104,   -10,
-     -66
+     -89,   -89,   -89,   153,   -89,   -89,   290,   -89,   -89,   -89,
+     295,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,   -89,
+     -89,   -89,   -89,   -89,    18,   246,    20,    -7,    -9,    -8,
+      84,   -89,    51,    -3,    -6,     4,   -50,   -89,   -10,   -88
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -726,120 +721,124 @@ static const yytype_int16 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint16 yytable[] =
 {
-      74,    70,    71,    87,     2,    86,    60,    85,    76,    73,
-      99,    72,   101,    91,    93,    95,   137,   138,   164,   103,
-     105,    29,   111,   112,    30,    47,    32,    33,    62,    41,
-     230,    47,    54,   143,   120,   122,    89,   205,   123,   206,
-      97,   157,   108,   159,   130,   124,   222,   207,   106,    34,
-     107,   129,   231,   202,   134,   203,    74,    70,    71,   165,
-     136,    41,   117,    42,   135,    73,   187,    72,    44,   179,
-     180,    45,    87,   120,   109,   181,   144,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   223,   179,   180,
-     110,    32,   125,   131,   181,   132,   117,   120,   133,   120,
-     141,   211,   212,   213,   161,   162,   216,   217,   218,   219,
-     220,   142,   204,   145,    34,   112,   146,   113,   120,   114,
-     115,   114,   115,   126,   127,   177,    41,   147,    42,   148,
-     134,   186,   188,   128,   149,    87,    45,   192,   150,   189,
-     135,   197,   151,   196,   174,   175,   176,   152,   243,   244,
-     153,   185,   200,   201,   209,   262,   263,   120,   120,   120,
-     160,   154,   120,   120,   120,   120,   120,   193,   194,   195,
-     155,   198,   199,   112,     4,   167,   168,   169,   170,   171,
-     172,   173,   174,   175,   176,   163,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,   120,   120,    35,    36,    37,    38,
-      39,   245,   246,    40,   166,   178,    23,    24,    25,   187,
-      26,   249,   172,   173,   174,   175,   176,   256,   255,   257,
-     210,   215,   214,    32,    33,    63,   168,   169,   170,   171,
-     172,   173,   174,   175,   176,   221,   224,   225,   227,   267,
-     228,   229,   233,    32,    33,   139,    34,   234,   272,   273,
-      35,    36,    37,    38,    39,   235,   236,    40,    64,    65,
-      42,   237,   238,   242,    66,    44,    34,    54,    45,   239,
-      35,    36,    37,    38,    39,    32,    33,    40,    64,    65,
-      42,   240,   241,   247,   250,    44,   251,    54,    45,   248,
-     253,   190,   254,   258,   259,    32,    33,   260,    34,   261,
-     264,   265,    35,    36,    37,    38,    39,   266,   268,    40,
-      41,   269,    42,   270,   271,   274,    43,    44,    34,   275,
-      45,    78,    35,    36,    37,    38,    39,    32,    33,    40,
-      41,   140,    42,    79,     0,     0,     0,    44,   252,    54,
-      45,     0,     0,     0,     0,     0,     0,    32,    33,     0,
-      34,     0,     0,     0,    35,    36,    37,    38,    39,     0,
-       0,    40,    41,     0,    42,     0,     0,     0,    77,    44,
-      34,     0,    45,     0,    35,    36,    37,    38,    39,    32,
-      33,    40,    41,     0,    42,     0,     0,     0,     0,    44,
-       0,     0,    45,     0,    32,    33,     0,     0,     0,     0,
-      32,    33,    34,     0,     0,     0,    35,    36,    37,    38,
-      39,     0,     0,    40,     0,     0,    42,    34,    32,    33,
-       0,    44,     0,    34,    45,    32,    33,     0,   118,    81,
-      65,    42,     0,     0,   119,    82,    83,    42,    54,    45,
-       0,    34,    83,    32,   183,    45,     0,     0,    34,    32,
-      33,     0,     0,    81,    65,    42,     0,   182,    32,    33,
-      83,     0,    42,    45,    32,    33,    34,    83,     0,     0,
-      45,     0,    34,     0,     0,   184,    32,    33,     0,     0,
-      42,    34,     0,     0,     0,    83,    42,    34,    45,     0,
-       0,    83,     0,   190,    45,    42,   226,     0,     0,    34,
-      83,    42,    54,    45,     0,     0,    83,     0,     0,    45,
-       0,     0,     0,    42,     0,     0,     0,     0,    83,     0,
-       0,    45,   169,   170,   171,   172,   173,   174,   175,   176,
-     170,   171,   172,   173,   174,   175,   176
+      72,    68,    69,    85,    71,    84,    83,    70,     2,   224,
+      97,   159,    99,   134,    28,    74,   182,   153,   154,   174,
+     175,   108,   109,   216,    46,   176,    29,    61,    59,   139,
+      46,   225,    40,   117,   119,    89,    91,    93,   199,    53,
+     200,   101,   103,   127,   106,   174,   175,   128,   201,    31,
+      32,   176,   160,   131,    72,    68,    69,   126,    71,   132,
+     114,    70,    31,    32,   217,    87,   133,   111,   112,    95,
+      85,   117,    33,   140,   205,   206,   207,    31,    32,   210,
+     211,   212,   213,   214,    40,    33,    41,   110,   120,   111,
+     112,    43,   107,   114,    44,   117,   117,    79,   121,    41,
+      33,   156,   157,    80,    81,   198,    53,    44,   104,   177,
+     105,   137,   109,   129,    41,   117,   256,   257,   138,    81,
+     237,   238,    44,   169,   170,   171,   131,   130,   183,   142,
+     155,    85,   132,   187,   184,   141,   143,   192,   144,   191,
+     145,    34,    35,    36,    37,    38,   146,   180,    39,   203,
+     181,   147,   117,   117,   117,   158,   209,   117,   117,   117,
+     117,   117,   188,   189,   190,   148,   193,   194,   109,   149,
+     195,   196,   162,   163,   164,   165,   166,   167,   168,   169,
+     170,   171,   162,   163,   164,   165,   166,   167,   168,   169,
+     170,   171,   167,   168,   169,   170,   171,   150,   117,   117,
+     151,   161,   173,   182,   204,   239,   240,   208,   215,   218,
+     219,   221,     4,   222,   223,   243,   227,   228,   229,   234,
+     172,   250,   249,   251,     5,     6,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,   230,   261,    31,    32,    62,   233,   231,   232,
+     236,   244,   266,   267,    23,   235,    24,   241,    25,   242,
+     245,   185,   247,   252,    31,    32,   135,    33,   248,   253,
+     254,    34,    35,    36,    37,    38,   255,   258,    39,    63,
+     259,    41,   262,   260,   263,    64,    43,    33,    53,    44,
+     265,    34,    35,    36,    37,    38,    31,    32,    39,    63,
+     264,    41,    76,   268,   269,   197,    43,    77,    53,    44,
+     136,   246,     0,     0,     0,     0,    31,    32,     0,    33,
+       0,     0,     0,    34,    35,    36,    37,    38,     0,     0,
+      39,    40,     0,    41,     0,     0,     0,    42,    43,    33,
+       0,    44,     0,    34,    35,    36,    37,    38,    31,    32,
+      39,    40,     0,    41,     0,     0,     0,     0,    43,     0,
+      53,    44,     0,     0,     0,     0,     0,     0,    31,    32,
+       0,    33,     0,     0,     0,    34,    35,    36,    37,    38,
+       0,     0,    39,    40,     0,    41,     0,     0,     0,    75,
+      43,    33,     0,    44,     0,    34,    35,    36,    37,    38,
+      31,    32,    39,    40,     0,    41,     0,     0,     0,     0,
+      43,     0,     0,    44,     0,    31,   122,     0,     0,     0,
+       0,    31,    32,    33,     0,     0,     0,    34,    35,    36,
+      37,    38,     0,     0,    39,     0,     0,    41,    33,    31,
+      32,     0,    43,     0,    33,    44,     0,   123,   124,   115,
+      40,     0,    41,     0,     0,   116,     0,   125,    41,     0,
+      44,     0,    33,    81,    31,   178,    44,     0,    31,    32,
+       0,     0,     0,     0,    79,     0,    41,    31,    32,     0,
+       0,    81,     0,     0,    44,     0,     0,    33,    31,    32,
+       0,    33,    31,    32,     0,     0,   179,     0,     0,     0,
+      33,    41,     0,     0,     0,    41,    81,     0,     0,    44,
+      81,    33,   185,    44,    41,    33,     0,     0,     0,    81,
+     220,    53,    44,     0,     0,    41,     0,     0,     0,    41,
+      81,     0,     0,    44,    81,     0,     0,    44,   163,   164,
+     165,   166,   167,   168,   169,   170,   171,   164,   165,   166,
+     167,   168,   169,   170,   171,   165,   166,   167,   168,   169,
+     170,   171
 };
 
 static const yytype_int16 yycheck[] =
 {
-      10,    10,    10,    13,     0,    13,     8,    13,    11,    10,
-      19,    10,    20,    15,    16,    17,    64,    65,    10,    21,
-      22,    47,    32,    33,    49,     6,     8,     9,     9,    43,
-       9,    12,    52,    81,    44,    45,    14,    32,    50,    34,
-      18,   107,    46,   109,    54,    50,    10,    42,    46,    31,
-      48,    54,    31,   156,    63,   158,    66,    66,    66,    51,
-      63,    43,    43,    45,    63,    66,    33,    66,    50,    36,
-      37,    53,    82,    83,    48,    42,    82,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    51,    36,    37,
-      47,     8,     9,    49,    42,    49,    77,   107,    49,   109,
-      50,   167,   168,   169,   114,   115,   172,   173,   174,   175,
-     176,    11,   160,    49,    31,   125,    50,     6,   128,     8,
-       9,     8,     9,    40,    41,    51,    43,    49,    45,    49,
-     139,   133,   142,    50,    49,   145,    53,   147,    49,   145,
-     139,   151,    49,   151,    10,    11,    12,    49,   214,   215,
-      49,   132,   154,   155,   164,    36,    37,   167,   168,   169,
-       7,    49,   172,   173,   174,   175,   176,   148,   149,   150,
-      49,   152,   153,   183,     1,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    50,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,   214,   215,    35,    36,    37,    38,
-      39,   221,   222,    42,    51,    36,    43,    44,    45,    33,
-      47,   229,     8,     9,    10,    11,    12,   237,   236,   238,
-      50,     7,     6,     8,     9,    10,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    10,    51,    51,    51,   259,
-      51,    49,    49,     8,     9,    10,    31,    46,   268,   269,
-      35,    36,    37,    38,    39,    46,    49,    42,    43,    44,
-      45,    49,    49,    36,    49,    50,    31,    52,    53,    50,
-      35,    36,    37,    38,    39,     8,     9,    42,    43,    44,
-      45,    51,    51,    50,    31,    50,     9,    52,    53,    51,
-      36,    52,    37,    34,    10,     8,     9,    51,    31,    51,
-       9,    31,    35,    36,    37,    38,    39,    51,    10,    42,
-      43,    10,    45,    31,    51,    51,    49,    50,    31,    51,
-      53,    12,    35,    36,    37,    38,    39,     8,     9,    42,
-      43,    66,    45,    12,    -1,    -1,    -1,    50,   233,    52,
-      53,    -1,    -1,    -1,    -1,    -1,    -1,     8,     9,    -1,
-      31,    -1,    -1,    -1,    35,    36,    37,    38,    39,    -1,
-      -1,    42,    43,    -1,    45,    -1,    -1,    -1,    49,    50,
-      31,    -1,    53,    -1,    35,    36,    37,    38,    39,     8,
-       9,    42,    43,    -1,    45,    -1,    -1,    -1,    -1,    50,
-      -1,    -1,    53,    -1,     8,     9,    -1,    -1,    -1,    -1,
-       8,     9,    31,    -1,    -1,    -1,    35,    36,    37,    38,
-      39,    -1,    -1,    42,    -1,    -1,    45,    31,     8,     9,
-      -1,    50,    -1,    31,    53,     8,     9,    -1,    36,    43,
-      44,    45,    -1,    -1,    42,    49,    50,    45,    52,    53,
-      -1,    31,    50,     8,     9,    53,    -1,    -1,    31,     8,
-       9,    -1,    -1,    43,    44,    45,    -1,    40,     8,     9,
-      50,    -1,    45,    53,     8,     9,    31,    50,    -1,    -1,
-      53,    -1,    31,    -1,    -1,    40,     8,     9,    -1,    -1,
-      45,    31,    -1,    -1,    -1,    50,    45,    31,    53,    -1,
-      -1,    50,    -1,    52,    53,    45,    40,    -1,    -1,    31,
-      50,    45,    52,    53,    -1,    -1,    50,    -1,    -1,    53,
-      -1,    -1,    -1,    45,    -1,    -1,    -1,    -1,    50,    -1,
-      -1,    53,     5,     6,     7,     8,     9,    10,    11,    12,
-       6,     7,     8,     9,    10,    11,    12
+      10,    10,    10,    13,    10,    13,    13,    10,     0,     9,
+      19,    10,    20,    63,    47,    11,    33,   105,   106,    36,
+      37,    31,    32,    10,     6,    42,    49,     9,     8,    79,
+      12,    31,    43,    43,    44,    15,    16,    17,    32,    52,
+      34,    21,    22,    53,    48,    36,    37,    49,    42,     8,
+       9,    42,    51,    62,    64,    64,    64,    53,    64,    62,
+      42,    64,     8,     9,    51,    14,    62,     8,     9,    18,
+      80,    81,    31,    80,   162,   163,   164,     8,     9,   167,
+     168,   169,   170,   171,    43,    31,    45,     6,    50,     8,
+       9,    50,    47,    75,    53,   105,   106,    43,    50,    45,
+      31,   111,   112,    49,    50,   155,    52,    53,    46,    40,
+      48,    50,   122,    49,    45,   125,    36,    37,    11,    50,
+     208,   209,    53,    10,    11,    12,   135,    49,   138,    50,
+       7,   141,   135,   143,   141,    49,    49,   147,    49,   147,
+      49,    35,    36,    37,    38,    39,    49,   129,    42,   159,
+     130,    49,   162,   163,   164,    50,     7,   167,   168,   169,
+     170,   171,   144,   145,   146,    49,   148,   149,   178,    49,
+     150,   151,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,     8,     9,    10,    11,    12,    49,   208,   209,
+      49,    51,    36,    33,    50,   215,   216,     6,    10,    51,
+      51,    51,     1,    51,    49,   223,    49,    46,    46,    51,
+      51,   231,   230,   232,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    49,   253,     8,     9,    10,    50,    49,    49,
+      36,    31,   262,   263,    43,    51,    45,    50,    47,    51,
+       9,    52,    36,    34,     8,     9,    10,    31,    37,    10,
+      51,    35,    36,    37,    38,    39,    51,     9,    42,    43,
+      31,    45,    10,    51,    10,    49,    50,    31,    52,    53,
+      51,    35,    36,    37,    38,    39,     8,     9,    42,    43,
+      31,    45,    12,    51,    51,   152,    50,    12,    52,    53,
+      64,   227,    -1,    -1,    -1,    -1,     8,     9,    -1,    31,
+      -1,    -1,    -1,    35,    36,    37,    38,    39,    -1,    -1,
+      42,    43,    -1,    45,    -1,    -1,    -1,    49,    50,    31,
+      -1,    53,    -1,    35,    36,    37,    38,    39,     8,     9,
+      42,    43,    -1,    45,    -1,    -1,    -1,    -1,    50,    -1,
+      52,    53,    -1,    -1,    -1,    -1,    -1,    -1,     8,     9,
+      -1,    31,    -1,    -1,    -1,    35,    36,    37,    38,    39,
+      -1,    -1,    42,    43,    -1,    45,    -1,    -1,    -1,    49,
+      50,    31,    -1,    53,    -1,    35,    36,    37,    38,    39,
+       8,     9,    42,    43,    -1,    45,    -1,    -1,    -1,    -1,
+      50,    -1,    -1,    53,    -1,     8,     9,    -1,    -1,    -1,
+      -1,     8,     9,    31,    -1,    -1,    -1,    35,    36,    37,
+      38,    39,    -1,    -1,    42,    -1,    -1,    45,    31,     8,
+       9,    -1,    50,    -1,    31,    53,    -1,    40,    41,    36,
+      43,    -1,    45,    -1,    -1,    42,    -1,    50,    45,    -1,
+      53,    -1,    31,    50,     8,     9,    53,    -1,     8,     9,
+      -1,    -1,    -1,    -1,    43,    -1,    45,     8,     9,    -1,
+      -1,    50,    -1,    -1,    53,    -1,    -1,    31,     8,     9,
+      -1,    31,     8,     9,    -1,    -1,    40,    -1,    -1,    -1,
+      31,    45,    -1,    -1,    -1,    45,    50,    -1,    -1,    53,
+      50,    31,    52,    53,    45,    31,    -1,    -1,    -1,    50,
+      40,    52,    53,    -1,    -1,    45,    -1,    -1,    -1,    45,
+      50,    -1,    -1,    53,    50,    -1,    -1,    53,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,     5,     6,     7,
+       8,     9,    10,    11,    12,     6,     7,     8,     9,    10,
+      11,    12
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -848,32 +847,31 @@ static const yytype_uint8 yystos[] =
 {
        0,    55,     0,    56,     1,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    43,    44,    45,    47,    57,    60,    47,
-      49,    61,     8,     9,    31,    35,    36,    37,    38,    39,
-      42,    43,    45,    49,    50,    53,    65,    79,    83,    87,
-      88,    89,    90,    93,    52,    64,    79,    81,    84,    62,
-      81,    63,    79,    10,    43,    44,    49,    69,    80,    82,
-      83,    84,    88,    89,    93,    67,    90,    49,    61,    65,
-      70,    43,    49,    50,    66,    82,    84,    93,    68,    87,
-      71,    81,    72,    81,    73,    81,    74,    87,    75,    83,
-      76,    84,    77,    81,    78,    81,    46,    48,    46,    48,
-      47,    93,    93,     6,     8,     9,    91,    79,    36,    42,
-      93,    94,    93,    50,    50,     9,    40,    41,    50,    90,
-      93,    49,    49,    49,    83,    88,    90,    91,    91,    10,
-      80,    50,    11,    91,    82,    49,    50,    49,    49,    49,
-      49,    49,    49,    49,    49,    49,    59,    94,    58,    94,
-       7,    93,    93,    50,    10,    51,    51,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    51,    36,    36,
-      37,    42,    40,     9,    40,    79,    81,    33,    93,    82,
-      52,    85,    93,    79,    79,    79,    84,    93,    79,    79,
-      81,    81,    57,    57,    91,    32,    34,    42,    92,    93,
-      50,    94,    94,    94,     6,     7,    94,    94,    94,    94,
-      94,    10,    10,    51,    51,    51,    40,    51,    51,    49,
-       9,    31,    86,    49,    46,    46,    49,    49,    49,    50,
-      51,    51,    36,    94,    94,    93,    93,    50,    51,    84,
-      31,     9,    85,    36,    37,    84,    93,    83,    34,    10,
-      51,    51,    36,    37,     9,    31,    51,    93,    10,    10,
-      31,    51,    93,    93,    51,    51
+      28,    29,    30,    43,    45,    47,    57,    59,    47,    49,
+      60,     8,     9,    31,    35,    36,    37,    38,    39,    42,
+      43,    45,    49,    50,    53,    64,    78,    82,    86,    87,
+      88,    89,    92,    52,    63,    78,    80,    83,    61,    80,
+      62,    78,    10,    43,    49,    68,    79,    81,    82,    83,
+      87,    88,    92,    66,    89,    49,    60,    64,    69,    43,
+      49,    50,    65,    81,    83,    92,    67,    86,    70,    80,
+      71,    80,    72,    80,    73,    86,    74,    82,    75,    83,
+      76,    80,    77,    80,    46,    48,    48,    47,    92,    92,
+       6,     8,     9,    90,    78,    36,    42,    92,    93,    92,
+      50,    50,     9,    40,    41,    50,    89,    92,    49,    49,
+      49,    82,    87,    89,    90,    10,    79,    50,    11,    90,
+      81,    49,    50,    49,    49,    49,    49,    49,    49,    49,
+      49,    49,    58,    93,    93,     7,    92,    92,    50,    10,
+      51,    51,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    51,    36,    36,    37,    42,    40,     9,    40,
+      78,    80,    33,    92,    81,    52,    84,    92,    78,    78,
+      78,    83,    92,    78,    78,    80,    80,    57,    90,    32,
+      34,    42,    91,    92,    50,    93,    93,    93,     6,     7,
+      93,    93,    93,    93,    93,    10,    10,    51,    51,    51,
+      40,    51,    51,    49,     9,    31,    85,    49,    46,    46,
+      49,    49,    49,    50,    51,    51,    36,    93,    93,    92,
+      92,    50,    51,    83,    31,     9,    84,    36,    37,    83,
+      92,    82,    34,    10,    51,    51,    36,    37,     9,    31,
+      51,    92,    10,    10,    31,    51,    92,    92,    51,    51
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1697,30 +1695,24 @@ yyreduce:
   case 5:
 #line 78 "a.y"
     {
-               if((yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name);
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 7:
-#line 85 "a.y"
-    {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
+               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
+                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname);
                (yyvsp[(1) - (2)].sym)->type = LLAB;
                (yyvsp[(1) - (2)].sym)->value = pc;
        }
     break;
 
-  case 12:
-#line 96 "a.y"
+  case 10:
+#line 92 "a.y"
     {
                (yyvsp[(1) - (3)].sym)->type = LVAR;
                (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 13:
-#line 101 "a.y"
+  case 11:
+#line 97 "a.y"
     {
                if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
                        yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name);
@@ -1728,186 +1720,186 @@ yyreduce:
        }
     break;
 
+  case 12:
+#line 102 "a.y"
+    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
+    break;
+
+  case 13:
+#line 103 "a.y"
+    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
+    break;
+
   case 14:
-#line 106 "a.y"
+#line 104 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 15:
-#line 107 "a.y"
+#line 105 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 16:
-#line 108 "a.y"
+#line 106 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 17:
-#line 109 "a.y"
+#line 107 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 18:
-#line 110 "a.y"
+#line 108 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 19:
-#line 111 "a.y"
+#line 109 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 20:
-#line 112 "a.y"
+#line 110 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 21:
-#line 113 "a.y"
+#line 111 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 22:
-#line 114 "a.y"
+#line 112 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 23:
-#line 115 "a.y"
+#line 113 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 24:
-#line 116 "a.y"
+#line 114 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 25:
-#line 117 "a.y"
+#line 115 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 26:
-#line 118 "a.y"
+#line 116 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 27:
-#line 119 "a.y"
+#line 117 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 28:
-#line 120 "a.y"
+#line 118 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 29:
-#line 121 "a.y"
+#line 119 "a.y"
     { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
     break;
 
   case 30:
 #line 122 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 31:
-#line 123 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 32:
-#line 126 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 33:
-#line 131 "a.y"
+  case 31:
+#line 127 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 34:
-#line 138 "a.y"
+  case 32:
+#line 134 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 35:
-#line 145 "a.y"
+  case 33:
+#line 141 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 36:
-#line 152 "a.y"
+  case 34:
+#line 148 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 37:
-#line 157 "a.y"
+  case 35:
+#line 153 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 38:
-#line 164 "a.y"
+  case 36:
+#line 160 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 39:
-#line 169 "a.y"
+  case 37:
+#line 165 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 40:
-#line 176 "a.y"
+  case 38:
+#line 172 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 41:
-#line 181 "a.y"
+  case 39:
+#line 177 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 42:
-#line 186 "a.y"
+  case 40:
+#line 182 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 43:
-#line 193 "a.y"
+  case 41:
+#line 189 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1915,41 +1907,43 @@ yyreduce:
        }
     break;
 
-  case 44:
-#line 201 "a.y"
+  case 42:
+#line 197 "a.y"
     {
+               settext((yyvsp[(1) - (3)].addr).sym);
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 45:
-#line 206 "a.y"
+  case 43:
+#line 203 "a.y"
     {
+               settext((yyvsp[(1) - (5)].addr).sym);
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
                (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
        }
     break;
 
-  case 46:
-#line 214 "a.y"
+  case 44:
+#line 212 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 47:
-#line 219 "a.y"
+  case 45:
+#line 217 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 48:
-#line 224 "a.y"
+  case 46:
+#line 222 "a.y"
     {
                (yyval.addr2).from = nullgen;
                (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
@@ -1958,16 +1952,16 @@ yyreduce:
        }
     break;
 
-  case 51:
-#line 237 "a.y"
+  case 49:
+#line 235 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 52:
-#line 242 "a.y"
+  case 50:
+#line 240 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
@@ -1977,16 +1971,16 @@ yyreduce:
        }
     break;
 
-  case 53:
-#line 252 "a.y"
+  case 51:
+#line 250 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 54:
-#line 257 "a.y"
+  case 52:
+#line 255 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
@@ -1996,40 +1990,40 @@ yyreduce:
        }
     break;
 
-  case 55:
-#line 267 "a.y"
+  case 53:
+#line 265 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 56:
-#line 272 "a.y"
+  case 54:
+#line 270 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
                (yyval.addr2).to = nullgen;
        }
     break;
 
-  case 57:
-#line 277 "a.y"
+  case 55:
+#line 275 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 58:
-#line 284 "a.y"
+  case 56:
+#line 282 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
        }
     break;
 
-  case 59:
-#line 289 "a.y"
+  case 57:
+#line 287 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -2037,8 +2031,8 @@ yyreduce:
        }
     break;
 
-  case 60:
-#line 297 "a.y"
+  case 58:
+#line 295 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
@@ -2046,8 +2040,8 @@ yyreduce:
        }
     break;
 
-  case 61:
-#line 305 "a.y"
+  case 59:
+#line 303 "a.y"
     {
                (yyval.addr2).from = (yyvsp[(3) - (5)].addr);
                (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
@@ -2057,8 +2051,8 @@ yyreduce:
        }
     break;
 
-  case 62:
-#line 315 "a.y"
+  case 60:
+#line 313 "a.y"
     {
                if((yyvsp[(1) - (3)].addr).type != D_CONST || (yyvsp[(3) - (3)].addr).type != D_CONST)
                        yyerror("arguments to PCDATA must be integer constants");
@@ -2067,8 +2061,8 @@ yyreduce:
        }
     break;
 
-  case 63:
-#line 324 "a.y"
+  case 61:
+#line 322 "a.y"
     {
                if((yyvsp[(1) - (3)].addr).type != D_CONST)
                        yyerror("index for FUNCDATA must be integer constant");
@@ -2079,22 +2073,22 @@ yyreduce:
        }
     break;
 
-  case 68:
-#line 341 "a.y"
+  case 66:
+#line 339 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 69:
-#line 345 "a.y"
+  case 67:
+#line 343 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
        }
     break;
 
-  case 75:
-#line 358 "a.y"
+  case 73:
+#line 356 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_BRANCH;
@@ -2102,76 +2096,68 @@ yyreduce:
        }
     break;
 
-  case 76:
-#line 364 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               if(pass == 2)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name);
-               (yyval.addr).type = D_BRANCH;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 77:
-#line 372 "a.y"
+  case 74:
+#line 362 "a.y"
     {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
                (yyval.addr) = nullgen;
+               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
+                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
                (yyval.addr).type = D_BRANCH;
                (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 78:
-#line 380 "a.y"
+  case 75:
+#line 373 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 79:
-#line 385 "a.y"
+  case 76:
+#line 378 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 80:
-#line 390 "a.y"
+  case 77:
+#line 383 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 81:
-#line 395 "a.y"
+  case 78:
+#line 388 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 82:
-#line 400 "a.y"
+  case 79:
+#line 393 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SP;
        }
     break;
 
-  case 83:
-#line 405 "a.y"
+  case 80:
+#line 398 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(1) - (1)].lval);
        }
     break;
 
-  case 84:
-#line 412 "a.y"
+  case 81:
+#line 405 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_CONST;
@@ -2179,8 +2165,8 @@ yyreduce:
        }
     break;
 
-  case 85:
-#line 418 "a.y"
+  case 82:
+#line 411 "a.y"
     {
                (yyval.addr) = (yyvsp[(2) - (2)].addr);
                (yyval.addr).index = (yyvsp[(2) - (2)].addr).type;
@@ -2193,8 +2179,8 @@ yyreduce:
        }
     break;
 
-  case 86:
-#line 429 "a.y"
+  case 83:
+#line 422 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_SCONST;
@@ -2202,8 +2188,8 @@ yyreduce:
        }
     break;
 
-  case 87:
-#line 435 "a.y"
+  case 84:
+#line 428 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2211,8 +2197,8 @@ yyreduce:
        }
     break;
 
-  case 88:
-#line 441 "a.y"
+  case 85:
+#line 434 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2220,8 +2206,8 @@ yyreduce:
        }
     break;
 
-  case 89:
-#line 447 "a.y"
+  case 86:
+#line 440 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2229,8 +2215,8 @@ yyreduce:
        }
     break;
 
-  case 90:
-#line 453 "a.y"
+  case 87:
+#line 446 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_FCONST;
@@ -2238,8 +2224,8 @@ yyreduce:
        }
     break;
 
-  case 91:
-#line 461 "a.y"
+  case 88:
+#line 454 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_CONST2;
@@ -2248,40 +2234,40 @@ yyreduce:
        }
     break;
 
-  case 92:
-#line 470 "a.y"
+  case 89:
+#line 463 "a.y"
     {
                (yyval.con2).v1 = (yyvsp[(1) - (1)].lval);
                (yyval.con2).v2 = ArgsSizeUnknown;
        }
     break;
 
-  case 93:
-#line 475 "a.y"
+  case 90:
+#line 468 "a.y"
     {
                (yyval.con2).v1 = -(yyvsp[(2) - (2)].lval);
                (yyval.con2).v2 = ArgsSizeUnknown;
        }
     break;
 
-  case 94:
-#line 480 "a.y"
+  case 91:
+#line 473 "a.y"
     {
                (yyval.con2).v1 = (yyvsp[(1) - (3)].lval);
                (yyval.con2).v2 = (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 95:
-#line 485 "a.y"
+  case 92:
+#line 478 "a.y"
     {
                (yyval.con2).v1 = -(yyvsp[(2) - (4)].lval);
                (yyval.con2).v2 = (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 98:
-#line 496 "a.y"
+  case 95:
+#line 489 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_NONE;
@@ -2289,8 +2275,8 @@ yyreduce:
        }
     break;
 
-  case 99:
-#line 502 "a.y"
+  case 96:
+#line 495 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2298,8 +2284,8 @@ yyreduce:
        }
     break;
 
-  case 100:
-#line 508 "a.y"
+  case 97:
+#line 501 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_SP;
@@ -2307,8 +2293,8 @@ yyreduce:
        }
     break;
 
-  case 101:
-#line 514 "a.y"
+  case 98:
+#line 507 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_NONE;
@@ -2319,8 +2305,8 @@ yyreduce:
        }
     break;
 
-  case 102:
-#line 523 "a.y"
+  case 99:
+#line 516 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2331,8 +2317,8 @@ yyreduce:
        }
     break;
 
-  case 103:
-#line 532 "a.y"
+  case 100:
+#line 525 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2343,24 +2329,24 @@ yyreduce:
        }
     break;
 
-  case 104:
-#line 541 "a.y"
+  case 101:
+#line 534 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(2) - (3)].lval);
        }
     break;
 
-  case 105:
-#line 546 "a.y"
+  case 102:
+#line 539 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_SP;
        }
     break;
 
-  case 106:
-#line 551 "a.y"
+  case 103:
+#line 544 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2368,8 +2354,8 @@ yyreduce:
        }
     break;
 
-  case 107:
-#line 557 "a.y"
+  case 104:
+#line 550 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+D_NONE;
@@ -2379,8 +2365,8 @@ yyreduce:
        }
     break;
 
-  case 108:
-#line 565 "a.y"
+  case 105:
+#line 558 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2390,15 +2376,15 @@ yyreduce:
        }
     break;
 
-  case 109:
-#line 575 "a.y"
+  case 106:
+#line 568 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (1)].addr);
        }
     break;
 
-  case 110:
-#line 579 "a.y"
+  case 107:
+#line 572 "a.y"
     {
                (yyval.addr) = (yyvsp[(1) - (6)].addr);
                (yyval.addr).index = (yyvsp[(3) - (6)].lval);
@@ -2407,8 +2393,8 @@ yyreduce:
        }
     break;
 
-  case 111:
-#line 588 "a.y"
+  case 108:
+#line 581 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = (yyvsp[(4) - (5)].lval);
@@ -2417,8 +2403,8 @@ yyreduce:
        }
     break;
 
-  case 112:
-#line 595 "a.y"
+  case 109:
+#line 588 "a.y"
     {
                (yyval.addr) = nullgen;
                (yyval.addr).type = D_STATIC;
@@ -2427,134 +2413,134 @@ yyreduce:
        }
     break;
 
-  case 113:
-#line 603 "a.y"
+  case 110:
+#line 596 "a.y"
     {
                (yyval.lval) = 0;
        }
     break;
 
-  case 114:
-#line 607 "a.y"
+  case 111:
+#line 600 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 115:
-#line 611 "a.y"
+  case 112:
+#line 604 "a.y"
     {
                (yyval.lval) = -(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 117:
-#line 618 "a.y"
+  case 114:
+#line 611 "a.y"
     {
                (yyval.lval) = D_AUTO;
        }
     break;
 
-  case 120:
-#line 626 "a.y"
+  case 117:
+#line 619 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
        }
     break;
 
-  case 121:
-#line 630 "a.y"
+  case 118:
+#line 623 "a.y"
     {
                (yyval.lval) = -(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 122:
-#line 634 "a.y"
+  case 119:
+#line 627 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 123:
-#line 638 "a.y"
+  case 120:
+#line 631 "a.y"
     {
                (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
        }
     break;
 
-  case 124:
-#line 642 "a.y"
+  case 121:
+#line 635 "a.y"
     {
                (yyval.lval) = (yyvsp[(2) - (3)].lval);
        }
     break;
 
-  case 126:
-#line 649 "a.y"
+  case 123:
+#line 642 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 127:
-#line 653 "a.y"
+  case 124:
+#line 646 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 128:
-#line 657 "a.y"
+  case 125:
+#line 650 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 129:
-#line 661 "a.y"
+  case 126:
+#line 654 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 130:
-#line 665 "a.y"
+  case 127:
+#line 658 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 131:
-#line 669 "a.y"
+  case 128:
+#line 662 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 132:
-#line 673 "a.y"
+  case 129:
+#line 666 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
        }
     break;
 
-  case 133:
-#line 677 "a.y"
+  case 130:
+#line 670 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 134:
-#line 681 "a.y"
+  case 131:
+#line 674 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
        }
     break;
 
-  case 135:
-#line 685 "a.y"
+  case 132:
+#line 678 "a.y"
     {
                (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
        }
@@ -2562,7 +2548,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 2566 "y.tab.c"
+#line 2552 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/src/cmd/8c/Makefile b/src/cmd/8c/Makefile
deleted file mode 100644 (file)
index 3f528d7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c
deleted file mode 100644 (file)
index 87e8fda..0000000
+++ /dev/null
@@ -1,1939 +0,0 @@
-// Inferno utils/8c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/cgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-/* ,x/^(print|prtree)\(/i/\/\/ */
-
-void
-cgen(Node *n, Node *nn)
-{
-       Node *l, *r, *t;
-       Prog *p1;
-       Node nod, nod1, nod2, nod3, nod4;
-       int o, hardleft;
-       int32 v, curs;
-       vlong c;
-
-       if(debug['g']) {
-               prtree(nn, "cgen lhs");
-               prtree(n, "cgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
-               sugen(n, nn, n->type->width);
-               return;
-       }
-       l = n->left;
-       r = n->right;
-       o = n->op;
-
-       if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
-               gmove(n, nn);
-               return;
-       }
-
-       if(n->addable >= INDEXED) {
-               if(nn == Z) {
-                       switch(o) {
-                       default:
-                               nullwarn(Z, Z);
-                               break;
-                       case OINDEX:
-                               nullwarn(l, r);
-                               break;
-                       }
-                       return;
-               }
-               gmove(n, nn);
-               return;
-       }
-       curs = cursafe;
-
-       if(l->complex >= FNX)
-       if(r != Z && r->complex >= FNX)
-       switch(o) {
-       default:
-               if(cond(o) && typesuv[l->type->etype])
-                       break;
-
-               regret(&nod, r, 0, 0);
-               cgen(r, &nod);
-
-               regsalloc(&nod1, r);
-               gmove(&nod, &nod1);
-
-               regfree(&nod);
-               nod = *n;
-               nod.right = &nod1;
-
-               cgen(&nod, nn);
-               return;
-
-       case OFUNC:
-       case OCOMMA:
-       case OANDAND:
-       case OOROR:
-       case OCOND:
-       case ODOT:
-               break;
-       }
-
-       hardleft = l->addable < INDEXED || l->complex >= FNX;
-       switch(o) {
-       default:
-               diag(n, "unknown op in cgen: %O", o);
-               break;
-
-       case ONEG:
-       case OCOM:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               regalloc(&nod, l, nn);
-               cgen(l, &nod);
-               gopcode(o, n->type, Z, &nod);
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       case OAS:
-               if(typefd[n->type->etype]) {
-                       cgen(r, &fregnode0);
-                       if(nn != Z)
-                               gins(AFMOVD, &fregnode0, &fregnode0);
-                       if(l->addable < INDEXED) {
-                               reglcgen(&nod, l, Z);
-                               gmove(&fregnode0, &nod);
-                               regfree(&nod);
-                       } else
-                               gmove(&fregnode0, l);
-                       if(nn != Z)
-                               gmove(&fregnode0, nn);
-                       return;
-               }
-               if(l->op == OBIT)
-                       goto bitas;
-               if(!hardleft) {
-                       if(nn != Z || r->addable < INDEXED) {
-                               if(r->complex >= FNX && nn == Z)
-                                       regret(&nod, r, 0, 0);
-                               else
-                                       regalloc(&nod, r, nn);
-                               cgen(r, &nod);
-                               gmove(&nod, l);
-                               if(nn != Z)
-                                       gmove(&nod, nn);
-                               regfree(&nod);
-                       } else
-                               gmove(r, l);
-                       break;
-               }
-               if(l->complex >= r->complex) {
-                       if(l->op == OINDEX && r->op == OCONST) {
-                               gmove(r, l);
-                               break;
-                       }
-                       reglcgen(&nod1, l, Z);
-                       if(r->addable >= INDEXED) {
-                               gmove(r, &nod1);
-                               if(nn != Z)
-                                       gmove(r, nn);
-                               regfree(&nod1);
-                               break;
-                       }
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-               } else {
-                       regalloc(&nod, r, nn);
-                       cgen(r, &nod);
-                       reglcgen(&nod1, l, Z);
-               }
-               gmove(&nod, &nod1);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       bitas:
-               n = l->left;
-               regalloc(&nod, r, nn);
-               if(l->complex >= r->complex) {
-                       reglcgen(&nod1, n, Z);
-                       cgen(r, &nod);
-               } else {
-                       cgen(r, &nod);
-                       reglcgen(&nod1, n, Z);
-               }
-               regalloc(&nod2, n, Z);
-               gmove(&nod1, &nod2);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OBIT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               bitload(n, &nod, Z, Z, nn);
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(r->op == OCONST) {
-                       if(r->vconst == 0) {
-                               cgen(l, nn);
-                               break;
-                       }
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(o == OASHL && r->vconst == 1)
-                               gopcode(OADD, n->type, &nod, &nod);
-                       else
-                               gopcode(o, n->type, r, &nod);
-                       gmove(&nod, nn);
-                       regfree(&nod);
-                       break;
-               }
-
-               /*
-                * get nod to be D_CX
-                */
-               if(nodreg(&nod, nn, D_CX)) {
-                       regsalloc(&nod1, n);
-                       gmove(&nod, &nod1);
-                       cgen(n, &nod);          /* probably a bug */
-                       gmove(&nod, nn);
-                       gmove(&nod1, &nod);
-                       break;
-               }
-               reg[D_CX]++;
-               if(nn->op == OREGISTER && nn->reg == D_CX)
-                       regalloc(&nod1, l, Z);
-               else
-                       regalloc(&nod1, l, nn);
-               if(r->complex >= l->complex) {
-                       cgen(r, &nod);
-                       cgen(l, &nod1);
-               } else {
-                       cgen(l, &nod1);
-                       cgen(r, &nod);
-               }
-               gopcode(o, n->type, &nod, &nod1);
-               gmove(&nod1, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OADD:
-       case OSUB:
-       case OOR:
-       case OXOR:
-       case OAND:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(typefd[n->type->etype])
-                       goto fop;
-               if(r->op == OCONST) {
-                       if(r->vconst == 0 && o != OAND) {
-                               cgen(l, 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;
-                       if(c > 0 && c <= 3) {
-                               if(l->left->complex >= r->complex) {
-                                       regalloc(&nod, l->left, nn);
-                                       cgen(l->left, &nod);
-                                       if(r->addable < INDEXED) {
-                                               regalloc(&nod1, r, Z);
-                                               cgen(r, &nod1);
-                                               genmuladd(&nod, &nod, 1 << c, &nod1);
-                                               regfree(&nod1);
-                                       }
-                                       else
-                                               genmuladd(&nod, &nod, 1 << c, r);
-                               }
-                               else {
-                                       regalloc(&nod, r, nn);
-                                       cgen(r, &nod);
-                                       regalloc(&nod1, l->left, Z);
-                                       cgen(l->left, &nod1);
-                                       genmuladd(&nod, &nod1, 1 << c, &nod);
-                                       regfree(&nod1);
-                               }
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               break;
-                       }
-               }
-               if(r->addable >= INDEXED) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       gopcode(o, n->type, r, &nod);
-                       gmove(&nod, nn);
-                       regfree(&nod);
-                       break;
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       regalloc(&nod1, r, Z);
-                       cgen(r, &nod1);
-                       gopcode(o, n->type, &nod1, &nod);
-               } else {
-                       regalloc(&nod1, r, nn);
-                       cgen(r, &nod1);
-                       regalloc(&nod, l, Z);
-                       cgen(l, &nod);
-                       gopcode(o, n->type, &nod1, &nod);
-               }
-               gmove(&nod, nn);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OLMOD:
-       case OMOD:
-       case OLMUL:
-       case OLDIV:
-       case OMUL:
-       case ODIV:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               if(typefd[n->type->etype])
-                       goto fop;
-               if(r->op == OCONST) {
-                       SET(v);
-                       switch(o) {
-                       case ODIV:
-                       case OMOD:
-                               c = r->vconst;
-                               if(c < 0)
-                                       c = -c;
-                               v = xlog2(c);
-                               if(v < 0)
-                                       break;
-                               /* fall thru */
-                       case OMUL:
-                       case OLMUL:
-                               regalloc(&nod, l, nn);
-                               cgen(l, &nod);
-                               switch(o) {
-                               case OMUL:
-                               case OLMUL:
-                                       mulgen(n->type, r, &nod);
-                                       break;
-                               case ODIV:
-                                       sdiv2(r->vconst, v, l, &nod);
-                                       break;
-                               case OMOD:
-                                       smod2(r->vconst, v, l, &nod);
-                                       break;
-                               }
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               goto done;
-                       case OLDIV:
-                               c = r->vconst;
-                               if((c & 0x80000000) == 0)
-                                       break;
-                               regalloc(&nod1, l, Z);
-                               cgen(l, &nod1);
-                               regalloc(&nod, l, nn);
-                               zeroregm(&nod);
-                               gins(ACMPL, &nod1, nodconst(c));
-                               gins(ASBBL, nodconst(-1), &nod);
-                               regfree(&nod1);
-                               gmove(&nod, nn);
-                               regfree(&nod);
-                               goto done;
-                       }
-               }
-
-               if(o == OMUL || o == OLMUL) {
-                       if(l->addable >= INDEXED) {
-                               t = l;
-                               l = r;
-                               r = t;
-                       }
-                       reg[D_DX]++; // for gopcode case OMUL
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(r->addable < INDEXED) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               gopcode(OMUL, n->type, &nod1, &nod);
-                               regfree(&nod1);
-                       }else
-                               gopcode(OMUL, n->type, r, &nod);        /* addressible */
-                       gmove(&nod, nn);
-                       regfree(&nod);
-                       reg[D_DX]--;
-                       break;
-               }
-
-               /*
-                * get nod to be D_AX
-                * get nod1 to be D_DX
-                */
-               if(nodreg(&nod, nn, D_AX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod, &nod2);
-                       v = reg[D_AX];
-                       reg[D_AX] = 0;
-
-                       if(isreg(l, D_AX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_AX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod);
-                       reg[D_AX] = v;
-                       break;
-               }
-               if(nodreg(&nod1, nn, D_DX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod1, &nod2);
-                       v = reg[D_DX];
-                       reg[D_DX] = 0;
-
-                       if(isreg(l, D_DX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_DX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod1);
-                       reg[D_DX] = v;
-                       break;
-               }
-               reg[D_AX]++;
-
-               if(r->op == OCONST && (o == ODIV || o == OLDIV)) {
-                       reg[D_DX]++;
-                       if(l->addable < INDEXED) {
-                               regalloc(&nod2, l, Z);
-                               cgen(l, &nod2);
-                               l = &nod2;
-                       }
-                       if(o == ODIV)
-                               sdivgen(l, r, &nod, &nod1);
-                       else
-                               udivgen(l, r, &nod, &nod1);
-                       gmove(&nod1, nn);
-                       if(l == &nod2)
-                               regfree(l);
-                       goto freeaxdx;
-               }
-
-               if(l->complex >= r->complex) {
-                       cgen(l, &nod);
-                       reg[D_DX]++;
-                       if(o == ODIV || o == OMOD)
-                               gins(ACDQ, Z, Z);
-                       if(o == OLDIV || o == OLMOD)
-                               zeroregm(&nod1);
-                       if(r->addable < INDEXED || r->op == OCONST) {
-                               regsalloc(&nod3, r);
-                               cgen(r, &nod3);
-                               gopcode(o, n->type, &nod3, Z);
-                       } else
-                               gopcode(o, n->type, r, Z);
-               } else {
-                       regsalloc(&nod3, r);
-                       cgen(r, &nod3);
-                       cgen(l, &nod);
-                       reg[D_DX]++;
-                       if(o == ODIV || o == OMOD)
-                               gins(ACDQ, Z, Z);
-                       if(o == OLDIV || o == OLMOD)
-                               zeroregm(&nod1);
-                       gopcode(o, n->type, &nod3, Z);
-               }
-               if(o == OMOD || o == OLMOD)
-                       gmove(&nod1, nn);
-               else
-                       gmove(&nod, nn);
-       freeaxdx:
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       case OASLSHR:
-       case OASASHL:
-       case OASASHR:
-               if(r->op == OCONST)
-                       goto asand;
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(typefd[n->type->etype])
-                       goto asfop;
-
-               /*
-                * get nod to be D_CX
-                */
-               if(nodreg(&nod, nn, D_CX)) {
-                       regsalloc(&nod1, n);
-                       gmove(&nod, &nod1);
-                       cgen(n, &nod);
-                       if(nn != Z)
-                               gmove(&nod, nn);
-                       gmove(&nod1, &nod);
-                       break;
-               }
-               reg[D_CX]++;
-
-               if(r->complex >= l->complex) {
-                       cgen(r, &nod);
-                       if(hardleft)
-                               reglcgen(&nod1, l, Z);
-                       else
-                               nod1 = *l;
-               } else {
-                       if(hardleft)
-                               reglcgen(&nod1, l, Z);
-                       else
-                               nod1 = *l;
-                       cgen(r, &nod);
-               }
-
-               gopcode(o, l->type, &nod, &nod1);
-               regfree(&nod);
-               if(nn != Z)
-                       gmove(&nod1, nn);
-               if(hardleft)
-                       regfree(&nod1);
-               break;
-
-       case OASAND:
-       case OASADD:
-       case OASSUB:
-       case OASXOR:
-       case OASOR:
-       asand:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(typefd[n->type->etype]||typefd[r->type->etype])
-                       goto asfop;
-               if(l->complex >= r->complex) {
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       if(r->op != OCONST) {
-                               regalloc(&nod1, r, nn);
-                               cgen(r, &nod1);
-                               gopcode(o, l->type, &nod1, &nod);
-                               regfree(&nod1);
-                       } else
-                               gopcode(o, l->type, r, &nod);
-               } else {
-                       regalloc(&nod1, r, nn);
-                       cgen(r, &nod1);
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       gopcode(o, l->type, &nod1, &nod);
-                       regfree(&nod1);
-               }
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       case OASLMUL:
-       case OASLDIV:
-       case OASLMOD:
-       case OASMUL:
-       case OASDIV:
-       case OASMOD:
-               if(l->op == OBIT)
-                       goto asbitop;
-               if(typefd[n->type->etype]||typefd[r->type->etype])
-                       goto asfop;
-               if(r->op == OCONST) {
-                       SET(v);
-                       switch(o) {
-                       case OASDIV:
-                       case OASMOD:
-                               c = r->vconst;
-                               if(c < 0)
-                                       c = -c;
-                               v = xlog2(c);
-                               if(v < 0)
-                                       break;
-                               /* fall thru */
-                       case OASMUL:
-                       case OASLMUL:
-                               if(hardleft)
-                                       reglcgen(&nod2, l, Z);
-                               else
-                                       nod2 = *l;
-                               regalloc(&nod, l, nn);
-                               cgen(&nod2, &nod);
-                               switch(o) {
-                               case OASMUL:
-                               case OASLMUL:
-                                       mulgen(n->type, r, &nod);
-                                       break;
-                               case OASDIV:
-                                       sdiv2(r->vconst, v, l, &nod);
-                                       break;
-                               case OASMOD:
-                                       smod2(r->vconst, v, l, &nod);
-                                       break;
-                               }
-                       havev:
-                               gmove(&nod, &nod2);
-                               if(nn != Z)
-                                       gmove(&nod, nn);
-                               if(hardleft)
-                                       regfree(&nod2);
-                               regfree(&nod);
-                               goto done;
-                       case OASLDIV:
-                               c = r->vconst;
-                               if((c & 0x80000000) == 0)
-                                       break;
-                               if(hardleft)
-                                       reglcgen(&nod2, l, Z);
-                               else
-                                       nod2 = *l;
-                               regalloc(&nod1, l, nn);
-                               cgen(&nod2, &nod1);
-                               regalloc(&nod, l, nn);
-                               zeroregm(&nod);
-                               gins(ACMPL, &nod1, nodconst(c));
-                               gins(ASBBL, nodconst(-1), &nod);
-                               regfree(&nod1);
-                               goto havev;
-                       }
-               }
-
-               if(o == OASMUL) {
-                       /* should favour AX */
-                       regalloc(&nod, l, nn);
-                       if(r->complex >= FNX) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               r = &nod1;
-                       }
-                       if(hardleft)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       cgen(&nod2, &nod);
-                       if(r->addable < INDEXED) {
-                               if(r->complex < FNX) {
-                                       regalloc(&nod1, r, Z);
-                                       cgen(r, &nod1);
-                               }
-                               gopcode(OASMUL, n->type, &nod1, &nod);
-                               regfree(&nod1);
-                       }
-                       else
-                               gopcode(OASMUL, n->type, r, &nod);
-                       if(r == &nod1)
-                               regfree(r);
-                       gmove(&nod, &nod2);
-                       if(nn != Z)
-                               gmove(&nod, nn);
-                       regfree(&nod);
-                       if(hardleft)
-                               regfree(&nod2);
-                       break;
-               }
-
-               /*
-                * get nod to be D_AX
-                * get nod1 to be D_DX
-                */
-               if(nodreg(&nod, nn, D_AX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod, &nod2);
-                       v = reg[D_AX];
-                       reg[D_AX] = 0;
-
-                       if(isreg(l, D_AX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_AX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod);
-                       reg[D_AX] = v;
-                       break;
-               }
-               if(nodreg(&nod1, nn, D_DX)) {
-                       regsalloc(&nod2, n);
-                       gmove(&nod1, &nod2);
-                       v = reg[D_DX];
-                       reg[D_DX] = 0;
-
-                       if(isreg(l, D_DX)) {
-                               nod3 = *n;
-                               nod3.left = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                       if(isreg(r, D_DX)) {
-                               nod3 = *n;
-                               nod3.right = &nod2;
-                               cgen(&nod3, nn);
-                       } else
-                               cgen(n, nn);
-
-                       gmove(&nod2, &nod1);
-                       reg[D_DX] = v;
-                       break;
-               }
-               reg[D_AX]++;
-               reg[D_DX]++;
-
-               if(l->complex >= r->complex) {
-                       if(hardleft)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       cgen(&nod2, &nod);
-                       if(r->op == OCONST) {
-                               switch(o) {
-                               case OASDIV:
-                                       sdivgen(&nod2, r, &nod, &nod1);
-                                       goto divdone;
-                               case OASLDIV:
-                                       udivgen(&nod2, r, &nod, &nod1);
-                               divdone:
-                                       gmove(&nod1, &nod2);
-                                       if(nn != Z)
-                                               gmove(&nod1, nn);
-                                       goto freelxaxdx;
-                               }
-                       }
-                       if(o == OASDIV || o == OASMOD)
-                               gins(ACDQ, Z, Z);
-                       if(o == OASLDIV || o == OASLMOD)
-                               zeroregm(&nod1);
-                       if(r->addable < INDEXED || r->op == OCONST ||
-                          !typeil[r->type->etype]) {
-                               regalloc(&nod3, r, Z);
-                               cgen(r, &nod3);
-                               gopcode(o, l->type, &nod3, Z);
-                               regfree(&nod3);
-                       } else
-                               gopcode(o, n->type, r, Z);
-               } else {
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-                       if(hardleft)
-                               reglcgen(&nod2, l, Z);
-                       else
-                               nod2 = *l;
-                       cgen(&nod2, &nod);
-                       if(o == OASDIV || o == OASMOD)
-                               gins(ACDQ, Z, Z);
-                       if(o == OASLDIV || o == OASLMOD)
-                               zeroregm(&nod1);
-                       gopcode(o, l->type, &nod3, Z);
-                       regfree(&nod3);
-               }
-               if(o == OASMOD || o == OASLMOD) {
-                       gmove(&nod1, &nod2);
-                       if(nn != Z)
-                               gmove(&nod1, nn);
-               } else {
-                       gmove(&nod, &nod2);
-                       if(nn != Z)
-                               gmove(&nod, nn);
-               }
-       freelxaxdx:
-               if(hardleft)
-                       regfree(&nod2);
-               regfree(&nod);
-               regfree(&nod1);
-               break;
-
-       fop:
-               if(l->complex >= r->complex) {
-                       cgen(l, &fregnode0);
-                       if(r->addable < INDEXED) {
-                               cgen(r, &fregnode0);
-                               fgopcode(o, &fregnode0, &fregnode1, 1, 0);
-                       } else
-                               fgopcode(o, r, &fregnode0, 0, 0);
-               } else {
-                       cgen(r, &fregnode0);
-                       if(l->addable < INDEXED) {
-                               cgen(l, &fregnode0);
-                               fgopcode(o, &fregnode0, &fregnode1, 1, 1);
-                       } else
-                               fgopcode(o, l, &fregnode0, 0, 1);
-               }
-               gmove(&fregnode0, nn);
-               break;
-
-       asfop:
-               if(l->complex >= r->complex) {
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-                       cgen(r, &fregnode0);
-               } else {
-                       cgen(r, &fregnode0);
-                       if(hardleft)
-                               reglcgen(&nod, l, Z);
-                       else
-                               nod = *l;
-               }
-               if(!typefd[l->type->etype]) {
-                       gmove(&nod, &fregnode0);
-                       fgopcode(o, &fregnode0, &fregnode1, 1, 1);
-               } else
-                       fgopcode(o, &nod, &fregnode0, 0, 1);
-               if(nn != Z)
-                       gins(AFMOVD, &fregnode0, &fregnode0);
-               gmove(&fregnode0, &nod);
-               if(nn != Z)
-                       gmove(&fregnode0, nn);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       asbitop:
-               regalloc(&nod4, n, nn);
-               if(l->complex >= r->complex) {
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-               } else {
-                       regalloc(&nod3, r, Z);
-                       cgen(r, &nod3);
-                       bitload(l, &nod, &nod1, &nod2, &nod4);
-               }
-               gmove(&nod, &nod4);
-
-               if(typefd[nod3.type->etype])
-                       fgopcode(o, &fregnode0, &fregnode1, 1, 1);
-               else {
-                       Node onod;
-
-                       /* incredible grot ... */
-                       onod = nod3;
-                       onod.op = o;
-                       onod.complex = 2;
-                       onod.addable = 0;
-                       onod.type = tfield;
-                       onod.left = &nod4;
-                       onod.right = &nod3;
-                       cgen(&onod, Z);
-               }
-               regfree(&nod3);
-               gmove(&nod4, &nod);
-               regfree(&nod4);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-
-       case OADDR:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               lcgen(l, nn);
-               break;
-
-       case OFUNC:
-               if(l->complex >= FNX) {
-                       if(l->op != OIND)
-                               diag(n, "bad function call");
-
-                       regret(&nod, l->left, 0, 0);
-                       cgen(l->left, &nod);
-                       regsalloc(&nod1, l->left);
-                       gmove(&nod, &nod1);
-                       regfree(&nod);
-
-                       nod = *n;
-                       nod.left = &nod2;
-                       nod2 = *l;
-                       nod2.left = &nod1;
-                       nod2.complex = 1;
-                       cgen(&nod, nn);
-
-                       return;
-               }
-               gargs(r, &nod, &nod1);
-               if(l->addable < INDEXED) {
-                       reglcgen(&nod, l, nn);
-                       nod.op = OREGISTER;
-                       gopcode(OFUNC, n->type, Z, &nod);
-                       regfree(&nod);
-               } else
-                       gopcode(OFUNC, n->type, Z, l);
-               if(REGARG >= 0 && reg[REGARG])
-                       reg[REGARG]--;
-               regret(&nod, n, l->type, 1); // update maxarg if nothing else
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(nod.op == OREGISTER)
-                       regfree(&nod);
-               if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype])
-                       gins(AFMOVDP, &fregnode0, &fregnode0);
-               break;
-
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               regialloc(&nod, n, nn);
-               r = l;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r)) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       cgen(l, &nod);
-                       nod.xoffset += v;
-                       r->vconst = v;
-               } else
-                       cgen(l, &nod);
-               regind(&nod, n);
-               gmove(&nod, nn);
-               regfree(&nod);
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHI:
-       case OHS:
-               if(nn == Z) {
-                       nullwarn(l, r);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OANDAND:
-       case OOROR:
-               boolgen(n, 1, nn);
-               if(nn == Z)
-                       patch(p, pc);
-               break;
-
-       case ONOT:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               boolgen(n, 1, nn);
-               break;
-
-       case OCOMMA:
-               cgen(l, Z);
-               cgen(r, nn);
-               break;
-
-       case OCAST:
-               if(nn == Z) {
-                       nullwarn(l, Z);
-                       break;
-               }
-               /*
-                * convert from types l->n->nn
-                */
-               if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
-                       /* both null, gen l->nn */
-                       cgen(l, nn);
-                       break;
-               }
-               if(typev[l->type->etype]) {
-                       cgen64(n, nn);
-                       break;
-               }
-               regalloc(&nod, l, nn);
-               cgen(l, &nod);
-               regalloc(&nod1, n, &nod);
-               gmove(&nod, &nod1);
-               gmove(&nod1, nn);
-               regfree(&nod1);
-               regfree(&nod);
-               break;
-
-       case ODOT:
-               sugen(l, nodrat, l->type->width);
-               if(nn == Z)
-                       break;
-               warn(n, "non-interruptable temporary");
-               nod = *nodrat;
-               if(!r || r->op != OCONST) {
-                       diag(n, "DOT and no offset");
-                       break;
-               }
-               nod.xoffset += (int32)r->vconst;
-               nod.type = n->type;
-               cgen(&nod, nn);
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               cgen(r->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               cgen(r->right, nn);
-               patch(p1, pc);
-               break;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPOSTDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-               if(nn == Z)
-                       goto pre;
-
-               if(hardleft)
-                       reglcgen(&nod, l, Z);
-               else
-                       nod = *l;
-
-               if(typefd[n->type->etype])
-                       goto fltinc;
-               gmove(&nod, nn);
-               gopcode(OADD, n->type, nodconst(v), &nod);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       case OPREINC:
-       case OPREDEC:
-               v = 1;
-               if(l->type->etype == TIND)
-                       v = l->type->link->width;
-               if(o == OPREDEC)
-                       v = -v;
-               if(l->op == OBIT)
-                       goto bitinc;
-
-       pre:
-               if(hardleft)
-                       reglcgen(&nod, l, Z);
-               else
-                       nod = *l;
-               if(typefd[n->type->etype])
-                       goto fltinc;
-               gopcode(OADD, n->type, nodconst(v), &nod);
-               if(nn != Z)
-                       gmove(&nod, nn);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       fltinc:
-               gmove(&nod, &fregnode0);
-               if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
-                       gins(AFMOVD, &fregnode0, &fregnode0);
-               gins(AFLD1, Z, Z);
-               if(v < 0)
-                       fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
-               else
-                       fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
-               if(nn != Z && (o == OPREINC || o == OPREDEC))
-                       gins(AFMOVD, &fregnode0, &fregnode0);
-               gmove(&fregnode0, &nod);
-               if(hardleft)
-                       regfree(&nod);
-               break;
-
-       bitinc:
-               if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
-                       bitload(l, &nod, &nod1, &nod2, Z);
-                       gmove(&nod, nn);
-                       gopcode(OADD, tfield, nodconst(v), &nod);
-                       bitstore(l, &nod, &nod1, &nod2, Z);
-                       break;
-               }
-               bitload(l, &nod, &nod1, &nod2, nn);
-               gopcode(OADD, tfield, nodconst(v), &nod);
-               bitstore(l, &nod, &nod1, &nod2, nn);
-               break;
-       }
-done:
-       cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
-       Node *r;
-       int32 v;
-
-       regialloc(t, n, nn);
-       if(n->op == OIND) {
-               r = n->left;
-               while(r->op == OADD)
-                       r = r->right;
-               if(sconst(r)) {
-                       v = r->vconst;
-                       r->vconst = 0;
-                       lcgen(n, t);
-                       t->xoffset += v;
-                       r->vconst = v;
-                       regind(t, n);
-                       return;
-               }
-       }
-       lcgen(n, t);
-       regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
-       Prog *p1;
-       Node nod;
-
-       if(debug['g']) {
-               prtree(nn, "lcgen lhs");
-               prtree(n, "lcgen");
-       }
-       if(n == Z || n->type == T)
-               return;
-       if(nn == Z) {
-               nn = &nod;
-               regalloc(&nod, n, Z);
-       }
-       switch(n->op) {
-       default:
-               if(n->addable < INDEXED) {
-                       diag(n, "unknown op in lcgen: %O", n->op);
-                       break;
-               }
-               gopcode(OADDR, n->type, n, nn);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, n->left);
-               lcgen(n->right, nn);
-               break;
-
-       case OIND:
-               cgen(n->left, nn);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               lcgen(n->right->left, nn);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               lcgen(n->right->right, nn);
-               patch(p1, pc);
-               break;
-       }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
-       if(n->type == T)
-               gbranch(OGOTO);
-       else
-               boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
-       int o;
-       Prog *p1, *p2, *p3;
-       Node *l, *r, nod, nod1;
-       int32 curs;
-
-       if(debug['g']) {
-               prtree(nn, "boolgen lhs");
-               prtree(n, "boolgen");
-       }
-       curs = cursafe;
-       l = n->left;
-       r = n->right;
-       switch(n->op) {
-
-       default:
-               if(typev[n->type->etype]) {
-                       testv(n, true);
-                       goto com;
-               }
-               o = ONE;
-               if(true)
-                       o = OEQ;
-               if(typefd[n->type->etype]) {
-                       if(n->addable < INDEXED) {
-                               cgen(n, &fregnode0);
-                               gins(AFLDZ, Z, Z);
-                               fgopcode(o, &fregnode0, &fregnode1, 1, 1);
-                       } else {
-                               gins(AFLDZ, Z, Z);
-                               fgopcode(o, n, &fregnode0, 0, 1);
-                       }
-                       goto com;
-               }
-               /* bad, 13 is address of external that becomes constant */
-               if(n->addable >= INDEXED && n->addable != 13) {
-                       gopcode(o, n->type, n, nodconst(0));
-                       goto com;
-               }
-               regalloc(&nod, n, nn);
-               cgen(n, &nod);
-               gopcode(o, n->type, &nod, nodconst(0));
-               regfree(&nod);
-               goto com;
-
-       case OCONST:
-               o = vconst(n);
-               if(!true)
-                       o = !o;
-               gbranch(OGOTO);
-               if(o) {
-                       p1 = p;
-                       gbranch(OGOTO);
-                       patch(p1, pc);
-               }
-               goto com;
-
-       case OCOMMA:
-               cgen(l, Z);
-               boolgen(r, true, nn);
-               break;
-
-       case ONOT:
-               boolgen(l, !true, nn);
-               break;
-
-       case OCOND:
-               bcgen(l, 1);
-               p1 = p;
-               bcgen(r->left, true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               bcgen(r->right, !true);
-               patch(p2, pc);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               bcgen(l, true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               patch(p1, pc);
-               gbranch(OGOTO);
-               patch(p2, pc);
-               goto com;
-
-       case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bcgen(l, !true);
-               p1 = p;
-               bcgen(r, !true);
-               p2 = p;
-               gbranch(OGOTO);
-               patch(p1, pc);
-               patch(p2, pc);
-               goto com;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               o = n->op;
-               if(typev[l->type->etype]) {
-                       if(!true)
-                               n->op = comrel[relindex(o)];
-                       cgen64(n, Z);
-                       goto com;
-               }
-               if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
-                       // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
-                       // Jump around instead.
-                       boolgen(n, 0, Z);
-                       p1 = p;
-                       gbranch(OGOTO);
-                       patch(p1, pc);
-                       goto com;
-               }
-               if(true)
-                       o = comrel[relindex(o)];
-               if(l->complex >= FNX && r->complex >= FNX) {
-                       regret(&nod, r, 0, 0);
-                       cgen(r, &nod);
-                       regsalloc(&nod1, r);
-                       gmove(&nod, &nod1);
-                       regfree(&nod);
-                       nod = *n;
-                       nod.right = &nod1;
-                       boolgen(&nod, true, nn);
-                       break;
-               }
-               if(typefd[l->type->etype]) {
-                       if(l->complex >= r->complex) {
-                               cgen(l, &fregnode0);
-                               if(r->addable < INDEXED) {
-                                       cgen(r, &fregnode0);
-                                       o = invrel[relindex(o)];
-                                       fgopcode(o, &fregnode0, &fregnode1, 1, 1);
-                               } else
-                                       fgopcode(o, r, &fregnode0, 0, 1);
-                       } else {
-                               o = invrel[relindex(o)];
-                               cgen(r, &fregnode0);
-                               if(l->addable < INDEXED) {
-                                       cgen(l, &fregnode0);
-                                       o = invrel[relindex(o)];
-                                       fgopcode(o, &fregnode0, &fregnode1, 1, 1);
-                               } else
-                                       fgopcode(o, l, &fregnode0, 0, 1);
-                       }
-                       switch(o) {
-                       case OEQ:
-                               // Already emitted AJEQ; want AJEQ and AJPC.
-                               p1 = p;
-                               gbranch(OGOTO);
-                               p2 = p;
-                               patch(p1, pc);
-                               gins(AJPC, Z, Z);
-                               patch(p2, pc);
-                               break;
-
-                       case ONE:
-                               // Already emitted AJNE; want AJNE or AJPS.
-                               p1 = p;
-                               gins(AJPS, Z, Z);
-                               p2 = p;
-                               gbranch(OGOTO);
-                               p3 = p;
-                               patch(p1, pc);
-                               patch(p2, pc);
-                               gbranch(OGOTO);
-                               patch(p3, pc);
-                               break;
-                       }
-                       goto com;
-               }
-               if(l->op == OCONST) {
-                       o = invrel[relindex(o)];
-                       /* bad, 13 is address of external that becomes constant */
-                       if(r->addable < INDEXED || r->addable == 13) {
-                               regalloc(&nod, r, nn);
-                               cgen(r, &nod);
-                               gopcode(o, l->type, &nod, l);
-                               regfree(&nod);
-                       } else
-                               gopcode(o, l->type, r, l);
-                       goto com;
-               }
-               if(l->complex >= r->complex) {
-                       regalloc(&nod, l, nn);
-                       cgen(l, &nod);
-                       if(r->addable < INDEXED) {
-                               regalloc(&nod1, r, Z);
-                               cgen(r, &nod1);
-                               gopcode(o, l->type, &nod, &nod1);
-                               regfree(&nod1);
-                       } else
-                               gopcode(o, l->type, &nod, r);
-                       regfree(&nod);
-                       goto com;
-               }
-               regalloc(&nod, r, nn);
-               cgen(r, &nod);
-               if(l->addable < INDEXED || l->addable == 13) {
-                       regalloc(&nod1, l, Z);
-                       cgen(l, &nod1);
-                       if(typechlp[l->type->etype])
-                               gopcode(o, types[TINT], &nod1, &nod);
-                       else
-                               gopcode(o, l->type, &nod1, &nod);
-                       regfree(&nod1);
-               } else
-                       gopcode(o, l->type, l, &nod);
-               regfree(&nod);
-
-       com:
-               if(nn != Z) {
-                       p1 = p;
-                       gmove(nodconst(1L), nn);
-                       gbranch(OGOTO);
-                       p2 = p;
-                       patch(p1, pc);
-                       gmove(nodconst(0L), nn);
-                       patch(p2, pc);
-               }
-               break;
-       }
-       cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
-       Prog *p1;
-       Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r;
-       Type *t;
-       int c, v, x;
-
-       if(n == Z || n->type == T)
-               return;
-       if(debug['g']) {
-               prtree(nn, "sugen lhs");
-               prtree(n, "sugen");
-       }
-       if(nn == nodrat)
-               if(w > nrathole)
-                       nrathole = w;
-       switch(n->op) {
-       case OIND:
-               if(nn == Z) {
-                       nullwarn(n->left, Z);
-                       break;
-               }
-
-       default:
-               goto copy;
-
-       case OCONST:
-               if(n->type && typev[n->type->etype]) {
-                       if(nn == Z) {
-                               nullwarn(n->left, Z);
-                               break;
-                       }
-
-                       if(nn->op == OREGPAIR) {
-                               loadpair(n, nn);
-                               break;
-                       }
-                       else if(!vaddr(nn, 0)) {
-                               t = nn->type;
-                               nn->type = types[TLONG];
-                               reglcgen(&nod1, nn, Z);
-                               nn->type = t;
-
-                               gmove(lo64(n), &nod1);
-                               nod1.xoffset += SZ_LONG;
-                               gmove(hi64(n), &nod1);
-                               regfree(&nod1);
-                       }
-                       else {
-                               gins(AMOVL, lo64(n), nn);
-                               nn->xoffset += SZ_LONG;
-                               gins(AMOVL, hi64(n), nn);
-                               nn->xoffset -= SZ_LONG;
-                               break;
-                       }
-                       break;
-               }
-               goto copy;
-
-       case ODOT:
-               l = n->left;
-               sugen(l, nodrat, l->type->width);
-               if(nn == Z)
-                       break;
-               warn(n, "non-interruptable temporary");
-               nod1 = *nodrat;
-               r = n->right;
-               if(!r || r->op != OCONST) {
-                       diag(n, "DOT and no offset");
-                       break;
-               }
-               nod1.xoffset += (int32)r->vconst;
-               nod1.type = n->type;
-               sugen(&nod1, nn, w);
-               break;
-
-       case OSTRUCT:
-               /*
-                * rewrite so lhs has no fn call
-                */
-               if(nn != Z && side(nn)) {
-                       nod1 = *n;
-                       nod1.type = typ(TIND, n->type);
-                       regret(&nod2, &nod1, 0, 0);
-                       lcgen(nn, &nod2);
-                       regsalloc(&nod0, &nod1);
-                       cgen(&nod2, &nod0);
-                       regfree(&nod2);
-
-                       nod1 = *n;
-                       nod1.op = OIND;
-                       nod1.left = &nod0;
-                       nod1.right = Z;
-                       nod1.complex = 1;
-
-                       sugen(n, &nod1, w);
-                       return;
-               }
-
-               r = n->left;
-               for(t = n->type->link; t != T; t = t->down) {
-                       l = r;
-                       if(r->op == OLIST) {
-                               l = r->left;
-                               r = r->right;
-                       }
-                       if(nn == Z) {
-                               cgen(l, nn);
-                               continue;
-                       }
-                       /*
-                        * hand craft *(&nn + o) = l
-                        */
-                       nod0 = znode;
-                       nod0.op = OAS;
-                       nod0.type = t;
-                       nod0.left = &nod1;
-                       nod0.right = nil;
-
-                       nod1 = znode;
-                       nod1.op = OIND;
-                       nod1.type = t;
-                       nod1.left = &nod2;
-
-                       nod2 = znode;
-                       nod2.op = OADD;
-                       nod2.type = typ(TIND, t);
-                       nod2.left = &nod3;
-                       nod2.right = &nod4;
-
-                       nod3 = znode;
-                       nod3.op = OADDR;
-                       nod3.type = nod2.type;
-                       nod3.left = nn;
-
-                       nod4 = znode;
-                       nod4.op = OCONST;
-                       nod4.type = nod2.type;
-                       nod4.vconst = t->offset;
-
-                       ccom(&nod0);
-                       acom(&nod0);
-                       xcom(&nod0);
-                       nod0.addable = 0;
-                       nod0.right = l;
-
-                       // prtree(&nod0, "hand craft");
-                       cgen(&nod0, Z);
-               }
-               break;
-
-       case OAS:
-               if(nn == Z) {
-                       if(n->addable < INDEXED)
-                               sugen(n->right, n->left, w);
-                       break;
-               }
-
-               sugen(n->right, nodrat, w);
-               warn(n, "non-interruptable temporary");
-               sugen(nodrat, n->left, w);
-               sugen(nodrat, nn, w);
-               break;
-
-       case OFUNC:
-               if(!hasdotdotdot(n->left->type)) {
-                       cgen(n, Z);
-                       if(nn != Z) {
-                               curarg -= n->type->width;
-                               regret(&nod1, n, n->left->type, 1);
-                               if(nn->complex >= FNX) {
-                                       regsalloc(&nod2, n);
-                                       cgen(&nod1, &nod2);
-                                       nod1 = nod2;
-                               }
-                               cgen(&nod1, nn);
-                       }
-                       break;
-               }
-               if(nn == Z) {
-                       sugen(n, nodrat, w);
-                       break;
-               }
-               h = nn;
-               if(nn->op == OREGPAIR) {
-                       regsalloc(&nod1, nn);
-                       nn = &nod1;
-               }
-               if(nn->op != OIND) {
-                       nn = new1(OADDR, nn, Z);
-                       nn->type = types[TIND];
-                       nn->addable = 0;
-               } else
-                       nn = nn->left;
-               n = new(OFUNC, n->left, new(OLIST, nn, n->right));
-               n->type = types[TVOID];
-               n->left->type = types[TVOID];
-               cgen(n, Z);
-               if(h->op == OREGPAIR)
-                       loadpair(nn->left, h);
-               break;
-
-       case OCOND:
-               bcgen(n->left, 1);
-               p1 = p;
-               sugen(n->right->left, nn, w);
-               gbranch(OGOTO);
-               patch(p1, pc);
-               p1 = p;
-               sugen(n->right->right, nn, w);
-               patch(p1, pc);
-               break;
-
-       case OCOMMA:
-               cgen(n->left, Z);
-               sugen(n->right, nn, w);
-               break;
-       }
-       return;
-
-copy:
-       if(nn == Z) {
-               switch(n->op) {
-               case OASADD:
-               case OASSUB:
-               case OASAND:
-               case OASOR:
-               case OASXOR:
-
-               case OASMUL:
-               case OASLMUL:
-
-
-               case OASASHL:
-               case OASASHR:
-               case OASLSHR:
-                       break;
-
-               case OPOSTINC:
-               case OPOSTDEC:
-               case OPREINC:
-               case OPREDEC:
-                       break;
-
-               default:
-                       return;
-               }
-       }
-
-       v = w == 8;
-       if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
-               t = nn->type;
-               nn->type = types[TLONG];
-               regialloc(&nod1, nn, Z);
-               lcgen(nn, &nod1);
-               regsalloc(&nod2, nn);
-               nn->type = t;
-
-               gins(AMOVL, &nod1, &nod2);
-               regfree(&nod1);
-
-               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);
-               return;
-       }
-
-       x = 0;
-       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) {
-//                     warn(n, "toughie");
-                       regsalloc(&nod1, n->right);
-                       cgen(n->right, &nod1);
-                       nod2 = *n;
-                       nod2.right = &nod1;
-                       cgen(&nod2, nn);
-                       cursafe = c;
-                       return;
-               }
-               if(cgen64(n, nn)) {
-                       cursafe = c;
-                       return;
-               }
-               if(n->op == OCOM) {
-                       n = n->left;
-                       x = 1;
-               }
-       }
-
-       /* botch, need to save in .safe */
-       c = 0;
-       if(n->complex > nn->complex) {
-               t = n->type;
-               n->type = types[TLONG];
-               if(v) {
-                       regalloc(&nod0, n, Z);
-                       if(!vaddr(n, 0)) {
-                               reglcgen(&nod1, n, Z);
-                               n->type = t;
-                               n = &nod1;
-                       }
-                       else
-                               n->type = t;
-               }
-               else {
-                       nodreg(&nod1, n, D_SI);
-                       if(reg[D_SI]) {
-                               gins(APUSHL, &nod1, Z);
-                               c |= 1;
-                               reg[D_SI]++;
-                       }
-                       lcgen(n, &nod1);
-                       n->type = t;
-               }
-
-               t = nn->type;
-               nn->type = types[TLONG];
-               if(v) {
-                       if(!vaddr(nn, 0)) {
-                               reglcgen(&nod2, nn, Z);
-                               nn->type = t;
-                               nn = &nod2;
-                       }
-                       else
-                               nn->type = t;
-               }
-               else {
-                       nodreg(&nod2, nn, D_DI);
-                       if(reg[D_DI]) {
-                               gins(APUSHL, &nod2, Z);
-                               c |= 2;
-                               reg[D_DI]++;
-                       }
-                       lcgen(nn, &nod2);
-                       nn->type = t;
-               }
-       } else {
-               t = nn->type;
-               nn->type = types[TLONG];
-               if(v) {
-                       regalloc(&nod0, nn, Z);
-                       if(!vaddr(nn, 0)) {
-                               reglcgen(&nod2, nn, Z);
-                               nn->type = t;
-                               nn = &nod2;
-                       }
-                       else
-                               nn->type = t;
-               }
-               else {
-                       nodreg(&nod2, nn, D_DI);
-                       if(reg[D_DI]) {
-                               gins(APUSHL, &nod2, Z);
-                               c |= 2;
-                               reg[D_DI]++;
-                       }
-                       lcgen(nn, &nod2);
-                       nn->type = t;
-               }
-
-               t = n->type;
-               n->type = types[TLONG];
-               if(v) {
-                       if(!vaddr(n, 0)) {
-                               reglcgen(&nod1, n, Z);
-                               n->type = t;
-                               n = &nod1;
-                       }
-                       else
-                               n->type = t;
-               }
-               else {
-                       nodreg(&nod1, n, D_SI);
-                       if(reg[D_SI]) {
-                               gins(APUSHL, &nod1, Z);
-                               c |= 1;
-                               reg[D_SI]++;
-                       }
-                       lcgen(n, &nod1);
-                       n->type = t;
-               }
-       }
-       if(v) {
-               gins(AMOVL, n, &nod0);
-               if(x)
-                       gins(ANOTL, Z, &nod0);
-               gins(AMOVL, &nod0, nn);
-               n->xoffset += SZ_LONG;
-               nn->xoffset += SZ_LONG;
-               gins(AMOVL, n, &nod0);
-               if(x)
-                       gins(ANOTL, Z, &nod0);
-               gins(AMOVL, &nod0, nn);
-               n->xoffset -= SZ_LONG;
-               nn->xoffset -= SZ_LONG;
-               if(nn == &nod2)
-                       regfree(&nod2);
-               if(n == &nod1)
-                       regfree(&nod1);
-               regfree(&nod0);
-               return;
-       }
-       nodreg(&nod3, n, D_CX);
-       if(reg[D_CX]) {
-               gins(APUSHL, &nod3, Z);
-               c |= 4;
-               reg[D_CX]++;
-       }
-       gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
-       gins(ACLD, Z, Z);
-       gins(AREP, Z, Z);
-       gins(AMOVSL, Z, Z);
-       if(c & 4) {
-               gins(APOPL, Z, &nod3);
-               reg[D_CX]--;
-       }
-       if(c & 2) {
-               gins(APOPL, Z, &nod2);
-               reg[nod2.reg]--;
-       }
-       if(c & 1) {
-               gins(APOPL, Z, &nod1);
-               reg[nod1.reg]--;
-       }
-}
diff --git a/src/cmd/8c/cgen64.c b/src/cmd/8c/cgen64.c
deleted file mode 100644 (file)
index 3424f76..0000000
+++ /dev/null
@@ -1,2657 +0,0 @@
-// Inferno utils/8c/cgen64.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/cgen64.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-zeroregm(Node *n)
-{
-       gins(AMOVL, nodconst(0), n);
-}
-
-/* do we need to load the address of a vlong? */
-int
-vaddr(Node *n, int a)
-{
-       switch(n->op) {
-       case ONAME:
-               if(a)
-                       return 1;
-               return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
-
-       case OCONST:
-       case OREGISTER:
-       case OINDREG:
-               return 1;
-       }
-       return 0;
-}
-
-int32
-hi64v(Node *n)
-{
-       if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
-               return (int32)(n->vconst) & ~0L;
-       else
-               return (int32)((uvlong)n->vconst>>32) & ~0L;
-}
-
-int32
-lo64v(Node *n)
-{
-       if(align(0, types[TCHAR], Aarg1, nil))  /* isbigendian */
-               return (int32)((uvlong)n->vconst>>32) & ~0L;
-       else
-               return (int32)(n->vconst) & ~0L;
-}
-
-Node *
-hi64(Node *n)
-{
-       return nodconst(hi64v(n));
-}
-
-Node *
-lo64(Node *n)
-{
-       return nodconst(lo64v(n));
-}
-
-static Node *
-anonreg(void)
-{
-       Node *n;
-
-       n = new(OREGISTER, Z, Z);
-       n->reg = D_NONE;
-       n->type = types[TLONG];
-       return n;
-}
-
-static Node *
-regpair(Node *n, Node *t)
-{
-       Node *r;
-
-       if(n != Z && n->op == OREGPAIR)
-               return n;
-       r = new(OREGPAIR, anonreg(), anonreg());
-       if(n != Z)
-               r->type = n->type;
-       else
-               r->type = t->type;
-       return r;
-}
-
-static void
-evacaxdx(Node *r)
-{
-       Node nod1, nod2;
-
-       if(r->reg == D_AX || r->reg == D_DX) {
-               reg[D_AX]++;
-               reg[D_DX]++;
-               /*
-                * this is just an optim that should
-                * check for spill
-                */
-               r->type = types[TULONG];
-               regalloc(&nod1, r, Z);
-               nodreg(&nod2, Z, r->reg);
-               gins(AMOVL, &nod2, &nod1);
-               regfree(r);
-               r->reg = nod1.reg;
-               reg[D_AX]--;
-               reg[D_DX]--;
-       }
-}
-
-/* lazy instantiation of register pair */
-static int
-instpair(Node *n, Node *l)
-{
-       int r;
-
-       r = 0;
-       if(n->left->reg == D_NONE) {
-               if(l != Z) {
-                       n->left->reg = l->reg;
-                       r = 1;
-               }
-               else
-                       regalloc(n->left, n->left, Z);
-       }
-       if(n->right->reg == D_NONE)
-               regalloc(n->right, n->right, Z);
-       return r;
-}
-
-static void
-zapreg(Node *n)
-{
-       if(n->reg != D_NONE) {
-               regfree(n);
-               n->reg = D_NONE;
-       }
-}
-
-static void
-freepair(Node *n)
-{
-       regfree(n->left);
-       regfree(n->right);
-}
-
-/* n is not OREGPAIR, nn is */
-void
-loadpair(Node *n, Node *nn)
-{
-       Node nod;
-
-       instpair(nn, Z);
-       if(n->op == OCONST) {
-               gins(AMOVL, lo64(n), nn->left);
-               n->xoffset += SZ_LONG;
-               gins(AMOVL, hi64(n), nn->right);
-               n->xoffset -= SZ_LONG;
-               return;
-       }
-       if(!vaddr(n, 0)) {
-               /* steal the right register for the laddr */
-               nod = regnode;
-               nod.reg = nn->right->reg;
-               lcgen(n, &nod);
-               n = &nod;
-               regind(n, n);
-               n->xoffset = 0;
-       }
-       gins(AMOVL, n, nn->left);
-       n->xoffset += SZ_LONG;
-       gins(AMOVL, n, nn->right);
-       n->xoffset -= SZ_LONG;
-}
-
-/* n is OREGPAIR, nn is not */
-static void
-storepair(Node *n, Node *nn, int f)
-{
-       Node nod;
-
-       if(!vaddr(nn, 0)) {
-               reglcgen(&nod, nn, Z);
-               nn = &nod;
-       }
-       gins(AMOVL, n->left, nn);
-       nn->xoffset += SZ_LONG;
-       gins(AMOVL, n->right, nn);
-       nn->xoffset -= SZ_LONG;
-       if(nn == &nod)
-               regfree(&nod);
-       if(f)
-               freepair(n);
-}
-
-enum
-{
-/* 4 only, see WW */
-       WNONE   = 0,
-       WCONST,
-       WADDR,
-       WHARD,
-};
-
-static int
-whatof(Node *n, int a)
-{
-       if(n->op == OCONST)
-               return WCONST;
-       return !vaddr(n, a) ? WHARD : WADDR;
-}
-
-/* can upgrade an extern to addr for AND */
-static int
-reduxv(Node *n)
-{
-       return lo64v(n) == 0 || hi64v(n) == 0;
-}
-
-int
-cond(int op)
-{
-       switch(op) {
-       case OANDAND:
-       case OOROR:
-       case ONOT:
-               return 1;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * for a func operand call it and then return
- * the safe node
- */
-static Node *
-vfunc(Node *n, Node *nn)
-{
-       Node *t;
-
-       if(n->op != OFUNC)
-               return n;
-       t = new(0, Z, Z);
-       if(nn == Z || nn == nodret)
-               nn = n;
-       regsalloc(t, nn);
-       sugen(n, t, 8);
-       return t;
-}
-
-/* try to steal a reg */
-static int
-getreg(Node **np, Node *t, int r)
-{
-       Node *n, *p;
-
-       n = *np;
-       if(n->reg == r) {
-               p = new(0, Z, Z);
-               regalloc(p, n, Z);
-               gins(AMOVL, n, p);
-               *t = *n;
-               *np = p;
-               return 1;
-       }
-       return 0;
-}
-
-static Node *
-snarfreg(Node *n, Node *t, int r, Node *d, Node *c)
-{
-       if(n == Z || n->op != OREGPAIR || (!getreg(&n->left, t, r) && !getreg(&n->right, t, r))) {
-               if(nodreg(t, Z, r)) {
-                       regalloc(c, d, Z);
-                       gins(AMOVL, t, c);
-                       reg[r]++;
-                       return c;
-               }
-               reg[r]++;
-       }
-       return Z;
-}
-
-enum
-{
-       Vstart  = OEND,
-
-       Vgo,
-       Vamv,
-       Vmv,
-       Vzero,
-       Vop,
-       Vopx,
-       Vins,
-       Vins0,
-       Vinsl,
-       Vinsr,
-       Vinsla,
-       Vinsra,
-       Vinsx,
-       Vmul,
-       Vshll,
-       VT,
-       VF,
-       V_l_lo_f,
-       V_l_hi_f,
-       V_l_lo_t,
-       V_l_hi_t,
-       V_l_lo_u,
-       V_l_hi_u,
-       V_r_lo_f,
-       V_r_hi_f,
-       V_r_lo_t,
-       V_r_hi_t,
-       V_r_lo_u,
-       V_r_hi_u,
-       Vspazz,
-       Vend,
-
-       V_T0,
-       V_T1,
-       V_F0,
-       V_F1,
-
-       V_a0,
-       V_a1,
-       V_f0,
-       V_f1,
-
-       V_p0,
-       V_p1,
-       V_p2,
-       V_p3,
-       V_p4,
-
-       V_s0,
-       V_s1,
-       V_s2,
-       V_s3,
-       V_s4,
-
-       C00,
-       C01,
-       C31,
-       C32,
-
-       O_l_lo,
-       O_l_hi,
-       O_r_lo,
-       O_r_hi,
-       O_t_lo,
-       O_t_hi,
-       O_l,
-       O_r,
-       O_l_rp,
-       O_r_rp,
-       O_t_rp,
-       O_r0,
-       O_r1,
-       O_Zop,
-
-       O_a0,
-       O_a1,
-
-       V_C0,
-       V_C1,
-
-       V_S0,
-       V_S1,
-
-       VOPS    = 5,
-       VLEN    = 5,
-       VARGS   = 2,
-
-       S00     = 0,
-       Sc0,
-       Sc1,
-       Sc2,
-       Sac3,
-       Sac4,
-       S10,
-
-       SAgen   = 0,
-       SAclo,
-       SAc32,
-       SAchi,
-       SAdgen,
-       SAdclo,
-       SAdc32,
-       SAdchi,
-
-       B0c     = 0,
-       Bca,
-       Bac,
-
-       T0i     = 0,
-       Tii,
-
-       Bop0    = 0,
-       Bop1,
-};
-
-/*
- * _testv:
- *     CMPL    lo,$0
- *     JNE     true
- *     CMPL    hi,$0
- *     JNE     true
- *     GOTO    false
- * false:
- *     GOTO    code
- * true:
- *     GOTO    patchme
- * code:
- */
-
-static uchar   testi[][VLEN] =
-{
-       {Vop, ONE, O_l_lo, C00},
-       {V_s0, Vop, ONE, O_l_hi, C00},
-       {V_s1, Vgo, V_s2, Vgo, V_s3},
-       {VF, V_p0, V_p1, VT, V_p2},
-       {Vgo, V_p3},
-       {VT, V_p0, V_p1, VF, V_p2},
-       {Vend},
-};
-
-/* shift left general case */
-static uchar   shll00[][VLEN] =
-{
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vinsl, ASHLL, O_r, O_l_rp},
-       {Vins, ASHLL, O_r, O_l_lo, Vgo},
-       {V_p0, V_s0},
-       {Vins, ASHLL, O_r, O_l_lo},
-       {Vins, AMOVL, O_l_lo, O_l_hi},
-       {Vzero, O_l_lo, V_p0, Vend},
-};
-
-/* shift left rp, const < 32 */
-static uchar   shllc0[][VLEN] =
-{
-       {Vinsl, ASHLL, O_r, O_l_rp},
-       {Vshll, O_r, O_l_lo, Vend},
-};
-
-/* shift left rp, const == 32 */
-static uchar   shllc1[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_l_hi},
-       {Vzero, O_l_lo, Vend},
-};
-
-/* shift left rp, const > 32 */
-static uchar   shllc2[][VLEN] =
-{
-       {Vshll, O_r, O_l_lo},
-       {Vins, AMOVL, O_l_lo, O_l_hi},
-       {Vzero, O_l_lo, Vend},
-};
-
-/* shift left addr, const == 32 */
-static uchar   shllac3[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_hi},
-       {Vzero, O_t_lo, Vend},
-};
-
-/* shift left addr, const > 32 */
-static uchar   shllac4[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_hi},
-       {Vshll, O_r, O_t_hi},
-       {Vzero, O_t_lo, Vend},
-};
-
-/* shift left of constant */
-static uchar   shll10[][VLEN] =
-{
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsl, ASHLL, O_r, O_t_rp},
-       {Vins, ASHLL, O_r, O_t_lo, Vgo},
-       {V_p0, V_s0},
-       {Vins, AMOVL, O_l_lo, O_t_hi},
-       {V_l_lo_t, Vins, ASHLL, O_r, O_t_hi},
-       {Vzero, O_t_lo, V_p0, Vend},
-};
-
-static uchar   (*shlltab[])[VLEN] =
-{
-       shll00,
-       shllc0,
-       shllc1,
-       shllc2,
-       shllac3,
-       shllac4,
-       shll10,
-};
-
-/* shift right general case */
-static uchar   shrl00[][VLEN] =
-{
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vinsr, ASHRL, O_r, O_l_rp},
-       {Vins, O_a0, O_r, O_l_hi, Vgo},
-       {V_p0, V_s0},
-       {Vins, O_a0, O_r, O_l_hi},
-       {Vins, AMOVL, O_l_hi, O_l_lo},
-       {V_T1, Vzero, O_l_hi},
-       {V_F1, Vins, ASARL, C31, O_l_hi},
-       {V_p0, Vend},
-};
-
-/* shift right rp, const < 32 */
-static uchar   shrlc0[][VLEN] =
-{
-       {Vinsr, ASHRL, O_r, O_l_rp},
-       {Vins, O_a0, O_r, O_l_hi, Vend},
-};
-
-/* shift right rp, const == 32 */
-static uchar   shrlc1[][VLEN] =
-{
-       {Vins, AMOVL, O_l_hi, O_l_lo},
-       {V_T1, Vzero, O_l_hi},
-       {V_F1, Vins, ASARL, C31, O_l_hi},
-       {Vend},
-};
-
-/* shift right rp, const > 32 */
-static uchar   shrlc2[][VLEN] =
-{
-       {Vins, O_a0, O_r, O_l_hi},
-       {Vins, AMOVL, O_l_hi, O_l_lo},
-       {V_T1, Vzero, O_l_hi},
-       {V_F1, Vins, ASARL, C31, O_l_hi},
-       {Vend},
-};
-
-/* shift right addr, const == 32 */
-static uchar   shrlac3[][VLEN] =
-{
-       {Vins, AMOVL, O_l_hi, O_t_lo},
-       {V_T1, Vzero, O_t_hi},
-       {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
-       {V_F1, Vins, ASARL, C31, O_t_hi},
-       {Vend},
-};
-
-/* shift right addr, const > 32 */
-static uchar   shrlac4[][VLEN] =
-{
-       {Vins, AMOVL, O_l_hi, O_t_lo},
-       {Vins, O_a0, O_r, O_t_lo},
-       {V_T1, Vzero, O_t_hi},
-       {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
-       {V_F1, Vins, ASARL, C31, O_t_hi},
-       {Vend},
-};
-
-/* shift right of constant */
-static uchar   shrl10[][VLEN] =
-{
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsr, ASHRL, O_r, O_t_rp},
-       {Vins, O_a0, O_r, O_t_hi, Vgo},
-       {V_p0, V_s0},
-       {Vins, AMOVL, O_l_hi, O_t_lo},
-       {V_l_hi_t, Vins, O_a0, O_r, O_t_lo},
-       {V_l_hi_u, V_S1},
-       {V_T1, Vzero, O_t_hi, V_p0},
-       {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
-       {V_F1, Vins, ASARL, C31, O_t_hi},
-       {Vend},
-};
-
-static uchar   (*shrltab[])[VLEN] =
-{
-       shrl00,
-       shrlc0,
-       shrlc1,
-       shrlc2,
-       shrlac3,
-       shrlac4,
-       shrl10,
-};
-
-/* shift asop left general case */
-static uchar   asshllgen[][VLEN] =
-{
-       {V_a0, V_a1},
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vins, AMOVL, O_l_lo, O_r0},
-       {Vins, AMOVL, O_l_hi, O_r1},
-       {Vinsla, ASHLL, O_r, O_r0},
-       {Vins, ASHLL, O_r, O_r0},
-       {Vins, AMOVL, O_r1, O_l_hi},
-       {Vins, AMOVL, O_r0, O_l_lo, Vgo},
-       {V_p0, V_s0},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vzero, O_l_lo},
-       {Vins, ASHLL, O_r, O_r0},
-       {Vins, AMOVL, O_r0, O_l_hi, V_p0},
-       {V_f0, V_f1, Vend},
-};
-
-/* shift asop left, const < 32 */
-static uchar   asshllclo[][VLEN] =
-{
-       {V_a0, V_a1},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vins, AMOVL, O_l_hi, O_r1},
-       {Vinsla, ASHLL, O_r, O_r0},
-       {Vshll, O_r, O_r0},
-       {Vins, AMOVL, O_r1, O_l_hi},
-       {Vins, AMOVL, O_r0, O_l_lo},
-       {V_f0, V_f1, Vend},
-};
-
-/* shift asop left, const == 32 */
-static uchar   asshllc32[][VLEN] =
-{
-       {V_a0},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vzero, O_l_lo},
-       {Vins, AMOVL, O_r0, O_l_hi},
-       {V_f0, Vend},
-};
-
-/* shift asop left, const > 32 */
-static uchar   asshllchi[][VLEN] =
-{
-       {V_a0},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vzero, O_l_lo},
-       {Vshll, O_r, O_r0},
-       {Vins, AMOVL, O_r0, O_l_hi},
-       {V_f0, Vend},
-};
-
-/* shift asop dest left general case */
-static uchar   asdshllgen[][VLEN] =
-{
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsl, ASHLL, O_r, O_t_rp},
-       {Vins, ASHLL, O_r, O_t_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo, Vgo},
-       {V_p0, V_s0},
-       {Vins, AMOVL, O_l_lo, O_t_hi},
-       {Vzero, O_l_lo},
-       {Vins, ASHLL, O_r, O_t_hi},
-       {Vzero, O_t_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi, V_p0},
-       {Vend},
-};
-
-/* shift asop dest left, const < 32 */
-static uchar   asdshllclo[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsl, ASHLL, O_r, O_t_rp},
-       {Vshll, O_r, O_t_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vend},
-};
-
-/* shift asop dest left, const == 32 */
-static uchar   asdshllc32[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_hi},
-       {Vzero, O_t_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vend},
-};
-
-/* shift asop dest, const > 32 */
-static uchar   asdshllchi[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_hi},
-       {Vzero, O_t_lo},
-       {Vshll, O_r, O_t_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vend},
-};
-
-static uchar   (*asshlltab[])[VLEN] =
-{
-       asshllgen,
-       asshllclo,
-       asshllc32,
-       asshllchi,
-       asdshllgen,
-       asdshllclo,
-       asdshllc32,
-       asdshllchi,
-};
-
-/* shift asop right general case */
-static uchar   asshrlgen[][VLEN] =
-{
-       {V_a0, V_a1},
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vins, AMOVL, O_l_lo, O_r0},
-       {Vins, AMOVL, O_l_hi, O_r1},
-       {Vinsra, ASHRL, O_r, O_r0},
-       {Vinsx, Bop0, O_r, O_r1},
-       {Vins, AMOVL, O_r0, O_l_lo},
-       {Vins, AMOVL, O_r1, O_l_hi, Vgo},
-       {V_p0, V_s0},
-       {Vins, AMOVL, O_l_hi, O_r0},
-       {Vinsx, Bop0, O_r, O_r0},
-       {V_T1, Vzero, O_l_hi},
-       {Vins, AMOVL, O_r0, O_l_lo},
-       {V_F1, Vins, ASARL, C31, O_r0},
-       {V_F1, Vins, AMOVL, O_r0, O_l_hi},
-       {V_p0, V_f0, V_f1, Vend},
-};
-
-/* shift asop right, const < 32 */
-static uchar   asshrlclo[][VLEN] =
-{
-       {V_a0, V_a1},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vins, AMOVL, O_l_hi, O_r1},
-       {Vinsra, ASHRL, O_r, O_r0},
-       {Vinsx, Bop0, O_r, O_r1},
-       {Vins, AMOVL, O_r0, O_l_lo},
-       {Vins, AMOVL, O_r1, O_l_hi},
-       {V_f0, V_f1, Vend},
-};
-
-/* shift asop right, const == 32 */
-static uchar   asshrlc32[][VLEN] =
-{
-       {V_a0},
-       {Vins, AMOVL, O_l_hi, O_r0},
-       {V_T1, Vzero, O_l_hi},
-       {Vins, AMOVL, O_r0, O_l_lo},
-       {V_F1, Vins, ASARL, C31, O_r0},
-       {V_F1, Vins, AMOVL, O_r0, O_l_hi},
-       {V_f0, Vend},
-};
-
-/* shift asop right, const > 32 */
-static uchar   asshrlchi[][VLEN] =
-{
-       {V_a0},
-       {Vins, AMOVL, O_l_hi, O_r0},
-       {V_T1, Vzero, O_l_hi},
-       {Vinsx, Bop0, O_r, O_r0},
-       {Vins, AMOVL, O_r0, O_l_lo},
-       {V_F1, Vins, ASARL, C31, O_r0},
-       {V_F1, Vins, AMOVL, O_r0, O_l_hi},
-       {V_f0, Vend},
-};
-
-/* shift asop dest right general case */
-static uchar   asdshrlgen[][VLEN] =
-{
-       {Vop, OGE, O_r, C32},
-       {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsr, ASHRL, O_r, O_t_rp},
-       {Vinsx, Bop0, O_r, O_t_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi, Vgo},
-       {V_p0, V_s0},
-       {Vins, AMOVL, O_l_hi, O_t_lo},
-       {V_T1, Vzero, O_t_hi},
-       {Vinsx, Bop0, O_r, O_t_lo},
-       {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
-       {V_F1, Vins, ASARL, C31, O_t_hi},
-       {Vins, AMOVL, O_t_hi, O_l_hi, V_p0},
-       {Vend},
-};
-
-/* shift asop dest right, const < 32 */
-static uchar   asdshrlclo[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsr, ASHRL, O_r, O_t_rp},
-       {Vinsx, Bop0, O_r, O_t_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vend},
-};
-
-/* shift asop dest right, const == 32 */
-static uchar   asdshrlc32[][VLEN] =
-{
-       {Vins, AMOVL, O_l_hi, O_t_lo},
-       {V_T1, Vzero, O_t_hi},
-       {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
-       {V_F1, Vins, ASARL, C31, O_t_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vend},
-};
-
-/* shift asop dest, const > 32 */
-static uchar   asdshrlchi[][VLEN] =
-{
-       {Vins, AMOVL, O_l_hi, O_t_lo},
-       {V_T1, Vzero, O_t_hi},
-       {Vinsx, Bop0, O_r, O_t_lo},
-       {V_T1, Vins, AMOVL, O_t_hi, O_l_hi},
-       {V_T1, Vins, AMOVL, O_t_lo, O_l_lo},
-       {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
-       {V_F1, Vins, ASARL, C31, O_t_hi},
-       {V_F1, Vins, AMOVL, O_t_lo, O_l_lo},
-       {V_F1, Vins, AMOVL, O_t_hi, O_l_hi},
-       {Vend},
-};
-
-static uchar   (*asshrltab[])[VLEN] =
-{
-       asshrlgen,
-       asshrlclo,
-       asshrlc32,
-       asshrlchi,
-       asdshrlgen,
-       asdshrlclo,
-       asdshrlc32,
-       asdshrlchi,
-};
-
-static uchar   shrlargs[]      = { ASHRL, 1 };
-static uchar   sarlargs[]      = { ASARL, 0 };
-
-/* ++ -- */
-static uchar   incdec[][VLEN] =
-{
-       {Vinsx, Bop0, C01, O_l_lo},
-       {Vinsx, Bop1, C00, O_l_hi, Vend},
-};
-
-/* ++ -- *p */
-static uchar   incdecpre[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsx, Bop0, C01, O_t_lo},
-       {Vinsx, Bop1, C00, O_t_hi},
-       {Vins, AMOVL, O_t_lo, O_l_lo},
-       {Vins, AMOVL, O_t_hi, O_l_hi, Vend},
-};
-
-/* *p ++ -- */
-static uchar   incdecpost[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsx, Bop0, C01, O_l_lo},
-       {Vinsx, Bop1, C00, O_l_hi, Vend},
-};
-
-/* binop rp, rp */
-static uchar   binop00[][VLEN] =
-{
-       {Vinsx, Bop0, O_r_lo, O_l_lo},
-       {Vinsx, Bop1, O_r_hi, O_l_hi, Vend},
-       {Vend},
-};
-
-/* binop rp, addr */
-static uchar   binoptmp[][VLEN] =
-{
-       {V_a0, Vins, AMOVL, O_r_lo, O_r0},
-       {Vinsx, Bop0, O_r0, O_l_lo},
-       {Vins, AMOVL, O_r_hi, O_r0},
-       {Vinsx, Bop1, O_r0, O_l_hi},
-       {V_f0, Vend},
-};
-
-/* binop t = *a op *b */
-static uchar   binop11[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vinsx, Bop0, O_r_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsx, Bop1, O_r_hi, O_t_hi, Vend},
-};
-
-/* binop t = rp +- c */
-static uchar   add0c[][VLEN] =
-{
-       {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
-       {V_r_lo_f, Vamv, Bop0, Bop1},
-       {Vinsx, Bop1, O_r_hi, O_l_hi},
-       {Vend},
-};
-
-/* binop t = rp & c */
-static uchar   and0c[][VLEN] =
-{
-       {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
-       {V_r_lo_f, Vins, AMOVL, C00, O_l_lo},
-       {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi},
-       {V_r_hi_f, Vins, AMOVL, C00, O_l_hi},
-       {Vend},
-};
-
-/* binop t = rp | c */
-static uchar   or0c[][VLEN] =
-{
-       {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
-       {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi},
-       {Vend},
-};
-
-/* binop t = c - rp */
-static uchar   sub10[][VLEN] =
-{
-       {V_a0, Vins, AMOVL, O_l_lo, O_r0},
-       {Vinsx, Bop0, O_r_lo, O_r0},
-       {Vins, AMOVL, O_l_hi, O_r_lo},
-       {Vinsx, Bop1, O_r_hi, O_r_lo},
-       {Vspazz, V_f0, Vend},
-};
-
-/* binop t = c + *b */
-static uchar   addca[][VLEN] =
-{
-       {Vins, AMOVL, O_r_lo, O_t_lo},
-       {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
-       {V_l_lo_f, Vamv, Bop0, Bop1},
-       {Vins, AMOVL, O_r_hi, O_t_hi},
-       {Vinsx, Bop1, O_l_hi, O_t_hi},
-       {Vend},
-};
-
-/* binop t = c & *b */
-static uchar   andca[][VLEN] =
-{
-       {V_l_lo_t, Vins, AMOVL, O_r_lo, O_t_lo},
-       {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
-       {V_l_lo_f, Vzero, O_t_lo},
-       {V_l_hi_t, Vins, AMOVL, O_r_hi, O_t_hi},
-       {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi},
-       {V_l_hi_f, Vzero, O_t_hi},
-       {Vend},
-};
-
-/* binop t = c | *b */
-static uchar   orca[][VLEN] =
-{
-       {Vins, AMOVL, O_r_lo, O_t_lo},
-       {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_r_hi, O_t_hi},
-       {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi},
-       {Vend},
-};
-
-/* binop t = c - *b */
-static uchar   subca[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsx, Bop0, O_r_lo, O_t_lo},
-       {Vinsx, Bop1, O_r_hi, O_t_hi},
-       {Vend},
-};
-
-/* binop t = *a +- c */
-static uchar   addac[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
-       {V_r_lo_f, Vamv, Bop0, Bop1},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {Vinsx, Bop1, O_r_hi, O_t_hi},
-       {Vend},
-};
-
-/* binop t = *a | c */
-static uchar   orac[][VLEN] =
-{
-       {Vins, AMOVL, O_l_lo, O_t_lo},
-       {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
-       {Vins, AMOVL, O_l_hi, O_t_hi},
-       {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_t_hi},
-       {Vend},
-};
-
-/* binop t = *a & c */
-static uchar   andac[][VLEN] =
-{
-       {V_r_lo_t, Vins, AMOVL, O_l_lo, O_t_lo},
-       {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
-       {V_r_lo_f, Vzero, O_t_lo},
-       {V_r_hi_t, Vins, AMOVL, O_l_hi, O_t_hi},
-       {V_r_hi_t, Vinsx, Bop0, O_r_hi, O_t_hi},
-       {V_r_hi_f, Vzero, O_t_hi},
-       {Vend},
-};
-
-static uchar   ADDargs[]       = { AADDL, AADCL };
-static uchar   ANDargs[]       = { AANDL, AANDL };
-static uchar   ORargs[]        = { AORL, AORL };
-static uchar   SUBargs[]       = { ASUBL, ASBBL };
-static uchar   XORargs[]       = { AXORL, AXORL };
-
-static uchar   (*ADDtab[])[VLEN] =
-{
-       add0c, addca, addac,
-};
-
-static uchar   (*ANDtab[])[VLEN] =
-{
-       and0c, andca, andac,
-};
-
-static uchar   (*ORtab[])[VLEN] =
-{
-       or0c, orca, orac,
-};
-
-static uchar   (*SUBtab[])[VLEN] =
-{
-       add0c, subca, addac,
-};
-
-/* mul of const32 */
-static uchar   mulc32[][VLEN] =
-{
-       {V_a0, Vop, ONE, O_l_hi, C00},
-       {V_s0, Vins, AMOVL, O_r_lo, O_r0},
-       {Vins, AMULL, O_r0, O_Zop},
-       {Vgo, V_p0, V_s0},
-       {Vins, AMOVL, O_l_hi, O_r0},
-       {Vmul, O_r_lo, O_r0},
-       {Vins, AMOVL, O_r_lo, O_l_hi},
-       {Vins, AMULL, O_l_hi, O_Zop},
-       {Vins, AADDL, O_r0, O_l_hi},
-       {V_f0, V_p0, Vend},
-};
-
-/* mul of const64 */
-static uchar   mulc64[][VLEN] =
-{
-       {V_a0, Vins, AMOVL, O_r_hi, O_r0},
-       {Vop, OOR, O_l_hi, O_r0},
-       {Vop, ONE, O_r0, C00},
-       {V_s0, Vins, AMOVL, O_r_lo, O_r0},
-       {Vins, AMULL, O_r0, O_Zop},
-       {Vgo, V_p0, V_s0},
-       {Vmul, O_r_lo, O_l_hi},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vmul, O_r_hi, O_r0},
-       {Vins, AADDL, O_l_hi, O_r0},
-       {Vins, AMOVL, O_r_lo, O_l_hi},
-       {Vins, AMULL, O_l_hi, O_Zop},
-       {Vins, AADDL, O_r0, O_l_hi},
-       {V_f0, V_p0, Vend},
-};
-
-/* mul general */
-static uchar   mull[][VLEN] =
-{
-       {V_a0, Vins, AMOVL, O_r_hi, O_r0},
-       {Vop, OOR, O_l_hi, O_r0},
-       {Vop, ONE, O_r0, C00},
-       {V_s0, Vins, AMOVL, O_r_lo, O_r0},
-       {Vins, AMULL, O_r0, O_Zop},
-       {Vgo, V_p0, V_s0},
-       {Vins, AIMULL, O_r_lo, O_l_hi},
-       {Vins, AMOVL, O_l_lo, O_r0},
-       {Vins, AIMULL, O_r_hi, O_r0},
-       {Vins, AADDL, O_l_hi, O_r0},
-       {Vins, AMOVL, O_r_lo, O_l_hi},
-       {Vins, AMULL, O_l_hi, O_Zop},
-       {Vins, AADDL, O_r0, O_l_hi},
-       {V_f0, V_p0, Vend},
-};
-
-/* cast rp l to rp t */
-static uchar   castrp[][VLEN] =
-{
-       {Vmv, O_l, O_t_lo},
-       {VT, Vins, AMOVL, O_t_lo, O_t_hi},
-       {VT, Vins, ASARL, C31, O_t_hi},
-       {VF, Vzero, O_t_hi},
-       {Vend},
-};
-
-/* cast rp l to addr t */
-static uchar   castrpa[][VLEN] =
-{
-       {VT, V_a0, Vmv, O_l, O_r0},
-       {VT, Vins, AMOVL, O_r0, O_t_lo},
-       {VT, Vins, ASARL, C31, O_r0},
-       {VT, Vins, AMOVL, O_r0, O_t_hi},
-       {VT, V_f0},
-       {VF, Vmv, O_l, O_t_lo},
-       {VF, Vzero, O_t_hi},
-       {Vend},
-};
-
-static uchar   netab0i[][VLEN] =
-{
-       {Vop, ONE, O_l_lo, O_r_lo},
-       {V_s0, Vop, ONE, O_l_hi, O_r_hi},
-       {V_s1, Vgo, V_s2, Vgo, V_s3},
-       {VF, V_p0, V_p1, VT, V_p2},
-       {Vgo, V_p3},
-       {VT, V_p0, V_p1, VF, V_p2},
-       {Vend},
-};
-
-static uchar   netabii[][VLEN] =
-{
-       {V_a0, Vins, AMOVL, O_l_lo, O_r0},
-       {Vop, ONE, O_r0, O_r_lo},
-       {V_s0, Vins, AMOVL, O_l_hi, O_r0},
-       {Vop, ONE, O_r0, O_r_hi},
-       {V_s1, Vgo, V_s2, Vgo, V_s3},
-       {VF, V_p0, V_p1, VT, V_p2},
-       {Vgo, V_p3},
-       {VT, V_p0, V_p1, VF, V_p2},
-       {V_f0, Vend},
-};
-
-static uchar   cmptab0i[][VLEN] =
-{
-       {Vopx, Bop0, O_l_hi, O_r_hi},
-       {V_s0, Vins0, AJNE},
-       {V_s1, Vopx, Bop1, O_l_lo, O_r_lo},
-       {V_s2, Vgo, V_s3, Vgo, V_s4},
-       {VT, V_p1, V_p3},
-       {VF, V_p0, V_p2},
-       {Vgo, V_p4},
-       {VT, V_p0, V_p2},
-       {VF, V_p1, V_p3},
-       {Vend},
-};
-
-static uchar   cmptabii[][VLEN] =
-{
-       {V_a0, Vins, AMOVL, O_l_hi, O_r0},
-       {Vopx, Bop0, O_r0, O_r_hi},
-       {V_s0, Vins0, AJNE},
-       {V_s1, Vins, AMOVL, O_l_lo, O_r0},
-       {Vopx, Bop1, O_r0, O_r_lo},
-       {V_s2, Vgo, V_s3, Vgo, V_s4},
-       {VT, V_p1, V_p3},
-       {VF, V_p0, V_p2},
-       {Vgo, V_p4},
-       {VT, V_p0, V_p2},
-       {VF, V_p1, V_p3},
-       {V_f0, Vend},
-};
-
-static uchar   (*NEtab[])[VLEN] =
-{
-       netab0i, netabii,
-};
-
-static uchar   (*cmptab[])[VLEN] =
-{
-       cmptab0i, cmptabii,
-};
-
-static uchar   GEargs[]        = { OGT, OHS };
-static uchar   GTargs[]        = { OGT, OHI };
-static uchar   HIargs[]        = { OHI, OHI };
-static uchar   HSargs[]        = { OHI, OHS };
-
-/* Big Generator */
-static void
-biggen(Node *l, Node *r, Node *t, int true, uchar code[][VLEN], uchar *a)
-{
-       int i, j, g, oc, op, lo, ro, to, xo, *xp;
-       Type *lt;
-       Prog *pr[VOPS];
-       Node *ot, *tl, *tr, tmps[2];
-       uchar *c, (*cp)[VLEN], args[VARGS];
-
-       if(a != nil)
-               memmove(args, a, VARGS);
-//print("biggen %d %d %d\n", args[0], args[1], args[2]);
-//if(l) prtree(l, "l");
-//if(r) prtree(r, "r");
-//if(t) prtree(t, "t");
-       lo = ro = to = 0;
-       cp = code;
-
-       for (;;) {
-               c = *cp++;
-               g = 1;
-               i = 0;
-//print("code %d %d %d %d %d\n", c[0], c[1], c[2], c[3], c[4]);
-               for(;;) {
-                       switch(op = c[i]) {
-                       case Vgo:
-                               if(g)
-                                       gbranch(OGOTO);
-                               i++;
-                               break;
-
-                       case Vamv:
-                               i += 3;
-                               if(i > VLEN) {
-                                       diag(l, "bad Vop");
-                                       return;
-                               }
-                               if(g)
-                                       args[c[i - 1]] = args[c[i - 2]];
-                               break;
-
-                       case Vzero:
-                               i += 2;
-                               if(i > VLEN) {
-                                       diag(l, "bad Vop");
-                                       return;
-                               }
-                               j = i - 1;
-                               goto op;
-
-                       case Vspazz:    // nasty hack to save a reg in SUB
-//print("spazz\n");
-                               if(g) {
-//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg);
-                                       ot = r->right;
-                                       r->right = r->left;
-                                       tl = new(0, Z, Z);
-                                       *tl = tmps[0];
-                                       r->left = tl;
-                                       tmps[0] = *ot;
-//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg);
-                               }
-                               i++;
-                               break;
-
-                       case Vmv:
-                       case Vmul:
-                       case Vshll:
-                               i += 3;
-                               if(i > VLEN) {
-                                       diag(l, "bad Vop");
-                                       return;
-                               }
-                               j = i - 2;
-                               goto op;
-
-                       case Vins0:
-                               i += 2;
-                               if(i > VLEN) {
-                                       diag(l, "bad Vop");
-                                       return;
-                               }
-                               gins(c[i - 1], Z, Z);
-                               break;
-
-                       case Vop:
-                       case Vopx:
-                       case Vins:
-                       case Vinsl:
-                       case Vinsr:
-                       case Vinsla:
-                       case Vinsra:
-                       case Vinsx:
-                               i += 4;
-                               if(i > VLEN) {
-                                       diag(l, "bad Vop");
-                                       return;
-                               }
-                               j = i - 2;
-                               goto op;
-
-                       op:
-                               if(!g)
-                                       break;
-                               tl = Z;
-                               tr = Z;
-                               for(; j < i; j++) {
-                                       switch(c[j]) {
-                                       case C00:
-                                               ot = nodconst(0);
-                                               break;
-                                       case C01:
-                                               ot = nodconst(1);
-                                               break;
-                                       case C31:
-                                               ot = nodconst(31);
-                                               break;
-                                       case C32:
-                                               ot = nodconst(32);
-                                               break;
-
-                                       case O_l:
-                                       case O_l_lo:
-                                               ot = l; xp = &lo; xo = 0;
-                                               goto op0;
-                                       case O_l_hi:
-                                               ot = l; xp = &lo; xo = SZ_LONG;
-                                               goto op0;
-                                       case O_r:
-                                       case O_r_lo:
-                                               ot = r; xp = &ro; xo = 0;
-                                               goto op0;
-                                       case O_r_hi:
-                                               ot = r; xp = &ro; xo = SZ_LONG;
-                                               goto op0;
-                                       case O_t_lo:
-                                               ot = t; xp = &to; xo = 0;
-                                               goto op0;
-                                       case O_t_hi:
-                                               ot = t; xp = &to; xo = SZ_LONG;
-                                               goto op0;
-                                       case O_l_rp:
-                                               ot = l;
-                                               break;
-                                       case O_r_rp:
-                                               ot = r;
-                                               break;
-                                       case O_t_rp:
-                                               ot = t;
-                                               break;
-                                       case O_r0:
-                                       case O_r1:
-                                               ot = &tmps[c[j] - O_r0];
-                                               break;
-                                       case O_Zop:
-                                               ot = Z;
-                                               break;
-
-                                       op0:
-                                               switch(ot->op) {
-                                               case OCONST:
-                                                       if(xo)
-                                                               ot = hi64(ot);
-                                                       else
-                                                               ot = lo64(ot);
-                                                       break;
-                                               case OREGPAIR:
-                                                       if(xo)
-                                                               ot = ot->right;
-                                                       else
-                                                               ot = ot->left;
-                                                       break;
-                                               case OREGISTER:
-                                                       break;
-                                               default:
-                                                       if(xo != *xp) {
-                                                               ot->xoffset += xo - *xp;
-                                                               *xp = xo;
-                                                       }
-                                               }
-                                               break;
-                                       
-                                       default:
-                                               diag(l, "bad V_lop");
-                                               return;
-                                       }
-                                       if(tl == nil)
-                                               tl = ot;
-                                       else
-                                               tr = ot;
-                               }
-                               if(op == Vzero) {
-                                       zeroregm(tl);
-                                       break;
-                               }
-                               oc = c[i - 3];
-                               if(op == Vinsx || op == Vopx) {
-//print("%d -> %d\n", oc, args[oc]);
-                                       oc = args[oc];
-                               }
-                               else {
-                                       switch(oc) {
-                                       case O_a0:
-                                       case O_a1:
-                                               oc = args[oc - O_a0];
-                                               break;
-                                       }
-                               }
-                               switch(op) {
-                               case Vmul:
-                                       mulgen(tr->type, tl, tr);
-                                       break;
-                               case Vmv:
-                                       gmove(tl, tr);
-                                       break;
-                               case Vshll:
-                                       shiftit(tr->type, tl, tr);
-                                       break;
-                               case Vop:
-                               case Vopx:
-                                       gopcode(oc, types[TULONG], tl, tr);
-                                       break;
-                               case Vins:
-                               case Vinsx:
-                                       gins(oc, tl, tr);
-                                       break;
-                               case Vinsl:
-                                       gins(oc, tl, tr->right);
-                                       p->from.index = tr->left->reg;
-                                       break;
-                               case Vinsr:
-                                       gins(oc, tl, tr->left);
-                                       p->from.index = tr->right->reg;
-                                       break;
-                               case Vinsla:
-                                       gins(oc, tl, tr + 1);
-                                       p->from.index = tr->reg;
-                                       break;
-                               case Vinsra:
-                                       gins(oc, tl, tr);
-                                       p->from.index = (tr + 1)->reg;
-                                       break;
-                               }
-                               break;
-
-                       case VT:
-                               g = true;
-                               i++;
-                               break;
-                       case VF:
-                               g = !true;
-                               i++;
-                               break;
-
-                       case V_T0: case V_T1:
-                               g = args[op - V_T0];
-                               i++;
-                               break;
-
-                       case V_F0: case V_F1:
-                               g = !args[op - V_F0];
-                               i++;
-                               break;
-
-                       case V_C0: case V_C1:
-                               if(g)
-                                       args[op - V_C0] = 0;
-                               i++;
-                               break;
-
-                       case V_S0: case V_S1:
-                               if(g)
-                                       args[op - V_S0] = 1;
-                               i++;
-                               break;
-
-                       case V_l_lo_f:
-                               g = lo64v(l) == 0;
-                               i++;
-                               break;
-                       case V_l_hi_f:
-                               g = hi64v(l) == 0;
-                               i++;
-                               break;
-                       case V_l_lo_t:
-                               g = lo64v(l) != 0;
-                               i++;
-                               break;
-                       case V_l_hi_t:
-                               g = hi64v(l) != 0;
-                               i++;
-                               break;
-                       case V_l_lo_u:
-                               g = lo64v(l) >= 0;
-                               i++;
-                               break;
-                       case V_l_hi_u:
-                               g = hi64v(l) >= 0;
-                               i++;
-                               break;
-                       case V_r_lo_f:
-                               g = lo64v(r) == 0;
-                               i++;
-                               break;
-                       case V_r_hi_f:
-                               g = hi64v(r) == 0;
-                               i++;
-                               break;
-                       case V_r_lo_t:
-                               g = lo64v(r) != 0;
-                               i++;
-                               break;
-                       case V_r_hi_t:
-                               g = hi64v(r) != 0;
-                               i++;
-                               break;
-                       case V_r_lo_u:
-                               g = lo64v(r) >= 0;
-                               i++;
-                               break;
-                       case V_r_hi_u:
-                               g = hi64v(r) >= 0;
-                               i++;
-                               break;
-
-                       case Vend:
-                               goto out;
-
-                       case V_a0: case V_a1:
-                               if(g) {
-                                       lt = l->type;
-                                       l->type = types[TULONG];
-                                       regalloc(&tmps[op - V_a0], l, Z);
-                                       l->type = lt;
-                               }
-                               i++;
-                               break;
-
-                       case V_f0: case V_f1:
-                               if(g)
-                                       regfree(&tmps[op - V_f0]);
-                               i++;
-                               break;
-
-                       case V_p0: case V_p1: case V_p2: case V_p3: case V_p4:
-                               if(g)
-                                       patch(pr[op - V_p0], pc);
-                               i++;
-                               break;
-
-                       case V_s0: case V_s1: case V_s2: case V_s3: case V_s4:
-                               if(g)
-                                       pr[op - V_s0] = p;
-                               i++;
-                               break;
-
-                       default:
-                               diag(l, "bad biggen: %d", op);
-                               return;
-                       }
-                       if(i == VLEN || c[i] == 0)
-                               break;
-               }
-       }
-out:
-       if(lo)
-               l->xoffset -= lo;
-       if(ro)
-               r->xoffset -= ro;
-       if(to)
-               t->xoffset -= to;
-}
-
-int
-cgen64(Node *n, Node *nn)
-{
-       Type *dt;
-       uchar *args, (*cp)[VLEN], (**optab)[VLEN];
-       int li, ri, lri, dr, si, m, op, sh, cmp, true;
-       Node *c, *d, *l, *r, *t, *s, nod1, nod2, nod3, nod4, nod5;
-
-       if(debug['g']) {
-               prtree(nn, "cgen64 lhs");
-               prtree(n, "cgen64");
-               print("AX = %d\n", reg[D_AX]);
-       }
-       cmp = 0;
-       sh = 0;
-
-       switch(n->op) {
-       case ONEG:
-               d = regpair(nn, n);
-               sugen(n->left, d, 8);
-               gins(ANOTL, Z, d->right);
-               gins(ANEGL, Z, d->left);
-               gins(ASBBL, nodconst(-1), d->right);
-               break;
-
-       case OCOM:
-               if(!vaddr(n->left, 0) || !vaddr(nn, 0))
-                       d = regpair(nn, n);
-               else
-                       return 0;
-               sugen(n->left, d, 8);
-               gins(ANOTL, Z, d->left);
-               gins(ANOTL, Z, d->right);
-               break;
-
-       case OADD:
-               optab = ADDtab;
-               args = ADDargs;
-               goto twoop;
-       case OAND:
-               optab = ANDtab;
-               args = ANDargs;
-               goto twoop;
-       case OOR:
-               optab = ORtab;
-               args = ORargs;
-               goto twoop;
-       case OSUB:
-               optab = SUBtab;
-               args = SUBargs;
-               goto twoop;
-       case OXOR:
-               optab = ORtab;
-               args = XORargs;
-               goto twoop;
-       case OASHL:
-               sh = 1;
-               args = nil;
-               optab = shlltab;
-               goto twoop;
-       case OLSHR:
-               sh = 1;
-               args = shrlargs;
-               optab = shrltab;
-               goto twoop;
-       case OASHR:
-               sh = 1;
-               args = sarlargs;
-               optab = shrltab;
-               goto twoop;
-       case OEQ:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case ONE:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OLE:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OLT:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OGE:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OGT:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OHI:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OHS:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OLO:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-       case OLS:
-               cmp = 1;
-               args = nil;
-               optab = nil;
-               goto twoop;
-
-twoop:
-               dr = nn != Z && nn->op == OREGPAIR;
-               l = vfunc(n->left, nn);
-               if(sh)
-                       r = n->right;
-               else
-                       r = vfunc(n->right, nn);
-
-               li = l->op == ONAME || l->op == OINDREG || l->op == OCONST;
-               ri = r->op == ONAME || r->op == OINDREG || r->op == OCONST;
-
-#define        IMM(l, r)       ((l) | ((r) << 1))
-
-               lri = IMM(li, ri);
-
-               /* find out what is so easy about some operands */
-               if(li)
-                       li = whatof(l, sh | cmp);
-               if(ri)
-                       ri = whatof(r, cmp);
-
-               if(sh)
-                       goto shift;
-
-               if(cmp)
-                       goto cmp;
-
-               /* evaluate hard subexps, stealing nn if possible. */
-               switch(lri) {
-               case IMM(0, 0):
-               bin00:
-                       if(l->complex > r->complex) {
-                               if(dr)
-                                       t = nn;
-                               else
-                                       t = regpair(Z, n);
-                               sugen(l, t, 8);
-                               l = t;
-                               t = regpair(Z, n);
-                               sugen(r, t, 8);
-                               r = t;
-                       }
-                       else {
-                               t = regpair(Z, n);
-                               sugen(r, t, 8);
-                               r = t;
-                               if(dr)
-                                       t = nn;
-                               else
-                                       t = regpair(Z, n);
-                               sugen(l, t, 8);
-                               l = t;
-                       }
-                       break;
-               case IMM(0, 1):
-                       if(dr)
-                               t = nn;
-                       else
-                               t = regpair(Z, n);
-                       sugen(l, t, 8);
-                       l = t;
-                       break;
-               case IMM(1, 0):
-                       if(n->op == OSUB && l->op == OCONST && hi64v(l) == 0) {
-                               lri = IMM(0, 0);
-                               goto bin00;
-                       }
-                       if(dr)
-                               t = nn;
-                       else
-                               t = regpair(Z, n);
-                       sugen(r, t, 8);
-                       r = t;
-                       break;
-               case IMM(1, 1):
-                       break;
-               }
-
-#define        WW(l, r)        ((l) | ((r) << 2))
-               d = Z;
-               dt = nn->type;
-               nn->type = types[TLONG];
-
-               switch(lri) {
-               case IMM(0, 0):
-                       biggen(l, r, Z, 0, binop00, args);
-                       break;
-               case IMM(0, 1):
-                       switch(ri) {
-                       case WNONE:
-                               diag(r, "bad whatof\n");
-                               break;
-                       case WCONST:
-                               biggen(l, r, Z, 0, optab[B0c], args);
-                               break;
-                       case WHARD:
-                               reglcgen(&nod2, r, Z);
-                               r = &nod2;
-                               /* fall thru */
-                       case WADDR:
-                               biggen(l, r, Z, 0, binoptmp, args);
-                               if(ri == WHARD)
-                                       regfree(r);
-                               break;
-                       }
-                       break;
-               case IMM(1, 0):
-                       if(n->op == OSUB) {
-                               switch(li) {
-                               case WNONE:
-                                       diag(l, "bad whatof\n");
-                                       break;
-                               case WHARD:
-                                       reglcgen(&nod2, l, Z);
-                                       l = &nod2;
-                                       /* fall thru */
-                               case WADDR:
-                               case WCONST:
-                                       biggen(l, r, Z, 0, sub10, args);
-                                       break;
-                               }
-                               if(li == WHARD)
-                                       regfree(l);
-                       }
-                       else {
-                               switch(li) {
-                               case WNONE:
-                                       diag(l, "bad whatof\n");
-                                       break;
-                               case WCONST:
-                                       biggen(r, l, Z, 0, optab[B0c], args);
-                                       break;
-                               case WHARD:
-                                       reglcgen(&nod2, l, Z);
-                                       l = &nod2;
-                                       /* fall thru */
-                               case WADDR:
-                                       biggen(r, l, Z, 0, binoptmp, args);
-                                       if(li == WHARD)
-                                               regfree(l);
-                                       break;
-                               }
-                       }
-                       break;
-               case IMM(1, 1):
-                       switch(WW(li, ri)) {
-                       case WW(WCONST, WHARD):
-                               if(r->op == ONAME && n->op == OAND && reduxv(l))
-                                       ri = WADDR;
-                               break;
-                       case WW(WHARD, WCONST):
-                               if(l->op == ONAME && n->op == OAND && reduxv(r))
-                                       li = WADDR;
-                               break;
-                       }
-                       if(li == WHARD) {
-                               reglcgen(&nod3, l, Z);
-                               l = &nod3;
-                       }
-                       if(ri == WHARD) {
-                               reglcgen(&nod2, r, Z);
-                               r = &nod2;
-                       }
-                       d = regpair(nn, n);
-                       instpair(d, Z);
-                       switch(WW(li, ri)) {
-                       case WW(WCONST, WADDR):
-                       case WW(WCONST, WHARD):
-                               biggen(l, r, d, 0, optab[Bca], args);
-                               break;
-
-                       case WW(WADDR, WCONST):
-                       case WW(WHARD, WCONST):
-                               biggen(l, r, d, 0, optab[Bac], args);
-                               break;
-
-                       case WW(WADDR, WADDR):
-                       case WW(WADDR, WHARD):
-                       case WW(WHARD, WADDR):
-                       case WW(WHARD, WHARD):
-                               biggen(l, r, d, 0, binop11, args);
-                               break;
-
-                       default:
-                               diag(r, "bad whatof pair %d %d\n", li, ri);
-                               break;
-                       }
-                       if(li == WHARD)
-                               regfree(l);
-                       if(ri == WHARD)
-                               regfree(r);
-                       break;
-               }
-
-               nn->type = dt;
-
-               if(d != Z)
-                       goto finished;
-
-               switch(lri) {
-               case IMM(0, 0):
-                       freepair(r);
-                       /* fall thru */;
-               case IMM(0, 1):
-                       if(!dr)
-                               storepair(l, nn, 1);
-                       break;
-               case IMM(1, 0):
-                       if(!dr)
-                               storepair(r, nn, 1);
-                       break;
-               case IMM(1, 1):
-                       break;
-               }
-               return 1;
-
-       shift:
-               c = Z;
-
-               /* evaluate hard subexps, stealing nn if possible. */
-               /* must also secure CX.  not as many optims as binop. */
-               switch(lri) {
-               case IMM(0, 0):
-               imm00:
-                       if(l->complex + 1 > r->complex) {
-                               if(dr)
-                                       t = nn;
-                               else
-                                       t = regpair(Z, l);
-                               sugen(l, t, 8);
-                               l = t;
-                               t = &nod1;
-                               c = snarfreg(l, t, D_CX, r, &nod2);
-                               cgen(r, t);
-                               r = t;
-                       }
-                       else {
-                               t = &nod1;
-                               c = snarfreg(nn, t, D_CX, r, &nod2);
-                               cgen(r, t);
-                               r = t;
-                               if(dr)
-                                       t = nn;
-                               else
-                                       t = regpair(Z, l);
-                               sugen(l, t, 8);
-                               l = t;
-                       }
-                       break;
-               case IMM(0, 1):
-               imm01:
-                       if(ri != WCONST) {
-                               lri = IMM(0, 0);
-                               goto imm00;
-                       }
-                       if(dr)
-                               t = nn;
-                       else
-                               t = regpair(Z, n);
-                       sugen(l, t, 8);
-                       l = t;
-                       break;
-               case IMM(1, 0):
-               imm10:
-                       if(li != WCONST) {
-                               lri = IMM(0, 0);
-                               goto imm00;
-                       }
-                       t = &nod1;
-                       c = snarfreg(nn, t, D_CX, r, &nod2);
-                       cgen(r, t);
-                       r = t;
-                       break;
-               case IMM(1, 1):
-                       if(ri != WCONST) {
-                               lri = IMM(1, 0);
-                               goto imm10;
-                       }
-                       if(li == WHARD) {
-                               lri = IMM(0, 1);
-                               goto imm01;
-                       }
-                       break;
-               }
-
-               d = Z;
-
-               switch(lri) {
-               case IMM(0, 0):
-                       biggen(l, r, Z, 0, optab[S00], args);
-                       break;
-               case IMM(0, 1):
-                       switch(ri) {
-                       case WNONE:
-                       case WADDR:
-                       case WHARD:
-                               diag(r, "bad whatof\n");
-                               break;
-                       case WCONST:
-                               m = r->vconst & 63;
-                               s = nodconst(m);
-                               if(m < 32)
-                                       cp = optab[Sc0];
-                               else if(m == 32)
-                                       cp = optab[Sc1];
-                               else
-                                       cp = optab[Sc2];
-                               biggen(l, s, Z, 0, cp, args);
-                               break;
-                       }
-                       break;
-               case IMM(1, 0):
-                       /* left is const */
-                       d = regpair(nn, n);
-                       instpair(d, Z);
-                       biggen(l, r, d, 0, optab[S10], args);
-                       regfree(r);
-                       break;
-               case IMM(1, 1):
-                       d = regpair(nn, n);
-                       instpair(d, Z);
-                       switch(WW(li, ri)) {
-                       case WW(WADDR, WCONST):
-                               m = r->vconst & 63;
-                               s = nodconst(m);
-                               if(m < 32) {
-                                       loadpair(l, d);
-                                       l = d;
-                                       cp = optab[Sc0];
-                               }
-                               else if(m == 32)
-                                       cp = optab[Sac3];
-                               else
-                                       cp = optab[Sac4];
-                               biggen(l, s, d, 0, cp, args);
-                               break;
-
-                       default:
-                               diag(r, "bad whatof pair %d %d\n", li, ri);
-                               break;
-                       }
-                       break;
-               }
-
-               if(c != Z) {
-                       gins(AMOVL, c, r);
-                       regfree(c);
-               }
-
-               if(d != Z)
-                       goto finished;
-
-               switch(lri) {
-               case IMM(0, 0):
-                       regfree(r);
-                       /* fall thru */
-               case IMM(0, 1):
-                       if(!dr)
-                               storepair(l, nn, 1);
-                       break;
-               case IMM(1, 0):
-                       regfree(r);
-                       break;
-               case IMM(1, 1):
-                       break;
-               }
-               return 1;
-
-       cmp:
-               op = n->op;
-               /* evaluate hard subexps */
-               switch(lri) {
-               case IMM(0, 0):
-                       if(l->complex > r->complex) {
-                               t = regpair(Z, l);
-                               sugen(l, t, 8);
-                               l = t;
-                               t = regpair(Z, r);
-                               sugen(r, t, 8);
-                               r = t;
-                       }
-                       else {
-                               t = regpair(Z, r);
-                               sugen(r, t, 8);
-                               r = t;
-                               t = regpair(Z, l);
-                               sugen(l, t, 8);
-                               l = t;
-                       }
-                       break;
-               case IMM(1, 0):
-                       t = r;
-                       r = l;
-                       l = t;
-                       ri = li;
-                       op = invrel[relindex(op)];
-                       /* fall thru */
-               case IMM(0, 1):
-                       t = regpair(Z, l);
-                       sugen(l, t, 8);
-                       l = t;
-                       break;
-               case IMM(1, 1):
-                       break;
-               }
-
-               true = 1;
-               optab = cmptab;
-               switch(op) {
-               case OEQ:
-                       optab = NEtab;
-                       true = 0;
-                       break;
-               case ONE:
-                       optab = NEtab;
-                       break;
-               case OLE:
-                       args = GTargs;
-                       true = 0;
-                       break;
-               case OGT:
-                       args = GTargs;
-                       break;
-               case OLS:
-                       args = HIargs;
-                       true = 0;
-                       break;
-               case OHI:
-                       args = HIargs;
-                       break;
-               case OLT:
-                       args = GEargs;
-                       true = 0;
-                       break;
-               case OGE:
-                       args = GEargs;
-                       break;
-               case OLO:
-                       args = HSargs;
-                       true = 0;
-                       break;
-               case OHS:
-                       args = HSargs;
-                       break;
-               default:
-                       diag(n, "bad cmp\n");
-                       SET(optab);
-               }
-
-               switch(lri) {
-               case IMM(0, 0):
-                       biggen(l, r, Z, true, optab[T0i], args);
-                       break;
-               case IMM(0, 1):
-               case IMM(1, 0):
-                       switch(ri) {
-                       case WNONE:
-                               diag(l, "bad whatof\n");
-                               break;
-                       case WCONST:
-                               biggen(l, r, Z, true, optab[T0i], args);
-                               break;
-                       case WHARD:
-                               reglcgen(&nod2, r, Z);
-                               r = &nod2;
-                               /* fall thru */
-                       case WADDR:
-                               biggen(l, r, Z, true, optab[T0i], args);
-                               if(ri == WHARD)
-                                       regfree(r);
-                               break;
-                       }
-                       break;
-               case IMM(1, 1):
-                       if(li == WHARD) {
-                               reglcgen(&nod3, l, Z);
-                               l = &nod3;
-                       }
-                       if(ri == WHARD) {
-                               reglcgen(&nod2, r, Z);
-                               r = &nod2;
-                       }
-                       biggen(l, r, Z, true, optab[Tii], args);
-                       if(li == WHARD)
-                               regfree(l);
-                       if(ri == WHARD)
-                               regfree(r);
-                       break;
-               }
-
-               switch(lri) {
-               case IMM(0, 0):
-                       freepair(r);
-                       /* fall thru */;
-               case IMM(0, 1):
-               case IMM(1, 0):
-                       freepair(l);
-                       break;
-               case IMM(1, 1):
-                       break;
-               }
-               return 1;
-
-       case OASMUL:
-       case OASLMUL:
-               m = 0;
-               goto mulop;
-
-       case OMUL:
-       case OLMUL:
-               m = 1;
-               goto mulop;
-
-       mulop:
-               dr = nn != Z && nn->op == OREGPAIR;
-               l = vfunc(n->left, nn);
-               r = vfunc(n->right, nn);
-               if(r->op != OCONST) {
-                       if(l->complex > r->complex) {
-                               if(m) {
-                                       t = l;
-                                       l = r;
-                                       r = t;
-                               }
-                               else if(!vaddr(l, 1)) {
-                                       reglcgen(&nod5, l, Z);
-                                       l = &nod5;
-                                       evacaxdx(l);
-                               }
-                       }
-                       t = regpair(Z, n);
-                       sugen(r, t, 8);
-                       r = t;
-                       evacaxdx(r->left);
-                       evacaxdx(r->right);
-                       if(l->complex <= r->complex && !m && !vaddr(l, 1)) {
-                               reglcgen(&nod5, l, Z);
-                               l = &nod5;
-                               evacaxdx(l);
-                       }
-               }
-               if(dr)
-                       t = nn;
-               else
-                       t = regpair(Z, n);
-               c = Z;
-               d = Z;
-               if(!nodreg(&nod1, t->left, D_AX)) {
-                       if(t->left->reg != D_AX){
-                               t->left->reg = D_AX;
-                               reg[D_AX]++;
-                       }else if(reg[D_AX] == 0)
-                               fatal(Z, "vlong mul AX botch");
-               }
-               if(!nodreg(&nod2, t->right, D_DX)) {
-                       if(t->right->reg != D_DX){
-                               t->right->reg = D_DX;
-                               reg[D_DX]++;
-                       }else if(reg[D_DX] == 0)
-                               fatal(Z, "vlong mul DX botch");
-               }
-               if(m)
-                       sugen(l, t, 8);
-               else
-                       loadpair(l, t);
-               if(t->left->reg != D_AX) {
-                       c = &nod3;
-                       regsalloc(c, t->left);
-                       gmove(&nod1, c);
-                       gmove(t->left, &nod1);
-                       zapreg(t->left);
-               }
-               if(t->right->reg != D_DX) {
-                       d = &nod4;
-                       regsalloc(d, t->right);
-                       gmove(&nod2, d);
-                       gmove(t->right, &nod2);
-                       zapreg(t->right);
-               }
-               if(c != Z || d != Z) {
-                       s = regpair(Z, n);
-                       s->left = &nod1;
-                       s->right = &nod2;
-               }
-               else
-                       s = t;
-               if(r->op == OCONST) {
-                       if(hi64v(r) == 0)
-                               biggen(s, r, Z, 0, mulc32, nil);
-                       else
-                               biggen(s, r, Z, 0, mulc64, nil);
-               }
-               else
-                       biggen(s, r, Z, 0, mull, nil);
-               instpair(t, Z);
-               if(c != Z) {
-                       gmove(&nod1, t->left);
-                       gmove(&nod3, &nod1);
-               }
-               if(d != Z) {
-                       gmove(&nod2, t->right);
-                       gmove(&nod4, &nod2);
-               }
-               if(r->op == OREGPAIR)
-                       freepair(r);
-               if(!m)
-                       storepair(t, l, 0);
-               if(l == &nod5)
-                       regfree(l);
-               if(!dr) {
-                       if(nn != Z)
-                               storepair(t, nn, 1);
-                       else
-                               freepair(t);
-               }
-               return 1;
-
-       case OASADD:
-               args = ADDargs;
-               goto vasop;
-       case OASAND:
-               args = ANDargs;
-               goto vasop;
-       case OASOR:
-               args = ORargs;
-               goto vasop;
-       case OASSUB:
-               args = SUBargs;
-               goto vasop;
-       case OASXOR:
-               args = XORargs;
-               goto vasop;
-
-       vasop:
-               l = n->left;
-               r = n->right;
-               dr = nn != Z && nn->op == OREGPAIR;
-               m = 0;
-               if(l->complex > r->complex) {
-                       if(!vaddr(l, 1)) {
-                               reglcgen(&nod1, l, Z);
-                               l = &nod1;
-                       }
-                       if(!vaddr(r, 1) || nn != Z || r->op == OCONST) {
-                               if(dr)
-                                       t = nn;
-                               else
-                                       t = regpair(Z, r);
-                               sugen(r, t, 8);
-                               r = t;
-                               m = 1;
-                       }
-               }
-               else {
-                       if(!vaddr(r, 1) || nn != Z || r->op == OCONST) {
-                               if(dr)
-                                       t = nn;
-                               else
-                                       t = regpair(Z, r);
-                               sugen(r, t, 8);
-                               r = t;
-                               m = 1;
-                       }
-                       if(!vaddr(l, 1)) {
-                               reglcgen(&nod1, l, Z);
-                               l = &nod1;
-                       }
-               }
-               if(nn != Z) {
-                       if(n->op == OASSUB)
-                               biggen(l, r, Z, 0, sub10, args);
-                       else
-                               biggen(r, l, Z, 0, binoptmp, args);
-                       storepair(r, l, 0);
-               }
-               else {
-                       if(m)
-                               biggen(l, r, Z, 0, binop00, args);
-                       else
-                               biggen(l, r, Z, 0, binoptmp, args);
-               }
-               if(l == &nod1)
-                       regfree(&nod1);
-               if(m) {
-                       if(nn == Z)
-                               freepair(r);
-                       else if(!dr)
-                               storepair(r, nn, 1);
-               }
-               return 1;
-
-       case OASASHL:
-               args = nil;
-               optab = asshlltab;
-               goto assh;
-       case OASLSHR:
-               args = shrlargs;
-               optab = asshrltab;
-               goto assh;
-       case OASASHR:
-               args = sarlargs;
-               optab = asshrltab;
-               goto assh;
-
-       assh:
-               c = Z;
-               l = n->left;
-               r = n->right;
-               if(r->op == OCONST) {
-                       m = r->vconst & 63;
-                       if(m < 32)
-                               m = SAclo;
-                       else if(m == 32)
-                               m = SAc32;
-                       else
-                               m = SAchi;
-               }
-               else
-                       m = SAgen;
-               if(l->complex > r->complex) {
-                       if(!vaddr(l, 0)) {
-                               reglcgen(&nod1, l, Z);
-                               l = &nod1;
-                       }
-                       if(m == SAgen) {
-                               t = &nod2;
-                               if(l->reg == D_CX) {
-                                       regalloc(t, r, Z);
-                                       gmove(l, t);
-                                       l->reg = t->reg;
-                                       t->reg = D_CX;
-                               }
-                               else
-                                       c = snarfreg(nn, t, D_CX, r, &nod3);
-                               cgen(r, t);
-                               r = t;
-                       }
-               }
-               else {
-                       if(m == SAgen) {
-                               t = &nod2;
-                               c = snarfreg(nn, t, D_CX, r, &nod3);
-                               cgen(r, t);
-                               r = t;
-                       }
-                       if(!vaddr(l, 0)) {
-                               reglcgen(&nod1, l, Z);
-                               l = &nod1;
-                       }
-               }
-
-               if(nn != Z) {
-                       m += SAdgen - SAgen;
-                       d = regpair(nn, n);
-                       instpair(d, Z);
-                       biggen(l, r, d, 0, optab[m], args);
-                       if(l == &nod1) {
-                               regfree(&nod1);
-                               l = Z;
-                       }
-                       if(r == &nod2 && c == Z) {
-                               regfree(&nod2);
-                               r = Z;
-                       }
-                       if(d != nn)
-                               storepair(d, nn, 1);
-               }
-               else
-                       biggen(l, r, Z, 0, optab[m], args);
-
-               if(c != Z) {
-                       gins(AMOVL, c, r);
-                       regfree(c);
-               }
-               if(l == &nod1)
-                       regfree(&nod1);
-               if(r == &nod2)
-                       regfree(&nod2);
-               return 1;
-
-       case OPOSTINC:
-               args = ADDargs;
-               cp = incdecpost;
-               goto vinc;
-       case OPOSTDEC:
-               args = SUBargs;
-               cp = incdecpost;
-               goto vinc;
-       case OPREINC:
-               args = ADDargs;
-               cp = incdecpre;
-               goto vinc;
-       case OPREDEC:
-               args = SUBargs;
-               cp = incdecpre;
-               goto vinc;
-
-       vinc:
-               l = n->left;
-               if(!vaddr(l, 1)) {
-                       reglcgen(&nod1, l, Z);
-                       l = &nod1;
-               }
-               
-               if(nn != Z) {
-                       d = regpair(nn, n);
-                       instpair(d, Z);
-                       biggen(l, Z, d, 0, cp, args);
-                       if(l == &nod1) {
-                               regfree(&nod1);
-                               l = Z;
-                       }
-                       if(d != nn)
-                               storepair(d, nn, 1);
-               }
-               else
-                       biggen(l, Z, Z, 0, incdec, args);
-
-               if(l == &nod1)
-                       regfree(&nod1);
-               return 1;
-
-       case OCAST:
-               l = n->left;
-               if(typev[l->type->etype]) {
-                       if(!vaddr(l, 1)) {
-                               if(l->complex + 1 > nn->complex) {
-                                       d = regpair(Z, l);
-                                       sugen(l, d, 8);
-                                       if(!vaddr(nn, 1)) {
-                                               reglcgen(&nod1, nn, Z);
-                                               r = &nod1;
-                                       }
-                                       else
-                                               r = nn;
-                               }
-                               else {
-                                       if(!vaddr(nn, 1)) {
-                                               reglcgen(&nod1, nn, Z);
-                                               r = &nod1;
-                                       }
-                                       else
-                                               r = nn;
-                                       d = regpair(Z, l);
-                                       sugen(l, d, 8);
-                               }
-//                             d->left->type = r->type;
-                               d->left->type = types[TLONG];
-                               gmove(d->left, r);
-                               freepair(d);
-                       }
-                       else {
-                               if(nn->op != OREGISTER && !vaddr(nn, 1)) {
-                                       reglcgen(&nod1, nn, Z);
-                                       r = &nod1;
-                               }
-                               else
-                                       r = nn;
-//                             l->type = r->type;
-                               l->type = types[TLONG];
-                               gmove(l, r);
-                       }
-                       if(r != nn)
-                               regfree(r);
-               }
-               else {
-                       if(typeu[l->type->etype] || cond(l->op))
-                               si = TUNSIGNED;
-                       else
-                               si = TSIGNED;
-                       regalloc(&nod1, l, Z);
-                       cgen(l, &nod1);
-                       if(nn->op == OREGPAIR) {
-                               m = instpair(nn, &nod1);
-                               biggen(&nod1, Z, nn, si == TSIGNED, castrp, nil);
-                       }
-                       else {
-                               m = 0;
-                               if(!vaddr(nn, si != TSIGNED)) {
-                                       dt = nn->type;
-                                       nn->type = types[TLONG];
-                                       reglcgen(&nod2, nn, Z);
-                                       nn->type = dt;
-                                       nn = &nod2;
-                               }
-                               dt = nn->type;
-                               nn->type = types[TLONG];
-                               biggen(&nod1, Z, nn, si == TSIGNED, castrpa, nil);
-                               nn->type = dt;
-                               if(nn == &nod2)
-                                       regfree(&nod2);
-                       }
-                       if(!m)
-                               regfree(&nod1);
-               }
-               return 1;
-
-       default:
-               if(n->op == OREGPAIR) {
-                       storepair(n, nn, 1);
-                       return 1;
-               }
-               if(nn->op == OREGPAIR) {
-                       loadpair(n, nn);
-                       return 1;
-               }
-               return 0;
-       }
-finished:
-       if(d != nn)
-               storepair(d, nn, 1);
-       return 1;
-}
-
-void
-testv(Node *n, int true)
-{
-       Type *t;
-       Node *nn, nod;
-
-       switch(n->op) {
-       case OINDREG:
-       case ONAME:
-               biggen(n, Z, Z, true, testi, nil);
-               break;
-
-       default:
-               n = vfunc(n, n);
-               if(n->addable >= INDEXED) {
-                       t = n->type;
-                       n->type = types[TLONG];
-                       reglcgen(&nod, n, Z);
-                       n->type = t;
-                       n = &nod;
-                       biggen(n, Z, Z, true, testi, nil);
-                       if(n == &nod)
-                               regfree(n);
-               }
-               else {
-                       nn = regpair(Z, n);
-                       sugen(n, nn, 8);
-                       biggen(nn, Z, Z, true, testi, nil);
-                       freepair(nn);
-               }
-       }
-}
diff --git a/src/cmd/8c/div.c b/src/cmd/8c/div.c
deleted file mode 100644 (file)
index 1494505..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-// Inferno utils/8c/div.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/div.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
- * Based on: Granlund, T.; Montgomery, P.L.
- * "Division by Invariant Integers using Multiplication".
- * SIGPLAN Notices, Vol. 29, June 1994, page 61.
- */
-
-#define        TN(n)   ((uvlong)1 << (n))
-#define        T31     TN(31)
-#define        T32     TN(32)
-
-int
-multiplier(uint32 d, int p, uvlong *mp)
-{
-       int l;
-       uvlong mlo, mhi, tlo, thi;
-
-       l = topbit(d - 1) + 1;
-       mlo = (((TN(l) - d) << 32) / d) + T32;
-       if(l + p == 64)
-               mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
-       else
-               mhi = (TN(32 + l) + TN(32 + l - p)) / d;
-       /*assert(mlo < mhi);*/
-       while(l > 0) {
-               tlo = mlo >> 1;
-               thi = mhi >> 1;
-               if(tlo == thi)
-                       break;
-               mlo = tlo;
-               mhi = thi;
-               l--;
-       }
-       *mp = mhi;
-       return l;
-}
-
-int
-sdiv(uint32 d, uint32 *mp, int *sp)
-{
-       int s;
-       uvlong m;
-
-       s = multiplier(d, 32 - 1, &m);
-       *mp = m;
-       *sp = s;
-       if(m >= T31)
-               return 1;
-       else
-               return 0;
-}
-
-int
-udiv(uint32 d, uint32 *mp, int *sp, int *pp)
-{
-       int p, s;
-       uvlong m;
-
-       s = multiplier(d, 32, &m);
-       p = 0;
-       if(m >= T32) {
-               while((d & 1) == 0) {
-                       d >>= 1;
-                       p++;
-               }
-               s = multiplier(d, 32 - p, &m);
-       }
-       *mp = m;
-       *pp = p;
-       if(m >= T32) {
-               /*assert(p == 0);*/
-               *sp = s - 1;
-               return 1;
-       }
-       else {
-               *sp = s;
-               return 0;
-       }
-}
-
-void
-sdivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
-       int a, s;
-       uint32 m;
-       vlong c;
-
-       c = r->vconst;
-       if(c < 0)
-               c = -c;
-       a = sdiv(c, &m, &s);
-//print("a=%d i=%d s=%d m=%ux\n", a, (int32)r->vconst, s, m);
-       gins(AMOVL, nodconst(m), ax);
-       gins(AIMULL, l, Z);
-       gins(AMOVL, l, ax);
-       if(a)
-               gins(AADDL, ax, dx);
-       gins(ASHRL, nodconst(31), ax);
-       gins(ASARL, nodconst(s), dx);
-       gins(AADDL, ax, dx);
-       if(r->vconst < 0)
-               gins(ANEGL, Z, dx);
-}
-
-void
-udivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
-       int a, s, t;
-       uint32 m;
-       Node nod;
-
-       a = udiv(r->vconst, &m, &s, &t);
-//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (int32)r->vconst, t, s, m);
-       if(t != 0) {
-               gins(AMOVL, l, ax);
-               gins(ASHRL, nodconst(t), ax);
-               gins(AMOVL, nodconst(m), dx);
-               gins(AMULL, dx, Z);
-       }
-       else if(a) {
-               if(l->op != OREGISTER) {
-                       regalloc(&nod, l, Z);
-                       gins(AMOVL, l, &nod);
-                       l = &nod;
-               }
-               gins(AMOVL, nodconst(m), ax);
-               gins(AMULL, l, Z);
-               gins(AADDL, l, dx);
-               gins(ARCRL, nodconst(1), dx);
-               if(l == &nod)
-                       regfree(l);
-       }
-       else {
-               gins(AMOVL, nodconst(m), ax);
-               gins(AMULL, l, Z);
-       }
-       if(s != 0)
-               gins(ASHRL, nodconst(s), dx);
-}
-
-void
-sext(Node *d, Node *s, Node *l)
-{
-       if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
-               reg[D_DX]++;
-               gins(ACDQ, Z, Z);
-       }
-       else {
-               regalloc(d, l, Z);
-               gins(AMOVL, s, d);
-               gins(ASARL, nodconst(31), d);
-       }
-}
-
-void
-sdiv2(int32 c, int v, Node *l, Node *n)
-{
-       Node nod;
-
-       if(v > 0) {
-               if(v > 1) {
-                       sext(&nod, n, l);
-                       gins(AANDL, nodconst((1 << v) - 1), &nod);
-                       gins(AADDL, &nod, n);
-                       regfree(&nod);
-               }
-               else {
-                       gins(ACMPL, n, nodconst(0x80000000));
-                       gins(ASBBL, nodconst(-1), n);
-               }
-               gins(ASARL, nodconst(v), n);
-       }
-       if(c < 0)
-               gins(ANEGL, Z, n);
-}
-
-void
-smod2(int32 c, int v, Node *l, Node *n)
-{
-       Node nod;
-
-       if(c == 1) {
-               zeroregm(n);
-               return;
-       }
-
-       sext(&nod, n, l);
-       if(v == 0) {
-               zeroregm(n);
-               gins(AXORL, &nod, n);
-               gins(ASUBL, &nod, n);
-       }
-       else if(v > 1) {
-               gins(AANDL, nodconst((1 << v) - 1), &nod);
-               gins(AADDL, &nod, n);
-               gins(AANDL, nodconst((1 << v) - 1), n);
-               gins(ASUBL, &nod, n);
-       }
-       else {
-               gins(AANDL, nodconst(1), n);
-               gins(AXORL, &nod, n);
-               gins(ASUBL, &nod, n);
-       }
-       regfree(&nod);
-}
diff --git a/src/cmd/8c/doc.go b/src/cmd/8c/doc.go
deleted file mode 100644 (file)
index 0d07db1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +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/8c
-
-Its target architecture is the x86, referred to by these tools for historical reasons as 386.
-
-*/
-package main
diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h
deleted file mode 100644 (file)
index aa3888d..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-// Inferno utils/8c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/gc.h
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "../cc/cc.h"
-#include       "../8l/8.out.h"
-
-/*
- * 8c/386
- * Intel 386
- */
-#define        SZ_CHAR         1
-#define        SZ_SHORT        2
-#define        SZ_INT          4
-#define        SZ_LONG         4
-#define        SZ_IND          4
-#define        SZ_FLOAT        4
-#define        SZ_VLONG        8
-#define        SZ_DOUBLE       8
-#define        FNX             100
-
-typedef        struct  Case    Case;
-typedef        struct  C1      C1;
-typedef        struct  Reg     Reg;
-typedef        struct  Rgn     Rgn;
-typedef        struct  Renv    Renv;
-
-EXTERN struct
-{
-       Node*   regtree;
-       Node*   basetree;
-       short   scale;
-       short   reg;
-       short   ptr;
-} idx;
-
-#define        A       ((Addr*)0)
-
-#define        INDEXED 9
-
-#define        P       ((Prog*)0)
-
-struct Case
-{
-       Case*   link;
-       int32   val;
-       int32   label;
-       char    def;
-       char    isv;
-};
-#define        C       ((Case*)0)
-
-struct C1
-{
-       int32   val;
-       int32   label;
-};
-
-struct Reg
-{
-       int32   pc;
-       int32   rpo;            /* reverse post ordering */
-
-       Bits    set;
-       Bits    use1;
-       Bits    use2;
-
-       Bits    refbehind;
-       Bits    refahead;
-       Bits    calbehind;
-       Bits    calahead;
-       Bits    regdiff;
-       Bits    act;
-
-       int32   regu;
-       int32   loop;           /* could be shorter */
-
-       Reg*    log5;
-       int32   active;
-
-       Reg*    p1;
-       Reg*    p2;
-       Reg*    p2link;
-       Reg*    s1;
-       Reg*    s2;
-       Reg*    link;
-       Prog*   prog;
-};
-#define        R       ((Reg*)0)
-
-struct Renv
-{
-       int     safe;
-       Node    base;
-       Node*   saved;
-       Node*   scope;
-};
-
-#define        NRGN    600
-struct Rgn
-{
-       Reg*    enter;
-       short   cost;
-       short   varno;
-       short   regno;
-};
-
-EXTERN int32   breakpc;
-EXTERN int32   nbreak;
-EXTERN Case*   cases;
-EXTERN Node    constnode;
-EXTERN Node    fconstnode;
-EXTERN int32   continpc;
-EXTERN int32   curarg;
-EXTERN int32   cursafe;
-EXTERN Prog*   lastp;
-EXTERN int32   maxargsafe;
-EXTERN int     mnstring;
-EXTERN Node*   nodrat;
-EXTERN Node*   nodret;
-EXTERN Node*   nodsafe;
-EXTERN int32   nrathole;
-EXTERN int32   nstring;
-EXTERN Prog*   p;
-EXTERN int32   pc;
-EXTERN Node    regnode;
-EXTERN Node    fregnode0;
-EXTERN Node    fregnode1;
-EXTERN char    string[NSNAME];
-EXTERN Sym*    symrathole;
-EXTERN Node    znode;
-EXTERN Prog    zprog;
-EXTERN int     reg[D_NONE];
-EXTERN int32   exregoffset;
-EXTERN int32   exfregoffset;
-
-#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])
-#define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define        bset(a,n)       ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define        CLOAD   5
-#define        CREF    5
-#define        CINF    1000
-#define        LOOP    3
-
-EXTERN Rgn     region[NRGN];
-EXTERN Rgn*    rgp;
-EXTERN int     nregion;
-EXTERN int     nvar;
-
-EXTERN Bits    externs;
-EXTERN Bits    params;
-EXTERN Bits    consts;
-EXTERN Bits    addrs;
-
-EXTERN int32   regbits;
-EXTERN int32   exregbits;
-
-EXTERN int     change;
-EXTERN int     suppress;
-
-EXTERN Reg*    firstr;
-EXTERN Reg*    lastr;
-EXTERN Reg     zreg;
-EXTERN Reg*    freer;
-EXTERN int32*  idom;
-EXTERN Reg**   rpo2r;
-EXTERN int32   maxnr;
-
-extern char*   anames[];
-
-/*
- * sgen.c
- */
-void   codgen(Node*, Node*);
-void   gen(Node*);
-void   noretval(int);
-void   usedset(Node*, int);
-void   xcom(Node*);
-void   indx(Node*);
-int    bcomplex(Node*, Node*);
-Prog*  gtext(Sym*, int32);
-vlong  argsize(int);
-
-/*
- * cgen.c
- */
-void   zeroregm(Node*);
-void   cgen(Node*, Node*);
-void   reglcgen(Node*, Node*, Node*);
-void   lcgen(Node*, Node*);
-void   bcgen(Node*, int);
-void   boolgen(Node*, int, Node*);
-void   sugen(Node*, Node*, int32);
-int    needreg(Node*, int);
-
-/*
- * cgen64.c
- */
-int    vaddr(Node*, int);
-void   loadpair(Node*, Node*);
-int    cgen64(Node*, Node*);
-void   testv(Node*, int);
-
-/*
- * txt.c
- */
-void   ginit(void);
-void   gclean(void);
-void   nextpc(void);
-void   gargs(Node*, Node*, Node*);
-void   garg1(Node*, Node*, Node*, int, Node**);
-Node*  nodconst(int32);
-Node*  nodfconst(double);
-int    nodreg(Node*, Node*, int);
-int    isreg(Node*, int);
-void   regret(Node*, Node*, Type*, int);
-void   regalloc(Node*, Node*, Node*);
-void   regfree(Node*);
-void   regialloc(Node*, Node*, Node*);
-void   regsalloc(Node*, Node*);
-void   regaalloc1(Node*, Node*);
-void   regaalloc(Node*, Node*);
-void   regind(Node*, Node*);
-void   gprep(Node*, Node*);
-void   naddr(Node*, Addr*);
-void   gmove(Node*, Node*);
-void   gins(int a, Node*, Node*);
-void   fgopcode(int, Node*, Node*, int, int);
-void   gopcode(int, Type*, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   gbranch(int);
-void   patch(Prog*, int32);
-int    sconst(Node*);
-void   gpseudo(int, Sym*, Node*);
-void   gprefetch(Node*);
-void   gpcdata(int, int);
-
-/*
- * swt.c
- */
-int    swcmp(const void*, const void*);
-void   doswit(Node*);
-void   swit1(C1*, int, int32, Node*);
-void   swit2(C1*, int, int32, Node*);
-void   newcase(void);
-void   bitload(Node*, Node*, Node*, Node*, Node*);
-void   bitstore(Node*, Node*, Node*, Node*, Node*);
-int32  outstring(char*, int32);
-void   nullwarn(Node*, Node*);
-void   sextern(Sym*, Node*, int32, int32);
-void   gextern(Sym*, Node*, int32, int32);
-void   outcode(void);
-
-/*
- * list
- */
-void   listinit(void);
-
-/*
- * reg.c
- */
-Reg*   rega(void);
-int    rcmp(const void*, const void*);
-void   regopt(Prog*);
-void   addmove(Reg*, int, int, int);
-Bits   mkvar(Reg*, Addr*);
-void   prop(Reg*, Bits, Bits);
-void   loopit(Reg*, int32);
-void   synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
-void   addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void   peep(void);
-void   excise(Reg*);
-Reg*   uniqp(Reg*);
-Reg*   uniqs(Reg*);
-int    regtyp(Addr*);
-int    anyvar(Addr*);
-int    subprop(Reg*);
-int    copyprop(Reg*);
-int    copy1(Addr*, Addr*, Reg*, int);
-int    copyu(Prog*, Addr*, Addr*);
-
-int    copyas(Addr*, Addr*);
-int    copyau(Addr*, Addr*);
-int    copysub(Addr*, Addr*, Addr*, int);
-int    copysub1(Prog*, Addr*, Addr*, int);
-
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
-
-#define        D_HI    D_NONE
-#define        D_LO    D_NONE
-
-/*
- * bound
- */
-void   comtarg(void);
-
-/*
- * com64
- */
-int    cond(int);
-int    com64(Node*);
-void   com64init(void);
-void   bool64(Node*);
-int32  lo64v(Node*);
-int32  hi64v(Node*);
-Node*  lo64(Node*);
-Node*  hi64(Node*);
-
-/*
- * div/mul
- */
-void   sdivgen(Node*, Node*, Node*, Node*);
-void   udivgen(Node*, Node*, Node*, Node*);
-void   sdiv2(int32, int, Node*, Node*);
-void   smod2(int32, int, Node*, Node*);
-void   mulgen(Type*, Node*, Node*);
-void   genmuladd(Node*, Node*, int, Node*);
-void   shiftit(Type*, Node*, Node*);
-
-/* wrecklessly steal a field */
-
-#define        rplink  label
diff --git a/src/cmd/8c/list.c b/src/cmd/8c/list.c
deleted file mode 100644 (file)
index 1730ecc..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Inferno utils/8c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
-       listinit8();
-}
diff --git a/src/cmd/8c/machcap.c b/src/cmd/8c/machcap.c
deleted file mode 100644 (file)
index 61e5aad..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// Inferno utils/8c/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/machcap.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-machcap(Node *n)
-{
-
-       if(n == Z)
-               return 1;       /* test */
-
-       switch(n->op) {
-       case OMUL:
-       case OLMUL:
-       case OASMUL:
-       case OASLMUL:
-               if(typechl[n->type->etype])
-                       return 1;
-               if(typev[n->type->etype]) {
-                               return 1;
-               }
-               break;
-
-       case OCOM:
-       case ONEG:
-       case OADD:
-       case OAND:
-       case OOR:
-       case OSUB:
-       case OXOR:
-       case OASHL:
-       case OLSHR:
-       case OASHR:
-               if(typechlv[n->left->type->etype])
-                       return 1;
-               break;
-
-       case OCAST:
-               if(typev[n->type->etype]) {
-                       if(typechlp[n->left->type->etype])
-                               return 1;
-               }
-               else if(!typefd[n->type->etype]) {
-                       if(typev[n->left->type->etype])
-                               return 1;
-               }
-               break;
-
-       case OCOND:
-       case OCOMMA:
-       case OLIST:
-       case OANDAND:
-       case OOROR:
-       case ONOT:
-               return 1;
-
-       case OASADD:
-       case OASSUB:
-       case OASAND:
-       case OASOR:
-       case OASXOR:
-               return 1;
-
-       case OASASHL:
-       case OASASHR:
-       case OASLSHR:
-               return 1;
-
-       case OPOSTINC:
-       case OPOSTDEC:
-       case OPREINC:
-       case OPREDEC:
-               return 1;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OGT:
-       case OLT:
-       case OGE:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               return 1;
-       }
-       return 0;
-}
diff --git a/src/cmd/8c/mul.c b/src/cmd/8c/mul.c
deleted file mode 100644 (file)
index 9955e76..0000000
+++ /dev/null
@@ -1,458 +0,0 @@
-// Inferno utils/8c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/mul.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-typedef struct Malg    Malg;
-typedef struct Mparam  Mparam;
-
-struct Malg
-{
-       schar   vals[10];
-};
-
-struct Mparam
-{
-       uint32  value;
-       schar   alg;
-       char    neg;
-       char    shift;
-       char    arg;
-       schar   off;
-};
-
-static Mparam  multab[32];
-static int     mulptr;
-
-static Malg    malgs[] =
-{
-       {0, 100},
-       {-1, 1, 100},
-       {-9, -5, -3, 3, 5, 9, 100},
-       {6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
-       {-8, -4, -2, 2, 4, 8, 100},
-};
-
-/*
- * return position of lowest 1
- */
-int
-lowbit(uint32 v)
-{
-       int s, i;
-       uint32 m;
-
-       s = 0;
-       m = 0xFFFFFFFFUL;
-       for(i = 16; i > 0; i >>= 1) {
-               m >>= i;
-               if((v & m) == 0) {
-                       v >>= i;
-                       s += i;
-               }
-       }
-       return s;
-}
-
-void
-genmuladd(Node *d, Node *s, int m, Node *a)
-{
-       Node nod;
-
-       nod.op = OINDEX;
-       nod.left = a;
-       nod.right = s;
-       nod.scale = m;
-       nod.type = types[TIND];
-       nod.xoffset = 0;
-       xcom(&nod);
-       gopcode(OADDR, d->type, &nod, d);
-}
-
-void
-mulparam(uint32 m, Mparam *mp)
-{
-       int c, i, j, n, o, q, s;
-       int bc, bi, bn, bo, bq, bs, bt;
-       schar *p;
-       int32 u;
-       uint32 t;
-
-       bc = bq = 10;
-       bi = bn = bo = bs = bt = 0;
-       for(i = 0; i < nelem(malgs); i++) {
-               for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
-               for(s = 0; s < 2; s++) {
-                       c = 10;
-                       q = 10;
-                       u = m - o;
-                       if(u == 0)
-                               continue;
-                       if(s) {
-                               o = -o;
-                               if(o > 0)
-                                       continue;
-                               u = -u;
-                       }
-                       n = lowbit(u);
-                       t = (uint32)u >> n;
-                       switch(i) {
-                       case 0:
-                               if(t == 1) {
-                                       c = s + 1;
-                                       q = 0;
-                                       break;
-                               }
-                               switch(t) {
-                               case 3:
-                               case 5:
-                               case 9:
-                                       c = s + 1;
-                                       if(n)
-                                               c++;
-                                       q = 0;
-                                       break;
-                               }
-                               if(s)
-                                       break;
-                               switch(t) {
-                               case 15:
-                               case 25:
-                               case 27:
-                               case 45:
-                               case 81:
-                                       c = 2;
-                                       if(n)
-                                               c++;
-                                       q = 1;
-                                       break;
-                               }
-                               break;
-                       case 1:
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 3;
-                                       break;
-                               }
-                               switch(t) {
-                               case 3:
-                               case 5:
-                               case 9:
-                                       c = 3;
-                                       q = 2;
-                                       break;
-                               }
-                               break;
-                       case 2:
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 2;
-                                       break;
-                               }
-                               break;
-                       case 3:
-                               if(s)
-                                       break;
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 1;
-                                       break;
-                               }
-                               break;
-                       case 4:
-                               if(t == 1) {
-                                       c = 3;
-                                       q = 0;
-                                       break;
-                               }
-                               break;
-                       }
-                       if(c < bc || (c == bc && q > bq)) {
-                               bc = c;
-                               bi = i;
-                               bn = n;
-                               bo = o;
-                               bq = q;
-                               bs = s;
-                               bt = t;
-                       }
-               }
-       }
-       mp->value = m;
-       if(bc <= 3) {
-               mp->alg = bi;
-               mp->shift = bn;
-               mp->off = bo;
-               mp->neg = bs;
-               mp->arg = bt;
-       }
-       else
-               mp->alg = -1;
-}
-
-int
-m0(int a)
-{
-       switch(a) {
-       case -2:
-       case 2:
-               return 2;
-       case -3:
-       case 3:
-               return 2;
-       case -4:
-       case 4:
-               return 4;
-       case -5:
-       case 5:
-               return 4;
-       case 6:
-               return 2;
-       case -8:
-       case 8:
-               return 8;
-       case -9:
-       case 9:
-               return 8;
-       case 10:
-               return 4;
-       case 12:
-               return 2;
-       case 15:
-               return 2;
-       case 18:
-               return 8;
-       case 20:
-               return 4;
-       case 24:
-               return 2;
-       case 25:
-               return 4;
-       case 27:
-               return 2;
-       case 36:
-               return 8;
-       case 40:
-               return 4;
-       case 45:
-               return 4;
-       case 72:
-               return 8;
-       case 81:
-               return 8;
-       }
-       diag(Z, "bad m0");
-       return 0;
-}
-
-int
-m1(int a)
-{
-       switch(a) {
-       case 15:
-               return 4;
-       case 25:
-               return 4;
-       case 27:
-               return 8;
-       case 45:
-               return 8;
-       case 81:
-               return 8;
-       }
-       diag(Z, "bad m1");
-       return 0;
-}
-
-int
-m2(int a)
-{
-       switch(a) {
-       case 6:
-               return 2;
-       case 10:
-               return 2;
-       case 12:
-               return 4;
-       case 18:
-               return 2;
-       case 20:
-               return 4;
-       case 24:
-               return 8;
-       case 36:
-               return 4;
-       case 40:
-               return 8;
-       case 72:
-               return 8;
-       }
-       diag(Z, "bad m2");
-       return 0;
-}
-
-void
-shiftit(Type *t, Node *s, Node *d)
-{
-       int32 c;
-
-       c = (int32)s->vconst & 31;
-       switch(c) {
-       case 0:
-               break;
-       case 1:
-               gopcode(OADD, t, d, d);
-               break;
-       default:
-               gopcode(OASHL, t, s, d);
-       }
-}
-
-static int
-mulgen1(uint32 v, Node *n)
-{
-       int i, o;
-       Mparam *p;
-       Node nod, nods;
-
-       for(i = 0; i < nelem(multab); i++) {
-               p = &multab[i];
-               if(p->value == v)
-                       goto found;
-       }
-
-       p = &multab[mulptr];
-       if(++mulptr == nelem(multab))
-               mulptr = 0;
-
-       mulparam(v, p);
-
-found:
-//     print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
-       if(p->alg < 0)
-               return 0;
-
-       nods = *nodconst(p->shift);
-
-       o = OADD;
-       if(p->alg > 0) {
-               regalloc(&nod, n, Z);
-               if(p->off < 0)
-                       o = OSUB;
-       }
-
-       switch(p->alg) {
-       case 0:
-               switch(p->arg) {
-               case 1:
-                       shiftit(n->type, &nods, n);
-                       break;
-               case 15:
-               case 25:
-               case 27:
-               case 45:
-               case 81:
-                       genmuladd(n, n, m1(p->arg), n);
-                       /* fall thru */
-               case 3:
-               case 5:
-               case 9:
-                       genmuladd(n, n, m0(p->arg), n);
-                       shiftit(n->type, &nods, n);
-                       break;
-               default:
-                       goto bad;
-               }
-               if(p->neg == 1)
-                       gins(ANEGL, Z, n);
-               break;
-       case 1:
-               switch(p->arg) {
-               case 1:
-                       gmove(n, &nod);
-                       shiftit(n->type, &nods, &nod);
-                       break;
-               case 3:
-               case 5:
-               case 9:
-                       genmuladd(&nod, n, m0(p->arg), n);
-                       shiftit(n->type, &nods, &nod);
-                       break;
-               default:
-                       goto bad;
-               }
-               if(p->neg)
-                       gopcode(o, n->type, &nod, n);
-               else {
-                       gopcode(o, n->type, n, &nod);
-                       gmove(&nod, n);
-               }
-               break;
-       case 2:
-               genmuladd(&nod, n, m0(p->off), n);
-               shiftit(n->type, &nods, n);
-               goto comop;
-       case 3:
-               genmuladd(&nod, n, m0(p->off), n);
-               shiftit(n->type, &nods, n);
-               genmuladd(n, &nod, m2(p->off), n);
-               break;
-       case 4:
-               genmuladd(&nod, n, m0(p->off), nodconst(0));
-               shiftit(n->type, &nods, n);
-               goto comop;
-       default:
-               diag(Z, "bad mul alg");
-               break;
-       comop:
-               if(p->neg) {
-                       gopcode(o, n->type, n, &nod);
-                       gmove(&nod, n);
-               }
-               else
-                       gopcode(o, n->type, &nod, n);
-       }
-
-       if(p->alg > 0)
-               regfree(&nod);
-
-       return 1;
-
-bad:
-       diag(Z, "mulgen botch");
-       return 1;
-}
-
-void
-mulgen(Type *t, Node *r, Node *n)
-{
-       if(!mulgen1(r->vconst, n))
-               gopcode(OMUL, t, r, n);
-}
diff --git a/src/cmd/8c/peep.c b/src/cmd/8c/peep.c
deleted file mode 100644 (file)
index 4f58fc0..0000000
+++ /dev/null
@@ -1,807 +0,0 @@
-// Inferno utils/8c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/peep.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static int
-needc(Prog *p)
-{
-       while(p != P) {
-               switch(p->as) {
-               case AADCL:
-               case ASBBL:
-               case ARCRL:
-                       return 1;
-               case AADDL:
-               case ASUBL:
-               case AJMP:
-               case ARET:
-               case ACALL:
-                       return 0;
-               default:
-                       if(p->to.type == D_BRANCH)
-                               return 0;
-               }
-               p = p->link;
-       }
-       return 0;
-}
-
-void
-peep(void)
-{
-       Reg *r, *r1, *r2;
-       Prog *p, *p1;
-       int t;
-
-       /*
-        * complete R structure
-        */
-       t = 0;
-       for(r=firstr; r!=R; r=r1) {
-               r1 = r->link;
-               if(r1 == R)
-                       break;
-               p = r->prog->link;
-               while(p != r1->prog)
-               switch(p->as) {
-               default:
-                       r2 = rega();
-                       r->link = r2;
-                       r2->link = r1;
-
-                       r2->prog = p;
-                       r2->p1 = r;
-                       r->s1 = r2;
-                       r2->s1 = r1;
-                       r1->p1 = r2;
-
-                       r = r2;
-                       t++;
-
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-                       p = p->link;
-               }
-       }
-
-       pc = 0; /* speculating it won't kill */
-
-loop1:
-
-       t = 0;
-       for(r=firstr; r!=R; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVL:
-                       if(regtyp(&p->to))
-                       if(regtyp(&p->from)) {
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-                       break;
-
-               case AMOVBLSX:
-               case AMOVBLZX:
-               case AMOVWLSX:
-               case AMOVWLZX:
-                       if(regtyp(&p->to)) {
-                               r1 = uniqs(r);
-                               if(r1 != R) {
-                                       p1 = r1->prog;
-                                       if(p->as == p1->as && p->to.type == p1->from.type)
-                                               p1->as = AMOVL;
-                               }
-                       }
-                       break;
-               case AADDL:
-               case AADDW:
-                       if(p->from.type != D_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1){
-                               if(p->as == AADDL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                       }
-                       else if(p->from.offset == 1){
-                               if(p->as == AADDL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                       }
-                       break;
-               case ASUBL:
-               case ASUBW:
-                       if(p->from.type != D_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1) {
-                               if(p->as == ASUBL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                       }
-                       else if(p->from.offset == 1){
-                               if(p->as == ASUBL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                       }
-                       break;
-               }
-       }
-       if(t)
-               goto loop1;
-}
-
-void
-excise(Reg *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       p->as = ANOP;
-       p->from = zprog.from;
-       p->to = zprog.to;
-}
-
-Reg*
-uniqp(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->p1;
-       if(r1 == R) {
-               r1 = r->p2;
-               if(r1 == R || r1->p2link != R)
-                       return R;
-       } else
-               if(r->p2 != R)
-                       return R;
-       return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
-       Reg *r1;
-
-       r1 = r->s1;
-       if(r1 == R) {
-               r1 = r->s2;
-               if(r1 == R)
-                       return R;
-       } else
-               if(r->s2 != R)
-                       return R;
-       return r1;
-}
-
-int
-regtyp(Addr *a)
-{
-       int t;
-
-       t = a->type;
-       if(t >= D_AX && t <= D_DI)
-               return 1;
-       return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-       int t;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=R; r=uniqp(r)) {
-               if(uniqs(r) == R)
-                       break;
-               p = r->prog;
-               switch(p->as) {
-               case ACALL:
-                       return 0;
-
-               case AIMULL:
-               case AIMULW:
-                       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 AROLB:
-               case AROLL:
-               case AROLW:
-               case ARORB:
-               case ARORL:
-               case ARORW:
-               case ASALB:
-               case ASALL:
-               case ASALW:
-               case ASARB:
-               case ASARL:
-               case ASARW:
-               case ASHLB:
-               case ASHLL:
-               case ASHLW:
-               case ASHRB:
-               case ASHRL:
-               case ASHRW:
-
-               case AREP:
-               case AREPN:
-
-               case ACWD:
-               case ACDQ:
-
-               case ASTOSB:
-               case ASTOSL:
-               case AMOVSB:
-               case AMOVSL:
-               case AFSTSW:
-                       return 0;
-
-               case AMOVL:
-                       if(p->to.type == v1->type)
-                               goto gotit;
-                       break;
-               }
-               if(copyau(&p->from, v2) ||
-                  copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->type;
-       v1->type = v2->type;
-       v2->type = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-int
-copyprop(Reg *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Reg *r;
-
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       for(r=firstr; r!=R; r=r->link)
-               r->active = 0;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = 1;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != R; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == R) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, A);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %D rar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %D set; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %D used+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %D used and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub %D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %D used+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, A);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %D set and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
-       switch(p->as) {
-
-       default:
-               if(debug['P'])
-                       print("unknown op %A\n", p->as);
-               return 2;
-
-       case ANEGB:
-       case ANEGW:
-       case ANEGL:
-       case ANOTB:
-       case ANOTW:
-       case ANOTL:
-               if(copyas(&p->to, v))
-                       return 2;
-               break;
-
-       case ALEAL:     /* lhs addr, rhs store */
-               if(copyas(&p->from, v))
-                       return 2;
-
-
-       case ANOP:      /* rhs store */
-       case AMOVL:
-       case AMOVBLSX:
-       case AMOVBLZX:
-       case AMOVWLSX:
-       case AMOVWLZX:
-               if(copyas(&p->to, v)) {
-                       if(s != A)
-                               return copysub(&p->from, v, s, 1);
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-               goto caseread;
-
-       case AROLB:
-       case AROLL:
-       case AROLW:
-       case ARORB:
-       case ARORL:
-       case ARORW:
-       case ASALB:
-       case ASALL:
-       case ASALW:
-       case ASARB:
-       case ASARL:
-       case ASARW:
-       case ASHLB:
-       case ASHLL:
-       case ASHLW:
-       case ASHRB:
-       case ASHRL:
-       case ASHRW:
-               if(copyas(&p->to, v))
-                       return 2;
-               if(copyas(&p->from, v))
-                       if(p->from.type == D_CX)
-                               return 2;
-               goto caseread;
-
-       case AADDB:     /* rhs rar */
-       case AADDL:
-       case AADDW:
-       case AANDB:
-       case AANDL:
-       case AANDW:
-       case ADECL:
-       case ADECW:
-       case AINCL:
-       case AINCW:
-       case ASUBB:
-       case ASUBL:
-       case ASUBW:
-       case AORB:
-       case AORL:
-       case AORW:
-       case AXORB:
-       case AXORL:
-       case AXORW:
-       case AMOVB:
-       case AMOVW:
-
-       case AFMOVB:
-       case AFMOVBP:
-       case AFMOVD:
-       case AFMOVDP:
-       case AFMOVF:
-       case AFMOVFP:
-       case AFMOVL:
-       case AFMOVLP:
-       case AFMOVV:
-       case AFMOVVP:
-       case AFMOVW:
-       case AFMOVWP:
-       case AFMOVX:
-       case AFMOVXP:
-       case AFADDDP:
-       case AFADDW:
-       case AFADDL:
-       case AFADDF:
-       case AFADDD:
-       case AFMULDP:
-       case AFMULW:
-       case AFMULL:
-       case AFMULF:
-       case AFMULD:
-       case AFSUBDP:
-       case AFSUBW:
-       case AFSUBL:
-       case AFSUBF:
-       case AFSUBD:
-       case AFSUBRDP:
-       case AFSUBRW:
-       case AFSUBRL:
-       case AFSUBRF:
-       case AFSUBRD:
-       case AFDIVDP:
-       case AFDIVW:
-       case AFDIVL:
-       case AFDIVF:
-       case AFDIVD:
-       case AFDIVRDP:
-       case AFDIVRW:
-       case AFDIVRL:
-       case AFDIVRF:
-       case AFDIVRD:
-               if(copyas(&p->to, v))
-                       return 2;
-               goto caseread;
-
-       case ACMPL:     /* read only */
-       case ACMPW:
-       case ACMPB:
-       
-       case APREFETCHT0:
-       case APREFETCHT1:
-       case APREFETCHT2:
-       case APREFETCHNTA:
-
-
-       case AFCOMB:
-       case AFCOMBP:
-       case AFCOMD:
-       case AFCOMDP:
-       case AFCOMDPP:
-       case AFCOMF:
-       case AFCOMFP:
-       case AFCOML:
-       case AFCOMLP:
-       case AFCOMW:
-       case AFCOMWP:
-       case AFUCOM:
-       case AFUCOMP:
-       case AFUCOMPP:
-       caseread:
-               if(s != A) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub(&p->to, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               break;
-
-       case AJGE:      /* no reference */
-       case AJNE:
-       case AJLE:
-       case AJEQ:
-       case AJHI:
-       case AJLS:
-       case AJMI:
-       case AJPL:
-       case AJGT:
-       case AJLT:
-       case AJCC:
-       case AJCS:
-
-       case AADJSP:
-       case AFLDZ:
-       case AWAIT:
-               break;
-
-       case AIMULL:
-       case AIMULW:
-               if(p->to.type != D_NONE) {
-                       if(copyas(&p->to, v))
-                               return 2;
-                       goto caseread;
-               }
-
-       case ADIVB:
-       case ADIVL:
-       case ADIVW:
-       case AIDIVB:
-       case AIDIVL:
-       case AIDIVW:
-       case AIMULB:
-       case AMULB:
-       case AMULL:
-       case AMULW:
-
-       case ACWD:
-       case ACDQ:
-               if(v->type == D_AX || v->type == D_DX)
-                       return 2;
-               goto caseread;
-
-       case AREP:
-       case AREPN:
-               if(v->type == D_CX)
-                       return 2;
-               goto caseread;
-
-       case AMOVSB:
-       case AMOVSL:
-               if(v->type == D_DI || v->type == D_SI)
-                       return 2;
-               goto caseread;
-
-       case ASTOSB:
-       case ASTOSL:
-               if(v->type == D_AX || v->type == D_DI)
-                       return 2;
-               goto caseread;
-
-       case AFSTSW:
-               if(v->type == D_AX)
-                       return 2;
-               goto caseread;
-
-       case AJMP:      /* funny */
-               if(s != A) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARET:      /* funny */
-               if(v->type == REGRET)
-                       return 2;
-               if(s != A)
-                       return 1;
-               return 3;
-
-       case ACALL:     /* funny */
-               if(REGARG >= 0 && v->type == (uchar)REGARG)
-                       return 2;
-
-               if(s != A) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-       }
-       return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
-       if(a->type != v->type)
-               return 0;
-       if(regtyp(v))
-               return 1;
-       if(v->type == D_AUTO || v->type == D_PARAM)
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
-       if(copyas(a, v))
-               return 1;
-       if(regtyp(v)) {
-               if(a->type-D_INDIR == v->type)
-                       return 1;
-               if(a->index == v->type)
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-       int t;
-
-       if(copyas(a, v)) {
-               t = s->type;
-               if(t >= D_AX && t <= D_DI) {
-                       if(f)
-                               a->type = t;
-               }
-               return 0;
-       }
-       if(regtyp(v)) {
-               t = v->type;
-               if(a->type == t+D_INDIR) {
-                       if(s->type == D_BP && a->index != D_NONE)
-                               return 1;       /* can't use BP-base with index */
-                       if(f)
-                               a->type = s->type+D_INDIR;
-//                     return 0;
-               }
-               if(a->index == t) {
-                       if(f)
-                               a->index = s->type;
-                       return 0;
-               }
-               return 0;
-       }
-       return 0;
-}
diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c
deleted file mode 100644 (file)
index ea862f3..0000000
+++ /dev/null
@@ -1,1438 +0,0 @@
-// Inferno utils/8c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/reg.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static void    fixjmp(Reg*);
-
-Reg*
-rega(void)
-{
-       Reg *r;
-
-       r = freer;
-       if(r == R) {
-               r = alloc(sizeof(*r));
-       } else
-               freer = r->link;
-
-       *r = zreg;
-       return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
-       Rgn *p1, *p2;
-       int c1, c2;
-
-       p1 = (Rgn*)a1;
-       p2 = (Rgn*)a2;
-       c1 = p2->cost;
-       c2 = p1->cost;
-       if(c1 -= c2)
-               return c1;
-       return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
-       Reg *r, *r1, *r2;
-       Prog *p1;
-       int i, z;
-       int32 initpc, val, npc;
-       uint32 vreg;
-       Bits bit;
-       struct
-       {
-               int32   m;
-               int32   c;
-               Reg*    p;
-       } log5[6], *lp;
-
-       firstr = R;
-       lastr = R;
-       nvar = 0;
-       regbits = RtoB(D_SP) | RtoB(D_AX);
-       for(z=0; z<BITS; z++) {
-               externs.b[z] = 0;
-               params.b[z] = 0;
-               consts.b[z] = 0;
-               addrs.b[z] = 0;
-       }
-
-       /*
-        * pass 1
-        * build aux data structure
-        * allocate pcs
-        * find use and set of variables
-        */
-       val = 5L * 5L * 5L * 5L * 5L;
-       lp = log5;
-       for(i=0; i<5; i++) {
-               lp->m = val;
-               lp->c = 0;
-               lp->p = R;
-               val /= 5L;
-               lp++;
-       }
-       val = 0;
-       for(; p != P; p = p->link) {
-               switch(p->as) {
-               case ADATA:
-               case AGLOBL:
-               case ANAME:
-               case ASIGNAME:
-               case AFUNCDATA:
-                       continue;
-               }
-               r = rega();
-               if(firstr == R) {
-                       firstr = r;
-                       lastr = r;
-               } else {
-                       lastr->link = r;
-                       r->p1 = lastr;
-                       lastr->s1 = r;
-                       lastr = r;
-               }
-               r->prog = p;
-               r->pc = val;
-               val++;
-
-               lp = log5;
-               for(i=0; i<5; i++) {
-                       lp->c--;
-                       if(lp->c <= 0) {
-                               lp->c = lp->m;
-                               if(lp->p != R)
-                                       lp->p->log5 = r;
-                               lp->p = r;
-                               (lp+1)->c = 0;
-                               break;
-                       }
-                       lp++;
-               }
-
-               r1 = r->p1;
-               if(r1 != R)
-               switch(r1->prog->as) {
-               case ARET:
-               case AJMP:
-               case AIRETL:
-                       r->p1 = R;
-                       r1->s1 = R;
-               }
-               bit = mkvar(r, &p->from);
-               if(bany(&bit))
-               switch(p->as) {
-               /*
-                * funny
-                */
-               case ALEAL:
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * left side read
-                */
-               default:
-                       for(z=0; z<BITS; z++)
-                               r->use1.b[z] |= bit.b[z];
-                       break;
-               }
-
-               bit = mkvar(r, &p->to);
-               if(bany(&bit))
-               switch(p->as) {
-               default:
-                       diag(Z, "reg: unknown op: %A", p->as);
-                       break;
-
-               /*
-                * right side read
-                */
-               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;
-
-               /*
-                * right side write
-                */
-               case ANOP:
-               case AMOVL:
-               case AMOVB:
-               case AMOVW:
-               case AMOVBLSX:
-               case AMOVBLZX:
-               case AMOVWLSX:
-               case AMOVWLZX:
-                       for(z=0; z<BITS; z++)
-                               r->set.b[z] |= bit.b[z];
-                       break;
-
-               /*
-                * right side read+write
-                */
-               case AADDB:
-               case AADDL:
-               case AADDW:
-               case AANDB:
-               case AANDL:
-               case AANDW:
-               case ASUBB:
-               case ASUBL:
-               case ASUBW:
-               case AORB:
-               case AORL:
-               case AORW:
-               case AXORB:
-               case AXORL:
-               case AXORW:
-               case ASALB:
-               case ASALL:
-               case ASALW:
-               case ASARB:
-               case ASARL:
-               case ASARW:
-               case AROLB:
-               case AROLL:
-               case AROLW:
-               case ARORB:
-               case ARORL:
-               case ARORW:
-               case ASHLB:
-               case ASHLL:
-               case ASHLW:
-               case ASHRB:
-               case ASHRL:
-               case ASHRW:
-               case AIMULL:
-               case AIMULW:
-               case ANEGL:
-               case ANOTL:
-               case AADCL:
-               case ASBBL:
-                       for(z=0; z<BITS; z++) {
-                               r->set.b[z] |= bit.b[z];
-                               r->use2.b[z] |= bit.b[z];
-                       }
-                       break;
-
-               /*
-                * funny
-                */
-               case AFMOVDP:
-               case AFMOVFP:
-               case AFMOVLP:
-               case AFMOVVP:
-               case AFMOVWP:
-               case ACALL:
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-                       break;
-               }
-
-               switch(p->as) {
-               case AIMULL:
-               case AIMULW:
-                       if(p->to.type != D_NONE)
-                               break;
-
-               case AIDIVB:
-               case AIDIVL:
-               case AIDIVW:
-               case AIMULB:
-               case ADIVB:
-               case ADIVL:
-               case ADIVW:
-               case AMULB:
-               case AMULL:
-               case AMULW:
-
-               case ACWD:
-               case ACDQ:
-                       r->regu |= RtoB(D_AX) | RtoB(D_DX);
-                       break;
-
-               case AREP:
-               case AREPN:
-               case ALOOP:
-               case ALOOPEQ:
-               case ALOOPNE:
-                       r->regu |= RtoB(D_CX);
-                       break;
-
-               case AMOVSB:
-               case AMOVSL:
-               case AMOVSW:
-               case ACMPSB:
-               case ACMPSL:
-               case ACMPSW:
-                       r->regu |= RtoB(D_SI) | RtoB(D_DI);
-                       break;
-
-               case ASTOSB:
-               case ASTOSL:
-               case ASTOSW:
-               case ASCASB:
-               case ASCASL:
-               case ASCASW:
-                       r->regu |= RtoB(D_AX) | RtoB(D_DI);
-                       break;
-
-               case AINSB:
-               case AINSL:
-               case AINSW:
-               case AOUTSB:
-               case AOUTSL:
-               case AOUTSW:
-                       r->regu |= RtoB(D_DI) | RtoB(D_DX);
-                       break;
-
-               case AFSTSW:
-               case ASAHF:
-                       r->regu |= RtoB(D_AX);
-                       break;
-               }
-       }
-       if(firstr == R)
-               return;
-       initpc = pc - val;
-       npc = val;
-
-       /*
-        * pass 2
-        * turn branch references to pointers
-        * build back pointers
-        */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       val = p->to.offset - initpc;
-                       r1 = firstr;
-                       while(r1 != R) {
-                               r2 = r1->log5;
-                               if(r2 != R && val >= r2->pc) {
-                                       r1 = r2;
-                                       continue;
-                               }
-                               if(r1->pc == val)
-                                       break;
-                               r1 = r1->link;
-                       }
-                       if(r1 == R) {
-                               nearln = p->lineno;
-                               diag(Z, "ref not found\n%P", p);
-                               continue;
-                       }
-                       if(r1 == r) {
-                               nearln = p->lineno;
-                               diag(Z, "ref to self\n%P", p);
-                               continue;
-                       }
-                       r->s2 = r1;
-                       r->p2link = r1->p2;
-                       r1->p2 = r;
-               }
-       }
-       if(debug['R']) {
-               p = firstr->prog;
-               print("\n%L %D\n", p->lineno, &p->from);
-       }
-
-       /*
-        * pass 2.1
-        * fix jumps
-        */
-       fixjmp(firstr);
-
-       /*
-        * pass 2.5
-        * find looping structure
-        */
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       change = 0;
-       loopit(firstr, npc);
-       if(debug['R'] && debug['v']) {
-               print("\nlooping structure:\n");
-               for(r = firstr; r != R; r = r->link) {
-                       print("%d:%P", r->loop, r->prog);
-                       for(z=0; z<BITS; z++)
-                               bit.b[z] = r->use1.b[z] |
-                                          r->use2.b[z] |
-                                          r->set.b[z];
-                       if(bany(&bit)) {
-                               print("\t");
-                               if(bany(&r->use1))
-                                       print(" u1=%B", r->use1);
-                               if(bany(&r->use2))
-                                       print(" u2=%B", r->use2);
-                               if(bany(&r->set))
-                                       print(" st=%B", r->set);
-                       }
-                       print("\n");
-               }
-       }
-
-       /*
-        * pass 3
-        * iterate propagating usage
-        *      back until flow graph is complete
-        */
-loop1:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       for(r = firstr; r != R; r = r->link)
-               if(r->prog->as == ARET)
-                       prop(r, zbits, zbits);
-loop11:
-       /* pick up unreachable code */
-       i = 0;
-       for(r = firstr; r != R; r = r1) {
-               r1 = r->link;
-               if(r1 && r1->active && !r->active) {
-                       prop(r, zbits, zbits);
-                       i = 1;
-               }
-       }
-       if(i)
-               goto loop11;
-       if(change)
-               goto loop1;
-
-
-       /*
-        * pass 4
-        * iterate propagating register/variable synchrony
-        *      forward until graph is complete
-        */
-loop2:
-       change = 0;
-       for(r = firstr; r != R; r = r->link)
-               r->active = 0;
-       synch(firstr, zbits);
-       if(change)
-               goto loop2;
-
-
-       /*
-        * pass 5
-        * isolate regions
-        * calculate costs (paint1)
-        */
-       r = firstr;
-       if(r) {
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
-                         ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "used and not set: %B", bit);
-                       if(debug['R'] && !debug['w'])
-                               print("used and not set: %B\n", bit);
-               }
-       }
-       if(debug['R'] && debug['v'])
-               print("\nprop structure:\n");
-       for(r = firstr; r != R; r = r->link)
-               r->act = zbits;
-       rgp = region;
-       nregion = 0;
-       for(r = firstr; r != R; r = r->link) {
-               if(debug['R'] && debug['v']) {
-                       print("%P\t", r->prog);
-                       if(bany(&r->set))
-                               print("s:%B ", r->set);
-                       if(bany(&r->refahead))
-                               print("ra:%B ", r->refahead);
-                       if(bany(&r->calahead))
-                               print("ca:%B ", r->calahead);
-                       print("\n");
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = r->set.b[z] &
-                         ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
-               if(bany(&bit)) {
-                       nearln = r->prog->lineno;
-                       warn(Z, "set and not used: %B", bit);
-                       if(debug['R'])
-                               print("set and not used: %B\n", bit);
-                       excise(r);
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
-               while(bany(&bit)) {
-                       i = bnum(bit);
-                       rgp->enter = r;
-                       rgp->varno = i;
-                       change = 0;
-                       if(debug['R'] && debug['v'])
-                               print("\n");
-                       paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
-                       if(change <= 0) {
-                               if(debug['R'])
-                                       print("%L$%d: %B\n",
-                                               r->prog->lineno, change, blsh(i));
-                               continue;
-                       }
-                       rgp->cost = change;
-                       nregion++;
-                       if(nregion >= NRGN) {
-                               fatal(Z, "too many regions");
-                               goto brk;
-                       }
-                       rgp++;
-               }
-       }
-brk:
-       qsort(region, nregion, sizeof(region[0]), rcmp);
-
-       /*
-        * pass 6
-        * determine used registers (paint2)
-        * replace code (paint3)
-        */
-       rgp = region;
-       for(i=0; i<nregion; i++) {
-               bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
-               vreg = allreg(vreg, rgp);
-               if(debug['R']) {
-                       print("%L$%d %R: %B\n",
-                               rgp->enter->prog->lineno,
-                               rgp->cost,
-                               rgp->regno,
-                               bit);
-               }
-               if(rgp->regno != 0)
-                       paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
-               rgp++;
-       }
-       /*
-        * pass 7
-        * peep-hole on basic block
-        */
-       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", (int)r->pc, r->prog);
-               print("\n");
-       }
-
-       /*
-        * pass 8
-        * recalculate pc
-        */
-       val = initpc;
-       for(r = firstr; r != R; r = r1) {
-               r->pc = val;
-               p = r->prog;
-               p1 = P;
-               r1 = r->link;
-               if(r1 != R)
-                       p1 = r1->prog;
-               for(; p != p1; p = p->link) {
-                       switch(p->as) {
-                       default:
-                               val++;
-                               break;
-
-                       case ANOP:
-                       case ADATA:
-                       case AGLOBL:
-                       case ANAME:
-                       case ASIGNAME:
-                       case AFUNCDATA:
-                               break;
-                       }
-               }
-       }
-       pc = val;
-
-       /*
-        * fix up branches
-        */
-       if(debug['R'])
-               if(bany(&addrs))
-                       print("addrs: %B\n", addrs);
-
-       r1 = 0; /* set */
-       for(r = firstr; r != R; r = r->link) {
-               p = r->prog;
-               if(p->to.type == D_BRANCH) {
-                       p->to.offset = r->s2->pc;
-                       p->to.u.branch = r->s2->prog;
-               }
-               r1 = r;
-       }
-
-       /*
-        * last pass
-        * eliminate nops
-        * free aux structures
-        */
-       for(p = firstr->prog; p != P; p = p->link){
-               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;
-       }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
-       Prog *p, *p1;
-       Addr *a;
-       Var *v;
-
-       p1 = alloc(sizeof(*p1));
-       *p1 = zprog;
-       p = r->prog;
-
-       p1->link = p->link;
-       p->link = p1;
-       p1->lineno = p->lineno;
-
-       v = var + bn;
-
-       a = &p1->to;
-       a->sym = v->sym;
-       a->offset = v->offset;
-       a->etype = v->etype;
-       a->type = v->name;
-
-       p1->as = AMOVL;
-       if(v->etype == TCHAR || v->etype == TUCHAR)
-               p1->as = AMOVB;
-       if(v->etype == TSHORT || v->etype == TUSHORT)
-               p1->as = AMOVW;
-
-       p1->from.type = rn;
-       if(!f) {
-               p1->from = *a;
-               *a = zprog.from;
-               a->type = rn;
-               if(v->etype == TUCHAR)
-                       p1->as = AMOVB;
-               if(v->etype == TUSHORT)
-                       p1->as = AMOVW;
-       }
-       if(debug['R'])
-               print("%P\t.a%P\n", p, p1);
-}
-
-uint32
-doregbits(int r)
-{
-       uint32 b;
-
-       b = 0;
-       if(r >= D_INDIR)
-               r -= D_INDIR;
-       if(r >= D_AX && r <= D_DI)
-               b |= RtoB(r);
-       else
-       if(r >= D_AL && r <= D_BL)
-               b |= RtoB(r-D_AL+D_AX);
-       else
-       if(r >= D_AH && r <= D_BH)
-               b |= RtoB(r-D_AH+D_AX);
-       return b;
-}
-
-Bits
-mkvar(Reg *r, Addr *a)
-{
-       Var *v;
-       int i, t, n, et, z;
-       int32 o;
-       Bits bit;
-       LSym *s;
-
-       /*
-        * mark registers used
-        */
-       t = a->type;
-       r->regu |= doregbits(t);
-       r->regu |= doregbits(a->index);
-
-       switch(t) {
-       default:
-               goto none;
-       case D_ADDR:
-               a->type = a->index;
-               bit = mkvar(r, a);
-               for(z=0; z<BITS; z++)
-                       addrs.b[z] |= bit.b[z];
-               a->type = t;
-               goto none;
-       case D_EXTERN:
-       case D_STATIC:
-       case D_PARAM:
-       case D_AUTO:
-               n = t;
-               break;
-       }
-       s = a->sym;
-       if(s == nil)
-               goto none;
-       if(s->name[0] == '.')
-               goto none;
-       et = a->etype;
-       o = a->offset;
-       v = var;
-       for(i=0; i<nvar; i++) {
-               if(s == v->sym)
-               if(n == v->name)
-               if(o == v->offset)
-                       goto out;
-               v++;
-       }
-       if(nvar >= NVAR)
-               fatal(Z, "variable not optimized: %s", s->name);
-       i = nvar;
-       nvar++;
-       v = &var[i];
-       v->sym = s;
-       v->offset = o;
-       v->name = n;
-       v->etype = et;
-       if(debug['R'])
-               print("bit=%2d et=%2d %D\n", i, et, a);
-
-out:
-       bit = blsh(i);
-       if(n == D_EXTERN || n == D_STATIC)
-               for(z=0; z<BITS; z++)
-                       externs.b[z] |= bit.b[z];
-       if(n == D_PARAM)
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-       if(v->etype != et || !typechlpfd[et])   /* funny punning */
-               for(z=0; z<BITS; z++)
-                       addrs.b[z] |= bit.b[z];
-       return bit;
-
-none:
-       return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
-       Reg *r1, *r2;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->p1) {
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] |= r1->refahead.b[z];
-                       if(ref.b[z] != r1->refahead.b[z]) {
-                               r1->refahead.b[z] = ref.b[z];
-                               change++;
-                       }
-                       cal.b[z] |= r1->calahead.b[z];
-                       if(cal.b[z] != r1->calahead.b[z]) {
-                               r1->calahead.b[z] = cal.b[z];
-                               change++;
-                       }
-               }
-               switch(r1->prog->as) {
-               case ACALL:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] |= ref.b[z] | externs.b[z];
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ATEXT:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = 0;
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ARET:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = externs.b[z];
-                               ref.b[z] = 0;
-                       }
-               }
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
-                               r1->use1.b[z] | r1->use2.b[z];
-                       cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
-                       r1->refbehind.b[z] = ref.b[z];
-                       r1->calbehind.b[z] = cal.b[z];
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-       }
-       for(; r != r1; r = r->p1)
-               for(r2 = r->p2; r2 != R; r2 = r2->p2link)
-                       prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- *     the actual dominators if the flow graph is reducible
- *     otherwise, dominators plus some other non-dominators.
- *     See Matthew S. Hecht and Jeffrey D. Ullman,
- *     "Analysis of a Simple Algorithm for Global Data Flow Problems",
- *     Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- *     Oct. 1-3, 1973, pp.  207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- *     such a node is a loop head.
- *     recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
-       Reg *r1;
-
-       r->rpo = 1;
-       r1 = r->s1;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       r1 = r->s2;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       rpo2r[n] = r;
-       n++;
-       return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
-       int32 t;
-
-       if(rpo1 == -1)
-               return rpo2;
-       while(rpo1 != rpo2){
-               if(rpo1 > rpo2){
-                       t = rpo2;
-                       rpo2 = rpo1;
-                       rpo1 = t;
-               }
-               while(rpo1 < rpo2){
-                       t = idom[rpo2];
-                       if(t >= rpo2)
-                               fatal(Z, "bad idom");
-                       rpo2 = t;
-               }
-       }
-       return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
-       while(s > r)
-               s = idom[s];
-       return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
-       int32 src;
-
-       src = r->rpo;
-       if(r->p1 != R && doms(idom, src, r->p1->rpo))
-               return 1;
-       for(r = r->p2; r != R; r = r->p2link)
-               if(doms(idom, src, r->rpo))
-                       return 1;
-       return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
-       if(r->rpo < head || r->active == head)
-               return;
-       r->active = head;
-       r->loop += LOOP;
-       if(r->p1 != R)
-               loopmark(rpo2r, head, r->p1);
-       for(r = r->p2; r != R; r = r->p2link)
-               loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
-       Reg *r1;
-       int32 i, d, me;
-
-       if(nr > maxnr) {
-               rpo2r = alloc(nr * sizeof(Reg*));
-               idom = alloc(nr * sizeof(int32));
-               maxnr = nr;
-       }
-
-       d = postorder(r, rpo2r, 0);
-       if(d > nr)
-               fatal(Z, "too many reg nodes");
-       nr = d;
-       for(i = 0; i < nr / 2; i++){
-               r1 = rpo2r[i];
-               rpo2r[i] = rpo2r[nr - 1 - i];
-               rpo2r[nr - 1 - i] = r1;
-       }
-       for(i = 0; i < nr; i++)
-               rpo2r[i]->rpo = i;
-
-       idom[0] = 0;
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               me = r1->rpo;
-               d = -1;
-               if(r1->p1 != R && r1->p1->rpo < me)
-                       d = r1->p1->rpo;
-               for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-                       if(r1->rpo < me)
-                               d = rpolca(idom, d, r1->rpo);
-               idom[i] = d;
-       }
-
-       for(i = 0; i < nr; i++){
-               r1 = rpo2r[i];
-               r1->loop++;
-               if(r1->p2 != R && loophead(idom, r1))
-                       loopmark(rpo2r, i, r1);
-       }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
-       Reg *r1;
-       int z;
-
-       for(r1 = r; r1 != R; r1 = r1->s1) {
-               for(z=0; z<BITS; z++) {
-                       dif.b[z] = (dif.b[z] &
-                               ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
-                                       r1->set.b[z] | r1->regdiff.b[z];
-                       if(dif.b[z] != r1->regdiff.b[z]) {
-                               r1->regdiff.b[z] = dif.b[z];
-                               change++;
-                       }
-               }
-               if(r1->active)
-                       break;
-               r1->active = 1;
-               for(z=0; z<BITS; z++)
-                       dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
-               if(r1->s2 != R)
-                       synch(r1->s2, dif);
-       }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
-       Var *v;
-       int i;
-
-       v = var + r->varno;
-       r->regno = 0;
-       switch(v->etype) {
-
-       default:
-               diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
-               break;
-
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-       case TARRAY:
-               i = BtoR(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i;
-                       return RtoB(i);
-               }
-               break;
-
-       case TDOUBLE:
-       case TFLOAT:
-               break;
-       }
-       return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L<<(bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
-               change -= CLOAD * r->loop;
-               if(debug['R'] && debug['v'])
-                       print("%d%P\td %B $%d\n", r->loop,
-                               r->prog, blsh(bn), change);
-       }
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       change += CREF * r->loop;
-                       if(p->as == AFMOVL)
-                               if(BtoR(bb) != D_F0)
-                                       change = -CINF;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tu1 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       change += CREF * r->loop;
-                       if(p->as == AFMOVL)
-                               if(BtoR(bb) != D_F0)
-                                       change = -CINF;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tu2 %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb) {
-                       change -= CLOAD * r->loop;
-                       if(p->as == AFMOVL)
-                               if(BtoR(bb) != D_F0)
-                                       change = -CINF;
-                       if(debug['R'] && debug['v'])
-                               print("%d%P\tst %B $%d\n", r->loop,
-                                       p, blsh(bn), change);
-               }
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint1(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint1(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-uint32
-regset(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Addr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = BtoR(b);
-               c = copyu(r->prog, &v, A);
-               if(c == 3)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Addr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = BtoR(b);
-               c = copyu(r->prog, &v, A);
-               if(c == 1 || c == 2 || c == 4)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
-       Reg *r1;
-       int z;
-       uint32 bb, vreg, x;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       vreg = regbits;
-       if(!(r->act.b[z] & bb))
-               return vreg;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(!(r1->act.b[z] & bb))
-                       break;
-               r = r1;
-       }
-       for(;;) {
-               r->act.b[z] &= ~bb;
-
-               vreg |= r->regu;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(!(r->act.b[z] & bb))
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-
-       bb = vreg;
-       for(; r; r=r->s1) {
-               x = r->regu & ~bb;
-               if(x) {
-                       vreg |= reguse(r, x);
-                       bb |= regset(r, x);
-               }
-       }
-       return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
-       Reg *r1;
-       Prog *p;
-       int z;
-       uint32 bb;
-
-       z = bn/32;
-       bb = 1L << (bn%32);
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               r1 = r->p1;
-               if(r1 == R)
-                       break;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
-               addmove(r, bn, rn, 0);
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = r->prog;
-
-               if(r->use1.b[z] & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->from, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       if(debug['R'])
-                               print("%P", p);
-                       addreg(&p->to, rn);
-                       if(debug['R'])
-                               print("\t.c%P\n", p);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb)
-                       addmove(r, bn, rn, 1);
-               r->regu |= rb;
-
-               if(r->refbehind.b[z] & bb)
-                       for(r1 = r->p2; r1 != R; r1 = r1->p2link)
-                               if(r1->refahead.b[z] & bb)
-                                       paint3(r1, bn, rb, rn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               r1 = r->s2;
-               if(r1 != R)
-                       if(r1->refbehind.b[z] & bb)
-                               paint3(r1, bn, rb, rn);
-               r = r->s1;
-               if(r == R)
-                       break;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
-       a->sym = 0;
-       a->offset = 0;
-       a->type = rn;
-}
-
-int32
-RtoB(int r)
-{
-
-       if(r < D_AX || r > D_DI)
-               return 0;
-       return 1L << (r-D_AX);
-}
-
-int
-BtoR(int32 b)
-{
-
-       b &= 0xffL;
-       if(b == 0)
-               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", (int)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;
-                       p->to.u.branch = r->s2->prog;
-                       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", (int)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", (int)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", (int)r->pc, r->prog);
-               print("\n");
-       }
-}
-
diff --git a/src/cmd/8c/sgen.c b/src/cmd/8c/sgen.c
deleted file mode 100644 (file)
index d647010..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-// Inferno utils/8c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/sgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
-       int32 a;
-
-       a = argsize(1);
-       if((textflag & NOSPLIT) != 0 && stkoff >= 128)
-               yyerror("stack frame too large for NOSPLIT function");
-
-       gpseudo(ATEXT, s, nodconst(stkoff));
-       p->to.type = D_CONST2;
-       p->to.offset2 = a;
-       return p;
-}
-
-void
-noretval(int n)
-{
-
-       if(n & 1) {
-               gins(ANOP, Z, Z);
-               p->to.type = REGRET;
-       }
-       if(n & 2) {
-               gins(ANOP, Z, Z);
-               p->to.type = FREGRET;
-       }
-}
-
-/* welcome to commute */
-static void
-commute(Node *n)
-{
-       Node *l, *r;
-
-       l = n->left;
-       r = n->right;
-       if(r->complex > l->complex) {
-               n->left = r;
-               n->right = l;
-       }
-}
-
-void
-indexshift(Node *n)
-{
-       int g;
-
-       if(!typechlp[n->type->etype])
-               return;
-       simplifyshift(n);
-       if(n->op == OASHL && n->right->op == OCONST){
-               g = vconst(n->right);
-               if(g >= 0 && g < 4)
-                       n->addable = 7;
-       }
-}
-
-/*
- *     calculate addressability as follows
- *             NAME ==> 10/11          name+value(SB/SP)
- *             REGISTER ==> 12         register
- *             CONST ==> 20            $value
- *             *(20) ==> 21            value
- *             &(10) ==> 13            $name+value(SB)
- *             &(11) ==> 1             $name+value(SP)
- *             (13) + (20) ==> 13      fold constants
- *             (1) + (20) ==> 1        fold constants
- *             *(13) ==> 10            back to name
- *             *(1) ==> 11             back to name
- *
- *             (20) * (X) ==> 7        multiplier in indexing
- *             (X,7) + (13,1) ==> 8    adder in indexing (addresses)
- *             (8) ==> &9(OINDEX)      index, almost addressable
- *             100                                     extern register
- *
- *     calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
-       Node *l, *r;
-       int g;
-
-       if(n == Z)
-               return;
-       l = n->left;
-       r = n->right;
-       n->complex = 0;
-       n->addable = 0;
-       switch(n->op) {
-       case OCONST:
-               n->addable = 20;
-               break;
-
-       case ONAME:
-               n->addable = 10;
-               if(n->class == CPARAM || n->class == CAUTO)
-                       n->addable = 11;
-               break;
-
-       case OEXREG:
-               n->addable = 0;
-               break;
-
-       case OREGISTER:
-               n->addable = 12;
-               break;
-
-       case OINDREG:
-               n->addable = 12;
-               break;
-
-       case OADDR:
-               xcom(l);
-               if(l->addable == 10)
-                       n->addable = 13;
-               else
-               if(l->addable == 11)
-                       n->addable = 1;
-               break;
-
-       case OADD:
-               xcom(l);
-               xcom(r);
-               if(n->type->etype != TIND)
-                       break;
-
-               switch(r->addable) {
-               case 20:
-                       switch(l->addable) {
-                       case 1:
-                       case 13:
-                       commadd:
-                               l->type = n->type;
-                               *n = *l;
-                               l = new(0, Z, Z);
-                               *l = *(n->left);
-                               l->xoffset += r->vconst;
-                               n->left = l;
-                               r = n->right;
-                               goto brk;
-                       }
-                       break;
-
-               case 1:
-               case 13:
-               case 10:
-               case 11:
-                       /* l is the base, r is the index */
-                       if(l->addable != 20)
-                               n->addable = 8;
-                       break;
-               }
-               switch(l->addable) {
-               case 20:
-                       switch(r->addable) {
-                       case 13:
-                       case 1:
-                               r = n->left;
-                               l = n->right;
-                               n->left = l;
-                               n->right = r;
-                               goto commadd;
-                       }
-                       break;
-
-               case 13:
-               case 1:
-               case 10:
-               case 11:
-                       /* r is the base, l is the index */
-                       if(r->addable != 20)
-                               n->addable = 8;
-                       break;
-               }
-               if(n->addable == 8 && !side(n)) {
-                       indx(n);
-                       l = new1(OINDEX, idx.basetree, idx.regtree);
-                       l->scale = idx.scale;
-                       l->addable = 9;
-                       l->complex = l->right->complex;
-                       l->type = l->left->type;
-                       n->op = OADDR;
-                       n->left = l;
-                       n->right = Z;
-                       n->addable = 8;
-                       break;
-               }
-               break;
-
-       case OINDEX:
-               xcom(l);
-               xcom(r);
-               n->addable = 9;
-               break;
-
-       case OIND:
-               xcom(l);
-               if(l->op == OADDR) {
-                       l = l->left;
-                       l->type = n->type;
-                       *n = *l;
-                       return;
-               }
-               switch(l->addable) {
-               case 20:
-                       n->addable = 21;
-                       break;
-               case 1:
-                       n->addable = 11;
-                       break;
-               case 13:
-                       n->addable = 10;
-                       break;
-               }
-               break;
-
-       case OASHL:
-               xcom(l);
-               xcom(r);
-               indexshift(n);
-               break;
-
-       case OMUL:
-       case OLMUL:
-               xcom(l);
-               xcom(r);
-               g = vlog(l);
-               if(g >= 0) {
-                       n->left = r;
-                       n->right = l;
-                       l = r;
-                       r = n->right;
-               }
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASHL;
-                       r->vconst = g;
-                       r->type = types[TINT];
-                       indexshift(n);
-                       break;
-               }
-commute(n);
-               break;
-
-       case OASLDIV:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASLSHR;
-                       r->vconst = g;
-                       r->type = types[TINT];
-               }
-               break;
-
-       case OLDIV:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OLSHR;
-                       r->vconst = g;
-                       r->type = types[TINT];
-                       indexshift(n);
-                       break;
-               }
-               break;
-
-       case OASLMOD:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OLMOD:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OAND;
-                       r->vconst--;
-               }
-               break;
-
-       case OASMUL:
-       case OASLMUL:
-               xcom(l);
-               xcom(r);
-               g = vlog(r);
-               if(g >= 0) {
-                       n->op = OASASHL;
-                       r->vconst = g;
-               }
-               break;
-
-       case OLSHR:
-       case OASHR:
-               xcom(l);
-               xcom(r);
-               indexshift(n);
-               break;
-
-       default:
-               if(l != Z)
-                       xcom(l);
-               if(r != Z)
-                       xcom(r);
-               break;
-       }
-brk:
-       if(n->addable >= 10)
-               return;
-       if(l != Z)
-               n->complex = l->complex;
-       if(r != Z) {
-               if(r->complex == n->complex)
-                       n->complex = r->complex+1;
-               else
-               if(r->complex > n->complex)
-                       n->complex = r->complex;
-       }
-       if(n->complex == 0)
-               n->complex++;
-
-       if(com64(n))
-               return;
-
-       switch(n->op) {
-
-       case OFUNC:
-               n->complex = FNX;
-               break;
-
-       case OLMOD:
-       case OMOD:
-       case OLMUL:
-       case OLDIV:
-       case OMUL:
-       case ODIV:
-       case OASLMUL:
-       case OASLDIV:
-       case OASLMOD:
-       case OASMUL:
-       case OASDIV:
-       case OASMOD:
-               if(r->complex >= l->complex) {
-                       n->complex = l->complex + 3;
-                       if(r->complex > n->complex)
-                               n->complex = r->complex;
-               } else {
-                       n->complex = r->complex + 3;
-                       if(l->complex > n->complex)
-                               n->complex = l->complex;
-               }
-               break;
-
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-       case OASLSHR:
-       case OASASHL:
-       case OASASHR:
-               if(r->complex >= l->complex) {
-                       n->complex = l->complex + 2;
-                       if(r->complex > n->complex)
-                               n->complex = r->complex;
-               } else {
-                       n->complex = r->complex + 2;
-                       if(l->complex > n->complex)
-                               n->complex = l->complex;
-               }
-               break;
-
-       case OADD:
-       case OXOR:
-       case OAND:
-       case OOR:
-               /*
-                * immediate operators, make const on right
-                */
-               if(l->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-               }
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLO:
-       case OLS:
-               /*
-                * compare operators, make const on left
-                */
-               if(r->op == OCONST) {
-                       n->left = r;
-                       n->right = l;
-                       n->op = invrel[relindex(n->op)];
-               }
-               break;
-       }
-}
-
-void
-indx(Node *n)
-{
-       Node *l, *r;
-
-       if(debug['x'])
-               prtree(n, "indx");
-
-       l = n->left;
-       r = n->right;
-       if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
-               n->right = l;
-               n->left = r;
-               l = r;
-               r = n->right;
-       }
-       if(l->addable != 7) {
-               idx.regtree = l;
-               idx.scale = 1;
-       } else
-       if(l->right->addable == 20) {
-               idx.regtree = l->left;
-               idx.scale = 1 << l->right->vconst;
-       } else
-       if(l->left->addable == 20) {
-               idx.regtree = l->right;
-               idx.scale = 1 << l->left->vconst;
-       } else
-               diag(n, "bad index");
-
-       idx.basetree = r;
-       if(debug['x']) {
-               print("scale = %d\n", idx.scale);
-               prtree(idx.regtree, "index");
-               prtree(idx.basetree, "base");
-       }
-}
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
deleted file mode 100644 (file)
index d960519..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-// Inferno utils/8c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/swt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
-       Node nreg;
-
-       if(typev[n->type->etype]) {
-               regsalloc(&nreg, n);
-               nreg.type = types[TVLONG];
-               cgen(n, &nreg);
-               swit2(q, nc, def, &nreg);
-               return;
-       }
-
-       regalloc(&nreg, n, Z);
-       nreg.type = types[TLONG];
-       cgen(n, &nreg);
-       swit2(q, nc, def, &nreg);
-       regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
-       C1 *r;
-       int i;
-       Prog *sp;
-
-       if(nc < 5) {
-               for(i=0; i<nc; i++) {
-                       if(debug['W'])
-                               print("case = %.8ux\n", q->val);
-                       gopcode(OEQ, n->type, n, nodconst(q->val));
-                       patch(p, q->label);
-                       q++;
-               }
-               gbranch(OGOTO);
-               patch(p, def);
-               return;
-       }
-       i = nc / 2;
-       r = q+i;
-       if(debug['W'])
-               print("case > %.8ux\n", r->val);
-       gopcode(OGT, n->type, n, nodconst(r->val));
-       sp = p;
-       gbranch(OGOTO);
-       p->as = AJEQ;
-       patch(p, r->label);
-       swit2(q, i, def, n);
-
-       if(debug['W'])
-               print("case < %.8ux\n", r->val);
-       patch(sp, pc);
-       swit2(r+1, nc-i-1, def, n);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int sh;
-       int32 v;
-       Node *l;
-
-       /*
-        * n1 gets adjusted/masked value
-        * n2 gets address of cell
-        * n3 gets contents of cell
-        */
-       l = b->left;
-       if(n2 != Z) {
-               regalloc(n1, l, nn);
-               reglcgen(n2, l, Z);
-               regalloc(n3, l, Z);
-               gmove(n2, n3);
-               gmove(n3, n1);
-       } else {
-               regalloc(n1, l, nn);
-               cgen(l, n1);
-       }
-       if(b->type->shift == 0 && typeu[b->type->etype]) {
-               v = ~0 + (1L << b->type->nbits);
-               gopcode(OAND, types[TLONG], nodconst(v), n1);
-       } else {
-               sh = 32 - b->type->shift - b->type->nbits;
-               if(sh > 0)
-                       gopcode(OASHL, types[TLONG], nodconst(sh), n1);
-               sh += b->type->shift;
-               if(sh > 0)
-                       if(typeu[b->type->etype])
-                               gopcode(OLSHR, types[TLONG], nodconst(sh), n1);
-                       else
-                               gopcode(OASHR, types[TLONG], nodconst(sh), n1);
-       }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
-       int32 v;
-       Node nod;
-       int sh;
-
-       regalloc(&nod, b->left, Z);
-       v = ~0 + (1L << b->type->nbits);
-       gopcode(OAND, types[TLONG], nodconst(v), n1);
-       gmove(n1, &nod);
-       if(nn != Z)
-               gmove(n1, nn);
-       sh = b->type->shift;
-       if(sh > 0)
-               gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
-       v <<= sh;
-       gopcode(OAND, types[TLONG], nodconst(~v), n3);
-       gopcode(OOR, types[TLONG], n3, &nod);
-       gmove(&nod, n2);
-
-       regfree(&nod);
-       regfree(n1);
-       regfree(n2);
-       regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
-       int32 r;
-
-       if(suppress)
-               return nstring;
-       r = nstring;
-       while(n) {
-               string[mnstring] = *s++;
-               mnstring++;
-               nstring++;
-               if(mnstring >= NSNAME) {
-                       gpseudo(ADATA, symstring, nodconst(0L));
-                       p->from.offset += nstring - NSNAME;
-                       p->from.scale = NSNAME;
-                       p->to.type = D_SCONST;
-                       memmove(p->to.u.sval, string, NSNAME);
-                       mnstring = 0;
-               }
-               n--;
-       }
-       return r;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       int32 e, lw;
-
-       for(e=0; e<w; e+=NSNAME) {
-               lw = NSNAME;
-               if(w-e < lw)
-                       lw = w-e;
-               gpseudo(ADATA, s, nodconst(0L));
-               p->from.offset += o+e;
-               p->from.scale = lw;
-               p->to.type = D_SCONST;
-               memmove(p->to.u.sval, a->cstring+e, lw);
-       }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
-       if(a->op == OCONST && typev[a->type->etype]) {
-               gpseudo(ADATA, s, lo64(a));
-               p->from.offset += o;
-               p->from.scale = 4;
-               gpseudo(ADATA, s, hi64(a));
-               p->from.offset += o + 4;
-               p->from.scale = 4;
-               return;
-       }
-       gpseudo(ADATA, s, a);
-       p->from.offset += o;
-       p->from.scale = w;
-       switch(p->to.type) {
-       default:
-               p->to.index = p->to.type;
-               p->to.type = D_ADDR;
-       case D_CONST:
-       case D_FCONST:
-       case D_ADDR:
-               break;
-       }
-}
-
-void
-outcode(void)
-{
-       int f;
-       Biobuf b;
-
-       f = open(outfile, OWRITE);
-       if(f < 0) {
-               diag(Z, "cannot open %s", outfile);
-               return;
-       }
-       Binit(&b, f, OWRITE);
-
-       Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       if(pragcgobuf.to > pragcgobuf.start) {
-               Bprint(&b, "\n");
-               Bprint(&b, "$$  // exports\n\n");
-               Bprint(&b, "$$  // local types\n\n");
-               Bprint(&b, "$$  // cgo\n");
-               Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
-               Bprint(&b, "\n$$\n\n");
-       }
-       Bprint(&b, "!\n");
-
-       writeobj(ctxt, &b);
-       Bterm(&b);
-       close(f);
-       lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
-       int32 o;
-       Type *v;
-       int w, packw;
-
-       o = i;
-       w = 1;
-       packw = 0;
-       switch(op) {
-       default:
-               diag(Z, "unknown align opcode %d", op);
-               break;
-
-       case Asu2:      /* padding at end of a struct */
-               w = *maxalign;
-               if(w < 1)
-                       w = 1;
-               if(packflg)
-                       packw = packflg;
-               break;
-
-       case Ael1:      /* initial align of struct element */
-               for(v=t; v->etype==TARRAY; v=v->link)
-                       ;
-               if(v->etype == TSTRUCT || v->etype == TUNION)
-                       w = v->align;
-               else {
-                       w = ewidth[v->etype];
-                       if(w == 8)
-                               w = 4;
-               }
-               if(w < 1 || w > SZ_LONG)
-                       fatal(Z, "align");
-               if(packflg) 
-                       packw = packflg;
-               break;
-
-       case Ael2:      /* width of a struct element */
-               o += t->width;
-               break;
-
-       case Aarg0:     /* initial passbyptr argument in arg list */
-               if(typesuv[t->etype]) {
-                       o = align(o, types[TIND], Aarg1, nil);
-                       o = align(o, types[TIND], Aarg2, nil);
-               }
-               break;
-
-       case Aarg1:     /* initial align of parameter */
-               w = ewidth[t->etype];
-               if(w <= 0 || w >= SZ_LONG) {
-                       w = SZ_LONG;
-                       break;
-               }
-               w = 1;          /* little endian no adjustment */
-               break;
-
-       case Aarg2:     /* width of a parameter */
-               o += t->width;
-               w = t->width;
-               if(w > SZ_LONG)
-                       w = SZ_LONG;
-               break;
-
-       case Aaut3:     /* total align of automatic */
-               o = align(o, t, Ael1, nil);
-               o = align(o, t, Ael2, nil);
-               break;
-       }
-       if(packw != 0 && xround(o, w) != xround(o, packw))
-               diag(Z, "#pragma pack changes offset of %T", t);
-       o = xround(o, w);
-       if(maxalign && *maxalign < w)
-               *maxalign = w;
-       if(debug['A'])
-               print("align %s %d %T = %d\n", bnames[op], i, t, o);
-       return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
-       v = xround(v, SZ_LONG);
-       if(v > max)
-               return v;
-       return max;
-}
diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c
deleted file mode 100644 (file)
index 7f87a0a..0000000
+++ /dev/null
@@ -1,1537 +0,0 @@
-// Inferno utils/8c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/txt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-
-int thechar = '8';
-char *thestring = "386";
-
-LinkArch       *thelinkarch = &link386;
-
-void
-linkarchinit(void)
-{
-}
-
-void
-ginit(void)
-{
-       int i;
-       Type *t;
-
-       exregoffset = 0;
-       exfregoffset = 0;
-       listinit();
-       nstring = 0;
-       mnstring = 0;
-       nrathole = 0;
-       pc = 0;
-       breakpc = -1;
-       continpc = -1;
-       cases = C;
-       lastp = P;
-       tfield = types[TLONG];
-
-       zprog.link = P;
-       zprog.as = AGOK;
-       zprog.from.type = D_NONE;
-       zprog.from.index = D_NONE;
-       zprog.from.scale = 0;
-       zprog.to = zprog.from;
-
-       regnode.op = OREGISTER;
-       regnode.class = CEXREG;
-       regnode.reg = REGTMP;
-       regnode.complex = 0;
-       regnode.addable = 11;
-       regnode.type = types[TLONG];
-
-       fregnode0 = regnode;
-       fregnode0.reg = D_F0;
-       fregnode0.type = types[TDOUBLE];
-
-       fregnode1 = fregnode0;
-       fregnode1.reg = D_F0+1;
-
-       constnode.op = OCONST;
-       constnode.class = CXXX;
-       constnode.complex = 0;
-       constnode.addable = 20;
-       constnode.type = types[TLONG];
-
-       fconstnode.op = OCONST;
-       fconstnode.class = CXXX;
-       fconstnode.complex = 0;
-       fconstnode.addable = 20;
-       fconstnode.type = types[TDOUBLE];
-
-       nodsafe = new(ONAME, Z, Z);
-       nodsafe->sym = slookup(".safe");
-       nodsafe->type = types[TINT];
-       nodsafe->etype = types[TINT]->etype;
-       nodsafe->class = CAUTO;
-       complex(nodsafe);
-
-       t = typ(TARRAY, types[TCHAR]);
-       symrathole = slookup(".rathole");
-       symrathole->class = CGLOBL;
-       symrathole->type = t;
-
-       nodrat = new(ONAME, Z, Z);
-       nodrat->sym = symrathole;
-       nodrat->type = types[TIND];
-       nodrat->etype = TVOID;
-       nodrat->class = CGLOBL;
-       complex(nodrat);
-       nodrat->type = t;
-
-       nodret = new(ONAME, Z, Z);
-       nodret->sym = slookup(".ret");
-       nodret->type = types[TIND];
-       nodret->etype = TIND;
-       nodret->class = CPARAM;
-       nodret = new(OIND, nodret, Z);
-       complex(nodret);
-
-       com64init();
-
-       for(i=0; i<nelem(reg); i++) {
-               reg[i] = 1;
-               if(i >= D_AX && i <= D_DI && i != D_SP)
-                       reg[i] = 0;
-       }
-}
-
-void
-gclean(void)
-{
-       int i;
-       Sym *s;
-
-       reg[D_SP]--;
-       for(i=D_AX; i<=D_DI; i++)
-               if(reg[i])
-                       diag(Z, "reg %R left allocated", i);
-       while(mnstring)
-               outstring("", 1L);
-       symstring->type->width = nstring;
-       symrathole->type->width = nrathole;
-       for(i=0; i<NHASH; i++)
-       for(s = hash[i]; s != S; s = s->link) {
-               if(s->type == T)
-                       continue;
-               if(s->type->width == 0)
-                       continue;
-               if(s->class != CGLOBL && s->class != CSTATIC)
-                       continue;
-               if(s->type == types[TENUM])
-                       continue;
-               gpseudo(AGLOBL, s, nodconst(s->type->width));
-       }
-       nextpc();
-       p->as = AEND;
-       outcode();
-}
-
-void
-nextpc(void)
-{
-       Plist *pl;
-
-       p = alloc(sizeof(*p));
-       *p = zprog;
-       p->lineno = nearln;
-       p->pc = pc;
-       pc++;
-       if(lastp == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastp->link = p;
-       lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
-       int32 regs;
-       Node fnxargs[20], *fnxp;
-
-       regs = cursafe;
-
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 0, &fnxp);   /* compile fns to temps */
-
-       curarg = 0;
-       fnxp = fnxargs;
-       garg1(n, tn1, tn2, 1, &fnxp);   /* compile normal args and temps */
-
-       cursafe = regs;
-}
-
-int
-nareg(void)
-{
-       int i, n;
-
-       n = 0;
-       for(i=D_AX; i<=D_DI; i++)
-               if(reg[i] == 0)
-                       n++;
-       return n;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
-       Node nod;
-
-       if(n == Z)
-               return;
-       if(n->op == OLIST) {
-               garg1(n->left, tn1, tn2, f, fnxp);
-               garg1(n->right, tn1, tn2, f, fnxp);
-               return;
-       }
-       if(f == 0) {
-               if(n->complex >= FNX) {
-                       regsalloc(*fnxp, n);
-                       nod = znode;
-                       nod.op = OAS;
-                       nod.left = *fnxp;
-                       nod.right = n;
-                       nod.type = n->type;
-                       cgen(&nod, Z);
-                       (*fnxp)++;
-               }
-               return;
-       }
-       if(typesu[n->type->etype] || typev[n->type->etype]) {
-               regaalloc(tn2, n);
-               if(n->complex >= FNX) {
-                       sugen(*fnxp, tn2, n->type->width);
-                       (*fnxp)++;
-               } else
-                       sugen(n, tn2, n->type->width);
-               return;
-       }
-       if(REGARG >= 0 && curarg == 0 && typeilp[n->type->etype]) {
-               regaalloc1(tn1, n);
-               if(n->complex >= FNX) {
-                       cgen(*fnxp, tn1);
-                       (*fnxp)++;
-               } else
-                       cgen(n, tn1);
-               return;
-       }
-       if(vconst(n) == 0) {
-               regaalloc(tn2, n);
-               gmove(n, tn2);
-               return;
-       }
-       regalloc(tn1, n, Z);
-       if(n->complex >= FNX) {
-               cgen(*fnxp, tn1);
-               (*fnxp)++;
-       } else
-               cgen(n, tn1);
-       regaalloc(tn2, n);
-       gmove(tn1, tn2);
-       regfree(tn1);
-}
-
-Node*
-nodconst(int32 v)
-{
-       constnode.vconst = v;
-       return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
-       fconstnode.fconst = d;
-       return &fconstnode;
-}
-
-int
-isreg(Node *n, int r)
-{
-
-       if(n->op == OREGISTER)
-               if(n->reg == r)
-                       return 1;
-       return 0;
-}
-
-int
-nodreg(Node *n, Node *nn, int r)
-{
-
-       *n = regnode;
-       n->reg = r;
-       if(reg[r] == 0)
-               return 0;
-       if(nn != Z) {
-               n->type = nn->type;
-               n->lineno = nn->lineno;
-               if(nn->op == OREGISTER)
-               if(nn->reg == r)
-                       return 0;
-       }
-       return 1;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
-       int r;
-
-       if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
-               r = REGRET;
-               if(typefd[nn->type->etype])
-                       r = FREGRET;
-               nodreg(n, nn, r);
-               reg[r]++;
-               return;
-       }
-       
-       if(mode == 1) {
-               // fetch returned value after call.
-               // already called gargs, so curarg is set.
-               curarg = (curarg+3) & ~3;
-               regaalloc(n, nn);
-               return;
-       }
-       
-       if(mode == 2) {
-               // store value to be returned.
-               // must compute arg offset.
-               if(t->etype != TFUNC)
-                       fatal(Z, "bad regret func %T", t);
-               *n = *nn;
-               n->op = ONAME;
-               n->class = CPARAM;
-               n->sym = slookup(".retx");
-               n->complex = 0;
-               n->addable = 20;
-               n->xoffset = argsize(0);
-               return;
-       }
-       
-       fatal(Z, "bad regret");
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
-       int i;
-
-       switch(tn->type->etype) {
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-               if(o != Z && o->op == OREGISTER) {
-                       i = o->reg;
-                       if(i >= D_AX && i <= D_DI)
-                               goto out;
-               }
-               for(i=D_AX; i<=D_DI; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               diag(tn, "out of fixed registers");
-               goto err;
-
-       case TFLOAT:
-       case TDOUBLE:
-       case TVLONG:
-               i = D_F0;
-               goto out;
-       }
-       diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
-       i = 0;
-out:
-       if(i)
-               reg[i]++;
-       nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
-       Node nod;
-
-       nod = *tn;
-       nod.type = types[TIND];
-       regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-
-       i = 0;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               goto err;
-       i = n->reg;
-       if(i < 0 || i >= nelem(reg))
-               goto err;
-       if(reg[i] <= 0)
-               goto err;
-       reg[i]--;
-       return;
-err:
-       diag(n, "error in regfree: %R", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
-       cursafe = align(cursafe, nn->type, Aaut3, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-       *n = *nodsafe;
-       n->xoffset = -(stkoff + cursafe);
-       n->type = nn->type;
-       n->etype = nn->type->etype;
-       n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
-       if(REGARG < 0) {
-               fatal(n, "regaalloc1 and REGARG<0");
-               return;
-       }
-       nodreg(n, nn, REGARG);
-       reg[REGARG]++;
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
-       curarg = align(curarg, nn->type, Aarg1, nil);
-       *n = *nn;
-       n->op = OINDREG;
-       n->reg = REGSP;
-       n->xoffset = curarg;
-       n->complex = 0;
-       n->addable = 20;
-       curarg = align(curarg, nn->type, Aarg2, nil);
-       maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
-       if(n->op != OREGISTER) {
-               diag(n, "regind not OREGISTER");
-               return;
-       }
-       n->op = OINDREG;
-       n->type = nn->type;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
-       int32 v;
-
-       a->type = D_NONE;
-       if(n == Z)
-               return;
-       switch(n->op) {
-       default:
-       bad:
-               diag(n, "bad in naddr: %O %D", n->op, a);
-               break;
-
-       case OREGISTER:
-               a->type = n->reg;
-               a->sym = nil;
-               break;
-
-       case OEXREG:
-               a->type = D_INDIR + D_TLS;
-               a->offset = n->reg - 1;
-               break;
-
-       case OIND:
-               naddr(n->left, a);
-               if(a->type >= D_AX && a->type <= D_DI)
-                       a->type += D_INDIR;
-               else
-               if(a->type == D_CONST)
-                       a->type = D_NONE+D_INDIR;
-               else
-               if(a->type == D_ADDR) {
-                       a->type = a->index;
-                       a->index = D_NONE;
-               } else
-                       goto bad;
-               break;
-
-       case OINDEX:
-               a->type = idx.ptr;
-               if(n->left->op == OADDR || n->left->op == OCONST)
-                       naddr(n->left, a);
-               if(a->type >= D_AX && a->type <= D_DI)
-                       a->type += D_INDIR;
-               else
-               if(a->type == D_CONST)
-                       a->type = D_NONE+D_INDIR;
-               else
-               if(a->type == D_ADDR) {
-                       a->type = a->index;
-                       a->index = D_NONE;
-               } else
-                       goto bad;
-               a->index = idx.reg;
-               a->scale = n->scale;
-               a->offset += n->xoffset;
-               break;
-
-       case OINDREG:
-               a->type = n->reg+D_INDIR;
-               a->sym = nil;
-               a->offset = n->xoffset;
-               break;
-
-       case ONAME:
-               a->etype = n->etype;
-               a->type = D_STATIC;
-               a->sym = linksym(n->sym);
-               a->offset = n->xoffset;
-               if(n->class == CSTATIC)
-                       break;
-               if(n->class == CEXTERN || n->class == CGLOBL) {
-                       a->type = D_EXTERN;
-                       break;
-               }
-               if(n->class == CAUTO) {
-                       a->type = D_AUTO;
-                       break;
-               }
-               if(n->class == CPARAM) {
-                       a->type = D_PARAM;
-                       break;
-               }
-               goto bad;
-
-       case OCONST:
-               if(typefd[n->type->etype]) {
-                       a->type = D_FCONST;
-                       a->u.dval = n->fconst;
-                       break;
-               }
-               a->sym = nil;
-               a->type = D_CONST;
-               a->offset = n->vconst;
-               break;
-
-       case OADDR:
-               naddr(n->left, a);
-               if(a->type >= D_INDIR) {
-                       a->type -= D_INDIR;
-                       break;
-               }
-               if(a->type == D_EXTERN || a->type == D_STATIC ||
-                  a->type == D_AUTO || a->type == D_PARAM)
-                       if(a->index == D_NONE) {
-                               a->index = a->type;
-                               a->type = D_ADDR;
-                               break;
-                       }
-               goto bad;
-
-       case OADD:
-               if(n->right->op == OCONST) {
-                       v = n->right->vconst;
-                       naddr(n->left, a);
-               } else
-               if(n->left->op == OCONST) {
-                       v = n->left->vconst;
-                       naddr(n->right, a);
-               } else
-                       goto bad;
-               a->offset += v;
-               break;
-
-       }
-}
-
-#define        CASE(a,b)       ((a<<8)|(b<<0))
-
-void
-gmove(Node *f, Node *t)
-{
-       int ft, tt, a;
-       Node nod, nod1;
-       Prog *p1;
-
-       ft = f->type->etype;
-       tt = t->type->etype;
-       if(debug['M'])
-               print("gop: %O %O[%s],%O[%s]\n", OAS,
-                       f->op, tnames[ft], t->op, tnames[tt]);
-       if(typefd[ft] && f->op == OCONST) {
-               if(f->fconst == 0)
-                       gins(AFLDZ, Z, Z);
-               else
-               if(f->fconst == 1)
-                       gins(AFLD1, Z, Z);
-               else
-                       gins(AFMOVD, f, &fregnode0);
-               gmove(&fregnode0, t);
-               return;
-       }
-/*
- * load
- */
-       if(f->op == ONAME || f->op == OINDREG ||
-          f->op == OIND || f->op == OINDEX)
-       switch(ft) {
-       case TCHAR:
-               a = AMOVBLSX;
-               goto ld;
-       case TUCHAR:
-               a = AMOVBLZX;
-               goto ld;
-       case TSHORT:
-               if(typefd[tt]) {
-                       gins(AFMOVW, f, &fregnode0);
-                       gmove(&fregnode0, t);
-                       return;
-               }
-               a = AMOVWLSX;
-               goto ld;
-       case TUSHORT:
-               a = AMOVWLZX;
-               goto ld;
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-               if(typefd[tt]) {
-                       gins(AFMOVL, f, &fregnode0);
-                       gmove(&fregnode0, t);
-                       return;
-               }
-               a = AMOVL;
-
-       ld:
-               regalloc(&nod, f, t);
-               nod.type = types[TLONG];
-               gins(a, f, &nod);
-               gmove(&nod, t);
-               regfree(&nod);
-               return;
-
-       case TFLOAT:
-               gins(AFMOVF, f, t);
-               return;
-       case TDOUBLE:
-               gins(AFMOVD, f, t);
-               return;
-       case TVLONG:
-               gins(AFMOVV, f, t);
-               return;
-       }
-
-/*
- * store
- */
-       if(t->op == ONAME || t->op == OINDREG ||
-          t->op == OIND || t->op == OINDEX)
-       switch(tt) {
-       case TCHAR:
-       case TUCHAR:
-               a = AMOVB;      goto st;
-       case TSHORT:
-       case TUSHORT:
-               a = AMOVW;      goto st;
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-               a = AMOVL;      goto st;
-
-       st:
-               if(f->op == OCONST) {
-                       gins(a, f, t);
-                       return;
-               }
-               regalloc(&nod, t, f);
-               gmove(f, &nod);
-               gins(a, &nod, t);
-               regfree(&nod);
-               return;
-
-       case TFLOAT:
-               gins(AFMOVFP, f, t);
-               return;
-       case TDOUBLE:
-               gins(AFMOVDP, f, t);
-               return;
-       case TVLONG:
-               gins(AFMOVVP, f, t);
-               return;
-       }
-
-/*
- * convert
- */
-       switch(CASE(ft,tt)) {
-       default:
-/*
- * integer to integer
- ********
-               a = AGOK;       break;
-
-       case CASE(      TCHAR,  TCHAR):
-       case CASE(      TUCHAR, TCHAR):
-       case CASE(      TSHORT, TCHAR):
-       case CASE(      TUSHORT,TCHAR):
-       case CASE(      TINT,   TCHAR):
-       case CASE(      TUINT,  TCHAR):
-       case CASE(      TLONG,  TCHAR):
-       case CASE(      TULONG, TCHAR):
-       case CASE(      TIND,   TCHAR):
-
-       case CASE(      TCHAR,  TUCHAR):
-       case CASE(      TUCHAR, TUCHAR):
-       case CASE(      TSHORT, TUCHAR):
-       case CASE(      TUSHORT,TUCHAR):
-       case CASE(      TINT,   TUCHAR):
-       case CASE(      TUINT,  TUCHAR):
-       case CASE(      TLONG,  TUCHAR):
-       case CASE(      TULONG, TUCHAR):
-       case CASE(      TIND,   TUCHAR):
-
-       case CASE(      TSHORT, TSHORT):
-       case CASE(      TUSHORT,TSHORT):
-       case CASE(      TINT,   TSHORT):
-       case CASE(      TUINT,  TSHORT):
-       case CASE(      TLONG,  TSHORT):
-       case CASE(      TULONG, TSHORT):
-       case CASE(      TIND,   TSHORT):
-
-       case CASE(      TSHORT, TUSHORT):
-       case CASE(      TUSHORT,TUSHORT):
-       case CASE(      TINT,   TUSHORT):
-       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(      TINT,   TLONG):
-       case CASE(      TUINT,  TLONG):
-       case CASE(      TLONG,  TLONG):
-       case CASE(      TULONG, TLONG):
-       case CASE(      TIND,   TLONG):
-
-       case CASE(      TINT,   TULONG):
-       case CASE(      TUINT,  TULONG):
-       case CASE(      TLONG,  TULONG):
-       case CASE(      TULONG, TULONG):
-       case CASE(      TIND,   TULONG):
-
-       case CASE(      TINT,   TIND):
-       case CASE(      TUINT,  TIND):
-       case CASE(      TLONG,  TIND):
-       case CASE(      TULONG, TIND):
-       case CASE(      TIND,   TIND):
- *****/
-               a = AMOVL;
-               break;
-
-       case CASE(      TSHORT, TINT):
-       case CASE(      TSHORT, TUINT):
-       case CASE(      TSHORT, TLONG):
-       case CASE(      TSHORT, TULONG):
-       case CASE(      TSHORT, TIND):
-               a = AMOVWLSX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xffff;
-                       if(f->vconst & 0x8000)
-                               f->vconst |= 0xffff0000;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TUSHORT,TINT):
-       case CASE(      TUSHORT,TUINT):
-       case CASE(      TUSHORT,TLONG):
-       case CASE(      TUSHORT,TULONG):
-       case CASE(      TUSHORT,TIND):
-               a = AMOVWLZX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xffff;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TCHAR,  TSHORT):
-       case CASE(      TCHAR,  TUSHORT):
-       case CASE(      TCHAR,  TINT):
-       case CASE(      TCHAR,  TUINT):
-       case CASE(      TCHAR,  TLONG):
-       case CASE(      TCHAR,  TULONG):
-       case CASE(      TCHAR,  TIND):
-               a = AMOVBLSX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xff;
-                       if(f->vconst & 0x80)
-                               f->vconst |= 0xffffff00;
-                       a = AMOVL;
-               }
-               break;
-
-       case CASE(      TUCHAR, TSHORT):
-       case CASE(      TUCHAR, TUSHORT):
-       case CASE(      TUCHAR, TINT):
-       case CASE(      TUCHAR, TUINT):
-       case CASE(      TUCHAR, TLONG):
-       case CASE(      TUCHAR, TULONG):
-       case CASE(      TUCHAR, TIND):
-               a = AMOVBLZX;
-               if(f->op == OCONST) {
-                       f->vconst &= 0xff;
-                       a = AMOVL;
-               }
-               break;
-
-/*
- * float to fix
- */
-       case CASE(      TFLOAT, TCHAR):
-       case CASE(      TFLOAT, TUCHAR):
-       case CASE(      TFLOAT, TSHORT):
-       case CASE(      TFLOAT, TUSHORT):
-       case CASE(      TFLOAT, TINT):
-       case CASE(      TFLOAT, TUINT):
-       case CASE(      TFLOAT, TLONG):
-       case CASE(      TFLOAT, TULONG):
-       case CASE(      TFLOAT, TIND):
-
-       case CASE(      TDOUBLE,TCHAR):
-       case CASE(      TDOUBLE,TUCHAR):
-       case CASE(      TDOUBLE,TSHORT):
-       case CASE(      TDOUBLE,TUSHORT):
-       case CASE(      TDOUBLE,TINT):
-       case CASE(      TDOUBLE,TUINT):
-       case CASE(      TDOUBLE,TLONG):
-       case CASE(      TDOUBLE,TULONG):
-       case CASE(      TDOUBLE,TIND):
-
-       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(      TVLONG, TIND):
-               if(fproundflg) {
-                       regsalloc(&nod, &regnode);
-                       gins(AFMOVLP, f, &nod);
-                       gmove(&nod, t);
-                       return;
-               }
-               regsalloc(&nod, &regnode);
-               regsalloc(&nod1, &regnode);
-               gins(AFSTCW, Z, &nod1);
-               nod1.xoffset += 2;
-               gins(AMOVW, nodconst(0xf7f), &nod1);
-               gins(AFLDCW, &nod1, Z);
-               gins(AFMOVLP, f, &nod);
-               nod1.xoffset -= 2;
-               gins(AFLDCW, &nod1, Z);
-               gmove(&nod, t);
-               return;
-
-/*
- * ulong to float
- */
-       case CASE(      TULONG, TDOUBLE):
-       case CASE(      TULONG, TVLONG):
-       case CASE(      TULONG, TFLOAT):
-       case CASE(      TUINT,  TDOUBLE):
-       case CASE(      TUINT,  TVLONG):
-       case CASE(      TUINT,  TFLOAT):
-               regalloc(&nod, f, f);
-               gmove(f, &nod);
-               regsalloc(&nod1, &regnode);
-               gmove(&nod, &nod1);
-               gins(AFMOVL, &nod1, &fregnode0);
-               gins(ACMPL, &nod, nodconst(0));
-               gins(AJGE, Z, Z);
-               p1 = p;
-               gins(AFADDD, nodfconst(4294967296.), &fregnode0);
-               patch(p1, pc);
-               regfree(&nod);
-               return;
-
-/*
- * fix to float
- */
-       case CASE(      TCHAR,  TFLOAT):
-       case CASE(      TUCHAR, TFLOAT):
-       case CASE(      TSHORT, TFLOAT):
-       case CASE(      TUSHORT,TFLOAT):
-       case CASE(      TINT,   TFLOAT):
-       case CASE(      TLONG,  TFLOAT):
-       case CASE(      TIND,   TFLOAT):
-
-       case CASE(      TCHAR,  TDOUBLE):
-       case CASE(      TUCHAR, TDOUBLE):
-       case CASE(      TSHORT, TDOUBLE):
-       case CASE(      TUSHORT,TDOUBLE):
-       case CASE(      TINT,   TDOUBLE):
-       case CASE(      TLONG,  TDOUBLE):
-       case CASE(      TIND,   TDOUBLE):
-
-       case CASE(      TCHAR,  TVLONG):
-       case CASE(      TUCHAR, TVLONG):
-       case CASE(      TSHORT, TVLONG):
-       case CASE(      TUSHORT,TVLONG):
-       case CASE(      TINT,   TVLONG):
-       case CASE(      TLONG,  TVLONG):
-       case CASE(      TIND,   TVLONG):
-               regsalloc(&nod, &regnode);
-               gmove(f, &nod);
-               gins(AFMOVL, &nod, &fregnode0);
-               return;
-
-/*
- * float to float
- */
-       case CASE(      TFLOAT, TFLOAT):
-       case CASE(      TDOUBLE,TFLOAT):
-       case CASE(      TVLONG, TFLOAT):
-
-       case CASE(      TFLOAT, TDOUBLE):
-       case CASE(      TDOUBLE,TDOUBLE):
-       case CASE(      TVLONG, TDOUBLE):
-
-       case CASE(      TFLOAT, TVLONG):
-       case CASE(      TDOUBLE,TVLONG):
-       case CASE(      TVLONG, TVLONG):
-               a = AFMOVD;     break;
-       }
-       if(a == AMOVL || a == AFMOVD)
-       if(samaddr(f, t))
-               return;
-       gins(a, f, t);
-}
-
-void
-doindex(Node *n)
-{
-       Node nod, nod1;
-       int32 v;
-
-if(debug['Y'])
-prtree(n, "index");
-
-if(n->left->complex >= FNX)
-print("botch in doindex\n");
-
-       regalloc(&nod, &regnode, Z);
-       v = constnode.vconst;
-       cgen(n->right, &nod);
-       idx.ptr = D_NONE;
-       if(n->left->op == OCONST)
-               idx.ptr = D_CONST;
-       else if(n->left->op == OREGISTER)
-               idx.ptr = n->left->reg;
-       else if(n->left->op != OADDR) {
-               reg[D_BP]++;    // can't be used as a base
-               regalloc(&nod1, &regnode, Z);
-               cgen(n->left, &nod1);
-               idx.ptr = nod1.reg;
-               regfree(&nod1);
-               reg[D_BP]--;
-       }
-       idx.reg = nod.reg;
-       regfree(&nod);
-       constnode.vconst = v;
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
-       if(f != Z && f->op == OINDEX)
-               doindex(f);
-       if(t != Z && t->op == OINDEX)
-               doindex(t);
-       nextpc();
-       p->as = a;
-       if(f != Z)
-               naddr(f, &p->from);
-       if(t != Z)
-               naddr(t, &p->to);
-       if(debug['g'])
-               print("%P\n", p);
-}
-
-void
-fgopcode(int o, Node *f, Node *t, int pop, int rev)
-{
-       int a, et;
-       Node nod;
-
-       et = TLONG;
-       if(f != Z && f->type != T)
-               et = f->type->etype;
-       if(!typefd[et]) {
-               diag(f, "fop: integer %O", o);
-               return;
-       }
-       if(debug['M']) {
-               if(t != Z && t->type != T)
-                       print("gop: %O %O-%s Z\n", o, f->op, tnames[et]);
-               else
-                       print("gop: %O %O-%s %O-%s\n", o,
-                               f->op, tnames[et], t->op, tnames[t->type->etype]);
-       }
-       a = AGOK;
-       switch(o) {
-
-       case OASADD:
-       case OADD:
-               if(et == TFLOAT)
-                       a = AFADDF;
-               else
-               if(et == TDOUBLE || et == TVLONG) {
-                       a = AFADDD;
-                       if(pop)
-                               a = AFADDDP;
-               }
-               break;
-
-       case OASSUB:
-       case OSUB:
-               if(et == TFLOAT) {
-                       a = AFSUBF;
-                       if(rev)
-                               a = AFSUBRF;
-               } else
-               if(et == TDOUBLE || et == TVLONG) {
-                       a = AFSUBD;
-                       if(pop)
-                               a = AFSUBDP;
-                       if(rev) {
-                               a = AFSUBRD;
-                               if(pop)
-                                       a = AFSUBRDP;
-                       }
-               }
-               break;
-
-       case OASMUL:
-       case OMUL:
-               if(et == TFLOAT)
-                       a = AFMULF;
-               else
-               if(et == TDOUBLE || et == TVLONG) {
-                       a = AFMULD;
-                       if(pop)
-                               a = AFMULDP;
-               }
-               break;
-
-       case OASMOD:
-       case OMOD:
-       case OASDIV:
-       case ODIV:
-               if(et == TFLOAT) {
-                       a = AFDIVF;
-                       if(rev)
-                               a = AFDIVRF;
-               } else
-               if(et == TDOUBLE || et == TVLONG) {
-                       a = AFDIVD;
-                       if(pop)
-                               a = AFDIVDP;
-                       if(rev) {
-                               a = AFDIVRD;
-                               if(pop)
-                                       a = AFDIVRDP;
-                       }
-               }
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-               pop += rev;
-               if(et == TFLOAT) {
-                       a = AFCOMF;
-                       if(pop) {
-                               a = AFCOMFP;
-                               if(pop > 1)
-                                       a = AGOK;
-                       }
-               } else
-               if(et == TDOUBLE || et == TVLONG) {
-                       a = AFCOMF;
-                       if(pop) {
-                               a = AFCOMDP;
-                               if(pop > 1)
-                                       a = AFCOMDPP;
-                       }
-               }
-               gins(a, f, t);
-               regalloc(&nod, &regnode, Z);
-               if(nod.reg != D_AX) {
-                       regfree(&nod);
-                       nod.reg = D_AX;
-                       gins(APUSHL, &nod, Z);
-                       gins(AWAIT, Z, Z);
-                       gins(AFSTSW, Z, &nod);
-                       gins(ASAHF, Z, Z);
-                       gins(APOPL, Z, &nod);
-               } else {
-                       gins(AWAIT, Z, Z);
-                       gins(AFSTSW, Z, &nod);
-                       gins(ASAHF, Z, Z);
-                       regfree(&nod);
-               }
-               switch(o) {
-               case OEQ:       a = AJEQ; break;
-               case ONE:       a = AJNE; break;
-               case OLT:       a = AJCS; break;
-               case OLE:       a = AJLS; break;
-               case OGE:       a = AJCC; break;
-               case OGT:       a = AJHI; break;
-               }
-               gins(a, Z, Z);
-               return;
-       }
-       if(a == AGOK)
-               diag(Z, "bad in gopcode %O", o);
-       gins(a, f, t);
-}
-
-void
-gopcode(int o, Type *ty, Node *f, Node *t)
-{
-       int a, et;
-
-       et = TLONG;
-       if(ty != T)
-               et = ty->etype;
-       if(typefd[et] && o != OADDR && o != OFUNC) {
-               diag(f, "gop: float %O", o);
-               return;
-       }
-       if(debug['M']) {
-               if(f != Z && f->type != T)
-                       print("gop: %O %O[%s],", o, f->op, tnames[et]);
-               else
-                       print("gop: %O Z,", o);
-               if(t != Z && t->type != T)
-                       print("%O[%s]\n", t->op, tnames[t->type->etype]);
-               else
-                       print("Z\n");
-       }
-       a = AGOK;
-       switch(o) {
-       case OCOM:
-               a = ANOTL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ANOTB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ANOTW;
-               break;
-
-       case ONEG:
-               a = ANEGL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ANEGB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ANEGW;
-               break;
-
-       case OADDR:
-               a = ALEAL;
-               break;
-
-       case OASADD:
-       case OADD:
-               a = AADDL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AADDB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AADDW;
-               break;
-
-       case OASSUB:
-       case OSUB:
-               a = ASUBL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASUBB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASUBW;
-               break;
-
-       case OASOR:
-       case OOR:
-               a = AORL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AORB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AORW;
-               break;
-
-       case OASAND:
-       case OAND:
-               a = AANDL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AANDB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AANDW;
-               break;
-
-       case OASXOR:
-       case OXOR:
-               a = AXORL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = AXORB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = AXORW;
-               break;
-
-       case OASLSHR:
-       case OLSHR:
-               a = ASHRL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASHRB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASHRW;
-               break;
-
-       case OASASHR:
-       case OASHR:
-               a = ASARL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASARB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ASARW;
-               break;
-
-       case OASASHL:
-       case OASHL:
-               a = ASALL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ASALB;
-               if(et == TSHORT || et == TUSHORT)
-                       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;
-
-       case OASMUL:
-       case OMUL:
-               if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
-                       t = Z;
-               a = AIMULL;
-               break;
-
-       case OASMOD:
-       case OMOD:
-       case OASDIV:
-       case ODIV:
-               a = AIDIVL;
-               break;
-
-       case OASLMUL:
-       case OLMUL:
-               a = AMULL;
-               break;
-
-       case OASLMOD:
-       case OLMOD:
-       case OASLDIV:
-       case OLDIV:
-               a = ADIVL;
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case OLO:
-       case OLS:
-       case OHS:
-       case OHI:
-               a = ACMPL;
-               if(et == TCHAR || et == TUCHAR)
-                       a = ACMPB;
-               if(et == TSHORT || et == TUSHORT)
-                       a = ACMPW;
-               gins(a, f, t);
-               switch(o) {
-               case OEQ:       a = AJEQ; break;
-               case ONE:       a = AJNE; break;
-               case OLT:       a = AJLT; break;
-               case OLE:       a = AJLE; break;
-               case OGE:       a = AJGE; break;
-               case OGT:       a = AJGT; break;
-               case OLO:       a = AJCS; break;
-               case OLS:       a = AJLS; break;
-               case OHS:       a = AJCC; break;
-               case OHI:       a = AJHI; break;
-               }
-               gins(a, Z, Z);
-               return;
-       }
-       if(a == AGOK)
-               diag(Z, "bad in gopcode %O", o);
-       gins(a, f, t);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
-       if(f->op != t->op)
-               return 0;
-       switch(f->op) {
-
-       case OREGISTER:
-               if(f->reg != t->reg)
-                       break;
-               return 1;
-       }
-       return 0;
-}
-
-void
-gbranch(int o)
-{
-       int a;
-
-       a = AGOK;
-       switch(o) {
-       case ORETURN:
-               a = ARET;
-               break;
-       case OGOTO:
-               a = AJMP;
-               break;
-       }
-       nextpc();
-       if(a == AGOK) {
-               diag(Z, "bad in gbranch %O",  o);
-               nextpc();
-       }
-       p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
-       op->to.offset = pc;
-       op->to.type = D_BRANCH;
-       op->to.u.branch = nil;
-       op->pcond = nil;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
-       nextpc();
-       p->as = a;
-       p->from.type = D_EXTERN;
-       p->from.sym = linksym(s);
-
-       switch(a) {
-       case ATEXT:
-               p->from.scale = textflag;
-               textflag = 0;
-               break;
-       case AGLOBL:
-               p->from.scale = s->dataflag;
-               break;
-       }
-
-       if(s->class == CSTATIC)
-               p->from.type = D_STATIC;
-       naddr(n, &p->to);
-       if(a == ADATA || a == AGLOBL)
-               pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
-       Node n1;
-       
-       n1 = *nodconst(index);
-       gins(APCDATA, &n1, nodconst(value));
-}
-
-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)
-{
-       int32 v;
-
-       if(n->op == OCONST && !typefd[n->type->etype]) {
-               v = n->vconst;
-               if(v >= -32766L && v < 32766L)
-                       return 1;
-       }
-       return 0;
-}
-
-int32
-exreg(Type *t)
-{
-       int32 o;
-
-       if(typechlp[t->etype]){
-               if(exregoffset >= 32)
-                       return 0;
-               o = exregoffset;
-               exregoffset += 4;
-               return o+1;     // +1 to avoid 0 == failure; naddr case OEXREG will -1.
-       }
-
-       return 0;
-}
-
-schar  ewidth[NTYPE] =
-{
-       -1,             /*[TXXX]*/
-       SZ_CHAR,        /*[TCHAR]*/
-       SZ_CHAR,        /*[TUCHAR]*/
-       SZ_SHORT,       /*[TSHORT]*/
-       SZ_SHORT,       /*[TUSHORT]*/
-       SZ_INT,         /*[TINT]*/
-       SZ_INT,         /*[TUINT]*/
-       SZ_LONG,        /*[TLONG]*/
-       SZ_LONG,        /*[TULONG]*/
-       SZ_VLONG,       /*[TVLONG]*/
-       SZ_VLONG,       /*[TUVLONG]*/
-       SZ_FLOAT,       /*[TFLOAT]*/
-       SZ_DOUBLE,      /*[TDOUBLE]*/
-       SZ_IND,         /*[TIND]*/
-       0,              /*[TFUNC]*/
-       -1,             /*[TARRAY]*/
-       0,              /*[TVOID]*/
-       -1,             /*[TSTRUCT]*/
-       -1,             /*[TUNION]*/
-       SZ_INT,         /*[TENUM]*/
-};
-int32  ncast[NTYPE] =
-{
-       0,                              /*[TXXX]*/
-       BCHAR|BUCHAR,                   /*[TCHAR]*/
-       BCHAR|BUCHAR,                   /*[TUCHAR]*/
-       BSHORT|BUSHORT,                 /*[TSHORT]*/
-       BSHORT|BUSHORT,                 /*[TUSHORT]*/
-       BINT|BUINT|BLONG|BULONG|BIND,   /*[TINT]*/
-       BINT|BUINT|BLONG|BULONG|BIND,   /*[TUINT]*/
-       BINT|BUINT|BLONG|BULONG|BIND,   /*[TLONG]*/
-       BINT|BUINT|BLONG|BULONG|BIND,   /*[TULONG]*/
-       BVLONG|BUVLONG,                 /*[TVLONG]*/
-       BVLONG|BUVLONG,                 /*[TUVLONG]*/
-       BFLOAT,                         /*[TFLOAT]*/
-       BDOUBLE,                        /*[TDOUBLE]*/
-       BLONG|BULONG|BIND,              /*[TIND]*/
-       0,                              /*[TFUNC]*/
-       0,                              /*[TARRAY]*/
-       0,                              /*[TVOID]*/
-       BSTRUCT,                        /*[TSTRUCT]*/
-       BUNION,                         /*[TUNION]*/
-       0,                              /*[TENUM]*/
-};
index fa0605e6c763522f18b0feefb432799f709d1908..af287f702349df87c1afe619ffcc8233d5e16985 100644 (file)
@@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
        a->sym = linksym(sym);
        a->node = sym->def;
        a->offset = 0;  // header
-       a->etype = TINT32;
+       a->etype = TSTRING;
 }
 
 void
index 09f58c40ae530132c288df72ca2d2000f4d58406..5445f91275e792fa8c76534a57e743e017053ded 100644 (file)
@@ -63,8 +63,8 @@ enum
 
 uint32 BLOAD(Reg*);
 uint32 BSTORE(Reg*);
-uint32 LOAD(Reg*);
-uint32 STORE(Reg*);
+uint64 LOAD(Reg*);
+uint64 STORE(Reg*);
 */
 
 // A Reg is a wrapper around a single Prog (one instruction) that holds
@@ -75,12 +75,18 @@ struct      Reg
 {
        Flow    f;
 
-       Bits    set;            // variables written by this instruction.
-       Bits    use1;           // variables read by prog->from.
-       Bits    use2;           // variables read by prog->to.
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
 
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
        Bits    refbehind;
        Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
        Bits    calbehind;
        Bits    calahead;
        Bits    regdiff;
@@ -106,6 +112,16 @@ struct     Reg
 
 #define        NRGN    600
 /*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
 struct Rgn
 {
        Reg*    enter;
@@ -158,8 +174,8 @@ void        loopit(Reg*, int32);
 void   synch(Reg*, Bits);
 uint32 allreg(uint32, Rgn*);
 void   paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void   paint3(Reg*, int, int32, int);
+uint32 paint2(Reg*, int, int);
+void   paint3(Reg*, int, uint32, int);
 void   addreg(Adr*, int);
 void   dumpone(Flow*, int);
 void   dumpit(char*, Flow*, int);
@@ -171,10 +187,10 @@ void      peep(Prog*);
 void   excise(Flow*);
 int    copyu(Prog*, Adr*, Adr*);
 
-int32  RtoB(int);
-int32  FtoB(int);
-int    BtoR(int32);
-int    BtoF(int32);
+uint32 RtoB(int);
+uint32 FtoB(int);
+int    BtoR(uint32);
+int    BtoF(uint32);
 
 /*
  * prog.c
@@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
 struct ProgInfo
 {
        uint32 flags; // the bits below
-       uint32 reguse; // required registers used by this instruction
-       uint32 regset; // required registers set by this instruction
+       uint32 reguse; // registers implicitly used by this instruction
+       uint32 regset; // registers implicitly set by this instruction
        uint32 regindex; // registers used by addressing mode
 };
 
@@ -205,12 +221,12 @@ enum
        SizeF = 1<<7, // float aka float32
        SizeD = 1<<8, // double aka float64
 
-       // Left side: address taken, read, write.
+       // Left side (Prog.from): address taken, read, write.
        LeftAddr = 1<<9,
        LeftRead = 1<<10,
        LeftWrite = 1<<11,
        
-       // Right side: address taken, read, write.
+       // Right side (Prog.to): address taken, read, write.
        RightAddr = 1<<12,
        RightRead = 1<<13,
        RightWrite = 1<<14,
index 302b273a1b4f5fa4c02146fc03446f41bfa7c163..13beaf94144a9af2977d0865c0c99f747a202657 100644 (file)
@@ -34,7 +34,7 @@
 #include "opt.h"
 
 #define        NREGVAR 16      /* 8 integer + 8 floating */
-#define        REGBITS ((uint32)0xffff)
+#define        REGBITS ((uint64)0xffffull)
 /*c2go enum {
        NREGVAR = 16,
        REGBITS = (1<<NREGVAR) - 1,
@@ -71,7 +71,7 @@ setaddrs(Bits bit)
                i = bnum(bit);
                node = var[i].node;
                n = var[i].name;
-               bit.b[i/32] &= ~(1L<<(i%32));
+               biclr(&bit, i);
 
                // disable all pieces of that variable
                for(i=0; i<nvar; i++) {
@@ -336,7 +336,7 @@ loop2:
                        rgp->varno = i;
                        change = 0;
                        paint1(r, i);
-                       bit.b[i/32] &= ~(1L<<(i%32));
+                       biclr(&bit, i);
                        if(change <= 0)
                                continue;
                        rgp->cost = change;
@@ -358,18 +358,19 @@ brk:
         * replace code (paint3)
         */
        rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
        for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
                bit = blsh(rgp->varno);
-               vreg = paint2(rgp->enter, rgp->varno);
+               vreg = paint2(rgp->enter, rgp->varno, 0);
                vreg = allreg(vreg, rgp);
                if(rgp->regno != 0)
                        paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
                rgp++;
        }
 
-       if(debug['R'] && debug['v'])
-               dumpit("pass6", &firstr->f, 1);
-
        /*
         * free aux structures. peep allocates new ones.
         */
@@ -378,6 +379,15 @@ brk:
        flowend(g);
        firstr = R;
 
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
        /*
         * pass 7
         * peep-hole on basic block
@@ -446,7 +456,7 @@ walkvardef(Node *n, Reg *r, int active)
                        break;
                for(v=n->opt; v!=nil; v=v->nextinnode) {
                        bn = v - var;
-                       r1->act.b[bn/32] |= 1L << (bn%32);
+                       biset(&r1->act, bn);
                }
                if(r1->f.prog->as == ACALL)
                        break;
@@ -788,10 +798,10 @@ prop(Reg *r, Bits ref, Bits cal)
                        for(z=0; z<BITS; z++) {
                                if(cal.b[z] == 0)
                                        continue;
-                               for(i=0; i<32; i++) {
-                                       if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
+                               for(i=0; i<64; i++) {
+                                       if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
                                                continue;
-                                       v = var+z*32+i;
+                                       v = var+z*64+i;
                                        if(v->node->opt == nil) // v represents fixed register, not Go variable
                                                continue;
 
@@ -807,10 +817,10 @@ prop(Reg *r, Bits ref, Bits cal)
                                        // This will set the bits at most twice, keeping the overall loop linear.
                                        v1 = v->node->opt;
                                        j = v1 - var;
-                                       if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
+                                       if(v == v1 || !btest(&cal, j)) {
                                                for(; v1 != nil; v1 = v1->nextinnode) {
                                                        j = v1 - var;
-                                                       cal.b[j/32] |= 1<<(j&31);
+                                                       biset(&cal, j);
                                                }
                                        }
                                }
@@ -926,10 +936,10 @@ paint1(Reg *r, int bn)
        Reg *r1;
        Prog *p;
        int z;
-       uint32 bb;
+       uint64 bb, rbz;
 
-       z = bn/32;
-       bb = 1L<<(bn%32);
+       z = bn/64;
+       bb = 1LL<<(bn%64);
        if(r->act.b[z] & bb)
                return;
        for(;;) {
@@ -945,7 +955,8 @@ paint1(Reg *r, int bn)
                r = r1;
        }
 
-       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
+       rbz = ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z]));
+       if(LOAD(r) & rbz & bb) {
                change -= CLOAD * r->f.loop;
        }
        for(;;) {
@@ -996,52 +1007,14 @@ paint1(Reg *r, int bn)
 }
 
 uint32
-regset(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Adr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = b & 0xFF ? BtoR(b): BtoF(b);
-               c = copyu(r->f.prog, &v, nil);
-               if(c == 3)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
-       uint32 b, set;
-       Adr v;
-       int c;
-
-       set = 0;
-       v = zprog.from;
-       while(b = bb & ~(bb-1)) {
-               v.type = b & 0xFF ? BtoR(b): BtoF(b);
-               c = copyu(r->f.prog, &v, nil);
-               if(c == 1 || c == 2 || c == 4)
-                       set |= b;
-               bb &= ~b;
-       }
-       return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
+paint2(Reg *r, int bn, int depth)
 {
        Reg *r1;
        int z;
-       uint32 bb, vreg, x;
+       uint64 bb, vreg;
 
-       z = bn/32;
-       bb = 1L << (bn%32);
+       z = bn/64;
+       bb = 1LL << (bn%64);
        vreg = regbits;
        if(!(r->act.b[z] & bb))
                return vreg;
@@ -1058,6 +1031,9 @@ paint2(Reg *r, int bn)
                r = r1;
        }
        for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
                r->act.b[z] &= ~bb;
 
                vreg |= r->regu;
@@ -1065,14 +1041,14 @@ paint2(Reg *r, int bn)
                if(r->refbehind.b[z] & bb)
                        for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
                                if(r1->refahead.b[z] & bb)
-                                       vreg |= paint2(r1, bn);
+                                       vreg |= paint2(r1, bn, depth+1);
 
                if(!(r->refahead.b[z] & bb))
                        break;
                r1 = (Reg*)r->f.s2;
                if(r1 != R)
                        if(r1->refbehind.b[z] & bb)
-                               vreg |= paint2(r1, bn);
+                               vreg |= paint2(r1, bn, depth+1);
                r = (Reg*)r->f.s1;
                if(r == R)
                        break;
@@ -1082,27 +1058,19 @@ paint2(Reg *r, int bn)
                        break;
        }
 
-       bb = vreg;
-       for(; r; r=(Reg*)r->f.s1) {
-               x = r->regu & ~bb;
-               if(x) {
-                       vreg |= reguse(r, x);
-                       bb |= regset(r, x);
-               }
-       }
        return vreg;
 }
 
 void
-paint3(Reg *r, int bn, int32 rb, int rn)
+paint3(Reg *r, int bn, uint32 rb, int rn)
 {
        Reg *r1;
        Prog *p;
        int z;
-       uint32 bb;
+       uint64 bb, rbz;
 
-       z = bn/32;
-       bb = 1L << (bn%32);
+       z = bn/64;
+       bb = 1LL << (bn%64);
        if(r->act.b[z] & bb)
                return;
        for(;;) {
@@ -1118,7 +1086,8 @@ paint3(Reg *r, int bn, int32 rb, int rn)
                r = r1;
        }
 
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
+       rbz = ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z]));
+       if(LOAD(r) & rbz & bb)
                addmove(r, bn, rn, 0);
        for(;;) {
                r->act.b[z] |= bb;
@@ -1175,7 +1144,7 @@ addreg(Adr *a, int rn)
        ostats.ncvtreg++;
 }
 
-int32
+uint32
 RtoB(int r)
 {
 
@@ -1185,7 +1154,7 @@ RtoB(int r)
 }
 
 int
-BtoR(int32 b)
+BtoR(uint32 b)
 {
 
        b &= 0xffL;
@@ -1194,7 +1163,7 @@ BtoR(int32 b)
        return bitno(b) + D_AX;
 }
 
-int32
+uint32
 FtoB(int f)
 {
        if(f < D_X0 || f > D_X7)
@@ -1203,7 +1172,7 @@ FtoB(int f)
 }
 
 int
-BtoF(int32 b)
+BtoF(uint32 b)
 {
        b &= 0xFF00L;
        if(b == 0)
@@ -1273,12 +1242,14 @@ dumpit(char *str, Flow *r0, int isreg)
                                print(" %.4ud", (int)r1->prog->pc);
                        print("\n");
                }
-//             r1 = r->s1;
-//             if(r1 != nil) {
-//                     print(" succ:");
-//                     for(; r1 != R; r1 = r1->s1)
-//                             print(" %.4ud", (int)r1->prog->pc);
-//                     print("\n");
-//             }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
        }
 }
index ed54f6744abfa35121b12671dd877d4837214953..596c5f61a8f9a32f15911d4c7b387eefa4d8be7a 100644 (file)
@@ -654,6 +654,8 @@ enum
 
        D_CONST2 = D_INDIR+D_INDIR,
 
+       D_LAST,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
similarity index 55%
rename from src/cmd/cc/Makefile
rename to src/cmd/9a/Makefile
index 34df31d6f5cf6e89819c888fa1cad5731e36fdc8..27290ddd71ec987998bb0779c48791edf069ef58 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2012 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.
 
@@ -6,5 +6,5 @@ include ../../Make.dist
 
 install: y.tab.h
 
-y.tab.h: cc.y
-       LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y cc.y
+y.tab.h: a.y
+       LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y
diff --git a/src/cmd/9a/a.h b/src/cmd/9a/a.h
new file mode 100644 (file)
index 0000000..7a01fc9
--- /dev/null
@@ -0,0 +1,170 @@
+// cmd/9a/a.h from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <bio.h>
+#include <link.h>
+#include "../9l/9.out.h"
+
+#ifndef        EXTERN
+#define        EXTERN  extern
+#endif
+
+#undef getc
+#undef ungetc
+#undef BUFSIZ
+
+#define        getc    ccgetc
+#define        ungetc  ccungetc
+
+typedef        struct  Sym     Sym;
+typedef        struct  Io      Io;
+
+#define        MAXALIGN        7
+#define        FPCHIP          1
+#define        NSYMB           8192
+#define        BUFSIZ          8192
+#define        HISTSZ          20
+#define        NINCLUDE        10
+#define        NHUNK           10000
+#ifndef EOF
+#define        EOF             (-1)
+#endif
+#define        IGN             (-2)
+#define        GETC()          ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
+#define        NHASH           503
+#define        STRINGSZ        200
+#define        NMACRO          10
+
+struct Sym
+{
+       Sym*    link;
+       char*   macro;
+       vlong   value;
+       ushort  type;
+       char    *name;
+       char*   labelname;
+       char    sym;
+};
+#define        S       ((Sym*)0)
+
+EXTERN struct
+{
+       char*   p;
+       int     c;
+} fi;
+
+struct Io
+{
+       Io*     link;
+       char    b[BUFSIZ];
+       char*   p;
+       short   c;
+       short   f;
+};
+#define        I       ((Io*)0)
+
+enum
+{
+       CLAST,
+       CMACARG,
+       CMACRO,
+       CPREPROC,
+};
+
+EXTERN int     debug[256];
+EXTERN Sym*    hash[NHASH];
+EXTERN char**  Dlist;
+EXTERN int     nDlist;
+EXTERN int     newflag;
+EXTERN char*   hunk;
+EXTERN char**  include;
+EXTERN Io*     iofree;
+EXTERN Io*     ionext;
+EXTERN Io*     iostack;
+EXTERN int32   lineno;
+EXTERN int     nerrors;
+EXTERN int32   nhunk;
+EXTERN int     nosched;
+EXTERN int     ninclude;
+EXTERN int32   nsymb;
+EXTERN Addr    nullgen;
+EXTERN char*   outfile;
+EXTERN int     pass;
+EXTERN int32   pc;
+EXTERN int     peekc;
+EXTERN int     sym;
+EXTERN char*   symb;
+EXTERN int     thechar;
+EXTERN char*   thestring;
+EXTERN int32   thunk;
+EXTERN Biobuf  obuf;
+EXTERN Link*   ctxt;
+EXTERN Biobuf  bstdout;
+
+void*  alloc(int32);
+void*  allocn(void*, int32, int32);
+void   ensuresymb(int32);
+void   errorexit(void);
+void   pushio(void);
+void   newio(void);
+void   newfile(char*, int);
+Sym*   slookup(char*);
+Sym*   lookup(void);
+Sym*   labellookup(Sym*);
+void   settext(LSym*);
+void   syminit(Sym*);
+int32  yylex(void);
+int    getc(void);
+int    getnsc(void);
+void   unget(int);
+int    escchar(int);
+void   cinit(void);
+void   pinit(char*);
+void   cclean(void);
+void   outcode(int, Addr*, int, Addr*);
+void   outgcode(int, Addr*, int, Addr*, Addr*);
+int    filbuf(void);
+Sym*   getsym(void);
+void   domacro(void);
+void   macund(void);
+void   macdef(void);
+void   macexpand(Sym*, char*);
+void   macinc(void);
+void   macprag(void);
+void   maclin(void);
+void   macif(int);
+void   macend(void);
+void   dodefine(char*);
+void   prfile(int32);
+void   linehist(char*, int);
+void   gethunk(void);
+void   yyerror(char*, ...);
+int    yyparse(void);
+void   setinclude(char*);
+int    assemble(char*);
diff --git a/src/cmd/9a/a.y b/src/cmd/9a/a.y
new file mode 100644 (file)
index 0000000..b366146
--- /dev/null
@@ -0,0 +1,991 @@
+// cmd/9a/a.y from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+%{
+#include <u.h>
+#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
+#include <libc.h>
+#include "a.h"
+#include "../../runtime/funcdata.h"
+%}
+%union
+{
+       Sym     *sym;
+       vlong   lval;
+       double  dval;
+       char    sval[8];
+       Addr    addr;
+}
+%left  '|'
+%left  '^'
+%left  '&'
+%left  '<' '>'
+%left  '+' '-'
+%left  '*' '/' '%'
+%token <lval>  LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
+%token <lval>  LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
+%token <lval>  LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
+%token <lval>  LCONST LSP LSB LFP LPC LCREG LFLUSH
+%token <lval>  LREG LFREG LR LCR LF LFPSCR
+%token <lval>  LLR LCTR LSPR LSPREG LSEG LMSR
+%token <lval>  LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
+%token <lval>  LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
+%token <dval>  LFCONST
+%token <sval>  LSCONST
+%token <sym>   LNAME LLAB LVAR
+%type  <lval>  con expr pointer offset sreg
+%type  <addr>  addr rreg regaddr name creg freg xlreg lr ctr
+%type  <addr>  imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
+%%
+prog:
+|      prog line
+
+line:
+       LNAME ':'
+       {
+               $1 = labellookup($1);
+               if($1->type == LLAB && $1->value != pc)
+                       yyerror("redeclaration of %s", $1->labelname);
+               $1->type = LLAB;
+               $1->value = pc;
+       }
+       line
+|      LNAME '=' expr ';'
+       {
+               $1->type = LVAR;
+               $1->value = $3;
+       }
+|      LVAR '=' expr ';'
+       {
+               if($1->value != $3)
+                       yyerror("redeclaration of %s", $1->name);
+               $1->value = $3;
+       }
+|      LSCHED ';'
+       {
+               nosched = $1;
+       }
+|      ';'
+|      inst ';'
+|      error ';'
+
+inst:
+/*
+ * load ints and bytes
+ */
+       LMOVW rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW addr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW regaddr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVB rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVB addr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVB regaddr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * load floats
+ */
+|      LFMOV addr ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFMOV regaddr ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFMOV fimm ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFMOV freg ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFMOV freg ',' addr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFMOV freg ',' regaddr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * store ints and bytes
+ */
+|      LMOVW rreg ',' addr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' regaddr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVB rreg ',' addr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVB rreg ',' regaddr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * store floats
+ */
+|      LMOVW freg ',' addr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW freg ',' regaddr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * floating point status
+ */
+|      LMOVW fpscr ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW freg ','  fpscr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW freg ',' imm ',' fpscr
+       {
+               outgcode($1, &$2, NREG, &$4, &$6);
+       }
+|      LMOVW fpscr ',' creg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW imm ',' fpscrf
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMTFSB imm ',' con
+       {
+               outcode($1, &$2, $4, &nullgen);
+       }
+/*
+ * field moves (mtcrf)
+ */
+|      LMOVW rreg ',' imm ',' lcr
+       {
+               outgcode($1, &$2, NREG, &$4, &$6);
+       }
+|      LMOVW rreg ',' creg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' lcr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * integer operations
+ * logical instructions
+ * shift instructions
+ * unary instructions
+ */
+|      LADDW rreg ',' sreg ',' rreg
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LADDW imm ',' sreg ',' rreg
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LADDW rreg ',' imm ',' rreg
+       {
+               outgcode($1, &$2, NREG, &$4, &$6);
+       }
+|      LADDW rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LADDW imm ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LLOGW rreg ',' sreg ',' rreg
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LLOGW rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LSHW rreg ',' sreg ',' rreg
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LSHW rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LSHW imm ',' sreg ',' rreg
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LSHW imm ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LABS rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LABS rreg
+       {
+               outcode($1, &$2, NREG, &$2);
+       }
+/*
+ * multiply-accumulate
+ */
+|      LMA rreg ',' sreg ',' rreg
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+/*
+ * move immediate: macro for cau+or, addi, addis, and other combinations
+ */
+|      LMOVW imm ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW ximm ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * condition register operations
+ */
+|      LCROP cbit ',' cbit
+       {
+               outcode($1, &$2, $4.reg, &$4);
+       }
+|      LCROP cbit ',' con ',' cbit
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+/*
+ * condition register moves
+ * move from machine state register
+ */
+|      LMOVW creg ',' creg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW psr ',' creg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW lcr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW psr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW xlreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' xlreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW creg ',' psr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVW rreg ',' psr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * branch, branch conditional
+ * branch conditional register
+ * branch conditional to count register
+ */
+|      LBRA rel
+       {
+               outcode($1, &nullgen, NREG, &$2);
+       }
+|      LBRA addr
+       {
+               outcode($1, &nullgen, NREG, &$2);
+       }
+|      LBRA '(' xlreg ')'
+       {
+               outcode($1, &nullgen, NREG, &$3);
+       }
+|      LBRA ',' rel
+       {
+               outcode($1, &nullgen, NREG, &$3);
+       }
+|      LBRA ',' addr
+       {
+               outcode($1, &nullgen, NREG, &$3);
+       }
+|      LBRA ',' '(' xlreg ')'
+       {
+               outcode($1, &nullgen, NREG, &$4);
+       }
+|      LBRA creg ',' rel
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LBRA creg ',' addr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LBRA creg ',' '(' xlreg ')'
+       {
+               outcode($1, &$2, NREG, &$5);
+       }
+|      LBRA con ',' rel
+       {
+               outcode($1, &nullgen, $2, &$4);
+       }
+|      LBRA con ',' addr
+       {
+               outcode($1, &nullgen, $2, &$4);
+       }
+|      LBRA con ',' '(' xlreg ')'
+       {
+               outcode($1, &nullgen, $2, &$5);
+       }
+|      LBRA con ',' con ',' rel
+       {
+               Addr g;
+               g = nullgen;
+               g.type = D_CONST;
+               g.offset = $2;
+               outcode($1, &g, $4, &$6);
+       }
+|      LBRA con ',' con ',' addr
+       {
+               Addr g;
+               g = nullgen;
+               g.type = D_CONST;
+               g.offset = $2;
+               outcode($1, &g, $4, &$6);
+       }
+|      LBRA con ',' con ',' '(' xlreg ')'
+       {
+               Addr g;
+               g = nullgen;
+               g.type = D_CONST;
+               g.offset = $2;
+               outcode($1, &g, $4, &$7);
+       }
+/*
+ * conditional trap
+ */
+|      LTRAP rreg ',' sreg
+       {
+               outcode($1, &$2, $4, &nullgen);
+       }
+|      LTRAP imm ',' sreg
+       {
+               outcode($1, &$2, $4, &nullgen);
+       }
+|      LTRAP rreg comma
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+|      LTRAP comma
+       {
+               outcode($1, &nullgen, NREG, &nullgen);
+       }
+/*
+ * floating point operate
+ */
+|      LFCONV freg ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFADD freg ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFADD freg ',' freg ',' freg
+       {
+               outcode($1, &$2, $4.reg, &$6);
+       }
+|      LFMA freg ',' freg ',' freg ',' freg
+       {
+               outgcode($1, &$2, $4.reg, &$6, &$8);
+       }
+|      LFCMP freg ',' freg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LFCMP freg ',' freg ',' creg
+       {
+               outcode($1, &$2, $6.reg, &$4);
+       }
+/*
+ * CMP
+ */
+|      LCMP rreg ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LCMP rreg ',' imm
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LCMP rreg ',' rreg ',' creg
+       {
+               outcode($1, &$2, $6.reg, &$4);
+       }
+|      LCMP rreg ',' imm ',' creg
+       {
+               outcode($1, &$2, $6.reg, &$4);
+       }
+/*
+ * rotate and mask
+ */
+|      LRLWM  imm ',' rreg ',' imm ',' rreg
+       {
+               outgcode($1, &$2, $4.reg, &$6, &$8);
+       }
+|      LRLWM  imm ',' rreg ',' mask ',' rreg
+       {
+               outgcode($1, &$2, $4.reg, &$6, &$8);
+       }
+|      LRLWM  rreg ',' rreg ',' imm ',' rreg
+       {
+               outgcode($1, &$2, $4.reg, &$6, &$8);
+       }
+|      LRLWM  rreg ',' rreg ',' mask ',' rreg
+       {
+               outgcode($1, &$2, $4.reg, &$6, &$8);
+       }
+/*
+ * load/store multiple
+ */
+|      LMOVMW addr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LMOVMW rreg ',' addr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * various indexed load/store
+ * indexed unary (eg, cache clear)
+ */
+|      LXLD regaddr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LXLD regaddr ',' imm ',' rreg
+       {
+               outgcode($1, &$2, NREG, &$4, &$6);
+       }
+|      LXST rreg ',' regaddr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LXST rreg ',' imm ',' regaddr
+       {
+               outgcode($1, &$2, NREG, &$4, &$6);
+       }
+|      LXMV regaddr ',' rreg
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LXMV rreg ',' regaddr
+       {
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LXOP regaddr
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+/*
+ * NOP
+ */
+|      LNOP comma
+       {
+               outcode($1, &nullgen, NREG, &nullgen);
+       }
+|      LNOP rreg comma
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+|      LNOP freg comma
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+|      LNOP ',' rreg
+       {
+               outcode($1, &nullgen, NREG, &$3);
+       }
+|      LNOP ',' freg
+       {
+               outcode($1, &nullgen, NREG, &$3);
+       }
+|      LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+/*
+ * word
+ */
+|      LWORD imm comma
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+|      LWORD ximm comma
+       {
+               outcode($1, &$2, NREG, &nullgen);
+       }
+/*
+ * PCDATA
+ */
+|      LPCDAT imm ',' imm
+       {
+               if($2.type != D_CONST || $4.type != D_CONST)
+                       yyerror("arguments to PCDATA must be integer constants");
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * FUNCDATA
+ */
+|      LFUNCDAT imm ',' addr
+       {
+               if($2.type != D_CONST)
+                       yyerror("index for FUNCDATA must be integer constant");
+               if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
+                       yyerror("value for FUNCDATA must be symbol reference");
+               outcode($1, &$2, NREG, &$4);
+       }
+/*
+ * END
+ */
+|      LEND comma
+       {
+               outcode($1, &nullgen, NREG, &nullgen);
+       }
+/*
+ * TEXT/GLOBL
+ */
+|      LTEXT name ',' imm
+       {
+               settext($2.sym);
+               outcode($1, &$2, NREG, &$4);
+       }
+|      LTEXT name ',' con ',' imm
+       {
+               settext($2.sym);
+               $6.offset &= 0xffffffffull;
+               $6.offset |= (vlong)ArgsSizeUnknown << 32;
+               outcode($1, &$2, $4, &$6);
+       }
+|      LTEXT name ',' con ',' imm '-' con
+       {
+               settext($2.sym);
+               $6.offset &= 0xffffffffull;
+               $6.offset |= ($8 & 0xffffffffull) << 32;
+               outcode($1, &$2, $4, &$6);
+       }
+/*
+ * DATA
+ */
+|      LDATA name '/' con ',' imm
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LDATA name '/' con ',' ximm
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+|      LDATA name '/' con ',' fimm
+       {
+               outcode($1, &$2, $4, &$6);
+       }
+/*
+ * RETURN
+ */
+|      LRETRN  comma
+       {
+               outcode($1, &nullgen, NREG, &nullgen);
+       }
+
+rel:
+       con '(' LPC ')'
+       {
+               $$ = nullgen;
+               $$.type = D_BRANCH;
+               $$.offset = $1 + pc;
+       }
+|      LNAME offset
+       {
+               $1 = labellookup($1);
+               $$ = nullgen;
+               if(pass == 2 && $1->type != LLAB)
+                       yyerror("undefined label: %s", $1->labelname);
+               $$.type = D_BRANCH;
+               $$.offset = $1->value + $2;
+       }
+
+rreg:
+       sreg
+       {
+               $$ = nullgen;
+               $$.type = D_REG;
+               $$.reg = $1;
+       }
+
+xlreg:
+       lr
+|      ctr
+
+lr:
+       LLR
+       {
+               $$ = nullgen;
+               $$.type = D_SPR;
+               $$.offset = $1;
+       }
+
+lcr:
+       LCR
+       {
+               $$ = nullgen;
+               $$.type = D_CREG;
+               $$.reg = NREG;  /* whole register */
+       }
+
+ctr:
+       LCTR
+       {
+               $$ = nullgen;
+               $$.type = D_SPR;
+               $$.offset = $1;
+       }
+
+msr:
+       LMSR
+       {
+               $$ = nullgen;
+               $$.type = D_MSR;
+       }
+
+psr:
+       LSPREG
+       {
+               $$ = nullgen;
+               $$.type = D_SPR;
+               $$.offset = $1;
+       }
+|      LSPR '(' con ')'
+       {
+               $$ = nullgen;
+               $$.type = $1;
+               $$.offset = $3;
+       }
+|      msr
+
+fpscr:
+       LFPSCR
+       {
+               $$ = nullgen;
+               $$.type = D_FPSCR;
+               $$.reg = NREG;
+       }
+
+fpscrf:
+       LFPSCR '(' con ')'
+       {
+               $$ = nullgen;
+               $$.type = D_FPSCR;
+               $$.reg = $3;
+       }
+
+freg:
+       LFREG
+       {
+               $$ = nullgen;
+               $$.type = D_FREG;
+               $$.reg = $1;
+       }
+|      LF '(' con ')'
+       {
+               $$ = nullgen;
+               $$.type = D_FREG;
+               $$.reg = $3;
+       }
+
+creg:
+       LCREG
+       {
+               $$ = nullgen;
+               $$.type = D_CREG;
+               $$.reg = $1;
+       }
+|      LCR '(' con ')'
+       {
+               $$ = nullgen;
+               $$.type = D_CREG;
+               $$.reg = $3;
+       }
+
+
+cbit:  con
+       {
+               $$ = nullgen;
+               $$.type = D_REG;
+               $$.reg = $1;
+       }
+
+mask:
+       con ',' con
+       {
+               int mb, me;
+               uint32 v;
+
+               $$ = nullgen;
+               $$.type = D_CONST;
+               mb = $1;
+               me = $3;
+               if(mb < 0 || mb > 31 || me < 0 || me > 31){
+                       yyerror("illegal mask start/end value(s)");
+                       mb = me = 0;
+               }
+               if(mb <= me)
+                       v = ((uint32)~0L>>mb) & (~0L<<(31-me));
+               else
+                       v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
+               $$.offset = v;
+       }
+
+ximm:
+       '$' addr
+       {
+               $$ = $2;
+               $$.type = D_CONST;
+       }
+|      '$' LSCONST
+       {
+               $$ = nullgen;
+               $$.type = D_SCONST;
+               memcpy($$.u.sval, $2, sizeof($$.u.sval));
+       }
+
+fimm:
+       '$' LFCONST
+       {
+               $$ = nullgen;
+               $$.type = D_FCONST;
+               $$.u.dval = $2;
+       }
+|      '$' '-' LFCONST
+       {
+               $$ = nullgen;
+               $$.type = D_FCONST;
+               $$.u.dval = -$3;
+       }
+
+imm:   '$' con
+       {
+               $$ = nullgen;
+               $$.type = D_CONST;
+               $$.offset = $2;
+       }
+
+sreg:
+       LREG
+|      LR '(' con ')'
+       {
+               if($$ < 0 || $$ >= NREG)
+                       print("register value out of range\n");
+               $$ = $3;
+       }
+
+regaddr:
+       '(' sreg ')'
+       {
+               $$ = nullgen;
+               $$.type = D_OREG;
+               $$.reg = $2;
+               $$.offset = 0;
+       }
+|      '(' sreg '+' sreg ')'
+       {
+               $$ = nullgen;
+               $$.type = D_OREG;
+               $$.reg = $2;
+               $$.scale = $4;
+               $$.offset = 0;
+       }
+
+addr:
+       name
+|      con '(' sreg ')'
+       {
+               $$ = nullgen;
+               $$.type = D_OREG;
+               $$.reg = $3;
+               $$.offset = $1;
+       }
+
+name:
+       con '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.type = D_OREG;
+               $$.name = $3;
+               $$.sym = nil;
+               $$.offset = $1;
+       }
+|      LNAME offset '(' pointer ')'
+       {
+               $$ = nullgen;
+               $$.type = D_OREG;
+               $$.name = $4;
+               $$.sym = linklookup(ctxt, $1->name, 0);
+               $$.offset = $2;
+       }
+|      LNAME '<' '>' offset '(' LSB ')'
+       {
+               $$ = nullgen;
+               $$.type = D_OREG;
+               $$.name = D_STATIC;
+               $$.sym = linklookup(ctxt, $1->name, 0);
+               $$.offset = $4;
+       }
+
+comma:
+|      ','
+
+offset:
+       {
+               $$ = 0;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+
+pointer:
+       LSB
+|      LSP
+|      LFP
+
+con:
+       LCONST
+|      LVAR
+       {
+               $$ = $1->value;
+       }
+|      '-' con
+       {
+               $$ = -$2;
+       }
+|      '+' con
+       {
+               $$ = $2;
+       }
+|      '~' con
+       {
+               $$ = ~$2;
+       }
+|      '(' expr ')'
+       {
+               $$ = $2;
+       }
+
+expr:
+       con
+|      expr '+' expr
+       {
+               $$ = $1 + $3;
+       }
+|      expr '-' expr
+       {
+               $$ = $1 - $3;
+       }
+|      expr '*' expr
+       {
+               $$ = $1 * $3;
+       }
+|      expr '/' expr
+       {
+               $$ = $1 / $3;
+       }
+|      expr '%' expr
+       {
+               $$ = $1 % $3;
+       }
+|      expr '<' '<' expr
+       {
+               $$ = $1 << $4;
+       }
+|      expr '>' '>' expr
+       {
+               $$ = $1 >> $4;
+       }
+|      expr '&' expr
+       {
+               $$ = $1 & $3;
+       }
+|      expr '^' expr
+       {
+               $$ = $1 ^ $3;
+       }
+|      expr '|' expr
+       {
+               $$ = $1 | $3;
+       }
diff --git a/src/cmd/9a/doc.go b/src/cmd/9a/doc.go
new file mode 100644 (file)
index 0000000..44bf89d
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+
+9a is a version of the Plan 9 assembler.  The original is documented at
+
+       http://plan9.bell-labs.com/magic/man2html/1/8a
+
+Go-specific considerations are documented at
+
+       http://golang.org/doc/asm
+
+Its target architecture is the Power64, referred to by these tools as
+power64 (big endian) or power64le (little endian).
+
+*/
+package main
diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c
new file mode 100644 (file)
index 0000000..e2945ef
--- /dev/null
@@ -0,0 +1,726 @@
+// cmd/9a/lex.c from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#define        EXTERN
+#include <u.h>
+#include <libc.h>
+#include "a.h"
+#include "y.tab.h"
+
+enum
+{
+       Plan9   = 1<<0,
+       Unix    = 1<<1,
+       Windows = 1<<2,
+};
+
+int
+systemtype(int sys)
+{
+#ifdef _WIN32
+       return sys&Windows;
+#else
+       return sys&Plan9;
+#endif
+}
+
+int
+pathchar(void)
+{
+       return '/';
+}
+
+int
+Lconv(Fmt *fp)
+{
+       return linklinefmt(ctxt, fp);
+}
+
+void
+dodef(char *p)
+{
+       if(nDlist%8 == 0)
+               Dlist = allocn(Dlist, nDlist*sizeof(char *),
+                       8*sizeof(char *));
+       Dlist[nDlist++] = p;
+}
+
+LinkArch*       thelinkarch = &linkpower64;
+
+void
+usage(void)
+{
+       print("usage: %ca [options] file.c...\n", thechar);
+       flagprint(1);
+       errorexit();
+}
+
+void
+main(int argc, char *argv[])
+{
+       char *p;
+
+       thechar = '9';
+       thestring = "power64";
+
+       // Allow GOARCH=thestring or GOARCH=thestringsuffix,
+       // but not other values.        
+       p = getgoarch();
+       if(strncmp(p, thestring, strlen(thestring)) != 0)
+               sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
+       if(strcmp(p, "power64le") == 0)
+               thelinkarch = &linkpower64le;
+
+       ctxt = linknew(thelinkarch);
+       ctxt->diag = yyerror;
+       ctxt->bso = &bstdout;
+       ctxt->enforce_data_order = 1;
+       Binit(&bstdout, 1, OWRITE);
+       listinit9();
+       fmtinstall('L', Lconv);
+
+       ensuresymb(NSYMB);
+       memset(debug, 0, sizeof(debug));
+       cinit();
+       outfile = 0;
+       setinclude(".");
+
+       flagfn1("D", "name[=value]: add #define", dodef);
+       flagfn1("I", "dir: add dir to include path", setinclude);
+       flagcount("S", "print assembly and machine code", &debug['S']);
+       flagcount("m", "debug preprocessor macros", &debug['m']);
+       flagstr("o", "file: set output file", &outfile);
+       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
+
+       flagparse(&argc, &argv, usage);
+       ctxt->debugasm = debug['S'];
+
+       if(argc < 1)
+               usage();
+       if(argc > 1){
+               print("can't assemble multiple files\n");
+               errorexit();
+       }
+
+       if(assemble(argv[0]))
+               errorexit();
+       Bflush(&bstdout);
+       exits(0);
+}
+
+int
+assemble(char *file)
+{
+       char *ofile, *p;
+       int i, of;
+
+       ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
+       strcpy(ofile, file);
+       p = utfrrune(ofile, pathchar());
+       if(p) {
+               include[0] = ofile;
+               *p++ = 0;
+       } else
+               p = ofile;
+       if(outfile == 0) {
+               outfile = p;
+               if(outfile){
+                       p = utfrrune(outfile, '.');
+                       if(p)
+                               if(p[1] == 's' && p[2] == 0)
+                                       p[0] = 0;
+                       p = utfrune(outfile, 0);
+                       p[0] = '.';
+                       p[1] = thechar;
+                       p[2] = 0;
+               } else
+                       outfile = "/dev/null";
+       }
+
+       of = create(outfile, OWRITE, 0664);
+       if(of < 0) {
+               yyerror("%ca: cannot create %s", thechar, outfile);
+               errorexit();
+       }
+       Binit(&obuf, of, OWRITE);
+       Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
+       Bprint(&obuf, "!\n");
+
+       for(pass = 1; pass <= 2; pass++) {
+               nosched = 0;
+               pinit(file);
+               for(i=0; i<nDlist; i++)
+                       dodefine(Dlist[i]);
+               yyparse();
+               cclean();
+               if(nerrors)
+                       return nerrors;
+       }
+
+       writeobj(ctxt, &obuf);
+       Bflush(&obuf);
+       return 0;
+}
+
+struct
+{
+       char    *name;
+       ushort  type;
+       ushort  value;
+} itab[] =
+{
+       "SP",           LSP,    D_AUTO,
+       "SB",           LSB,    D_EXTERN,
+       "FP",           LFP,    D_PARAM,
+       "PC",           LPC,    D_BRANCH,
+
+       "LR",           LLR,    D_LR,
+       "CTR",          LCTR,   D_CTR,
+
+       "XER",          LSPREG, D_XER,
+       "MSR",          LMSR,   D_MSR,
+       "FPSCR",        LFPSCR, D_FPSCR,
+       "SPR",          LSPR,   D_SPR,
+       "DCR",          LSPR,   D_DCR,
+
+       "CR",           LCR,    0,
+       "CR0",          LCREG,  0,
+       "CR1",          LCREG,  1,
+       "CR2",          LCREG,  2,
+       "CR3",          LCREG,  3,
+       "CR4",          LCREG,  4,
+       "CR5",          LCREG,  5,
+       "CR6",          LCREG,  6,
+       "CR7",          LCREG,  7,
+
+       "R",            LR,     0,
+       "R0",           LREG,   0,
+       "R1",           LREG,   1,
+       "R2",           LREG,   2,
+       "R3",           LREG,   3,
+       "R4",           LREG,   4,
+       "R5",           LREG,   5,
+       "R6",           LREG,   6,
+       "R7",           LREG,   7,
+       "R8",           LREG,   8,
+       "R9",           LREG,   9,
+       "R10",          LREG,   10,
+       "R11",          LREG,   11,
+       "R12",          LREG,   12,
+       "R13",          LREG,   13,
+       "R14",          LREG,   14,
+       "R15",          LREG,   15,
+       "R16",          LREG,   16,
+       "R17",          LREG,   17,
+       "R18",          LREG,   18,
+       "R19",          LREG,   19,
+       "R20",          LREG,   20,
+       "R21",          LREG,   21,
+       "R22",          LREG,   22,
+       "R23",          LREG,   23,
+       "R24",          LREG,   24,
+       "R25",          LREG,   25,
+       "R26",          LREG,   26,
+       "R27",          LREG,   27,
+       "R28",          LREG,   28,
+       "R29",          LREG,   29,
+       "g",            LREG,   30, // avoid unintentionally clobbering g using R30
+       "R31",          LREG,   31,
+
+       "F",            LF,     0,
+       "F0",           LFREG,  0,
+       "F1",           LFREG,  1,
+       "F2",           LFREG,  2,
+       "F3",           LFREG,  3,
+       "F4",           LFREG,  4,
+       "F5",           LFREG,  5,
+       "F6",           LFREG,  6,
+       "F7",           LFREG,  7,
+       "F8",           LFREG,  8,
+       "F9",           LFREG,  9,
+       "F10",          LFREG,  10,
+       "F11",          LFREG,  11,
+       "F12",          LFREG,  12,
+       "F13",          LFREG,  13,
+       "F14",          LFREG,  14,
+       "F15",          LFREG,  15,
+       "F16",          LFREG,  16,
+       "F17",          LFREG,  17,
+       "F18",          LFREG,  18,
+       "F19",          LFREG,  19,
+       "F20",          LFREG,  20,
+       "F21",          LFREG,  21,
+       "F22",          LFREG,  22,
+       "F23",          LFREG,  23,
+       "F24",          LFREG,  24,
+       "F25",          LFREG,  25,
+       "F26",          LFREG,  26,
+       "F27",          LFREG,  27,
+       "F28",          LFREG,  28,
+       "F29",          LFREG,  29,
+       "F30",          LFREG,  30,
+       "F31",          LFREG,  31,
+
+       "CREQV",        LCROP, ACREQV,
+       "CRXOR",        LCROP, ACRXOR,
+       "CRAND",        LCROP, ACRAND,
+       "CROR",         LCROP, ACROR,
+       "CRANDN",       LCROP, ACRANDN,
+       "CRORN",        LCROP, ACRORN,
+       "CRNAND",       LCROP, ACRNAND,
+       "CRNOR",        LCROP, ACRNOR,
+
+       "ADD",          LADDW, AADD,
+       "ADDV",         LADDW, AADDV,
+       "ADDCC",        LADDW, AADDCC,
+       "ADDVCC",       LADDW, AADDVCC,
+       "ADDC",         LADDW, AADDC,
+       "ADDCV",        LADDW, AADDCV,
+       "ADDCCC",       LADDW, AADDCCC,
+       "ADDCVCC",      LADDW, AADDCVCC,
+       "ADDE",         LLOGW, AADDE,
+       "ADDEV",        LLOGW, AADDEV,
+       "ADDECC",       LLOGW, AADDECC,
+       "ADDEVCC",      LLOGW, AADDEVCC,
+
+       "ADDME",        LABS, AADDME,
+       "ADDMEV",       LABS, AADDMEV,
+       "ADDMECC",      LABS, AADDMECC,
+       "ADDMEVCC",     LABS, AADDMEVCC,
+       "ADDZE",        LABS, AADDZE,
+       "ADDZEV",       LABS, AADDZEV,
+       "ADDZECC",      LABS, AADDZECC,
+       "ADDZEVCC",     LABS, AADDZEVCC,
+
+       "SUB",          LADDW, ASUB,
+       "SUBV",         LADDW, ASUBV,
+       "SUBCC",        LADDW, ASUBCC,
+       "SUBVCC",       LADDW, ASUBVCC,
+       "SUBE",         LLOGW, ASUBE,
+       "SUBECC",       LLOGW, ASUBECC,
+       "SUBEV",        LLOGW, ASUBEV,
+       "SUBEVCC",      LLOGW, ASUBEVCC,
+       "SUBC",         LADDW, ASUBC,
+       "SUBCCC",       LADDW, ASUBCCC,
+       "SUBCV",        LADDW, ASUBCV,
+       "SUBCVCC",      LADDW, ASUBCVCC,
+
+       "SUBME",        LABS, ASUBME,
+       "SUBMEV",       LABS, ASUBMEV,
+       "SUBMECC",      LABS, ASUBMECC,
+       "SUBMEVCC",     LABS, ASUBMEVCC,
+       "SUBZE",        LABS, ASUBZE,
+       "SUBZEV",       LABS, ASUBZEV,
+       "SUBZECC",      LABS, ASUBZECC,
+       "SUBZEVCC",     LABS, ASUBZEVCC,
+
+       "AND",          LADDW, AAND,
+       "ANDCC",        LADDW, AANDCC,  /* includes andil & andiu */
+       "ANDN",         LLOGW, AANDN,
+       "ANDNCC",       LLOGW, AANDNCC,
+       "EQV",          LLOGW, AEQV,
+       "EQVCC",        LLOGW, AEQVCC,
+       "NAND",         LLOGW, ANAND,
+       "NANDCC",       LLOGW, ANANDCC,
+       "NOR",          LLOGW, ANOR,
+       "NORCC",        LLOGW, ANORCC,
+       "OR",           LADDW, AOR,     /* includes oril & oriu */
+       "ORCC",         LADDW, AORCC,
+       "ORN",          LLOGW, AORN,
+       "ORNCC",        LLOGW, AORNCC,
+       "XOR",          LADDW, AXOR,    /* includes xoril & xoriu */
+       "XORCC",        LLOGW, AXORCC,
+
+       "EXTSB",        LABS,   AEXTSB,
+       "EXTSBCC",      LABS,   AEXTSBCC,
+       "EXTSH",        LABS, AEXTSH,
+       "EXTSHCC",      LABS, AEXTSHCC,
+
+       "CNTLZW",       LABS, ACNTLZW,
+       "CNTLZWCC",     LABS, ACNTLZWCC,
+
+       "RLWMI",        LRLWM, ARLWMI,
+       "RLWMICC",      LRLWM, ARLWMICC,
+       "RLWNM",        LRLWM, ARLWNM,
+       "RLWNMCC", LRLWM, ARLWNMCC,
+
+       "SLW",          LSHW, ASLW,
+       "SLWCC",        LSHW, ASLWCC,
+       "SRW",          LSHW, ASRW,
+       "SRWCC",        LSHW, ASRWCC,
+       "SRAW",         LSHW, ASRAW,
+       "SRAWCC",       LSHW, ASRAWCC,
+
+       "BR",           LBRA, ABR,
+       "BC",           LBRA, ABC,
+       "BCL",          LBRA, ABC,
+       "BL",           LBRA, ABL,
+       "BEQ",          LBRA, ABEQ,
+       "BNE",          LBRA, ABNE,
+       "BGT",          LBRA, ABGT,
+       "BGE",          LBRA, ABGE,
+       "BLT",          LBRA, ABLT,
+       "BLE",          LBRA, ABLE,
+       "BVC",          LBRA, ABVC,
+       "BVS",          LBRA, ABVS,
+
+       "CMP",          LCMP, ACMP,
+       "CMPU",         LCMP, ACMPU,
+       "CMPW",         LCMP, ACMPW,
+       "CMPWU",        LCMP, ACMPWU,
+
+       "DIVW",         LLOGW, ADIVW,
+       "DIVWV",        LLOGW, ADIVWV,
+       "DIVWCC",       LLOGW, ADIVWCC,
+       "DIVWVCC",      LLOGW, ADIVWVCC,
+       "DIVWU",        LLOGW, ADIVWU,
+       "DIVWUV",       LLOGW, ADIVWUV,
+       "DIVWUCC",      LLOGW, ADIVWUCC,
+       "DIVWUVCC",     LLOGW, ADIVWUVCC,
+
+       "FABS",         LFCONV, AFABS,
+       "FABSCC",       LFCONV, AFABSCC,
+       "FNEG",         LFCONV, AFNEG,
+       "FNEGCC",       LFCONV, AFNEGCC,
+       "FNABS",        LFCONV, AFNABS,
+       "FNABSCC",      LFCONV, AFNABSCC,
+
+       "FADD",         LFADD,  AFADD,
+       "FADDCC",       LFADD,  AFADDCC,
+       "FSUB",         LFADD,  AFSUB,
+       "FSUBCC",       LFADD,  AFSUBCC,
+       "FMUL",         LFADD,  AFMUL,
+       "FMULCC",       LFADD,  AFMULCC,
+       "FDIV",         LFADD,  AFDIV,
+       "FDIVCC",       LFADD,  AFDIVCC,
+       "FRSP",         LFCONV, AFRSP,
+       "FRSPCC",       LFCONV, AFRSPCC,
+       "FCTIW",        LFCONV, AFCTIW,
+       "FCTIWCC",      LFCONV, AFCTIWCC,
+       "FCTIWZ",       LFCONV, AFCTIWZ,
+       "FCTIWZCC",     LFCONV, AFCTIWZCC,
+
+       "FMADD",        LFMA, AFMADD,
+       "FMADDCC",      LFMA, AFMADDCC,
+       "FMSUB",        LFMA, AFMSUB,
+       "FMSUBCC",      LFMA, AFMSUBCC,
+       "FNMADD",       LFMA, AFNMADD,
+       "FNMADDCC",     LFMA, AFNMADDCC,
+       "FNMSUB",       LFMA, AFNMSUB,
+       "FNMSUBCC",     LFMA, AFNMSUBCC,
+       "FMADDS",       LFMA, AFMADDS,
+       "FMADDSCC",     LFMA, AFMADDSCC,
+       "FMSUBS",       LFMA, AFMSUBS,
+       "FMSUBSCC",     LFMA, AFMSUBSCC,
+       "FNMADDS",      LFMA, AFNMADDS,
+       "FNMADDSCC",    LFMA, AFNMADDSCC,
+       "FNMSUBS",      LFMA, AFNMSUBS,
+       "FNMSUBSCC",    LFMA, AFNMSUBSCC,
+
+       "FCMPU",        LFCMP, AFCMPU,
+       "FCMPO",        LFCMP, AFCMPO,
+       "MTFSB0",       LMTFSB, AMTFSB0,
+       "MTFSB1",       LMTFSB, AMTFSB1,
+
+       "FMOVD",        LFMOV, AFMOVD,
+       "FMOVS",        LFMOV, AFMOVS,
+       "FMOVDCC",      LFCONV, AFMOVDCC,       /* fmr. */
+
+       "GLOBL",        LTEXT, AGLOBL,
+
+       "MOVB",         LMOVB, AMOVB,
+       "MOVBZ",        LMOVB, AMOVBZ,
+       "MOVBU",        LMOVB, AMOVBU,
+       "MOVBZU", LMOVB, AMOVBZU,
+       "MOVH",         LMOVB, AMOVH,
+       "MOVHZ",        LMOVB, AMOVHZ,
+       "MOVHU",        LMOVB, AMOVHU,
+       "MOVHZU", LMOVB, AMOVHZU,
+       "MOVHBR",       LXMV, AMOVHBR,
+       "MOVWBR",       LXMV, AMOVWBR,
+       "MOVW",         LMOVW, AMOVW,
+       "MOVWU",        LMOVW, AMOVWU,
+       "MOVMW",        LMOVMW, AMOVMW,
+       "MOVFL",        LMOVW,  AMOVFL,
+
+       "MULLW",        LADDW, AMULLW,          /* includes multiply immediate 10-139 */
+       "MULLWV",       LLOGW, AMULLWV,
+       "MULLWCC",      LLOGW, AMULLWCC,
+       "MULLWVCC",     LLOGW, AMULLWVCC,
+
+       "MULHW",        LLOGW, AMULHW,
+       "MULHWCC",      LLOGW, AMULHWCC,
+       "MULHWU",       LLOGW, AMULHWU,
+       "MULHWUCC",     LLOGW, AMULHWUCC,
+
+       "NEG",          LABS, ANEG,
+       "NEGV",         LABS, ANEGV,
+       "NEGCC",        LABS, ANEGCC,
+       "NEGVCC",       LABS, ANEGVCC,
+
+       "NOP",          LNOP, ANOP,     /* ori 0,0,0 */
+       "SYSCALL",      LNOP, ASYSCALL,
+       "UNDEF",        LNOP, AUNDEF,
+
+       "RET",          LRETRN, ARETURN,
+       "RETURN",       LRETRN, ARETURN,
+       "RFI",          LRETRN, ARFI,
+       "RFCI",         LRETRN, ARFCI,
+
+       "DATA",         LDATA, ADATA,
+       "END",          LEND, AEND,
+       "TEXT",         LTEXT, ATEXT,
+
+       /* 64-bit instructions */
+       "CNTLZD",       LABS,   ACNTLZD,
+       "CNTLZDCC",     LABS,   ACNTLZDCC,
+       "DIVD", LLOGW,  ADIVD,
+       "DIVDCC",       LLOGW,  ADIVDCC,
+       "DIVDVCC",      LLOGW,  ADIVDVCC,
+       "DIVDV",        LLOGW,  ADIVDV,
+       "DIVDU",        LLOGW,  ADIVDU,
+       "DIVDUCC",      LLOGW,  ADIVDUCC,
+       "DIVDUVCC",     LLOGW,  ADIVDUVCC,
+       "DIVDUV",       LLOGW,  ADIVDUV,
+       "EXTSW",        LABS, AEXTSW,
+       "EXTSWCC",      LABS, AEXTSWCC,
+       "FCTID",        LFCONV, AFCTID,
+       "FCTIDCC",      LFCONV, AFCTIDCC,
+       "FCTIDZ",       LFCONV, AFCTIDZ,
+       "FCTIDZCC",     LFCONV, AFCTIDZCC,
+       "FCFID",        LFCONV, AFCFID,
+       "FCFIDCC",      LFCONV, AFCFIDCC,
+       "LDAR", LXLD, ALDAR,
+       "MOVD", LMOVW,  AMOVD,
+       "MOVDU",        LMOVW,  AMOVDU,
+       "MOVWZ",        LMOVW,  AMOVWZ,
+       "MOVWZU",       LMOVW,  AMOVWZU,
+       "MULHD",        LLOGW,  AMULHD,
+       "MULHDCC",      LLOGW,  AMULHDCC,
+       "MULHDU",       LLOGW,  AMULHDU,
+       "MULHDUCC",     LLOGW,  AMULHDUCC,
+       "MULLD",        LADDW,  AMULLD, /* includes multiply immediate? */
+       "MULLDCC",      LLOGW,  AMULLDCC,
+       "MULLDVCC",     LLOGW,  AMULLDVCC,
+       "MULLDV",       LLOGW,  AMULLDV,
+       "RFID", LRETRN, ARFID,
+       "HRFID", LRETRN, AHRFID,
+       "RLDMI",        LRLWM,  ARLDMI,
+       "RLDMICC",      LRLWM,  ARLDMICC,
+       "RLDC", LRLWM,  ARLDC,
+       "RLDCCC",       LRLWM,  ARLDCCC,
+       "RLDCR",        LRLWM,  ARLDCR,
+       "RLDCRCC",      LRLWM,  ARLDCRCC,
+       "RLDCL",        LRLWM,  ARLDCL,
+       "RLDCLCC",      LRLWM,  ARLDCLCC,
+       "SLBIA",        LNOP,   ASLBIA,
+       "SLBIE",        LNOP,   ASLBIE,
+       "SLBMFEE",      LABS,   ASLBMFEE,
+       "SLBMFEV",      LABS,   ASLBMFEV,
+       "SLBMTE",       LABS,   ASLBMTE,
+       "SLD",  LSHW,   ASLD,
+       "SLDCC",        LSHW,   ASLDCC,
+       "SRD",  LSHW,   ASRD,
+       "SRAD", LSHW,   ASRAD,
+       "SRADCC",       LSHW,   ASRADCC,
+       "SRDCC",        LSHW,   ASRDCC,
+       "STDCCC",       LXST,   ASTDCCC,
+       "TD",   LADDW,  ATD,
+
+       /* pseudo instructions */
+       "REM",  LLOGW,  AREM,
+       "REMCC",        LLOGW,  AREMCC,
+       "REMV", LLOGW,  AREMV,
+       "REMVCC",       LLOGW,  AREMVCC,
+       "REMU", LLOGW,  AREMU,
+       "REMUCC",       LLOGW,  AREMUCC,
+       "REMUV",        LLOGW,  AREMUV,
+       "REMUVCC",      LLOGW,  AREMUVCC,
+       "REMD", LLOGW,  AREMD,
+       "REMDCC",       LLOGW,  AREMDCC,
+       "REMDV",        LLOGW,  AREMDV,
+       "REMDVCC",      LLOGW,  AREMDVCC,
+       "REMDU",        LLOGW,  AREMDU,
+       "REMDUCC",      LLOGW,  AREMDUCC,
+       "REMDUV",       LLOGW,  AREMDUV,
+       "REMDUVCC",     LLOGW,  AREMDUVCC,
+
+/* special instructions */
+       "DCBF",         LXOP,   ADCBF,
+       "DCBI",         LXOP,   ADCBI,
+       "DCBST",        LXOP,   ADCBST,
+       "DCBT",         LXOP,   ADCBT,
+       "DCBTST",       LXOP,   ADCBTST,
+       "DCBZ",         LXOP,   ADCBZ,
+       "ICBI",         LXOP,   AICBI,
+
+       "ECIWX",        LXLD,   AECIWX,
+       "ECOWX",        LXST,   AECOWX,
+       "LWAR", LXLD, ALWAR,
+       "LWAR", LXLD, ALWAR,
+       "STWCCC", LXST, ASTWCCC,
+       "EIEIO",        LRETRN, AEIEIO,
+       "TLBIE",        LNOP,   ATLBIE,
+       "TLBIEL",       LNOP,   ATLBIEL,
+       "LSW",  LXLD, ALSW,
+       "STSW", LXST, ASTSW,
+       
+       "ISYNC",        LRETRN, AISYNC,
+       "SYNC",         LRETRN, ASYNC,
+       "TLBSYNC",      LRETRN, ATLBSYNC,
+       "PTESYNC",      LRETRN, APTESYNC,
+/*     "TW",           LADDW,  ATW,*/
+
+       "WORD",         LWORD, AWORD,
+       "DWORD",        LWORD, ADWORD,
+       "SCHED",        LSCHED, 0,
+       "NOSCHED",      LSCHED, 0x80,
+
+       "PCDATA",       LPCDAT, APCDATA,
+       "FUNCDATA",     LFUNCDAT,       AFUNCDATA,
+
+       0
+};
+
+void
+cinit(void)
+{
+       Sym *s;
+       int i;
+
+       nullgen.type = D_NONE;
+       nullgen.name = D_NONE;
+       nullgen.reg = NREG;
+       nullgen.scale = NREG; // replaced Gen.xreg with Prog.scale
+
+       nerrors = 0;
+       iostack = I;
+       iofree = I;
+       peekc = IGN;
+       nhunk = 0;
+       for(i=0; i<NHASH; i++)
+               hash[i] = S;
+       for(i=0; itab[i].name; i++) {
+               s = slookup(itab[i].name);
+               s->type = itab[i].type;
+               s->value = itab[i].value;
+       }
+}
+
+void
+syminit(Sym *s)
+{
+
+       s->type = LNAME;
+       s->value = 0;
+}
+
+void
+cclean(void)
+{
+
+       outcode(AEND, &nullgen, NREG, &nullgen);
+}
+
+static Prog *lastpc;
+
+void
+outcode(int a, Addr *g1, int reg, Addr *g2)
+{
+       Prog *p;
+       Plist *pl;
+
+       if(pass == 1)
+               goto out;
+
+       if(g1->scale != NREG) {
+               if(reg != NREG || g2->scale != NREG)
+                       yyerror("bad addressing modes");
+               reg = g1->scale;
+       } else
+       if(g2->scale != NREG) {
+               if(reg != NREG)
+                       yyerror("bad addressing modes");
+               reg = g2->scale;
+       }
+
+       p = ctxt->arch->prg();
+       p->as = a;
+       p->lineno = lineno;
+       if(nosched)
+               p->mark |= NOSCHED;
+       p->from = *g1;
+       p->reg = reg;
+       p->to = *g2;
+       p->pc = pc;
+
+       if(lastpc == nil) {
+               pl = linknewplist(ctxt);
+               pl->firstpc = p;
+       } else
+               lastpc->link = p;
+       lastpc = p;
+out:
+       if(a != AGLOBL && a != ADATA)
+               pc++;
+}
+
+void
+outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3)
+{
+       Prog *p;
+       Plist *pl;
+
+       if(pass == 1)
+               goto out;
+
+       p = ctxt->arch->prg();
+       p->as = a;
+       p->lineno = lineno;
+       if(nosched)
+               p->mark |= NOSCHED;
+       p->from = *g1;
+       p->reg = reg;
+       p->from3 = *g2;
+       p->to = *g3;
+       p->pc = pc;
+
+       if(lastpc == nil) {
+               pl = linknewplist(ctxt);
+               pl->firstpc = p;
+       } else
+               lastpc->link = p;
+       lastpc = p;
+out:
+       if(a != AGLOBL && a != ADATA)
+               pc++;
+}
+
+#include "../cc/lexbody"
+#include "../cc/macbody"
diff --git a/src/cmd/9a/y.tab.c b/src/cmd/9a/y.tab.c
new file mode 100644 (file)
index 0000000..6025a24
--- /dev/null
@@ -0,0 +1,3398 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* 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 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, 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
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   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.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     LMOVW = 258,
+     LMOVB = 259,
+     LABS = 260,
+     LLOGW = 261,
+     LSHW = 262,
+     LADDW = 263,
+     LCMP = 264,
+     LCROP = 265,
+     LBRA = 266,
+     LFMOV = 267,
+     LFCONV = 268,
+     LFCMP = 269,
+     LFADD = 270,
+     LFMA = 271,
+     LTRAP = 272,
+     LXORW = 273,
+     LNOP = 274,
+     LEND = 275,
+     LRETT = 276,
+     LWORD = 277,
+     LTEXT = 278,
+     LDATA = 279,
+     LRETRN = 280,
+     LCONST = 281,
+     LSP = 282,
+     LSB = 283,
+     LFP = 284,
+     LPC = 285,
+     LCREG = 286,
+     LFLUSH = 287,
+     LREG = 288,
+     LFREG = 289,
+     LR = 290,
+     LCR = 291,
+     LF = 292,
+     LFPSCR = 293,
+     LLR = 294,
+     LCTR = 295,
+     LSPR = 296,
+     LSPREG = 297,
+     LSEG = 298,
+     LMSR = 299,
+     LPCDAT = 300,
+     LFUNCDAT = 301,
+     LSCHED = 302,
+     LXLD = 303,
+     LXST = 304,
+     LXOP = 305,
+     LXMV = 306,
+     LRLWM = 307,
+     LMOVMW = 308,
+     LMOVEM = 309,
+     LMOVFL = 310,
+     LMTFSB = 311,
+     LMA = 312,
+     LFCONST = 313,
+     LSCONST = 314,
+     LNAME = 315,
+     LLAB = 316,
+     LVAR = 317
+   };
+#endif
+/* Tokens.  */
+#define LMOVW 258
+#define LMOVB 259
+#define LABS 260
+#define LLOGW 261
+#define LSHW 262
+#define LADDW 263
+#define LCMP 264
+#define LCROP 265
+#define LBRA 266
+#define LFMOV 267
+#define LFCONV 268
+#define LFCMP 269
+#define LFADD 270
+#define LFMA 271
+#define LTRAP 272
+#define LXORW 273
+#define LNOP 274
+#define LEND 275
+#define LRETT 276
+#define LWORD 277
+#define LTEXT 278
+#define LDATA 279
+#define LRETRN 280
+#define LCONST 281
+#define LSP 282
+#define LSB 283
+#define LFP 284
+#define LPC 285
+#define LCREG 286
+#define LFLUSH 287
+#define LREG 288
+#define LFREG 289
+#define LR 290
+#define LCR 291
+#define LF 292
+#define LFPSCR 293
+#define LLR 294
+#define LCTR 295
+#define LSPR 296
+#define LSPREG 297
+#define LSEG 298
+#define LMSR 299
+#define LPCDAT 300
+#define LFUNCDAT 301
+#define LSCHED 302
+#define LXLD 303
+#define LXST 304
+#define LXOP 305
+#define LXMV 306
+#define LRLWM 307
+#define LMOVMW 308
+#define LMOVEM 309
+#define LMOVFL 310
+#define LMTFSB 311
+#define LMA 312
+#define LFCONST 313
+#define LSCONST 314
+#define LNAME 315
+#define LLAB 316
+#define LVAR 317
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 30 "a.y"
+
+#include <u.h>
+#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
+#include <libc.h>
+#include "a.h"
+#include "../../runtime/funcdata.h"
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 38 "a.y"
+{
+       Sym     *sym;
+       vlong   lval;
+       double  dval;
+       char    sval[8];
+       Addr    addr;
+}
+/* Line 193 of yacc.c.  */
+#line 236 "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 216 of yacc.c.  */
+#line 249 "y.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    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 _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+            && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   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 _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  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)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((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
+
+/* 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  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   862
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  81
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  31
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  183
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  453
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   317
+
+#define YYTRANSLATE(YYX)                                               \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+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,    79,    12,     5,     2,
+      77,    78,    10,     8,    76,     9,     2,    11,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    73,    75,
+       6,    74,     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,    80,     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,     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,     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,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       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,    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
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     4,     7,     8,    13,    18,    23,    26,
+      28,    31,    34,    39,    44,    49,    54,    59,    64,    69,
+      74,    79,    84,    89,    94,    99,   104,   109,   114,   119,
+     124,   129,   134,   141,   146,   151,   156,   163,   168,   173,
+     180,   187,   194,   199,   204,   211,   216,   223,   228,   235,
+     240,   245,   248,   255,   260,   265,   270,   277,   282,   287,
+     292,   297,   302,   307,   312,   317,   320,   323,   328,   332,
+     336,   342,   347,   352,   359,   364,   369,   376,   383,   390,
+     399,   404,   409,   413,   416,   421,   426,   433,   442,   447,
+     454,   459,   464,   471,   478,   487,   496,   505,   514,   519,
+     524,   529,   536,   541,   548,   553,   558,   561,   564,   568,
+     572,   576,   580,   583,   587,   591,   596,   601,   604,   609,
+     616,   625,   632,   639,   646,   649,   654,   657,   659,   661,
+     663,   665,   667,   669,   671,   673,   678,   680,   682,   687,
+     689,   694,   696,   701,   703,   707,   710,   713,   716,   720,
+     723,   725,   730,   734,   740,   742,   747,   752,   758,   766,
+     767,   769,   770,   773,   776,   778,   780,   782,   784,   786,
+     789,   792,   795,   799,   801,   805,   809,   813,   817,   821,
+     826,   831,   835,   839
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      82,     0,    -1,    -1,    82,    83,    -1,    -1,    70,    73,
+      84,    83,    -1,    70,    74,   111,    75,    -1,    72,    74,
+     111,    75,    -1,    57,    75,    -1,    75,    -1,    85,    75,
+      -1,     1,    75,    -1,    13,    87,    76,    87,    -1,    13,
+     105,    76,    87,    -1,    13,   104,    76,    87,    -1,    14,
+      87,    76,    87,    -1,    14,   105,    76,    87,    -1,    14,
+     104,    76,    87,    -1,    22,   105,    76,    96,    -1,    22,
+     104,    76,    96,    -1,    22,   101,    76,    96,    -1,    22,
+      96,    76,    96,    -1,    22,    96,    76,   105,    -1,    22,
+      96,    76,   104,    -1,    13,    87,    76,   105,    -1,    13,
+      87,    76,   104,    -1,    14,    87,    76,   105,    -1,    14,
+      87,    76,   104,    -1,    13,    96,    76,   105,    -1,    13,
+      96,    76,   104,    -1,    13,    94,    76,    96,    -1,    13,
+      96,    76,    94,    -1,    13,    96,    76,   102,    76,    94,
+      -1,    13,    94,    76,    97,    -1,    13,   102,    76,    95,
+      -1,    66,   102,    76,   110,    -1,    13,    87,    76,   102,
+      76,    90,    -1,    13,    87,    76,    97,    -1,    13,    87,
+      76,    90,    -1,    18,    87,    76,   103,    76,    87,    -1,
+      18,   102,    76,   103,    76,    87,    -1,    18,    87,    76,
+     102,    76,    87,    -1,    18,    87,    76,    87,    -1,    18,
+     102,    76,    87,    -1,    16,    87,    76,   103,    76,    87,
+      -1,    16,    87,    76,    87,    -1,    17,    87,    76,   103,
+      76,    87,    -1,    17,    87,    76,    87,    -1,    17,   102,
+      76,   103,    76,    87,    -1,    17,   102,    76,    87,    -1,
+      15,    87,    76,    87,    -1,    15,    87,    -1,    67,    87,
+      76,   103,    76,    87,    -1,    13,   102,    76,    87,    -1,
+      13,   100,    76,    87,    -1,    20,    98,    76,    98,    -1,
+      20,    98,    76,   110,    76,    98,    -1,    13,    97,    76,
+      97,    -1,    13,    93,    76,    97,    -1,    13,    90,    76,
+      87,    -1,    13,    93,    76,    87,    -1,    13,    88,    76,
+      87,    -1,    13,    87,    76,    88,    -1,    13,    97,    76,
+      93,    -1,    13,    87,    76,    93,    -1,    21,    86,    -1,
+      21,   105,    -1,    21,    77,    88,    78,    -1,    21,    76,
+      86,    -1,    21,    76,   105,    -1,    21,    76,    77,    88,
+      78,    -1,    21,    97,    76,    86,    -1,    21,    97,    76,
+     105,    -1,    21,    97,    76,    77,    88,    78,    -1,    21,
+     110,    76,    86,    -1,    21,   110,    76,   105,    -1,    21,
+     110,    76,    77,    88,    78,    -1,    21,   110,    76,   110,
+      76,    86,    -1,    21,   110,    76,   110,    76,   105,    -1,
+      21,   110,    76,   110,    76,    77,    88,    78,    -1,    27,
+      87,    76,   103,    -1,    27,   102,    76,   103,    -1,    27,
+      87,   107,    -1,    27,   107,    -1,    23,    96,    76,    96,
+      -1,    25,    96,    76,    96,    -1,    25,    96,    76,    96,
+      76,    96,    -1,    26,    96,    76,    96,    76,    96,    76,
+      96,    -1,    24,    96,    76,    96,    -1,    24,    96,    76,
+      96,    76,    97,    -1,    19,    87,    76,    87,    -1,    19,
+      87,    76,   102,    -1,    19,    87,    76,    87,    76,    97,
+      -1,    19,    87,    76,   102,    76,    97,    -1,    62,   102,
+      76,    87,    76,   102,    76,    87,    -1,    62,   102,    76,
+      87,    76,    99,    76,    87,    -1,    62,    87,    76,    87,
+      76,   102,    76,    87,    -1,    62,    87,    76,    87,    76,
+      99,    76,    87,    -1,    63,   105,    76,    87,    -1,    63,
+      87,    76,   105,    -1,    58,   104,    76,    87,    -1,    58,
+     104,    76,   102,    76,    87,    -1,    59,    87,    76,   104,
+      -1,    59,    87,    76,   102,    76,   104,    -1,    61,   104,
+      76,    87,    -1,    61,    87,    76,   104,    -1,    60,   104,
+      -1,    29,   107,    -1,    29,    87,   107,    -1,    29,    96,
+     107,    -1,    29,    76,    87,    -1,    29,    76,    96,    -1,
+      29,   102,    -1,    32,   102,   107,    -1,    32,   100,   107,
+      -1,    55,   102,    76,   102,    -1,    56,   102,    76,   105,
+      -1,    30,   107,    -1,    33,   106,    76,   102,    -1,    33,
+     106,    76,   110,    76,   102,    -1,    33,   106,    76,   110,
+      76,   102,     9,   110,    -1,    34,   106,    11,   110,    76,
+     102,    -1,    34,   106,    11,   110,    76,   100,    -1,    34,
+     106,    11,   110,    76,   101,    -1,    35,   107,    -1,   110,
+      77,    40,    78,    -1,    70,   108,    -1,   103,    -1,    89,
+      -1,    91,    -1,    49,    -1,    46,    -1,    50,    -1,    54,
+      -1,    52,    -1,    51,    77,   110,    78,    -1,    92,    -1,
+      48,    -1,    48,    77,   110,    78,    -1,    44,    -1,    47,
+      77,   110,    78,    -1,    41,    -1,    46,    77,   110,    78,
+      -1,   110,    -1,   110,    76,   110,    -1,    79,   105,    -1,
+      79,    69,    -1,    79,    68,    -1,    79,     9,    68,    -1,
+      79,   110,    -1,    43,    -1,    45,    77,   110,    78,    -1,
+      77,   103,    78,    -1,    77,   103,     8,   103,    78,    -1,
+     106,    -1,   110,    77,   103,    78,    -1,   110,    77,   109,
+      78,    -1,    70,   108,    77,   109,    78,    -1,    70,     6,
+       7,   108,    77,    38,    78,    -1,    -1,    76,    -1,    -1,
+       8,   110,    -1,     9,   110,    -1,    38,    -1,    37,    -1,
+      39,    -1,    36,    -1,    72,    -1,     9,   110,    -1,     8,
+     110,    -1,    80,   110,    -1,    77,   111,    78,    -1,   110,
+      -1,   111,     8,   111,    -1,   111,     9,   111,    -1,   111,
+      10,   111,    -1,   111,    11,   111,    -1,   111,    12,   111,
+      -1,   111,     6,     6,   111,    -1,   111,     7,     7,   111,
+      -1,   111,     5,   111,    -1,   111,     4,   111,    -1,   111,
+       3,   111,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,    66,    66,    67,    71,    70,    79,    84,    90,    94,
+      95,    96,   102,   106,   110,   114,   118,   122,   129,   133,
+     137,   141,   145,   149,   156,   160,   164,   168,   175,   179,
+     186,   190,   194,   198,   202,   206,   213,   217,   221,   231,
+     235,   239,   243,   247,   251,   255,   259,   263,   267,   271,
+     275,   279,   286,   293,   297,   304,   308,   316,   320,   324,
+     328,   332,   336,   340,   344,   353,   357,   361,   365,   369,
+     373,   377,   381,   385,   389,   393,   397,   401,   409,   417,
+     428,   432,   436,   440,   447,   451,   455,   459,   463,   467,
+     474,   478,   482,   486,   493,   497,   501,   505,   512,   516,
+     524,   528,   532,   536,   540,   544,   548,   555,   559,   563,
+     567,   571,   575,   582,   586,   593,   602,   613,   620,   625,
+     632,   642,   646,   650,   657,   663,   669,   680,   688,   689,
+     692,   700,   708,   716,   723,   729,   735,   738,   746,   754,
+     760,   768,   774,   782,   790,   811,   816,   824,   830,   837,
+     845,   846,   854,   861,   871,   872,   881,   889,   897,   906,
+     907,   910,   913,   917,   923,   924,   925,   928,   929,   933,
+     937,   941,   945,   951,   952,   956,   960,   964,   968,   972,
+     976,   980,   984,   988
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
+  "'-'", "'*'", "'/'", "'%'", "LMOVW", "LMOVB", "LABS", "LLOGW", "LSHW",
+  "LADDW", "LCMP", "LCROP", "LBRA", "LFMOV", "LFCONV", "LFCMP", "LFADD",
+  "LFMA", "LTRAP", "LXORW", "LNOP", "LEND", "LRETT", "LWORD", "LTEXT",
+  "LDATA", "LRETRN", "LCONST", "LSP", "LSB", "LFP", "LPC", "LCREG",
+  "LFLUSH", "LREG", "LFREG", "LR", "LCR", "LF", "LFPSCR", "LLR", "LCTR",
+  "LSPR", "LSPREG", "LSEG", "LMSR", "LPCDAT", "LFUNCDAT", "LSCHED", "LXLD",
+  "LXST", "LXOP", "LXMV", "LRLWM", "LMOVMW", "LMOVEM", "LMOVFL", "LMTFSB",
+  "LMA", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='",
+  "';'", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog", "line",
+  "@1", "inst", "rel", "rreg", "xlreg", "lr", "lcr", "ctr", "msr", "psr",
+  "fpscr", "fpscrf", "freg", "creg", "cbit", "mask", "ximm", "fimm", "imm",
+  "sreg", "regaddr", "addr", "name", "comma", "offset", "pointer", "con",
+  "expr", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   124,    94,    38,    60,    62,    43,    45,
+      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,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,    58,    61,    59,    44,    40,    41,    36,
+     126
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    81,    82,    82,    84,    83,    83,    83,    83,    83,
+      83,    83,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    85,    85,    85,    85,    85,
+      85,    85,    85,    85,    85,    86,    86,    87,    88,    88,
+      89,    90,    91,    92,    93,    93,    93,    94,    95,    96,
+      96,    97,    97,    98,    99,   100,   100,   101,   101,   102,
+     103,   103,   104,   104,   105,   105,   106,   106,   106,   107,
+     107,   108,   108,   108,   109,   109,   109,   110,   110,   110,
+     110,   110,   110,   111,   111,   111,   111,   111,   111,   111,
+     111,   111,   111,   111
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     0,     4,     4,     4,     2,     1,
+       2,     2,     4,     4,     4,     4,     4,     4,     4,     4,
+       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
+       4,     4,     6,     4,     4,     4,     6,     4,     4,     6,
+       6,     6,     4,     4,     6,     4,     6,     4,     6,     4,
+       4,     2,     6,     4,     4,     4,     6,     4,     4,     4,
+       4,     4,     4,     4,     4,     2,     2,     4,     3,     3,
+       5,     4,     4,     6,     4,     4,     6,     6,     6,     8,
+       4,     4,     3,     2,     4,     4,     6,     8,     4,     6,
+       4,     4,     6,     6,     8,     8,     8,     8,     4,     4,
+       4,     6,     4,     6,     4,     4,     2,     2,     3,     3,
+       3,     3,     2,     3,     3,     4,     4,     2,     4,     6,
+       8,     6,     6,     6,     2,     4,     2,     1,     1,     1,
+       1,     1,     1,     1,     1,     4,     1,     1,     4,     1,
+       4,     1,     4,     1,     3,     2,     2,     2,     3,     2,
+       1,     4,     3,     5,     1,     4,     4,     5,     7,     0,
+       1,     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
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   159,   159,
+     159,     0,     0,     0,   159,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     9,     3,
+       0,    11,     0,     0,   167,   141,   150,   139,     0,   131,
+       0,   137,   130,   132,     0,   134,   133,   161,   168,     0,
+       0,     0,     0,     0,   128,     0,   129,   136,     0,     0,
+       0,     0,     0,     0,   127,     0,     0,   154,     0,     0,
+       0,     0,    51,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   143,     0,   161,     0,     0,    65,     0,    66,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     160,   159,     0,    83,   160,   159,   159,   112,   107,   117,
+     159,   159,     0,     0,     0,   124,     0,     0,     8,     0,
+       0,     0,   106,     0,     0,     0,     0,     0,     0,     0,
+       0,     4,     0,     0,    10,   170,   169,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   173,     0,   146,   145,
+     149,   171,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   149,
+       0,     0,     0,     0,     0,     0,   126,     0,    68,    69,
+       0,     0,     0,     0,     0,     0,   147,     0,     0,     0,
+       0,     0,     0,     0,     0,   160,    82,     0,   110,   111,
+     108,   109,   114,   113,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   161,   162,   163,     0,
+       0,   152,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   172,    12,    62,    38,    64,    37,     0,    25,
+      24,    61,    59,    60,    58,    30,    33,    31,     0,    29,
+      28,    63,    57,    54,     0,    53,    34,    14,    13,   165,
+     164,   166,     0,     0,    15,    27,    26,    17,    16,    50,
+      45,   127,    47,   127,    49,   127,    42,     0,   127,    43,
+     127,    90,    91,    55,   143,     0,    67,     0,    71,    72,
+       0,    74,    75,     0,     0,   148,    21,    23,    22,    20,
+      19,    18,    84,    88,    85,     0,    80,    81,   118,     0,
+       0,   115,   116,   100,     0,     0,   102,   105,   104,     0,
+       0,    99,    98,    35,     0,     5,     6,     7,   151,   142,
+     140,   135,     0,     0,     0,   183,   182,   181,     0,     0,
+     174,   175,   176,   177,   178,     0,     0,     0,   155,   156,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    70,
+       0,     0,     0,   125,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   157,   153,   179,   180,   131,
+      36,    32,     0,    44,    46,    48,    41,    39,    40,    92,
+      93,    56,    73,    76,     0,    77,    78,    89,    86,     0,
+     119,     0,   122,   123,   121,   101,   103,     0,     0,     0,
+       0,     0,    52,     0,   138,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   158,    79,    87,   120,    97,    96,
+     144,    95,    94
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,     1,    39,   229,    40,    97,    62,    63,    64,    65,
+      66,    67,    68,    69,   276,    70,    71,    91,   427,    72,
+     103,    73,    74,    75,   159,    77,   113,   154,   283,   156,
+     157
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -176
+static const yytype_int16 yypact[] =
+{
+    -176,   464,  -176,   -63,   560,   637,    97,    97,   -24,   -24,
+      97,   556,   317,   618,    12,    12,    12,    12,   -27,    47,
+     -47,   -29,   725,   725,   -47,   -26,   -26,   -43,   -17,    97,
+     -17,   -23,   -24,   658,   -26,    97,    51,   -11,  -176,  -176,
+      -2,  -176,   556,   556,  -176,  -176,  -176,  -176,    -1,     2,
+      11,  -176,  -176,  -176,    24,  -176,  -176,    91,  -176,    26,
+     716,   556,    57,    65,  -176,    85,  -176,  -176,    92,    98,
+     104,   110,   119,   134,  -176,   155,   160,  -176,    69,   162,
+     165,   170,   172,   176,   556,   179,   180,   182,   183,   185,
+     556,   187,  -176,     2,    91,   736,   326,  -176,   196,  -176,
+      52,     6,   197,   198,   202,   203,   215,   216,   217,   222,
+    -176,   223,   235,  -176,    73,   -47,   -47,  -176,  -176,  -176,
+     -47,   -47,   239,    79,   178,  -176,   240,   246,  -176,    97,
+     247,   248,  -176,   252,   253,   255,   262,   263,   266,   267,
+     268,  -176,   556,   556,  -176,  -176,  -176,   556,   556,   556,
+     556,   193,   556,   556,   166,     9,  -176,   278,  -176,  -176,
+      69,  -176,   607,    97,    97,   109,    20,   683,    61,    97,
+      27,    97,    97,   340,   637,    97,    97,    97,    97,  -176,
+      97,    97,   -24,    97,   -24,   556,   166,   326,  -176,  -176,
+     199,   152,   742,   762,   153,   283,  -176,   696,    12,    12,
+      12,    12,    12,    12,    12,    97,  -176,    97,  -176,  -176,
+    -176,  -176,  -176,  -176,   382,     4,   556,   -26,   725,   -24,
+      72,   -17,    97,    97,    97,   725,    97,   556,    97,   527,
+     436,   567,   274,   276,   277,   279,   154,  -176,  -176,     4,
+      97,  -176,   556,   556,   556,   353,   339,   556,   556,   556,
+     556,   556,  -176,  -176,  -176,  -176,  -176,  -176,   284,  -176,
+    -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,   295,  -176,
+    -176,  -176,  -176,  -176,   303,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,   304,   308,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,   305,  -176,   316,  -176,   323,  -176,   325,   333,  -176,
+     334,   335,   336,  -176,   343,   342,  -176,   326,  -176,  -176,
+     326,  -176,  -176,   139,   344,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,   345,   348,   349,  -176,  -176,  -176,   354,
+     355,  -176,  -176,  -176,   356,   357,  -176,  -176,  -176,   360,
+     373,  -176,  -176,  -176,   374,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,   327,   377,   379,   298,   612,   506,   556,   556,
+     125,   125,  -176,  -176,  -176,   405,   410,   556,  -176,  -176,
+      97,    97,    97,    97,    97,    97,    -8,    -8,   556,  -176,
+     385,   388,   782,  -176,    -8,    12,    12,   -26,   381,    97,
+     -17,   382,   382,    97,   429,  -176,  -176,   498,   498,  -176,
+    -176,  -176,   390,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176,   326,  -176,  -176,  -176,  -176,   393,
+     462,   712,  -176,  -176,  -176,  -176,  -176,   398,   399,   416,
+     419,   426,  -176,   451,  -176,   454,    12,   556,   328,    97,
+      97,   556,    97,    97,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -176,  -176,   306,  -176,  -176,   -88,    -5,   -73,  -176,  -154,
+    -176,  -176,  -137,  -158,  -176,    67,    39,  -175,   141,   -15,
+     149,   113,   167,    80,    32,   200,   124,   -83,   299,    35,
+      70
+};
+
+/* 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 -1
+static const yytype_uint16 yytable[] =
+{
+      79,    82,    83,    85,    87,    89,   120,   188,   255,   267,
+     303,   186,    41,   111,   115,   195,    46,   240,    48,    46,
+      46,    48,    48,   191,   131,   256,   133,   135,   137,   110,
+     140,   271,   128,    45,    42,    43,    76,    81,    93,    78,
+      78,   279,   280,   281,    99,   105,    92,   100,    78,   110,
+      60,    98,    84,    84,   129,    84,    47,   123,   123,    50,
+     129,    45,    44,   143,    47,   138,    93,    50,    78,    46,
+      46,    48,    48,   144,   196,   274,   147,   145,   146,   148,
+     102,   106,   107,   108,   109,    80,   116,   241,   149,   254,
+      46,    47,    48,   104,    50,   160,   161,   151,    58,   152,
+     153,   150,    45,    90,   308,   311,    61,    93,   130,   208,
+     132,   134,    54,    55,   305,    56,    46,    47,    48,   179,
+      50,    86,    88,   114,   141,   142,    84,   189,   193,   194,
+     190,   112,   117,   162,   121,   249,   250,   251,   126,   127,
+      46,   163,    48,   118,   119,   136,   173,   139,   125,   129,
+      45,    84,    46,   352,    48,    93,   215,   253,   261,   262,
+     263,   164,   152,   153,   273,   275,   277,   278,   165,   284,
+     287,   288,   289,   290,   166,   292,   294,   296,   299,   301,
+     167,   209,   232,   233,   234,   235,   168,   237,   238,   216,
+     279,   280,   281,   314,   260,   169,    46,    78,    48,   270,
+     236,   257,    78,   411,   264,   266,   286,   272,   401,    78,
+     170,   400,   230,   231,   333,   382,   194,   338,   339,   340,
+     304,   342,   122,   124,   309,   312,   155,   190,   313,   318,
+     306,   171,    78,   265,   380,   206,   172,   381,   174,   210,
+     211,   175,   259,   239,   212,   213,   176,   269,   177,   329,
+     332,   330,   178,    78,   285,   180,   181,   341,   182,   183,
+      78,   184,   343,   185,   316,   319,   320,   321,   322,   323,
+     324,   325,   192,   197,   198,   258,   194,   317,   199,   200,
+     268,   242,   243,   244,   245,   246,   247,   248,   249,   250,
+     251,   201,   202,   203,   415,   297,   155,   302,   204,   205,
+     336,   337,   243,   244,   245,   246,   247,   248,   249,   250,
+     251,   207,   355,   356,   357,   214,   217,   360,   361,   362,
+     363,   364,   218,   219,   220,    42,    43,   328,   221,   222,
+     331,   223,   334,   335,    42,    43,    42,    43,   224,   225,
+     282,   435,   226,   227,   228,   291,   359,   293,   295,   298,
+     300,   315,   348,    44,   349,   350,   252,   351,    45,   358,
+     365,   282,    44,    93,    44,   403,   404,   405,   406,   407,
+     408,   366,   326,   422,   327,    52,    53,   279,   280,   281,
+     367,   370,   368,    46,   425,    48,   369,    94,   432,    58,
+      42,    43,   371,    95,    96,   344,   315,    61,    58,   372,
+      58,   373,   402,    90,   394,    90,    61,   354,    61,   374,
+     375,   376,   377,    92,   416,   409,   410,   190,    44,   378,
+     379,   384,   383,   417,   385,   386,   429,   429,   397,   398,
+     387,   388,   389,   390,   448,   449,   391,   451,   452,   242,
+     243,   244,   245,   246,   247,   248,   249,   250,   251,   392,
+     393,   399,   418,   419,    58,   395,   160,   396,    51,    90,
+     421,    84,    61,   412,     2,     3,   413,   433,   434,   436,
+     426,   437,   447,   146,   439,   440,   450,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,   441,    19,    20,   442,    21,    22,    23,    24,
+     420,   424,   443,   446,   428,   431,   247,   248,   249,   250,
+     251,   346,   245,   246,   247,   248,   249,   250,   251,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,     3,   444,
+      34,    35,   445,   430,    36,   345,    37,   423,   353,    38,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,     0,    19,    20,     0,    21,
+      22,    23,    24,     0,    42,    43,     0,     0,    42,    43,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+       0,     0,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,     0,    44,    34,    35,     0,    44,    36,     0,    37,
+       0,    45,    38,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,     0,    56,    42,    43,   244,   245,   246,
+     247,   248,   249,   250,   251,     0,    42,    43,    58,     0,
+      57,     0,    58,    90,     0,     0,    61,    59,     0,    60,
+      61,     0,   347,    44,     0,    42,    43,     0,    45,     0,
+      46,     0,    48,    49,    44,     0,    52,    53,    54,    55,
+       0,    56,    47,     0,     0,    50,    42,    43,     0,     0,
+       0,     0,     0,    44,     0,     0,     0,    57,     0,    58,
+      46,     0,    48,     0,    59,     0,    84,    61,    57,     0,
+      58,    42,    43,     0,    44,    59,     0,   101,    61,     0,
+       0,    46,     0,    48,    42,    43,     0,    57,     0,    58,
+       0,     0,     0,     0,    59,     0,     0,    61,     0,    44,
+      42,   438,     0,     0,    42,    43,     0,     0,    57,     0,
+      58,    51,    44,    42,    43,    90,     0,     0,    61,     0,
+      47,     0,     0,    50,    42,    43,     0,     0,    44,     0,
+      42,    43,    44,    57,     0,    58,     0,     0,     0,     0,
+      59,    44,    84,    61,     0,     0,    57,     0,    58,     0,
+      42,    43,    44,    59,     0,     0,    61,     0,    44,     0,
+     196,   158,    57,     0,    58,   158,    57,     0,    58,    90,
+      42,    43,    61,    90,     0,    57,    61,    58,    44,     0,
+       0,     0,    90,     0,     0,    61,    94,     0,    58,     0,
+       0,     0,    94,   187,    58,     0,    61,     0,    44,   307,
+       0,     0,    61,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    94,     0,    58,     0,     0,     0,     0,   310,
+       0,     0,    61,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    94,     0,    58,     0,     0,     0,     0,   414,
+       0,     0,    61
+};
+
+static const yytype_int16 yycheck[] =
+{
+       5,     6,     7,     8,     9,    10,    21,    95,   162,   167,
+     185,    94,    75,    18,    19,     9,    43,     8,    45,    43,
+      43,    45,    45,    96,    29,   162,    31,    32,    33,    76,
+      35,   168,    75,    41,     8,     9,     4,     5,    46,     4,
+       5,    37,    38,    39,    12,    13,    11,    12,    13,    76,
+      79,    12,    79,    79,    77,    79,    44,    22,    23,    47,
+      77,    41,    36,    74,    44,    33,    46,    47,    33,    43,
+      43,    45,    45,    75,    68,    48,    77,    42,    43,    77,
+      13,    14,    15,    16,    17,     5,    19,    78,    77,   162,
+      43,    44,    45,    13,    47,    60,    61,     6,    72,     8,
+       9,    77,    41,    77,   192,   193,    80,    46,    28,   114,
+      30,    31,    51,    52,   187,    54,    43,    44,    45,    84,
+      47,     8,     9,    76,    73,    74,    79,    95,    76,    77,
+      95,    18,    19,    76,    21,    10,    11,    12,    25,    26,
+      43,    76,    45,    19,    20,    32,    77,    34,    24,    77,
+      41,    79,    43,   236,    45,    46,    77,   162,   163,   164,
+     165,    76,     8,     9,   169,   170,   171,   172,    76,   174,
+     175,   176,   177,   178,    76,   180,   181,   182,   183,   184,
+      76,   114,   147,   148,   149,   150,    76,   152,   153,    11,
+      37,    38,    39,    40,   162,    76,    43,   162,    45,   167,
+       7,   162,   167,   378,   165,   166,   174,   168,   366,   174,
+      76,   365,   142,   143,   219,    76,    77,   222,   223,   224,
+     185,   226,    22,    23,   192,   193,    59,   192,   193,   197,
+      78,    76,   197,   166,   307,   111,    76,   310,    76,   115,
+     116,    76,   162,    77,   120,   121,    76,   167,    76,   214,
+     218,   216,    76,   218,   174,    76,    76,   225,    76,    76,
+     225,    76,   227,    76,   197,   198,   199,   200,   201,   202,
+     203,   204,    76,    76,    76,   162,    77,   197,    76,    76,
+     167,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    76,    76,    76,   382,   182,   129,   184,    76,    76,
+     220,   221,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    76,   242,   243,   244,    76,    76,   247,   248,   249,
+     250,   251,    76,    76,    76,     8,     9,   214,    76,    76,
+     217,    76,   219,   220,     8,     9,     8,     9,    76,    76,
+     173,   414,    76,    76,    76,   178,     7,   180,   181,   182,
+     183,    68,    78,    36,    78,    78,    78,    78,    41,     6,
+      76,   194,    36,    46,    36,   370,   371,   372,   373,   374,
+     375,    76,   205,   388,   207,    49,    50,    37,    38,    39,
+      77,    76,    78,    43,   389,    45,    78,    70,   393,    72,
+       8,     9,    76,    76,    77,   228,    68,    80,    72,    76,
+      72,    76,   367,    77,    77,    77,    80,   240,    80,    76,
+      76,    76,    76,   378,   382,   376,   377,   382,    36,    76,
+      78,    76,    78,   384,    76,    76,   391,   392,   358,   359,
+      76,    76,    76,    76,   439,   440,    76,   442,   443,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    76,
+      76,    46,   385,   386,    72,    78,   421,    78,    48,    77,
+      79,    79,    80,    78,     0,     1,    78,    38,    78,    76,
+     390,     9,   437,   438,    76,    76,   441,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    76,    29,    30,    76,    32,    33,    34,    35,
+     387,   388,    76,   436,   391,   392,     8,     9,    10,    11,
+      12,    75,     6,     7,     8,     9,    10,    11,    12,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,     1,    78,
+      66,    67,    78,   392,    70,   229,    72,   388,   239,    75,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    -1,    29,    30,    -1,    32,
+      33,    34,    35,    -1,     8,     9,    -1,    -1,     8,     9,
+       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      -1,    -1,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    -1,    36,    66,    67,    -1,    36,    70,    -1,    72,
+      -1,    41,    75,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    -1,    54,     8,     9,     5,     6,     7,
+       8,     9,    10,    11,    12,    -1,     8,     9,    72,    -1,
+      70,    -1,    72,    77,    -1,    -1,    80,    77,    -1,    79,
+      80,    -1,    75,    36,    -1,     8,     9,    -1,    41,    -1,
+      43,    -1,    45,    46,    36,    -1,    49,    50,    51,    52,
+      -1,    54,    44,    -1,    -1,    47,     8,     9,    -1,    -1,
+      -1,    -1,    -1,    36,    -1,    -1,    -1,    70,    -1,    72,
+      43,    -1,    45,    -1,    77,    -1,    79,    80,    70,    -1,
+      72,     8,     9,    -1,    36,    77,    -1,    79,    80,    -1,
+      -1,    43,    -1,    45,     8,     9,    -1,    70,    -1,    72,
+      -1,    -1,    -1,    -1,    77,    -1,    -1,    80,    -1,    36,
+       8,     9,    -1,    -1,     8,     9,    -1,    -1,    70,    -1,
+      72,    48,    36,     8,     9,    77,    -1,    -1,    80,    -1,
+      44,    -1,    -1,    47,     8,     9,    -1,    -1,    36,    -1,
+       8,     9,    36,    70,    -1,    72,    -1,    -1,    -1,    -1,
+      77,    36,    79,    80,    -1,    -1,    70,    -1,    72,    -1,
+       8,     9,    36,    77,    -1,    -1,    80,    -1,    36,    -1,
+      68,    69,    70,    -1,    72,    69,    70,    -1,    72,    77,
+       8,     9,    80,    77,    -1,    70,    80,    72,    36,    -1,
+      -1,    -1,    77,    -1,    -1,    80,    70,    -1,    72,    -1,
+      -1,    -1,    70,    77,    72,    -1,    80,    -1,    36,    77,
+      -1,    -1,    80,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    70,    -1,    72,    -1,    -1,    -1,    -1,    77,
+      -1,    -1,    80,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    70,    -1,    72,    -1,    -1,    -1,    -1,    77,
+      -1,    -1,    80
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    82,     0,     1,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    29,
+      30,    32,    33,    34,    35,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    66,    67,    70,    72,    75,    83,
+      85,    75,     8,     9,    36,    41,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    54,    70,    72,    77,
+      79,    80,    87,    88,    89,    90,    91,    92,    93,    94,
+      96,    97,   100,   102,   103,   104,   105,   106,   110,    87,
+     104,   105,    87,    87,    79,    87,   102,    87,   102,    87,
+      77,    98,   110,    46,    70,    76,    77,    86,    97,   105,
+     110,    79,    96,   101,   104,   105,    96,    96,    96,    96,
+      76,    87,   102,   107,    76,    87,    96,   102,   107,   107,
+     100,   102,   106,   110,   106,   107,   102,   102,    75,    77,
+     104,    87,   104,    87,   104,    87,   102,    87,   105,   102,
+      87,    73,    74,    74,    75,   110,   110,    77,    77,    77,
+      77,     6,     8,     9,   108,   103,   110,   111,    69,   105,
+     110,   110,    76,    76,    76,    76,    76,    76,    76,    76,
+      76,    76,    76,    77,    76,    76,    76,    76,    76,   110,
+      76,    76,    76,    76,    76,    76,   108,    77,    86,   105,
+     110,    88,    76,    76,    77,     9,    68,    76,    76,    76,
+      76,    76,    76,    76,    76,    76,   107,    76,    87,    96,
+     107,   107,   107,   107,    76,    77,    11,    76,    76,    76,
+      76,    76,    76,    76,    76,    76,    76,    76,    76,    84,
+     111,   111,   110,   110,   110,   110,     7,   110,   110,    77,
+       8,    78,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    78,    87,    88,    90,    93,    97,   102,   104,
+     105,    87,    87,    87,    97,    96,    97,    94,   102,   104,
+     105,    93,    97,    87,    48,    87,    95,    87,    87,    37,
+      38,    39,   103,   109,    87,   104,   105,    87,    87,    87,
+      87,   103,    87,   103,    87,   103,    87,   102,   103,    87,
+     103,    87,   102,    98,   110,    88,    78,    77,    86,   105,
+      77,    86,   105,   110,    40,    68,    96,   104,   105,    96,
+      96,    96,    96,    96,    96,    96,   103,   103,   102,   110,
+     110,   102,   105,    87,   102,   102,   104,   104,    87,    87,
+      87,   105,    87,   110,   103,    83,    75,    75,    78,    78,
+      78,    78,   108,   109,   103,   111,   111,   111,     6,     7,
+     111,   111,   111,   111,   111,    76,    76,    77,    78,    78,
+      76,    76,    76,    76,    76,    76,    76,    76,    76,    78,
+      88,    88,    76,    78,    76,    76,    76,    76,    76,    76,
+      76,    76,    76,    76,    77,    78,    78,   111,   111,    46,
+      90,    94,   110,    87,    87,    87,    87,    87,    87,    97,
+      97,    98,    78,    78,    77,    86,   105,    97,    96,    96,
+     102,    79,   100,   101,   102,    87,   104,    99,   102,   110,
+      99,   102,    87,    38,    78,    88,    76,     9,     9,    76,
+      76,    76,    76,    76,    78,    78,    96,   110,    87,    87,
+     110,    87,    87
+};
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                (-2)
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrorlab
+
+
+/* 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.  */
+
+#define YYFAIL         goto yyerrlab
+
+#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                                                         \
+    {                                                          \
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;                                                 \
+    }                                                          \
+while (YYID (0))
+
+
+#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.  */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
+do {                                                                     \
+  if (yydebug)                                                           \
+    {                                                                    \
+      YYFPRINTF (stderr, "%s ", Title);                                          \
+      yy_symbol_print (stderr,                                           \
+                 Type, Value); \
+      YYFPRINTF (stderr, "\n");                                                  \
+    }                                                                    \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+       break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                           \
+do {                                                           \
+  if (yydebug)                                                 \
+    yy_stack_print ((Bottom), (Top));                          \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+    YYSTYPE *yyvsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+            yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+                      &(yyvsp[(yyi + 1) - (yynrhs)])
+                                      );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+       switch (*++yyp)
+         {
+         case '\'':
+         case ',':
+           goto do_not_strip_quotes;
+
+         case '\\':
+           if (*++yyp != '\\')
+             goto do_not_strip_quotes;
+           /* Fall through.  */
+         default:
+           if (yyres)
+             yyres[yyn] = *yyp;
+           yyn++;
+           break;
+
+         case '"':
+           if (yyres)
+             yyres[yyn] = '\0';
+           return yyn;
+         }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# 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];
+
+  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;
+         }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+       return YYSIZE_MAXIMUM;
+
+      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 */
+\f
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+#endif
+{
+  YYUSE (yyvaluep);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+       break;
+    }
+}
+\f
+
+/* 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 look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* 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];
+  char *yymsg = yymsgbuf;
+  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;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  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;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack.  Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       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
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow (YY_("memory exhausted"),
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+
+                   &yystacksize);
+
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+       goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       yytype_int16 *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyexhaustedlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      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 look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 4:
+#line 71 "a.y"
+    {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
+               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
+                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname);
+               (yyvsp[(1) - (2)].sym)->type = LLAB;
+               (yyvsp[(1) - (2)].sym)->value = pc;
+       }
+    break;
+
+  case 6:
+#line 80 "a.y"
+    {
+               (yyvsp[(1) - (4)].sym)->type = LVAR;
+               (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 7:
+#line 85 "a.y"
+    {
+               if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval))
+                       yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name);
+               (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 8:
+#line 91 "a.y"
+    {
+               nosched = (yyvsp[(1) - (2)].lval);
+       }
+    break;
+
+  case 12:
+#line 103 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 13:
+#line 107 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 14:
+#line 111 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 15:
+#line 115 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 16:
+#line 119 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 17:
+#line 123 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 18:
+#line 130 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 19:
+#line 134 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 20:
+#line 138 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 21:
+#line 142 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 22:
+#line 146 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 23:
+#line 150 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 24:
+#line 157 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 25:
+#line 161 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 26:
+#line 165 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 27:
+#line 169 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 28:
+#line 176 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 29:
+#line 180 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 30:
+#line 187 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 31:
+#line 191 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 32:
+#line 195 "a.y"
+    {
+               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 33:
+#line 199 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 34:
+#line 203 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 35:
+#line 207 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+       }
+    break;
+
+  case 36:
+#line 214 "a.y"
+    {
+               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 37:
+#line 218 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 38:
+#line 222 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 39:
+#line 232 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 40:
+#line 236 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 41:
+#line 240 "a.y"
+    {
+               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 42:
+#line 244 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 43:
+#line 248 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 44:
+#line 252 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 45:
+#line 256 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 46:
+#line 260 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 47:
+#line 264 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 48:
+#line 268 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 49:
+#line 272 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 50:
+#line 276 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 51:
+#line 280 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &(yyvsp[(2) - (2)].addr));
+       }
+    break;
+
+  case 52:
+#line 287 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 53:
+#line 294 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 54:
+#line 298 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 55:
+#line 305 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 56:
+#line 309 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 57:
+#line 317 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 58:
+#line 321 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 59:
+#line 325 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 60:
+#line 329 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 61:
+#line 333 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 62:
+#line 337 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 63:
+#line 341 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 64:
+#line 345 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 65:
+#line 354 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
+       }
+    break;
+
+  case 66:
+#line 358 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
+       }
+    break;
+
+  case 67:
+#line 362 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &nullgen, NREG, &(yyvsp[(3) - (4)].addr));
+       }
+    break;
+
+  case 68:
+#line 366 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+       }
+    break;
+
+  case 69:
+#line 370 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+       }
+    break;
+
+  case 70:
+#line 374 "a.y"
+    {
+               outcode((yyvsp[(1) - (5)].lval), &nullgen, NREG, &(yyvsp[(4) - (5)].addr));
+       }
+    break;
+
+  case 71:
+#line 378 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 72:
+#line 382 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 73:
+#line 386 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(5) - (6)].addr));
+       }
+    break;
+
+  case 74:
+#line 390 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 75:
+#line 394 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 76:
+#line 398 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &nullgen, (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr));
+       }
+    break;
+
+  case 77:
+#line 402 "a.y"
+    {
+               Addr g;
+               g = nullgen;
+               g.type = D_CONST;
+               g.offset = (yyvsp[(2) - (6)].lval);
+               outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 78:
+#line 410 "a.y"
+    {
+               Addr g;
+               g = nullgen;
+               g.type = D_CONST;
+               g.offset = (yyvsp[(2) - (6)].lval);
+               outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 79:
+#line 418 "a.y"
+    {
+               Addr g;
+               g = nullgen;
+               g.type = D_CONST;
+               g.offset = (yyvsp[(2) - (8)].lval);
+               outcode((yyvsp[(1) - (8)].lval), &g, (yyvsp[(4) - (8)].lval), &(yyvsp[(7) - (8)].addr));
+       }
+    break;
+
+  case 80:
+#line 429 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+       }
+    break;
+
+  case 81:
+#line 433 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+       }
+    break;
+
+  case 82:
+#line 437 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 83:
+#line 441 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+       }
+    break;
+
+  case 84:
+#line 448 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 85:
+#line 452 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 86:
+#line 456 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 87:
+#line 460 "a.y"
+    {
+               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+       }
+    break;
+
+  case 88:
+#line 464 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 89:
+#line 468 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+       }
+    break;
+
+  case 90:
+#line 475 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 91:
+#line 479 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 92:
+#line 483 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+       }
+    break;
+
+  case 93:
+#line 487 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+       }
+    break;
+
+  case 94:
+#line 494 "a.y"
+    {
+               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+       }
+    break;
+
+  case 95:
+#line 498 "a.y"
+    {
+               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+       }
+    break;
+
+  case 96:
+#line 502 "a.y"
+    {
+               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+       }
+    break;
+
+  case 97:
+#line 506 "a.y"
+    {
+               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
+       }
+    break;
+
+  case 98:
+#line 513 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 99:
+#line 517 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 100:
+#line 525 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 101:
+#line 529 "a.y"
+    {
+               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 102:
+#line 533 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 103:
+#line 537 "a.y"
+    {
+               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 104:
+#line 541 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 105:
+#line 545 "a.y"
+    {
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 106:
+#line 549 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 107:
+#line 556 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+       }
+    break;
+
+  case 108:
+#line 560 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 109:
+#line 564 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 110:
+#line 568 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+       }
+    break;
+
+  case 111:
+#line 572 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+       }
+    break;
+
+  case 112:
+#line 576 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 113:
+#line 583 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 114:
+#line 587 "a.y"
+    {
+               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+       }
+    break;
+
+  case 115:
+#line 594 "a.y"
+    {
+               if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST)
+                       yyerror("arguments to PCDATA must be integer constants");
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 116:
+#line 603 "a.y"
+    {
+               if((yyvsp[(2) - (4)].addr).type != D_CONST)
+                       yyerror("index for FUNCDATA must be integer constant");
+               if((yyvsp[(4) - (4)].addr).type != D_EXTERN && (yyvsp[(4) - (4)].addr).type != D_STATIC && (yyvsp[(4) - (4)].addr).type != D_OREG)
+                       yyerror("value for FUNCDATA must be symbol reference");
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 117:
+#line 614 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+       }
+    break;
+
+  case 118:
+#line 621 "a.y"
+    {
+               settext((yyvsp[(2) - (4)].addr).sym);
+               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+       }
+    break;
+
+  case 119:
+#line 626 "a.y"
+    {
+               settext((yyvsp[(2) - (6)].addr).sym);
+               (yyvsp[(6) - (6)].addr).offset &= 0xffffffffull;
+               (yyvsp[(6) - (6)].addr).offset |= (vlong)ArgsSizeUnknown << 32;
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 120:
+#line 633 "a.y"
+    {
+               settext((yyvsp[(2) - (8)].addr).sym);
+               (yyvsp[(6) - (8)].addr).offset &= 0xffffffffull;
+               (yyvsp[(6) - (8)].addr).offset |= ((yyvsp[(8) - (8)].lval) & 0xffffffffull) << 32;
+               outcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr));
+       }
+    break;
+
+  case 121:
+#line 643 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 122:
+#line 647 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 123:
+#line 651 "a.y"
+    {
+               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+       }
+    break;
+
+  case 124:
+#line 658 "a.y"
+    {
+               outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+       }
+    break;
+
+  case 125:
+#line 664 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_BRANCH;
+               (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
+       }
+    break;
+
+  case 126:
+#line 670 "a.y"
+    {
+               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
+               (yyval.addr) = nullgen;
+               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
+                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
+               (yyval.addr).type = D_BRANCH;
+               (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 127:
+#line 681 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_REG;
+               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 130:
+#line 693 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_SPR;
+               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 131:
+#line 701 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_CREG;
+               (yyval.addr).reg = NREG;        /* whole register */
+       }
+    break;
+
+  case 132:
+#line 709 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_SPR;
+               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 133:
+#line 717 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_MSR;
+       }
+    break;
+
+  case 134:
+#line 724 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_SPR;
+               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 135:
+#line 730 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = (yyvsp[(1) - (4)].lval);
+               (yyval.addr).offset = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 137:
+#line 739 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_FPSCR;
+               (yyval.addr).reg = NREG;
+       }
+    break;
+
+  case 138:
+#line 747 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_FPSCR;
+               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 139:
+#line 755 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_FREG;
+               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 140:
+#line 761 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_FREG;
+               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 141:
+#line 769 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_CREG;
+               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 142:
+#line 775 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_CREG;
+               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 143:
+#line 783 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_REG;
+               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+       }
+    break;
+
+  case 144:
+#line 791 "a.y"
+    {
+               int mb, me;
+               uint32 v;
+
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_CONST;
+               mb = (yyvsp[(1) - (3)].lval);
+               me = (yyvsp[(3) - (3)].lval);
+               if(mb < 0 || mb > 31 || me < 0 || me > 31){
+                       yyerror("illegal mask start/end value(s)");
+                       mb = me = 0;
+               }
+               if(mb <= me)
+                       v = ((uint32)~0L>>mb) & (~0L<<(31-me));
+               else
+                       v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
+               (yyval.addr).offset = v;
+       }
+    break;
+
+  case 145:
+#line 812 "a.y"
+    {
+               (yyval.addr) = (yyvsp[(2) - (2)].addr);
+               (yyval.addr).type = D_CONST;
+       }
+    break;
+
+  case 146:
+#line 817 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_SCONST;
+               memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
+       }
+    break;
+
+  case 147:
+#line 825 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_FCONST;
+               (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
+       }
+    break;
+
+  case 148:
+#line 831 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_FCONST;
+               (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
+       }
+    break;
+
+  case 149:
+#line 838 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_CONST;
+               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 151:
+#line 847 "a.y"
+    {
+               if((yyval.lval) < 0 || (yyval.lval) >= NREG)
+                       print("register value out of range\n");
+               (yyval.lval) = (yyvsp[(3) - (4)].lval);
+       }
+    break;
+
+  case 152:
+#line 855 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_OREG;
+               (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
+               (yyval.addr).offset = 0;
+       }
+    break;
+
+  case 153:
+#line 862 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_OREG;
+               (yyval.addr).reg = (yyvsp[(2) - (5)].lval);
+               (yyval.addr).scale = (yyvsp[(4) - (5)].lval);
+               (yyval.addr).offset = 0;
+       }
+    break;
+
+  case 155:
+#line 873 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_OREG;
+               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
+       }
+    break;
+
+  case 156:
+#line 882 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_OREG;
+               (yyval.addr).name = (yyvsp[(3) - (4)].lval);
+               (yyval.addr).sym = nil;
+               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
+       }
+    break;
+
+  case 157:
+#line 890 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_OREG;
+               (yyval.addr).name = (yyvsp[(4) - (5)].lval);
+               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
+               (yyval.addr).offset = (yyvsp[(2) - (5)].lval);
+       }
+    break;
+
+  case 158:
+#line 898 "a.y"
+    {
+               (yyval.addr) = nullgen;
+               (yyval.addr).type = D_OREG;
+               (yyval.addr).name = D_STATIC;
+               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 0);
+               (yyval.addr).offset = (yyvsp[(4) - (7)].lval);
+       }
+    break;
+
+  case 161:
+#line 910 "a.y"
+    {
+               (yyval.lval) = 0;
+       }
+    break;
+
+  case 162:
+#line 914 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 163:
+#line 918 "a.y"
+    {
+               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 168:
+#line 930 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
+       }
+    break;
+
+  case 169:
+#line 934 "a.y"
+    {
+               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 170:
+#line 938 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 171:
+#line 942 "a.y"
+    {
+               (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
+       }
+    break;
+
+  case 172:
+#line 946 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(2) - (3)].lval);
+       }
+    break;
+
+  case 174:
+#line 953 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 175:
+#line 957 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 176:
+#line 961 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 177:
+#line 965 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 178:
+#line 969 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 179:
+#line 973 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
+       }
+    break;
+
+  case 180:
+#line 977 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
+       }
+    break;
+
+  case 181:
+#line 981 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 182:
+#line 985 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+  case 183:
+#line 989 "a.y"
+    {
+               (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
+       }
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 3185 "y.tab.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++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.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+       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;
+         }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+        error, discard it.  */
+
+      if (yychar <= YYEOF)
+       {
+         /* Return failure if at end of input.  */
+         if (yychar == YYEOF)
+           YYABORT;
+       }
+      else
+       {
+         yydestruct ("Error: discarding",
+                     yytoken, &yylval);
+         yychar = YYEMPTY;
+       }
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+
+      yydestruct ("Error: popping",
+                 yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  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);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                 yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
diff --git a/src/cmd/9a/y.tab.h b/src/cmd/9a/y.tab.h
new file mode 100644 (file)
index 0000000..e6b93a2
--- /dev/null
@@ -0,0 +1,188 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* 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 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, 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
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   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
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     LMOVW = 258,
+     LMOVB = 259,
+     LABS = 260,
+     LLOGW = 261,
+     LSHW = 262,
+     LADDW = 263,
+     LCMP = 264,
+     LCROP = 265,
+     LBRA = 266,
+     LFMOV = 267,
+     LFCONV = 268,
+     LFCMP = 269,
+     LFADD = 270,
+     LFMA = 271,
+     LTRAP = 272,
+     LXORW = 273,
+     LNOP = 274,
+     LEND = 275,
+     LRETT = 276,
+     LWORD = 277,
+     LTEXT = 278,
+     LDATA = 279,
+     LRETRN = 280,
+     LCONST = 281,
+     LSP = 282,
+     LSB = 283,
+     LFP = 284,
+     LPC = 285,
+     LCREG = 286,
+     LFLUSH = 287,
+     LREG = 288,
+     LFREG = 289,
+     LR = 290,
+     LCR = 291,
+     LF = 292,
+     LFPSCR = 293,
+     LLR = 294,
+     LCTR = 295,
+     LSPR = 296,
+     LSPREG = 297,
+     LSEG = 298,
+     LMSR = 299,
+     LPCDAT = 300,
+     LFUNCDAT = 301,
+     LSCHED = 302,
+     LXLD = 303,
+     LXST = 304,
+     LXOP = 305,
+     LXMV = 306,
+     LRLWM = 307,
+     LMOVMW = 308,
+     LMOVEM = 309,
+     LMOVFL = 310,
+     LMTFSB = 311,
+     LMA = 312,
+     LFCONST = 313,
+     LSCONST = 314,
+     LNAME = 315,
+     LLAB = 316,
+     LVAR = 317
+   };
+#endif
+/* Tokens.  */
+#define LMOVW 258
+#define LMOVB 259
+#define LABS 260
+#define LLOGW 261
+#define LSHW 262
+#define LADDW 263
+#define LCMP 264
+#define LCROP 265
+#define LBRA 266
+#define LFMOV 267
+#define LFCONV 268
+#define LFCMP 269
+#define LFADD 270
+#define LFMA 271
+#define LTRAP 272
+#define LXORW 273
+#define LNOP 274
+#define LEND 275
+#define LRETT 276
+#define LWORD 277
+#define LTEXT 278
+#define LDATA 279
+#define LRETRN 280
+#define LCONST 281
+#define LSP 282
+#define LSB 283
+#define LFP 284
+#define LPC 285
+#define LCREG 286
+#define LFLUSH 287
+#define LREG 288
+#define LFREG 289
+#define LR 290
+#define LCR 291
+#define LF 292
+#define LFPSCR 293
+#define LLR 294
+#define LCTR 295
+#define LSPR 296
+#define LSPREG 297
+#define LSEG 298
+#define LMSR 299
+#define LPCDAT 300
+#define LFUNCDAT 301
+#define LSCHED 302
+#define LXLD 303
+#define LXST 304
+#define LXOP 305
+#define LXMV 306
+#define LRLWM 307
+#define LMOVMW 308
+#define LMOVEM 309
+#define LMOVFL 310
+#define LMTFSB 311
+#define LMA 312
+#define LFCONST 313
+#define LSCONST 314
+#define LNAME 315
+#define LLAB 316
+#define LVAR 317
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 38 "a.y"
+{
+       Sym     *sym;
+       vlong   lval;
+       double  dval;
+       char    sval[8];
+       Addr    addr;
+}
+/* Line 1529 of yacc.c.  */
+#line 181 "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/9g/cgen.c b/src/cmd/9g/cgen.c
new file mode 100644 (file)
index 0000000..e389360
--- /dev/null
@@ -0,0 +1,1763 @@
+// 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 <u.h>
+#include <libc.h>
+#include "gg.h"
+
+/*
+ * generate:
+ *     res = n;
+ * simplifies and calls gmove.
+ */
+void
+cgen(Node *n, Node *res)
+{
+       Node *nl, *nr, *r;
+       Node n1, n2;
+       int a, f;
+       Prog *p1, *p2, *p3;
+       Addr addr;
+
+//print("cgen %N(%d) -> %N(%d)\n", n, n->addable, res, res->addable);
+       if(debug['g']) {
+               dump("\ncgen-n", n);
+               dump("cgen-res", res);
+       }
+       if(n == N || n->type == T)
+               goto ret;
+
+       if(res == N || res->type == T)
+               fatal("cgen: res nil");
+
+       while(n->op == OCONVNOP)
+               n = n->left;
+
+       switch(n->op) {
+       case OSLICE:
+       case OSLICEARR:
+       case OSLICESTR:
+       case OSLICE3:
+       case OSLICE3ARR:
+               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)
+                       fatal("cgen: this is going to misscompile");
+               if(res->ullman >= UINF) {
+                       tempname(&n1, n->type);
+                       cgen(n, &n1);
+                       cgen(&n1, res);
+                       goto ret;
+               }
+       }
+
+       if(isfat(n->type)) {
+               if(n->type->width < 0)
+                       fatal("forgot to compute width for %T", n->type);
+               sgen(n, res, n->type->width);
+               goto ret;
+       }
+
+       if(!res->addable) {
+               if(n->ullman > res->ullman) {
+                       regalloc(&n1, n->type, res);
+                       cgen(n, &n1);
+                       if(n1.ullman > res->ullman) {
+                               dump("n1", &n1);
+                               dump("res", res);
+                               fatal("loop in cgen");
+                       }
+                       cgen(&n1, res);
+                       regfree(&n1);
+                       goto ret;
+               }
+
+               if(res->ullman >= UINF)
+                       goto gen;
+
+               if(complexop(n, res)) {
+                       complexgen(n, res);
+                       goto ret;
+               }
+
+               f = 1;  // gen thru register
+               switch(n->op) {
+               case OLITERAL:
+                       if(smallintconst(n))
+                               f = 0;
+                       break;
+               case OREGISTER:
+                       f = 0;
+                       break;
+               }
+
+               if(!iscomplex[n->type->etype]) {
+                       a = optoas(OAS, res->type);
+                       if(sudoaddable(a, res, &addr)) {
+                               if(f) {
+                                       regalloc(&n2, res->type, N);
+                                       cgen(n, &n2);
+                                       p1 = gins(a, &n2, N);
+                                       regfree(&n2);
+                               } else
+                                       p1 = gins(a, n, N);
+                               p1->to = addr;
+                               if(debug['g'])
+                                       print("%P [ignore previous line]\n", p1);
+                               sudoclean();
+                               goto ret;
+                       }
+               }
+
+       gen:
+               igen(res, &n1, N);
+               cgen(n, &n1);
+               regfree(&n1);
+               goto ret;
+       }
+
+       // update addressability for string, slice
+       // can't do in walk because n->left->addable
+       // changes if n->left is an escaping local variable.
+       switch(n->op) {
+       case OSPTR:
+       case OLEN:
+               if(isslice(n->left->type) || istype(n->left->type, TSTRING))
+                       n->addable = n->left->addable;
+               break;
+       case OCAP:
+               if(isslice(n->left->type))
+                       n->addable = n->left->addable;
+               break;
+       case OITAB:
+               n->addable = n->left->addable;
+               break;
+       }
+
+       if(complexop(n, res)) {
+               complexgen(n, res);
+               goto ret;
+       }
+
+       // if both are addressable, move
+       if(n->addable) {
+               if(n->op == OREGISTER || res->op == OREGISTER) {
+                       gmove(n, res);
+               } else {
+                       regalloc(&n1, n->type, N);
+                       gmove(n, &n1);
+                       cgen(&n1, res);
+                       regfree(&n1);
+               }
+               goto ret;
+       }
+
+       nl = n->left;
+       nr = n->right;
+
+       if(nl != N && nl->ullman >= UINF)
+       if(nr != N && nr->ullman >= UINF) {
+               tempname(&n1, nl->type);
+               cgen(nl, &n1);
+               n2 = *n;
+               n2.left = &n1;
+               cgen(&n2, res);
+               goto ret;
+       }
+
+       if(!iscomplex[n->type->etype]) {
+               a = optoas(OAS, n->type);
+               if(sudoaddable(a, n, &addr)) {
+                       if(res->op == OREGISTER) {
+                               p1 = gins(a, N, res);
+                               p1->from = addr;
+                       } else {
+                               regalloc(&n2, n->type, N);
+                               p1 = gins(a, N, &n2);
+                               p1->from = addr;
+                               gins(a, &n2, res);
+                               regfree(&n2);
+                       }
+                       sudoclean();
+                       goto ret;
+               }
+       }
+
+       // TODO(minux): we shouldn't reverse FP comparisons, but then we need to synthesize
+       // OGE, OLE, and ONE ourselves.
+       // if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) goto flt;
+
+       switch(n->op) {
+       default:
+               dump("cgen", n);
+               fatal("cgen: unknown op %+hN", n);
+               break;
+
+       // these call bgen to get a bool value
+       case OOROR:
+       case OANDAND:
+       case OEQ:
+       case ONE:
+       case OLT:
+       case OLE:
+       case OGE:
+       case OGT:
+       case ONOT:
+               p1 = gbranch(ABR, T, 0);
+               p2 = pc;
+               gmove(nodbool(1), res);
+               p3 = gbranch(ABR, T, 0);
+               patch(p1, pc);
+               bgen(n, 1, 0, p2);
+               gmove(nodbool(0), res);
+               patch(p3, pc);
+               goto ret;
+
+       case OPLUS:
+               cgen(nl, res);
+               goto ret;
+
+       // unary
+       case OCOM:
+               a = optoas(OXOR, nl->type);
+               regalloc(&n1, nl->type, N);
+               cgen(nl, &n1);
+               nodconst(&n2, nl->type, -1);
+               gins(a, &n2, &n1);
+               gmove(&n1, res);
+               regfree(&n1);
+               goto ret;
+
+       case OMINUS:
+               if(isfloat[nl->type->etype]) {
+                       nr = nodintconst(-1);
+                       convlit(&nr, n->type);
+                       a = optoas(OMUL, nl->type);
+                       goto sbop;
+               }
+               a = optoas(n->op, nl->type);
+               goto uop;
+
+       // symmetric binary
+       case OAND:
+       case OOR:
+       case OXOR:
+       case OADD:
+       case OMUL:
+               a = optoas(n->op, nl->type);
+               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);
+
+               // if we do the conversion n1 -> n2 here
+               // reusing the register, then gmove won't
+               // have to allocate its own register.
+               gmove(&n1, &n2);
+               gmove(&n2, res);
+               regfree(&n2);
+               regfree(&n1);
+               break;
+
+       case ODOT:
+       case ODOTPTR:
+       case OINDEX:
+       case OIND:
+       case ONAME:     // PHEAP or PPARAMREF var
+               igen(n, &n1, res);
+               gmove(&n1, res);
+               regfree(&n1);
+               break;
+       
+       case OITAB:
+               // interface table is first word of interface value
+               igen(nl, &n1, res);
+               n1.type = n->type;
+               gmove(&n1, res);
+               regfree(&n1);
+               break;
+
+       case OSPTR:
+               // pointer is the first word of string or slice.
+               if(isconst(nl, CTSTR)) {
+                       regalloc(&n1, types[tptr], res);
+                       p1 = gins(AMOVD, N, &n1);
+                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
+                       gmove(&n1, res);
+                       regfree(&n1);
+                       break;
+               }
+               igen(nl, &n1, res);
+               n1.type = n->type;
+               gmove(&n1, res);
+               regfree(&n1);
+               break;
+
+       case OLEN:
+               if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
+                       // 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, 0);
+
+                       n2 = n1;
+                       n2.op = OINDREG;
+                       n2.type = types[simtype[TINT]];
+                       gmove(&n2, &n1);
+
+                       patch(p1, pc);
+
+                       gmove(&n1, res);
+                       regfree(&n1);
+                       break;
+               }
+               if(istype(nl->type, TSTRING) || isslice(nl->type)) {
+                       // both slice and string have len one pointer into the struct.
+                       // a zero pointer means zero length
+                       igen(nl, &n1, res);
+                       n1.type = types[simtype[TUINT]];
+                       n1.xoffset += Array_nel;
+                       gmove(&n1, res);
+                       regfree(&n1);
+                       break;
+               }
+               fatal("cgen: OLEN: unknown type %lT", nl->type);
+               break;
+
+       case OCAP:
+               if(istype(nl->type, TCHAN)) {
+                       // 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, 0);
+
+                       n2 = n1;
+                       n2.op = OINDREG;
+                       n2.xoffset = widthint;
+                       n2.type = types[simtype[TINT]];
+                       gmove(&n2, &n1);
+
+                       patch(p1, pc);
+
+                       gmove(&n1, res);
+                       regfree(&n1);
+                       break;
+               }
+               if(isslice(nl->type)) {
+                       igen(nl, &n1, res);
+                       n1.type = types[simtype[TUINT]];
+                       n1.xoffset += Array_cap;
+                       gmove(&n1, res);
+                       regfree(&n1);
+                       break;
+               }
+               fatal("cgen: OCAP: unknown type %lT", nl->type);
+               break;
+
+       case OADDR:
+               if(n->bounded) // let race detector avoid nil checks
+                       disable_checknil++;
+               agen(nl, res);
+               if(n->bounded)
+                       disable_checknil--;
+               break;
+
+       case OCALLMETH:
+               cgen_callmeth(n, 0);
+               cgen_callret(n, res);
+               break;
+
+       case OCALLINTER:
+               cgen_callinter(n, res, 0);
+               cgen_callret(n, res);
+               break;
+
+       case OCALLFUNC:
+               cgen_call(n, 0);
+               cgen_callret(n, res);
+               break;
+
+       case OMOD:
+       case ODIV:
+               if(isfloat[n->type->etype]) {
+                       a = optoas(n->op, nl->type);
+                       goto abop;
+               }
+
+               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:
+       case OLROT:
+               cgen_shift(n->op, n->bounded, nl, nr, res);
+               break;
+       }
+       goto ret;
+
+sbop:  // symmetric binary
+       /*
+        * 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;
+       }
+
+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;
+                       gmove(&n1, res);
+                       sudoclean();
+                       regfree(&n1);
+                       goto ret;
+               }
+        *
+        */
+               // TODO(minux): enable using constants directly in certain instructions.
+               //if(smallintconst(nr))
+               //      n2 = *nr;
+               //else {
+                       regalloc(&n2, nr->type, N);
+                       cgen(nr, &n2);
+               //}
+       } else {
+               //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);
+       // Normalize result for types smaller than word.
+       if(n->type->width < widthreg) {
+               switch(n->op) {
+               case OADD:
+               case OSUB:
+               case OMUL:
+               case OLSH:
+                       gins(optoas(OAS, n->type), &n1, &n1);
+                       break;
+               }
+       }
+       gmove(&n1, res);
+       regfree(&n1);
+       if(n2.op != OLITERAL)
+               regfree(&n2);
+       goto ret;
+
+uop:   // unary
+       regalloc(&n1, nl->type, res);
+       cgen(nl, &n1);
+       gins(a, N, &n1);
+       gmove(&n1, res);
+       regfree(&n1);
+       goto ret;
+
+ret:
+       ;
+}
+
+/*
+ * allocate a register (reusing res if possible) and generate
+ *  a = 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, 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 (reusing res if possible) and generate
+ * a = &n
+ * The caller must call regfree(a).
+ * The generated code checks that the result is not nil.
+ */
+void
+agenr(Node *n, Node *a, Node *res)
+{
+       Node *nl, *nr;
+       Node n1, n2, n3, n4, tmp;
+       Prog *p1, *p2;
+       uint32 w;
+       uint64 v;
+
+       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);
+               cgen_checknil(a);
+               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[TINT64]);
+                       if(!isconst(nl, CTSTR))
+                               agenr(nl, &n3, res);
+                       if(!isconst(nr, CTINT)) {
+                               cgen(nr, &tmp);
+                               regalloc(&n1, tmp.type, N);
+                               gmove(&tmp, &n1);
+                       }
+               } else if(nl->addable) {
+                       if(!isconst(nr, CTINT)) {
+                               tempname(&tmp, types[TINT64]);
+                               cgen(nr, &tmp);
+                               regalloc(&n1, tmp.type, N);
+                               gmove(&tmp, &n1);
+                       }
+                       if(!isconst(nl, CTSTR)) {
+                               agenr(nl, &n3, res);
+                       }
+               } else {
+                       tempname(&tmp, types[TINT64]);
+                       cgen(nr, &tmp);
+                       nr = &tmp;
+                       if(!isconst(nl, CTSTR))
+                               agenr(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)
+               // w is width
+
+               // 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->bounded) {
+                                       n1 = n3;
+                                       n1.op = OINDREG;
+                                       n1.type = types[tptr];
+                                       n1.xoffset = Array_nel;
+                                       regalloc(&n4, n1.type, N);
+                                       gmove(&n1, &n4);
+                                       ginscon2(optoas(OCMP, types[TUINT64]), &n4, v);
+                                       regfree(&n4);
+                                       p1 = gbranch(optoas(OGT, types[TUINT64]), T, +1);
+                                       ginscall(panicindex, 0);
+                                       patch(p1, pc);
+                               }
+
+                               n1 = n3;
+                               n1.op = OINDREG;
+                               n1.type = types[tptr];
+                               n1.xoffset = Array_array;
+                               gmove(&n1, &n3);
+                       }
+
+                       if (v*w != 0) {
+                               ginscon(optoas(OADD, types[tptr]), v*w, &n3);
+                       }
+                       *a = n3;
+                       break;
+               }
+
+               regalloc(&n2, types[TINT64], &n1);                      // i
+               gmove(&n1, &n2);
+               regfree(&n1);
+
+               if(!debug['B'] && !n->bounded) {
+                       // check bounds
+                       if(isconst(nl, CTSTR)) {
+                               nodconst(&n4, types[TUINT64], 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;
+                               regalloc(&n4, types[TUINT64], N);
+                               gmove(&n1, &n4);
+                       } else {
+                               if(nl->type->bound < (1<<15)-1)
+                                       nodconst(&n4, types[TUINT64], nl->type->bound);
+                               else {
+                                       regalloc(&n4, types[TUINT64], N);
+                                       p1 = gins(AMOVD, N, &n4);
+                                       p1->from.type = D_CONST;
+                                       p1->from.offset = nl->type->bound;
+                               }
+                       }
+                       gins(optoas(OCMP, types[TUINT64]), &n2, &n4);
+                       if(n4.op == OREGISTER)
+                               regfree(&n4);
+                       p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
+                       if(p2)
+                               patch(p2, pc);
+                       ginscall(panicindex, 0);
+                       patch(p1, pc);
+               }
+               
+               if(isconst(nl, CTSTR)) {
+                       regalloc(&n3, types[tptr], res);
+                       p1 = gins(AMOVD, N, &n3);
+                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
+                       p1->from.type = D_CONST;
+               } else 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 already scaled */
+                       gins(optoas(OADD, types[tptr]), &n2, &n3);
+               } /* else if(w == 2 || w == 4 || w == 8) {
+                       // TODO(minux): scale using shift
+               } */ else {
+                       regalloc(&n4, types[TUINT64], N);
+                       nodconst(&n1, types[TUINT64], w);
+                       gmove(&n1, &n4);
+                       gins(optoas(OMUL, types[TUINT64]), &n4, &n2);
+                       gins(optoas(OADD, types[tptr]), &n2, &n3);
+                       regfree(&n4);
+               }
+
+               *a = n3;
+               regfree(&n2);
+               break;
+
+       default:
+               regalloc(a, types[tptr], res);
+               agen(n, a);
+               break;
+       }
+}
+
+static void
+ginsadd(int as, vlong off, Node *dst)
+{
+       Node n1;
+
+       regalloc(&n1, types[tptr], dst);
+       gmove(dst, &n1);
+       ginscon(as, off, &n1);
+       gmove(&n1, dst);
+       regfree(&n1);
+}
+
+/*
+ * generate:
+ *     res = &n;
+ * The generated code checks that the result is not nil.
+ */
+void
+agen(Node *n, Node *res)
+{
+       Node *nl, *nr;
+       Node n1, n2, n3;
+
+       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);
+               gvardef(&n1);
+               clearfat(&n1);
+               regalloc(&n2, types[tptr], res);
+               memset(&n3, 0, sizeof n3);
+               n3.op = OADDR;
+               n3.left = &n1;
+               gins(AMOVD, &n3, &n2);
+               gmove(&n2, res);
+               regfree(&n2);
+               goto ret;
+       }
+               
+       if(n->addable) {
+               memset(&n1, 0, sizeof n1);
+               n1.op = OADDR;
+               n1.left = n;
+               regalloc(&n2, types[tptr], res);
+               gins(AMOVD, &n1, &n2);
+               gmove(&n2, res);
+               regfree(&n2);
+               goto ret;
+       }
+
+       nl = n->left;
+       nr = n->right;
+       USED(nr);
+
+       switch(n->op) {
+       default:
+               fatal("agen: unknown op %+hN", n);
+               break;
+
+       case OCALLMETH:
+               // TODO(minux): 5g has this: Release res so that it is available for cgen_call.
+               // Pick it up again after the call for OCALLMETH and OCALLFUNC.
+               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:
+       case OSLICE3:
+       case OSLICE3ARR:
+               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) {
+                       ginsadd(optoas(OADD, types[tptr]), n->xoffset, res);
+               }
+               break;
+
+       case OIND:
+               cgen(nl, res);
+               cgen_checknil(res);
+               break;
+
+       case ODOT:
+               agen(nl, res);
+               if(n->xoffset != 0) {
+                       ginsadd(optoas(OADD, types[tptr]), n->xoffset, res);
+               }
+               break;
+
+       case ODOTPTR:
+               cgen(nl, res);
+               cgen_checknil(res);
+               if(n->xoffset != 0) {
+                       ginsadd(optoas(OADD, types[tptr]), n->xoffset, res);
+               }
+               break;
+       }
+
+ret:
+       ;
+}
+
+/*
+ * generate:
+ *     newreg = &n;
+ *     res = newreg
+ *
+ * on exit, a has been changed to be *newreg.
+ * caller must regfree(a).
+ * The generated code checks that the result is not *nil.
+ */
+void
+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)
+                       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_R0+REGSP)
+                       reg[n->val.u.reg]++;
+               *a = *n;
+               return;
+
+       case ODOT:
+               igen(n->left, a, res);
+               a->xoffset += n->xoffset;
+               a->type = n->type;
+               fixlargeoffset(a);
+               return;
+
+       case ODOTPTR:
+               cgenr(n->left, a, res);
+               cgen_checknil(a);
+               a->op = OINDREG;
+               a->xoffset += n->xoffset;
+               a->type = n->type;
+               fixlargeoffset(a);
+               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));
+               memset(a, 0, sizeof *a);
+               a->op = OINDREG;
+               a->val.u.reg = D_R0+REGSP;
+               a->addable = 1;
+               a->xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
+               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);
+                               cgen_checknil(&n1);
+                               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;
+                       fixlargeoffset(a);
+                       return;
+               }
+               break;
+       }
+
+       agenr(n, a, res);
+       a->op = OINDREG;
+       a->type = n->type;
+}
+
+/*
+ * generate:
+ *     if(n == true) goto to;
+ */
+void
+bgen(Node *n, int true, int likely, Prog *to)
+{
+       int et, a;
+       Node *nl, *nr, *l, *r;
+       Node n1, n2, tmp;
+       NodeList *ll;
+       Prog *p1, *p2;
+
+       if(debug['g']) {
+               dump("\nbgen", n);
+       }
+
+       if(n == N)
+               n = nodbool(1);
+
+       if(n->ninit != nil)
+               genlist(n->ninit);
+
+       if(n->type == T) {
+               convlit(&n, types[TBOOL]);
+               if(n->type == T)
+                       goto ret;
+       }
+
+       et = n->type->etype;
+       if(et != TBOOL) {
+               yyerror("cgen: bad type %T for %O", n->type, n->op);
+               patch(gins(AEND, N, N), to);
+               goto ret;
+       }
+       nr = N;
+
+       while(n->op == OCONVNOP) {
+               n = n->left;
+               if(n->ninit != nil)
+                       genlist(n->ninit);
+       }
+
+       switch(n->op) {
+       default:
+               regalloc(&n1, n->type, N);
+               cgen(n, &n1);
+               nodconst(&n2, n->type, 0);
+               gins(optoas(OCMP, n->type), &n1, &n2);
+               a = ABNE;
+               if(!true)
+                       a = ABEQ;
+               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(ABR, T, likely), to);
+               goto ret;
+
+       case OANDAND:
+               if(!true)
+                       goto caseor;
+
+       caseand:
+               p1 = gbranch(ABR, T, 0);
+               p2 = gbranch(ABR, T, 0);
+               patch(p1, pc);
+               bgen(n->left, !true, -likely, p2);
+               bgen(n->right, !true, -likely, p2);
+               p1 = gbranch(ABR, T, 0);
+               patch(p1, to);
+               patch(p2, pc);
+               goto ret;
+
+       case OOROR:
+               if(!true)
+                       goto caseand;
+
+       caseor:
+               bgen(n->left, true, likely, to);
+               bgen(n->right, true, likely, to);
+               goto ret;
+
+       case OEQ:
+       case ONE:
+       case OLT:
+       case OGT:
+       case OLE:
+       case OGE:
+               nr = n->right;
+               if(nr == N || nr->type == T)
+                       goto ret;
+
+       case ONOT:      // unary
+               nl = n->left;
+               if(nl == N || nl->type == T)
+                       goto ret;
+               break;
+       }
+
+       switch(n->op) {
+
+       case ONOT:
+               bgen(nl, !true, likely, to);
+               goto ret;
+
+       case OEQ:
+       case ONE:
+       case OLT:
+       case OGT:
+       case OLE:
+       case OGE:
+               a = n->op;
+               if(!true) {
+                       if(isfloat[nr->type->etype]) {
+                               // brcom is not valid on floats when NaN is involved.
+                               p1 = gbranch(ABR, T, 0);
+                               p2 = gbranch(ABR, T, 0);
+                               patch(p1, pc);
+                               ll = n->ninit;   // avoid re-genning ninit
+                               n->ninit = nil;
+                               bgen(n, 1, -likely, p2);
+                               n->ninit = ll;
+                               patch(gbranch(ABR, T, 0), to);
+                               patch(p2, pc);
+                               goto ret;
+                       }
+                       a = brcom(a);
+                       true = !true;
+               }
+
+               // make simplest on right
+               if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
+                       a = brrev(a);
+                       r = nl;
+                       nl = nr;
+                       nr = r;
+               }
+
+               if(isslice(nl->type)) {
+                       // front end should only leave cmp to literal nil
+                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
+                               yyerror("illegal slice comparison");
+                               break;
+                       }
+                       a = optoas(a, types[tptr]);
+                       igen(nl, &n1, N);
+                       n1.xoffset += Array_array;
+                       n1.type = types[tptr];
+                       nodconst(&tmp, types[tptr], 0);
+                       regalloc(&n2, types[tptr], &n1);
+                       gmove(&n1, &n2);
+                       gins(optoas(OCMP, types[tptr]), &n2, &tmp);
+                       regfree(&n2);
+                       patch(gbranch(a, types[tptr], likely), to);
+                       regfree(&n1);
+                       break;
+               }
+
+               if(isinter(nl->type)) {
+                       // 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]);
+                       igen(nl, &n1, N);
+                       n1.type = types[tptr];
+                       nodconst(&tmp, types[tptr], 0);
+                       regalloc(&n2, types[tptr], &n1);
+                       gmove(&n1, &n2);
+                       gins(optoas(OCMP, types[tptr]), &n2, &tmp);
+                       regfree(&n2);
+                       patch(gbranch(a, types[tptr], likely), to);
+                       regfree(&n1);
+                       break;
+               }
+               if(iscomplex[nl->type->etype]) {
+                       complexbool(a, nl, nr, true, likely, to);
+                       break;
+               }
+
+               if(nr->ullman >= UINF) {
+                       regalloc(&n1, nl->type, N);
+                       cgen(nl, &n1);
+
+                       tempname(&tmp, nl->type);
+                       gmove(&n1, &tmp);
+                       regfree(&n1);
+
+                       regalloc(&n2, nr->type, N);
+                       cgen(nr, &n2);
+
+                       regalloc(&n1, nl->type, N);
+                       cgen(&tmp, &n1);
+
+                       goto cmp;
+               }
+
+               regalloc(&n1, nl->type, N);
+               cgen(nl, &n1);
+
+               // TODO(minux): cmpi does accept 16-bit signed immediate as p->to.
+               // and cmpli accepts 16-bit unsigned immediate.
+               //if(smallintconst(nr)) {
+               //      gins(optoas(OCMP, nr->type), &n1, nr);
+               //      patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
+               //      regfree(&n1);
+               //      break;
+               //}
+
+               regalloc(&n2, nr->type, N);
+               cgen(nr, &n2);
+       cmp:
+               l = &n1;
+               r = &n2;
+               gins(optoas(OCMP, nr->type), l, r);
+               if(isfloat[nr->type->etype] && (a == OLE || a == OGE)) {
+                       // To get NaN right, must rewrite x <= y into separate x < y or x = y.
+                       switch(a) {
+                       case OLE:
+                               a = OLT;
+                               break;
+                       case OGE:
+                               a = OGT;
+                               break;
+                       }
+                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
+                       patch(gbranch(optoas(OEQ, nr->type), nr->type, likely), to);                    
+               } else {
+                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
+               }
+               regfree(&n1);
+               regfree(&n2);
+               break;
+       }
+       goto ret;
+
+ret:
+       ;
+}
+
+/*
+ * n is on stack, either local variable
+ * or return value from function call.
+ * return n's offset from SP.
+ */
+int64
+stkof(Node *n)
+{
+       Type *t;
+       Iter flist;
+       int64 off;
+
+       switch(n->op) {
+       case OINDREG:
+               return n->xoffset;
+
+       case ODOT:
+               t = n->left->type;
+               if(isptr[t->etype])
+                       break;
+               off = stkof(n->left);
+               if(off == -1000 || off == 1000)
+                       return off;
+               return off + n->xoffset;
+
+       case OINDEX:
+               t = n->left->type;
+               if(!isfixedarray(t))
+                       break;
+               off = stkof(n->left);
+               if(off == -1000 || off == 1000)
+                       return off;
+               if(isconst(n->right, CTINT))
+                       return off + t->type->width * mpgetfix(n->right->val.u.xval);
+               return 1000;
+               
+       case OCALLMETH:
+       case OCALLINTER:
+       case OCALLFUNC:
+               t = n->left->type;
+               if(isptr[t->etype])
+                       t = t->type;
+
+               t = structfirst(&flist, getoutarg(t));
+               if(t != T)
+                       return t->width + widthptr;     // +widthptr: correct for saved LR
+               break;
+       }
+
+       // botch - probably failing to recognize address
+       // arithmetic on the above. eg INDEX and DOT
+       return -1000;
+}
+
+/*
+ * block copy:
+ *     memmove(&ns, &n, w);
+ */
+void
+sgen(Node *n, Node *ns, int64 w)
+{
+       Node dst, src, tmp, nend;
+       int32 c, odst, osrc;
+       int dir, align, op;
+       Prog *p, *ploop;
+       NodeList *l;
+       Node *res = ns;
+
+       if(debug['g']) {
+               print("\nsgen w=%lld\n", w);
+               dump("r", n);
+               dump("res", ns);
+       }
+
+       if(n->ullman >= UINF && ns->ullman >= UINF)
+               fatal("sgen UINF");
+
+       if(w < 0)
+               fatal("sgen copy %lld", w);
+       
+       // If copying .args, that's all the results, so record definition sites
+       // for them for the liveness analysis.
+       if(ns->op == ONAME && strcmp(ns->sym->name, ".args") == 0)
+               for(l = curfn->dcl; l != nil; l = l->next)
+                       if(l->n->class == PPARAMOUT)
+                               gvardef(l->n);
+
+       // Avoid taking the address for simple enough types.
+       //if(componentgen(n, ns))
+       //      return;
+       
+       if(w == 0) {
+               // evaluate side effects only.
+               regalloc(&dst, types[tptr], N);
+               agen(res, &dst);
+               agen(n, &dst);
+               regfree(&dst);
+               return;
+       }
+
+       // determine alignment.
+       // want to avoid unaligned access, so have to use
+       // smaller operations for less aligned types.
+       // for example moving [4]byte must use 4 MOVB not 1 MOVW.
+       align = n->type->align;
+       switch(align) {
+       default:
+               fatal("sgen: invalid alignment %d for %T", align, n->type);
+       case 1:
+               op = AMOVBU;
+               break;
+       case 2:
+               op = AMOVHU;
+               break;
+       case 4:
+               op = AMOVWZU; // there is no lwau, only lwaux
+               break;
+       case 8:
+               op = AMOVDU;
+               break;
+       }
+       if(w%align)
+               fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type);
+       c = w / align;
+
+       // offset on the stack
+       osrc = stkof(n);
+       odst = stkof(res);
+       if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
+               // osrc and odst both on stack, and at least one is in
+               // an unknown position.  Could generate code to test
+               // for forward/backward copy, but instead just copy
+               // to a temporary location first.
+               tempname(&tmp, n->type);
+               sgen(n, &tmp, w);
+               sgen(&tmp, res, w);
+               return;
+       }
+       if(osrc%align != 0 || odst%align != 0)
+               fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
+
+       // if we are copying forward on the stack and
+       // the src and dst overlap, then reverse direction
+       dir = align;
+       if(osrc < odst && odst < osrc+w)
+               dir = -dir;
+
+       if(n->ullman >= res->ullman) {
+               agenr(n, &dst, res);    // temporarily use dst
+               regalloc(&src, types[tptr], N);
+               gins(AMOVD, &dst, &src);
+               if(res->op == ONAME)
+                       gvardef(res);
+               agen(res, &dst);
+       } else {
+               if(res->op == ONAME)
+                       gvardef(res);
+               agenr(res, &dst, res);
+               agenr(n, &src, N);
+       }
+
+       regalloc(&tmp, types[tptr], N);
+
+       // set up end marker
+       memset(&nend, 0, sizeof nend);
+
+       // move src and dest to the end of block if necessary
+       if(dir < 0) {
+               if(c >= 4) {
+                       regalloc(&nend, types[tptr], N);
+                       p = gins(AMOVD, &src, &nend);
+               }
+
+               p = gins(AADD, N, &src);
+               p->from.type = D_CONST;
+               p->from.offset = w;
+
+               p = gins(AADD, N, &dst);
+               p->from.type = D_CONST;
+               p->from.offset = w;
+       } else {
+               p = gins(AADD, N, &src);
+               p->from.type = D_CONST;
+               p->from.offset = -dir;
+
+               p = gins(AADD, N, &dst);
+               p->from.type = D_CONST;
+               p->from.offset = -dir;
+
+               if(c >= 4) {
+                       regalloc(&nend, types[tptr], N);
+                       p = gins(AMOVD, &src, &nend);
+                       p->from.type = D_CONST;
+                       p->from.offset = w;
+               }
+       }
+
+
+       // move
+       // TODO: enable duffcopy for larger copies.
+       if(c >= 4) {
+               p = gins(op, &src, &tmp);
+               p->from.type = D_OREG;
+               p->from.offset = dir;
+               ploop = p;
+
+               p = gins(op, &tmp, &dst);
+               p->to.type = D_OREG;
+               p->to.offset = dir;
+
+               p = gins(ACMP, &src, &nend);
+
+               patch(gbranch(ABNE, T, 0), ploop);
+               regfree(&nend);
+       } else {
+               while(c-- > 0) {
+                       p = gins(op, &src, &tmp);
+                       p->from.type = D_OREG;
+                       p->from.offset = dir;
+       
+                       p = gins(op, &tmp, &dst);
+                       p->to.type = D_OREG;
+                       p->to.offset = dir;
+               }
+       }
+
+       regfree(&dst);
+       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.
+ * 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 can't.
+ */
+int
+componentgen(Node *nr, Node *nl)
+{
+       Node nodl, nodr;
+       Type *t;
+       int freel, freer;
+       vlong fldcount;
+       vlong loffset, roffset;
+
+       freel = 0;
+       freer = 0;
+
+       switch(nl->type->etype) {
+       default:
+               goto no;
+
+       case TARRAY:
+               t = nl->type;
+
+               // Slices are ok.
+               if(isslice(t))
+                       break;
+               // Small arrays are ok.
+               if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
+                       break;
+
+               goto no;
+
+       case TSTRUCT:
+               // Small structs with non-fat types are ok.
+               // Zero-sized structs are treated separately elsewhere.
+               fldcount = 0;
+               for(t=nl->type->type; t; t=t->down) {
+                       if(isfat(t->type))
+                               goto no;
+                       if(t->etype != TFIELD)
+                               fatal("componentgen: not a TFIELD: %lT", t);
+                       fldcount++;
+               }
+               if(fldcount == 0 || fldcount > 4)
+                       goto no;
+
+               break;
+
+       case TSTRING:
+       case TINTER:
+               break;
+       }
+
+       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;
+               }
+       }
+       
+       // nl and nr are 'cadable' which basically means they are names (variables) now.
+       // If they are the same variable, don't generate any code, because the
+       // VARDEF we generate will mark the old value as dead incorrectly.
+       // (And also the assignments are useless.)
+       if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
+               goto yes;
+
+       switch(nl->type->etype) {
+       case TARRAY:
+               // componentgen for arrays.
+               if(nl->op == ONAME)
+                       gvardef(nl);
+               t = nl->type;
+               if(!isslice(t)) {
+                       nodl.type = t->type;
+                       nodr.type = nodl.type;
+                       for(fldcount=0; fldcount < t->bound; fldcount++) {
+                               if(nr == N)
+                                       clearslim(&nodl);
+                               else
+                                       gmove(&nodr, &nodl);
+                               nodl.xoffset += t->type->width;
+                               nodr.xoffset += t->type->width;
+                       }
+                       goto yes;
+               }
+
+               // componentgen for slices.
+               nodl.xoffset += Array_array;
+               nodl.type = ptrto(nl->type->type);
+
+               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[simtype[TUINT]];
+
+               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[simtype[TUINT]];
+
+               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:
+               if(nl->op == ONAME)
+                       gvardef(nl);
+               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[simtype[TUINT]];
+
+               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:
+               if(nl->op == ONAME)
+                       gvardef(nl);
+               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;
+
+       case TSTRUCT:
+               if(nl->op == ONAME)
+                       gvardef(nl);
+               loffset = nodl.xoffset;
+               roffset = nodr.xoffset;
+               // funarg structs may not begin at offset zero.
+               if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
+                       loffset -= nl->type->type->width;
+               if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
+                       roffset -= nr->type->type->width;
+
+               for(t=nl->type->type; t; t=t->down) {
+                       nodl.xoffset = loffset + t->width;
+                       nodl.type = t->type;
+
+                       if(nr == N)
+                               clearslim(&nodl);
+                       else {
+                               nodr.xoffset = roffset + t->width;
+                               nodr.type = nodl.type;
+                               gmove(&nodr, &nodl);
+                       }
+               }
+               goto yes;
+       }
+
+no:
+       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/9g/doc.go b/src/cmd/9g/doc.go
new file mode 100644 (file)
index 0000000..200be2e
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+
+9g is the version of the gc compiler for the Power64.
+The $GOARCH for these tools is power64 (big endian) or
+power64le (little endian).
+
+It reads .go files and outputs .9 files. The flags are documented in ../gc/doc.go.
+
+*/
+package main
diff --git a/src/cmd/9g/galign.c b/src/cmd/9g/galign.c
new file mode 100644 (file)
index 0000000..97a5a5d
--- /dev/null
@@ -0,0 +1,54 @@
+// 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 <u.h>
+#include <libc.h>
+#include "gg.h"
+
+int    thechar = '9';
+char*  thestring = "power64";
+LinkArch*      thelinkarch;
+
+void
+linkarchinit(void)
+{
+       thestring = getgoarch();
+       if(strcmp(thestring, "power64le") == 0)
+               thelinkarch = &linkpower64le;
+       else
+               thelinkarch = &linkpower64;
+}
+
+vlong MAXWIDTH = 1LL<<50;
+
+/*
+ * go declares several platform-specific type aliases:
+ * int, uint, float, and uintptr
+ */
+Typedef        typedefs[] =
+{
+       {"int",         TINT,           TINT64},
+       {"uint",                TUINT,          TUINT64},
+       {"uintptr",     TUINTPTR,       TUINT64},
+       {0}
+};
+
+void
+betypeinit(void)
+{
+       widthptr = 8;
+       widthint = 8;
+       widthreg = 8;
+
+       zprog.link = P;
+       zprog.as = AGOK;
+       zprog.reg = NREG;
+       zprog.from.name = D_NONE;
+       zprog.from.type = D_NONE;
+       zprog.from.reg = NREG;
+       zprog.to = zprog.from;
+       zprog.from3 = zprog.from;
+
+       listinit9();
+}
diff --git a/src/cmd/9g/gg.h b/src/cmd/9g/gg.h
new file mode 100644 (file)
index 0000000..703fbd0
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef        EXTERN
+#define        EXTERN  extern
+#endif
+
+#include "../gc/go.h"
+#include "../9l/9.out.h"
+
+// TODO(minux): Remove when no longer used.
+#define noimpl sysfatal("%s not implemented (%s:%d).", __func__, __FILE__, __LINE__)
+
+#define TEXTFLAG reg
+
+EXTERN int32   dynloc;
+EXTERN uchar   reg[NREG+NFREG];
+EXTERN int32   pcloc;          // instruction counter
+EXTERN Strlit  emptystring;
+EXTERN Prog    zprog;
+EXTERN Node*   newproc;
+EXTERN Node*   deferproc;
+EXTERN Node*   deferreturn;
+EXTERN Node*   panicindex;
+EXTERN Node*   panicslice;
+EXTERN Node*   panicdiv;
+EXTERN Node*   throwreturn;
+extern vlong   unmappedzero;
+
+/*
+ * ggen.c
+ */
+void   compile(Node*);
+void   gen(Node*);
+Node*  lookdot(Node*, Node*, int);
+void   cgen_as(Node*, Node*);
+void   cgen_callmeth(Node*, int);
+void   cgen_callinter(Node*, Node*, int);
+void   cgen_proc(Node*, int);
+void   cgen_callret(Node*, Node*);
+void   cgen_div(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);
+void   ginscall(Node*, int);
+int    gen_as_init(Node*);
+
+/*
+ * 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   sgen(Node*, Node*, int64);
+void   gmove(Node*, Node*);
+Prog*  gins(int, Node*, Node*);
+void   naddr(Node*, Addr*, int);
+void   cgen_aret(Node*, Node*);
+int    componentgen(Node*, Node*);
+
+/*
+ * gsubr.c
+ */
+void   clearp(Prog*);
+Prog*  gbranch(int, Type*, int);
+Prog*  prog(int);
+void   gconv(int, int);
+int    conv2pt(Type*);
+vlong  convvtox(vlong, int);
+void   fnparam(Type*, int, int);
+Prog*  gop(int, Node*, Node*, Node*);
+int    optoas(int, Type*);
+void   ginit(void);
+void   gclean(void);
+void   regalloc(Node*, Type*, Node*);
+void   regfree(Node*);
+Node*  nodarg(Type*, int);
+void   nodreg(Node*, Type*, int);
+void   nodindreg(Node*, Type*, int);
+void   ginscon(int, vlong, Node*);
+void   ginscon2(int, Node*, vlong);
+void   buildtxt(void);
+Plist* newplist(void);
+int    isfat(Type*);
+void   sudoclean(void);
+int    sudoaddable(int, Node*, Addr*);
+void   afunclit(Addr*, Node*);
+void   nodfconst(Node*, Type*, Mpflt*);
+void   gtrack(Sym*);
+void   fixlargeoffset(Node *n);
+
+/*
+ * cplx.c
+ */
+int    complexop(Node*, Node*);
+void   complexmove(Node*, Node*);
+void   complexgen(Node*, Node*);
+
+/*
+ * gobj.c
+ */
+void   datastring(char*, int, Addr*);
+void   datagostring(Strlit*, Addr*);
+
+/*
+ * list.c
+ */
+void   listinit(void);
+
+void   zaddr(Biobuf*, Addr*, int, int);
diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c
new file mode 100644 (file)
index 0000000..7d9cf50
--- /dev/null
@@ -0,0 +1,1040 @@
+// 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.
+
+#undef EXTERN
+#define        EXTERN
+#include <u.h>
+#include <libc.h>
+#include "gg.h"
+#include "opt.h"
+
+static Prog *appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset);
+static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi);
+
+void
+defframe(Prog *ptxt)
+{
+       uint32 frame;
+       Prog *p;
+       vlong hi, lo;
+       NodeList *l;
+       Node *n;
+
+       // fill in argument size
+       ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
+
+       // fill in final stack size
+       ptxt->to.offset <<= 32;
+       frame = rnd(stksize+maxarg, widthreg);
+       ptxt->to.offset |= frame;
+       
+       // insert code to zero ambiguously live variables
+       // so that the garbage collector only sees initialized values
+       // when it looks for pointers.
+       p = ptxt;
+       lo = hi = 0;
+       // iterate through declarations - they are sorted in decreasing xoffset order.
+       for(l=curfn->dcl; l != nil; l = l->next) {
+               n = l->n;
+               if(!n->needzero)
+                       continue;
+               if(n->class != PAUTO)
+                       fatal("needzero class %d", n->class);
+               if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
+                       fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
+
+               if(lo != hi && n->xoffset + n->type->width >= lo - 2*widthreg) {
+                       // merge with range we already have
+                       lo = n->xoffset;
+                       continue;
+               }
+               // zero old range
+               p = zerorange(p, frame, lo, hi);
+
+               // set new range
+               hi = n->xoffset + n->type->width;
+               lo = n->xoffset;
+       }
+       // zero final range
+       zerorange(p, frame, lo, hi);
+}
+
+static Prog*
+zerorange(Prog *p, vlong frame, vlong lo, vlong hi)
+{
+       vlong cnt, i;
+       Prog *p1;
+       Node *f;
+
+       cnt = hi - lo;
+       if(cnt == 0)
+               return p;
+       if(cnt < 4*widthptr) {
+               for(i = 0; i < cnt; i += widthptr)
+                       p = appendpp(p, AMOVD, D_REG, REGZERO, 0, D_OREG, REGSP, 8+frame+lo+i);
+       } else if(cnt <= 128*widthptr) {
+               p = appendpp(p, AADD, D_CONST, NREG, 8+frame+lo-8, D_REG, REGRT1, 0);
+               p->reg = REGSP;
+               p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0);
+               f = sysfunc("duffzero");
+               naddr(f, &p->to, 1);
+               afunclit(&p->to, f);
+               p->to.offset = 4*(128-cnt/widthptr);
+       } else {
+               p = appendpp(p, AMOVD, D_CONST, NREG, 8+frame+lo-8, D_REG, REGTMP, 0);
+               p = appendpp(p, AADD, D_REG, REGTMP, 0, D_REG, REGRT1, 0);
+               p->reg = REGSP;
+               p = appendpp(p, AMOVD, D_CONST, NREG, cnt, D_REG, REGTMP, 0);
+               p = appendpp(p, AADD, D_REG, REGTMP, 0, D_REG, REGRT2, 0);
+               p->reg = REGRT1;
+               p1 = p = appendpp(p, AMOVDU, D_REG, REGZERO, 0, D_OREG, REGRT1, widthptr);
+               p = appendpp(p, ACMP, D_REG, REGRT1, 0, D_REG, REGRT2, 0);
+               p = appendpp(p, ABNE, D_NONE, NREG, 0, D_BRANCH, NREG, 0);
+               patch(p, p1);
+       }
+       return p;
+}
+
+static Prog*
+appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)
+{
+       Prog *q;
+       q = mal(sizeof(*q));
+       clearp(q);
+       q->as = as;
+       q->lineno = p->lineno;
+       q->from.type = ftype;
+       q->from.reg = freg;
+       q->from.offset = foffset;
+       q->to.type = ttype;
+       q->to.reg = treg;
+       q->to.offset = toffset;
+       q->link = p->link;
+       p->link = q;
+       return q;
+}
+
+// Sweep the prog list to mark any used nodes.
+void
+markautoused(Prog *p)
+{
+       for (; p; p = p->link) {
+               if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
+                       continue;
+
+               if (p->from.node)
+                       p->from.node->used = 1;
+
+               if (p->to.node)
+                       p->to.node->used = 1;
+       }
+}
+
+// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
+void
+fixautoused(Prog *p)
+{
+       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->as == AVARDEF || p->as == AVARKILL) && p->to.node && !p->to.node->used) {
+                       // Cannot remove VARDEF instruction, because - unlike TYPE handled above -
+                       // VARDEFs are interspersed with other code, and a jump might be using the
+                       // VARDEF as a target. Replace with a no-op instead. A later pass will remove
+                       // the no-ops.
+                       p->to.type = D_NONE;
+                       p->to.node = N;
+                       p->as = ANOP;
+                       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: BL reg, f
+ * where both reg and f are registers.
+ * On power, f must be moved to CTR first.
+ */
+static void
+ginsBL(Node *reg, Node *f)
+{
+       Prog *p;
+       p = gins(AMOVD, f, N);
+       p->to.type = D_SPR;
+       p->to.offset = D_CTR;
+       p = gins(ABL, reg, N);
+       p->to.type = D_SPR;
+       p->to.offset = D_CTR;
+}
+
+/*
+ * 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, reg2;
+       Node r1;
+
+       if(f->type != T)
+               setmaxarg(f->type);
+
+       switch(proc) {
+       default:
+               fatal("ginscall: bad proc %d", proc);
+               break;
+
+       case 0: // normal call
+       case -1:        // normal call but no return
+               if(f->op == ONAME && f->class == PFUNC) {
+                       if(f == deferreturn) {
+                               // Deferred calls will appear to be returning to
+                               // the CALL deferreturn(SB) that we are about to emit.
+                               // However, the stack trace code will show the line
+                               // of the instruction byte before the return PC. 
+                               // To avoid that being an unrelated instruction,
+                               // insert a Power64 NOP that we will have the right line number.
+                               // Power64 NOP is really or r0, r0, r0; use that description
+                               // because the NOP pseudo-instruction would be removed by
+                               // the linker.
+                               nodreg(&reg, types[TINT], D_R0);
+                               gins(AOR, &reg, &reg);
+                       }
+                       p = gins(ABL, N, f);
+                       afunclit(&p->to, f);
+                       if(proc == -1 || noreturn(p))
+                               gins(AUNDEF, N, N);
+                       break;
+               }
+               nodreg(&reg, types[tptr], D_R0+REGENV);
+               nodreg(&r1, types[tptr], D_R0+3);
+               gmove(f, &reg);
+               reg.op = OINDREG;
+               gmove(&reg, &r1);
+               reg.op = OREGISTER;
+               ginsBL(&reg, &r1);
+               break;
+       
+       case 3: // normal call of c function pointer
+               ginsBL(N, f);
+               break;
+
+       case 1: // call in new proc (go)
+       case 2: // deferred call (defer)
+               nodconst(&con, types[TINT64], argsize(f->type));
+               nodreg(&reg, types[TINT64], D_R0+3);
+               nodreg(&reg2, types[TINT64], D_R0+4);
+               gmove(f, &reg);
+
+               p = gins(ASUB, N, N);
+               p->from.type = D_CONST;
+               p->from.offset = 3 * 8;
+               p->to.type = D_REG;
+               p->to.reg = REGSP;
+
+               gmove(&con, &reg2);
+               p = gins(AMOVW, &reg2, N);
+               p->to.type = D_OREG;
+               p->to.reg = REGSP;
+               p->to.offset = 8;
+
+               p = gins(AMOVD, &reg, N);
+               p->to.type = D_OREG;
+               p->to.reg = REGSP;
+               p->to.offset = 16;
+
+               if(proc == 1)
+                       ginscall(newproc, 0);
+               else {
+                       if(!hasdefer)
+                               fatal("hasdefer=0 but has defer");
+                       ginscall(deferproc, 0);
+               }
+
+               p = gins(AADD, N, N);
+               p->from.type = D_CONST;
+               p->from.offset = 3 * 8;
+               p->to.type = D_REG;
+               p->to.reg = REGSP;
+
+               if(proc == 2) {
+                       nodreg(&reg, types[TINT64], D_R0+3);
+                       p = gins(ACMP, &reg, N);
+                       p->to.type = D_REG;
+                       p->to.reg = D_R0;
+                       p = gbranch(ABEQ, T, +1);
+                       cgen_ret(N);
+                       patch(p, pc);
+               }
+               break;
+       }
+}
+
+/*
+ * n is call to interface method.
+ * generate res = n.
+ */
+void
+cgen_callinter(Node *n, Node *res, int proc)
+{
+       Node *i, *f;
+       Node tmpi, nodi, nodo, nodr, nodsp;
+       Prog *p;
+
+       i = n->left;
+       if(i->op != ODOTINTER)
+               fatal("cgen_callinter: not ODOTINTER %O", i->op);
+
+       f = i->right;           // field
+       if(f->op != ONAME)
+               fatal("cgen_callinter: not ONAME %O", f->op);
+
+       i = i->left;            // interface
+
+       if(!i->addable) {
+               tempname(&tmpi, i->type);
+               cgen(i, &tmpi);
+               i = &tmpi;
+       }
+
+       genlist(n->list);               // assign the args
+
+       // i is now addable, prepare an indirected
+       // register to hold its address.
+       igen(i, &nodi, res);            // REG = &inter
+
+       nodindreg(&nodsp, types[tptr], D_R0+REGSP);
+       nodsp.xoffset = widthptr;
+       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");
+       cgen_checknil(&nodo); // in case offset is huge
+       nodo.op = OINDREG;
+       nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
+       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.
+               p = gins(AMOVD, &nodo, &nodr);  // REG = &(32+offset(REG)) -- i.tab->fun[f]
+               p->from.type = D_CONST;
+       }
+
+       nodr.type = n->left->type;
+       ginscall(&nodr, proc);
+
+       regfree(&nodr);
+       regfree(&nodo);
+}
+
+/*
+ * generate function call;
+ *     proc=0  normal call
+ *     proc=1  goroutine run in new proc
+ *     proc=2  defer call save away stack
+ */
+void
+cgen_call(Node *n, int proc)
+{
+       Type *t;
+       Node nod, afun;
+
+       if(n == N)
+               return;
+
+       if(n->left->ullman >= UINF) {
+               // if name involves a fn call
+               // precompute the address of the fn
+               tempname(&afun, types[tptr]);
+               cgen(n->left, &afun);
+       }
+
+       genlist(n->list);               // assign the args
+       t = n->left->type;
+
+       // call tempname pointer
+       if(n->left->ullman >= UINF) {
+               regalloc(&nod, types[tptr], N);
+               cgen_as(&nod, &afun);
+               nod.type = t;
+               ginscall(&nod, proc);
+               regfree(&nod);
+               return;
+       }
+
+       // call pointer
+       if(n->left->op != ONAME || n->left->class != PFUNC) {
+               regalloc(&nod, types[tptr], N);
+               cgen_as(&nod, n->left);
+               nod.type = t;
+               ginscall(&nod, proc);
+               regfree(&nod);
+               return;
+       }
+
+       // call direct
+       n->left->method = 1;
+       ginscall(n->left, proc);
+}
+
+/*
+ * call to n has already been generated.
+ * generate:
+ *     res = return value from call.
+ */
+void
+cgen_callret(Node *n, Node *res)
+{
+       Node nod;
+       Type *fp, *t;
+       Iter flist;
+
+       t = n->left->type;
+       if(t->etype == TPTR32 || t->etype == TPTR64)
+               t = t->type;
+
+       fp = structfirst(&flist, getoutarg(t));
+       if(fp == T)
+               fatal("cgen_callret: nil");
+
+       memset(&nod, 0, sizeof(nod));
+       nod.op = OINDREG;
+       nod.val.u.reg = D_R0+REGSP;
+       nod.addable = 1;
+
+       nod.xoffset = fp->width + widthptr; // +widthptr: saved LR at 0(R1)
+       nod.type = fp->type;
+       cgen_as(res, &nod);
+}
+
+/*
+ * call to n has already been generated.
+ * generate:
+ *     res = &return value from call.
+ */
+void
+cgen_aret(Node *n, Node *res)
+{
+       Node nod1, nod2;
+       Type *fp, *t;
+       Iter flist;
+
+       t = n->left->type;
+       if(isptr[t->etype])
+               t = t->type;
+
+       fp = structfirst(&flist, getoutarg(t));
+       if(fp == T)
+               fatal("cgen_aret: nil");
+
+       memset(&nod1, 0, sizeof(nod1));
+       nod1.op = OINDREG;
+       nod1.val.u.reg = D_R0 + REGSP;
+       nod1.addable = 1;
+
+       nod1.xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
+       nod1.type = fp->type;
+
+       if(res->op != OREGISTER) {
+               regalloc(&nod2, types[tptr], res);
+               agen(&nod1, &nod2);
+               gins(AMOVD, &nod2, res);
+               regfree(&nod2);
+       } else
+               agen(&nod1, res);
+}
+
+/*
+ * generate return.
+ * n->left is assignments to return values.
+ */
+void
+cgen_ret(Node *n)
+{
+       Prog *p;
+
+       if(n != N)
+               genlist(n->list);               // copy out args
+       if(hasdefer)
+               ginscall(deferreturn, 0);
+       genlist(curfn->exit);
+       p = gins(ARET, N, N);
+       if(n != N && n->op == ORETJMP) {
+               p->to.name = D_EXTERN;
+               p->to.type = D_CONST;
+               p->to.sym = linksym(n->left->sym);
+       }
+}
+
+void
+cgen_asop(Node *n)
+{
+       USED(n);
+       fatal("cgen_asop"); // no longer used
+}
+
+int
+samereg(Node *a, Node *b)
+{
+       if(a == N || b == N)
+               return 0;
+       if(a->op != OREGISTER)
+               return 0;
+       if(b->op != OREGISTER)
+               return 0;
+       if(a->val.u.reg != b->val.u.reg)
+               return 0;
+       return 1;
+}
+
+/*
+ * generate division.
+ * generates one of:
+ *     res = nl / nr
+ *     res = nl % nr
+ * according to op.
+ */
+void
+dodiv(int op, Node *nl, Node *nr, Node *res)
+{
+       int a, check;
+       Type *t, *t0;
+       Node tl, tr, tl2, tr2, nm1, nz, tm;
+       Prog *p1, *p2;
+
+       // Have to be careful about handling
+       // most negative int divided by -1 correctly.
+       // The hardware will generate undefined result.
+       // Also need to explicitly trap on division on zero,
+       // the hardware will silently generate undefined result.
+       // DIVW will leave unpredicable result in higher 32-bit,
+       // so always use DIVD/DIVDU.
+       t = nl->type;
+       t0 = t;
+       check = 0;
+       if(issigned[t->etype]) {
+               check = 1;
+               if(isconst(nl, CTINT) && mpgetfix(nl->val.u.xval) != -(1ULL<<(t->width*8-1)))
+                       check = 0;
+               else if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) != -1)
+                       check = 0;
+       }
+       if(t->width < 8) {
+               if(issigned[t->etype])
+                       t = types[TINT64];
+               else
+                       t = types[TUINT64];
+               check = 0;
+       }
+
+       a = optoas(ODIV, t);
+
+       regalloc(&tl, t0, N);
+       regalloc(&tr, t0, N);
+       if(nl->ullman >= nr->ullman) {
+               cgen(nl, &tl);
+               cgen(nr, &tr);
+       } else {
+               cgen(nr, &tr);
+               cgen(nl, &tl);
+       }
+       if(t != t0) {
+               // Convert
+               tl2 = tl;
+               tr2 = tr;
+               tl.type = t;
+               tr.type = t;
+               gmove(&tl2, &tl);
+               gmove(&tr2, &tr);
+       }
+
+       // Handle divide-by-zero panic.
+       p1 = gins(optoas(OCMP, t), &tr, N);
+       p1->to.type = D_REG;
+       p1->to.reg = REGZERO;
+       p1 = gbranch(optoas(ONE, t), T, +1);
+       if(panicdiv == N)
+               panicdiv = sysfunc("panicdivide");
+       ginscall(panicdiv, -1);
+       patch(p1, pc);
+
+       if(check) {
+               nodconst(&nm1, t, -1);
+               gins(optoas(OCMP, t), &tr, &nm1);
+               p1 = gbranch(optoas(ONE, t), T, +1);
+               if(op == ODIV) {
+                       // a / (-1) is -a.
+                       gins(optoas(OMINUS, t), N, &tl);
+                       gmove(&tl, res);
+               } else {
+                       // a % (-1) is 0.
+                       nodconst(&nz, t, 0);
+                       gmove(&nz, res);
+               }
+               p2 = gbranch(AJMP, T, 0);
+               patch(p1, pc);
+       }
+       p1 = gins(a, &tr, &tl);
+       if(op == ODIV) {
+               regfree(&tr);
+               gmove(&tl, res);
+       } else {
+               // A%B = A-(A/B*B)
+               regalloc(&tm, t, N);
+               // patch div to use the 3 register form
+               // TODO(minux): add gins3?
+               p1->reg = p1->to.reg;
+               p1->to.reg = tm.val.u.reg;
+               gins(optoas(OMUL, t), &tr, &tm);
+               regfree(&tr);
+               gins(optoas(OSUB, t), &tm, &tl);
+               regfree(&tm);
+               gmove(&tl, res);
+       }
+       regfree(&tl);
+       if(check)
+               patch(p2, pc);
+}
+
+/*
+ * generate division according to op, one of:
+ *     res = nl / nr
+ *     res = nl % nr
+ */
+void
+cgen_div(int op, Node *nl, Node *nr, Node *res)
+{
+       Node n1, n2, n3;
+       int w, a;
+       Magic m;
+
+       // TODO(minux): enable division by magic multiply (also need to fix longmod below)
+       //if(nr->op != OLITERAL)
+               goto longdiv;
+       w = nl->type->width*8;
+
+       // 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 TUINT64:
+               m.w = w;
+               m.ud = mpgetfix(nr->val.u.xval);
+               umagic(&m);
+               if(m.bad)
+                       break;
+               if(op == OMOD)
+                       goto longmod;
+
+               cgenr(nl, &n1, N);
+               nodconst(&n2, nl->type, m.um);
+               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, &n3);
+                       nodconst(&n2, nl->type, 1);
+                       gins(optoas(ORROTC, nl->type), &n2, &n3);
+                       nodconst(&n2, nl->type, m.s-1);
+                       gins(optoas(ORSH, nl->type), &n2, &n3);
+               } else {
+                       nodconst(&n2, nl->type, m.s);
+                       gins(optoas(ORSH, nl->type), &n2, &n3); // shift dx
+               }
+
+               gmove(&n3, res);
+               regfree(&n1);
+               regfree(&n3);
+               return;
+
+       case TINT64:
+               m.w = w;
+               m.sd = mpgetfix(nr->val.u.xval);
+               smagic(&m);
+               if(m.bad)
+                       break;
+               if(op == OMOD)
+                       goto longmod;
+
+               cgenr(nl, &n1, res);
+               nodconst(&n2, nl->type, m.sm);
+               regalloc(&n3, nl->type, N);
+               cgen_hmul(&n1, &n2, &n3);
+
+               if(m.sm < 0) {
+                       // need to add numerator
+                       gins(optoas(OADD, nl->type), &n1, &n3);
+               }
+
+               nodconst(&n2, nl->type, m.s);
+               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, &n3); // added
+
+               if(m.sd < 0) {
+                       // this could probably be removed
+                       // by factoring it into the multiplier
+                       gins(optoas(OMINUS, nl->type), N, &n3);
+               }
+
+               gmove(&n3, res);
+               regfree(&n1);
+               regfree(&n3);
+               return;
+       }
+       goto longdiv;
+
+longdiv:
+       // division and mod using (slow) hardware instruction
+       dodiv(op, nl, nr, res);
+       return;
+
+longmod:
+       // mod using formula A%B = A-(A/B*B) but
+       // we know that there is a fast algorithm for A/B
+       regalloc(&n1, nl->type, res);
+       cgen(nl, &n1);
+       regalloc(&n2, nl->type, N);
+       cgen_div(ODIV, &n1, nr, &n2);
+       a = optoas(OMUL, nl->type);
+       if(w == 8) {
+               // use 2-operand 16-bit multiply
+               // because there is no 2-operand 8-bit multiply
+               //a = AIMULW;
+       }
+       if(!smallintconst(nr)) {
+               regalloc(&n3, nl->type, N);
+               cgen(nr, &n3);
+               gins(a, &n3, &n2);
+               regfree(&n3);
+       } else
+               gins(a, nr, &n2);
+       gins(optoas(OSUB, nl->type), &n2, &n1);
+       gmove(&n1, res);
+       regfree(&n1);
+       regfree(&n2);
+}
+
+/*
+ * generate high multiply:
+ *   res = (nl*nr) >> width
+ */
+void
+cgen_hmul(Node *nl, Node *nr, Node *res)
+{
+       int w;
+       Node n1, n2, *tmp;
+       Type *t;
+       Prog *p;
+
+       // largest ullman on left.
+       if(nl->ullman < nr->ullman) {
+               tmp = nl;
+               nl = nr;
+               nr = tmp;
+       }
+       t = nl->type;
+       w = t->width * 8;
+       cgenr(nl, &n1, res);
+       cgenr(nr, &n2, N);
+       switch(simtype[t->etype]) {
+       case TINT8:
+       case TINT16:
+       case TINT32:
+               gins(optoas(OMUL, t), &n2, &n1);
+               p = gins(ASRAD, N, &n1);
+               p->from.type = D_CONST;
+               p->from.offset = w;
+               break;
+       case TUINT8:
+       case TUINT16:
+       case TUINT32:
+               gins(optoas(OMUL, t), &n2, &n1);
+               p = gins(ASRD, N, &n1);
+               p->from.type = D_CONST;
+               p->from.offset = w;
+               break;
+       case TINT64:
+       case TUINT64:
+               if(issigned[t->etype])
+                       p = gins(AMULHD, &n2, &n1);
+               else
+                       p = gins(AMULHDU, &n2, &n1);
+               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, int bounded, Node *nl, Node *nr, Node *res)
+{
+       Node n1, n2, n3, n4, n5;
+       int a;
+       Prog *p1;
+       uvlong sc;
+       Type *tcount;
+
+       a = optoas(op, nl->type);
+
+       if(nr->op == OLITERAL) {
+               regalloc(&n1, nl->type, res);
+               cgen(nl, &n1);
+               sc = mpgetfix(nr->val.u.xval);
+               if(sc >= nl->type->width*8) {
+                       // 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);
+               } else
+                       gins(a, nr, &n1);
+               gmove(&n1, res);
+               regfree(&n1);
+               goto ret;
+       }
+
+       if(nl->ullman >= UINF) {
+               tempname(&n4, nl->type);
+               cgen(nl, &n4);
+               nl = &n4;
+       }
+       if(nr->ullman >= UINF) {
+               tempname(&n5, nr->type);
+               cgen(nr, &n5);
+               nr = &n5;
+       }
+
+       // Allow either uint32 or uint64 as shift type,
+       // to avoid unnecessary conversion from uint32 to uint64
+       // just to do the comparison.
+       tcount = types[simtype[nr->type->etype]];
+       if(tcount->etype < TUINT32)
+               tcount = types[TUINT32];
+
+       regalloc(&n1, nr->type, N);             // to hold the shift type in CX
+       regalloc(&n3, tcount, &n1);     // to clear high bits of CX
+
+       regalloc(&n2, nl->type, res);
+       if(nl->ullman >= nr->ullman) {
+               cgen(nl, &n2);
+               cgen(nr, &n1);
+               gmove(&n1, &n3);
+       } else {
+               cgen(nr, &n1);
+               gmove(&n1, &n3);
+               cgen(nl, &n2);
+       }
+       regfree(&n3);
+
+       // test and fix up large shifts
+       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);
+       }
+
+       gins(a, &n1, &n2);
+
+       gmove(&n2, res);
+
+       regfree(&n1);
+       regfree(&n2);
+
+ret:
+       ;
+}
+
+void
+clearfat(Node *nl)
+{
+       uint64 w, c, q, t, boff;
+       Node dst, end, r0, *f;
+       Prog *p, *pl;
+
+       /* clear a fat object */
+       if(debug['g']) {
+               print("clearfat %N (%T, size: %lld)\n", nl, nl->type, nl->type->width);
+       }
+
+       w = nl->type->width;
+       // Avoid taking the address for simple enough types.
+       //if(componentgen(N, nl))
+       //      return;
+
+       c = w % 8;      // bytes
+       q = w / 8;      // dwords
+
+       if(reg[REGRT1] > 0)
+               fatal("R%d in use during clearfat", REGRT1);
+
+       nodreg(&r0, types[TUINT64], 0); // r0 is always zero
+       nodreg(&dst, types[tptr], D_R0+REGRT1);
+       reg[REGRT1]++;
+       agen(nl, &dst);
+
+       if(q > 128) {
+               p = gins(ASUB, N, &dst);
+               p->from.type = D_CONST;
+               p->from.offset = 8;
+
+               regalloc(&end, types[tptr], N);
+               p = gins(AMOVD, &dst, &end);
+               p->from.type = D_CONST;
+               p->from.offset = q*8;
+
+               p = gins(AMOVDU, &r0, &dst);
+               p->to.type = D_OREG;
+               p->to.offset = 8;
+               pl = p;
+
+               p = gins(ACMP, &dst, &end);
+               patch(gbranch(ABNE, T, 0), pl);
+
+               regfree(&end);
+               // The loop leaves R3 on the last zeroed dword
+               boff = 8;
+       } else if(q >= 4) {
+               p = gins(ASUB, N, &dst);
+               p->from.type = D_CONST;
+               p->from.offset = 8;
+               f = sysfunc("duffzero");
+               p = gins(ADUFFZERO, N, f);
+               afunclit(&p->to, f);
+               // 4 and 128 = magic constants: see ../../runtime/asm_power64x.s
+               p->to.offset = 4*(128-q);
+               // duffzero leaves R3 on the last zeroed dword
+               boff = 8;
+       } else {
+               for(t = 0; t < q; t++) {
+                       p = gins(AMOVD, &r0, &dst);
+                       p->to.type = D_OREG;
+                       p->to.offset = 8*t;
+               }
+               boff = 8*q;
+       }
+
+       for(t = 0; t < c; t++) {
+               p = gins(AMOVB, &r0, &dst);
+               p->to.type = D_OREG;
+               p->to.offset = t+boff;
+       }
+       reg[REGRT1]--;
+}
+
+// Called after regopt and peep have run.
+// Expand CHECKNIL pseudo-op into actual nil pointer check.
+void
+expandchecks(Prog *firstp)
+{
+       Prog *p, *p1, *p2;
+
+       for(p = firstp; p != P; p = p->link) {
+               if(debug_checknil && ctxt->debugvlog)
+                       print("expandchecks: %P\n", p);
+               if(p->as != ACHECKNIL)
+                       continue;
+               if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
+                       warnl(p->lineno, "generated nil check");
+               if(p->from.type != D_REG)
+                       fatal("invalid nil check %P\n", p);
+               /*
+               // check is
+               //      TD $4, R0, arg (R0 is always zero)
+               // eqv. to:
+               //      tdeq r0, arg
+               // NOTE: this needs special runtime support to make SIGTRAP recoverable.
+               reg = p->from.reg;
+               p->as = ATD;
+               p->from = p->to = p->from3 = zprog.from;
+               p->from.type = D_CONST;
+               p->from.offset = 4;
+               p->from.reg = NREG;
+               p->reg = 0;
+               p->to.type = D_REG;
+               p->to.reg = reg;
+               */
+               // check is
+               //      CMP arg, R0
+               //      BNE 2(PC) [likely]
+               //      MOVD R0, 0(R0)
+               p1 = mal(sizeof *p1);
+               p2 = mal(sizeof *p2);
+               clearp(p1);
+               clearp(p2);
+               p1->link = p2;
+               p2->link = p->link;
+               p->link = p1;
+               p1->lineno = p->lineno;
+               p2->lineno = p->lineno;
+               p1->pc = 9999;
+               p2->pc = 9999;
+               p->as = ACMP;
+               p->to.type = D_REG;
+               p->to.reg = REGZERO;
+               p1->as = ABNE;
+               //p1->from.type = D_CONST;
+               //p1->from.offset = 1; // likely
+               p1->to.type = D_BRANCH;
+               p1->to.u.branch = p2->link;
+               // crash by write to memory address 0.
+               p2->as = AMOVD;
+               p2->from.type = D_REG;
+               p2->from.reg = 0;
+               p2->to.type = D_OREG;
+               p2->to.reg = 0;
+               p2->to.offset = 0;
+       }
+}
diff --git a/src/cmd/9g/gobj.c b/src/cmd/9g/gobj.c
new file mode 100644 (file)
index 0000000..3da5587
--- /dev/null
@@ -0,0 +1,240 @@
+// Derived from Inferno utils/6c/swt.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include "gg.h"
+
+int
+dsname(Sym *s, int off, char *t, int n)
+{
+       Prog *p;
+
+       p = gins(ADATA, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.offset = off;
+       p->from.reg = NREG;
+       p->from.sym = linksym(s);
+
+       p->reg = n;
+       
+       p->to.type = D_SCONST;
+       p->to.name = D_NONE;
+       p->to.reg = NREG;
+       p->to.offset = 0;
+       memmove(p->to.u.sval, t, n);
+       return off + n;
+}
+
+/*
+ * make a refer to the data s, s+len
+ * emitting DATA if needed.
+ */
+void
+datastring(char *s, int len, Addr *a)
+{
+       Sym *sym;
+       
+       sym = stringsym(s, len);
+       a->type = D_OREG;
+       a->name = D_EXTERN;
+       a->etype = simtype[TINT];
+       a->offset = widthptr+widthint;  // skip header
+       a->reg = NREG;
+       a->sym = linksym(sym);
+       a->node = sym->def;
+}
+
+/*
+ * make a refer to the string sval,
+ * emitting DATA if needed.
+ */
+void
+datagostring(Strlit *sval, Addr *a)
+{
+       Sym *sym;
+
+       sym = stringsym(sval->s, sval->len);
+       a->type = D_OREG;
+       a->name = D_EXTERN;
+       a->sym = linksym(sym);
+       a->reg = NREG;
+       a->node = sym->def;
+       a->offset = 0;  // header
+       a->etype = TSTRING;
+}
+
+void
+gdata(Node *nam, Node *nr, int wid)
+{
+       Prog *p;
+
+       if(nr->op == OLITERAL) {
+               switch(nr->val.ctype) {
+               case CTCPLX:
+                       gdatacomplex(nam, nr->val.u.cval);
+                       return;
+               case CTSTR:
+                       gdatastring(nam, nr->val.u.sval);
+                       return;
+               }
+       }
+       p = gins(ADATA, nam, nr);
+       p->reg = wid;
+}
+
+void
+gdatacomplex(Node *nam, Mpcplx *cval)
+{
+       Prog *p;
+       int w;
+
+       w = cplxsubtype(nam->type->etype);
+       w = types[w]->width;
+
+       p = gins(ADATA, nam, N);
+       p->reg = w;
+       p->to.type = D_FCONST;
+       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.u.dval = mpgetflt(&cval->imag);
+}
+
+void
+gdatastring(Node *nam, Strlit *sval)
+{
+       Prog *p;
+       Node nod1;
+
+       p = gins(ADATA, nam, N);
+       datastring(sval->s, sval->len, &p->to);
+       p->reg = types[tptr]->width;
+       p->to.type = D_CONST;
+       p->to.etype = simtype[tptr];
+
+       nodconst(&nod1, types[TINT], sval->len);
+       p = gins(ADATA, nam, &nod1);
+       p->reg = widthint;
+       p->from.offset += widthptr;
+}
+
+int
+dstringptr(Sym *s, int off, char *str)
+{
+       Prog *p;
+
+       off = rnd(off, widthptr);
+       p = gins(ADATA, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.sym = linksym(s);
+       p->from.offset = off;
+       p->reg = widthptr;
+
+       datastring(str, strlen(str)+1, &p->to);
+       p->to.type = D_CONST;
+       p->to.etype = simtype[TINT];
+       off += widthptr;
+
+       return off;
+}
+
+int
+dgostrlitptr(Sym *s, int off, Strlit *lit)
+{
+       Prog *p;
+
+       if(lit == nil)
+               return duintptr(s, off, 0);
+
+       off = rnd(off, widthptr);
+       p = gins(ADATA, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.sym = linksym(s);
+       p->from.offset = off;
+       p->reg = widthptr;
+       datagostring(lit, &p->to);
+       p->to.type = D_CONST;
+       p->to.etype = simtype[TINT];
+       off += widthptr;
+
+       return off;
+}
+
+int
+dgostringptr(Sym *s, int off, char *str)
+{
+       int n;
+       Strlit *lit;
+
+       if(str == nil)
+               return duintptr(s, off, 0);
+
+       n = strlen(str);
+       lit = mal(sizeof *lit + n);
+       strcpy(lit->s, str);
+       lit->len = n;
+       return dgostrlitptr(s, off, lit);
+}
+
+int
+dsymptr(Sym *s, int off, Sym *x, int xoff)
+{
+       Prog *p;
+
+       off = rnd(off, widthptr);
+
+       p = gins(ADATA, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.sym = linksym(s);
+       p->from.offset = off;
+       p->reg = widthptr;
+       p->to.type = D_CONST;
+       p->to.name = D_EXTERN;
+       p->to.sym = linksym(x);
+       p->to.offset = xoff;
+       off += widthptr;
+
+       return off;
+}
+
+void
+nopout(Prog *p)
+{
+       p->as = ANOP;
+}
+
diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c
new file mode 100644 (file)
index 0000000..e5cd5ed
--- /dev/null
@@ -0,0 +1,1707 @@
+// Derived from Inferno utils/6c/txt.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include "gg.h"
+#include "../../runtime/funcdata.h"
+
+// TODO(rsc): Can make this bigger if we move
+// the text segment up higher in 6l for all GOOS.
+// At the same time, can raise StackBig in ../../runtime/stack.h.
+vlong unmappedzero = 4096;
+
+void
+clearp(Prog *p)
+{
+       *p = zprog;
+       p->as = AEND;
+       p->pc = pcloc;
+       pcloc++;
+}
+
+static int ddumped;
+static Prog *dfirst;
+static Prog *dpc;
+
+/*
+ * generate and return proc with p->as = as,
+ * linked into program. pc is next instruction.
+ */
+Prog*
+prog(int as)
+{
+       Prog *p;
+
+       if(as == ADATA || as == AGLOBL) {
+               if(ddumped)
+                       fatal("already dumped data");
+               if(dpc == nil) {
+                       dpc = mal(sizeof(*dpc));
+                       dfirst = dpc;
+               }
+               p = dpc;
+               dpc = mal(sizeof(*dpc));
+               p->link = dpc;
+               p->reg = 0; // used for flags
+       } else {
+               p = pc;
+               pc = mal(sizeof(*pc));
+               clearp(pc);
+               p->link = pc;
+       }
+
+       if(lineno == 0) {
+               if(debug['K'])
+                       warn("prog: line 0");
+       }
+
+       p->as = as;
+       p->lineno = lineno;
+       return p;
+}
+
+void
+dumpdata(void)
+{
+       ddumped = 1;
+       if(dfirst == nil)
+               return;
+       newplist();
+       *pc = *dfirst;
+       pc = dpc;
+       clearp(pc);
+}
+
+/*
+ * 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, int likely)
+{
+       Prog *p;
+       
+       USED(t);
+
+       p = prog(as);
+       p->to.type = D_BRANCH;
+       p->to.u.branch = P;
+       // TODO(minux): Enable this code.
+       // Note: liblink used Bcc CR0, label form, so we need another way
+       // to set likely/unlikely flag. Also note the y bit is not exactly
+       // likely/unlikely bit.
+       if(0 && as != ABR && likely != 0) {
+               p->from.type = D_CONST;
+               p->from.offset = likely > 0;
+       }
+       return p;
+}
+
+/*
+ * patch previous branch to jump to to.
+ */
+void
+patch(Prog *p, Prog *to)
+{
+       if(p->to.type != D_BRANCH)
+               fatal("patch: not a branch");
+       p->to.u.branch = to;
+       p->to.offset = to->pc;
+}
+
+Prog*
+unpatch(Prog *p)
+{
+       Prog *q;
+
+       if(p->to.type != D_BRANCH)
+               fatal("unpatch: not a branch");
+       q = p->to.u.branch;
+       p->to.u.branch = P;
+       p->to.offset = 0;
+       return q;
+}
+
+/*
+ * start a new Prog list.
+ */
+Plist*
+newplist(void)
+{
+       Plist *pl;
+
+       pl = linknewplist(ctxt);
+
+       pc = mal(sizeof(*pc));
+       clearp(pc);
+       pl->firstpc = pc;
+
+       return pl;
+}
+
+void
+gused(Node *n)
+{
+       gins(ANOP, n, N);       // used
+}
+
+Prog*
+gjmp(Prog *to)
+{
+       Prog *p;
+
+       p = gbranch(ABR, T, 0);
+       if(to != P)
+               patch(p, to);
+       return p;
+}
+
+void
+ggloblnod(Node *nam)
+{
+       Prog *p;
+
+       p = gins(AGLOBL, nam, N);
+       p->lineno = nam->lineno;
+       p->from.sym->gotype = linksym(ngotype(nam));
+       p->to.sym = nil;
+       p->to.type = D_CONST;
+       p->to.offset = nam->type->width;
+       if(nam->readonly)
+               p->reg = RODATA;
+       if(nam->type != T && !haspointers(nam->type))
+               p->reg |= NOPTR;
+}
+
+void
+gtrack(Sym *s)
+{
+       Prog *p;
+       
+       p = gins(AUSEFIELD, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.sym = linksym(s);
+}
+
+void
+ggloblsym(Sym *s, int32 width, int8 flags)
+{
+       Prog *p;
+
+       p = gins(AGLOBL, N, N);
+       p->from.type = D_OREG;
+       p->from.name = D_EXTERN;
+       p->from.sym = linksym(s);
+       p->to.type = D_CONST;
+       p->to.name = D_NONE;
+       p->to.offset = width;
+       p->reg = flags;
+}
+
+int
+isfat(Type *t)
+{
+       if(t != T)
+       switch(t->etype) {
+       case TSTRUCT:
+       case TARRAY:
+       case TSTRING:
+       case TINTER:    // maybe remove later
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * naddr of func generates code for address of func.
+ * if using opcode that can take address implicitly,
+ * call afunclit to fix up the argument.
+ */
+void
+afunclit(Addr *a, Node *n)
+{
+       if(a->type == D_CONST && a->name == D_EXTERN) {
+               a->type = D_OREG;
+               a->sym = linksym(n->sym);
+       }
+}
+
+static int     resvd[] =
+{
+       REGZERO,
+       REGSP,  // reserved for SP, XXX: not reserved in 9c.
+       30,     // for g
+       REGTMP, // REGTMP
+       FREGCVI+NREG,
+       FREGZERO+NREG,
+       FREGHALF+NREG,
+       FREGONE+NREG,
+       FREGTWO+NREG,
+};
+
+void
+ginit(void)
+{
+       int i;
+
+       for(i=0; i<nelem(reg); i++)
+               reg[i] = 1;
+       for(i=0; i<NREG; i++)
+               reg[i] = 0;
+       for(i=NREG; i<NREG+NREG; i++)
+               reg[i] = 0;
+
+       for(i=0; i<nelem(resvd); i++)
+               reg[resvd[i]]++;
+}
+
+static uintptr regpc[nelem(reg)];
+
+void
+gclean(void)
+{
+       int i;
+
+       for(i=0; i<nelem(resvd); i++)
+               reg[resvd[i]]--;
+
+       for(i=0; i<nelem(reg); i++)
+               if(reg[i])
+                       yyerror("reg %R left allocated, %p\n", i, regpc[i]);
+}
+
+int32
+anyregalloc(void)
+{
+       int i, j;
+
+       for(i=0; i<nelem(reg); i++) {
+               if(reg[i] == 0)
+                       goto ok;
+               for(j=0; j<nelem(resvd); j++)
+                       if(resvd[j] == i)
+                               goto ok;
+               return 1;
+       ok:;
+       }
+       return 0;
+}
+
+/*
+ * allocate register of type t, leave in n.
+ * if o != N, o is desired fixed register.
+ * caller must regfree(n).
+ */
+void
+regalloc(Node *n, Type *t, Node *o)
+{
+       int i, et;
+       int fixfree, fltfree;
+
+       if(t == T)
+               fatal("regalloc: t nil");
+       et = simtype[t->etype];
+
+       if(debug['r']) {
+               fixfree = 0;
+               fltfree = 0;
+               for(i = D_R0; i < D_F0+NREG; i++)
+                       if(reg[i] == 0) {
+                               if(i < D_F0)
+                                       fixfree++;
+                               else
+                                       fltfree++;
+                       }
+               print("regalloc fix %d flt %d free\n", fixfree, fltfree);
+       }
+
+       switch(et) {
+       case TINT8:
+       case TUINT8:
+       case TINT16:
+       case TUINT16:
+       case TINT32:
+       case TUINT32:
+       case TINT64:
+       case TUINT64:
+       case TPTR32:
+       case TPTR64:
+       case TBOOL:
+               if(o != N && o->op == OREGISTER) {
+                       i = o->val.u.reg;
+                       if(i >= D_R0+REGMIN && i <= D_R0+REGMAX)
+                               goto out;
+               }
+               for(i=D_R0+REGMIN; i<=D_R0+REGMAX; i++)
+                       if(reg[i] == 0) {
+                               regpc[i] = (uintptr)getcallerpc(&n);
+                               goto out;
+                       }
+               flusherrors();
+               for(i=D_R0; i<D_R0+NREG; i++)
+                       print("R%d %p\n", i, regpc[i]);
+               fatal("out of fixed registers");
+
+       case TFLOAT32:
+       case TFLOAT64:
+               if(o != N && o->op == OREGISTER) {
+                       i = o->val.u.reg;
+                       if(i >= D_F0+FREGMIN && i <= D_F0+FREGMAX)
+                               goto out;
+               }
+               for(i=D_F0+FREGMIN; i<=D_F0+FREGMAX; i++)
+                       if(reg[i] == 0) {
+                               regpc[i] = (uintptr)getcallerpc(&n);
+                               goto out;
+                       }
+               flusherrors();
+               for(i=D_F0; i<D_F0+NREG; i++)
+                       print("F%d %p\n", i, regpc[i]);
+               fatal("out of floating registers");
+
+       case TCOMPLEX64:
+       case TCOMPLEX128:
+               tempname(n, t);
+               return;
+       }
+       fatal("regalloc: unknown type %T", t);
+       return;
+
+out:
+       reg[i]++;
+       nodreg(n, t, i);
+}
+
+void
+regfree(Node *n)
+{
+       int i;
+
+       if(n->op == ONAME)
+               return;
+       if(n->op != OREGISTER && n->op != OINDREG)
+               fatal("regfree: not a register");
+       i = n->val.u.reg;
+       if(i == D_R0 + REGSP)
+               return;
+       if(i < 0 || i >= nelem(reg))
+               fatal("regfree: reg out of range");
+       if(reg[i] <= 0)
+               fatal("regfree: reg not allocated");
+       reg[i]--;
+       if(reg[i] == 0)
+               regpc[i] = 0;
+}
+
+/*
+ * initialize n to be register r of type t.
+ */
+void
+nodreg(Node *n, Type *t, int r)
+{
+       if(t == T)
+               fatal("nodreg: t nil");
+
+       memset(n, 0, sizeof(*n));
+       n->op = OREGISTER;
+       n->addable = 1;
+       ullmancalc(n);
+       n->val.u.reg = r;
+       n->type = t;
+}
+
+/*
+ * initialize n to be indirect of register r; n is type t.
+ */
+void
+nodindreg(Node *n, Type *t, int r)
+{
+       nodreg(n, t, r);
+       n->op = OINDREG;
+}
+
+Node*
+nodarg(Type *t, int fp)
+{
+       Node *n;
+       NodeList *l;
+       Type *first;
+       Iter savet;
+
+       // entire argument struct, not just one arg
+       if(t->etype == TSTRUCT && t->funarg) {
+               n = nod(ONAME, N, N);
+               n->sym = lookup(".args");
+               n->type = t;
+               first = structfirst(&savet, &t);
+               if(first == nil)
+                       fatal("nodarg: bad struct");
+               if(first->width == BADWIDTH)
+                       fatal("nodarg: offset not computed for %T", t);
+               n->xoffset = first->width;
+               n->addable = 1;
+               goto fp;
+       }
+
+       if(t->etype != TFIELD)
+               fatal("nodarg: not field %T", t);
+       
+       if(fp == 1) {
+               for(l=curfn->dcl; l; l=l->next) {
+                       n = l->n;
+                       if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
+                               return n;
+               }
+       }
+
+       n = nod(ONAME, N, N);
+       n->type = t->type;
+       n->sym = t->sym;
+       
+       if(t->width == BADWIDTH)
+               fatal("nodarg: offset not computed for %T", t);
+       n->xoffset = t->width;
+       n->addable = 1;
+       n->orig = t->nname;
+
+fp:
+       // Rewrite argument named _ to __,
+       // or else the assignment to _ will be
+       // discarded during code generation.
+       if(isblank(n))
+               n->sym = lookup("__");
+
+       switch(fp) {
+       default:
+               fatal("nodarg %T %d", t, fp);
+
+       case 0:         // output arg for calling another function
+               n->op = OINDREG;
+               n->val.u.reg = D_R0+REGSP;
+               n->xoffset += 8;
+               break;
+
+       case 1:         // input arg to current function
+               n->class = PPARAM;
+               break;
+
+       case 2:         // offset output arg
+fatal("shouldn't be used");
+               n->op = OINDREG;
+               n->val.u.reg = D_R0 + REGSP;
+               n->xoffset += types[tptr]->width;
+               break;
+       }
+       n->typecheck = 1;
+       return n;
+}
+
+/*
+ * generate
+ *     as $c, n
+ */
+void
+ginscon(int as, vlong c, Node *n2)
+{
+       Node n1, ntmp;
+
+       nodconst(&n1, types[TINT64], c);
+
+       if(as != AMOVD && (c < -BIG || c > BIG)) {
+               // cannot have more than 16-bit of immediate in ADD, etc.
+               // instead, MOV into register first.
+               regalloc(&ntmp, types[TINT64], N);
+               gins(AMOVD, &n1, &ntmp);
+               gins(as, &ntmp, n2);
+               regfree(&ntmp);
+               return;
+       }
+       gins(as, &n1, n2);
+}
+
+/*
+ * generate
+ *     as n, $c (CMP/CMPU)
+ */
+void
+ginscon2(int as, Node *n2, vlong c)
+{
+       Node n1, ntmp;
+
+       nodconst(&n1, types[TINT64], c);
+
+       switch(as) {
+       default:
+               fatal("ginscon2");
+       case ACMP:
+               if(-BIG <= c && c <= BIG) {
+                       gins(as, n2, &n1);
+                       return;
+               }
+               break;
+       case ACMPU:
+               if(0 <= c && c <= 2*BIG) {
+                       gins(as, n2, &n1);
+                       return;
+               }
+               break;
+       }
+       // MOV n1 into register first
+       regalloc(&ntmp, types[TINT64], N);
+       gins(AMOVD, &n1, &ntmp);
+       gins(as, n2, &ntmp);
+       regfree(&ntmp);
+}
+
+#define        CASE(a,b)       (((a)<<16)|((b)<<0))
+/*c2go int CASE(int, int); */
+
+/*
+ * Is this node a memory operand?
+ */
+int
+ismem(Node *n)
+{
+       switch(n->op) {
+       case OITAB:
+       case OSPTR:
+       case OLEN:
+       case OCAP:
+       case OINDREG:
+       case ONAME:
+       case OPARAM:
+       case OCLOSUREVAR:
+       case OADDR:
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * set up nodes representing 2^63
+ */
+Node bigi;
+Node bigf;
+
+void
+bignodes(void)
+{
+       static int did;
+
+       if(did)
+               return;
+       did = 1;
+
+       nodconst(&bigi, types[TUINT64], 1);
+       mpshiftfix(bigi.val.u.xval, 63);
+
+       bigf = bigi;
+       bigf.type = types[TFLOAT64];
+       bigf.val.ctype = CTFLT;
+       bigf.val.u.fval = mal(sizeof *bigf.val.u.fval);
+       mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval);
+}
+
+/*
+ * generate move:
+ *     t = f
+ * hard part is conversions.
+ */
+void
+gmove(Node *f, Node *t)
+{
+       int a, ft, tt;
+       Type *cvt;
+       Node r1, r2, r3, con;
+       Prog *p1, *p2;
+
+       if(debug['M'])
+               print("gmove %lN -> %lN\n", f, t);
+
+       ft = simsimtype(f->type);
+       tt = simsimtype(t->type);
+       cvt = t->type;
+
+       if(iscomplex[ft] || iscomplex[tt]) {
+               complexmove(f, t);
+               return;
+       }
+
+       // cannot have two memory operands
+       if(ismem(f) && ismem(t))
+               goto hard;
+
+       // convert constant to desired type
+       if(f->op == OLITERAL) {
+               switch(tt) {
+               default:
+                       convconst(&con, t->type, &f->val);
+                       break;
+
+               case TINT32:
+               case TINT16:
+               case TINT8:
+                       convconst(&con, types[TINT64], &f->val);
+                       regalloc(&r1, con.type, t);
+                       gins(AMOVD, &con, &r1);
+                       gmove(&r1, t);
+                       regfree(&r1);
+                       return;
+
+               case TUINT32:
+               case TUINT16:
+               case TUINT8:
+                       convconst(&con, types[TUINT64], &f->val);
+                       regalloc(&r1, con.type, t);
+                       gins(AMOVD, &con, &r1);
+                       gmove(&r1, t);
+                       regfree(&r1);
+                       return;
+               }
+
+               f = &con;
+               ft = tt;        // so big switch will choose a simple mov
+
+               // constants can't move directly to memory.
+               if(ismem(t)) {
+                       goto hard;
+                       // float constants come from memory.
+                       //if(isfloat[tt])
+                       //      goto hard;
+
+                       // 64-bit immediates are also from memory.
+                       //if(isint[tt])
+                       //      goto hard;
+                       //// 64-bit immediates are really 32-bit sign-extended
+                       //// unless moving into a register.
+                       //if(isint[tt]) {
+                       //      if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
+                       //              goto hard;
+                       //      if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
+                       //              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:
+               fatal("gmove %lT -> %lT", f->type, t->type);
+
+       /*
+        * integer copy and truncate
+        */
+       case CASE(TINT8, TINT8):        // same size
+       case CASE(TUINT8, TINT8):
+       case CASE(TINT16, TINT8):       // truncate
+       case CASE(TUINT16, TINT8):
+       case CASE(TINT32, TINT8):
+       case CASE(TUINT32, TINT8):
+       case CASE(TINT64, TINT8):
+       case CASE(TUINT64, TINT8):
+               a = AMOVB;
+               break;
+
+       case CASE(TINT8, TUINT8):       // same size
+       case CASE(TUINT8, TUINT8):
+       case CASE(TINT16, TUINT8):      // truncate
+       case CASE(TUINT16, TUINT8):
+       case CASE(TINT32, TUINT8):
+       case CASE(TUINT32, TUINT8):
+       case CASE(TINT64, TUINT8):
+       case CASE(TUINT64, TUINT8):
+               a = AMOVBZ;
+               break;
+
+       case CASE(TINT16, TINT16):      // same size
+       case CASE(TUINT16, TINT16):
+       case CASE(TINT32, TINT16):      // truncate
+       case CASE(TUINT32, TINT16):
+       case CASE(TINT64, TINT16):
+       case CASE(TUINT64, TINT16):
+               a = AMOVH;
+               break;
+
+       case CASE(TINT16, TUINT16):     // same size
+       case CASE(TUINT16, TUINT16):
+       case CASE(TINT32, TUINT16):     // truncate
+       case CASE(TUINT32, TUINT16):
+       case CASE(TINT64, TUINT16):
+       case CASE(TUINT64, TUINT16):
+               a = AMOVHZ;
+               break;
+
+       case CASE(TINT32, TINT32):      // same size
+       case CASE(TUINT32, TINT32):
+       case CASE(TINT64, TINT32):      // truncate
+       case CASE(TUINT64, TINT32):
+               a = AMOVW;
+               break;
+
+       case CASE(TINT32, TUINT32):     // same size
+       case CASE(TUINT32, TUINT32):
+       case CASE(TINT64, TUINT32):
+       case CASE(TUINT64, TUINT32):
+               a = AMOVWZ;
+               break;
+
+       case CASE(TINT64, TINT64):      // same size
+       case CASE(TINT64, TUINT64):
+       case CASE(TUINT64, TINT64):
+       case CASE(TUINT64, TUINT64):
+               a = AMOVD;
+               break;
+
+       /*
+        * integer up-conversions
+        */
+       case CASE(TINT8, TINT16):       // sign extend int8
+       case CASE(TINT8, TUINT16):
+       case CASE(TINT8, TINT32):
+       case CASE(TINT8, TUINT32):
+       case CASE(TINT8, TINT64):
+       case CASE(TINT8, TUINT64):
+               a = AMOVB;
+               goto rdst;
+
+       case CASE(TUINT8, TINT16):      // zero extend uint8
+       case CASE(TUINT8, TUINT16):
+       case CASE(TUINT8, TINT32):
+       case CASE(TUINT8, TUINT32):
+       case CASE(TUINT8, TINT64):
+       case CASE(TUINT8, TUINT64):
+               a = AMOVBZ;
+               goto rdst;
+
+       case CASE(TINT16, TINT32):      // sign extend int16
+       case CASE(TINT16, TUINT32):
+       case CASE(TINT16, TINT64):
+       case CASE(TINT16, TUINT64):
+               a = AMOVH;
+               goto rdst;
+
+       case CASE(TUINT16, TINT32):     // zero extend uint16
+       case CASE(TUINT16, TUINT32):
+       case CASE(TUINT16, TINT64):
+       case CASE(TUINT16, TUINT64):
+               a = AMOVHZ;
+               goto rdst;
+
+       case CASE(TINT32, TINT64):      // sign extend int32
+       case CASE(TINT32, TUINT64):
+               a = AMOVW;
+               goto rdst;
+
+       case CASE(TUINT32, TINT64):     // zero extend uint32
+       case CASE(TUINT32, TUINT64):
+               a = AMOVWZ;
+               goto rdst;
+
+       /*
+       * float to integer
+       */
+       case CASE(TFLOAT32, TINT32):
+       case CASE(TFLOAT64, TINT32):
+       case CASE(TFLOAT32, TINT64):
+       case CASE(TFLOAT64, TINT64):
+       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):
+       case CASE(TFLOAT32, TUINT32):
+       case CASE(TFLOAT64, TUINT32):
+       case CASE(TFLOAT32, TUINT64):
+       case CASE(TFLOAT64, TUINT64):
+               //warn("gmove: convert float to int not implemented: %N -> %N\n", f, t);
+               //return;
+               // algorithm is:
+               //      if small enough, use native float64 -> int64 conversion.
+               //      otherwise, subtract 2^63, convert, and add it back.
+               bignodes();
+               regalloc(&r1, types[ft], f);
+               gmove(f, &r1);
+               if(tt == TUINT64) {
+                       regalloc(&r2, types[TFLOAT64], N);
+                       gmove(&bigf, &r2);
+                       gins(AFCMPU, &r1, &r2);
+                       p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1);
+                       gins(AFSUB, &r2, &r1);
+                       patch(p1, pc);
+                       regfree(&r2);
+               }
+               regalloc(&r2, types[TFLOAT64], N);
+               regalloc(&r3, types[TINT64], t);
+               gins(AFCTIDZ, &r1, &r2);
+               p1 = gins(AFMOVD, &r2, N);
+               p1->to.type = D_OREG;
+               p1->to.reg = REGSP;
+               p1->to.offset = -8;
+               p1 = gins(AMOVD, N, &r3);
+               p1->from.type = D_OREG;
+               p1->from.reg = REGSP;
+               p1->from.offset = -8;
+               regfree(&r2);
+               regfree(&r1);
+               if(tt == TUINT64) {
+                       p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); // use CR0 here again
+                       nodreg(&r1, types[TINT64], D_R0+REGTMP);
+                       gins(AMOVD, &bigi, &r1);
+                       gins(AADD, &r1, &r3);
+                       patch(p1, pc);
+               }
+               gmove(&r3, t);
+               regfree(&r3);
+               return;
+
+       /*
+        * integer to float
+        */
+       case CASE(TINT32, TFLOAT32):
+       case CASE(TINT32, TFLOAT64):
+       case CASE(TINT64, TFLOAT32):
+       case CASE(TINT64, TFLOAT64):
+       case CASE(TINT16, TFLOAT32):
+       case CASE(TINT16, TFLOAT64):
+       case CASE(TINT8, TFLOAT32):
+       case CASE(TINT8, TFLOAT64):
+       case CASE(TUINT16, TFLOAT32):
+       case CASE(TUINT16, TFLOAT64):
+       case CASE(TUINT8, TFLOAT32):
+       case CASE(TUINT8, TFLOAT64):
+       case CASE(TUINT32, TFLOAT32):
+       case CASE(TUINT32, TFLOAT64):
+       case CASE(TUINT64, TFLOAT32):
+       case CASE(TUINT64, TFLOAT64):
+               //warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
+               //return;
+               // algorithm is:
+               //      if small enough, use native int64 -> uint64 conversion.
+               //      otherwise, halve (rounding to odd?), convert, and double.
+               bignodes();
+               regalloc(&r1, types[TINT64], N);
+               gmove(f, &r1);
+               if(ft == TUINT64) {
+                       nodreg(&r2, types[TUINT64], D_R0+REGTMP);
+                       gmove(&bigi, &r2);
+                       gins(ACMPU, &r1, &r2);
+                       p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
+                       p2 = gins(ASRD, N, &r1);
+                       p2->from.type = D_CONST;
+                       p2->from.offset = 1;
+                       patch(p1, pc);
+               }
+               regalloc(&r2, types[TFLOAT64], t);
+               p1 = gins(AMOVD, &r1, N);
+               p1->to.type = D_OREG;
+               p1->to.reg = REGSP;
+               p1->to.offset = -8;
+               p1 = gins(AFMOVD, N, &r2);
+               p1->from.type = D_OREG;
+               p1->from.reg = REGSP;
+               p1->from.offset = -8;
+               gins(AFCFID, &r2, &r2);
+               regfree(&r1);
+               if(ft == TUINT64) {
+                       p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); // use CR0 here again
+                       nodreg(&r1, types[TFLOAT64], D_F0+FREGTWO);
+                       gins(AFMUL, &r1, &r2);
+                       patch(p1, pc);
+               }
+               gmove(&r2, t);
+               regfree(&r2);
+               return;
+
+       /*
+        * float to float
+        */
+       case CASE(TFLOAT32, TFLOAT32):
+               a = AFMOVS;
+               break;
+
+       case CASE(TFLOAT64, TFLOAT64):
+               a = AFMOVD;
+               break;
+
+       case CASE(TFLOAT32, TFLOAT64):
+               a = AFMOVS;
+               goto rdst;
+
+       case CASE(TFLOAT64, TFLOAT32):
+               a = AFRSP;
+               goto rdst;
+       }
+
+       gins(a, f, t);
+       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;
+}
+
+/*
+ * generate one instruction:
+ *     as f, t
+ */
+Prog*
+gins(int as, Node *f, Node *t)
+{
+       int32 w;
+       Prog *p;
+       Addr af, at;
+
+       // TODO(austin): Add self-move test like in 6g (but be careful
+       // of truncation moves)
+
+       memset(&af, 0, sizeof af);
+       memset(&at, 0, sizeof at);
+       if(f != N)
+               naddr(f, &af, 1);
+       if(t != N)
+               naddr(t, &at, 1);
+       p = prog(as);
+       if(f != N)
+               p->from = af;
+       if(t != N)
+               p->to = at;
+       if(as == ATEXT)
+               p->reg = 0;
+       if(debug['g'])
+               print("%P\n", p);
+
+       w = 0;
+       switch(as) {
+       case AMOVB:
+       case AMOVBU:
+       case AMOVBZ:
+       case AMOVBZU:
+               w = 1;
+               break;
+       case AMOVH:
+       case AMOVHU:
+       case AMOVHZ:
+       case AMOVHZU:
+               w = 2;
+               break;
+       case AMOVW:
+       case AMOVWU:
+       case AMOVWZ:
+       case AMOVWZU:
+               w = 4;
+               break;
+       case AMOVD:
+       case AMOVDU:
+               if(af.type == D_CONST)
+                       break;
+               w = 8;
+               break;
+       }
+       if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != D_REG && at.width > w))) {
+               dump("f", f);
+               dump("t", t);
+               fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
+       }
+
+       return p;
+}
+
+void
+fixlargeoffset(Node *n)
+{
+       Node a;
+
+       if(n == N)
+               return;
+       if(n->op != OINDREG)
+               return;
+       if(n->val.u.reg == D_R0+REGSP) // stack offset cannot be large
+               return;
+       if(n->xoffset != (int32)n->xoffset) {
+               // TODO(minux): offset too large, move into R31 and add to R31 instead.
+               // this is used only in test/fixedbugs/issue6036.go.
+               print("offset too large: %N\n", n);
+               noimpl;
+               a = *n;
+               a.op = OREGISTER;
+               a.type = types[tptr];
+               a.xoffset = 0;
+               cgen_checknil(&a);
+               ginscon(optoas(OADD, types[tptr]), n->xoffset, &a);
+               n->xoffset = 0;
+       }
+}
+
+/*
+ * generate code to compute n;
+ * make a refer to result.
+ */
+void
+naddr(Node *n, Addr *a, int canemitcode)
+{
+       Sym *s;
+
+       a->type = D_NONE;
+       a->name = D_NONE;
+       a->reg = NREG;
+       a->gotype = nil;
+       a->node = N;
+       a->etype = 0;
+       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);
+               break;
+
+       case ONAME:
+               a->etype = 0;
+               a->reg = NREG;
+               if(n->type != T)
+                       a->etype = simtype[n->type->etype];
+               a->offset = n->xoffset;
+               s = n->sym;
+               a->node = n->orig;
+               //if(a->node >= (Node*)&n)
+               //      fatal("stack node");
+               if(s == S)
+                       s = lookup(".noname");
+               if(n->method) {
+                       if(n->type != T)
+                       if(n->type->sym != S)
+                       if(n->type->sym->pkg != nil)
+                               s = pkglookup(s->name, n->type->sym->pkg);
+               }
+
+               a->type = D_OREG;
+               switch(n->class) {
+               default:
+                       fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
+               case PEXTERN:
+                       a->name = D_EXTERN;
+                       break;
+               case PAUTO:
+                       a->name = D_AUTO;
+                       break;
+               case PPARAM:
+               case PPARAMOUT:
+                       a->name = D_PARAM;
+                       break;
+               case PFUNC:
+                       a->name = D_EXTERN;
+                       a->type = D_CONST;
+                       a->width = widthptr;
+                       s = funcsym(s);
+                       break;
+               }
+               a->sym = linksym(s);
+               break;
+
+       case OLITERAL:
+               switch(n->val.ctype) {
+               default:
+                       fatal("naddr: const %lT", n->type);
+                       break;
+               case CTFLT:
+                       a->type = D_FCONST;
+                       a->u.dval = mpgetflt(n->val.u.fval);
+                       break;
+               case CTINT:
+               case CTRUNE:
+                       a->sym = nil;
+                       a->type = D_CONST;
+                       a->offset = mpgetfix(n->val.u.xval);
+                       break;
+               case CTSTR:
+                       datagostring(n->val.u.sval, a);
+                       break;
+               case CTBOOL:
+                       a->sym = nil;
+                       a->type = D_CONST;
+                       a->offset = n->val.u.bval;
+                       break;
+               case CTNIL:
+                       a->sym = nil;
+                       a->type = D_CONST;
+                       a->offset = 0;
+                       break;
+               }
+               break;
+
+       case OREGISTER:
+               if(n->val.u.reg < D_F0) {
+                       a->type = D_REG;
+                       a->reg = n->val.u.reg;
+               } else {
+                       a->type = D_FREG;
+                       a->reg = n->val.u.reg - D_F0;
+               }
+               a->sym = nil;
+               break;
+
+       case OINDREG:
+               a->type = D_OREG;
+               a->reg = n->val.u.reg;
+               a->sym = linksym(n->sym);
+               a->offset = n->xoffset;
+               if(a->offset != (int32)a->offset)
+                       yyerror("offset %lld too large for OINDREG", a->offset);
+               break;
+
+       case OPARAM:
+               // n->left is PHEAP ONAME for stack parameter.
+               // compute address of actual parameter on stack.
+               a->etype = simtype[n->left->type->etype];
+               a->width = n->left->type->width;
+               a->offset = n->xoffset;
+               a->sym = linksym(n->left->sym);
+               a->type = D_OREG;
+               a->name = D_PARAM;
+               a->node = n->left->orig;
+               break;
+
+       case OCLOSUREVAR:
+               if(!curfn->needctxt)
+                       fatal("closurevar without needctxt");
+               a->type = D_OREG;
+               a->reg = REGENV;
+               a->offset = n->xoffset;
+               a->sym = nil;
+               break;
+
+       case OCFUNC:
+               naddr(n->left, a, canemitcode);
+               a->sym = linksym(n->left->sym);
+               break;
+
+       case OITAB:
+               // itable of interface value
+               naddr(n->left, a, canemitcode);
+               a->etype = simtype[tptr];
+               if(a->type == D_CONST && a->offset == 0)
+                       break;  // itab(nil)
+               a->width = widthptr;
+               break;
+
+       case OSPTR:
+               // pointer in a string or slice
+               naddr(n->left, a, canemitcode);
+               a->etype = simtype[tptr];
+               if(a->type == D_CONST && a->offset == 0)
+                       break;  // ptr(nil)
+               a->offset += Array_array;
+               a->width = widthptr;
+               break;
+
+       case OLEN:
+               // len of string or slice
+               naddr(n->left, a, canemitcode);
+               a->etype = simtype[TINT];
+               if(a->type == D_CONST && a->offset == 0)
+                       break;  // len(nil)
+               a->offset += Array_nel;
+               a->width = widthint;
+               break;
+
+       case OCAP:
+               // cap of string or slice
+               naddr(n->left, a, canemitcode);
+               a->etype = simtype[TINT];
+               if(a->type == D_CONST && a->offset == 0)
+                       break;  // cap(nil)
+               a->offset += Array_cap;
+               a->width = widthint;
+               break;
+
+       case OADDR:
+               naddr(n->left, a, canemitcode);
+               a->etype = tptr;
+               switch(a->type) {
+               case D_OREG:
+                       a->type = D_CONST;
+                       break;
+
+               case D_REG:
+               case D_CONST:
+                       break;
+
+               default:
+                       fatal("naddr: OADDR %d\n", a->type);
+               }
+               break;
+       }
+}
+
+/*
+ * return Axxx for Oxxx on type t.
+ */
+int
+optoas(int op, Type *t)
+{
+       int a;
+
+       if(t == T)
+               fatal("optoas: t is nil");
+
+       a = AGOK;
+       switch(CASE(op, simtype[t->etype])) {
+       default:
+               fatal("optoas: no entry for op=%O type=%T", op, t);
+               break;
+
+       case CASE(OEQ, TBOOL):
+       case CASE(OEQ, TINT8):
+       case CASE(OEQ, TUINT8):
+       case CASE(OEQ, TINT16):
+       case CASE(OEQ, TUINT16):
+       case CASE(OEQ, TINT32):
+       case CASE(OEQ, TUINT32):
+       case CASE(OEQ, TINT64):
+       case CASE(OEQ, TUINT64):
+       case CASE(OEQ, TPTR32):
+       case CASE(OEQ, TPTR64):
+       case CASE(OEQ, TFLOAT32):
+       case CASE(OEQ, TFLOAT64):
+               a = ABEQ;
+               break;
+
+       case CASE(ONE, TBOOL):
+       case CASE(ONE, TINT8):
+       case CASE(ONE, TUINT8):
+       case CASE(ONE, TINT16):
+       case CASE(ONE, TUINT16):
+       case CASE(ONE, TINT32):
+       case CASE(ONE, TUINT32):
+       case CASE(ONE, TINT64):
+       case CASE(ONE, TUINT64):
+       case CASE(ONE, TPTR32):
+       case CASE(ONE, TPTR64):
+       case CASE(ONE, TFLOAT32):
+       case CASE(ONE, TFLOAT64):
+               a = ABNE;
+               break;
+
+       case CASE(OLT, TINT8):  // ACMP
+       case CASE(OLT, TINT16):
+       case CASE(OLT, TINT32):
+       case CASE(OLT, TINT64):
+       case CASE(OLT, TUINT8): // ACMPU
+       case CASE(OLT, TUINT16):
+       case CASE(OLT, TUINT32):
+       case CASE(OLT, TUINT64):
+       case CASE(OLT, TFLOAT32): // AFCMPU
+       case CASE(OLT, TFLOAT64):
+               a = ABLT;
+               break;
+
+       case CASE(OLE, TINT8):  // ACMP
+       case CASE(OLE, TINT16):
+       case CASE(OLE, TINT32):
+       case CASE(OLE, TINT64):
+       case CASE(OLE, TUINT8): // ACMPU
+       case CASE(OLE, TUINT16):
+       case CASE(OLE, TUINT32):
+       case CASE(OLE, TUINT64):
+       case CASE(OLE, TFLOAT32): // AFCMPU
+       case CASE(OLE, TFLOAT64):
+               a = ABLE;
+               break;
+
+       case CASE(OGT, TINT8):
+       case CASE(OGT, TINT16):
+       case CASE(OGT, TINT32):
+       case CASE(OGT, TINT64):
+       case CASE(OGT, TUINT8):
+       case CASE(OGT, TUINT16):
+       case CASE(OGT, TUINT32):
+       case CASE(OGT, TUINT64):
+       case CASE(OGT, TFLOAT32):
+       case CASE(OGT, TFLOAT64):
+               a = ABGT;
+               break;
+
+       case CASE(OGE, TINT8):
+       case CASE(OGE, TINT16):
+       case CASE(OGE, TINT32):
+       case CASE(OGE, TINT64):
+       case CASE(OGE, TUINT8):
+       case CASE(OGE, TUINT16):
+       case CASE(OGE, TUINT32):
+       case CASE(OGE, TUINT64):
+       case CASE(OGE, TFLOAT32):
+       case CASE(OGE, TFLOAT64):
+               a = ABGE;
+               break;
+
+       case CASE(OCMP, TBOOL):
+       case CASE(OCMP, TINT8):
+       case CASE(OCMP, TINT16):
+       case CASE(OCMP, TINT32):
+       case CASE(OCMP, TPTR32):
+       case CASE(OCMP, TINT64):
+               a = ACMP;
+               break;
+
+       case CASE(OCMP, TUINT8):
+       case CASE(OCMP, TUINT16):
+       case CASE(OCMP, TUINT32):
+       case CASE(OCMP, TUINT64):
+       case CASE(OCMP, TPTR64):
+               a = ACMPU;
+               break;
+
+       case CASE(OCMP, TFLOAT32):
+       case CASE(OCMP, TFLOAT64):
+               a = AFCMPU;
+               break;
+
+       case CASE(OAS, TBOOL):
+       case CASE(OAS, TINT8):
+               a = AMOVB;
+               break;
+
+       case CASE(OAS, TUINT8):
+               a = AMOVBZ;
+               break;
+
+       case CASE(OAS, TINT16):
+               a = AMOVH;
+               break;
+
+       case CASE(OAS, TUINT16):
+               a = AMOVHZ;
+               break;
+
+       case CASE(OAS, TINT32):
+               a = AMOVW;
+               break;
+
+       case CASE(OAS, TUINT32):
+       case CASE(OAS, TPTR32):
+               a = AMOVWZ;
+               break;
+
+       case CASE(OAS, TINT64):
+       case CASE(OAS, TUINT64):
+       case CASE(OAS, TPTR64):
+               a = AMOVD;
+               break;
+
+       case CASE(OAS, TFLOAT32):
+               a = AFMOVS;
+               break;
+
+       case CASE(OAS, TFLOAT64):
+               a = AFMOVD;
+               break;
+
+       case CASE(OADD, TINT8):
+       case CASE(OADD, TUINT8):
+       case CASE(OADD, TINT16):
+       case CASE(OADD, TUINT16):
+       case CASE(OADD, TINT32):
+       case CASE(OADD, TUINT32):
+       case CASE(OADD, TPTR32):
+       case CASE(OADD, TINT64):
+       case CASE(OADD, TUINT64):
+       case CASE(OADD, TPTR64):
+               a = AADD;
+               break;
+
+       case CASE(OADD, TFLOAT32):
+               a = AFADDS;
+               break;
+
+       case CASE(OADD, TFLOAT64):
+               a = AFADD;
+               break;
+
+       case CASE(OSUB, TINT8):
+       case CASE(OSUB, TUINT8):
+       case CASE(OSUB, TINT16):
+       case CASE(OSUB, TUINT16):
+       case CASE(OSUB, TINT32):
+       case CASE(OSUB, TUINT32):
+       case CASE(OSUB, TPTR32):
+       case CASE(OSUB, TINT64):
+       case CASE(OSUB, TUINT64):
+       case CASE(OSUB, TPTR64):
+               a = ASUB;
+               break;
+
+       case CASE(OSUB, TFLOAT32):
+               a = AFSUBS;
+               break;
+
+       case CASE(OSUB, TFLOAT64):
+               a = AFSUB;
+               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):
+       case CASE(OMINUS, TINT64):
+       case CASE(OMINUS, TUINT64):
+       case CASE(OMINUS, TPTR64):
+               a = ANEG;
+               break;
+
+       case CASE(OAND, TINT8):
+       case CASE(OAND, TUINT8):
+       case CASE(OAND, TINT16):
+       case CASE(OAND, TUINT16):
+       case CASE(OAND, TINT32):
+       case CASE(OAND, TUINT32):
+       case CASE(OAND, TPTR32):
+       case CASE(OAND, TINT64):
+       case CASE(OAND, TUINT64):
+       case CASE(OAND, TPTR64):
+               a = AAND;
+               break;
+
+       case CASE(OOR, TINT8):
+       case CASE(OOR, TUINT8):
+       case CASE(OOR, TINT16):
+       case CASE(OOR, TUINT16):
+       case CASE(OOR, TINT32):
+       case CASE(OOR, TUINT32):
+       case CASE(OOR, TPTR32):
+       case CASE(OOR, TINT64):
+       case CASE(OOR, TUINT64):
+       case CASE(OOR, TPTR64):
+               a = AOR;
+               break;
+
+       case CASE(OXOR, TINT8):
+       case CASE(OXOR, TUINT8):
+       case CASE(OXOR, TINT16):
+       case CASE(OXOR, TUINT16):
+       case CASE(OXOR, TINT32):
+       case CASE(OXOR, TUINT32):
+       case CASE(OXOR, TPTR32):
+       case CASE(OXOR, TINT64):
+       case CASE(OXOR, TUINT64):
+       case CASE(OXOR, TPTR64):
+               a = AXOR;
+               break;
+
+       // TODO(minux): handle rotates
+       //case CASE(OLROT, TINT8):
+       //case CASE(OLROT, TUINT8):
+       //case CASE(OLROT, TINT16):
+       //case CASE(OLROT, TUINT16):
+       //case CASE(OLROT, TINT32):
+       //case CASE(OLROT, TUINT32):
+       //case CASE(OLROT, TPTR32):
+       //case CASE(OLROT, TINT64):
+       //case CASE(OLROT, TUINT64):
+       //case CASE(OLROT, TPTR64):
+       //      a = 0//???; RLDC?
+       //      break;
+
+       case CASE(OLSH, TINT8):
+       case CASE(OLSH, TUINT8):
+       case CASE(OLSH, TINT16):
+       case CASE(OLSH, TUINT16):
+       case CASE(OLSH, TINT32):
+       case CASE(OLSH, TUINT32):
+       case CASE(OLSH, TPTR32):
+       case CASE(OLSH, TINT64):
+       case CASE(OLSH, TUINT64):
+       case CASE(OLSH, TPTR64):
+               a = ASLD;
+               break;
+
+       case CASE(ORSH, TUINT8):
+       case CASE(ORSH, TUINT16):
+       case CASE(ORSH, TUINT32):
+       case CASE(ORSH, TPTR32):
+       case CASE(ORSH, TUINT64):
+       case CASE(ORSH, TPTR64):
+               a = ASRD;
+               break;
+
+       case CASE(ORSH, TINT8):
+       case CASE(ORSH, TINT16):
+       case CASE(ORSH, TINT32):
+       case CASE(ORSH, TINT64):
+               a = ASRAD;
+               break;
+
+       // TODO(minux): handle rotates
+       //case CASE(ORROTC, TINT8):
+       //case CASE(ORROTC, TUINT8):
+       //case CASE(ORROTC, TINT16):
+       //case CASE(ORROTC, TUINT16):
+       //case CASE(ORROTC, TINT32):
+       //case CASE(ORROTC, TUINT32):
+       //case CASE(ORROTC, TINT64):
+       //case CASE(ORROTC, TUINT64):
+       //      a = 0//??? RLDC??
+       //      break;
+
+       case CASE(OHMUL, TINT64):
+               a = AMULHD;
+               break;
+       case CASE(OHMUL, TUINT64):
+       case CASE(OHMUL, TPTR64):
+               a = AMULHDU;
+               break;
+
+       case CASE(OMUL, TINT8):
+       case CASE(OMUL, TINT16):
+       case CASE(OMUL, TINT32):
+       case CASE(OMUL, TINT64):
+               a = AMULLD;
+               break;
+
+       case CASE(OMUL, TUINT8):
+       case CASE(OMUL, TUINT16):
+       case CASE(OMUL, TUINT32):
+       case CASE(OMUL, TPTR32):
+               // don't use word multiply, the high 32-bit are undefined.
+               // fallthrough
+       case CASE(OMUL, TUINT64):
+       case CASE(OMUL, TPTR64):
+               a = AMULLD; // for 64-bit multiplies, signedness doesn't matter.
+               break;
+
+       case CASE(OMUL, TFLOAT32):
+               a = AFMULS;
+               break;
+
+       case CASE(OMUL, TFLOAT64):
+               a = AFMUL;
+               break;
+
+       case CASE(ODIV, TINT8):
+       case CASE(ODIV, TINT16):
+       case CASE(ODIV, TINT32):
+       case CASE(ODIV, TINT64):
+               a = ADIVD;
+               break;
+
+       case CASE(ODIV, TUINT8):
+       case CASE(ODIV, TUINT16):
+       case CASE(ODIV, TUINT32):
+       case CASE(ODIV, TPTR32):
+       case CASE(ODIV, TUINT64):
+       case CASE(ODIV, TPTR64):
+               a = ADIVDU;
+               break;
+
+       case CASE(ODIV, TFLOAT32):
+               a = AFDIVS;
+               break;
+
+       case CASE(ODIV, TFLOAT64):
+               a = AFDIV;
+               break;
+
+       }
+       return a;
+}
+
+enum
+{
+       ODynam          = 1<<0,
+       OAddable        = 1<<1,
+};
+
+int
+xgen(Node *n, Node *a, int o)
+{
+       // TODO(minux)
+       USED(n); USED(a); USED(o);
+       return -1;
+}
+
+void
+sudoclean(void)
+{
+       return;
+}
+
+/*
+ * generate code to compute address of n,
+ * a reference to a (perhaps nested) field inside
+ * an array or struct.
+ * return 0 on failure, 1 on success.
+ * on success, leaves usable address in a.
+ *
+ * caller is responsible for calling sudoclean
+ * after successful sudoaddable,
+ * to release the register used for a.
+ */
+int
+sudoaddable(int as, Node *n, Addr *a)
+{
+       // TODO(minux)
+       USED(as); USED(n); USED(a);
+       return 0;
+}
diff --git a/src/cmd/9g/opt.h b/src/cmd/9g/opt.h
new file mode 100644 (file)
index 0000000..7f15b5a
--- /dev/null
@@ -0,0 +1,234 @@
+// Derived from Inferno utils/6c/gc.h
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include       "../gc/popt.h"
+
+#define        Z       N
+#define        Adr     Addr
+
+#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])
+#define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
+
+#define        CLOAD   5
+#define        CREF    5
+#define        CINF    1000
+#define        LOOP    3
+
+typedef        struct  Reg     Reg;
+typedef        struct  Rgn     Rgn;
+
+/*c2go
+extern Node *Z;
+enum
+{
+       CLOAD = 5,
+       CREF = 5,
+       CINF = 1000,
+       LOOP = 3,
+};
+
+uint32 BLOAD(Reg*);
+uint32 BSTORE(Reg*);
+uint32 LOAD(Reg*);
+uint32 STORE(Reg*);
+*/
+
+// A Reg is a wrapper around a single Prog (one instruction) that holds
+// register optimization information while the optimizer runs.
+// r->prog is the instruction.
+// r->prog->opt points back to r.
+struct Reg
+{
+       Flow    f;
+
+       Bits    set;            // regopt variables written by this instruction.
+       Bits    use1;           // regopt variables read by prog->from.
+       Bits    use2;           // regopt variables read by prog->to.
+
+       // refahead/refbehind are the regopt variables whose current
+       // value may be used in the following/preceding instructions
+       // up to a CALL (or the value is clobbered).
+       Bits    refbehind;
+       Bits    refahead;
+       // calahead/calbehind are similar, but for variables in
+       // instructions that are reachable after hitting at least one
+       // CALL.
+       Bits    calbehind;
+       Bits    calahead;
+       Bits    regdiff;
+       Bits    act;
+
+       uint64  regu;           // register used bitmap
+};
+#define        R       ((Reg*)0)
+/*c2go extern Reg *R; */
+
+#define        NRGN    600
+/*c2go enum { NRGN = 600 }; */
+
+// A Rgn represents a single regopt variable over a region of code
+// where a register could potentially be dedicated to that variable.
+// The code encompassed by a Rgn is defined by the flow graph,
+// starting at enter, flood-filling forward while varno is refahead
+// and backward while varno is refbehind, and following branches.  A
+// single variable may be represented by multiple disjoint Rgns and
+// each Rgn may choose a different register for that variable.
+// Registers are allocated to regions greedily in order of descending
+// cost.
+struct Rgn
+{
+       Reg*    enter;
+       short   cost;
+       short   varno;
+       short   regno;
+};
+
+EXTERN int32   exregoffset;            // not set
+EXTERN int32   exfregoffset;           // not set
+EXTERN Reg     zreg;
+EXTERN Rgn     region[NRGN];
+EXTERN Rgn*    rgp;
+EXTERN int     nregion;
+EXTERN int     nvar;
+EXTERN int32   regbits;
+EXTERN int32   exregbits;              // TODO(austin) not used; remove
+EXTERN Bits    externs;
+EXTERN Bits    params;
+EXTERN Bits    consts;
+EXTERN Bits    addrs;
+EXTERN Bits    ivar;
+EXTERN Bits    ovar;
+EXTERN int     change;
+EXTERN int32   maxnr;
+
+EXTERN struct
+{
+       int32   ncvtreg;
+       int32   nspill;
+       int32   ndelmov;
+       int32   nvar;
+} ostats;
+
+/*
+ * reg.c
+ */
+int    rcmp(const void*, const void*);
+void   regopt(Prog*);
+void   addmove(Reg*, int, int, int);
+Bits   mkvar(Reg*, Adr*);
+void   prop(Reg*, Bits, Bits);
+void   synch(Reg*, Bits);
+uint64 allreg(uint64, Rgn*);
+void   paint1(Reg*, int);
+uint64 paint2(Reg*, int, int);
+void   paint3(Reg*, int, uint64, int);
+void   addreg(Adr*, int);
+void   dumpone(Flow*, int);
+void   dumpit(char*, Flow*, int);
+
+/*
+ * peep.c
+ */
+void   peep(Prog*);
+void   excise(Flow*);
+int    copyu(Prog*, Adr*, Adr*);
+
+uint64 RtoB(int);
+uint64 FtoB(int);
+int    BtoR(uint64);
+int    BtoF(uint64);
+
+/*
+ * prog.c
+ */
+typedef struct ProgInfo ProgInfo;
+struct ProgInfo
+{
+       uint32 flags; // the bits below
+       uint64 reguse; // registers implicitly used by this instruction
+       uint64 regset; // registers implicitly set by this instruction
+       uint64 regindex; // registers used by addressing mode
+};
+
+enum
+{
+       // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
+       Pseudo = 1<<1,
+       
+       // There's nothing to say about the instruction,
+       // but it's still okay to see.
+       OK = 1<<2,
+
+       // Size of right-side write, or right-side read if no write.
+       SizeB = 1<<3,
+       SizeW = 1<<4,
+       SizeL = 1<<5,
+       SizeQ = 1<<6,
+       SizeF = 1<<7, // float aka float32
+       SizeD = 1<<8, // double aka float64
+
+       // Left side (Prog.from): address taken, read, write.
+       LeftAddr = 1<<9,
+       LeftRead = 1<<10,
+       LeftWrite = 1<<11,
+
+       // Register in middle (Prog.reg); only ever read.
+       RegRead = 1<<12,
+       CanRegRead = 1<<13,
+
+       // Right side (Prog.to): address taken, read, write.
+       RightAddr = 1<<14,
+       RightRead = 1<<15,
+       RightWrite = 1<<16,
+
+       // Instruction updates whichever of from/to is type D_OREG
+       PostInc = 1<<17,
+
+       // Instruction kinds
+       Move = 1<<18, // straight move
+       Conv = 1<<19, // size conversion
+       Cjmp = 1<<20, // conditional jump
+       Break = 1<<21, // breaks control flow (no fallthrough)
+       Call = 1<<22, // function call
+       Jump = 1<<23, // jump
+       Skip = 1<<24, // data instruction
+};
+
+void proginfo(ProgInfo*, Prog*);
+
+// To allow use of AJMP, ACALL, ARET in ../gc/popt.c.
+enum
+{
+       AJMP = ABR,
+       ACALL = ABL,
+       ARET = ARETURN,
+};
similarity index 65%
rename from src/cmd/cc/bits.c
rename to src/cmd/9g/peep.c
index 4496d65e77dd8b123a80dac62927e33a1ecf066d..ec314d6338ee8880e86c2913bd047ef65ff11dbb 100644 (file)
@@ -1,5 +1,5 @@
-// Inferno utils/cc/bits.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/bits.c
+// Derived from Inferno utils/6c/peep.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
 //
 //     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
 //     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#include       <u.h>
-#include       "cc.h"
+#include <u.h>
+#include <libc.h>
+#include "gg.h"
+#include "opt.h"
 
-Bits
-bor(Bits a, Bits b)
+void
+peep(Prog *p)
 {
-       Bits c;
-       int i;
-
-       for(i=0; i<BITS; i++)
-               c.b[i] = a.b[i] | b.b[i];
-       return c;
+       USED(p);
+       // TODO(minux)
+       return;
 }
 
-Bits
-band(Bits a, Bits b)
+void
+excise(Flow *r)
 {
-       Bits c;
-       int i;
-
-       for(i=0; i<BITS; i++)
-               c.b[i] = a.b[i] & b.b[i];
-       return c;
+       Prog *p, *l;
+
+       p = r->prog;
+       if(debug['P'] && debug['v'])
+               print("%P ===delete===\n", p);
+       l = p->link;
+       *p = zprog;
+       p->as = ANOP;
+       p->link = l;
+       ostats.ndelmov++;
 }
 
-/*
-Bits
-bnot(Bits a)
+int
+regtyp(Adr *a)
 {
-       Bits c;
-       int i;
-
-       for(i=0; i<BITS; i++)
-               c.b[i] = ~a.b[i];
-       return c;
+       switch(a->type) {
+       default:
+               return 0;
+       case D_REG:
+       case D_FREG:
+               return 1;
+       }
 }
-*/
 
 int
-bany(Bits *a)
+sameaddr(Addr *a, Addr *v)
 {
-       int i;
-
-       for(i=0; i<BITS; i++)
-               if(a->b[i])
+       if(a->type != v->type)
+               return 0;
+       if(regtyp(v) && a->reg == v->reg)
+               return 1;
+       if(v->type == D_AUTO || v->type == D_PARAM)
+               if(v->offset == a->offset)
                        return 1;
        return 0;
 }
 
 int
-beq(Bits a, Bits b)
-{
-       int i;
-
-       for(i=0; i<BITS; i++)
-               if(a.b[i] != b.b[i])
-                       return 0;
-       return 1;
-}
-
-int
-bnum(Bits a)
-{
-       int i;
-       int32 b;
-
-       for(i=0; i<BITS; i++)
-               if(b = a.b[i])
-                       return 32*i + bitno(b);
-       diag(Z, "bad in bnum");
-       return 0;
-}
-
-Bits
-blsh(uint n)
+smallindir(Addr *a, Addr *reg)
 {
-       Bits c;
-
-       c = zbits;
-       c.b[n/32] = 1L << (n%32);
-       return c;
+       return reg->type == D_REG && a->type == D_OREG &&
+               a->reg == reg->reg &&
+               0 <= a->offset && a->offset < 4096;
 }
 
 int
-bset(Bits a, uint n)
+stackaddr(Addr *a)
 {
-       if(a.b[n/32] & (1L << (n%32)))
-               return 1;
-       return 0;
+       return a->type == D_REG && a->reg == REGSP;
 }
diff --git a/src/cmd/9g/prog.c b/src/cmd/9g/prog.c
new file mode 100644 (file)
index 0000000..e3e50f2
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright 2014 The Go 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>
+#include "gg.h"
+#include "opt.h"
+
+enum {
+       LeftRdwr = LeftRead | LeftWrite,
+       RightRdwr = RightRead | RightWrite,
+};
+
+// This table gives the basic information about instruction
+// generated by the compiler and processed in the optimizer.
+// See opt.h for bit definitions.
+//
+// Instructions not generated need not be listed.
+// As an exception to that rule, we typically write down all the
+// size variants of an operation even if we just use a subset.
+//
+// The table is formatted for 8-space tabs.
+static ProgInfo progtable[ALAST] = {
+       [ATYPE]=        {Pseudo | Skip},
+       [ATEXT]=        {Pseudo},
+       [AFUNCDATA]=    {Pseudo},
+       [APCDATA]=      {Pseudo},
+       [AUNDEF]=       {Break},
+       [AUSEFIELD]=    {OK},
+       [ACHECKNIL]=    {LeftRead},
+       [AVARDEF]=      {Pseudo | RightWrite},
+       [AVARKILL]=     {Pseudo | RightWrite},
+
+       // NOP is an internal no-op that also stands
+       // for USED and SET annotations, not the Power opcode.
+       [ANOP]=         {LeftRead | RightWrite},
+
+       // Integer
+       [AADD]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [ASUB]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [ANEG]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [AAND]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [AOR]=          {SizeQ | LeftRead | RegRead | RightWrite},
+       [AXOR]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [AMULLD]=       {SizeQ | LeftRead | RegRead | RightWrite},
+       [AMULLW]=       {SizeL | LeftRead | RegRead | RightWrite},
+       [AMULHD]=       {SizeL | LeftRead | RegRead | RightWrite},
+       [AMULHDU]=      {SizeL | LeftRead | RegRead | RightWrite},
+       [ADIVD]=        {SizeQ | LeftRead | RegRead | RightWrite},
+       [ADIVDU]=       {SizeQ | LeftRead | RegRead | RightWrite},
+       [ASLD]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [ASRD]=         {SizeQ | LeftRead | RegRead | RightWrite},
+       [ASRAD]=        {SizeQ | LeftRead | RegRead | RightWrite},
+       [ACMP]=         {SizeQ | LeftRead | RightRead},
+       [ACMPU]=        {SizeQ | LeftRead | RightRead},
+       [ATD]=          {SizeQ | RightRead},
+
+       // Floating point.
+       [AFADD]=        {SizeD | LeftRead | RegRead | RightWrite},
+       [AFADDS]=       {SizeF | LeftRead | RegRead | RightWrite},
+       [AFSUB]=        {SizeD | LeftRead | RegRead | RightWrite},
+       [AFSUBS]=       {SizeF | LeftRead | RegRead | RightWrite},
+       [AFMUL]=        {SizeD | LeftRead | RegRead | RightWrite},
+       [AFMULS]=       {SizeF | LeftRead | RegRead | RightWrite},
+       [AFDIV]=        {SizeD | LeftRead | RegRead | RightWrite},
+       [AFDIVS]=       {SizeF | LeftRead | RegRead | RightWrite},
+       [AFCTIDZ]=      {SizeF | LeftRead | RegRead | RightWrite},
+       [AFCFID]=       {SizeF | LeftRead | RegRead | RightWrite},
+       [AFCMPU]=       {SizeD | LeftRead | RightRead},
+       [AFRSP]=        {SizeD | LeftRead | RightWrite | Conv},
+
+       // Moves
+       [AMOVB]=        {SizeB | LeftRead | RightWrite | Move | Conv},
+       [AMOVBU]=       {SizeB | LeftRead | RightWrite | Move | Conv | PostInc},
+       [AMOVBZ]=       {SizeB | LeftRead | RightWrite | Move | Conv},
+       [AMOVH]=        {SizeW | LeftRead | RightWrite | Move | Conv},
+       [AMOVHU]=       {SizeW | LeftRead | RightWrite | Move | Conv | PostInc},
+       [AMOVHZ]=       {SizeW | LeftRead | RightWrite | Move | Conv},
+       [AMOVW]=        {SizeL | LeftRead | RightWrite | Move | Conv},
+       // there is no AMOVWU.
+       [AMOVWZU]=      {SizeL | LeftRead | RightWrite | Move | Conv | PostInc},
+       [AMOVWZ]=       {SizeL | LeftRead | RightWrite | Move | Conv},
+       [AMOVD]=        {SizeQ | LeftRead | RightWrite | Move},
+       [AMOVDU]=       {SizeQ | LeftRead | RightWrite | Move | PostInc},
+       [AFMOVS]=       {SizeF | LeftRead | RightWrite | Move | Conv},
+       [AFMOVD]=       {SizeD | LeftRead | RightWrite | Move},
+
+       // Jumps
+       [ABR]=          {Jump | Break},
+       [ABL]=          {Call},
+       [ABEQ]=         {Cjmp},
+       [ABNE]=         {Cjmp},
+       [ABGE]=         {Cjmp},
+       [ABLT]=         {Cjmp},
+       [ABGT]=         {Cjmp},
+       [ABLE]=         {Cjmp},
+       [ARETURN]=      {Break},
+
+       [ADUFFZERO]=    {Call},
+       [ADUFFCOPY]=    {Call},
+};
+
+void
+proginfo(ProgInfo *info, Prog *p)
+{
+       *info = progtable[p->as];
+       if(info->flags == 0) {
+               *info = progtable[AADD];
+               fatal("proginfo: unknown instruction %P", p);
+       }
+
+       if((info->flags & RegRead) && p->reg == NREG) {
+               info->flags &= ~RegRead;
+               info->flags |= /*CanRegRead |*/ RightRead;
+       }
+
+       if((p->from.type == D_OREG || p->from.type == D_CONST) && p->from.reg != NREG) {
+               info->regindex |= RtoB(p->from.reg);
+               if(info->flags & PostInc) {
+                       info->regset |= RtoB(p->from.reg);
+               }
+       }
+       if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) {
+               info->regindex |= RtoB(p->to.reg);
+               if(info->flags & PostInc) {
+                       info->regset |= RtoB(p->to.reg);
+               }
+       }
+
+       if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) {
+               info->flags &= ~LeftRead;
+               info->flags |= LeftAddr;
+       }
+
+       if(p->as == ADUFFZERO) {
+               info->reguse |= RtoB(0) | RtoB(2);
+               info->regset |= RtoB(2);
+       }
+       if(p->as == ADUFFCOPY) {
+               info->reguse |= RtoB(0) | RtoB(2) | RtoB(3);
+               info->regset |= RtoB(2) | RtoB(3);
+       }
+}
diff --git a/src/cmd/9g/reg.c b/src/cmd/9g/reg.c
new file mode 100644 (file)
index 0000000..2e546a9
--- /dev/null
@@ -0,0 +1,1346 @@
+// Derived from Inferno utils/6c/reg.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include "gg.h"
+#include "opt.h"
+
+#define        NREGVAR 64      /* 32 general + 32 floating */
+#define        REGBITS ((uint64)0xffffffffffffffffull)
+/*c2go enum {
+       NREGVAR = 64,
+       REGBITS = 0xffffffffffffffff,
+};
+*/
+
+static Reg*    firstr;
+static int     first   = 1;
+
+int
+rcmp(const void *a1, const void *a2)
+{
+       Rgn *p1, *p2;
+       int c1, c2;
+
+       p1 = (Rgn*)a1;
+       p2 = (Rgn*)a2;
+       c1 = p2->cost;
+       c2 = p1->cost;
+       if(c1 -= c2)
+               return c1;
+       return p2->varno - p1->varno;
+}
+
+static void
+setaddrs(Bits bit)
+{
+       int i, n;
+       Var *v;
+       Node *node;
+
+       while(bany(&bit)) {
+               // convert each bit to a variable
+               i = bnum(bit);
+               node = var[i].node;
+               n = var[i].name;
+               biclr(&bit, i);
+
+               // disable all pieces of that variable
+               for(i=0; i<nvar; i++) {
+                       v = var+i;
+                       if(v->node == node && v->name == n)
+                               v->addr = 2;
+               }
+       }
+}
+
+static char* regname[] = {
+       ".R0",
+       ".R1",
+       ".R2",
+       ".R3",
+       ".R4",
+       ".R5",
+       ".R6",
+       ".R7",
+       ".R8",
+       ".R9",
+       ".R10",
+       ".R11",
+       ".R12",
+       ".R13",
+       ".R14",
+       ".R15",
+       ".R16",
+       ".R17",
+       ".R18",
+       ".R19",
+       ".R20",
+       ".R21",
+       ".R22",
+       ".R23",
+       ".R24",
+       ".R25",
+       ".R26",
+       ".R27",
+       ".R28",
+       ".R29",
+       ".R30",
+       ".R31",
+       ".F0",
+       ".F1",
+       ".F2",
+       ".F3",
+       ".F4",
+       ".F5",
+       ".F6",
+       ".F7",
+       ".F8",
+       ".F9",
+       ".F10",
+       ".F11",
+       ".F12",
+       ".F13",
+       ".F14",
+       ".F15",
+       ".F16",
+       ".F17",
+       ".F18",
+       ".F19",
+       ".F20",
+       ".F21",
+       ".F22",
+       ".F23",
+       ".F24",
+       ".F25",
+       ".F26",
+       ".F27",
+       ".F28",
+       ".F29",
+       ".F30",
+       ".F31",
+};
+
+static Node* regnodes[NREGVAR];
+
+static void walkvardef(Node *n, Reg *r, int active);
+
+void
+regopt(Prog *firstp)
+{
+       Reg *r, *r1;
+       Prog *p;
+       Graph *g;
+       ProgInfo info;
+       int i, z, active;
+       uint64 vreg, usedreg;
+       Bits bit;
+
+       if(first) {
+               fmtinstall('Q', Qconv);
+               first = 0;
+       }
+
+       mergetemp(firstp);
+
+       /*
+        * control flow is more complicated in generated go code
+        * than in generated c code.  define pseudo-variables for
+        * registers, so we have complete register usage information.
+        */
+       nvar = NREGVAR;
+       memset(var, 0, NREGVAR*sizeof var[0]);
+       for(i=0; i<NREGVAR; i++) {
+               if(regnodes[i] == N)
+                       regnodes[i] = newname(lookup(regname[i]));
+               var[i].node = regnodes[i];
+       }
+
+       // Exclude registers with fixed functions
+       regbits = (1<<D_R0)|RtoB(REGSP)|RtoB(REGG);
+       // Also exclude floating point registers with fixed constants
+       regbits |= FtoB(D_F0+27)|FtoB(D_F0+28)|FtoB(D_F0+29)|FtoB(D_F0+30)|FtoB(D_F0+31);
+       externs = zbits;
+       params = zbits;
+       consts = zbits;
+       addrs = zbits;
+       ivar = zbits;
+       ovar = zbits;
+
+       /*
+        * pass 1
+        * build aux data structure
+        * allocate pcs
+        * find use and set of variables
+        */
+       g = flowstart(firstp, sizeof(Reg));
+       if(g == nil) {
+               for(i=0; i<nvar; i++)
+                       var[i].node->opt = nil;
+               return;
+       }
+
+       firstr = (Reg*)g->start;
+
+       for(r = firstr; r != R; r = (Reg*)r->f.link) {
+               p = r->f.prog;
+               if(p->as == AVARDEF || p->as == AVARKILL)
+                       continue;
+               proginfo(&info, p);
+
+               // Avoid making variables for direct-called functions.
+               if(p->as == ABL && p->to.name == D_EXTERN)
+                       continue;
+
+               // from vs to doesn't matter for registers
+               r->use1.b[0] |= info.reguse | info.regindex;
+               r->set.b[0] |= info.regset;
+
+               // Compute used register for from
+               bit = mkvar(r, &p->from);
+               if(info.flags & LeftAddr)
+                       setaddrs(bit);
+               if(info.flags & LeftRead)
+                       for(z=0; z<BITS; z++)
+                               r->use1.b[z] |= bit.b[z];
+
+               // Compute used register for reg
+               if(info.flags & RegRead) {
+                       if(p->from.type != D_FREG)
+                               r->use1.b[0] |= RtoB(p->reg);
+                       else
+                               r->use1.b[0] |= FtoB(D_F0+p->reg);
+               }
+
+               // Currently we never generate three register forms.
+               // If we do, this will need to change.
+               if(p->from3.type != D_NONE)
+                       fatal("regopt not implemented for from3");
+
+               // Compute used register for to
+               bit = mkvar(r, &p->to);
+               if(info.flags & RightAddr)
+                       setaddrs(bit);
+               if(info.flags & RightRead)
+                       for(z=0; z<BITS; z++)
+                               r->use2.b[z] |= bit.b[z];
+               if(info.flags & RightWrite)
+                       for(z=0; z<BITS; z++)
+                               r->set.b[z] |= bit.b[z];
+       }
+
+       for(i=0; i<nvar; i++) {
+               Var *v = var+i;
+               if(v->addr) {
+                       bit = blsh(i);
+                       for(z=0; z<BITS; z++)
+                               addrs.b[z] |= bit.b[z];
+               }
+
+               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->f, 1);
+
+       /*
+        * pass 2
+        * find looping structure
+        */
+       flowrpo(g);
+
+       if(debug['R'] && debug['v'])
+               dumpit("pass2", &firstr->f, 1);
+
+       /*
+        * pass 2.5
+        * iterate propagating fat vardef covering forward
+        * r->act records vars with a VARDEF since the last CALL.
+        * (r->act will be reused in pass 5 for something else,
+        * but we'll be done with it by then.)
+        */
+       active = 0;
+       for(r = firstr; r != R; r = (Reg*)r->f.link) {
+               r->f.active = 0;
+               r->act = zbits;
+       }
+       for(r = firstr; r != R; r = (Reg*)r->f.link) {
+               p = r->f.prog;
+               if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) {
+                       active++;
+                       walkvardef(p->to.node, r, active);
+               }
+       }
+
+       /*
+        * pass 3
+        * iterate propagating usage
+        *      back until flow graph is complete
+        */
+loop1:
+       change = 0;
+       for(r = firstr; r != R; r = (Reg*)r->f.link)
+               r->f.active = 0;
+       for(r = firstr; r != R; r = (Reg*)r->f.link)
+               if(r->f.prog->as == ARET)
+                       prop(r, zbits, zbits);
+loop11:
+       /* pick up unreachable code */
+       i = 0;
+       for(r = firstr; r != R; r = r1) {
+               r1 = (Reg*)r->f.link;
+               if(r1 && r1->f.active && !r->f.active) {
+                       prop(r, zbits, zbits);
+                       i = 1;
+               }
+       }
+       if(i)
+               goto loop11;
+       if(change)
+               goto loop1;
+
+       if(debug['R'] && debug['v'])
+               dumpit("pass3", &firstr->f, 1);
+
+       /*
+        * pass 4
+        * iterate propagating register/variable synchrony
+        *      forward until graph is complete
+        */
+loop2:
+       change = 0;
+       for(r = firstr; r != R; r = (Reg*)r->f.link)
+               r->f.active = 0;
+       synch(firstr, zbits);
+       if(change)
+               goto loop2;
+
+       if(debug['R'] && debug['v'])
+               dumpit("pass4", &firstr->f, 1);
+
+       /*
+        * pass 4.5
+        * move register pseudo-variables into regu.
+        */
+       for(r = firstr; r != R; r = (Reg*)r->f.link) {
+               r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;
+
+               r->set.b[0] &= ~REGBITS;
+               r->use1.b[0] &= ~REGBITS;
+               r->use2.b[0] &= ~REGBITS;
+               r->refbehind.b[0] &= ~REGBITS;
+               r->refahead.b[0] &= ~REGBITS;
+               r->calbehind.b[0] &= ~REGBITS;
+               r->calahead.b[0] &= ~REGBITS;
+               r->regdiff.b[0] &= ~REGBITS;
+               r->act.b[0] &= ~REGBITS;
+       }
+
+       if(debug['R'] && debug['v'])
+               dumpit("pass4.5", &firstr->f, 1);
+
+       /*
+        * pass 5
+        * isolate regions
+        * calculate costs (paint1)
+        */
+       r = firstr;
+       if(r) {
+               for(z=0; z<BITS; z++)
+                       bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
+                         ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
+               if(bany(&bit) && !r->f.refset) {
+                       // should never happen - all variables are preset
+                       if(debug['w'])
+                               print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
+                       r->f.refset = 1;
+               }
+       }
+       for(r = firstr; r != R; r = (Reg*)r->f.link)
+               r->act = zbits;
+       rgp = region;
+       nregion = 0;
+       for(r = firstr; r != R; r = (Reg*)r->f.link) {
+               for(z=0; z<BITS; z++)
+                       bit.b[z] = r->set.b[z] &
+                         ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
+               if(bany(&bit) && !r->f.refset) {
+                       if(debug['w'])
+                               print("%L: set and not used: %Q\n", r->f.prog->lineno, bit);
+                       r->f.refset = 1;
+                       excise(&r->f);
+               }
+               for(z=0; z<BITS; z++)
+                       bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
+               while(bany(&bit)) {
+                       i = bnum(bit);
+                       rgp->enter = r;
+                       rgp->varno = i;
+                       change = 0;
+                       paint1(r, i);
+                       biclr(&bit, i);
+                       if(change <= 0)
+                               continue;
+                       rgp->cost = change;
+                       nregion++;
+                       if(nregion >= NRGN) {
+                               if(debug['R'] && debug['v'])
+                                       print("too many regions\n");
+                               goto brk;
+                       }
+                       rgp++;
+               }
+       }
+brk:
+       qsort(region, nregion, sizeof(region[0]), rcmp);
+
+       if(debug['R'] && debug['v'])
+               dumpit("pass5", &firstr->f, 1);
+
+       /*
+        * pass 6
+        * determine used registers (paint2)
+        * replace code (paint3)
+        */
+       rgp = region;
+       if(debug['R'] && debug['v'])
+               print("\nregisterizing\n");
+       for(i=0; i<nregion; i++) {
+               if(debug['R'] && debug['v'])
+                       print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
+               bit = blsh(rgp->varno);
+               usedreg = paint2(rgp->enter, rgp->varno, 0);
+               vreg = allreg(usedreg, rgp);
+               if(rgp->regno != 0) {
+                       if(debug['R'] && debug['v']) {
+                               Var *v;
+
+                               v = var + rgp->varno;
+                               print("registerize %N+%lld (bit=%2d et=%2E) in %R usedreg=%llx vreg=%llx\n",
+                                               v->node, v->offset, rgp->varno, v->etype, rgp->regno, usedreg, vreg);
+                       }
+                       paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
+               }
+               rgp++;
+       }
+
+       /*
+        * free aux structures. peep allocates new ones.
+        */
+       for(i=0; i<nvar; i++)
+               var[i].node->opt = nil;
+       flowend(g);
+       firstr = R;
+
+       if(debug['R'] && debug['v']) {
+               // Rebuild flow graph, since we inserted instructions
+               g = flowstart(firstp, sizeof(Reg));
+               firstr = (Reg*)g->start;
+               dumpit("pass6", &firstr->f, 1);
+               flowend(g);
+               firstr = R;
+       }
+
+       /*
+        * pass 7
+        * peep-hole on basic block
+        */
+       if(!debug['R'] || debug['P'])
+               peep(firstp);
+
+       /*
+        * eliminate nops
+        */
+       for(p=firstp; p!=P; p=p->link) {
+               while(p->link != P && p->link->as == ANOP)
+                       p->link = p->link->link;
+               if(p->to.type == D_BRANCH)
+                       while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
+                               p->to.u.branch = p->to.u.branch->link;
+       }
+
+       if(debug['R']) {
+               if(ostats.ncvtreg ||
+                  ostats.nspill ||
+                  ostats.ndelmov ||
+                  ostats.nvar ||
+                  0)
+                       print("\nstats\n");
+
+               if(ostats.ncvtreg)
+                       print(" %4d cvtreg\n", ostats.ncvtreg);
+               if(ostats.nspill)
+                       print(" %4d spill\n", ostats.nspill);
+               if(ostats.ndelmov)
+                       print(" %4d delmov\n", ostats.ndelmov);
+               if(ostats.nvar)
+                       print(" %4d var\n", ostats.nvar);
+
+               memset(&ostats, 0, sizeof(ostats));
+       }
+
+       return;
+}
+
+static void
+walkvardef(Node *n, Reg *r, int active)
+{
+       Reg *r1, *r2;
+       int bn;
+       Var *v;
+       
+       for(r1=r; r1!=R; r1=(Reg*)r1->f.s1) {
+               if(r1->f.active == active)
+                       break;
+               r1->f.active = active;
+               if(r1->f.prog->as == AVARKILL && r1->f.prog->to.node == n)
+                       break;
+               for(v=n->opt; v!=nil; v=v->nextinnode) {
+                       bn = v - var;
+                       biset(&r1->act, bn);
+               }
+               if(r1->f.prog->as == ABL)
+                       break;
+       }
+
+       for(r2=r; r2!=r1; r2=(Reg*)r2->f.s1)
+               if(r2->f.s2 != nil)
+                       walkvardef(n, (Reg*)r2->f.s2, active);
+}
+
+/*
+ * add mov b,rn
+ * just after r
+ */
+void
+addmove(Reg *r, int bn, int rn, int f)
+{
+       Prog *p, *p1, *p2;
+       Adr *a;
+       Var *v;
+
+       p1 = mal(sizeof(*p1));
+       *p1 = zprog;
+       p = r->f.prog;
+       
+       // If there's a stack fixup coming (ADD $n,R1 after BL newproc or BL deferproc),
+       // delay the load until after the fixup.
+       p2 = p->link;
+       if(p2 && p2->as == AADD && p2->to.reg == REGSP && p2->to.type == D_REG)
+               p = p2;
+
+       p1->link = p->link;
+       p->link = p1;
+       p1->lineno = p->lineno;
+
+       v = var + bn;
+
+       a = &p1->to;
+       a->name = v->name;
+       a->node = v->node;
+       a->sym = linksym(v->node->sym);
+       a->offset = v->offset;
+       a->etype = v->etype;
+       a->type = D_OREG;
+       if(a->etype == TARRAY || a->sym == nil)
+               a->type = D_CONST;
+
+       if(v->addr)
+               fatal("addmove: shouldn't be doing this %A\n", a);
+
+       switch(v->etype) {
+       default:
+               print("What is this %E\n", v->etype);
+
+       case TINT8:
+               p1->as = AMOVB;
+               break;
+       case TBOOL:
+       case TUINT8:
+//print("movbu %E %d %S\n", v->etype, bn, v->sym);
+               p1->as = AMOVBZ;
+               break;
+       case TINT16:
+               p1->as = AMOVH;
+               break;
+       case TUINT16:
+               p1->as = AMOVHZ;
+               break;
+       case TINT32:
+               p1->as = AMOVW;
+               break;
+       case TUINT32:
+       case TPTR32:
+               p1->as = AMOVWZ;
+               break;
+       case TINT64:
+       case TUINT64:
+       case TPTR64:
+               p1->as = AMOVD;
+               break;
+       case TFLOAT32:
+               p1->as = AFMOVS;
+               break;
+       case TFLOAT64:
+               p1->as = AFMOVD;
+               break;
+       }
+
+       p1->from.type = D_REG;
+       p1->from.reg = rn;
+       if(rn >= NREG) {
+               p1->from.type = D_FREG;
+               p1->from.reg = rn-NREG;
+       }
+       if(!f) {
+               p1->from = *a;
+               *a = zprog.from;
+               a->type = D_REG;
+               a->reg = rn;
+               if(rn >= NREG) {
+                       a->type = D_FREG;
+                       a->reg = rn-NREG;
+               }
+               if(v->etype == TUINT8 || v->etype == TBOOL)
+                       p1->as = AMOVBZ;
+               if(v->etype == TUINT16)
+                       p1->as = AMOVHZ;
+       }
+       if(debug['R'])
+               print("%P\t.a%P\n", p, p1);
+       ostats.nspill++;
+}
+
+static int
+overlap(int64 o1, int w1, int64 o2, int w2)
+{
+       int64 t1, t2;
+
+       t1 = o1+w1;
+       t2 = o2+w2;
+
+       if(!(t1 > o2 && t2 > o1))
+               return 0;
+
+       return 1;
+}
+
+Bits
+mkvar(Reg *r, Adr *a)
+{
+       USED(r);
+       Var *v;
+       int i, t, n, et, z, flag;
+       int64 w;
+       int64 o;
+       Bits bit;
+       Node *node;
+
+       // mark registers used
+       t = a->type;
+       switch(t) {
+       default:
+               print("type %d %d %D\n", t, a->name, a);
+               goto none;
+
+       case D_NONE:
+               goto none;
+
+       case D_BRANCH:
+       case D_CONST:
+       case D_FCONST:
+       case D_SCONST:
+       case D_SPR:
+       case D_OREG:
+               break;
+
+       case D_REG:
+               if(a->reg != NREG) {
+                       bit = zbits;
+                       bit.b[0] = RtoB(a->reg);
+                       return bit;
+               }
+               break;
+
+       case D_FREG:
+               if(a->reg != NREG) {
+                       bit = zbits;
+                       bit.b[0] = FtoB(D_F0+a->reg);
+                       return bit;
+               }
+               break;
+       }
+
+       switch(a->name) {
+       default:
+               goto none;
+
+       case D_EXTERN:
+       case D_STATIC:
+       case D_AUTO:
+       case D_PARAM:
+               n = a->name;
+               break;
+       }
+
+       node = a->node;
+       if(node == N || node->op != ONAME || node->orig == N)
+               goto none;
+       node = node->orig;
+       if(node->orig != node)
+               fatal("%D: bad node", a);
+       if(node->sym == S || node->sym->name[0] == '.')
+               goto none;
+       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++) {
+               v = var+i;
+               if(v->node == node && v->name == n) {
+                       if(v->offset == o)
+                       if(v->etype == et)
+                       if(v->width == w)
+                               return blsh(i);
+
+                       // if they overlap, disable both
+                       if(overlap(v->offset, v->width, o, w)) {
+                               v->addr = 1;
+                               flag = 1;
+                       }
+               }
+       }
+
+       switch(et) {
+       case 0:
+       case TFUNC:
+               goto none;
+       }
+
+       if(nvar >= NVAR) {
+               if(debug['w'] > 1 && node != N)
+                       fatal("variable not optimized: %#N", node);
+               
+               // If we're not tracking a word in a variable, mark the rest as
+               // having its address taken, so that we keep the whole thing
+               // live at all calls. otherwise we might optimize away part of
+               // a variable but not all of it.
+               for(i=0; i<nvar; i++) {
+                       v = var+i;
+                       if(v->node == node)
+                               v->addr = 1;
+               }
+               goto none;
+       }
+
+       i = nvar;
+       nvar++;
+       v = var+i;
+       v->offset = o;
+       v->name = n;
+       v->etype = et;
+       v->width = w;
+       v->addr = flag;         // funny punning
+       v->node = node;
+       
+       // node->opt is the head of a linked list
+       // of Vars within the given Node, so that
+       // we can start at a Var and find all the other
+       // Vars in the same Go variable.
+       v->nextinnode = node->opt;
+       node->opt = v;
+
+       bit = blsh(i);
+       if(n == D_EXTERN || n == D_STATIC)
+               for(z=0; z<BITS; z++)
+                       externs.b[z] |= bit.b[z];
+       if(n == D_PARAM)
+               for(z=0; z<BITS; z++)
+                       params.b[z] |= bit.b[z];
+
+       if(node->class == PPARAM)
+               for(z=0; z<BITS; z++)
+                       ivar.b[z] |= bit.b[z];
+       if(node->class == PPARAMOUT)
+               for(z=0; z<BITS; z++)
+                       ovar.b[z] |= bit.b[z];
+
+       // Treat values with their address taken as live at calls,
+       // because the garbage collector's liveness analysis in ../gc/plive.c does.
+       // These must be consistent or else we will elide stores and the garbage
+       // collector will see uninitialized data.
+       // The typical case where our own analysis is out of sync is when the
+       // node appears to have its address taken but that code doesn't actually
+       // get generated and therefore doesn't show up as an address being
+       // taken when we analyze the instruction stream.
+       // One instance of this case is when a closure uses the same name as
+       // an outer variable for one of its own variables declared with :=.
+       // The parser flags the outer variable as possibly shared, and therefore
+       // sets addrtaken, even though it ends up not being actually shared.
+       // If we were better about _ elision, _ = &x would suffice too.
+       // The broader := in a closure problem is mentioned in a comment in
+       // closure.c:/^typecheckclosure and dcl.c:/^oldname.
+       if(node->addrtaken)
+               v->addr = 1;
+
+       // Disable registerization for globals, because:
+       // (1) we might panic at any time and we want the recovery code
+       // to see the latest values (issue 1304).
+       // (2) we don't know what pointers might point at them and we want
+       // loads via those pointers to see updated values and vice versa (issue 7995).
+       //
+       // Disable registerization for results if using defer, because the deferred func
+       // might recover and return, causing the current values to be used.
+       if(node->class == PEXTERN || (hasdefer && node->class == PPARAMOUT))
+               v->addr = 1;
+
+       if(debug['R'])
+               print("bit=%2d et=%2E w=%lld+%lld %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+       ostats.nvar++;
+
+       return bit;
+
+none:
+       return zbits;
+}
+
+void
+prop(Reg *r, Bits ref, Bits cal)
+{
+       Reg *r1, *r2;
+       int z, i, j;
+       Var *v, *v1;
+
+       for(r1 = r; r1 != R; r1 = (Reg*)r1->f.p1) {
+               for(z=0; z<BITS; z++) {
+                       ref.b[z] |= r1->refahead.b[z];
+                       if(ref.b[z] != r1->refahead.b[z]) {
+                               r1->refahead.b[z] = ref.b[z];
+                               change++;
+                       }
+                       cal.b[z] |= r1->calahead.b[z];
+                       if(cal.b[z] != r1->calahead.b[z]) {
+                               r1->calahead.b[z] = cal.b[z];
+                               change++;
+                       }
+               }
+               switch(r1->f.prog->as) {
+               case ABL:
+                       if(noreturn(r1->f.prog))
+                               break;
+
+                       // Mark all input variables (ivar) as used, because that's what the
+                       // liveness bitmaps say. The liveness bitmaps say that so that a
+                       // panic will not show stale values in the parameter dump.
+                       // Mark variables with a recent VARDEF (r1->act) as used,
+                       // so that the optimizer flushes initializations to memory,
+                       // so that if a garbage collection happens during this CALL,
+                       // the collector will see initialized memory. Again this is to
+                       // match what the liveness bitmaps say.
+                       for(z=0; z<BITS; z++) {
+                               cal.b[z] |= ref.b[z] | externs.b[z] | ivar.b[z] | r1->act.b[z];
+                               ref.b[z] = 0;
+                       }
+                       
+                       // cal.b is the current approximation of what's live across the call.
+                       // Every bit in cal.b is a single stack word. For each such word,
+                       // find all the other tracked stack words in the same Go variable
+                       // (struct/slice/string/interface) and mark them live too.
+                       // This is necessary because the liveness analysis for the garbage
+                       // collector works at variable granularity, not at word granularity.
+                       // It is fundamental for slice/string/interface: the garbage collector
+                       // needs the whole value, not just some of the words, in order to
+                       // interpret the other bits correctly. Specifically, slice needs a consistent
+                       // ptr and cap, string needs a consistent ptr and len, and interface
+                       // needs a consistent type word and data word.
+                       for(z=0; z<BITS; z++) {
+                               if(cal.b[z] == 0)
+                                       continue;
+                               for(i=0; i<64; i++) {
+                                       if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
+                                               continue;
+                                       v = var+z*64+i;
+                                       if(v->node->opt == nil) // v represents fixed register, not Go variable
+                                               continue;
+
+                                       // v->node->opt is the head of a linked list of Vars
+                                       // corresponding to tracked words from the Go variable v->node.
+                                       // Walk the list and set all the bits.
+                                       // For a large struct this could end up being quadratic:
+                                       // after the first setting, the outer loop (for z, i) would see a 1 bit
+                                       // for all of the remaining words in the struct, and for each such
+                                       // word would go through and turn on all the bits again.
+                                       // To avoid the quadratic behavior, we only turn on the bits if
+                                       // v is the head of the list or if the head's bit is not yet turned on.
+                                       // This will set the bits at most twice, keeping the overall loop linear.
+                                       v1 = v->node->opt;
+                                       j = v1 - var;
+                                       if(v == v1 || !btest(&cal, j)) {
+                                               for(; v1 != nil; v1 = v1->nextinnode) {
+                                                       j = v1 - var;
+                                                       biset(&cal, j);
+                                               }
+                                       }
+                               }
+                       }
+                       break;
+
+               case ATEXT:
+                       for(z=0; z<BITS; z++) {
+                               cal.b[z] = 0;
+                               ref.b[z] = 0;
+                       }
+                       break;
+
+               case ARET:
+                       for(z=0; z<BITS; z++) {
+                               cal.b[z] = externs.b[z] | ovar.b[z];
+                               ref.b[z] = 0;
+                       }
+                       break;
+               }
+               for(z=0; z<BITS; z++) {
+                       ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
+                               r1->use1.b[z] | r1->use2.b[z];
+                       cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
+                       r1->refbehind.b[z] = ref.b[z];
+                       r1->calbehind.b[z] = cal.b[z];
+               }
+               if(r1->f.active)
+                       break;
+               r1->f.active = 1;
+       }
+       for(; r != r1; r = (Reg*)r->f.p1)
+               for(r2 = (Reg*)r->f.p2; r2 != R; r2 = (Reg*)r2->f.p2link)
+                       prop(r2, r->refbehind, r->calbehind);
+}
+
+void
+synch(Reg *r, Bits dif)
+{
+       Reg *r1;
+       int z;
+
+       for(r1 = r; r1 != R; r1 = (Reg*)r1->f.s1) {
+               for(z=0; z<BITS; z++) {
+                       dif.b[z] = (dif.b[z] &
+                               ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
+                                       r1->set.b[z] | r1->regdiff.b[z];
+                       if(dif.b[z] != r1->regdiff.b[z]) {
+                               r1->regdiff.b[z] = dif.b[z];
+                               change++;
+                       }
+               }
+               if(r1->f.active)
+                       break;
+               r1->f.active = 1;
+               for(z=0; z<BITS; z++)
+                       dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
+               if(r1->f.s2 != nil)
+                       synch((Reg*)r1->f.s2, dif);
+       }
+}
+
+uint64
+allreg(uint64 b, Rgn *r)
+{
+       Var *v;
+       int i;
+
+       v = var + r->varno;
+       r->regno = 0;
+       switch(v->etype) {
+
+       default:
+               fatal("unknown etype %d/%E", bitno(b), v->etype);
+               break;
+
+       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 TPTR32:
+       case TPTR64:
+               i = BtoR(~b);
+               if(i && r->cost > 0) {
+                       r->regno = i;
+                       return RtoB(i);
+               }
+               break;
+
+       case TFLOAT32:
+       case TFLOAT64:
+               i = BtoF(~b);
+               if(i && r->cost > 0) {
+                       r->regno = i;
+                       return FtoB(i);
+               }
+               break;
+       }
+       return 0;
+}
+
+void
+paint1(Reg *r, int bn)
+{
+       Reg *r1;
+       int z;
+       uint64 bb;
+
+       z = bn/64;
+       bb = 1LL<<(bn%64);
+       if(r->act.b[z] & bb)
+               return;
+       for(;;) {
+               if(!(r->refbehind.b[z] & bb))
+                       break;
+               r1 = (Reg*)r->f.p1;
+               if(r1 == R)
+                       break;
+               if(!(r1->refahead.b[z] & bb))
+                       break;
+               if(r1->act.b[z] & bb)
+                       break;
+               r = r1;
+       }
+
+       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
+               change -= CLOAD * r->f.loop;
+       }
+       for(;;) {
+               r->act.b[z] |= bb;
+
+               if(r->f.prog->as != ANOP) { // don't give credit for NOPs
+                       if(r->use1.b[z] & bb)
+                               change += CREF * r->f.loop;
+                       if((r->use2.b[z]|r->set.b[z]) & bb)
+                               change += CREF * r->f.loop;
+               }
+
+               if(STORE(r) & r->regdiff.b[z] & bb) {
+                       change -= CLOAD * r->f.loop;
+               }
+
+               if(r->refbehind.b[z] & bb)
+                       for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
+                               if(r1->refahead.b[z] & bb)
+                                       paint1(r1, bn);
+
+               if(!(r->refahead.b[z] & bb))
+                       break;
+               r1 = (Reg*)r->f.s2;
+               if(r1 != R)
+                       if(r1->refbehind.b[z] & bb)
+                               paint1(r1, bn);
+               r = (Reg*)r->f.s1;
+               if(r == R)
+                       break;
+               if(r->act.b[z] & bb)
+                       break;
+               if(!(r->refbehind.b[z] & bb))
+                       break;
+       }
+}
+
+uint64
+paint2(Reg *r, int bn, int depth)
+{
+       Reg *r1;
+       int z;
+       uint64 bb, vreg;
+
+       z = bn/64;
+       bb = 1LL << (bn%64);
+       vreg = regbits;
+       if(!(r->act.b[z] & bb))
+               return vreg;
+       for(;;) {
+               if(!(r->refbehind.b[z] & bb))
+                       break;
+               r1 = (Reg*)r->f.p1;
+               if(r1 == R)
+                       break;
+               if(!(r1->refahead.b[z] & bb))
+                       break;
+               if(!(r1->act.b[z] & bb))
+                       break;
+               r = r1;
+       }
+       for(;;) {
+               if(debug['R'] && debug['v'])
+                       print("  paint2 %d %P\n", depth, r->f.prog);
+
+               r->act.b[z] &= ~bb;
+
+               vreg |= r->regu;
+
+               if(r->refbehind.b[z] & bb)
+                       for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
+                               if(r1->refahead.b[z] & bb)
+                                       vreg |= paint2(r1, bn, depth+1);
+
+               if(!(r->refahead.b[z] & bb))
+                       break;
+               r1 = (Reg*)r->f.s2;
+               if(r1 != R)
+                       if(r1->refbehind.b[z] & bb)
+                               vreg |= paint2(r1, bn, depth+1);
+               r = (Reg*)r->f.s1;
+               if(r == R)
+                       break;
+               if(!(r->act.b[z] & bb))
+                       break;
+               if(!(r->refbehind.b[z] & bb))
+                       break;
+       }
+       return vreg;
+}
+
+void
+paint3(Reg *r, int bn, uint64 rb, int rn)
+{
+       Reg *r1;
+       Prog *p;
+       int z;
+       uint64 bb;
+
+       z = bn/64;
+       bb = 1LL << (bn%64);
+       if(r->act.b[z] & bb)
+               return;
+       for(;;) {
+               if(!(r->refbehind.b[z] & bb))
+                       break;
+               r1 = (Reg*)r->f.p1;
+               if(r1 == R)
+                       break;
+               if(!(r1->refahead.b[z] & bb))
+                       break;
+               if(r1->act.b[z] & bb)
+                       break;
+               r = r1;
+       }
+
+       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
+               addmove(r, bn, rn, 0);
+       for(;;) {
+               r->act.b[z] |= bb;
+               p = r->f.prog;
+
+               if(r->use1.b[z] & bb) {
+                       if(debug['R'] && debug['v'])
+                               print("%P", p);
+                       addreg(&p->from, rn);
+                       if(debug['R'] && debug['v'])
+                               print(" ===change== %P\n", p);
+               }
+               if((r->use2.b[z]|r->set.b[z]) & bb) {
+                       if(debug['R'] && debug['v'])
+                               print("%P", p);
+                       addreg(&p->to, rn);
+                       if(debug['R'] && debug['v'])
+                               print(" ===change== %P\n", p);
+               }
+
+               if(STORE(r) & r->regdiff.b[z] & bb)
+                       addmove(r, bn, rn, 1);
+               r->regu |= rb;
+
+               if(r->refbehind.b[z] & bb)
+                       for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
+                               if(r1->refahead.b[z] & bb)
+                                       paint3(r1, bn, rb, rn);
+
+               if(!(r->refahead.b[z] & bb))
+                       break;
+               r1 = (Reg*)r->f.s2;
+               if(r1 != R)
+                       if(r1->refbehind.b[z] & bb)
+                               paint3(r1, bn, rb, rn);
+               r = (Reg*)r->f.s1;
+               if(r == R)
+                       break;
+               if(r->act.b[z] & bb)
+                       break;
+               if(!(r->refbehind.b[z] & bb))
+                       break;
+       }
+}
+
+void
+addreg(Adr *a, int rn)
+{
+       a->sym = nil;
+       a->node = nil;
+       a->name = D_NONE;
+       a->type = D_REG;
+       a->reg = rn;
+       if(rn >= NREG) {
+               a->type = D_FREG;
+               a->reg = rn-NREG;
+       }
+
+       ostats.ncvtreg++;
+}
+
+/*
+ * track register variables including external registers:
+ *     bit     reg
+ *     0       R0
+ *     1       R1
+ *     ...     ...
+ *     31      R31
+ *     32+0    F0
+ *     32+1    F1
+ *     ...     ...
+ *     32+31   F31
+ */
+uint64
+RtoB(int r)
+{
+       if(r > D_R0 && r <= D_R0+31)
+               return 1ULL << (r - D_R0);
+       return 0;
+}
+
+int
+BtoR(uint64 b)
+{
+       b &= 0xffffffffull;
+       if(b == 0)
+               return 0;
+       return bitno(b) + D_R0;
+}
+
+uint64
+FtoB(int r)
+{
+       if(r >= D_F0 && r <= D_F0+31)
+               return 1ULL << (32 + r - D_F0);
+       return 0;
+}
+
+int
+BtoF(uint64 b)
+{
+       b >>= 32;
+       if(b == 0)
+               return 0;
+       return bitno(b) + D_F0;
+}
+
+void
+dumpone(Flow *f, int isreg)
+{
+       int z;
+       Bits bit;
+       Reg *r;
+
+       print("%d:%P", f->loop, f->prog);
+       if(isreg) {     
+               r = (Reg*)f;
+               for(z=0; z<BITS; z++)
+                       bit.b[z] =
+                               r->set.b[z] |
+                               r->use1.b[z] |
+                               r->use2.b[z] |
+                               r->refbehind.b[z] |
+                               r->refahead.b[z] |
+                               r->calbehind.b[z] |
+                               r->calahead.b[z] |
+                               r->regdiff.b[z] |
+                               r->act.b[z] |
+                                       0;
+               if(bany(&bit)) {
+                       print("\t");
+                       if(bany(&r->set))
+                               print(" s:%Q", r->set);
+                       if(bany(&r->use1))
+                               print(" u1:%Q", r->use1);
+                       if(bany(&r->use2))
+                               print(" u2:%Q", r->use2);
+                       if(bany(&r->refbehind))
+                               print(" rb:%Q ", r->refbehind);
+                       if(bany(&r->refahead))
+                               print(" ra:%Q ", r->refahead);
+                       if(bany(&r->calbehind))
+                               print(" cb:%Q ", r->calbehind);
+                       if(bany(&r->calahead))
+                               print(" ca:%Q ", r->calahead);
+                       if(bany(&r->regdiff))
+                               print(" d:%Q ", r->regdiff);
+                       if(bany(&r->act))
+                               print(" a:%Q ", r->act);
+               }
+       }
+       print("\n");
+}
+
+
+void
+dumpit(char *str, Flow *r0, int isreg)
+{
+       Flow *r, *r1;
+
+       print("\n%s\n", str);
+       for(r = r0; r != nil; r = r->link) {
+               dumpone(r, isreg);
+               r1 = r->p2;
+               if(r1 != nil) {
+                       print(" pred:");
+                       for(; r1 != nil; r1 = r1->p2link)
+                               print(" %.4ud", (int)r1->prog->pc);
+                       print("\n");
+               }
+               // Print successors if it's not just the next one
+               if(r->s1 != r->link || r->s2 != nil) {
+                       print(" succ:");
+                       if(r->s1 != nil)
+                               print(" %.4ud", (int)r->s1->prog->pc);
+                       if(r->s2 != nil)
+                               print(" %.4ud", (int)r->s2->prog->pc);
+                       print("\n");
+               }
+       }
+}
diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h
new file mode 100644 (file)
index 0000000..87917f8
--- /dev/null
@@ -0,0 +1,516 @@
+// cmd/9c/9.out.h from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/*
+ * powerpc 64
+ */
+#define        NSNAME  8
+#define        NSYM    50
+#define        NREG    32      /* number of general registers */
+#define        NFREG   32      /* number of floating point registers */
+
+#include "../ld/textflag.h"
+
+enum
+{
+       REGZERO         = 0,    /* set to zero */
+       REGSP           = 1,
+       REGSB           = 2,
+       REGRET          = 3,
+       REGARG          = -1,   /* -1 disables passing the first argument in register */
+       REGRT1          = 3,    /* reserved for runtime, duffzero and duffcopy */
+       REGRT2          = 4,    /* reserved for runtime, duffcopy */
+       REGMIN          = 7,    /* register variables allocated from here to REGMAX */
+       REGENV          = 11,   /* environment for closures */
+       REGMAX          = 27,
+       REGEXT          = 30,   /* external registers allocated from here down */
+       REGG            = 30,   /* G */
+       REGTMP          = 31,   /* used by the linker */
+
+       FREGRET         = 0,
+       FREGMIN         = 17,   /* first register variable */
+       FREGMAX         = 26,   /* last register variable for 9g only */
+       FREGEXT         = 26,   /* first external register */
+       FREGCVI         = 27,   /* floating conversion constant */
+       FREGZERO        = 28,   /* both float and double */
+       FREGHALF        = 29,   /* double */
+       FREGONE         = 30,   /* double */
+       FREGTWO         = 31    /* double */
+/*
+ * GENERAL:
+ *
+ * compiler allocates R3 up as temps
+ * compiler allocates register variables R7-R27
+ * compiler allocates external registers R30 down
+ *
+ * compiler allocates register variables F17-F26
+ * compiler allocates external registers F26 down
+ */
+};
+
+enum {
+       BIG = 32768-8,
+};
+
+enum {
+/* mark flags */
+       LABEL           = 1<<0,
+       LEAF            = 1<<1,
+       FLOAT           = 1<<2,
+       BRANCH          = 1<<3,
+       LOAD            = 1<<4,
+       FCMP            = 1<<5,
+       SYNC            = 1<<6,
+       LIST            = 1<<7,
+       FOLL            = 1<<8,
+       NOSCHED         = 1<<9,
+};
+
+enum
+{
+       C_NONE,
+       C_REG,
+       C_FREG,
+       C_CREG,
+       C_SPR,          /* special processor register */
+       C_ZCON,
+       C_SCON,         /* 16 bit signed */
+       C_UCON,         /* low 16 bits 0 */
+       C_ADDCON,       /* -0x8000 <= v < 0 */
+       C_ANDCON,       /* 0 < v <= 0xFFFF */
+       C_LCON,         /* other 32 */
+       C_DCON,         /* other 64 (could subdivide further) */
+       C_SACON,
+       C_SECON,
+       C_LACON,
+       C_LECON,
+       C_SBRA,
+       C_LBRA,
+       C_SAUTO,
+       C_LAUTO,
+       C_SEXT,
+       C_LEXT,
+       C_ZOREG,
+       C_SOREG,
+       C_LOREG,
+       C_FPSCR,
+       C_MSR,
+       C_XER,
+       C_LR,
+       C_CTR,
+       C_ANY,
+       C_GOK,
+       C_ADDR,
+
+       C_NCLASS,       /* must be the last */
+};
+
+enum
+{
+       AXXX,
+       AADD,
+       AADDCC,
+       AADDV,
+       AADDVCC,
+       AADDC,
+       AADDCCC,
+       AADDCV,
+       AADDCVCC,
+       AADDME,
+       AADDMECC,
+       AADDMEVCC,
+       AADDMEV,
+       AADDE,
+       AADDECC,
+       AADDEVCC,
+       AADDEV,
+       AADDZE,
+       AADDZECC,
+       AADDZEVCC,
+       AADDZEV,
+       AAND,
+       AANDCC,
+       AANDN,
+       AANDNCC,
+       ABC,
+       ABCL,
+       ABEQ,
+       ABGE,
+       ABGT,
+       ABL,
+       ABLE,
+       ABLT,
+       ABNE,
+       ABR,
+       ABVC,
+       ABVS,
+       ACMP,
+       ACMPU,
+       ACNTLZW,
+       ACNTLZWCC,
+       ACRAND,
+       ACRANDN,
+       ACREQV,
+       ACRNAND,
+       ACRNOR,
+       ACROR,
+       ACRORN,
+       ACRXOR,
+       ADIVW,
+       ADIVWCC,
+       ADIVWVCC,
+       ADIVWV,
+       ADIVWU,
+       ADIVWUCC,
+       ADIVWUVCC,
+       ADIVWUV,
+       AEQV,
+       AEQVCC,
+       AEXTSB,
+       AEXTSBCC,
+       AEXTSH,
+       AEXTSHCC,
+       AFABS,
+       AFABSCC,
+       AFADD,
+       AFADDCC,
+       AFADDS,
+       AFADDSCC,
+       AFCMPO,
+       AFCMPU,
+       AFCTIW,
+       AFCTIWCC,
+       AFCTIWZ,
+       AFCTIWZCC,
+       AFDIV,
+       AFDIVCC,
+       AFDIVS,
+       AFDIVSCC,
+       AFMADD,
+       AFMADDCC,
+       AFMADDS,
+       AFMADDSCC,
+       AFMOVD,
+       AFMOVDCC,
+       AFMOVDU,
+       AFMOVS,
+       AFMOVSU,
+       AFMSUB,
+       AFMSUBCC,
+       AFMSUBS,
+       AFMSUBSCC,
+       AFMUL,
+       AFMULCC,
+       AFMULS,
+       AFMULSCC,
+       AFNABS,
+       AFNABSCC,
+       AFNEG,
+       AFNEGCC,
+       AFNMADD,
+       AFNMADDCC,
+       AFNMADDS,
+       AFNMADDSCC,
+       AFNMSUB,
+       AFNMSUBCC,
+       AFNMSUBS,
+       AFNMSUBSCC,
+       AFRSP,
+       AFRSPCC,
+       AFSUB,
+       AFSUBCC,
+       AFSUBS,
+       AFSUBSCC,
+       AMOVMW,
+       ALSW,
+       ALWAR,
+       AMOVWBR,
+       AMOVB,
+       AMOVBU,
+       AMOVBZ,
+       AMOVBZU,
+       AMOVH,
+       AMOVHBR,
+       AMOVHU,
+       AMOVHZ,
+       AMOVHZU,
+       AMOVW,
+       AMOVWU,
+       AMOVFL,
+       AMOVCRFS,
+       AMTFSB0,
+       AMTFSB0CC,
+       AMTFSB1,
+       AMTFSB1CC,
+       AMULHW,
+       AMULHWCC,
+       AMULHWU,
+       AMULHWUCC,
+       AMULLW,
+       AMULLWCC,
+       AMULLWVCC,
+       AMULLWV,
+       ANAND,
+       ANANDCC,
+       ANEG,
+       ANEGCC,
+       ANEGVCC,
+       ANEGV,
+       ANOR,
+       ANORCC,
+       AOR,
+       AORCC,
+       AORN,
+       AORNCC,
+       AREM,
+       AREMCC,
+       AREMV,
+       AREMVCC,
+       AREMU,
+       AREMUCC,
+       AREMUV,
+       AREMUVCC,
+       ARFI,
+       ARLWMI,
+       ARLWMICC,
+       ARLWNM,
+       ARLWNMCC,
+       ASLW,
+       ASLWCC,
+       ASRW,
+       ASRAW,
+       ASRAWCC,
+       ASRWCC,
+       ASTSW,
+       ASTWCCC,
+       ASUB,
+       ASUBCC,
+       ASUBVCC,
+       ASUBC,
+       ASUBCCC,
+       ASUBCV,
+       ASUBCVCC,
+       ASUBME,
+       ASUBMECC,
+       ASUBMEVCC,
+       ASUBMEV,
+       ASUBV,
+       ASUBE,
+       ASUBECC,
+       ASUBEV,
+       ASUBEVCC,
+       ASUBZE,
+       ASUBZECC,
+       ASUBZEVCC,
+       ASUBZEV,
+       ASYNC,
+       AXOR,
+       AXORCC,
+
+       ADCBF,
+       ADCBI,
+       ADCBST,
+       ADCBT,
+       ADCBTST,
+       ADCBZ,
+       AECIWX,
+       AECOWX,
+       AEIEIO,
+       AICBI,
+       AISYNC,
+       APTESYNC,
+       ATLBIE,
+       ATLBIEL,
+       ATLBSYNC,
+       ATW,
+
+       ASYSCALL,
+       ADATA,
+       AGLOBL,
+       AGOK,
+       AHISTORY,
+       ANAME,
+       ANOP,
+       ARETURN,
+       ATEXT,
+       AWORD,
+       AEND,
+       ADYNT,
+       AINIT,
+       ASIGNAME,
+
+       ARFCI,
+
+       /* optional on 32-bit */
+       AFRES,
+       AFRESCC,
+       AFRSQRTE,
+       AFRSQRTECC,
+       AFSEL,
+       AFSELCC,
+       AFSQRT,
+       AFSQRTCC,
+       AFSQRTS,
+       AFSQRTSCC,
+
+       /* 64-bit */
+       
+       ACNTLZD,
+       ACNTLZDCC,
+       ACMPW,  /* CMP with L=0 */
+       ACMPWU,
+       ADIVD,
+       ADIVDCC,
+       ADIVDVCC,
+       ADIVDV,
+       ADIVDU,
+       ADIVDUCC,
+       ADIVDUVCC,
+       ADIVDUV,
+       AEXTSW,
+       AEXTSWCC,
+       /* AFCFIW; AFCFIWCC */
+       AFCFID,
+       AFCFIDCC,
+       AFCTID,
+       AFCTIDCC,
+       AFCTIDZ,
+       AFCTIDZCC,
+       ALDAR,
+       AMOVD,
+       AMOVDU,
+       AMOVWZ,
+       AMOVWZU,
+       AMULHD,
+       AMULHDCC,
+       AMULHDU,
+       AMULHDUCC,
+       AMULLD,
+       AMULLDCC,
+       AMULLDVCC,
+       AMULLDV,
+       ARFID,
+       ARLDMI,
+       ARLDMICC,
+       ARLDC,
+       ARLDCCC,
+       ARLDCR,
+       ARLDCRCC,
+       ARLDCL,
+       ARLDCLCC,
+       ASLBIA,
+       ASLBIE,
+       ASLBMFEE,
+       ASLBMFEV,
+       ASLBMTE,
+       ASLD,
+       ASLDCC,
+       ASRD,
+       ASRAD,
+       ASRADCC,
+       ASRDCC,
+       ASTDCCC,
+       ATD,
+
+       /* 64-bit pseudo operation */
+       ADWORD,
+       AREMD,
+       AREMDCC,
+       AREMDV,
+       AREMDVCC,
+       AREMDU,
+       AREMDUCC,
+       AREMDUV,
+       AREMDUVCC,
+
+       /* more 64-bit operations */
+       AHRFID,
+
+       AUNDEF,
+       AUSEFIELD,
+       ATYPE,
+       AFUNCDATA,
+       APCDATA,
+       ACHECKNIL,
+       AVARDEF,
+       AVARKILL,
+       ADUFFCOPY,
+       ADUFFZERO,
+
+       ALAST
+};
+
+/* type/name */
+enum
+{
+       D_GOK   = 0,
+       D_NONE,
+
+/* name */
+       D_EXTERN,
+       D_STATIC,
+       D_AUTO,
+       D_PARAM,
+
+/* type */
+       D_BRANCH,
+       D_OREG,
+       D_CONST,
+       D_FCONST,
+       D_SCONST,
+       D_REG,
+       D_FPSCR,
+       D_MSR,
+       D_FREG,
+       D_CREG,
+       D_SPR,
+       D_OPT,  /* branch/trap option */
+       D_FILE,
+       D_FILE1,
+       D_DCR,  /* device control register */
+       D_DCONST,
+       D_ADDR, // not used, use D_CONST with non-empty sym.
+
+       D_LAST,
+
+/* reg names for 9g OREGISTER */
+       D_R0 = 0, // type is D_REG
+       D_F0 = D_R0+NREG, // type is D_FREG
+
+/* reg names in offset field iff type is D_SPR */
+       D_XER   = 1,
+       D_LR    = 8,
+       D_CTR   = 9
+       /* and many supervisor level registers */
+};
+
+/*
+ * this is the ranlib header
+ */
+#define        SYMDEF  "__.GOSYMDEF"
similarity index 100%
rename from src/cmd/5c/Makefile
rename to src/cmd/9l/Makefile
diff --git a/src/cmd/9l/asm.c b/src/cmd/9l/asm.c
new file mode 100644 (file)
index 0000000..b8ca777
--- /dev/null
@@ -0,0 +1,338 @@
+// Inferno utils/5l/asm.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Writing object files.
+
+#include       "l.h"
+#include       "../ld/lib.h"
+#include       "../ld/elf.h"
+#include       "../ld/dwarf.h"
+
+
+char linuxdynld[] = "/lib64/ld64.so.1";
+char freebsddynld[] = "XXX";
+char openbsddynld[] = "XXX";
+char netbsddynld[] = "XXX";
+char dragonflydynld[] = "XXX";
+char solarisdynld[] = "XXX";
+
+static int
+needlib(char *name)
+{
+       char *p;
+       LSym *s;
+
+       if(*name == '\0')
+               return 0;
+
+       /* reuse hash code in symbol table */
+       p = smprint(".dynlib.%s", name);
+       s = linklookup(ctxt, p, 0);
+       free(p);
+       if(s->type == 0) {
+               s->type = 100;  // avoid SDATA, etc.
+               return 1;
+       }
+       return 0;
+}
+
+int    nelfsym = 1;
+
+// b is the addresses, a is the I-form branch instruction template, peform
+// addition so that the instruction jumps to address (offset) b.
+static int32
+braddoff(int32 a, int32 b)
+{
+       return (((uint32)a) & 0xfc000003U) | (0x03fffffcU & (uint32)((a & 0x3fffffcU) + b));
+}
+
+void
+adddynrela(LSym *rel, LSym *s, Reloc *r)
+{
+       // TODO(minux)
+       USED(rel); USED(s); USED(r);
+}
+
+void
+adddynrel(LSym *s, Reloc *r)
+{
+       LSym *targ;
+
+       // TODO(minux)
+
+       targ = r->sym;
+       ctxt->cursym = s;
+       diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
+}
+
+int
+elfreloc1(Reloc *r, vlong sectoff)
+{
+       USED(r); USED(sectoff);
+       // TODO(minux)
+       return -1;
+}
+
+void
+elfsetupplt(void)
+{
+       // TODO(minux)
+       return;
+}
+
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+       USED(r);
+       USED(sectoff);
+
+       return -1;
+}
+
+
+int
+archreloc(Reloc *r, LSym *s, vlong *val)
+{
+       uint32 o1, o2;
+       int32 t;
+
+       if(linkmode == LinkExternal) {
+               // TODO(minux): translate R_ADDRPOWER and R_CALLPOWER into standard ELF relocations.
+               // R_ADDRPOWER corresponds to R_PPC_ADDR16_HA and R_PPC_ADDR16_LO.
+               // R_CALLPOWER corresponds to R_PPC_REL24.
+               return -1;
+       }
+       switch(r->type) {
+       case R_CONST:
+               *val = r->add;
+               return 0;
+       case R_GOTOFF:
+               *val = symaddr(r->sym) + r->add - symaddr(linklookup(ctxt, ".got", 0));
+               return 0;
+       case R_ADDRPOWER:
+               // r->add is two power64 instructions holding an immediate 32-bit constant.
+               // We want to add r->sym's address to that constant.
+               // The encoding of the immediate x<<16 + y,
+               // where x is the low 16 bits of the first instruction and y is the low 16
+               // bits of the second. Both x and y are signed (int16, not uint16).
+               o1 = r->add >> 32;
+               o2 = r->add;
+               t = symaddr(r->sym);
+               if(t < 0) {
+                       ctxt->diag("relocation for %s is too big (>=2G): %lld", s->name, symaddr(r->sym));
+               }
+               t += ((o1 & 0xffff) << 16) + ((int32)o2 << 16 >> 16);
+               if(t & 0x8000)
+                       t += 0x10000;
+               o1 = (o1 & 0xffff0000) | ((t >> 16) & 0xffff);
+               o2 = (o2 & 0xffff0000) | (t & 0xffff);
+               // when laid out, the instruction order must always be o1, o2.
+               if(ctxt->arch->endian == BigEndian)
+                       *val = ((vlong)o1 << 32) | o2;
+               else
+                       *val = ((vlong)o2 << 32) | o1;
+               return 0;
+       case R_CALLPOWER:
+               *val = braddoff((uint32)r->add, (int32)(symaddr(r->sym) - (s->value + r->off)));
+               return 0;
+       }
+       return -1;
+}
+
+void
+adddynsym(Link *ctxt, LSym *s)
+{
+       USED(ctxt); USED(s);
+       // TODO(minux)
+       return;
+}
+
+void
+adddynlib(char *lib)
+{
+       LSym *s;
+       
+       if(!needlib(lib))
+               return;
+       
+       if(iself) {
+               s = linklookup(ctxt, ".dynstr", 0);
+               if(s->size == 0)
+                       addstring(s, "");
+               elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
+       } else {
+               diag("adddynlib: unsupported binary format");
+       }
+}
+
+void
+asmb(void)
+{
+       uint32 symo;
+       Section *sect;
+       LSym *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);
+       for(sect = sect->next; sect != nil; sect = sect->next) {
+               cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
+               datblk(sect->vaddr, sect->len);
+       }
+
+       if(segrodata.filelen > 0) {
+               if(debug['v'])
+                       Bprint(&bso, "%5.2f rodatblk\n", cputime());
+               Bflush(&bso);
+
+               cseek(segrodata.fileoff);
+               datblk(segrodata.vaddr, segrodata.filelen);
+       }
+
+       if(debug['v'])
+               Bprint(&bso, "%5.2f datblk\n", cputime());
+       Bflush(&bso);
+
+       cseek(segdata.fileoff);
+       datblk(segdata.vaddr, segdata.filelen);
+
+       /* output symbol table */
+       symsize = 0;
+       lcsize = 0;
+       symo = 0;
+       if(!debug['s']) {
+               // TODO: rationalize
+               if(debug['v'])
+                       Bprint(&bso, "%5.2f sym\n", cputime());
+               Bflush(&bso);
+               switch(HEADTYPE) {
+               default:
+                       if(iself)
+                               goto ElfSym;
+               case Hplan9:
+                       symo = segdata.fileoff+segdata.filelen;
+                       break;
+               ElfSym:
+                       symo = segdata.fileoff+segdata.filelen;
+                       symo = rnd(symo, INITRND);
+                       break;
+               }
+               cseek(symo);
+               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(linkmode == LinkExternal)
+                                       elfemitreloc();
+                       }
+                       break;
+               case Hplan9:
+                       asmplan9sym();
+                       cflush();
+
+                       sym = linklookup(ctxt, "pclntab", 0);
+                       if(sym != nil) {
+                               lcsize = sym->np;
+                               for(i=0; i < lcsize; i++)
+                                       cput(sym->p[i]);
+
+                               cflush();
+                       }
+                       break;
+               }
+       }
+
+       ctxt->cursym = nil;
+       if(debug['v'])
+               Bprint(&bso, "%5.2f header\n", cputime());
+       Bflush(&bso);
+       cseek(0L);
+       switch(HEADTYPE) {
+       default:
+       case Hplan9:    /* plan 9 */
+               LPUT(0x647);                    /* magic */
+               LPUT(segtext.filelen);                  /* sizes */
+               LPUT(segdata.filelen);
+               LPUT(segdata.len - segdata.filelen);
+               LPUT(symsize);                  /* nsyms */
+               LPUT(entryvalue());             /* va of entry */
+               LPUT(0L);
+               LPUT(lcsize);
+               break;
+       case Hlinux:
+       case Hfreebsd:
+       case Hnetbsd:
+       case Hopenbsd:
+       case Hnacl:
+               asmbelf(symo);
+               break;
+       }
+       cflush();
+       if(debug['c']){
+               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", segtext.filelen+segdata.len+symsize+lcsize);
+       }
+}
+
+vlong
+rnd(vlong v, int32 r)
+{
+       vlong c;
+
+       if(r <= 0)
+               return v;
+       v += r - 1;
+       c = v % r;
+       if(c < 0)
+               c += r;
+       v -= c;
+       return v;
+}
similarity index 55%
rename from src/cmd/cc/doc.go
rename to src/cmd/9l/doc.go
index 10901b4413ef0a787b039f0bcd0f2853f82d7813..9df5dc6148d0b1c62a13ebaa1ef3298dd0fe2d64 100644 (file)
@@ -6,8 +6,11 @@
 
 /*
 
-This directory contains the portable section of the Plan 9 C compilers.
-See ../6c, ../8c, and ../5c for more information.
+9l is the linker for the Power64.
+The $GOARCH for these tools is power64 (big endian) or
+power64le (little endian).
+
+The flags are documented in ../ld/doc.go.
 
 */
 package main
diff --git a/src/cmd/9l/l.h b/src/cmd/9l/l.h
new file mode 100644 (file)
index 0000000..dda741c
--- /dev/null
@@ -0,0 +1,100 @@
+// cmd/9l/l.h from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include       <u.h>
+#include       <libc.h>
+#include       <bio.h>
+#include       <link.h>
+#include       "9.out.h"
+
+#ifndef        EXTERN
+#define        EXTERN  extern
+#endif
+
+enum
+{
+       thechar = '9',
+       PtrSize = 8,
+       IntSize = 8,
+       RegSize = 8,
+       MaxAlign = 32,  // max data alignment
+       FuncAlign = 8
+};
+
+#define        P               ((Prog*)0)
+#define        S               ((LSym*)0)
+
+enum
+{
+       FPCHIP          = 1,
+       STRINGSZ        = 200,
+       MAXHIST         = 20,                           /* limit of path elements for history symbols */
+       DATBLK          = 1024,
+       NHASH           = 10007,
+       NHUNK           = 100000,
+       MINSIZ          = 64,
+       NENT            = 100,
+       NSCHED          = 20,
+       MINLC           = 4,
+
+       Roffset = 22,           /* no. bits for offset in relocation address */
+       Rindex  = 10            /* no. bits for index in relocation address */
+};
+
+EXTERN int32   autosize;
+EXTERN LSym*   datap;
+EXTERN int     debug[128];
+EXTERN int32   lcsize;
+EXTERN char    literal[32];
+EXTERN int     nerrors;
+EXTERN vlong   instoffset;
+EXTERN char*   rpath;
+EXTERN vlong   pc;
+EXTERN int32   symsize;
+EXTERN int32   staticgen;
+EXTERN Prog*   lastp;
+EXTERN vlong   textsize;
+
+void   asmb(void);
+void   adddynlib(char *lib);
+void   adddynrel(LSym *s, Reloc *r);
+void   adddynsym(Link *ctxt, LSym *s);
+int    archreloc(Reloc *r, LSym *s, vlong *val);
+void   listinit(void);
+vlong  rnd(vlong, int32);
+
+#define        LPUT(a) (ctxt->arch->endian == BigEndian ? lputb(a):lputl(a))
+#define        WPUT(a) (ctxt->arch->endian == BigEndian ? wputb(a):wputl(a))
+#define        VPUT(a) (ctxt->arch->endian == BigEndian ? vputb(a):vputl(a))
+
+/* Used by ../ld/dwarf.c */
+enum
+{
+       DWARFREGSP = 1
+};
similarity index 91%
rename from src/cmd/5c/list.c
rename to src/cmd/9l/list.c
index 98da424dea680e9e9b63cfb485a521cd2ee4316c..af8dc1588560635fd9e652045c93641a65f062b6 100644 (file)
@@ -1,5 +1,5 @@
-// Inferno utils/5c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.c
+// Inferno utils/5l/list.h
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/list.c
 //
 //     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
 //     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+// Printing.
 
-#define        EXTERN
-#include "gc.h"
+#include "l.h"
+#include "../ld/lib.h"
 
 void
 listinit(void)
 {
-       listinit5();
+       listinit9();
 }
diff --git a/src/cmd/9l/obj.c b/src/cmd/9l/obj.c
new file mode 100644 (file)
index 0000000..badb72a
--- /dev/null
@@ -0,0 +1,108 @@
+// Inferno utils/5l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Reading object files.
+
+#include       "l.h"
+#include       "../ld/lib.h"
+#include       "../ld/elf.h"
+#include       "../ld/dwarf.h"
+#include       <ar.h>
+
+char *thestring = "power64";
+LinkArch *thelinkarch;
+
+void
+linkarchinit(void)
+{
+       thestring = getgoarch();
+       if(strcmp(thestring, "power64le") == 0)
+               thelinkarch = &linkpower64le;
+       else
+               thelinkarch = &linkpower64;
+}
+
+void
+archinit(void)
+{
+       // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+       // Go was built; see ../../make.bash.
+       if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+               linkmode = LinkInternal;
+
+       switch(HEADTYPE) {
+       default:
+               if(linkmode == LinkAuto)
+                       linkmode = LinkInternal;
+               if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
+                       sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
+               break;
+       }
+
+       switch(HEADTYPE) {
+       default:
+               diag("unknown -H option");
+               errorexit();
+       case Hplan9:    /* plan 9 */
+               HEADR = 32L;
+               if(INITTEXT == -1)
+                       INITTEXT = 4128;
+               if(INITDAT == -1)
+                       INITDAT = 0;
+               if(INITRND == -1)
+                       INITRND = 4096;
+               break;
+       case Hlinux:    /* power64 elf */
+               debug['d'] = 1; // TODO(minux): dynamic linking is not supported yet.
+               elfinit();
+               HEADR = ELFRESERVE;
+               if(INITTEXT == -1)
+                       INITTEXT = 0x10000 + HEADR;
+               if(INITDAT == -1)
+                       INITDAT = 0;
+               if(INITRND == -1)
+                       INITRND = 0x10000;
+               break;
+       case Hnacl:
+               elfinit();
+               HEADR = 0x10000;
+               funcalign = 16;
+               if(INITTEXT == -1)
+                       INITTEXT = 0x20000;
+               if(INITDAT == -1)
+                       INITDAT = 0;
+               if(INITRND == -1)
+                       INITRND = 0x10000;
+               break;
+       }
+       if(INITDAT != 0 && INITRND != 0)
+               print("warning: -D0x%ux is ignored because of -R0x%ux\n",
+                       INITDAT, INITRND);
+}
diff --git a/src/cmd/cc/acid.c b/src/cmd/cc/acid.c
deleted file mode 100644 (file)
index 23147e5..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-// Inferno utils/cc/acid.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/acid.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-static char *kwd[] =
-{
-       "$adt", "$aggr", "$append", "$complex", "$defn",
-       "$delete", "$do", "$else", "$eval", "$head", "$if",
-       "$local", "$loop", "$return", "$tail", "$then",
-       "$union", "$whatis", "$while",
-};
-
-char*
-amap(char *s)
-{
-       int i, bot, top, new;
-
-       bot = 0;
-       top = bot + nelem(kwd) - 1;
-       while(bot <= top){
-               new = bot + (top - bot)/2;
-               i = strcmp(kwd[new]+1, s);
-               if(i == 0)
-                       return kwd[new];
-
-               if(i < 0)
-                       bot = new + 1;
-               else
-                       top = new - 1;
-       }
-       return s;
-}
-
-Sym*
-acidsue(Type *t)
-{
-       int h;
-       Sym *s;
-
-       if(t != T)
-       for(h=0; h<nelem(hash); h++)
-               for(s = hash[h]; s != S; s = s->link)
-                       if(s->suetag && s->suetag->link == t)
-                               return s;
-       return 0;
-}
-
-Sym*
-acidfun(Type *t)
-{
-       int h;
-       Sym *s;
-
-       for(h=0; h<nelem(hash); h++)
-               for(s = hash[h]; s != S; s = s->link)
-                       if(s->type == t)
-                               return s;
-       return 0;
-}
-
-char   acidchar[NTYPE];
-Init   acidcinit[] =
-{
-       TCHAR,          'C',    0,
-       TUCHAR,         'b',    0,
-       TSHORT,         'd',    0,
-       TUSHORT,        'u',    0,
-       TLONG,          'D',    0,
-       TULONG,         'U',    0,
-       TVLONG,         'V',    0,
-       TUVLONG,        'W',    0,
-       TFLOAT,         'f',    0,
-       TDOUBLE,        'F',    0,
-       TARRAY,         'a',    0,
-       TIND,           'X',    0,
-       -1,             0,      0,
-};
-
-static void
-acidinit(void)
-{
-       Init *p;
-
-       for(p=acidcinit; p->code >= 0; p++)
-               acidchar[p->code] = p->value;
-
-       acidchar[TINT] = acidchar[TLONG];
-       acidchar[TUINT] = acidchar[TULONG];
-       if(types[TINT]->width != types[TLONG]->width) {
-               acidchar[TINT] = acidchar[TSHORT];
-               acidchar[TUINT] = acidchar[TUSHORT];
-               if(types[TINT]->width != types[TSHORT]->width)
-                       warn(Z, "acidmember int not long or short");
-       }
-       if(types[TIND]->width == types[TUVLONG]->width)
-               acidchar[TIND] = 'Y';
-       
-}
-
-void
-acidmember(Type *t, int32 off, int flag)
-{
-       Sym *s, *s1;
-       Type *l;
-       static int acidcharinit = 0;
-
-       if(acidcharinit == 0) {
-               acidinit();
-               acidcharinit = 1;
-       }
-       s = t->sym;
-       switch(t->etype) {
-       default:
-               Bprint(&outbuf, "       T%d\n", t->etype);
-               break;
-
-       case TIND:
-               if(s == S)
-                       break;
-               l = t->link;
-               if(flag) { 
-                       if(typesu[l->etype]) {
-                               s1 = acidsue(l->link);
-                               if(s1 != S) {
-                                       Bprint(&outbuf, "       'A' %s %d %s;\n",
-                                               amap(s1->name),
-                                               t->offset+off, amap(s->name));
-                                       break;
-                               }
-                       }
-               } else {
-                       l = t->link;
-                       s1 = S;
-                       if(typesu[l->etype])
-                               s1 = acidsue(l->link);
-                       if(s1 != S) {
-                               Bprint(&outbuf,
-                                       "\tprint(indent, \"%s\t(%s)\", addr.%s\\X, \"\\n\");\n",
-                                       amap(s->name), amap(s1->name), amap(s->name));
-                       } else {
-                               Bprint(&outbuf,
-                                       "\tprint(indent, \"%s\t\", addr.%s\\X, \"\\n\");\n",
-                                       amap(s->name), amap(s->name));
-                       }
-                       break;
-               }
-
-       case TINT:
-       case TUINT:
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TFLOAT:
-       case TDOUBLE:
-       case TARRAY:
-               if(s == S)
-                       break;
-               if(flag) {
-                       Bprint(&outbuf, "       '%c' %d %s;\n",
-                       acidchar[t->etype], t->offset+off, amap(s->name));
-               } else {
-                       Bprint(&outbuf, "\tprint(indent, \"%s\t\", addr.%s, \"\\n\");\n",
-                               amap(s->name), amap(s->name));
-               }
-               break;
-
-       case TSTRUCT:
-       case TUNION:
-               s1 = acidsue(t->link);
-               if(s1 == S)
-                       break;
-               if(flag) {
-                       if(s == S) {
-                               Bprint(&outbuf, "       {\n");
-                               for(l = t->link; l != T; l = l->down)
-                                       acidmember(l, t->offset+off, flag);
-                               Bprint(&outbuf, "       };\n");
-                       } else {
-                               Bprint(&outbuf, "       %s %d %s;\n",
-                                       amap(s1->name),
-                                       t->offset+off, amap(s->name));
-                       }
-               } else {
-                       if(s != S) {
-                               Bprint(&outbuf, "\tprint(indent, \"%s %s {\\n\");\n",
-                                       amap(s1->name), amap(s->name));
-                               Bprint(&outbuf, "\tindent_%s(addr.%s, indent+\"\\t\");\n",
-                                       amap(s1->name), amap(s->name));
-                               Bprint(&outbuf, "\tprint(indent, \"}\\n\");\n");
-                       } else {
-                               Bprint(&outbuf, "\tprint(indent, \"%s {\\n\");\n",
-                                       amap(s1->name));
-                               Bprint(&outbuf, "\tindent_%s(addr+%d, indent+\"\\t\");\n",
-                                       amap(s1->name), t->offset+off);
-                               Bprint(&outbuf, "\tprint(indent, \"}\\n\");\n");
-                       }
-               }
-               break;
-       }
-}
-
-void
-acidtype(Type *t)
-{
-       Sym *s;
-       Type *l;
-       Io *i;
-       int n;
-       char *an;
-
-       if(!debug['a'])
-               return;
-       if(debug['a'] > 1) {
-               n = 0;
-               for(i=iostack; i; i=i->link)
-                       n++;
-               if(n > 1)
-                       return;
-       }
-       s = acidsue(t->link);
-       if(s == S)
-               return;
-       switch(t->etype) {
-       default:
-               Bprint(&outbuf, "T%d\n", t->etype);
-               return;
-
-       case TUNION:
-       case TSTRUCT:
-               if(debug['s'])
-                       goto asmstr;
-               an = amap(s->name);
-               Bprint(&outbuf, "sizeof%s = %d;\n", an, t->width);
-               Bprint(&outbuf, "aggr %s\n{\n", an);
-               for(l = t->link; l != T; l = l->down)
-                       acidmember(l, 0, 1);
-               Bprint(&outbuf, "};\n\n");
-
-               Bprint(&outbuf, "defn\n%s(addr) {\n\tindent_%s(addr, \"\\t\");\n}\n", an, an);
-               Bprint(&outbuf, "defn\nindent_%s(addr, indent) {\n\tcomplex %s addr;\n", an, an);
-               for(l = t->link; l != T; l = l->down)
-                       acidmember(l, 0, 0);
-               Bprint(&outbuf, "};\n\n");
-               break;
-       asmstr:
-               if(s == S)
-                       break;
-               for(l = t->link; l != T; l = l->down)
-                       if(l->sym != S)
-                               Bprint(&outbuf, "#define\t%s.%s\t%d\n",
-                                       s->name,
-                                       l->sym->name,
-                                       l->offset);
-               break;
-       }
-}
-
-void
-acidvar(Sym *s)
-{
-       int n;
-       Io *i;
-       Type *t;
-       Sym *s1, *s2;
-
-       if(!debug['a'] || debug['s'])
-               return;
-       if(debug['a'] > 1) {
-               n = 0;
-               for(i=iostack; i; i=i->link)
-                       n++;
-               if(n > 1)
-                       return;
-       }
-       t = s->type;
-       while(t && t->etype == TIND)
-               t = t->link;
-       if(t == T)
-               return;
-       if(t->etype == TENUM) {
-               Bprint(&outbuf, "%s = ", amap(s->name));
-               if(!typefd[t->etype])
-                       Bprint(&outbuf, "%lld;\n", s->vconst);
-               else
-                       Bprint(&outbuf, "%f\n;", s->fconst);
-               return;
-       }
-       if(!typesu[t->etype])
-               return;
-       s1 = acidsue(t->link);
-       if(s1 == S)
-               return;
-       switch(s->class) {
-       case CAUTO:
-       case CPARAM:
-               s2 = acidfun(thisfn);
-               if(s2)
-                       Bprint(&outbuf, "complex %s %s:%s;\n",
-                               amap(s1->name), amap(s2->name), amap(s->name));
-               break;
-       
-       case CSTATIC:
-       case CEXTERN:
-       case CGLOBL:
-       case CLOCAL:
-               Bprint(&outbuf, "complex %s %s;\n",
-                       amap(s1->name), amap(s->name));
-               break;
-       }
-}
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
deleted file mode 100644 (file)
index 9530f5c..0000000
+++ /dev/null
@@ -1,835 +0,0 @@
-// Inferno utils/cc/cc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/cc.h
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <libc.h>
-#include <bio.h>
-#include <link.h>
-
-#ifndef        EXTERN
-#define EXTERN extern
-#endif
-
-#undef getc
-#undef ungetc
-#undef BUFSIZ
-
-#define        getc    ccgetc
-#define        ungetc  ccungetc
-
-typedef        struct  Node    Node;
-typedef        struct  Sym     Sym;
-typedef        struct  Type    Type;
-typedef        struct  Funct   Funct;
-typedef        struct  Decl    Decl;
-typedef        struct  Io      Io;
-typedef        struct  Term    Term;
-typedef        struct  Init    Init;
-typedef        struct  Bits    Bits;
-typedef        struct  Bvec    Bvec;
-typedef        struct  Dynimp  Dynimp;
-typedef        struct  Dynexp  Dynexp;
-typedef        struct  Var     Var;
-
-typedef        Rune    TRune;  /* target system type */
-
-#define        BUFSIZ          8192
-#define        NSYMB           500
-#define        NHASH           1024
-#define        STRINGSZ        200
-#define        HISTSZ          20
-#define YYMAXDEPTH     500
-#define        NTERM           10
-#define        MAXALIGN        7
-
-#define        SIGN(n)         ((uvlong)1<<(n-1))
-#define        MASK(n)         (SIGN(n)|(SIGN(n)-1))
-
-#define        BITS    5
-#define        NVAR    (BITS*sizeof(uint32)*8)
-struct Bits
-{
-       uint32  b[BITS];
-};
-
-struct Bvec
-{
-       int32   n;      // number of bits
-       uint32  b[];
-};
-
-struct Var
-{
-       vlong   offset;
-       LSym*   sym;
-       char    name;
-       char    etype;
-};
-
-struct Node
-{
-       Node*   left;
-       Node*   right;
-       void*   label;
-       int32   pc;
-       int     reg;
-       int32   xoffset;
-       double  fconst;         /* fp constant */
-       vlong   vconst;         /* non fp const */
-       char*   cstring;        /* character string */
-       TRune*  rstring;        /* rune string */
-
-       Sym*    sym;
-       Type*   type;
-       int32   lineno;
-       uchar   op;
-       uchar   oldop;
-       uchar   xcast;
-       uchar   class;
-       uchar   etype;
-       uchar   complex;
-       uchar   addable;
-       uchar   scale;
-       uchar   garb;
-};
-#define        Z       ((Node*)0)
-
-struct Sym
-{
-       Sym*    link;
-       LSym*   lsym;
-       Type*   type;
-       Type*   suetag;
-       Type*   tenum;
-       char*   macro;
-       int32   varlineno;
-       int32   offset;
-       vlong   vconst;
-       double  fconst;
-       Node*   label;
-       ushort  lexical;
-       char    *name;
-       ushort  block;
-       ushort  sueblock;
-       uchar   class;
-       uchar   sym;
-       uchar   aused;
-       uchar   sig;
-       uchar   dataflag;
-};
-#define        S       ((Sym*)0)
-
-enum{
-       SIGNONE = 0,
-       SIGDONE = 1,
-       SIGINTERN = 2,
-
-       SIGNINTERN = 1729*325*1729,
-};
-
-struct Decl
-{
-       Decl*   link;
-       Sym*    sym;
-       Type*   type;
-       int32   varlineno;
-       int32   offset;
-       short   val;
-       ushort  block;
-       uchar   class;
-       uchar   aused;
-};
-#define        D       ((Decl*)0)
-
-struct Type
-{
-       Sym*    sym;
-       Sym*    tag;
-       Funct*  funct;
-       Type*   link;
-       Type*   down;
-       int32   width;
-       int32   offset;
-       int32   lineno;
-       uchar   shift;
-       uchar   nbits;
-       uchar   etype;
-       uchar   garb;
-       uchar   align;
-};
-
-#define        T       ((Type*)0)
-#define        NODECL  ((void(*)(int, Type*, Sym*))0)
-
-struct Init                    /* general purpose initialization */
-{
-       int     code;
-       uint32  value;
-       char*   s;
-};
-
-EXTERN struct
-{
-       char*   p;
-       int     c;
-} fi;
-
-struct Io
-{
-       Io*     link;
-       char*   p;
-       char    b[BUFSIZ];
-       short   c;
-       short   f;
-};
-#define        I       ((Io*)0)
-
-struct Term
-{
-       vlong   mult;
-       Node    *node;
-};
-
-enum
-{
-       Axxx,
-       Ael1,
-       Ael2,
-       Asu2,
-       Aarg0,
-       Aarg1,
-       Aarg2,
-       Aaut3,
-       NALIGN,
-};
-
-enum
-{
-       DMARK,
-       DAUTO,
-       DSUE,
-       DLABEL,
-};
-enum
-{
-       OXXX,
-       OADD,
-       OADDR,
-       OAND,
-       OANDAND,
-       OARRAY,
-       OAS,
-       OASI,
-       OASADD,
-       OASAND,
-       OASASHL,
-       OASASHR,
-       OASDIV,
-       OASHL,
-       OASHR,
-       OASLDIV,
-       OASLMOD,
-       OASLMUL,
-       OASLSHR,
-       OASMOD,
-       OASMUL,
-       OASOR,
-       OASSUB,
-       OASXOR,
-       OBIT,
-       OBREAK,
-       OCASE,
-       OCAST,
-       OCOMMA,
-       OCOND,
-       OCONST,
-       OCONTINUE,
-       ODIV,
-       ODOT,
-       ODOTDOT,
-       ODWHILE,
-       OENUM,
-       OEQ,
-       OEXREG,
-       OFOR,
-       OFUNC,
-       OGE,
-       OGOTO,
-       OGT,
-       OHI,
-       OHS,
-       OIF,
-       OIND,
-       OINDREG,
-       OINIT,
-       OLABEL,
-       OLDIV,
-       OLE,
-       OLIST,
-       OLMOD,
-       OLMUL,
-       OLO,
-       OLS,
-       OLSHR,
-       OLT,
-       OMOD,
-       OMUL,
-       ONAME,
-       ONE,
-       ONOT,
-       OOR,
-       OOROR,
-       OPOSTDEC,
-       OPOSTINC,
-       OPREDEC,
-       OPREINC,
-       OPREFETCH,
-       OPROTO,
-       OREGISTER,
-       ORETURN,
-       OSET,
-       OSIGN,
-       OSIZE,
-       OSTRING,
-       OLSTRING,
-       OSTRUCT,
-       OSUB,
-       OSWITCH,
-       OUNION,
-       OUSED,
-       OWHILE,
-       OXOR,
-       ONEG,
-       OCOM,
-       OPOS,
-       OELEM,
-
-       OTST,           /* used in some compilers */
-       OINDEX,
-       OFAS,
-       OREGPAIR,
-       OROTL,
-
-       OEND
-};
-enum
-{
-       TXXX,
-       TCHAR,
-       TUCHAR,
-       TSHORT,
-       TUSHORT,
-       TINT,
-       TUINT,
-       TLONG,
-       TULONG,
-       TVLONG,
-       TUVLONG,
-       TFLOAT,
-       TDOUBLE,
-       TIND,
-       TFUNC,
-       TARRAY,
-       TVOID,
-       TSTRUCT,
-       TUNION,
-       TENUM,
-       NTYPE,
-
-       TAUTO   = NTYPE,
-       TEXTERN,
-       TSTATIC,
-       TTYPEDEF,
-       TTYPESTR,
-       TREGISTER,
-       TCONSTNT,
-       TVOLATILE,
-       TUNSIGNED,
-       TSIGNED,
-       TDOT,
-       TFILE,
-       TOLD,
-       NALLTYPES,
-
-       /* adapt size of Rune to target system's size */
-       TRUNE = sizeof(TRune)==4? TUINT: TUSHORT,
-};
-enum
-{
-       CXXX,
-       CAUTO,
-       CEXTERN,
-       CGLOBL,
-       CSTATIC,
-       CLOCAL,
-       CTYPEDEF,
-       CTYPESTR,
-       CPARAM,
-       CSELEM,
-       CLABEL,
-       CEXREG,
-       NCTYPES,
-};
-enum
-{
-       GXXX            = 0,
-       GCONSTNT        = 1<<0,
-       GVOLATILE       = 1<<1,
-       NGTYPES         = 1<<2,
-
-       GINCOMPLETE     = 1<<2,
-};
-enum
-{
-       BCHAR           = 1L<<TCHAR,
-       BUCHAR          = 1L<<TUCHAR,
-       BSHORT          = 1L<<TSHORT,
-       BUSHORT         = 1L<<TUSHORT,
-       BINT            = 1L<<TINT,
-       BUINT           = 1L<<TUINT,
-       BLONG           = 1L<<TLONG,
-       BULONG          = 1L<<TULONG,
-       BVLONG          = 1L<<TVLONG,
-       BUVLONG         = 1L<<TUVLONG,
-       BFLOAT          = 1L<<TFLOAT,
-       BDOUBLE         = 1L<<TDOUBLE,
-       BIND            = 1L<<TIND,
-       BFUNC           = 1L<<TFUNC,
-       BARRAY          = 1L<<TARRAY,
-       BVOID           = 1L<<TVOID,
-       BSTRUCT         = 1L<<TSTRUCT,
-       BUNION          = 1L<<TUNION,
-       BENUM           = 1L<<TENUM,
-       BFILE           = 1L<<TFILE,
-       BDOT            = 1L<<TDOT,
-       BCONSTNT        = 1L<<TCONSTNT,
-       BVOLATILE       = 1L<<TVOLATILE,
-       BUNSIGNED       = 1L<<TUNSIGNED,
-       BSIGNED         = 1L<<TSIGNED,
-       BAUTO           = 1L<<TAUTO,
-       BEXTERN         = 1L<<TEXTERN,
-       BSTATIC         = 1L<<TSTATIC,
-       BTYPEDEF        = 1L<<TTYPEDEF,
-       BTYPESTR        = 1L<<TTYPESTR,
-       BREGISTER       = 1L<<TREGISTER,
-
-       BINTEGER        = BCHAR|BUCHAR|BSHORT|BUSHORT|BINT|BUINT|
-                               BLONG|BULONG|BVLONG|BUVLONG,
-       BNUMBER         = BINTEGER|BFLOAT|BDOUBLE,
-
-/* these can be overloaded with complex types */
-
-       BCLASS          = BAUTO|BEXTERN|BSTATIC|BTYPEDEF|BTYPESTR|BREGISTER,
-       BGARB           = BCONSTNT|BVOLATILE,
-};
-
-struct Funct
-{
-       Sym*    sym[OEND];
-       Sym*    castto[NTYPE];
-       Sym*    castfr[NTYPE];
-};
-
-EXTERN struct
-{
-       Type*   tenum;          /* type of entire enum */
-       Type*   cenum;          /* type of current enum run */
-       vlong   lastenum;       /* value of current enum */
-       double  floatenum;      /* value of current enum */
-} en;
-
-EXTERN int     autobn;
-EXTERN int32   autoffset;
-EXTERN int     blockno;
-EXTERN Decl*   dclstack;
-EXTERN int     debug[256];
-EXTERN int32   firstbit;
-EXTERN Sym*    firstarg;
-EXTERN Type*   firstargtype;
-EXTERN Decl*   firstdcl;
-EXTERN int     fperror;
-EXTERN Sym*    hash[NHASH];
-EXTERN char*   hunk;
-EXTERN char**  include;
-EXTERN Io*     iofree;
-EXTERN Io*     ionext;
-EXTERN Io*     iostack;
-EXTERN int32   lastbit;
-EXTERN char    lastclass;
-EXTERN Type*   lastdcl;
-EXTERN int32   lastfield;
-EXTERN Type*   lasttype;
-EXTERN int32   lineno;
-EXTERN int32   nearln;
-EXTERN int     nerrors;
-EXTERN int     newflag;
-EXTERN int32   nhunk;
-EXTERN int     ninclude;
-EXTERN Node*   nodproto;
-EXTERN Node*   nodcast;
-EXTERN int32   nsymb;
-EXTERN Biobuf  outbuf;
-EXTERN Biobuf  diagbuf;
-EXTERN char*   outfile;
-EXTERN int     peekc;
-EXTERN int32   stkoff;
-EXTERN Type*   strf;
-EXTERN Type*   strl;
-EXTERN char*   symb;
-EXTERN Sym*    symstring;
-EXTERN int     taggen;
-EXTERN Type*   tfield;
-EXTERN Type*   tufield;
-extern int     thechar;
-extern char*   thestring;
-extern LinkArch*       thelinkarch;
-EXTERN Type*   thisfn;
-EXTERN int32   thunk;
-EXTERN Type*   types[NALLTYPES];
-EXTERN Type*   fntypes[NALLTYPES];
-EXTERN Node*   initlist;
-EXTERN Term    term[NTERM];
-EXTERN int     nterm;
-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 int     nacl;
-EXTERN Bits    zbits;
-EXTERN Fmt     pragcgobuf;
-EXTERN Biobuf  bstdout;
-EXTERN Var     var[NVAR];
-
-extern char    *onames[], *tnames[], *gnames[];
-extern char    *cnames[], *qnames[], *bnames[];
-extern uchar   tab[NTYPE][NTYPE];
-extern uchar   comrel[], invrel[], logrel[];
-extern int32   ncast[], tadd[], tand[];
-extern int32   targ[], tasadd[], tasign[], tcast[];
-extern int32   tdot[], tfunct[], tindir[], tmul[];
-extern int32   tnot[], trel[], tsub[];
-
-extern uchar   typeaf[];
-extern uchar   typefd[];
-extern uchar   typei[];
-extern uchar   typesu[];
-extern uchar   typesuv[];
-extern uchar   typeu[];
-extern uchar   typev[];
-extern uchar   typec[];
-extern uchar   typeh[];
-extern uchar   typeil[];
-extern uchar   typeilp[];
-extern uchar   typechl[];
-extern uchar   typechlv[];
-extern uchar   typechlvp[];
-extern uchar   typechlp[];
-extern uchar   typechlpfd[];
-
-EXTERN uchar*  typeword;
-EXTERN uchar*  typecmplx;
-EXTERN Link*   ctxt;
-
-extern uint32  thash1;
-extern uint32  thash2;
-extern uint32  thash3;
-extern uint32  thash[];
-
-/*
- *     compat.c/unix.c/windows.c
- */
-int    systemtype(int);
-int    pathchar(void);
-
-/*
- *     parser
- */
-int    yyparse(void);
-int    mpatov(char*, vlong*);
-
-/*
- *     lex.c
- */
-void*  allocn(void*, int32, int32);
-void*  alloc(int32);
-void    ensuresymb(int32);
-void   cinit(void);
-int    compile(char*, char**, int);
-void   errorexit(void);
-int    filbuf(void);
-int    getc(void);
-int32  getr(void);
-int    getnsc(void);
-Sym*   lookup(void);
-void   main(int, char*[]);
-void   newfile(char*, int);
-void   newio(void);
-void   pushio(void);
-int32  escchar(int32, int, int);
-Sym*   slookup(char*);
-void   syminit(Sym*);
-void   unget(int);
-int32  yylex(void);
-int    Lconv(Fmt*);
-int    Tconv(Fmt*);
-int    FNconv(Fmt*);
-int    Oconv(Fmt*);
-int    Qconv(Fmt*);
-int    VBconv(Fmt*);
-int    Bconv(Fmt*);
-void   setinclude(char*);
-
-/*
- * mac.c
- */
-void   dodefine(char*);
-void   domacro(void);
-Sym*   getsym(void);
-int32  getnsn(void);
-void   macdef(void);
-void   macprag(void);
-void   macend(void);
-void   macexpand(Sym*, char*);
-void   macif(int);
-void   macinc(void);
-void   maclin(void);
-void   macund(void);
-
-/*
- * dcl.c
- */
-Node*  doinit(Sym*, Type*, int32, Node*);
-Type*  tcopy(Type*);
-Node*  init1(Sym*, Type*, int32, int);
-Node*  newlist(Node*, Node*);
-void   adecl(int, Type*, Sym*);
-int    anyproto(Node*);
-void   argmark(Node*, int);
-void   dbgdecl(Sym*);
-Node*  dcllabel(Sym*, int);
-Node*  dodecl(void(*)(int, Type*, Sym*), int, Type*, Node*);
-Sym*   mkstatic(Sym*);
-void   doenum(Sym*, Node*);
-void   snap(Type*);
-Type*  dotag(Sym*, int, int);
-void   edecl(int, Type*, Sym*);
-Type*  fnproto(Node*);
-Type*  fnproto1(Node*);
-void   markdcl(void);
-Type*  paramconv(Type*, int);
-void   pdecl(int, Type*, Sym*);
-Decl*  push(void);
-Decl*  push1(Sym*);
-Node*  revertdcl(void);
-int32  xround(int32, int);
-int    rsametype(Type*, Type*, int, int);
-int    sametype(Type*, Type*);
-uint32 sign(Sym*);
-uint32 signature(Type*);
-void   sualign(Type*);
-void   tmerge(Type*, Sym*);
-void   walkparam(Node*, int);
-void   xdecl(int, Type*, Sym*);
-Node*  contig(Sym*, Node*, int32);
-
-/*
- * com.c
- */
-void   ccom(Node*);
-void   complex(Node*);
-int    tcom(Node*);
-int    tcoma(Node*, Node*, Type*, int);
-int    tcomd(Node*);
-int    tcomo(Node*, int);
-int    tcomx(Node*);
-int    tlvalue(Node*);
-void   constas(Node*, Type*, Type*);
-
-/*
- * con.c
- */
-void   acom(Node*);
-void   acom1(vlong, Node*);
-void   acom2(Node*, Type*);
-int    acomcmp1(const void*, const void*);
-int    acomcmp2(const void*, const void*);
-int    addo(Node*);
-void   evconst(Node*);
-
-/*
- * funct.c
- */
-int    isfunct(Node*);
-void   dclfunct(Type*, Sym*);
-
-/*
- * sub.c
- */
-void   arith(Node*, int);
-int    deadheads(Node*);
-Type*  dotsearch(Sym*, Type*, Node*, int32*);
-int32  dotoffset(Type*, Type*, Node*);
-void   gethunk(void);
-Node*  invert(Node*);
-int    bitno(int32);
-void   makedot(Node*, Type*, int32);
-int    mixedasop(Type*, Type*);
-Node*  new(int, Node*, Node*);
-Node*  new1(int, Node*, Node*);
-int    nilcast(Type*, Type*);
-int    nocast(Type*, Type*);
-void   prtree(Node*, char*);
-void   prtree1(Node*, int, int);
-void   relcon(Node*, Node*);
-int    relindex(int);
-int    simpleg(int32);
-Type*  garbt(Type*, int32);
-int    simplec(int32);
-Type*  simplet(int32);
-int    stcompat(Node*, Type*, Type*, int32[]);
-int    tcompat(Node*, Type*, Type*, int32[]);
-void   tinit(void);
-Type*  typ(int, Type*);
-Type*  copytyp(Type*);
-void   typeext(Type*, Node*);
-void   typeext1(Type*, Node*);
-int    side(Node*);
-int    vconst(Node*);
-int    xlog2(uvlong);
-int    vlog(Node*);
-int    topbit(uint32);
-void   simplifyshift(Node*);
-int32  typebitor(int32, int32);
-void   diag(Node*, char*, ...);
-void   warn(Node*, char*, ...);
-void   yyerror(char*, ...);
-void   fatal(Node*, char*, ...);
-LSym*  linksym(Sym*);
-
-/*
- * acid.c
- */
-void   acidtype(Type*);
-void   acidvar(Sym*);
-
-/*
- * godefs.c
- */
-int    Uconv(Fmt*);
-void   godeftype(Type*);
-void   godefvar(Sym*);
-
-/*
- * bits.c
- */
-Bits   bor(Bits, Bits);
-Bits   band(Bits, Bits);
-Bits   bnot(Bits);
-int    bany(Bits*);
-int    bnum(Bits);
-Bits   blsh(uint);
-int    beq(Bits, Bits);
-int    bset(Bits, uint);
-
-/*
- * dpchk.c
- */
-void   dpcheck(Node*);
-void   arginit(void);
-void   pragvararg(void);
-void   pragpack(void);
-void   pragfpround(void);
-void   pragdataflag(void);
-void   pragtextflag(void);
-void   pragincomplete(void);
-void   pragcgo(char*);
-
-/*
- * calls to machine depend part
- */
-void   codgen(Node*, Node*);
-void   gclean(void);
-void   gextern(Sym*, Node*, int32, int32);
-void   ginit(void);
-int32  outstring(char*, int32);
-int32  outlstring(TRune*, int32);
-void   sextern(Sym*, Node*, int32, int32);
-void   xcom(Node*);
-int32  exreg(Type*);
-int32  align(int32, Type*, int, int32*);
-int32  maxround(int32, int32);
-int    hasdotdotdot(Type*);
-void    linkarchinit(void);
-
-extern schar   ewidth[];
-
-/*
- * com64
- */
-int    com64(Node*);
-void   com64init(void);
-void   bool64(Node*);
-double convvtof(vlong);
-vlong  convftov(double);
-double convftox(double, int);
-vlong  convvtox(vlong, int);
-
-/*
- * machcap
- */
-int    machcap(Node*);
-
-#pragma        varargck        argpos  warn    2
-#pragma        varargck        argpos  diag    2
-#pragma        varargck        argpos  yyerror 1
-
-#pragma        varargck        type    "B"     Bits
-#pragma        varargck        type    "F"     Node*
-#pragma        varargck        type    "L"     int32
-#pragma        varargck        type    "Q"     int32
-#pragma        varargck        type    "O"     int
-#pragma        varargck        type    "O"     uint
-#pragma        varargck        type    "T"     Type*
-#pragma        varargck        type    "U"     char*
-#pragma        varargck        type    "|"     int
-
-enum
-{
-       Plan9   = 1<<0,
-       Unix    = 1<<1,
-       Windows = 1<<2,
-};
-int    pathchar(void);
-int    systemtype(int);
-void*  alloc(int32 n);
-void*  allocn(void*, int32, int32);
diff --git a/src/cmd/cc/cc.y b/src/cmd/cc/cc.y
deleted file mode 100644 (file)
index 8d7cb14..0000000
+++ /dev/null
@@ -1,1220 +0,0 @@
-// Inferno utils/cc/cc.y
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/cc.y
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-%{
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and cc.h re-#defines getc */
-#include "cc.h"
-%}
-%union {
-       Node*   node;
-       Sym*    sym;
-       Type*   type;
-       struct
-       {
-               Type*   t;
-               uchar   c;
-       } tycl;
-       struct
-       {
-               Type*   t1;
-               Type*   t2;
-               Type*   t3;
-               uchar   c;
-       } tyty;
-       struct
-       {
-               char*   s;
-               int32   l;
-       } sval;
-       int32   lval;
-       double  dval;
-       vlong   vval;
-}
-%type  <sym>   ltag
-%type  <lval>  gctname gcname cname gname tname
-%type  <lval>  gctnlist gcnlist zgnlist
-%type  <type>  tlist sbody complex
-%type  <tycl>  types
-%type  <node>  zarglist arglist zcexpr
-%type  <node>  name block stmnt cexpr expr xuexpr pexpr
-%type  <node>  zelist elist adecl slist uexpr string lstring
-%type  <node>  xdecor xdecor2 labels label ulstmnt
-%type  <node>  adlist edecor tag qual qlist
-%type  <node>  abdecor abdecor1 abdecor2 abdecor3
-%type  <node>  zexpr lexpr init ilist forexpr
-
-%left  ';'
-%left  ','
-%right '=' LPE LME LMLE LDVE LMDE LRSHE LLSHE LANDE LXORE LORE
-%right '?' ':'
-%left  LOROR
-%left  LANDAND
-%left  '|'
-%left  '^'
-%left  '&'
-%left  LEQ LNE
-%left  '<' '>' LLE LGE
-%left  LLSH LRSH
-%left  '+' '-'
-%left  '*' '/' '%'
-%right LMM LPP LMG '.' '[' '('
-
-%token <sym>   LNAME LTYPE
-%token <dval>  LFCONST LDCONST
-%token <vval>  LCONST LLCONST LUCONST LULCONST LVLCONST LUVLCONST
-%token <sval>  LSTRING LLSTRING
-%token         LAUTO LBREAK LCASE LCHAR LCONTINUE LDEFAULT LDO
-%token         LDOUBLE LELSE LEXTERN LFLOAT LFOR LGOTO
-%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
-%%
-prog:
-|      prog xdecl
-
-/*
- * external declarator
- */
-xdecl:
-       zctlist ';'
-       {
-               dodecl(xdecl, lastclass, lasttype, Z);
-       }
-|      zctlist xdlist ';'
-|      zctlist xdecor
-       {
-               lastdcl = T;
-               firstarg = S;
-               dodecl(xdecl, lastclass, lasttype, $2);
-               if(lastdcl == T || lastdcl->etype != TFUNC) {
-                       diag($2, "not a function");
-                       lastdcl = types[TFUNC];
-               }
-               thisfn = lastdcl;
-               markdcl();
-               firstdcl = dclstack;
-               argmark($2, 0);
-       }
-       pdecl
-       {
-               argmark($2, 1);
-       }
-       block
-       {
-               Node *n;
-
-               n = revertdcl();
-               if(n)
-                       $6 = new(OLIST, n, $6);
-               if(!debug['a'] && !debug['Z'])
-                       codgen($6, $2);
-       }
-
-xdlist:
-       xdecor
-       {
-               dodecl(xdecl, lastclass, lasttype, $1);
-       }
-|      xdecor
-       {
-               $1 = dodecl(xdecl, lastclass, lasttype, $1);
-       }
-       '=' init
-       {
-               doinit($1->sym, $1->type, 0L, $4);
-       }
-|      xdlist ',' xdlist
-
-xdecor:
-       xdecor2
-|      '*' zgnlist xdecor
-       {
-               $$ = new(OIND, $3, Z);
-               $$->garb = simpleg($2);
-       }
-
-xdecor2:
-       tag
-|      '(' xdecor ')'
-       {
-               $$ = $2;
-       }
-|      xdecor2 '(' zarglist ')'
-       {
-               $$ = new(OFUNC, $1, $3);
-       }
-|      xdecor2 '[' zexpr ']'
-       {
-               $$ = new(OARRAY, $1, $3);
-       }
-
-/*
- * automatic declarator
- */
-adecl:
-       ctlist ';'
-       {
-               $$ = dodecl(adecl, lastclass, lasttype, Z);
-       }
-|      ctlist adlist ';'
-       {
-               $$ = $2;
-       }
-
-adlist:
-       xdecor
-       {
-               dodecl(adecl, lastclass, lasttype, $1);
-               $$ = Z;
-       }
-|      xdecor
-       {
-               $1 = dodecl(adecl, lastclass, lasttype, $1);
-       }
-       '=' init
-       {
-               int32 w;
-
-               w = $1->sym->type->width;
-               $$ = doinit($1->sym, $1->type, 0L, $4);
-               $$ = contig($1->sym, $$, w);
-       }
-|      adlist ',' adlist
-       {
-               $$ = $1;
-               if($3 != Z) {
-                       $$ = $3;
-                       if($1 != Z)
-                               $$ = new(OLIST, $1, $3);
-               }
-       }
-
-/*
- * parameter declarator
- */
-pdecl:
-|      pdecl ctlist pdlist ';'
-
-pdlist:
-       xdecor
-       {
-               dodecl(pdecl, lastclass, lasttype, $1);
-       }
-|      pdlist ',' pdlist
-
-/*
- * structure element declarator
- */
-edecl:
-       tlist
-       {
-               lasttype = $1;
-       }
-       zedlist ';'
-|      edecl tlist
-       {
-               lasttype = $2;
-       }
-       zedlist ';'
-
-zedlist:                                       /* extension */
-       {
-               lastfield = 0;
-               edecl(CXXX, lasttype, S);
-       }
-|      edlist
-
-edlist:
-       edecor
-       {
-               dodecl(edecl, CXXX, lasttype, $1);
-       }
-|      edlist ',' edlist
-
-edecor:
-       xdecor
-       {
-               lastbit = 0;
-               firstbit = 1;
-       }
-|      tag ':' lexpr
-       {
-               $$ = new(OBIT, $1, $3);
-       }
-|      ':' lexpr
-       {
-               $$ = new(OBIT, Z, $2);
-       }
-
-/*
- * abstract declarator
- */
-abdecor:
-       {
-               $$ = (Z);
-       }
-|      abdecor1
-
-abdecor1:
-       '*' zgnlist
-       {
-               $$ = new(OIND, (Z), Z);
-               $$->garb = simpleg($2);
-       }
-|      '*' zgnlist abdecor1
-       {
-               $$ = new(OIND, $3, Z);
-               $$->garb = simpleg($2);
-       }
-|      abdecor2
-
-abdecor2:
-       abdecor3
-|      abdecor2 '(' zarglist ')'
-       {
-               $$ = new(OFUNC, $1, $3);
-       }
-|      abdecor2 '[' zexpr ']'
-       {
-               $$ = new(OARRAY, $1, $3);
-       }
-
-abdecor3:
-       '(' ')'
-       {
-               $$ = new(OFUNC, (Z), Z);
-       }
-|      '[' zexpr ']'
-       {
-               $$ = new(OARRAY, (Z), $2);
-       }
-|      '(' abdecor1 ')'
-       {
-               $$ = $2;
-       }
-
-init:
-       expr
-|      '{' ilist '}'
-       {
-               $$ = new(OINIT, invert($2), Z);
-       }
-
-qual:
-       '[' lexpr ']'
-       {
-               $$ = new(OARRAY, $2, Z);
-       }
-|      '.' ltag
-       {
-               $$ = new(OELEM, Z, Z);
-               $$->sym = $2;
-       }
-|      qual '='
-
-qlist:
-       init ','
-|      qlist init ','
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-|      qual
-|      qlist qual
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-
-ilist:
-       qlist
-|      init
-|      qlist init
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-
-zarglist:
-       {
-               $$ = Z;
-       }
-|      arglist
-       {
-               $$ = invert($1);
-       }
-
-
-arglist:
-       name
-|      tlist abdecor
-       {
-               $$ = new(OPROTO, $2, Z);
-               $$->type = $1;
-       }
-|      tlist xdecor
-       {
-               $$ = new(OPROTO, $2, Z);
-               $$->type = $1;
-       }
-|      '.' '.' '.'
-       {
-               $$ = new(ODOTDOT, Z, Z);
-       }
-|      arglist ',' arglist
-       {
-               $$ = new(OLIST, $1, $3);
-       }
-
-block:
-       '{' slist '}'
-       {
-               $$ = invert($2);
-       //      if($2 != Z)
-       //              $$ = new(OLIST, $2, $$);
-               if($$ == Z)
-                       $$ = new(OLIST, Z, Z);
-       }
-
-slist:
-       {
-               $$ = Z;
-       }
-|      slist adecl
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-|      slist stmnt
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-
-labels:
-       label
-|      labels label
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-
-label:
-       LCASE expr ':'
-       {
-               $$ = new(OCASE, $2, Z);
-       }
-|      LDEFAULT ':'
-       {
-               $$ = new(OCASE, Z, Z);
-       }
-|      LNAME ':'
-       {
-               $$ = new(OLABEL, dcllabel($1, 1), Z);
-       }
-
-stmnt:
-       error ';'
-       {
-               $$ = Z;
-       }
-|      ulstmnt
-|      labels ulstmnt
-       {
-               $$ = new(OLIST, $1, $2);
-       }
-
-forexpr:
-       zcexpr
-|      ctlist adlist
-       {
-               $$ = $2;
-       }
-
-ulstmnt:
-       zcexpr ';'
-|      {
-               markdcl();
-       }
-       block
-       {
-               $$ = revertdcl();
-               if($$)
-                       $$ = new(OLIST, $$, $2);
-               else
-                       $$ = $2;
-       }
-|      LIF '(' cexpr ')' stmnt
-       {
-               $$ = new(OIF, $3, new(OLIST, $5, Z));
-               if($5 == Z)
-                       warn($3, "empty if body");
-       }
-|      LIF '(' cexpr ')' stmnt LELSE stmnt
-       {
-               $$ = new(OIF, $3, new(OLIST, $5, $7));
-               if($5 == Z)
-                       warn($3, "empty if body");
-               if($7 == Z)
-                       warn($3, "empty else body");
-       }
-|      { markdcl(); } LFOR '(' forexpr ';' zcexpr ';' zcexpr ')' stmnt
-       {
-               $$ = revertdcl();
-               if($$){
-                       if($4)
-                               $4 = new(OLIST, $$, $4);
-                       else
-                               $4 = $$;
-               }
-               $$ = new(OFOR, new(OLIST, $6, new(OLIST, $4, $8)), $10);
-       }
-|      LWHILE '(' cexpr ')' stmnt
-       {
-               $$ = new(OWHILE, $3, $5);
-       }
-|      LDO stmnt LWHILE '(' cexpr ')' ';'
-       {
-               $$ = new(ODWHILE, $5, $2);
-       }
-|      LRETURN zcexpr ';'
-       {
-               $$ = new(ORETURN, $2, Z);
-               $$->type = thisfn->link;
-       }
-|      LSWITCH '(' cexpr ')' stmnt
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->vconst = 0;
-               $$->type = types[TINT];
-               $3 = new(OSUB, $$, $3);
-
-               $$ = new(OCONST, Z, Z);
-               $$->vconst = 0;
-               $$->type = types[TINT];
-               $3 = new(OSUB, $$, $3);
-
-               $$ = new(OSWITCH, $3, $5);
-       }
-|      LBREAK ';'
-       {
-               $$ = new(OBREAK, Z, Z);
-       }
-|      LCONTINUE ';'
-       {
-               $$ = new(OCONTINUE, Z, Z);
-       }
-|      LGOTO ltag ';'
-       {
-               $$ = new(OGOTO, dcllabel($2, 0), Z);
-       }
-|      LUSED '(' zelist ')' ';'
-       {
-               $$ = new(OUSED, $3, Z);
-       }
-|      LPREFETCH '(' zelist ')' ';'
-       {
-               $$ = new(OPREFETCH, $3, Z);
-       }
-|      LSET '(' zelist ')' ';'
-       {
-               $$ = new(OSET, $3, Z);
-       }
-
-zcexpr:
-       {
-               $$ = Z;
-       }
-|      cexpr
-
-zexpr:
-       {
-               $$ = Z;
-       }
-|      lexpr
-
-lexpr:
-       expr
-       {
-               $$ = new(OCAST, $1, Z);
-               $$->type = types[TLONG];
-       }
-
-cexpr:
-       expr
-|      cexpr ',' cexpr
-       {
-               $$ = new(OCOMMA, $1, $3);
-       }
-
-expr:
-       xuexpr
-|      expr '*' expr
-       {
-               $$ = new(OMUL, $1, $3);
-       }
-|      expr '/' expr
-       {
-               $$ = new(ODIV, $1, $3);
-       }
-|      expr '%' expr
-       {
-               $$ = new(OMOD, $1, $3);
-       }
-|      expr '+' expr
-       {
-               $$ = new(OADD, $1, $3);
-       }
-|      expr '-' expr
-       {
-               $$ = new(OSUB, $1, $3);
-       }
-|      expr LRSH expr
-       {
-               $$ = new(OASHR, $1, $3);
-       }
-|      expr LLSH expr
-       {
-               $$ = new(OASHL, $1, $3);
-       }
-|      expr '<' expr
-       {
-               $$ = new(OLT, $1, $3);
-       }
-|      expr '>' expr
-       {
-               $$ = new(OGT, $1, $3);
-       }
-|      expr LLE expr
-       {
-               $$ = new(OLE, $1, $3);
-       }
-|      expr LGE expr
-       {
-               $$ = new(OGE, $1, $3);
-       }
-|      expr LEQ expr
-       {
-               $$ = new(OEQ, $1, $3);
-       }
-|      expr LNE expr
-       {
-               $$ = new(ONE, $1, $3);
-       }
-|      expr '&' expr
-       {
-               $$ = new(OAND, $1, $3);
-       }
-|      expr '^' expr
-       {
-               $$ = new(OXOR, $1, $3);
-       }
-|      expr '|' expr
-       {
-               $$ = new(OOR, $1, $3);
-       }
-|      expr LANDAND expr
-       {
-               $$ = new(OANDAND, $1, $3);
-       }
-|      expr LOROR expr
-       {
-               $$ = new(OOROR, $1, $3);
-       }
-|      expr '?' cexpr ':' expr
-       {
-               $$ = new(OCOND, $1, new(OLIST, $3, $5));
-       }
-|      expr '=' expr
-       {
-               $$ = new(OAS, $1, $3);
-       }
-|      expr LPE expr
-       {
-               $$ = new(OASADD, $1, $3);
-       }
-|      expr LME expr
-       {
-               $$ = new(OASSUB, $1, $3);
-       }
-|      expr LMLE expr
-       {
-               $$ = new(OASMUL, $1, $3);
-       }
-|      expr LDVE expr
-       {
-               $$ = new(OASDIV, $1, $3);
-       }
-|      expr LMDE expr
-       {
-               $$ = new(OASMOD, $1, $3);
-       }
-|      expr LLSHE expr
-       {
-               $$ = new(OASASHL, $1, $3);
-       }
-|      expr LRSHE expr
-       {
-               $$ = new(OASASHR, $1, $3);
-       }
-|      expr LANDE expr
-       {
-               $$ = new(OASAND, $1, $3);
-       }
-|      expr LXORE expr
-       {
-               $$ = new(OASXOR, $1, $3);
-       }
-|      expr LORE expr
-       {
-               $$ = new(OASOR, $1, $3);
-       }
-
-xuexpr:
-       uexpr
-|      '(' tlist abdecor ')' xuexpr
-       {
-               $$ = new(OCAST, $5, Z);
-               dodecl(NODECL, CXXX, $2, $3);
-               $$->type = lastdcl;
-               $$->xcast = 1;
-       }
-|      '(' tlist abdecor ')' '{' ilist '}'     /* extension */
-       {
-               $$ = new(OSTRUCT, $6, Z);
-               dodecl(NODECL, CXXX, $2, $3);
-               $$->type = lastdcl;
-       }
-
-uexpr:
-       pexpr
-|      '*' xuexpr
-       {
-               $$ = new(OIND, $2, Z);
-       }
-|      '&' xuexpr
-       {
-               $$ = new(OADDR, $2, Z);
-       }
-|      '+' xuexpr
-       {
-               $$ = new(OPOS, $2, Z);
-       }
-|      '-' xuexpr
-       {
-               $$ = new(ONEG, $2, Z);
-       }
-|      '!' xuexpr
-       {
-               $$ = new(ONOT, $2, Z);
-       }
-|      '~' xuexpr
-       {
-               $$ = new(OCOM, $2, Z);
-       }
-|      LPP xuexpr
-       {
-               $$ = new(OPREINC, $2, Z);
-       }
-|      LMM xuexpr
-       {
-               $$ = new(OPREDEC, $2, Z);
-       }
-|      LSIZEOF uexpr
-       {
-               $$ = new(OSIZE, $2, Z);
-       }
-|      LSIGNOF uexpr
-       {
-               $$ = new(OSIGN, $2, Z);
-       }
-
-pexpr:
-       '(' cexpr ')'
-       {
-               $$ = $2;
-       }
-|      LSIZEOF '(' tlist abdecor ')'
-       {
-               $$ = new(OSIZE, Z, Z);
-               dodecl(NODECL, CXXX, $3, $4);
-               $$->type = lastdcl;
-       }
-|      LSIGNOF '(' tlist abdecor ')'
-       {
-               $$ = new(OSIGN, Z, Z);
-               dodecl(NODECL, CXXX, $3, $4);
-               $$->type = lastdcl;
-       }
-|      pexpr '(' zelist ')'
-       {
-               $$ = new(OFUNC, $1, Z);
-               if($1->op == ONAME)
-               if($1->type == T)
-                       dodecl(xdecl, CXXX, types[TINT], $$);
-               $$->right = invert($3);
-       }
-|      pexpr '[' cexpr ']'
-       {
-               $$ = new(OIND, new(OADD, $1, $3), Z);
-       }
-|      pexpr LMG ltag
-       {
-               $$ = new(ODOT, new(OIND, $1, Z), Z);
-               $$->sym = $3;
-       }
-|      pexpr '.' ltag
-       {
-               $$ = new(ODOT, $1, Z);
-               $$->sym = $3;
-       }
-|      pexpr LPP
-       {
-               $$ = new(OPOSTINC, $1, Z);
-       }
-|      pexpr LMM
-       {
-               $$ = new(OPOSTDEC, $1, Z);
-       }
-|      name
-|      LCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TINT];
-               $$->vconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LLCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TLONG];
-               $$->vconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LUCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TUINT];
-               $$->vconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LULCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TULONG];
-               $$->vconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LDCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TDOUBLE];
-               $$->fconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LFCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TFLOAT];
-               $$->fconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LVLCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TVLONG];
-               $$->vconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      LUVLCONST
-       {
-               $$ = new(OCONST, Z, Z);
-               $$->type = types[TUVLONG];
-               $$->vconst = $1;
-               $$->cstring = strdup(symb);
-       }
-|      string
-|      lstring
-
-string:
-       LSTRING
-       {
-               $$ = new(OSTRING, Z, Z);
-               $$->type = typ(TARRAY, types[TCHAR]);
-               $$->type->width = $1.l + 1;
-               $$->cstring = $1.s;
-               $$->sym = symstring;
-               $$->etype = TARRAY;
-               $$->class = CSTATIC;
-       }
-|      string LSTRING
-       {
-               char *s;
-               int n;
-
-               n = $1->type->width - 1;
-               s = alloc(n+$2.l+MAXALIGN);
-
-               memcpy(s, $1->cstring, n);
-               memcpy(s+n, $2.s, $2.l);
-               s[n+$2.l] = 0;
-
-               $$ = $1;
-               $$->type->width += $2.l;
-               $$->cstring = s;
-       }
-
-lstring:
-       LLSTRING
-       {
-               $$ = new(OLSTRING, Z, Z);
-               $$->type = typ(TARRAY, types[TRUNE]);
-               $$->type->width = $1.l + sizeof(TRune);
-               $$->rstring = (TRune*)$1.s;
-               $$->sym = symstring;
-               $$->etype = TARRAY;
-               $$->class = CSTATIC;
-       }
-|      lstring LLSTRING
-       {
-               char *s;
-               int n;
-
-               n = $1->type->width - sizeof(TRune);
-               s = alloc(n+$2.l+MAXALIGN);
-
-               memcpy(s, $1->rstring, n);
-               memcpy(s+n, $2.s, $2.l);
-               *(TRune*)(s+n+$2.l) = 0;
-
-               $$ = $1;
-               $$->type->width += $2.l;
-               $$->rstring = (TRune*)s;
-       }
-
-zelist:
-       {
-               $$ = Z;
-       }
-|      elist
-
-elist:
-       expr
-|      elist ',' elist
-       {
-               $$ = new(OLIST, $1, $3);
-       }
-
-sbody:
-       '{'
-       {
-               $<tyty>$.t1 = strf;
-               $<tyty>$.t2 = strl;
-               $<tyty>$.t3 = lasttype;
-               $<tyty>$.c = lastclass;
-               strf = T;
-               strl = T;
-               lastbit = 0;
-               firstbit = 1;
-               lastclass = CXXX;
-               lasttype = T;
-       }
-       edecl '}'
-       {
-               $$ = strf;
-               strf = $<tyty>2.t1;
-               strl = $<tyty>2.t2;
-               lasttype = $<tyty>2.t3;
-               lastclass = $<tyty>2.c;
-       }
-
-zctlist:
-       {
-               lastclass = CXXX;
-               lasttype = types[TINT];
-       }
-|      ctlist
-
-types:
-       complex
-       {
-               $$.t = $1;
-               $$.c = CXXX;
-       }
-|      tname
-       {
-               $$.t = simplet($1);
-               $$.c = CXXX;
-       }
-|      gcnlist
-       {
-               $$.t = simplet($1);
-               $$.c = simplec($1);
-               $$.t = garbt($$.t, $1);
-       }
-|      complex gctnlist
-       {
-               $$.t = $1;
-               $$.c = simplec($2);
-               $$.t = garbt($$.t, $2);
-               if($2 & ~BCLASS & ~BGARB)
-                       diag(Z, "duplicate types given: %T and %Q", $1, $2);
-       }
-|      tname gctnlist
-       {
-               $$.t = simplet(typebitor($1, $2));
-               $$.c = simplec($2);
-               $$.t = garbt($$.t, $2);
-       }
-|      gcnlist complex zgnlist
-       {
-               $$.t = $2;
-               $$.c = simplec($1);
-               $$.t = garbt($$.t, $1|$3);
-       }
-|      gcnlist tname
-       {
-               $$.t = simplet($2);
-               $$.c = simplec($1);
-               $$.t = garbt($$.t, $1);
-       }
-|      gcnlist tname gctnlist
-       {
-               $$.t = simplet(typebitor($2, $3));
-               $$.c = simplec($1|$3);
-               $$.t = garbt($$.t, $1|$3);
-       }
-
-tlist:
-       types
-       {
-               $$ = $1.t;
-               if($1.c != CXXX)
-                       diag(Z, "illegal combination of class 4: %s", cnames[$1.c]);
-       }
-
-ctlist:
-       types
-       {
-               lasttype = $1.t;
-               lastclass = $1.c;
-       }
-
-complex:
-       LSTRUCT ltag
-       {
-               dotag($2, TSTRUCT, 0);
-               $$ = $2->suetag;
-       }
-|      LSTRUCT ltag
-       {
-               dotag($2, TSTRUCT, autobn);
-       }
-       sbody
-       {
-               $$ = $2->suetag;
-               if($$->link != T)
-                       diag(Z, "redeclare tag: %s", $2->name);
-               $$->link = $4;
-               sualign($$);
-       }
-|      LSTRUCT sbody
-       {
-               diag(Z, "struct must have tag");
-               taggen++;
-               sprint(symb, "_%d_", taggen);
-               $$ = dotag(lookup(), TSTRUCT, autobn);
-               $$->link = $2;
-               sualign($$);
-       }
-|      LUNION ltag
-       {
-               dotag($2, TUNION, 0);
-               $$ = $2->suetag;
-       }
-|      LUNION ltag
-       {
-               dotag($2, TUNION, autobn);
-       }
-       sbody
-       {
-               $$ = $2->suetag;
-               if($$->link != T)
-                       diag(Z, "redeclare tag: %s", $2->name);
-               $$->link = $4;
-               sualign($$);
-       }
-|      LUNION sbody
-       {
-               taggen++;
-               sprint(symb, "_%d_", taggen);
-               $$ = dotag(lookup(), TUNION, autobn);
-               $$->link = $2;
-               sualign($$);
-       }
-|      LENUM ltag
-       {
-               dotag($2, TENUM, 0);
-               $$ = $2->suetag;
-               if($$->link == T)
-                       $$->link = types[TINT];
-               $$ = $$->link;
-       }
-|      LENUM ltag
-       {
-               dotag($2, TENUM, autobn);
-       }
-       '{'
-       {
-               en.tenum = T;
-               en.cenum = T;
-       }
-       enum '}'
-       {
-               $$ = $2->suetag;
-               if($$->link != T)
-                       diag(Z, "redeclare tag: %s", $2->name);
-               if(en.tenum == T) {
-                       diag(Z, "enum type ambiguous: %s", $2->name);
-                       en.tenum = types[TINT];
-               }
-               $$->link = en.tenum;
-               $$ = en.tenum;
-       }
-|      LENUM '{'
-       {
-               en.tenum = T;
-               en.cenum = T;
-       }
-       enum '}'
-       {
-               $$ = en.tenum;
-       }
-|      LTYPE
-       {
-               $$ = tcopy($1->type);
-       }
-
-gctnlist:
-       gctname
-|      gctnlist gctname
-       {
-               $$ = typebitor($1, $2);
-       }
-
-zgnlist:
-       {
-               $$ = 0;
-       }
-|      zgnlist gname
-       {
-               $$ = typebitor($1, $2);
-       }
-
-gctname:
-       tname
-|      gname
-|      cname
-
-gcnlist:
-       gcname
-|      gcnlist gcname
-       {
-               $$ = typebitor($1, $2);
-       }
-
-gcname:
-       gname
-|      cname
-
-enum:
-       LNAME
-       {
-               doenum($1, Z);
-       }
-|      LNAME '=' expr
-       {
-               doenum($1, $3);
-       }
-|      enum ','
-|      enum ',' enum
-
-tname: /* type words */
-       LCHAR { $$ = BCHAR; }
-|      LSHORT { $$ = BSHORT; }
-|      LINT { $$ = BINT; }
-|      LLONG { $$ = BLONG; }
-|      LSIGNED { $$ = BSIGNED; }
-|      LUNSIGNED { $$ = BUNSIGNED; }
-|      LFLOAT { $$ = BFLOAT; }
-|      LDOUBLE { $$ = BDOUBLE; }
-|      LVOID { $$ = BVOID; }
-
-cname: /* class words */
-       LAUTO { $$ = BAUTO; }
-|      LSTATIC { $$ = BSTATIC; }
-|      LEXTERN { $$ = BEXTERN; }
-|      LTYPEDEF { $$ = BTYPEDEF; }
-|      LTYPESTR { $$ = BTYPESTR; }
-|      LREGISTER { $$ = BREGISTER; }
-|      LINLINE { $$ = 0; }
-
-gname: /* garbage words */
-       LCONSTNT { $$ = BCONSTNT; }
-|      LVOLATILE { $$ = BVOLATILE; }
-|      LRESTRICT { $$ = 0; }
-
-name:
-       LNAME
-       {
-               $$ = new(ONAME, Z, Z);
-               if($1->class == CLOCAL)
-                       $1 = mkstatic($1);
-               $$->sym = $1;
-               $$->type = $1->type;
-               $$->etype = TVOID;
-               if($$->type != T)
-                       $$->etype = $$->type->etype;
-               $$->xoffset = $1->offset;
-               $$->class = $1->class;
-               $1->aused = 1;
-       }
-tag:
-       ltag
-       {
-               $$ = new(ONAME, Z, Z);
-               $$->sym = $1;
-               $$->type = $1->type;
-               $$->etype = TVOID;
-               if($$->type != T)
-                       $$->etype = $$->type->etype;
-               $$->xoffset = $1->offset;
-               $$->class = $1->class;
-       }
-ltag:
-       LNAME
-|      LTYPE
-%%
diff --git a/src/cmd/cc/com.c b/src/cmd/cc/com.c
deleted file mode 100644 (file)
index 4886b73..0000000
+++ /dev/null
@@ -1,1384 +0,0 @@
-// Inferno utils/cc/com.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/com.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-int compar(Node*, int);
-
-void
-complex(Node *n)
-{
-
-       if(n == Z)
-               return;
-
-       nearln = n->lineno;
-       if(debug['t'])
-               if(n->op != OCONST)
-                       prtree(n, "pre complex");
-       if(tcom(n))
-               return;
-       if(debug['t'])
-               if(n->op != OCONST)
-                       prtree(n, "t complex");
-       ccom(n);
-       if(debug['t'])
-               if(n->op != OCONST)
-                       prtree(n, "c complex");
-       acom(n);
-       if(debug['t'])
-               if(n->op != OCONST)
-                       prtree(n, "a complex");
-       xcom(n);
-       if(debug['t'])
-               if(n->op != OCONST)
-                       prtree(n, "x complex");
-}
-
-/*
- * evaluate types
- * evaluate lvalues (addable == 1)
- */
-enum
-{
-       ADDROF  = 1<<0,
-       CASTOF  = 1<<1,
-       ADDROP  = 1<<2,
-};
-
-int
-tcom(Node *n)
-{
-
-       return tcomo(n, ADDROF);
-}
-
-int
-tcomo(Node *n, int f)
-{
-       Node *l, *r;
-       Type *t;
-       int o;
-       static TRune zer;
-
-       if(n == Z) {
-               diag(Z, "Z in tcom");
-               errorexit();
-       }
-       n->addable = 0;
-       l = n->left;
-       r = n->right;
-
-       switch(n->op) {
-       default:
-               diag(n, "unknown op in type complex: %O", n->op);
-               goto bad;
-
-       case ODOTDOT:
-               /*
-                * tcom has already been called on this subtree
-                */
-               *n = *n->left;
-               if(n->type == T)
-                       goto bad;
-               break;
-
-       case OCAST:
-               if(n->type == T)
-                       break;
-               if(n->type->width == types[TLONG]->width) {
-                       if(tcomo(l, ADDROF|CASTOF))
-                               goto bad;
-               } else
-                       if(tcom(l))
-                               goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, n->type, tcast))
-                       goto bad;
-               break;
-
-       case ORETURN:
-               if(l == Z) {
-                       if(n->type->etype != TVOID)
-                               diag(n, "null return of a typed function");
-                       break;
-               }
-               if(tcom(l))
-                       goto bad;
-               typeext(n->type, l);
-               if(tcompat(n, n->type, l->type, tasign))
-                       break;
-               constas(n, n->type, l->type);
-               if(!sametype(n->type, l->type)) {
-                       l = new1(OCAST, l, Z);
-                       l->type = n->type;
-                       n->left = l;
-               }
-               break;
-
-       case OASI:      /* same as as, but no test for const */
-               n->op = OAS;
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-
-               typeext(l->type, r);
-               if(tlvalue(l) || tcompat(n, l->type, r->type, tasign))
-                       goto bad;
-               if(!sametype(l->type, r->type)) {
-                       r = new1(OCAST, r, Z);
-                       r->type = l->type;
-                       n->right = r;
-               }
-               n->type = l->type;
-               break;
-
-       case OAS:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               typeext(l->type, r);
-               if(tcompat(n, l->type, r->type, tasign))
-                       goto bad;
-               constas(n, l->type, r->type);
-               if(!sametype(l->type, r->type)) {
-                       r = new1(OCAST, r, Z);
-                       r->type = l->type;
-                       n->right = r;
-               }
-               n->type = l->type;
-               break;
-
-       case OASADD:
-       case OASSUB:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               typeext1(l->type, r);
-               if(tcompat(n, l->type, r->type, tasadd))
-                       goto bad;
-               constas(n, l->type, r->type);
-               t = l->type;
-               arith(n, 0);
-               while(n->left->op == OCAST)
-                       n->left = n->left->left;
-               if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
-                       r = new1(OCAST, n->right, Z);
-                       r->type = t;
-                       n->right = r;
-                       n->type = t;
-               }
-               break;
-
-       case OASMUL:
-       case OASLMUL:
-       case OASDIV:
-       case OASLDIV:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               typeext1(l->type, r);
-               if(tcompat(n, l->type, r->type, tmul))
-                       goto bad;
-               constas(n, l->type, r->type);
-               t = l->type;
-               arith(n, 0);
-               while(n->left->op == OCAST)
-                       n->left = n->left->left;
-               if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
-                       r = new1(OCAST, n->right, Z);
-                       r->type = t;
-                       n->right = r;
-                       n->type = t;
-               }
-               if(typeu[n->type->etype]) {
-                       if(n->op == OASDIV)
-                               n->op = OASLDIV;
-                       if(n->op == OASMUL)
-                               n->op = OASLMUL;
-               }
-               break;
-
-       case OASLSHR:
-       case OASASHR:
-       case OASASHL:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tand))
-                       goto bad;
-               n->type = l->type;
-               if(typeu[n->type->etype]) {
-                       if(n->op == OASASHR)
-                               n->op = OASLSHR;
-               }
-               break;
-
-       case OASMOD:
-       case OASLMOD:
-       case OASOR:
-       case OASAND:
-       case OASXOR:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tand))
-                       goto bad;
-               t = l->type;
-               arith(n, 0);
-               while(n->left->op == OCAST)
-                       n->left = n->left->left;
-               if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
-                       r = new1(OCAST, n->right, Z);
-                       r->type = t;
-                       n->right = r;
-                       n->type = t;
-               }
-               if(typeu[n->type->etype]) {
-                       if(n->op == OASMOD)
-                               n->op = OASLMOD;
-               }
-               break;
-
-       case OPREINC:
-       case OPREDEC:
-       case OPOSTINC:
-       case OPOSTDEC:
-               if(tcom(l))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, types[TINT], tadd))
-                       goto bad;
-               n->type = l->type;
-               if(n->type->etype == TIND)
-               if(n->type->link->width < 1)
-                       diag(n, "inc/dec of a void pointer");
-               break;
-
-       case OEQ:
-       case ONE:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               typeext(l->type, r);
-               typeext(r->type, l);
-               if(tcompat(n, l->type, r->type, trel))
-                       goto bad;
-               arith(n, 0);
-               n->type = types[TINT];
-               break;
-
-       case OLT:
-       case OGE:
-       case OGT:
-       case OLE:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               typeext1(l->type, r);
-               typeext1(r->type, l);
-               if(tcompat(n, l->type, r->type, trel))
-                       goto bad;
-               arith(n, 0);
-               if(typeu[n->type->etype])
-                       n->op = logrel[relindex(n->op)];
-               n->type = types[TINT];
-               break;
-
-       case OCOND:
-               o = tcom(l);
-               o |= tcom(r->left);
-               if(o | tcom(r->right))
-                       goto bad;
-               if(r->right->type->etype == TIND && vconst(r->left) == 0) {
-                       r->left->type = r->right->type;
-                       r->left->vconst = 0;
-               }
-               if(r->left->type->etype == TIND && vconst(r->right) == 0) {
-                       r->right->type = r->left->type;
-                       r->right->vconst = 0;
-               }
-               if(sametype(r->right->type, r->left->type)) {
-                       r->type = r->right->type;
-                       n->type = r->type;
-                       break;
-               }
-               if(tcompat(r, r->left->type, r->right->type, trel))
-                       goto bad;
-               arith(r, 0);
-               n->type = r->type;
-               break;
-
-       case OADD:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tadd))
-                       goto bad;
-               arith(n, 1);
-               break;
-
-       case OSUB:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tsub))
-                       goto bad;
-               arith(n, 1);
-               break;
-
-       case OMUL:
-       case OLMUL:
-       case ODIV:
-       case OLDIV:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tmul))
-                       goto bad;
-               arith(n, 1);
-               if(typeu[n->type->etype]) {
-                       if(n->op == ODIV)
-                               n->op = OLDIV;
-                       if(n->op == OMUL)
-                               n->op = OLMUL;
-               }
-               break;
-
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tand))
-                       goto bad;
-               n->right = Z;
-               arith(n, 1);
-               n->right = new1(OCAST, r, Z);
-               n->right->type = types[TINT];
-               if(typeu[n->type->etype])
-                       if(n->op == OASHR)
-                               n->op = OLSHR;
-               break;
-
-       case OAND:
-       case OOR:
-       case OXOR:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tand))
-                       goto bad;
-               arith(n, 1);
-               break;
-
-       case OMOD:
-       case OLMOD:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, l->type, r->type, tand))
-                       goto bad;
-               arith(n, 1);
-               if(typeu[n->type->etype])
-                       n->op = OLMOD;
-               break;
-
-       case OPOS:
-               if(tcom(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-
-               r = l;
-               l = new(OCONST, Z, Z);
-               l->vconst = 0;
-               l->type = types[TINT];
-               n->op = OADD;
-               n->right = r;
-               n->left = l;
-
-               if(tcom(l))
-                       goto bad;
-               if(tcompat(n, l->type, r->type, tsub))
-                       goto bad;
-               arith(n, 1);
-               break;
-
-       case ONEG:
-               if(tcom(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-
-               if(!machcap(n)) {
-                       r = l;
-                       l = new(OCONST, Z, Z);
-                       l->vconst = 0;
-                       l->type = types[TINT];
-                       n->op = OSUB;
-                       n->right = r;
-                       n->left = l;
-
-                       if(tcom(l))
-                               goto bad;
-                       if(tcompat(n, l->type, r->type, tsub))
-                               goto bad;
-               }
-               arith(n, 1);
-               break;
-
-       case OCOM:
-               if(tcom(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-
-               if(!machcap(n)) {
-                       r = l;
-                       l = new(OCONST, Z, Z);
-                       l->vconst = -1;
-                       l->type = types[TINT];
-                       n->op = OXOR;
-                       n->right = r;
-                       n->left = l;
-
-                       if(tcom(l))
-                               goto bad;
-                       if(tcompat(n, l->type, r->type, tand))
-                               goto bad;
-               }
-               arith(n, 1);
-               break;
-
-       case ONOT:
-               if(tcom(l))
-                       goto bad;
-               if(isfunct(n))
-                       break;
-               if(tcompat(n, T, l->type, tnot))
-                       goto bad;
-               n->type = types[TINT];
-               break;
-
-       case OANDAND:
-       case OOROR:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               if(tcompat(n, T, l->type, tnot) |
-                  tcompat(n, T, r->type, tnot))
-                       goto bad;
-               n->type = types[TINT];
-               break;
-
-       case OCOMMA:
-               o = tcom(l);
-               if(o | tcom(r))
-                       goto bad;
-               n->type = r->type;
-               break;
-
-
-       case OSIGN:     /* extension signof(type) returns a hash */
-               if(l != Z) {
-                       if(l->op != OSTRING && l->op != OLSTRING)
-                               if(tcomo(l, 0))
-                                       goto bad;
-                       if(l->op == OBIT) {
-                               diag(n, "signof bitfield");
-                               goto bad;
-                       }
-                       n->type = l->type;
-               }
-               if(n->type == T)
-                       goto bad;
-               if(n->type->width < 0) {
-                       diag(n, "signof undefined type");
-                       goto bad;
-               }
-               n->op = OCONST;
-               n->left = Z;
-               n->right = Z;
-               n->vconst = convvtox(signature(n->type), TULONG);
-               n->type = types[TULONG];
-               break;
-
-       case OSIZE:
-               if(l != Z) {
-                       if(l->op != OSTRING && l->op != OLSTRING)
-                               if(tcomo(l, 0))
-                                       goto bad;
-                       if(l->op == OBIT) {
-                               diag(n, "sizeof bitfield");
-                               goto bad;
-                       }
-                       n->type = l->type;
-               }
-               if(n->type == T)
-                       goto bad;
-               if(n->type->width <= 0) {
-                       diag(n, "sizeof undefined type");
-                       goto bad;
-               }
-               if(n->type->etype == TFUNC) {
-                       diag(n, "sizeof function");
-                       goto bad;
-               }
-               n->op = OCONST;
-               n->left = Z;
-               n->right = Z;
-               n->vconst = convvtox(n->type->width, TINT);
-               n->type = types[TINT];
-               break;
-
-       case OFUNC:
-               o = tcomo(l, 0);
-               if(o)
-                       goto bad;
-               if(l->type->etype == TIND && l->type->link->etype == TFUNC) {
-                       l = new1(OIND, l, Z);
-                       l->type = l->left->type->link;
-                       n->left = l;
-               }
-               if(tcompat(n, T, l->type, tfunct))
-                       goto bad;
-               if(o | tcoma(l, r, l->type->down, 1))
-                       goto bad;
-               n->type = l->type->link;
-               if(!debug['B'])
-                       if(l->type->down == T || l->type->down->etype == TOLD) {
-                               nerrors--;
-                               diag(n, "function args not checked: %F", l);
-                       }
-               dpcheck(n);
-               break;
-
-       case ONAME:
-               if(n->type == T) {
-                       diag(n, "name not declared: %F", n);
-                       goto bad;
-               }
-               if(n->type->etype == TENUM) {
-                       n->op = OCONST;
-                       n->type = n->sym->tenum;
-                       if(!typefd[n->type->etype])
-                               n->vconst = n->sym->vconst;
-                       else
-                               n->fconst = n->sym->fconst;
-                       break;
-               }
-               n->addable = 1;
-               if(n->class == CEXREG) {
-                       n->op = OREGISTER;
-                       // on 386 or amd64, "extern register" generates
-                       // memory references relative to the
-                       // gs or fs segment.
-                       if(thechar == '8' || thechar == '6')    // [sic]
-                               n->op = OEXREG;
-                       n->reg = n->sym->offset;
-                       n->xoffset = 0;
-                       break;
-               }
-               break;
-
-       case OLSTRING:
-               if(n->type->link != types[TRUNE]) {
-                       o = outstring(0, 0);
-                       while(o & 3) {
-                               outlstring(&zer, sizeof(TRune));
-                               o = outlstring(0, 0);
-                       }
-               }
-               n->op = ONAME;
-               n->xoffset = outlstring(n->rstring, n->type->width);
-               n->addable = 1;
-               break;
-
-       case OSTRING:
-               if(n->type->link != types[TCHAR]) {
-                       o = outstring(0, 0);
-                       while(o & 3) {
-                               outstring("", 1);
-                               o = outstring(0, 0);
-                       }
-               }
-               n->op = ONAME;
-               n->xoffset = outstring(n->cstring, n->type->width);
-               n->addable = 1;
-               break;
-
-       case OCONST:
-               break;
-
-       case ODOT:
-               if(tcom(l))
-                       goto bad;
-               if(tcompat(n, T, l->type, tdot))
-                       goto bad;
-               if(tcomd(n))
-                       goto bad;
-               break;
-
-       case OADDR:
-               if(tcomo(l, ADDROP))
-                       goto bad;
-               if(tlvalue(l))
-                       goto bad;
-               if(l->type->nbits) {
-                       diag(n, "address of a bit field");
-                       goto bad;
-               }
-               if(l->op == OREGISTER) {
-                       diag(n, "address of a register");
-                       goto bad;
-               }
-               n->type = typ(TIND, l->type);
-               n->type->width = types[TIND]->width;
-               break;
-
-       case OIND:
-               if(tcom(l))
-                       goto bad;
-               if(tcompat(n, T, l->type, tindir))
-                       goto bad;
-               n->type = l->type->link;
-               n->addable = 1;
-               break;
-
-       case OSTRUCT:
-               if(tcomx(n))
-                       goto bad;
-               break;
-       }
-       t = n->type;
-       if(t == T)
-               goto bad;
-       if(t->width < 0) {
-               snap(t);
-               if(t->width < 0) {
-                       if(typesu[t->etype] && t->tag)
-                               diag(n, "structure not fully declared %s", t->tag->name);
-                       else
-                               diag(n, "structure not fully declared");
-                       goto bad;
-               }
-       }
-       if(typeaf[t->etype]) {
-               if(f & ADDROF)
-                       goto addaddr;
-               if(f & ADDROP)
-                       warn(n, "address of array/func ignored");
-       }
-       return 0;
-
-addaddr:
-       if(tlvalue(n))
-               goto bad;
-       l = new1(OXXX, Z, Z);
-       *l = *n;
-       n->op = OADDR;
-       if(l->type->etype == TARRAY)
-               l->type = l->type->link;
-       n->left = l;
-       n->right = Z;
-       n->addable = 0;
-       n->type = typ(TIND, l->type);
-       n->type->width = types[TIND]->width;
-       return 0;
-
-bad:
-       n->type = T;
-       return 1;
-}
-
-int
-tcoma(Node *l, Node *n, Type *t, int f)
-{
-       Node *n1;
-       int o;
-
-       if(t != T)
-       if(t->etype == TOLD || t->etype == TDOT)        /* .../old in prototype */
-               t = T;
-       if(n == Z) {
-               if(t != T && !sametype(t, types[TVOID])) {
-                       diag(n, "not enough function arguments: %F", l);
-                       return 1;
-               }
-               return 0;
-       }
-       if(n->op == OLIST) {
-               o = tcoma(l, n->left, t, 0);
-               if(t != T) {
-                       t = t->down;
-                       if(t == T)
-                               t = types[TVOID];
-               }
-               return o | tcoma(l, n->right, t, 1);
-       }
-       if(f && t != T)
-               tcoma(l, Z, t->down, 0);
-       if(tcom(n) || tcompat(n, T, n->type, targ))
-               return 1;
-       if(sametype(t, types[TVOID])) {
-               diag(n, "too many function arguments: %F", l);
-               return 1;
-       }
-       if(t != T) {
-               typeext(t, n);
-               if(stcompat(nodproto, t, n->type, tasign)) {
-                       diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F",
-                               n->type, t, l);
-                       return 1;
-               }
-//             switch(t->etype) {
-//             case TCHAR:
-//             case TSHORT:
-//                     t = types[TINT];
-//                     break;
-//
-//             case TUCHAR:
-//             case TUSHORT:
-//                     t = types[TUINT];
-//                     break;
-//             }
-       } else {
-               switch(n->type->etype) {
-               case TCHAR:
-               case TSHORT:
-                       t = types[TINT];
-                       break;
-
-               case TUCHAR:
-               case TUSHORT:
-                       t = types[TUINT];
-                       break;
-
-               case TFLOAT:
-                       t = types[TDOUBLE];
-               }
-       }
-
-       if(t != T && !sametype(t, n->type)) {
-               n1 = new1(OXXX, Z, Z);
-               *n1 = *n;
-               n->op = OCAST;
-               n->left = n1;
-               n->right = Z;
-               n->type = t;
-               n->addable = 0;
-       }
-       return 0;
-}
-
-int
-tcomd(Node *n)
-{
-       Type *t;
-       int32 o;
-
-       o = 0;
-       t = dotsearch(n->sym, n->left->type->link, n, &o);
-       if(t == T) {
-               diag(n, "not a member of struct/union: %F", n);
-               return 1;
-       }
-       makedot(n, t, o);
-       return 0;
-}
-
-int
-tcomx(Node *n)
-{
-       Type *t;
-       Node *l, *r, **ar, **al;
-       int e;
-
-       e = 0;
-       if(n->type->etype != TSTRUCT) {
-               diag(n, "constructor must be a structure");
-               return 1;
-       }
-       l = invert(n->left);
-       n->left = l;
-       al = &n->left;
-       for(t = n->type->link; t != T; t = t->down) {
-               if(l == Z) {
-                       diag(n, "constructor list too short");
-                       return 1;
-               }
-               if(l->op == OLIST) {
-                       r = l->left;
-                       ar = &l->left;
-                       al = &l->right;
-                       l = l->right;
-               } else {
-                       r = l;
-                       ar = al;
-                       l = Z;
-               }
-               if(tcom(r))
-                       e++;
-               typeext(t, r);
-               if(tcompat(n, t, r->type, tasign))
-                       e++;
-               constas(n, t, r->type);
-               if(!e && !sametype(t, r->type)) {
-                       r = new1(OCAST, r, Z);
-                       r->type = t;
-                       *ar = r;
-               }
-       }
-       if(l != Z) {
-               diag(n, "constructor list too long");
-               return 1;
-       }
-       return e;
-}
-
-int
-tlvalue(Node *n)
-{
-
-       if(!n->addable) {
-               diag(n, "not an l-value");
-               return 1;
-       }
-       return 0;
-}
-
-/*
- *     general rewrite
- *     (IND(ADDR x)) ==> x
- *     (ADDR(IND x)) ==> x
- *     remove some zero operands
- *     remove no op casts
- *     evaluate constants
- */
-void
-ccom(Node *n)
-{
-       Node *l, *r;
-       int t;
-
-loop:
-       if(n == Z)
-               return;
-       l = n->left;
-       r = n->right;
-       switch(n->op) {
-
-       case OAS:
-       case OASXOR:
-       case OASAND:
-       case OASOR:
-       case OASMOD:
-       case OASLMOD:
-       case OASLSHR:
-       case OASASHR:
-       case OASASHL:
-       case OASDIV:
-       case OASLDIV:
-       case OASMUL:
-       case OASLMUL:
-       case OASSUB:
-       case OASADD:
-               ccom(l);
-               ccom(r);
-               if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL)
-               if(r->op == OCONST) {
-                       t = n->type->width * 8; /* bits per byte */
-                       if(r->vconst >= t || r->vconst < 0)
-                               warn(n, "stupid shift: %lld", r->vconst);
-               }
-               break;
-
-       case OCAST:
-               ccom(l);
-               if(l->op == OCONST) {
-                       evconst(n);
-                       if(n->op == OCONST)
-                               break;
-               }
-               if(nocast(l->type, n->type)) {
-                       l->type = n->type;
-                       *n = *l;
-               }
-               break;
-
-       case OCOND:
-               ccom(l);
-               ccom(r);
-               if(l->op == OCONST)
-                       if(vconst(l) == 0)
-                               *n = *r->right;
-                       else
-                               *n = *r->left;
-               break;
-
-       case OREGISTER:
-       case OINDREG:
-       case OCONST:
-       case ONAME:
-               break;
-
-       case OADDR:
-               ccom(l);
-               l->etype = TVOID;
-               if(l->op == OIND) {
-                       l->left->type = n->type;
-                       *n = *l->left;
-                       break;
-               }
-               goto common;
-
-       case OIND:
-               ccom(l);
-               if(l->op == OADDR) {
-                       l->left->type = n->type;
-                       *n = *l->left;
-                       break;
-               }
-               goto common;
-
-       case OEQ:
-       case ONE:
-
-       case OLE:
-       case OGE:
-       case OLT:
-       case OGT:
-
-       case OLS:
-       case OHS:
-       case OLO:
-       case OHI:
-               ccom(l);
-               ccom(r);
-               if(compar(n, 0) || compar(n, 1))
-                       break;
-               relcon(l, r);
-               relcon(r, l);
-               goto common;
-
-       case OASHR:
-       case OASHL:
-       case OLSHR:
-               ccom(l);
-               if(vconst(l) == 0 && !side(r)) {
-                       *n = *l;
-                       break;
-               }
-               ccom(r);
-               if(vconst(r) == 0) {
-                       *n = *l;
-                       break;
-               }
-               if(r->op == OCONST) {
-                       t = n->type->width * 8; /* bits per byte */
-                       if(r->vconst >= t || r->vconst <= -t)
-                               warn(n, "stupid shift: %lld", r->vconst);
-               }
-               goto common;
-
-       case OMUL:
-       case OLMUL:
-               ccom(l);
-               t = vconst(l);
-               if(t == 0 && !side(r)) {
-                       *n = *l;
-                       break;
-               }
-               if(t == 1) {
-                       *n = *r;
-                       goto loop;
-               }
-               ccom(r);
-               t = vconst(r);
-               if(t == 0 && !side(l)) {
-                       *n = *r;
-                       break;
-               }
-               if(t == 1) {
-                       *n = *l;
-                       break;
-               }
-               goto common;
-
-       case ODIV:
-       case OLDIV:
-               ccom(l);
-               if(vconst(l) == 0 && !side(r)) {
-                       *n = *l;
-                       break;
-               }
-               ccom(r);
-               t = vconst(r);
-               if(t == 0) {
-                       diag(n, "divide check");
-                       *n = *r;
-                       break;
-               }
-               if(t == 1) {
-                       *n = *l;
-                       break;
-               }
-               goto common;
-
-       case OSUB:
-               ccom(r);
-               if(r->op == OCONST) {
-                       if(typefd[r->type->etype]) {
-                               n->op = OADD;
-                               r->fconst = -r->fconst;
-                               goto loop;
-                       } else {
-                               n->op = OADD;
-                               r->vconst = -r->vconst;
-                               goto loop;
-                       }
-               }
-               ccom(l);
-               goto common;
-
-       case OXOR:
-       case OOR:
-       case OADD:
-               ccom(l);
-               if(vconst(l) == 0) {
-                       *n = *r;
-                       goto loop;
-               }
-               ccom(r);
-               if(vconst(r) == 0) {
-                       *n = *l;
-                       break;
-               }
-               goto commute;
-
-       case OAND:
-               ccom(l);
-               ccom(r);
-               if(vconst(l) == 0 && !side(r)) {
-                       *n = *l;
-                       break;
-               }
-               if(vconst(r) == 0 && !side(l)) {
-                       *n = *r;
-                       break;
-               }
-
-       commute:
-               /* look for commutative constant */
-               if(r->op == OCONST) {
-                       if(l->op == n->op) {
-                               if(l->left->op == OCONST) {
-                                       n->right = l->right;
-                                       l->right = r;
-                                       goto loop;
-                               }
-                               if(l->right->op == OCONST) {
-                                       n->right = l->left;
-                                       l->left = r;
-                                       goto loop;
-                               }
-                       }
-               }
-               if(l->op == OCONST) {
-                       if(r->op == n->op) {
-                               if(r->left->op == OCONST) {
-                                       n->left = r->right;
-                                       r->right = l;
-                                       goto loop;
-                               }
-                               if(r->right->op == OCONST) {
-                                       n->left = r->left;
-                                       r->left = l;
-                                       goto loop;
-                               }
-                       }
-               }
-               goto common;
-
-       case OANDAND:
-               ccom(l);
-               if(vconst(l) == 0) {
-                       *n = *l;
-                       break;
-               }
-               ccom(r);
-               goto common;
-
-       case OOROR:
-               ccom(l);
-               if(l->op == OCONST && l->vconst != 0) {
-                       *n = *l;
-                       n->vconst = 1;
-                       break;
-               }
-               ccom(r);
-               goto common;
-
-       default:
-               if(l != Z)
-                       ccom(l);
-               if(r != Z)
-                       ccom(r);
-       common:
-               if(l != Z)
-               if(l->op != OCONST)
-                       break;
-               if(r != Z)
-               if(r->op != OCONST)
-                       break;
-               evconst(n);
-       }
-}
-
-/*     OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */
-static char *cmps[12] = 
-{
-       "==", "!=", "<=", "<=", "<", "<", ">=", ">=", ">", ">",
-};
-
-/* 128-bit numbers */
-typedef struct Big Big;
-struct Big
-{
-       vlong a;
-       uvlong b;
-};
-static int
-cmp(Big x, Big y)
-{
-       if(x.a != y.a){
-               if(x.a < y.a)
-                       return -1;
-               return 1;
-       }
-       if(x.b != y.b){
-               if(x.b < y.b)
-                       return -1;
-               return 1;
-       }
-       return 0;
-}
-static Big
-add(Big x, int y)
-{
-       uvlong ob;
-       
-       ob = x.b;
-       x.b += y;
-       if(y > 0 && x.b < ob)
-               x.a++;
-       if(y < 0 && x.b > ob)
-               x.a--;
-       return x;
-} 
-
-Big
-big(vlong a, uvlong b)
-{
-       Big x;
-
-       x.a = a;
-       x.b = b;
-       return x;
-}
-
-int
-compar(Node *n, int reverse)
-{
-       Big lo, hi, x;
-       int op;
-       char xbuf[40], cmpbuf[50];
-       Node *l, *r;
-       Type *lt, *rt;
-
-       /*
-        * The point of this function is to diagnose comparisons 
-        * that can never be true or that look misleading because
-        * of the `usual arithmetic conversions'.  As an example 
-        * of the latter, if x is a ulong, then if(x <= -1) really means
-        * if(x <= 0xFFFFFFFF), while if(x <= -1LL) really means
-        * what it says (but 8c compiles it wrong anyway).
-        */
-
-       if(reverse){
-               r = n->left;
-               l = n->right;
-               op = comrel[relindex(n->op)];
-       }else{
-               l = n->left;
-               r = n->right;
-               op = n->op;
-       }
-
-       /*
-        * Skip over left casts to find out the original expression range.
-        */
-       while(l->op == OCAST)
-               l = l->left;
-       if(l->op == OCONST)
-               return 0;
-       lt = l->type;
-       if(l->op == ONAME && l->sym->type){
-               lt = l->sym->type;
-               if(lt->etype == TARRAY)
-                       lt = lt->link;
-       }
-       if(lt == T)
-               return 0;
-       if(lt->etype == TXXX || lt->etype > TUVLONG)
-               return 0;
-       
-       /*
-        * Skip over the right casts to find the on-screen value.
-        */
-       if(r->op != OCONST)
-               return 0;
-       while(r->oldop == OCAST && !r->xcast)
-               r = r->left;
-       rt = r->type;
-       if(rt == T)
-               return 0;
-
-       x.b = r->vconst;
-       x.a = 0;
-       if((rt->etype&1) && r->vconst < 0)      /* signed negative */
-               x.a = ~0ULL;
-
-       if((lt->etype&1)==0){
-               /* unsigned */
-               lo = big(0, 0);
-               if(lt->width == 8)
-                       hi = big(0, ~0ULL);
-               else
-                       hi = big(0, (1ULL<<(l->type->width*8))-1);
-       }else{
-               lo = big(~0ULL, -(1ULL<<(l->type->width*8-1)));
-               hi = big(0, (1ULL<<(l->type->width*8-1))-1);
-       }
-
-       switch(op){
-       case OLT:
-       case OLO:
-       case OGE:
-       case OHS:
-               if(cmp(x, lo) <= 0)
-                       goto useless;
-               if(cmp(x, add(hi, 1)) >= 0)
-                       goto useless;
-               break;
-       case OLE:
-       case OLS:
-       case OGT:
-       case OHI:
-               if(cmp(x, add(lo, -1)) <= 0)
-                       goto useless;
-               if(cmp(x, hi) >= 0)
-                       goto useless;
-               break;
-       case OEQ:
-       case ONE:
-               /*
-                * Don't warn about comparisons if the expression
-                * is as wide as the value: the compiler-supplied casts
-                * will make both outcomes possible.
-                */
-               if(lt->width >= rt->width && debug['w'] < 2)
-                       return 0;
-               if(cmp(x, lo) < 0 || cmp(x, hi) > 0)
-                       goto useless;
-               break;
-       }
-       return 0;
-
-useless:
-       if((x.a==0 && x.b<=9) || (x.a==~0LL && x.b >= -9ULL))
-               snprint(xbuf, sizeof xbuf, "%lld", x.b);
-       else if(x.a == 0)
-               snprint(xbuf, sizeof xbuf, "%#llux", x.b);
-       else
-               snprint(xbuf, sizeof xbuf, "%#llx", x.b);
-       if(reverse)
-               snprint(cmpbuf, sizeof cmpbuf, "%s %s %T",
-                       xbuf, cmps[relindex(n->op)], lt);
-       else
-               snprint(cmpbuf, sizeof cmpbuf, "%T %s %s",
-                       lt, cmps[relindex(n->op)], xbuf);
-       warn(n, "useless or misleading comparison: %s", cmpbuf);
-       return 0;
-}
-
diff --git a/src/cmd/cc/com64.c b/src/cmd/cc/com64.c
deleted file mode 100644 (file)
index f46fedc..0000000
+++ /dev/null
@@ -1,644 +0,0 @@
-// Inferno utils/cc/com64.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/com64.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-/*
- * this is machine depend, but it is totally
- * common on all of the 64-bit symulating machines.
- */
-
-#define        FNX     100     /* botch -- redefinition */
-
-Node*  nodaddv;
-Node*  nodsubv;
-Node*  nodmulv;
-Node*  noddivv;
-Node*  noddivvu;
-Node*  nodmodv;
-Node*  nodmodvu;
-Node*  nodlshv;
-Node*  nodrshav;
-Node*  nodrshlv;
-Node*  nodandv;
-Node*  nodorv;
-Node*  nodxorv;
-Node*  nodnegv;
-Node*  nodcomv;
-
-Node*  nodtestv;
-Node*  nodeqv;
-Node*  nodnev;
-Node*  nodlev;
-Node*  nodltv;
-Node*  nodgev;
-Node*  nodgtv;
-Node*  nodhiv;
-Node*  nodhsv;
-Node*  nodlov;
-Node*  nodlsv;
-
-Node*  nodf2v;
-Node*  nodd2v;
-Node*  nodp2v;
-Node*  nodsi2v;
-Node*  nodui2v;
-Node*  nodsl2v;
-Node*  nodul2v;
-Node*  nodsh2v;
-Node*  noduh2v;
-Node*  nodsc2v;
-Node*  noduc2v;
-
-Node*  nodv2f;
-Node*  nodv2d;
-Node*  nodv2ui;
-Node*  nodv2si;
-Node*  nodv2ul;
-Node*  nodv2sl;
-Node*  nodv2uh;
-Node*  nodv2sh;
-Node*  nodv2uc;
-Node*  nodv2sc;
-
-Node*  nodvpp;
-Node*  nodppv;
-Node*  nodvmm;
-Node*  nodmmv;
-
-Node*  nodvasop;
-
-char   etconv[NALLTYPES];      /* for _vasop */
-Init   initetconv[] =
-{
-       TCHAR,          1,      0,
-       TUCHAR,         2,      0,
-       TSHORT,         3,      0,
-       TUSHORT,        4,      0,
-       TLONG,          5,      0,
-       TULONG,         6,      0,
-       TVLONG,         7,      0,
-       TUVLONG,        8,      0,
-       TINT,           9,      0,
-       TUINT,          10,     0,
-       -1,             0,      0,
-};
-
-Node*
-fvn(char *name, int type)
-{
-       Node *n;
-
-       n = new(ONAME, Z, Z);
-       n->sym = slookup(name);
-       n->sym->sig = SIGINTERN;
-       if(fntypes[type] == 0)
-               fntypes[type] = typ(TFUNC, types[type]);
-       n->type = fntypes[type];
-       n->etype = type;
-       n->class = CGLOBL;
-       n->addable = 10;
-       n->complex = 0;
-       return n;
-}
-
-void
-com64init(void)
-{
-       Init *p;
-
-       nodaddv = fvn("_addv", TVLONG);
-       nodsubv = fvn("_subv", TVLONG);
-       nodmulv = fvn("_mulv", TVLONG);
-       noddivv = fvn("_divv", TVLONG);
-       noddivvu = fvn("_divvu", TVLONG);
-       nodmodv = fvn("_modv", TVLONG);
-       nodmodvu = fvn("_modvu", TVLONG);
-       nodlshv = fvn("_lshv", TVLONG);
-       nodrshav = fvn("_rshav", TVLONG);
-       nodrshlv = fvn("_rshlv", TVLONG);
-       nodandv = fvn("_andv", TVLONG);
-       nodorv = fvn("_orv", TVLONG);
-       nodxorv = fvn("_xorv", TVLONG);
-       nodnegv = fvn("_negv", TVLONG);
-       nodcomv = fvn("_comv", TVLONG);
-
-       nodtestv = fvn("_testv", TLONG);
-       nodeqv = fvn("_eqv", TLONG);
-       nodnev = fvn("_nev", TLONG);
-       nodlev = fvn("_lev", TLONG);
-       nodltv = fvn("_ltv", TLONG);
-       nodgev = fvn("_gev", TLONG);
-       nodgtv = fvn("_gtv", TLONG);
-       nodhiv = fvn("_hiv", TLONG);
-       nodhsv = fvn("_hsv", TLONG);
-       nodlov = fvn("_lov", TLONG);
-       nodlsv = fvn("_lsv", TLONG);
-
-       nodf2v = fvn("_f2v", TVLONG);
-       nodd2v = fvn("_d2v", TVLONG);
-       nodp2v = fvn("_p2v", TVLONG);
-       nodsi2v = fvn("_si2v", TVLONG);
-       nodui2v = fvn("_ui2v", TVLONG);
-       nodsl2v = fvn("_sl2v", TVLONG);
-       nodul2v = fvn("_ul2v", TVLONG);
-       nodsh2v = fvn("_sh2v", TVLONG);
-       noduh2v = fvn("_uh2v", TVLONG);
-       nodsc2v = fvn("_sc2v", TVLONG);
-       noduc2v = fvn("_uc2v", TVLONG);
-
-       nodv2f = fvn("_v2f", TFLOAT);
-       nodv2d = fvn("_v2d", TDOUBLE);
-       nodv2sl = fvn("_v2sl", TLONG);
-       nodv2ul = fvn("_v2ul", TULONG);
-       nodv2si = fvn("_v2si", TINT);
-       nodv2ui = fvn("_v2ui", TUINT);
-       nodv2sh = fvn("_v2sh", TSHORT);
-       nodv2uh = fvn("_v2ul", TUSHORT);
-       nodv2sc = fvn("_v2sc", TCHAR);
-       nodv2uc = fvn("_v2uc", TUCHAR);
-
-       nodvpp = fvn("_vpp", TVLONG);
-       nodppv = fvn("_ppv", TVLONG);
-       nodvmm = fvn("_vmm", TVLONG);
-       nodmmv = fvn("_mmv", TVLONG);
-
-       nodvasop = fvn("_vasop", TVLONG);
-
-       for(p = initetconv; p->code >= 0; p++)
-               etconv[p->code] = p->value;
-}
-
-int
-com64(Node *n)
-{
-       Node *l, *r, *a, *t;
-       int lv, rv;
-
-       if(n->type == 0)
-               return 0;
-
-       l = n->left;
-       r = n->right;
-
-       lv = 0;
-       if(l && l->type && typev[l->type->etype])
-               lv = 1;
-       rv = 0;
-       if(r && r->type && typev[r->type->etype])
-               rv = 1;
-
-       if(lv) {
-               switch(n->op) {
-               case OEQ:
-                       a = nodeqv;
-                       goto setbool;
-               case ONE:
-                       a = nodnev;
-                       goto setbool;
-               case OLE:
-                       a = nodlev;
-                       goto setbool;
-               case OLT:
-                       a = nodltv;
-                       goto setbool;
-               case OGE:
-                       a = nodgev;
-                       goto setbool;
-               case OGT:
-                       a = nodgtv;
-                       goto setbool;
-               case OHI:
-                       a = nodhiv;
-                       goto setbool;
-               case OHS:
-                       a = nodhsv;
-                       goto setbool;
-               case OLO:
-                       a = nodlov;
-                       goto setbool;
-               case OLS:
-                       a = nodlsv;
-                       goto setbool;
-
-               case OANDAND:
-               case OOROR:
-                       if(machcap(n))
-                               return 1;
-
-                       if(rv) {
-                               r = new(OFUNC, nodtestv, r);
-                               n->right = r;
-                               r->complex = FNX;
-                               r->op = OFUNC;
-                               r->type = types[TLONG];
-                       }
-
-               case OCOND:
-               case ONOT:
-                       if(machcap(n))
-                               return 1;
-
-                       l = new(OFUNC, nodtestv, l);
-                       n->left = l;
-                       l->complex = FNX;
-                       l->op = OFUNC;
-                       l->type = types[TLONG];
-                       n->complex = FNX;
-                       return 1;
-               }
-       }
-
-       if(rv) {
-               if(machcap(n))
-                       return 1;
-               switch(n->op) {
-               case OANDAND:
-               case OOROR:
-                       r = new(OFUNC, nodtestv, r);
-                       n->right = r;
-                       r->complex = FNX;
-                       r->op = OFUNC;
-                       r->type = types[TLONG];
-                       return 1;
-               }
-       }
-
-       if(typev[n->type->etype]) {
-               if(machcap(n))
-                       return 1;
-               switch(n->op) {
-               default:
-                       diag(n, "unknown vlong %O", n->op);
-               case OFUNC:
-                       n->complex = FNX;
-               case ORETURN:
-               case OAS:
-               case OIND:
-                       return 1;
-               case OADD:
-                       a = nodaddv;
-                       goto setbop;
-               case OSUB:
-                       a = nodsubv;
-                       goto setbop;
-               case OMUL:
-               case OLMUL:
-                       a = nodmulv;
-                       goto setbop;
-               case ODIV:
-                       a = noddivv;
-                       goto setbop;
-               case OLDIV:
-                       a = noddivvu;
-                       goto setbop;
-               case OMOD:
-                       a = nodmodv;
-                       goto setbop;
-               case OLMOD:
-                       a = nodmodvu;
-                       goto setbop;
-               case OASHL:
-                       a = nodlshv;
-                       goto setbop;
-               case OASHR:
-                       a = nodrshav;
-                       goto setbop;
-               case OLSHR:
-                       a = nodrshlv;
-                       goto setbop;
-               case OAND:
-                       a = nodandv;
-                       goto setbop;
-               case OOR:
-                       a = nodorv;
-                       goto setbop;
-               case OXOR:
-                       a = nodxorv;
-                       goto setbop;
-               case OPOSTINC:
-                       a = nodvpp;
-                       goto setvinc;
-               case OPOSTDEC:
-                       a = nodvmm;
-                       goto setvinc;
-               case OPREINC:
-                       a = nodppv;
-                       goto setvinc;
-               case OPREDEC:
-                       a = nodmmv;
-                       goto setvinc;
-               case ONEG:
-                       a = nodnegv;
-                       goto setfnx;
-               case OCOM:
-                       a = nodcomv;
-                       goto setfnx;
-               case OCAST:
-                       switch(l->type->etype) {
-                       case TCHAR:
-                               a = nodsc2v;
-                               goto setfnxl;
-                       case TUCHAR:
-                               a = noduc2v;
-                               goto setfnxl;
-                       case TSHORT:
-                               a = nodsh2v;
-                               goto setfnxl;
-                       case TUSHORT:
-                               a = noduh2v;
-                               goto setfnxl;
-                       case TINT:
-                               a = nodsi2v;
-                               goto setfnx;
-                       case TUINT:
-                               a = nodui2v;
-                               goto setfnx;
-                       case TLONG:
-                               a = nodsl2v;
-                               goto setfnx;
-                       case TULONG:
-                               a = nodul2v;
-                               goto setfnx;
-                       case TFLOAT:
-                               a = nodf2v;
-                               goto setfnx;
-                       case TDOUBLE:
-                               a = nodd2v;
-                               goto setfnx;
-                       case TIND:
-                               a = nodp2v;
-                               goto setfnx;
-                       }
-                       diag(n, "unknown %T->vlong cast", l->type);
-                       return 1;
-               case OASADD:
-                       a = nodaddv;
-                       goto setasop;
-               case OASSUB:
-                       a = nodsubv;
-                       goto setasop;
-               case OASMUL:
-               case OASLMUL:
-                       a = nodmulv;
-                       goto setasop;
-               case OASDIV:
-                       a = noddivv;
-                       goto setasop;
-               case OASLDIV:
-                       a = noddivvu;
-                       goto setasop;
-               case OASMOD:
-                       a = nodmodv;
-                       goto setasop;
-               case OASLMOD:
-                       a = nodmodvu;
-                       goto setasop;
-               case OASASHL:
-                       a = nodlshv;
-                       goto setasop;
-               case OASASHR:
-                       a = nodrshav;
-                       goto setasop;
-               case OASLSHR:
-                       a = nodrshlv;
-                       goto setasop;
-               case OASAND:
-                       a = nodandv;
-                       goto setasop;
-               case OASOR:
-                       a = nodorv;
-                       goto setasop;
-               case OASXOR:
-                       a = nodxorv;
-                       goto setasop;
-               }
-       }
-
-       if(typefd[n->type->etype] && l && l->op == OFUNC) {
-               switch(n->op) {
-               case OASADD:
-               case OASSUB:
-               case OASMUL:
-               case OASLMUL:
-               case OASDIV:
-               case OASLDIV:
-               case OASMOD:
-               case OASLMOD:
-               case OASASHL:
-               case OASASHR:
-               case OASLSHR:
-               case OASAND:
-               case OASOR:
-               case OASXOR:
-                       if(l->right && typev[l->right->etype]) {
-                               diag(n, "sorry float <asop> vlong not implemented\n");
-                       }
-               }
-       }
-
-       if(n->op == OCAST) {
-               if(l->type && typev[l->type->etype]) {
-                       if(machcap(n))
-                               return 1;
-                       switch(n->type->etype) {
-                       case TDOUBLE:
-                               a = nodv2d;
-                               goto setfnx;
-                       case TFLOAT:
-                               a = nodv2f;
-                               goto setfnx;
-                       case TLONG:
-                               a = nodv2sl;
-                               goto setfnx;
-                       case TULONG:
-                               a = nodv2ul;
-                               goto setfnx;
-                       case TINT:
-                               a = nodv2si;
-                               goto setfnx;
-                       case TUINT:
-                               a = nodv2ui;
-                               goto setfnx;
-                       case TSHORT:
-                               a = nodv2sh;
-                               goto setfnx;
-                       case TUSHORT:
-                               a = nodv2uh;
-                               goto setfnx;
-                       case TCHAR:
-                               a = nodv2sc;
-                               goto setfnx;
-                       case TUCHAR:
-                               a = nodv2uc;
-                               goto setfnx;
-                       case TIND:      // small pun here
-                               a = nodv2ul;
-                               goto setfnx;
-                       }
-                       diag(n, "unknown vlong->%T cast", n->type);
-                       return 1;
-               }
-       }
-
-       return 0;
-
-setbop:
-       n->left = a;
-       n->right = new(OLIST, l, r);
-       n->complex = FNX;
-       n->op = OFUNC;
-       return 1;
-
-setfnxl:
-       l = new(OCAST, l, 0);
-       l->type = types[TLONG];
-       l->complex = l->left->complex;
-
-setfnx:
-       n->left = a;
-       n->right = l;
-       n->complex = FNX;
-       n->op = OFUNC;
-       return 1;
-
-setvinc:
-       n->left = a;
-       l = new(OADDR, l, Z);
-       l->type = typ(TIND, l->left->type);
-       n->right = new(OLIST, l, r);
-       n->complex = FNX;
-       n->op = OFUNC;
-       return 1;
-
-setbool:
-       if(machcap(n))
-               return 1;
-       n->left = a;
-       n->right = new(OLIST, l, r);
-       n->complex = FNX;
-       n->op = OFUNC;
-       n->type = types[TLONG];
-       return 1;
-
-setasop:
-       if(l->op == OFUNC) {
-               l = l->right;
-               goto setasop;
-       }
-
-       t = new(OCONST, 0, 0);
-       t->vconst = etconv[l->type->etype];
-       t->type = types[TLONG];
-       t->addable = 20;
-       r = new(OLIST, t, r);
-
-       t = new(OADDR, a, 0);
-       t->type = typ(TIND, a->type);
-       r = new(OLIST, t, r);
-
-       t = new(OADDR, l, 0);
-       t->type = typ(TIND, l->type);
-       r = new(OLIST, t, r);
-
-       n->left = nodvasop;
-       n->right = r;
-       n->complex = FNX;
-       n->op = OFUNC;
-
-       return 1;
-}
-
-void
-bool64(Node *n)
-{
-       Node *n1;
-
-       if(machcap(Z))
-               return;
-       if(typev[n->type->etype]) {
-               n1 = new(OXXX, 0, 0);
-               *n1 = *n;
-
-               n->right = n1;
-               n->left = nodtestv;
-               n->complex = FNX;
-               n->addable = 0;
-               n->op = OFUNC;
-               n->type = types[TLONG];
-       }
-}
-
-/*
- * more machine depend stuff.
- * this is common for 8,16,32,64 bit machines.
- * this is common for ieee machines.
- */
-double
-convvtof(vlong v)
-{
-       double d;
-
-       d = v;          /* BOTCH */
-       return d;
-}
-
-vlong
-convftov(double d)
-{
-       vlong v;
-
-
-       v = d;          /* BOTCH */
-       return v;
-}
-
-double
-convftox(double d, int et)
-{
-
-       if(!typefd[et])
-               diag(Z, "bad type in castftox %s", tnames[et]);
-       return d;
-}
-
-vlong
-convvtox(vlong c, int et)
-{
-       int n;
-
-       n = 8 * ewidth[et];
-       c &= MASK(n);
-       if(!typeu[et])
-               if(c & SIGN(n))
-                       c |= ~MASK(n);
-       return c;
-}
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c
deleted file mode 100644 (file)
index 117508f..0000000
+++ /dev/null
@@ -1,1707 +0,0 @@
-// Inferno utils/cc/dcl.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/dcl.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-#include "../ld/textflag.h"
-
-static int haspointers(Type*);
-
-Node*
-dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
-{
-       Sym *s;
-       Node *n1;
-       int32 v;
-
-       nearln = lineno;
-       lastfield = 0;
-
-loop:
-       if(n != Z)
-       switch(n->op) {
-       default:
-               diag(n, "unknown declarator: %O", n->op);
-               break;
-
-       case OARRAY:
-               t = typ(TARRAY, t);
-               t->width = 0;
-               n1 = n->right;
-               n = n->left;
-               if(n1 != Z) {
-                       complex(n1);
-                       v = -1;
-                       if(n1->op == OCONST)
-                               v = n1->vconst;
-                       if(v <= 0) {
-                               diag(n, "array size must be a positive constant");
-                               v = 1;
-                       }
-                       t->width = v * t->link->width;
-               }
-               goto loop;
-
-       case OIND:
-               t = typ(TIND, t);
-               t->garb = n->garb;
-               n = n->left;
-               goto loop;
-
-       case OFUNC:
-               t = typ(TFUNC, t);
-               t->down = fnproto(n);
-               n = n->left;
-               goto loop;
-
-       case OBIT:
-               n1 = n->right;
-               complex(n1);
-               lastfield = -1;
-               if(n1->op == OCONST)
-                       lastfield = n1->vconst;
-               if(lastfield < 0) {
-                       diag(n, "field width must be non-negative constant");
-                       lastfield = 1;
-               }
-               if(lastfield == 0) {
-                       lastbit = 0;
-                       firstbit = 1;
-                       if(n->left != Z) {
-                               diag(n, "zero width named field");
-                               lastfield = 1;
-                       }
-               }
-               if(!typei[t->etype]) {
-                       diag(n, "field type must be int-like");
-                       t = types[TINT];
-                       lastfield = 1;
-               }
-               if(lastfield > tfield->width*8) {
-                       diag(n, "field width larger than field unit");
-                       lastfield = 1;
-               }
-               lastbit += lastfield;
-               if(lastbit > tfield->width*8) {
-                       lastbit = lastfield;
-                       firstbit = 1;
-               }
-               n = n->left;
-               goto loop;
-
-       case ONAME:
-               if(f == NODECL)
-                       break;
-               s = n->sym;
-               (*f)(c, t, s);
-               if(s->class == CLOCAL)
-                       s = mkstatic(s);
-               if(dataflag) {
-                       s->dataflag = dataflag;
-                       dataflag = 0;
-               } else if(s->type != T && !haspointers(s->type))
-                       s->dataflag = NOPTR;
-               firstbit = 0;
-               n->sym = s;
-               n->type = s->type;
-               n->xoffset = s->offset;
-               n->class = s->class;
-               n->etype = TVOID;
-               if(n->type != T)
-                       n->etype = n->type->etype;
-               if(debug['d'])
-                       dbgdecl(s);
-               acidvar(s);
-               godefvar(s);
-               s->varlineno = lineno;
-               break;
-       }
-       lastdcl = t;
-       return n;
-}
-
-Sym*
-mkstatic(Sym *s)
-{
-       Sym *s1;
-
-       if(s->class != CLOCAL)
-               return s;
-       snprint(symb, NSYMB, "%s$%d", s->name, s->block);
-       s1 = lookup();
-       if(s1->class != CSTATIC) {
-               s1->type = s->type;
-               s1->offset = s->offset;
-               s1->block = s->block;
-               s1->class = CSTATIC;
-       }
-       return s1;
-}
-
-/*
- * make a copy of a typedef
- * the problem is to split out incomplete
- * arrays so that it is in the variable
- * rather than the typedef.
- */
-Type*
-tcopy(Type *t)
-{
-       Type *tl, *tx;
-       int et;
-
-       if(t == T)
-               return t;
-       et = t->etype;
-       if(typesu[et])
-               return t;
-       tl = tcopy(t->link);
-       if(tl != t->link ||
-         (et == TARRAY && t->width == 0)) {
-               tx = copytyp(t);
-               tx->link = tl;
-               return tx;
-       }
-       return t;
-}
-
-Node*
-doinit(Sym *s, Type *t, int32 o, Node *a)
-{
-       Node *n;
-
-       if(t == T)
-               return Z;
-       if(s->class == CEXTERN) {
-               s->class = CGLOBL;
-               if(debug['d'])
-                       dbgdecl(s);
-       }
-       if(debug['i']) {
-               print("t = %T; o = %d; n = %s\n", t, o, s->name);
-               prtree(a, "doinit value");
-       }
-
-
-       n = initlist;
-       if(a->op == OINIT)
-               a = a->left;
-       initlist = a;
-
-       a = init1(s, t, o, 0);
-       if(initlist != Z)
-               diag(initlist, "more initializers than structure: %s",
-                       s->name);
-       initlist = n;
-
-       return a;
-}
-
-/*
- * get next major operator,
- * dont advance initlist.
- */
-Node*
-peekinit(void)
-{
-       Node *a;
-
-       a = initlist;
-
-loop:
-       if(a == Z)
-               return a;
-       if(a->op == OLIST) {
-               a = a->left;
-               goto loop;
-       }
-       return a;
-}
-
-/*
- * consume and return next element on
- * initlist. expand strings.
- */
-Node*
-nextinit(void)
-{
-       Node *a, *b, *n;
-
-       a = initlist;
-       n = Z;
-
-       if(a == Z)
-               return a;
-       if(a->op == OLIST) {
-               n = a->right;
-               a = a->left;
-       }
-       if(a->op == OUSED) {
-               a = a->left;
-               b = new(OCONST, Z, Z);
-               b->type = a->type->link;
-               if(a->op == OSTRING) {
-                       b->vconst = convvtox(*a->cstring, TCHAR);
-                       a->cstring++;
-               }
-               if(a->op == OLSTRING) {
-                       b->vconst = convvtox(*a->rstring, TRUNE);
-                       a->rstring++;
-               }
-               a->type->width -= b->type->width;
-               if(a->type->width <= 0)
-                       initlist = n;
-               return b;
-       }
-       initlist = n;
-       return a;
-}
-
-int
-isstruct(Node *a, Type *t)
-{
-       Node *n;
-
-       switch(a->op) {
-       case ODOTDOT:
-               n = a->left;
-               if(n && n->type && sametype(n->type, t))
-                       return 1;
-       case OSTRING:
-       case OLSTRING:
-       case OCONST:
-       case OINIT:
-       case OELEM:
-               return 0;
-       }
-
-       n = new(ODOTDOT, Z, Z);
-       *n = *a;
-
-       /*
-        * ODOTDOT is a flag for tcom
-        * a second tcom will not be performed
-        */
-       a->op = ODOTDOT;
-       a->left = n;
-       a->right = Z;
-
-       if(tcom(n))
-               return 0;
-
-       if(sametype(n->type, t))
-               return 1;
-       return 0;
-}
-
-Node*
-init1(Sym *s, Type *t, int32 o, int exflag)
-{
-       Node *a, *l, *r, nod;
-       Type *t1;
-       int32 e, w, so, mw;
-
-       a = peekinit();
-       if(a == Z)
-               return Z;
-
-       if(debug['i']) {
-               print("t = %T; o = %d; n = %s\n", t, o, s->name);
-               prtree(a, "init1 value");
-       }
-
-       if(exflag && a->op == OINIT)
-               return doinit(s, t, o, nextinit());
-
-       switch(t->etype) {
-       default:
-               diag(Z, "unknown type in initialization: %T to: %s", t, s->name);
-               return Z;
-
-       case TCHAR:
-       case TUCHAR:
-       case TINT:
-       case TUINT:
-       case TSHORT:
-       case TUSHORT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TFLOAT:
-       case TDOUBLE:
-       case TIND:
-       single:
-               if(a->op == OARRAY || a->op == OELEM)
-                       return Z;
-
-               a = nextinit();
-               if(a == Z)
-                       return Z;
-
-               if(t->nbits)
-                       diag(Z, "cannot initialize bitfields");
-               if(s->class == CAUTO) {
-                       l = new(ONAME, Z, Z);
-                       l->sym = s;
-                       l->type = t;
-                       l->etype = TVOID;
-                       if(s->type)
-                               l->etype = s->type->etype;
-                       l->xoffset = s->offset + o;
-                       l->class = s->class;
-
-                       l = new(OASI, l, a);
-                       return l;
-               }
-
-               complex(a);
-               if(a->type == T)
-                       return Z;
-
-               if(a->op == OCONST) {
-                       if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){
-                               diag(a, "initialize pointer to an integer: %s", s->name);
-                               return Z;
-                       }
-                       if(!sametype(a->type, t)) {
-                               /* hoop jumping to save malloc */
-                               if(nodcast == Z)
-                                       nodcast = new(OCAST, Z, Z);
-                               nod = *nodcast;
-                               nod.left = a;
-                               nod.type = t;
-                               nod.lineno = a->lineno;
-                               complex(&nod);
-                               if(nod.type)
-                                       *a = nod;
-                       }
-                       if(a->op != OCONST) {
-                               diag(a, "initializer is not a constant: %s",
-                                       s->name);
-                               return Z;
-                       }
-                       if(vconst(a) == 0)
-                               return Z;
-                       goto gext;
-               }
-               if(t->etype == TIND) {
-                       while(a->op == OCAST) {
-                               warn(a, "CAST in initialization ignored");
-                               a = a->left;
-                       }
-                       if(!sametype(t, a->type)) {
-                               diag(a, "initialization of incompatible pointers: %s\n%T and %T",
-                                       s->name, t, a->type);
-                       }
-                       if(a->op == OADDR)
-                               a = a->left;
-                       goto gext;
-               }
-
-               while(a->op == OCAST)
-                       a = a->left;
-               if(a->op == OADDR) {
-                       warn(a, "initialize pointer to an integer: %s", s->name);
-                       a = a->left;
-                       goto gext;
-               }
-               diag(a, "initializer is not a constant: %s", s->name);
-               return Z;
-
-       gext:
-               gextern(s, a, o, t->width);
-
-               return Z;
-
-       case TARRAY:
-               w = t->link->width;
-               if(a->op == OSTRING || a->op == OLSTRING)
-               if(typei[t->link->etype]) {
-                       /*
-                        * get rid of null if sizes match exactly
-                        */
-                       a = nextinit();
-                       mw = t->width/w;
-                       so = a->type->width/a->type->link->width;
-                       if(mw && so > mw) {
-                               if(so != mw+1)
-                                       diag(a, "string initialization larger than array");
-                               a->type->width -= a->type->link->width;
-                       }
-
-                       /*
-                        * arrange strings to be expanded
-                        * inside OINIT braces.
-                        */
-                       a = new(OUSED, a, Z);
-                       return doinit(s, t, o, a);
-               }
-
-               mw = -w;
-               l = Z;
-               for(e=0;;) {
-                       /*
-                        * peek ahead for element initializer
-                        */
-                       a = peekinit();
-                       if(a == Z)
-                               break;
-                       if(a->op == OELEM && t->link->etype != TSTRUCT)
-                               break;
-                       if(a->op == OARRAY) {
-                               if(e && exflag)
-                                       break;
-                               a = nextinit();
-                               r = a->left;
-                               complex(r);
-                               if(r->op != OCONST) {
-                                       diag(r, "initializer subscript must be constant");
-                                       return Z;
-                               }
-                               e = r->vconst;
-                               if(t->width != 0)
-                                       if(e < 0 || e*w >= t->width) {
-                                               diag(a, "initialization index out of range: %d", e);
-                                               continue;
-                                       }
-                       }
-
-                       so = e*w;
-                       if(so > mw)
-                               mw = so;
-                       if(t->width != 0)
-                               if(mw >= t->width)
-                                       break;
-                       r = init1(s, t->link, o+so, 1);
-                       l = newlist(l, r);
-                       e++;
-               }
-               if(t->width == 0)
-                       t->width = mw+w;
-               return l;
-
-       case TUNION:
-       case TSTRUCT:
-               /*
-                * peek ahead to find type of rhs.
-                * if its a structure, then treat
-                * this element as a variable
-                * rather than an aggregate.
-                */
-               if(isstruct(a, t))
-                       goto single;
-
-               if(t->width <= 0) {
-                       diag(Z, "incomplete structure: %s", s->name);
-                       return Z;
-               }
-               l = Z;
-
-       again:
-               for(t1 = t->link; t1 != T; t1 = t1->down) {
-                       if(a->op == OARRAY && t1->etype != TARRAY)
-                               break;
-                       if(a->op == OELEM) {
-                               if(t1->sym != a->sym)
-                                       continue;
-                               nextinit();
-                       }
-                       r = init1(s, t1, o+t1->offset, 1);
-                       l = newlist(l, r);
-                       a = peekinit();
-                       if(a == Z)
-                               break;
-                       if(a->op == OELEM)
-                               goto again;
-               }
-               if(a && a->op == OELEM)
-                       diag(a, "structure element not found %F", a);
-               return l;
-       }
-}
-
-Node*
-newlist(Node *l, Node *r)
-{
-       if(r == Z)
-               return l;
-       if(l == Z)
-               return r;
-       return new(OLIST, l, r);
-}
-
-static int
-haspointers(Type *t)
-{
-       Type *fld;
-
-       switch(t->etype) {
-       case TSTRUCT:
-               for(fld = t->link; fld != T; fld = fld->down) {
-                       if(haspointers(fld))
-                               return 1;
-               }
-               return 0;
-       case TARRAY:
-               return haspointers(t->link);
-       case TIND:
-               return t->link->etype != TFUNC;
-       default:
-               return 0;
-       }
-}
-
-void
-sualign(Type *t)
-{
-       Type *l;
-       int32 o, w, maxal;
-
-       o = 0;
-       maxal = 0;
-       switch(t->etype) {
-
-       case TSTRUCT:
-               t->offset = 0;
-               w = 0;
-               for(l = t->link; l != T; l = l->down) {
-                       if(l->nbits) {
-                               if(l->shift <= 0) {
-                                       l->shift = -l->shift;
-                                       w = xround(w, tfield->width);
-                                       o = w;
-                                       w += tfield->width;
-                               }
-                               l->offset = o;
-                       } else {
-                               if(l->width <= 0)
-                               if(l->down != T)
-                                       if(l->sym)
-                                               diag(Z, "incomplete structure element: %s",
-                                                       l->sym->name);
-                                       else
-                                               diag(Z, "incomplete structure element");
-                               w = align(w, l, Ael1, &maxal);
-                               l->offset = w;
-                               w = align(w, l, Ael2, &maxal);
-                       }
-               }
-               w = align(w, t, Asu2, &maxal);
-               t->width = w;
-               t->align = maxal;
-               acidtype(t);
-               godeftype(t);
-               return;
-
-       case TUNION:
-               t->offset = 0;
-               w = 0;
-               for(l = t->link; l != T; l = l->down) {
-                       if(l->width <= 0)
-                               if(l->sym)
-                                       diag(Z, "incomplete union element: %s",
-                                               l->sym->name);
-                               else
-                                       diag(Z, "incomplete union element");
-                       l->offset = 0;
-                       l->shift = 0;
-                       if((debug['q'] || debug['Q']) && haspointers(l))
-                               diag(Z, "precise garbage collector cannot handle unions with pointers");
-
-                       o = align(align(0, l, Ael1, &maxal), l, Ael2, &maxal);
-                       if(o > w)
-                               w = o;
-               }
-               w = align(w, t, Asu2, &maxal);
-               t->width = w;
-               t->align = maxal;
-               acidtype(t);
-               godeftype(t);
-               return;
-
-       default:
-               diag(Z, "unknown type in sualign: %T", t);
-               break;
-       }
-}
-
-int32
-xround(int32 v, int w)
-{
-       int r;
-
-       if(w <= 0 || w > 8) {
-               diag(Z, "rounding by %d", w);
-               w = 1;
-       }
-       r = v%w;
-       if(r)
-               v += w-r;
-       return v;
-}
-
-Type*
-ofnproto(Node *n)
-{
-       Type *tl, *tr, *t;
-
-       if(n == Z)
-               return T;
-       switch(n->op) {
-       case OLIST:
-               tl = ofnproto(n->left);
-               tr = ofnproto(n->right);
-               if(tl == T)
-                       return tr;
-               tl->down = tr;
-               return tl;
-
-       case ONAME:
-               t = copytyp(n->sym->type);
-               t->down = T;
-               return t;
-       }
-       return T;
-}
-
-#define        ANSIPROTO       1
-#define        OLDPROTO        2
-
-void
-argmark(Node *n, int pass)
-{
-       Type *t;
-
-       if(hasdotdotdot(thisfn->link))
-               autoffset = align(0, thisfn->link, Aarg0, nil);
-       stkoff = 0;
-       for(; n->left != Z; n = n->left) {
-               if(n->op != OFUNC || n->left->op != ONAME)
-                       continue;
-               walkparam(n->right, pass);
-               if(pass != 0 && anyproto(n->right) == OLDPROTO) {
-                       t = typ(TFUNC, n->left->sym->type->link);
-                       t->down = typ(TOLD, T);
-                       t->down->down = ofnproto(n->right);
-                       tmerge(t, n->left->sym);
-                       n->left->sym->type = t;
-               }
-               break;
-       }
-       autoffset = 0;
-       stkoff = 0;
-}
-
-void
-walkparam(Node *n, int pass)
-{
-       Sym *s;
-       Node *n1;
-
-       if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID])
-               return;
-
-loop:
-       if(n == Z)
-               return;
-       switch(n->op) {
-       default:
-               diag(n, "argument not a name/prototype: %O", n->op);
-               break;
-
-       case OLIST:
-               walkparam(n->left, pass);
-               n = n->right;
-               goto loop;
-
-       case OPROTO:
-               for(n1 = n; n1 != Z; n1=n1->left)
-                       if(n1->op == ONAME) {
-                               if(pass == 0) {
-                                       s = n1->sym;
-                                       push1(s);
-                                       s->offset = -1;
-                                       break;
-                               }
-                               dodecl(pdecl, CPARAM, n->type, n->left);
-                               break;
-                       }
-               if(n1)
-                       break;
-               if(pass == 0) {
-                       /*
-                        * extension:
-                        *      allow no name in argument declaration
-                       diag(Z, "no name in argument declaration");
-                        */
-                       break;
-               }
-               dodecl(NODECL, CPARAM, n->type, n->left);
-               pdecl(CPARAM, lastdcl, S);
-               break;
-
-       case ODOTDOT:
-               break;
-       
-       case ONAME:
-               s = n->sym;
-               if(pass == 0) {
-                       push1(s);
-                       s->offset = -1;
-                       break;
-               }
-               if(s->offset != -1) {
-                       if(autoffset == 0) {
-                               firstarg = s;
-                               firstargtype = s->type;
-                       }
-                       autoffset = align(autoffset, s->type, Aarg1, nil);
-                       s->offset = autoffset;
-                       autoffset = align(autoffset, s->type, Aarg2, nil);
-               } else
-                       dodecl(pdecl, CXXX, types[TINT], n);
-               break;
-       }
-}
-
-void
-markdcl(void)
-{
-       Decl *d;
-
-       blockno++;
-       d = push();
-       d->val = DMARK;
-       d->offset = autoffset;
-       d->block = autobn;
-       autobn = blockno;
-}
-
-Node*
-revertdcl(void)
-{
-       Decl *d;
-       Sym *s;
-       Node *n, *n1;
-
-       n = Z;
-       for(;;) {
-               d = dclstack;
-               if(d == D) {
-                       diag(Z, "pop off dcl stack");
-                       break;
-               }
-               dclstack = d->link;
-               s = d->sym;
-               switch(d->val) {
-               case DMARK:
-                       autoffset = d->offset;
-                       autobn = d->block;
-                       return n;
-
-               case DAUTO:
-                       if(debug['d'])
-                               print("revert1 \"%s\"\n", s->name);
-                       if(s->aused == 0) {
-                               nearln = s->varlineno;
-                               if(s->class == CAUTO)
-                                       warn(Z, "auto declared and not used: %s", s->name);
-                               if(s->class == CPARAM)
-                                       warn(Z, "param declared and not used: %s", s->name);
-                       }
-                       if(s->type && (s->type->garb & GVOLATILE)) {
-                               n1 = new(ONAME, Z, Z);
-                               n1->sym = s;
-                               n1->type = s->type;
-                               n1->etype = TVOID;
-                               if(n1->type != T)
-                                       n1->etype = n1->type->etype;
-                               n1->xoffset = s->offset;
-                               n1->class = s->class;
-
-                               n1 = new(OADDR, n1, Z);
-                               n1 = new(OUSED, n1, Z);
-                               if(n == Z)
-                                       n = n1;
-                               else
-                                       n = new(OLIST, n1, n);
-                       }
-                       s->type = d->type;
-                       s->class = d->class;
-                       s->offset = d->offset;
-                       s->block = d->block;
-                       s->varlineno = d->varlineno;
-                       s->aused = d->aused;
-                       break;
-
-               case DSUE:
-                       if(debug['d'])
-                               print("revert2 \"%s\"\n", s->name);
-                       s->suetag = d->type;
-                       s->sueblock = d->block;
-                       break;
-
-               case DLABEL:
-                       if(debug['d'])
-                               print("revert3 \"%s\"\n", s->name);
-                       if(s->label && s->label->addable == 0)
-                               warn(s->label, "label declared and not used \"%s\"", s->name);
-                       s->label = Z;
-                       break;
-               }
-       }
-       return n;
-}
-
-Type*
-fnproto(Node *n)
-{
-       int r;
-
-       r = anyproto(n->right);
-       if(r == 0 || (r & OLDPROTO)) {
-               if(r & ANSIPROTO)
-                       diag(n, "mixed ansi/old function declaration: %F", n->left);
-               return T;
-       }
-       return fnproto1(n->right);
-}
-
-int
-anyproto(Node *n)
-{
-       int r;
-
-       r = 0;
-
-loop:
-       if(n == Z)
-               return r;
-       switch(n->op) {
-       case OLIST:
-               r |= anyproto(n->left);
-               n = n->right;
-               goto loop;
-
-       case ODOTDOT:
-       case OPROTO:
-               return r | ANSIPROTO;
-       }
-       return r | OLDPROTO;
-}
-
-Type*
-fnproto1(Node *n)
-{
-       Type *t;
-
-       if(n == Z)
-               return T;
-       switch(n->op) {
-       case OLIST:
-               t = fnproto1(n->left);
-               if(t != T)
-                       t->down = fnproto1(n->right);
-               return t;
-
-       case OPROTO:
-               lastdcl = T;
-               dodecl(NODECL, CXXX, n->type, n->left);
-               t = typ(TXXX, T);
-               if(lastdcl != T)
-                       *t = *paramconv(lastdcl, 1);
-               return t;
-
-       case ONAME:
-               diag(n, "incomplete argument prototype");
-               return typ(TINT, T);
-
-       case ODOTDOT:
-               return typ(TDOT, T);
-       }
-       diag(n, "unknown op in fnproto");
-       return T;
-}
-
-void
-dbgdecl(Sym *s)
-{
-       print("decl \"%s\": C=%s [B=%d:O=%d] T=%T\n",
-               s->name, cnames[s->class], s->block, s->offset, s->type);
-}
-
-Decl*
-push(void)
-{
-       Decl *d;
-
-       d = alloc(sizeof(*d));
-       d->link = dclstack;
-       dclstack = d;
-       return d;
-}
-
-Decl*
-push1(Sym *s)
-{
-       Decl *d;
-
-       d = push();
-       d->sym = s;
-       d->val = DAUTO;
-       d->type = s->type;
-       d->class = s->class;
-       d->offset = s->offset;
-       d->block = s->block;
-       d->varlineno = s->varlineno;
-       d->aused = s->aused;
-       return d;
-}
-
-int
-sametype(Type *t1, Type *t2)
-{
-
-       if(t1 == t2)
-               return 1;
-       return rsametype(t1, t2, 5, 1);
-}
-
-int
-rsametype(Type *t1, Type *t2, int n, int f)
-{
-       int et;
-
-       n--;
-       for(;;) {
-               if(t1 == t2)
-                       return 1;
-               if(t1 == T || t2 == T)
-                       return 0;
-               if(n <= 0)
-                       return 1;
-               et = t1->etype;
-               if(et != t2->etype)
-                       return 0;
-               if(et == TFUNC) {
-                       if(!rsametype(t1->link, t2->link, n, 0))
-                               return 0;
-                       t1 = t1->down;
-                       t2 = t2->down;
-                       while(t1 != T && t2 != T) {
-                               if(t1->etype == TOLD) {
-                                       t1 = t1->down;
-                                       continue;
-                               }
-                               if(t2->etype == TOLD) {
-                                       t2 = t2->down;
-                                       continue;
-                               }
-                               while(t1 != T || t2 != T) {
-                                       if(!rsametype(t1, t2, n, 0))
-                                               return 0;
-                                       t1 = t1->down;
-                                       t2 = t2->down;
-                               }
-                               break;
-                       }
-                       return 1;
-               }
-               if(et == TARRAY)
-                       if(t1->width != t2->width && t1->width != 0 && t2->width != 0)
-                               return 0;
-               if(typesu[et]) {
-                       if(t1->link == T)
-                               snap(t1);
-                       if(t2->link == T)
-                               snap(t2);
-                       t1 = t1->link;
-                       t2 = t2->link;
-                       for(;;) {
-                               if(t1 == t2)
-                                       return 1;
-                               if(!rsametype(t1, t2, n, 0))
-                                       return 0;
-                               t1 = t1->down;
-                               t2 = t2->down;
-                       }
-               }
-               t1 = t1->link;
-               t2 = t2->link;
-               if((f || !debug['V']) && et == TIND) {
-                       if(t1 != T && t1->etype == TVOID)
-                               return 1;
-                       if(t2 != T && t2->etype == TVOID)
-                               return 1;
-               }
-       }
-}
-
-typedef struct Typetab Typetab;
-
-struct Typetab{
-       int n;
-       Type **a;
-};
-
-static int
-sigind(Type *t, Typetab *tt)
-{
-       int n;
-       Type **a, **na, **p, **e;
-
-       n = tt->n;
-       a = tt->a;
-       e = a+n;
-       /* linear search seems ok */
-       for(p = a ; p < e; p++)
-               if(sametype(*p, t))
-                       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;
-       }
-       a[tt->n++] = t;
-       return -1;
-}
-
-static uint32
-signat(Type *t, Typetab *tt)
-{
-       int i;
-       Type *t1;
-       int32 s;
-
-       s = 0;
-       for(; t; t=t->link) {
-               s = s*thash1 + thash[t->etype];
-               if(t->garb&GINCOMPLETE)
-                       return s;
-               switch(t->etype) {
-               default:
-                       return s;
-               case TARRAY:
-                       s = s*thash2 + 0;       /* was t->width */
-                       break;
-               case TFUNC:
-                       for(t1=t->down; t1; t1=t1->down)
-                               s = s*thash3 + signat(t1, tt);
-                       break;
-               case TSTRUCT:
-               case TUNION:
-                       if((i = sigind(t, tt)) >= 0){
-                               s = s*thash2 + i;
-                               return s;
-                       }
-                       for(t1=t->link; t1; t1=t1->down)
-                               s = s*thash3 + signat(t1, tt);
-                       return s;
-               case TIND:
-                       break;
-               }
-       }
-       return s;
-}
-
-uint32
-signature(Type *t)
-{
-       uint32 s;
-       Typetab tt;
-
-       tt.n = 0;
-       tt.a = nil;
-       s = signat(t, &tt);
-       free(tt.a);
-       return s;
-}
-
-uint32
-sign(Sym *s)
-{
-       uint32 v;
-       Type *t;
-
-       if(s->sig == SIGINTERN)
-               return SIGNINTERN;
-       if((t = s->type) == T)
-               return 0;
-       v = signature(t);
-       if(v == 0)
-               v = SIGNINTERN;
-       return v;
-}
-
-void
-snap(Type *t)
-{
-       if(typesu[t->etype])
-       if(t->link == T && t->tag && t->tag->suetag) {
-               t->link = t->tag->suetag->link;
-               t->width = t->tag->suetag->width;
-       }
-}
-
-Type*
-dotag(Sym *s, int et, int bn)
-{
-       Decl *d;
-
-       if(bn != 0 && bn != s->sueblock) {
-               d = push();
-               d->sym = s;
-               d->val = DSUE;
-               d->type = s->suetag;
-               d->block = s->sueblock;
-               s->suetag = T;
-       }
-       if(s->suetag == T) {
-               s->suetag = typ(et, T);
-               s->sueblock = autobn;
-       }
-       if(s->suetag->etype != et)
-               diag(Z, "tag used for more than one type: %s",
-                       s->name);
-       if(s->suetag->tag == S)
-               s->suetag->tag = s;
-       return s->suetag;
-}
-
-Node*
-dcllabel(Sym *s, int f)
-{
-       Decl *d, d1;
-       Node *n;
-
-       n = s->label;
-       if(n != Z) {
-               if(f) {
-                       if(n->complex)
-                               diag(Z, "label reused: %s", s->name);
-                       n->complex = 1; // declared
-               } else
-                       n->addable = 1; // used
-               return n;
-       }
-
-       d = push();
-       d->sym = s;
-       d->val = DLABEL;
-       dclstack = d->link;
-
-       d1 = *firstdcl;
-       *firstdcl = *d;
-       *d = d1;
-
-       firstdcl->link = d;
-       firstdcl = d;
-
-       n = new(OXXX, Z, Z);
-       n->sym = s;
-       n->complex = f;
-       n->addable = !f;
-       s->label = n;
-
-       if(debug['d'])
-               dbgdecl(s);
-       return n;
-}
-
-Type*
-paramconv(Type *t, int f)
-{
-
-       switch(t->etype) {
-       case TUNION:
-       case TSTRUCT:
-               if(t->width <= 0)
-                       diag(Z, "incomplete structure: %s", t->tag->name);
-               break;
-
-       case TARRAY:
-               t = typ(TIND, t->link);
-               t->width = types[TIND]->width;
-               break;
-
-       case TFUNC:
-               t = typ(TIND, t);
-               t->width = types[TIND]->width;
-               break;
-
-       case TFLOAT:
-               if(!f)
-                       t = types[TDOUBLE];
-               break;
-
-       case TCHAR:
-       case TSHORT:
-               if(!f)
-                       t = types[TINT];
-               break;
-
-       case TUCHAR:
-       case TUSHORT:
-               if(!f)
-                       t = types[TUINT];
-               break;
-       }
-       return t;
-}
-
-void
-adecl(int c, Type *t, Sym *s)
-{
-
-       if(c == CSTATIC)
-               c = CLOCAL;
-       if(t->etype == TFUNC) {
-               if(c == CXXX)
-                       c = CEXTERN;
-               if(c == CLOCAL)
-                       c = CSTATIC;
-               if(c == CAUTO || c == CEXREG)
-                       diag(Z, "function cannot be %s %s", cnames[c], s->name);
-       }
-       if(c == CXXX)
-               c = CAUTO;
-       if(s) {
-               if(s->class == CSTATIC)
-                       if(c == CEXTERN || c == CGLOBL) {
-                               warn(Z, "just say static: %s", s->name);
-                               c = CSTATIC;
-                       }
-               if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL)
-               if(s->block == autobn)
-                       diag(Z, "auto redeclaration of: %s", s->name);
-               if(c != CPARAM)
-                       push1(s);
-               s->block = autobn;
-               s->offset = 0;
-               s->type = t;
-               s->class = c;
-               s->aused = 0;
-       }
-       switch(c) {
-       case CAUTO:
-               autoffset = align(autoffset, t, Aaut3, nil);
-               stkoff = maxround(stkoff, autoffset);
-               s->offset = -autoffset;
-               break;
-
-       case CPARAM:
-               if(autoffset == 0) {
-                       firstarg = s;
-                       firstargtype = t;
-               }
-               autoffset = align(autoffset, t, Aarg1, nil);
-               if(s)
-                       s->offset = autoffset;
-               autoffset = align(autoffset, t, Aarg2, nil);
-               break;
-       }
-}
-
-void
-pdecl(int c, Type *t, Sym *s)
-{
-       if(s && s->offset != -1) {
-               diag(Z, "not a parameter: %s", s->name);
-               return;
-       }
-       t = paramconv(t, c==CPARAM);
-       if(c == CXXX)
-               c = CPARAM;
-       if(c != CPARAM) {
-               diag(Z, "parameter cannot have class: %s", s->name);
-               c = CPARAM;
-       }
-       adecl(c, t, s);
-}
-
-void
-xdecl(int c, Type *t, Sym *s)
-{
-       int32 o;
-
-       o = 0;
-       switch(c) {
-       case CEXREG:
-               o = exreg(t);
-               if(o == 0)
-                       c = CEXTERN;
-               if(s->class == CGLOBL)
-                       c = CGLOBL;
-               break;
-
-       case CEXTERN:
-               if(s->class == CGLOBL)
-                       c = CGLOBL;
-               break;
-
-       case CXXX:
-               c = CGLOBL;
-               if(s->class == CEXTERN)
-                       s->class = CGLOBL;
-               break;
-
-       case CAUTO:
-               diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
-               c = CEXTERN;
-               break;
-
-       case CTYPESTR:
-               if(!typesuv[t->etype]) {
-                       diag(Z, "typestr must be struct/union: %s", s->name);
-                       break;
-               }
-               dclfunct(t, s);
-               break;
-       }
-
-       if(s->class == CSTATIC)
-               if(c == CEXTERN || c == CGLOBL) {
-                       warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
-                       c = CSTATIC;
-               }
-       if(s->type != T)
-               if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) {
-                       diag(Z, "external redeclaration of: %s", s->name);
-                       Bprint(&diagbuf, "      %s %T %L\n", cnames[c], t, nearln);
-                       Bprint(&diagbuf, "      %s %T %L\n", cnames[s->class], s->type, s->varlineno);
-               }
-       tmerge(t, s);
-       s->type = t;
-       if(c == CTYPEDEF && (typechlv[t->etype] || typefd[t->etype])) {
-               s->type = copytyp(t);
-               s->type->tag = s;
-       }
-       s->class = c;
-       s->block = 0;
-       s->offset = o;
-}
-
-void
-tmerge(Type *t1, Sym *s)
-{
-       Type *ta, *tb, *t2;
-
-       t2 = s->type;
-       for(;;) {
-               if(t1 == T || t2 == T || t1 == t2)
-                       break;
-               if(t1->etype != t2->etype)
-                       break;
-               switch(t1->etype) {
-               case TFUNC:
-                       ta = t1->down;
-                       tb = t2->down;
-                       if(ta == T) {
-                               t1->down = tb;
-                               break;
-                       }
-                       if(tb == T)
-                               break;
-                       while(ta != T && tb != T) {
-                               if(ta == tb)
-                                       break;
-                               /* ignore old-style flag */
-                               if(ta->etype == TOLD) {
-                                       ta = ta->down;
-                                       continue;
-                               }
-                               if(tb->etype == TOLD) {
-                                       tb = tb->down;
-                                       continue;
-                               }
-                               /* checking terminated by ... */
-                               if(ta->etype == TDOT && tb->etype == TDOT) {
-                                       ta = T;
-                                       tb = T;
-                                       break;
-                               }
-                               if(!sametype(ta, tb))
-                                       break;
-                               ta = ta->down;
-                               tb = tb->down;
-                       }
-                       if(ta != tb)
-                               diag(Z, "function inconsistently declared: %s", s->name);
-
-                       /* take new-style over old-style */
-                       ta = t1->down;
-                       tb = t2->down;
-                       if(ta != T && ta->etype == TOLD)
-                               if(tb != T && tb->etype != TOLD)
-                                       t1->down = tb;
-                       break;
-
-               case TARRAY:
-                       /* should we check array size change? */
-                       if(t2->width > t1->width)
-                               t1->width = t2->width;
-                       break;
-
-               case TUNION:
-               case TSTRUCT:
-                       return;
-               }
-               t1 = t1->link;
-               t2 = t2->link;
-       }
-}
-
-void
-edecl(int c, Type *t, Sym *s)
-{
-       Type *t1;
-
-       if(s == S)
-               diag(Z, "unnamed structure elements not supported");
-       else
-               if(c != CXXX)
-                       diag(Z, "structure element cannot have class: %s", s->name);
-       t1 = t;
-       t = copytyp(t1);
-       t->sym = s;
-       t->down = T;
-       if(lastfield) {
-               t->shift = lastbit - lastfield;
-               t->nbits = lastfield;
-               if(firstbit)
-                       t->shift = -t->shift;
-               if(typeu[t->etype])
-                       t->etype = tufield->etype;
-               else
-                       t->etype = tfield->etype;
-       }
-       if(strf == T)
-               strf = t;
-       else
-               strl->down = t;
-       strl = t;
-}
-
-/*
- * this routine is very suspect.
- * ansi requires the enum type to
- * be represented as an 'int'
- * this means that 0x81234567
- * would be illegal. this routine
- * makes signed and unsigned go
- * to unsigned.
- */
-Type*
-maxtype(Type *t1, Type *t2)
-{
-
-       if(t1 == T)
-               return t2;
-       if(t2 == T)
-               return t1;
-       if(t1->etype > t2->etype)
-               return t1;
-       return t2;
-}
-
-void
-doenum(Sym *s, Node *n)
-{
-
-       if(n) {
-               complex(n);
-               if(n->op != OCONST) {
-                       diag(n, "enum not a constant: %s", s->name);
-                       return;
-               }
-               en.cenum = n->type;
-               en.tenum = maxtype(en.cenum, en.tenum);
-
-               if(!typefd[en.cenum->etype])
-                       en.lastenum = n->vconst;
-               else
-                       en.floatenum = n->fconst;
-       }
-       if(dclstack)
-               push1(s);
-       xdecl(CXXX, types[TENUM], s);
-
-       if(en.cenum == T) {
-               en.tenum = types[TINT];
-               en.cenum = types[TINT];
-               en.lastenum = 0;
-       }
-       s->tenum = en.cenum;
-
-       if(!typefd[s->tenum->etype]) {
-               s->vconst = convvtox(en.lastenum, s->tenum->etype);
-               en.lastenum++;
-       } else {
-               s->fconst = en.floatenum;
-               en.floatenum++;
-       }
-
-       if(debug['d'])
-               dbgdecl(s);
-       acidvar(s);
-       godefvar(s);
-}
-
-void
-symadjust(Sym *s, Node *n, int32 del)
-{
-
-       switch(n->op) {
-       default:
-               if(n->left)
-                       symadjust(s, n->left, del);
-               if(n->right)
-                       symadjust(s, n->right, del);
-               return;
-
-       case ONAME:
-               if(n->sym == s)
-                       n->xoffset -= del;
-               return;
-
-       case OCONST:
-       case OSTRING:
-       case OLSTRING:
-       case OINDREG:
-       case OREGISTER:
-               return;
-       }
-}
-
-Node*
-contig(Sym *s, Node *n, int32 v)
-{
-       Node *p, *r, *q, *m;
-       int32 w;
-       Type *zt;
-
-       if(debug['i']) {
-               print("contig v = %d; s = %s\n", v, s->name);
-               prtree(n, "doinit value");
-       }
-
-       if(n == Z)
-               goto no;
-       w = s->type->width;
-
-       /*
-        * nightmare: an automatic array whose size
-        * increases when it is initialized
-        */
-       if(v != w) {
-               if(v != 0)
-                       diag(n, "automatic adjustable array: %s", s->name);
-               v = s->offset;
-               autoffset = align(autoffset, s->type, Aaut3, nil);
-               s->offset = -autoffset;
-               stkoff = maxround(stkoff, autoffset);
-               symadjust(s, n, v - s->offset);
-       }
-       if(w <= ewidth[TIND])
-               goto no;
-       if(n->op == OAS)
-               diag(Z, "oops in contig");
-/*ZZZ this appears incorrect
-need to check if the list completely covers the data.
-if not, bail
- */
-       if(n->op == OLIST)
-               goto no;
-       if(n->op == OASI)
-               if(n->left->type)
-               if(n->left->type->width == w)
-                       goto no;
-       while(w & (ewidth[TIND]-1))
-               w++;
-/*
- * insert the following code, where long becomes vlong if pointers are fat
- *
-       *(long**)&X = (long*)((char*)X + sizeof(X));
-       do {
-               *(long**)&X -= 1;
-               **(long**)&X = 0;
-       } while(*(long**)&X);
- */
-
-       for(q=n; q->op != ONAME; q=q->left)
-               ;
-
-       zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG];
-
-       p = new(ONAME, Z, Z);
-       *p = *q;
-       p->type = typ(TIND, zt);
-       p->xoffset = s->offset;
-
-       r = new(ONAME, Z, Z);
-       *r = *p;
-       r = new(OPOSTDEC, r, Z);
-
-       q = new(ONAME, Z, Z);
-       *q = *p;
-       q = new(OIND, q, Z);
-
-       m = new(OCONST, Z, Z);
-       m->vconst = 0;
-       m->type = zt;
-
-       q = new(OAS, q, m);
-
-       r = new(OLIST, r, q);
-
-       q = new(ONAME, Z, Z);
-       *q = *p;
-       r = new(ODWHILE, q, r);
-
-       q = new(ONAME, Z, Z);
-       *q = *p;
-       q->type = q->type->link;
-       q->xoffset += w;
-       q = new(OADDR, q, 0);
-
-       q = new(OASI, p, q);
-       r = new(OLIST, q, r);
-
-       n = new(OLIST, r, n);
-
-no:
-       return n;
-}
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
deleted file mode 100644 (file)
index 606bf40..0000000
+++ /dev/null
@@ -1,793 +0,0 @@
-// Inferno utils/cc/dpchk.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/dpchk.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "cc.h"
-#include       "y.tab.h"
-
-enum
-{
-       Fnone   = 0,
-       Fl,
-       Fvl,
-       Fignor,
-       Fstar,
-       Fadj,
-
-       Fverb   = 10,
-};
-
-typedef        struct  Tprot   Tprot;
-struct Tprot
-{
-       Type*   type;
-       Bits    flag;
-       Tprot*  link;
-};
-
-typedef        struct  Tname   Tname;
-struct Tname
-{
-       char*   name;
-       int     param;
-       int     count;
-       Tname*  link;
-       Tprot*  prot;
-};
-
-static Type*   indchar;
-static uchar   flagbits[512];
-static char*   lastfmt;
-static int     lastadj;
-static int     lastverb;
-static int     nstar;
-static Tprot*  tprot;
-static Tname*  tname;
-
-void
-argflag(int c, int v)
-{
-
-       switch(v) {
-       case Fignor:
-       case Fstar:
-       case Fl:
-       case Fvl:
-               flagbits[c] = v;
-               break;
-       case Fverb:
-               flagbits[c] = lastverb;
-/*print("flag-v %c %d\n", c, lastadj);*/
-               lastverb++;
-               break;
-       case Fadj:
-               flagbits[c] = lastadj;
-/*print("flag-l %c %d\n", c, lastadj);*/
-               lastadj++;
-               break;
-       }
-}
-
-Bits
-getflag(char *s)
-{
-       Bits flag;
-       int f;
-       Fmt fmt;
-       Rune c;
-
-       flag = zbits;
-       nstar = 0;
-       fmtstrinit(&fmt);
-       for(;;) {
-               s += chartorune(&c, s);
-               if(c == 0 || c >= nelem(flagbits))
-                       break;
-               fmtrune(&fmt, c);
-               f = flagbits[c];
-               switch(f) {
-               case Fnone:
-                       argflag(c, Fverb);
-                       f = flagbits[c];
-                       break;
-               case Fstar:
-                       nstar++;
-               case Fignor:
-                       continue;
-               case Fl:
-                       if(bset(flag, Fl))
-                               flag = bor(flag, blsh(Fvl));
-               }
-               flag = bor(flag, blsh(f));
-               if(f >= Fverb)
-                       break;
-       }
-       free(lastfmt);
-       lastfmt = fmtstrflush(&fmt);
-       return flag;
-}
-
-static void
-newprot(Sym *m, Type *t, char *s, Tprot **prot)
-{
-       Bits flag;
-       Tprot *l;
-
-       if(t == T) {
-               warn(Z, "%s: newprot: type not defined", m->name);
-               return;
-       }
-       flag = getflag(s);
-       for(l=*prot; l; l=l->link)
-               if(beq(flag, l->flag) && sametype(t, l->type))
-                       return;
-       l = alloc(sizeof(*l));
-       l->type = t;
-       l->flag = flag;
-       l->link = *prot;
-       *prot = l;
-}
-
-static Tname*
-newname(char *s, int p, int count)
-{
-       Tname *l;
-
-       for(l=tname; l; l=l->link)
-               if(strcmp(l->name, s) == 0) {
-                       if(p >= 0 && l->param != p)
-                               yyerror("vargck %s already defined\n", s);
-                       return l;
-               }
-       if(p < 0)
-               return nil;
-
-       l = alloc(sizeof(*l));
-       l->name = s;
-       l->param = p;
-       l->link = tname;
-       l->count = count;
-       tname = l;
-       return l;
-}
-
-void
-arginit(void)
-{
-       int i;
-
-/* debug['F'] = 1;*/
-/* debug['w'] = 1;*/
-
-       lastadj = Fadj;
-       lastverb = Fverb;
-       indchar = typ(TIND, types[TCHAR]);
-
-       memset(flagbits, Fnone, sizeof(flagbits));
-
-       for(i='0'; i<='9'; i++)
-               argflag(i, Fignor);
-       argflag('.', Fignor);
-       argflag('#', Fignor);
-       argflag('u', Fignor);
-       argflag('h', Fignor);
-       argflag('+', Fignor);
-       argflag('-', Fignor);
-
-       argflag('*', Fstar);
-       argflag('l', Fl);
-
-       argflag('o', Fverb);
-       flagbits['x'] = flagbits['o'];
-       flagbits['X'] = flagbits['o'];
-}
-
-static char*
-getquoted(void)
-{
-       int c;
-       Rune r;
-       Fmt fmt;
-
-       c = getnsc();
-       if(c != '"')
-               return nil;
-       fmtstrinit(&fmt);
-       for(;;) {
-               r = getr();
-               if(r == '\n') {
-                       free(fmtstrflush(&fmt));
-                       return nil;
-               }
-               if(r == '"')
-                       break;
-               fmtrune(&fmt, r);
-       }
-       free(lastfmt);
-       lastfmt = fmtstrflush(&fmt);
-       return strdup(lastfmt);
-}
-
-void
-pragvararg(void)
-{
-       Sym *s;
-       int n, c;
-       char *t;
-       Type *ty;
-       Tname *l;
-
-       if(!debug['F'])
-               goto out;
-       s = getsym();
-       if(s && strcmp(s->name, "argpos") == 0)
-               goto ckpos;
-       if(s && strcmp(s->name, "type") == 0)
-               goto cktype;
-       if(s && strcmp(s->name, "flag") == 0)
-               goto ckflag;
-       if(s && strcmp(s->name, "countpos") == 0)
-               goto ckcount;
-       yyerror("syntax in #pragma varargck");
-       goto out;
-
-ckpos:
-/*#pragma      varargck        argpos  warn    2*/
-       s = getsym();
-       if(s == S)
-               goto bad;
-       n = getnsn();
-       if(n < 0)
-               goto bad;
-       newname(s->name, n, 0);
-       goto out;
-
-ckcount:
-/*#pragma      varargck        countpos        name 2*/
-       s = getsym();
-       if(s == S)
-               goto bad;
-       n = getnsn();
-       if(n < 0)
-               goto bad;
-       newname(s->name, 0, n);
-       goto out;
-
-ckflag:
-/*#pragma      varargck        flag    'c'*/
-       c = getnsc();
-       if(c != '\'')
-               goto bad;
-       c = getr();
-       if(c == '\\')
-               c = getr();
-       else if(c == '\'')
-               goto bad;
-       if(c == '\n')
-               goto bad;
-       if(getc() != '\'')
-               goto bad;
-       argflag(c, Fignor);
-       goto out;
-
-cktype:
-       c = getnsc();
-       unget(c);
-       if(c != '"') {
-/*#pragma      varargck        type    name    int*/
-               s = getsym();
-               if(s == S)
-                       goto bad;
-               l = newname(s->name, -1, -1);
-               s = getsym();
-               if(s == S)
-                       goto bad;
-               ty = s->type;
-               while((c = getnsc()) == '*')
-                       ty = typ(TIND, ty);
-               unget(c);
-               newprot(s, ty, "a", &l->prot);
-               goto out;
-       }
-
-/*#pragma      varargck        type    O       int*/
-       t = getquoted();
-       if(t == nil)
-               goto bad;
-       s = getsym();
-       if(s == S)
-               goto bad;
-       ty = s->type;
-       while((c = getnsc()) == '*')
-               ty = typ(TIND, ty);
-       unget(c);
-       newprot(s, ty, t, &tprot);
-       goto out;
-
-bad:
-       yyerror("syntax in #pragma varargck");
-
-out:
-       while(getnsc() != '\n')
-               ;
-}
-
-Node*
-nextarg(Node *n, Node **a)
-{
-       if(n == Z) {
-               *a = Z;
-               return Z;
-       }
-       if(n->op == OLIST) {
-               *a = n->left;
-               return n->right;
-       }
-       *a = n;
-       return Z;
-}
-
-void
-checkargs(Node *nn, char *s, int pos)
-{
-       Node *a, *n;
-       Bits flag;
-       Tprot *l;
-
-       if(!debug['F'])
-               return;
-       n = nn;
-       for(;;) {
-               s = strchr(s, '%');
-               if(s == 0) {
-                       nextarg(n, &a);
-                       if(a != Z)
-                               warn(nn, "more arguments than format %T",
-                                       a->type);
-                       return;
-               }
-               s++;
-               flag = getflag(s);
-               while(nstar > 0) {
-                       n = nextarg(n, &a);
-                       pos++;
-                       nstar--;
-                       if(a == Z) {
-                               warn(nn, "more format than arguments %s",
-                                       lastfmt);
-                               return;
-                       }
-                       if(a->type == T)
-                               continue;
-                       if(!sametype(types[TINT], a->type) &&
-                          !sametype(types[TUINT], a->type))
-                               warn(nn, "format mismatch '*' in %s %T, arg %d",
-                                       lastfmt, a->type, pos);
-               }
-               for(l=tprot; l; l=l->link)
-                       if(sametype(types[TVOID], l->type)) {
-                               if(beq(flag, l->flag)) {
-                                       s++;
-                                       goto loop;
-                               }
-                       }
-
-               n = nextarg(n, &a);
-               pos++;
-               if(a == Z) {
-                       warn(nn, "more format than arguments %s",
-                               lastfmt);
-                       return;
-               }
-               if(a->type == 0)
-                       continue;
-               for(l=tprot; l; l=l->link)
-                       if(sametype(a->type, l->type)) {
-/*print("checking %T/%ux %T/%ux\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
-                               if(beq(flag, l->flag))
-                                       goto loop;
-                       }
-               warn(nn, "format mismatch %s %T, arg %d", lastfmt, a->type, pos);
-       loop:;
-       }
-}
-
-void
-dpcheck(Node *n)
-{
-       char *s;
-       Node *a, *b;
-       Tname *l;
-       Tprot *tl;
-       int i, j;
-
-       if(n == Z)
-               return;
-       b = n->left;
-       if(b == Z || b->op != ONAME)
-               return;
-       s = b->sym->name;
-       for(l=tname; l; l=l->link)
-               if(strcmp(s, l->name) == 0)
-                       break;
-       if(l == 0)
-               return;
-
-       if(l->count > 0) {
-               // fetch count, then check remaining length
-               i = l->count;
-               a = nil;
-               b = n->right;
-               while(i > 0) {
-                       b = nextarg(b, &a);
-                       i--;
-               }
-               if(a == Z) {
-                       diag(n, "can't find count arg");
-                       return;
-               }
-               if(a->op != OCONST || !typechl[a->type->etype]) {
-                       diag(n, "count is invalid constant");
-                       return;
-               }
-               j = a->vconst;
-               i = 0;
-               while(b != Z) {
-                       b = nextarg(b, &a);
-                       i++;
-               }
-               if(i != j)
-                       diag(n, "found %d argument%s after count %d", i, i == 1 ? "" : "s", j);
-       }
-
-       if(l->prot != nil) {
-               // check that all arguments after param or count
-               // are listed in type list.
-               i = l->count;
-               if(i == 0)
-                       i = l->param;
-               if(i == 0)
-                       return;
-               a = nil;
-               b = n->right;
-               while(i > 0) {
-                       b = nextarg(b, &a);
-                       i--;
-               }
-               if(a == Z) {
-                       diag(n, "can't find count/param arg");
-                       return;
-               }
-               while(b != Z) {
-                       b = nextarg(b, &a);
-                       for(tl=l->prot; tl; tl=tl->link)
-                               if(sametype(a->type, tl->type))
-                                       break;
-                       if(tl == nil)
-                               diag(a, "invalid type %T in call to %s", a->type, s);
-               }
-       }
-
-       if(l->param <= 0)
-               return;
-       i = l->param;
-       a = nil;
-       b = n->right;
-       while(i > 0) {
-               b = nextarg(b, &a);
-               i--;
-       }
-       if(a == Z) {
-               diag(n, "can't find format arg");
-               return;
-       }
-       if(!sametype(indchar, a->type)) {
-               diag(n, "format arg type %T", a->type);
-               return;
-       }
-       if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
-/*             warn(n, "format arg not constant string");*/
-               return;
-       }
-       s = a->left->cstring;
-       checkargs(b, s, l->param);
-}
-
-void
-pragpack(void)
-{
-       Sym *s;
-
-       packflg = 0;
-       s = getsym();
-       if(s) {
-               packflg = atoi(s->name+1);
-               if(strcmp(s->name, "on") == 0 ||
-                  strcmp(s->name, "yes") == 0)
-                       packflg = 1;
-       }
-       while(getnsc() != '\n')
-               ;
-       if(debug['f'])
-               if(packflg)
-                       print("%4d: pack %d\n", lineno, packflg);
-               else
-                       print("%4d: pack off\n", lineno);
-}
-
-void
-pragfpround(void)
-{
-       Sym *s;
-
-       fproundflg = 0;
-       s = getsym();
-       if(s) {
-               fproundflg = atoi(s->name+1);
-               if(strcmp(s->name, "on") == 0 ||
-                  strcmp(s->name, "yes") == 0)
-                       fproundflg = 1;
-       }
-       while(getnsc() != '\n')
-               ;
-       if(debug['f'])
-               if(fproundflg)
-                       print("%4d: fproundflg %d\n", lineno, fproundflg);
-               else
-                       print("%4d: fproundflg off\n", lineno);
-}
-
-void
-pragtextflag(void)
-{
-       Sym *s;
-
-       s = getsym();
-       if(s == S) {
-               textflag = getnsn();
-       } else {
-               if(s->macro) {
-                       macexpand(s, symb);
-               }
-               if(symb[0] < '0' || symb[0] > '9')
-                       yyerror("pragma textflag not an integer");
-               textflag = atoi(symb);
-       }
-       while(getnsc() != '\n')
-               ;
-       if(debug['f'])
-               print("%4d: textflag %d\n", lineno, textflag);
-}
-
-void
-pragdataflag(void)
-{
-       Sym *s;
-
-       s = getsym();
-       if(s == S) {
-               dataflag = getnsn();
-       } else {
-               if(s->macro) {
-                       macexpand(s, symb);
-               }
-               if(symb[0] < '0' || symb[0] > '9')
-                       yyerror("pragma dataflag not an integer");
-               dataflag = atoi(symb);
-       }
-       while(getnsc() != '\n')
-               ;
-       if(debug['f'])
-               print("%4d: dataflag %d\n", lineno, dataflag);
-}
-
-void
-pragincomplete(void)
-{
-       Sym *s;
-       Type *t;
-       int istag, w, et;
-
-       istag = 0;
-       s = getsym();
-       if(s == nil)
-               goto out;
-       et = 0;
-       w = s->lexical;
-       if(w == LSTRUCT)
-               et = TSTRUCT;
-       else if(w == LUNION)
-               et = TUNION;
-       if(et != 0){
-               s = getsym();
-               if(s == nil){
-                       yyerror("missing struct/union tag in pragma incomplete");
-                       goto out;
-               }
-               if(s->lexical != LNAME && s->lexical != LTYPE){
-                       yyerror("invalid struct/union tag: %s", s->name);
-                       goto out;
-               }
-               dotag(s, et, 0);
-               istag = 1;
-       }else if(strcmp(s->name, "_off_") == 0){
-               debug['T'] = 0;
-               goto out;
-       }else if(strcmp(s->name, "_on_") == 0){
-               debug['T'] = 1;
-               goto out;
-       }
-       t = s->type;
-       if(istag)
-               t = s->suetag;
-       if(t == T)
-               yyerror("unknown type %s in pragma incomplete", s->name);
-       else if(!typesu[t->etype])
-               yyerror("not struct/union type in pragma incomplete: %s", s->name);
-       else
-               t->garb |= GINCOMPLETE;
-out:
-       while(getnsc() != '\n')
-               ;
-       if(debug['f'])
-               print("%s incomplete\n", s->name);
-}
-
-Sym*
-getimpsym(void)
-{
-       int c;
-       char *cp;
-
-       c = getnsc();
-       if(isspace(c) || c == '"') {
-               unget(c);
-               return S;
-       }
-       for(cp = symb;;) {
-               if(cp <= symb+NSYMB-4)
-                       *cp++ = c;
-               c = getc();
-               if(c > 0 && !isspace(c) && c != '"')
-                       continue;
-               unget(c);
-               break;
-       }
-       *cp = 0;
-       if(cp > symb+NSYMB-4)
-               yyerror("symbol too large: %s", symb);
-       return lookup();
-}
-
-static int
-more(void)
-{
-       int c;
-       
-       do
-               c = getnsc();
-       while(c == ' ' || c == '\t');
-       unget(c);
-       return c != '\n';
-}
-
-void
-pragcgo(char *verb)
-{
-       Sym *local, *remote;
-       char *p;
-
-       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, "dynexport") == 0)
-               verb = "cgo_export_dynamic";
-       if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
-               local = getimpsym();
-               if(local == nil)
-                       goto err2;
-               if(!more()) {
-                       fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
-                       goto out;
-               }
-               remote = getimpsym();
-               if(remote == nil)
-                       goto err2;
-               fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
-               goto out;
-       
-       err2:
-               yyerror("usage: #pragma %s local [remote]", verb);
-               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;
-       }
-       
-       if(strcmp(verb, "cgo_ldflag") == 0) {
-               p = getquoted();
-               if(p == nil)
-                       goto err5;
-               fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
-               goto out;
-
-       err5:
-               yyerror("usage: #pragma cgo_ldflag \"arg\"");
-               goto out;
-       }
-       
-out:
-       while(getnsc() != '\n')
-               ;
-}
diff --git a/src/cmd/cc/funct.c b/src/cmd/cc/funct.c
deleted file mode 100644 (file)
index 92c067d..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-// Inferno utils/cc/funct.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/funct.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "cc.h"
-
-typedef        struct  Ftab    Ftab;
-struct Ftab
-{
-       char    op;
-       char*   name;
-       char    typ;
-};
-typedef        struct  Gtab    Gtab;
-struct Gtab
-{
-       char    etype;
-       char*   name;
-};
-
-Ftab   ftabinit[OEND];
-Gtab   gtabinit[NALLTYPES];
-
-int
-isfunct(Node *n)
-{
-       Type *t, *t1;
-       Funct *f;
-       Node *l;
-       Sym *s;
-       int o;
-
-       o = n->op;
-       if(n->left == Z)
-               goto no;
-       t = n->left->type;
-       if(t == T)
-               goto no;
-       f = t->funct;
-
-       switch(o) {
-       case OAS:       // put cast on rhs
-       case OASI:
-       case OASADD:
-       case OASAND:
-       case OASASHL:
-       case OASASHR:
-       case OASDIV:
-       case OASLDIV:
-       case OASLMOD:
-       case OASLMUL:
-       case OASLSHR:
-       case OASMOD:
-       case OASMUL:
-       case OASOR:
-       case OASSUB:
-       case OASXOR:
-               if(n->right == Z)
-                       goto no;
-               t1 = n->right->type;
-               if(t1 == T)
-                       goto no;
-               if(t1->funct == f)
-                       break;
-
-               l = new(OXXX, Z, Z);
-               *l = *n->right;
-
-               n->right->left = l;
-               n->right->right = Z;
-               n->right->type = t;
-               n->right->op = OCAST;
-
-               if(!isfunct(n->right))
-                       prtree(n, "isfunc !");
-               break;
-
-       case OCAST:     // t f(T) or T f(t)
-               t1 = n->type;
-               if(t1 == T)
-                       goto no;
-               if(f != nil) {
-                       s = f->castfr[t1->etype];
-                       if(s == S)
-                               goto no;
-                       n->right = n->left;
-                       goto build;
-               }
-               f = t1->funct;
-               if(f != nil) {
-                       s = f->castto[t->etype];
-                       if(s == S)
-                               goto no;
-                       n->right = n->left;
-                       goto build;
-               }
-               goto no;
-       }
-
-       if(f == nil)
-               goto no;
-       s = f->sym[o];
-       if(s == S)
-               goto no;
-
-       /*
-        * the answer is yes,
-        * now we rewrite the node
-        * and give diagnostics
-        */
-       switch(o) {
-       default:
-               diag(n, "isfunct op missing %O\n", o);
-               goto bad;
-
-       case OADD:      // T f(T, T)
-       case OAND:
-       case OASHL:
-       case OASHR:
-       case ODIV:
-       case OLDIV:
-       case OLMOD:
-       case OLMUL:
-       case OLSHR:
-       case OMOD:
-       case OMUL:
-       case OOR:
-       case OSUB:
-       case OXOR:
-
-       case OEQ:       // int f(T, T)
-       case OGE:
-       case OGT:
-       case OHI:
-       case OHS:
-       case OLE:
-       case OLO:
-       case OLS:
-       case OLT:
-       case ONE:
-               if(n->right == Z)
-                       goto bad;
-               t1 = n->right->type;
-               if(t1 == T)
-                       goto bad;
-               if(t1->funct != f)
-                       goto bad;
-               n->right = new(OLIST, n->left, n->right);
-               break;
-
-       case OAS:       // structure copies done by the compiler
-       case OASI:
-               goto no;
-
-       case OASADD:    // T f(T*, T)
-       case OASAND:
-       case OASASHL:
-       case OASASHR:
-       case OASDIV:
-       case OASLDIV:
-       case OASLMOD:
-       case OASLMUL:
-       case OASLSHR:
-       case OASMOD:
-       case OASMUL:
-       case OASOR:
-       case OASSUB:
-       case OASXOR:
-               if(n->right == Z)
-                       goto bad;
-               t1 = n->right->type;
-               if(t1 == T)
-                       goto bad;
-               if(t1->funct != f)
-                       goto bad;
-               n->right = new(OLIST, new(OADDR, n->left, Z), n->right);
-               break;
-
-       case OPOS:      // T f(T)
-       case ONEG:
-       case ONOT:
-       case OCOM:
-               n->right = n->left;
-               break;
-
-
-       }
-
-build:
-       l = new(ONAME, Z, Z);
-       l->sym = s;
-       l->type = s->type;
-       l->etype = s->type->etype;
-       l->xoffset = s->offset;
-       l->class = s->class;
-       tcomo(l, 0);
-
-       n->op = OFUNC;
-       n->left = l;
-       n->type = l->type->link;
-       if(tcompat(n, T, l->type, tfunct))
-               goto bad;
-       if(tcoma(n->left, n->right, l->type->down, 1))
-               goto bad;
-       return 1;
-
-no:
-       return 0;
-
-bad:
-       diag(n, "can't rewrite typestr for op %O\n", o);
-       prtree(n, "isfunct");
-       n->type = T;
-       return 1;
-}
-
-void
-dclfunct(Type *t, Sym *s)
-{
-       Funct *f;
-       Node *n;
-       Type *f1, *f2, *f3, *f4;
-       int o, i, c;
-       char str[100];
-
-       if(t->funct)
-               return;
-
-       // recognize generated tag of dorm _%d_
-       if(t->tag == S)
-               goto bad;
-       for(i=0; c = t->tag->name[i]; i++) {
-               if(c == '_') {
-                       if(i == 0 || t->tag->name[i+1] == 0)
-                               continue;
-                       break;
-               }
-               if(c < '0' || c > '9')
-                       break;
-       }
-       if(c == 0)
-               goto bad;
-
-       f = alloc(sizeof(*f));
-       for(o=0; o<nelem(f->sym); o++)
-               f->sym[o] = S;
-
-       t->funct = f;
-
-       f1 = typ(TFUNC, t);
-       f1->down = copytyp(t);
-       f1->down->down = t;
-
-       f2 = typ(TFUNC, types[TINT]);
-       f2->down = copytyp(t);
-       f2->down->down = t;
-
-       f3 = typ(TFUNC, t);
-       f3->down = typ(TIND, t);
-       f3->down->down = t;
-
-       f4 = typ(TFUNC, t);
-       f4->down = t;
-
-       for(i=0;; i++) {
-               o = ftabinit[i].op;
-               if(o == OXXX)
-                       break;
-               sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name);
-               n = new(ONAME, Z, Z);
-               n->sym = slookup(str);
-               f->sym[o] = n->sym;
-               switch(ftabinit[i].typ) {
-               default:
-                       diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ);
-                       break;
-
-               case 1: // T f(T,T)     +
-                       dodecl(xdecl, CEXTERN, f1, n);
-                       break;
-
-               case 2: // int f(T,T)   ==
-                       dodecl(xdecl, CEXTERN, f2, n);
-                       break;
-
-               case 3: // void f(T*,T) +=
-                       dodecl(xdecl, CEXTERN, f3, n);
-                       break;
-
-               case 4: // T f(T)       ~
-                       dodecl(xdecl, CEXTERN, f4, n);
-                       break;
-               }
-       }
-       for(i=0;; i++) {
-               o = gtabinit[i].etype;
-               if(o == TXXX)
-                       break;
-
-               /*
-                * OCAST types T1 _T2_T1_(T2)
-                */
-               sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name);
-               n = new(ONAME, Z, Z);
-               n->sym = slookup(str);
-               f->castto[o] = n->sym;
-
-               f1 = typ(TFUNC, t);
-               f1->down = types[o];
-               dodecl(xdecl, CEXTERN, f1, n);
-
-               sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name);
-               n = new(ONAME, Z, Z);
-               n->sym = slookup(str);
-               f->castfr[o] = n->sym;
-
-               f1 = typ(TFUNC, types[o]);
-               f1->down = t;
-               dodecl(xdecl, CEXTERN, f1, n);
-       }
-       return;
-bad:
-       diag(Z, "dclfunct bad %T %s\n", t, s->name);
-}
-
-Gtab   gtabinit[NALLTYPES] =
-{
-       TCHAR,          "c",
-       TUCHAR,         "uc",
-       TSHORT,         "h",
-       TUSHORT,        "uh",
-       TINT,           "i",
-       TUINT,          "ui",
-       TLONG,          "l",
-       TULONG,         "ul",
-       TVLONG,         "v",
-       TUVLONG,        "uv",
-       TFLOAT,         "f",
-       TDOUBLE,        "d",
-       TXXX
-};
-
-Ftab   ftabinit[OEND] =
-{
-       OADD,           "add",          1,
-       OAND,           "and",          1,
-       OASHL,          "ashl",         1,
-       OASHR,          "ashr",         1,
-       ODIV,           "div",          1,
-       OLDIV,          "ldiv",         1,
-       OLMOD,          "lmod",         1,
-       OLMUL,          "lmul",         1,
-       OLSHR,          "lshr",         1,
-       OMOD,           "mod",          1,
-       OMUL,           "mul",          1,
-       OOR,            "or",           1,
-       OSUB,           "sub",          1,
-       OXOR,           "xor",          1,
-
-       OEQ,            "eq",           2,
-       OGE,            "ge",           2,
-       OGT,            "gt",           2,
-       OHI,            "hi",           2,
-       OHS,            "hs",           2,
-       OLE,            "le",           2,
-       OLO,            "lo",           2,
-       OLS,            "ls",           2,
-       OLT,            "lt",           2,
-       ONE,            "ne",           2,
-
-       OASADD,         "asadd",        3,
-       OASAND,         "asand",        3,
-       OASASHL,        "asashl",       3,
-       OASASHR,        "asashr",       3,
-       OASDIV,         "asdiv",        3,
-       OASLDIV,        "asldiv",       3,
-       OASLMOD,        "aslmod",       3,
-       OASLMUL,        "aslmul",       3,
-       OASLSHR,        "aslshr",       3,
-       OASMOD,         "asmod",        3,
-       OASMUL,         "asmul",        3,
-       OASOR,          "asor",         3,
-       OASSUB,         "assub",        3,
-       OASXOR,         "asxor",        3,
-
-       OPOS,           "pos",          4,
-       ONEG,           "neg",          4,
-       OCOM,           "com",          4,
-       ONOT,           "not",          4,
-
-//     OPOSTDEC,
-//     OPOSTINC,
-//     OPREDEC,
-//     OPREINC,
-
-       OXXX,
-};
-
-//     Node*   nodtestv;
-
-//     Node*   nodvpp;
-//     Node*   nodppv;
-//     Node*   nodvmm;
-//     Node*   nodmmv;
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
deleted file mode 100644 (file)
index d9f67f0..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-//   cmd/cc/godefs.cc
-//
-//   derived from pickle.cc which itself was derived from acid.cc.
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc. All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009-2011 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-static int upper;
-
-static char *kwd[] =
-{
-       "_bool",
-       "_break",
-       "_byte",
-       "_case",
-       "_chan",
-       "_complex128",
-       "_complex64",
-       "_const",
-       "_continue",
-       "_default",
-       "_defer",
-       "_else",
-       "_fallthrough",
-       "_false",
-       "_float32",
-       "_float64",
-       "_for",
-       "_func",
-       "_go",
-       "_goto",
-       "_if",
-       "_import",
-       "_int",
-       "_int16",
-       "_int32",
-       "_int64",
-       "_int8",
-       "_interface",
-       "_intptr",
-       "_map",
-       "_package",
-       "_panic",
-       "_range",
-       "_return",
-       "_select",
-       "_string",
-       "_struct",
-       "_switch",
-       "_true",
-       "_type",
-       "_uint",
-       "_uint16",
-       "_uint32",
-       "_uint64",
-       "_uint8",
-       "_uintptr",
-       "_var",
-};
-
-static char*
-pmap(char *s)
-{
-       int i, bot, top, mid;
-
-       bot = -1;
-       top = nelem(kwd);
-       while(top - bot > 1){
-               mid = (bot + top) / 2;
-               i = strcmp(kwd[mid]+1, s);
-               if(i == 0)
-                       return kwd[mid];
-               if(i < 0)
-                       bot = mid;
-               else
-                       top = mid;
-       }
-
-       return s;
-}
-
-
-int
-Uconv(Fmt *fp)
-{
-       char str[STRINGSZ+1];
-       char *s, *n;
-       int i;
-
-       str[0] = 0;
-       s = va_arg(fp->args, char*);
-
-       // strip package name
-       n = strrchr(s, '.');
-       if(n != nil)
-               s = n + 1;
-
-       if(s && *s) {
-               if(upper)
-                       str[0] = toupper((uchar)*s);
-               else
-                       str[0] = tolower((uchar)*s);
-               for(i = 1; i < STRINGSZ && s[i] != 0; i++)
-                       str[i] = tolower((uchar)s[i]);
-               str[i] = 0;
-       }
-
-       return fmtstrcpy(fp, pmap(str));
-}
-
-
-static Sym*
-findsue(Type *t)
-{
-       int h;
-       Sym *s;
-
-       if(t != T)
-       for(h=0; h<nelem(hash); h++)
-               for(s = hash[h]; s != S; s = s->link)
-                       if(s->suetag && s->suetag->link == t)
-                               return s;
-       return 0;
-}
-
-static void
-printtypename(Type *t)
-{
-       Sym *s;
-       int w;
-       char *n;
-
-       for( ; t != nil; t = t->link) {
-               switch(t->etype) {
-               case TIND:
-                       // Special handling of *void.
-                       if(t->link != nil && t->link->etype==TVOID) {
-                               Bprint(&outbuf, "unsafe.Pointer");
-                               return;
-                       }
-                       // *func == func
-                       if(t->link != nil && t->link->etype==TFUNC)
-                               continue;
-                       Bprint(&outbuf, "*");
-                       continue;
-               case TARRAY:
-                       w = t->width;
-                       if(t->link && t->link->width)
-                               w /= t->link->width;
-                       Bprint(&outbuf, "[%d]", w);
-                       continue;
-               }
-               break;
-       }
-
-       if(t == nil) {
-               Bprint(&outbuf, "bad // should not happen");
-               return;
-       }
-
-       switch(t->etype) {
-       case TINT:
-       case TUINT:
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TLONG:
-       case TULONG:
-       case TVLONG:
-       case TUVLONG:
-       case TFLOAT:
-       case TDOUBLE:
-               // All names used in the runtime code should be typedefs.
-               if(t->tag != nil) {
-                       if(strcmp(t->tag->name, "intgo") == 0)
-                               Bprint(&outbuf, "int");
-                       else if(strcmp(t->tag->name, "uintgo") == 0)
-                               Bprint(&outbuf, "uint");
-                       else
-                               Bprint(&outbuf, "%s", t->tag->name);
-               } else  
-                       Bprint(&outbuf, "C.%T", t);
-               break;
-       case TUNION:
-       case TSTRUCT:
-               s = findsue(t->link);
-               n = "bad";
-               if(s != S)
-                       n = s->name;
-               else if(t->tag)
-                       n = t->tag->name;
-               if(strcmp(n, "String") == 0)
-                       Bprint(&outbuf, "string");
-               else if(strcmp(n, "Slice") == 0)
-                       Bprint(&outbuf, "[]byte");
-               else if(strcmp(n, "Eface") == 0)
-                       Bprint(&outbuf, "interface{}");
-               else
-                       Bprint(&outbuf, "%U", n);
-               break;
-       case TFUNC:
-               // There's no equivalent to a C function in the Go world.
-               Bprint(&outbuf, "unsafe.Pointer");
-               break;
-       case TDOT:
-               Bprint(&outbuf, "...interface{}");
-               break;
-       default:
-               Bprint(&outbuf, " weird<%T>", t);
-       }
-}
-
-static int
-dontrun(void)
-{
-       Io *i;
-       int n;
-
-       if(!debug['q'] && !debug['Q'])
-               return 1;
-       if(debug['q'] + debug['Q'] > 1) {
-               n = 0;
-               for(i=iostack; i; i=i->link)
-                       n++;
-               if(n > 1)
-                       return 1;
-       }
-
-       upper = debug['Q'];
-       return 0;
-}
-
-void
-godeftype(Type *t)
-{
-       Sym *s;
-       Type *l;
-       int gotone;
-
-       if(dontrun())
-               return;
-
-       switch(t->etype) {
-       case TUNION:
-       case TSTRUCT:
-               s = findsue(t->link);
-               if(s == S) {
-                       Bprint(&outbuf, "/* can't find %T */\n\n", t);
-                       return;
-               }
-
-               gotone = 0; // for unions, take first member of size equal to union
-               Bprint(&outbuf, "type %U struct {\n", s->name);
-               for(l = t->link; l != T; l = l->down) {
-                       Bprint(&outbuf, "\t");
-                       if(t->etype == TUNION) {
-                               if(!gotone && l->width == t->width)
-                                       gotone = 1;
-                               else
-                                       Bprint(&outbuf, "// (union)\t");
-                       }
-                       if(l->sym != nil)  // not anonymous field
-                               Bprint(&outbuf, "%U\t", l->sym->name);
-                       printtypename(l);
-                       Bprint(&outbuf, "\n");
-               }
-               Bprint(&outbuf, "}\n\n");
-               break;
-
-       default:
-               Bprint(&outbuf, "/* %T */\n\n", t);
-               break;
-       }
-}
-
-void
-godefvar(Sym *s)
-{
-       Type *t, *t1;
-       char n;
-
-       if(dontrun())
-               return;
-
-       t = s->type;
-       if(t == nil)
-               return;
-
-       switch(t->etype) {
-       case TENUM:
-               if(!typefd[t->etype])
-                       Bprint(&outbuf, "const %s = %lld\n", s->name, s->vconst);
-               else
-                       Bprint(&outbuf, "const %s = %f\n;", s->name, s->fconst);
-               break;
-
-       case TFUNC:
-               Bprint(&outbuf, "func %U(", s->name);
-               n = 'a';
-               for(t1 = t->down; t1 != T; t1 = t1->down) {
-                       if(t1->etype == TVOID)
-                               break;
-                       if(t1 != t->down)
-                               Bprint(&outbuf, ", ");
-                       Bprint(&outbuf, "%c ", n++);
-                       printtypename(t1);
-               }
-               Bprint(&outbuf, ")");
-               if(t->link && t->link->etype != TVOID) {
-                       Bprint(&outbuf, " ");
-                       printtypename(t->link);
-               }
-               Bprint(&outbuf, "\n");
-               break;
-
-       default:
-               switch(s->class) {
-               case CTYPEDEF:
-                       if(!typesu[t->etype]) {
-                               Bprint(&outbuf, "// type %U\t", s->name);
-                               printtypename(t);
-                               Bprint(&outbuf, "\n");
-                       }
-                       break;
-               case CSTATIC:
-               case CEXTERN:
-               case CGLOBL:
-                       if(strchr(s->name, '$') != nil)
-                               break;
-                       if(strncmp(s->name, "go.weak.", 8) == 0)
-                               break;
-                       Bprint(&outbuf, "var %U\t", s->name);
-                       printtypename(t);
-                       Bprint(&outbuf, "\n");
-                       break;
-               }
-               break;
-       }
-}
diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c
deleted file mode 100644 (file)
index 7c9f718..0000000
+++ /dev/null
@@ -1,1593 +0,0 @@
-// Inferno utils/cc/lex.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/lex.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "cc.h"
-#include       "y.tab.h"
-#include       "../ld/textflag.h"
-
-#ifndef        CPP
-#define        CPP     "cpp"
-#endif
-
-int
-systemtype(int sys)
-{
-#ifdef _WIN32
-       return sys&Windows;
-#else
-       return sys&Plan9;
-#endif
-}
-
-int
-pathchar(void)
-{
-       return '/';
-}
-
-/*
- * known debug flags
- *     -a              acid declaration output
- *     -A              !B
- *     -B              non ANSI
- *     -d              print declarations
- *     -D name         define
- *     -F              format specification check
- *     -G              print pgen stuff
- *     -g              print cgen trees
- *     -i              print initialization
- *     -I path         include
- *     -l              generate little-endian code
- *     -L              print every NAME symbol
- *     -M              constant multiplication
- *     -m              print add/sub/mul trees
- *     -n              print acid or godefs to file (%.c=%.acid) (with -a or -aa)
- *     -o file         output file
- *     -p              use standard cpp ANSI preprocessor (not on windows)
- *     -p              something with peepholes
- *     -q              print equivalent Go code for variables and types (lower-case identifiers)
- *     -Q              print equivalent Go code for variables and types (upper-case identifiers)
- *     -r              print registerization
- *     -s              print structure offsets (with -a or -aa)
- *     -S              print assembly
- *     -t              print type trees
- *     -V              enable void* conversion warnings
- *     -v              verbose printing
- *     -w              print warnings
- *     -X              abort on error
- *     -.              Inhibit search for includes in source directory
- */
-
-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[])
-{
-       int c;
-       char *p;
-
-       // Allow GOARCH=thestring or GOARCH=thestringsuffix,
-       // but not other values.        
-       p = getgoarch();
-       if(strncmp(p, thestring, strlen(thestring)) != 0)
-               sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
-       if(strcmp(p, "amd64p32") == 0) // must be before cinit
-               ewidth[TIND] = 4;
-               
-       nacl = strcmp(getgoos(), "nacl") == 0;
-       if(nacl)
-               flag_largemodel = 1;
-
-       quotefmtinstall(); // before cinit, which overrides %Q
-
-       linkarchinit();
-       ctxt = linknew(thelinkarch);
-       ctxt->diag = yyerror;
-       ctxt->bso = &bstdout;
-       Binit(&bstdout, 1, OWRITE);
-
-       ensuresymb(NSYMB);
-       memset(debug, 0, sizeof(debug));
-       tinit();
-       cinit();
-       ginit();
-       arginit();
-       
-       fmtstrinit(&pragcgobuf);
-
-       tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
-       ndef = 0;
-       defs = nil;
-       outfile = 0;
-       setinclude(".");
-
-       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']);
-       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
-       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);
-       ctxt->debugasm = debug['S'];
-       ctxt->debugvlog = debug['v'];
-
-       if(argc < 1 && outfile == 0)
-               usage();
-
-       if(argc > 1){
-               print("can't compile multiple files\n");
-               errorexit();
-       }
-
-       if(argc == 0)
-               c = compile("stdin", defs, ndef);
-       else
-               c = compile(argv[0], defs, ndef);
-
-       Bflush(&bstdout);
-       if(c)
-               errorexit();
-       exits(0);
-}
-
-int
-compile(char *file, char **defs, int ndef)
-{
-       char *ofile;
-       char *p, **av, opt[256];
-       int i, c, fd[2];
-       static int first = 1;
-
-       ofile = alloc(strlen(file)+10);
-       strcpy(ofile, file);
-       p = utfrrune(ofile, pathchar());
-       if(p) {
-               *p++ = 0;
-               if(!debug['.'])
-                       include[0] = strdup(ofile);
-       } else
-               p = ofile;
-
-       if(outfile == 0) {
-               outfile = p;
-               if(outfile) {
-                       if(p = utfrrune(outfile, '.'))
-                               if(p[1] == 'c' && p[2] == 0)
-                                       p[0] = 0;
-                       p = utfrune(outfile, 0);
-                       if(debug['a'] && debug['n'])
-                               strcat(p, ".acid");
-                       else if((debug['q'] || debug['Q']) && debug['n'])
-                               strcat(p, ".go");
-                       else {
-                               p[0] = '.';
-                               p[1] = thechar;
-                               p[2] = 0;
-                       }
-               } else
-                       outfile = "/dev/null";
-       }
-
-       if (first)
-               Binit(&diagbuf, 1, OWRITE);
-       /*
-        * if we're writing acid to standard output, don't keep scratching
-        * outbuf.
-        */
-       if((debug['a'] || debug['q'] || debug['Q']) && !debug['n']) {
-               if (first) {
-                       outfile = 0;
-                       Binit(&outbuf, dup(1, -1), OWRITE);
-                       dup(2, 1);
-               }
-       } else {
-               c = create(outfile, OWRITE, 0664);
-               if(c < 0) {
-                       diag(Z, "cannot open %s - %r", outfile);
-                       outfile = 0;
-                       errorexit();
-               }
-               Binit(&outbuf, c, OWRITE);
-               outfile = strdup(outfile);
-       }
-       newio();
-       first = 0;
-
-       /* Use an ANSI preprocessor */
-       if(debug['p']) {
-               if(systemtype(Windows)) {
-                       diag(Z, "-p option not supported on windows");
-                       errorexit();
-               }
-               if(access(file, AREAD) < 0) {
-                       diag(Z, "%s does not exist", file);
-                       errorexit();
-               }
-               if(pipe(fd) < 0) {
-                       diag(Z, "pipe failed");
-                       errorexit();
-               }
-               switch(fork()) {
-               case -1:
-                       diag(Z, "fork failed");
-                       errorexit();
-               case 0:
-                       close(fd[0]);
-                       dup(fd[1], 1);
-                       close(fd[1]);
-                       av = alloc((ndef+ninclude+5)*sizeof(char *));
-                       av[0] = CPP;
-                       i = 1;
-                       if(debug['.']){
-                               sprint(opt, "-.");
-                               av[i++] = strdup(opt);
-                       }
-                       if(debug['+']) {
-                               sprint(opt, "-+");
-                               av[i++] = strdup(opt);
-                       }
-                       for(c = 0; c < ndef; c++)
-                               av[i++] = smprint("-D%s", defs[c]);
-                       for(c = 0; c < ninclude; c++)
-                               av[i++] = smprint("-I%s", include[c]);
-                       if(strcmp(file, "stdin") != 0)
-                               av[i++] = file;
-                       av[i] = 0;
-                       if(debug['p'] > 1) {
-                               for(c = 0; c < i; c++)
-                                       fprint(2, "%s ", av[c]);
-                               fprint(2, "\n");
-                       }
-                       exec(av[0], av);
-                       fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
-                       errorexit();
-               default:
-                       close(fd[1]);
-                       newfile(file, fd[0]);
-                       break;
-               }
-       } else {
-               if(strcmp(file, "stdin") == 0)
-                       newfile(file, 0);
-               else
-                       newfile(file, -1);
-       }
-       yyparse();
-       if(!debug['a'] && !debug['q'] && !debug['Q'])
-               gclean();
-       return nerrors;
-}
-
-void
-errorexit(void)
-{
-       Bflush(&bstdout);
-       if(outfile)
-               remove(outfile);
-       exits("error");
-}
-
-void
-pushio(void)
-{
-       Io *i;
-
-       i = iostack;
-       if(i == I) {
-               yyerror("botch in pushio");
-               errorexit();
-       }
-       i->p = fi.p;
-       i->c = fi.c;
-}
-
-void
-newio(void)
-{
-       Io *i;
-       static int pushdepth = 0;
-
-       i = iofree;
-       if(i == I) {
-               pushdepth++;
-               if(pushdepth > 1000) {
-                       yyerror("macro/io expansion too deep");
-                       errorexit();
-               }
-               i = alloc(sizeof(*i));
-       } else
-               iofree = i->link;
-       i->c = 0;
-       i->f = -1;
-       ionext = i;
-}
-
-void
-newfile(char *s, int f)
-{
-       Io *i;
-
-       if(debug['e'])
-               print("%L: %s\n", lineno, s);
-
-       i = ionext;
-       i->link = iostack;
-       iostack = i;
-       i->f = f;
-       if(f < 0)
-               i->f = open(s, 0);
-       if(i->f < 0) {
-               yyerror("%cc: %r: %s", thechar, s);
-               errorexit();
-       }
-       fi.c = 0;
-       linklinehist(ctxt, lineno, s, 0);
-}
-
-Sym*
-slookup(char *s)
-{
-       ensuresymb(strlen(s));
-       strcpy(symb, s);
-       return lookup();
-}
-
-Sym*
-lookup(void)
-{
-       Sym *s;
-       uint32 h;
-       char *p;
-       int c, n;
-       char *r, *w;
-
-       if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) {
-               // turn leading Â· into ""·
-               h = strlen(symb);
-               ensuresymb(h+2);
-               memmove(symb+2, symb, h+1);
-               symb[0] = '"';
-               symb[1] = '"';
-       }
-
-       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;
-       }
-       *w = '\0';
-
-       h = 0;
-       for(p=symb; *p;) {
-               h = h * 3;
-               h += *p++;
-       }
-       n = (p - symb) + 1;
-       h &= 0xffffff;
-       h %= NHASH;
-       c = symb[0];
-       for(s = hash[h]; s != S; s = s->link) {
-               if(s->name[0] != c)
-                       continue;
-               if(strcmp(s->name, symb) == 0)
-                       return s;
-       }
-       s = alloc(sizeof(*s));
-       s->name = alloc(n);
-       memmove(s->name, symb, n);
-       s->link = hash[h];
-       hash[h] = s;
-       syminit(s);
-
-       return s;
-}
-
-void
-syminit(Sym *s)
-{
-       s->lexical = LNAME;
-       s->block = 0;
-       s->offset = 0;
-       s->type = T;
-       s->suetag = T;
-       s->class = CXXX;
-       s->aused = 0;
-       s->sig = SIGNONE;
-}
-
-#define        EOF     (-1)
-#define        IGN     (-2)
-#define        ESC     (1<<20)
-#define        GETC()  ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
-
-enum
-{
-       Numdec          = 1<<0,
-       Numlong         = 1<<1,
-       Numuns          = 1<<2,
-       Numvlong        = 1<<3,
-       Numflt          = 1<<4,
-};
-
-int32
-yylex(void)
-{
-       vlong vv;
-       int32 c, c1, t;
-       char *cp;
-       Rune rune;
-       Sym *s;
-
-       if(peekc != IGN) {
-               c = peekc;
-               peekc = IGN;
-               goto l1;
-       }
-l0:
-       c = GETC();
-
-l1:
-       if(c >= Runeself) {
-               /*
-                * extension --
-                *      all multibyte runes are alpha
-                */
-               cp = symb;
-               goto talph;
-       }
-       if(isspace(c)) {
-               if(c == '\n')
-                       lineno++;
-               goto l0;
-       }
-       if(isalpha(c)) {
-               cp = symb;
-               if(c != 'L')
-                       goto talph;
-               *cp++ = c;
-               c = GETC();
-               if(c == '\'') {
-                       /* L'x' */
-                       c = escchar('\'', 1, 0);
-                       if(c == EOF)
-                               c = '\'';
-                       c1 = escchar('\'', 1, 0);
-                       if(c1 != EOF) {
-                               yyerror("missing '");
-                               peekc = c1;
-                       }
-                       yylval.vval = convvtox(c, TRUNE);
-                       return LUCONST;
-               }
-               if(c == '"') {
-                       goto caselq;
-               }
-               goto talph;
-       }
-       if(isdigit(c))
-               goto tnum;
-       switch(c)
-       {
-
-       case EOF:
-               peekc = EOF;
-               return -1;
-
-       case '_':
-               cp = symb;
-               goto talph;
-
-       case '#':
-               domacro();
-               goto l0;
-
-       case '.':
-               c1 = GETC();
-               if(isdigit(c1)) {
-                       cp = symb;
-                       *cp++ = c;
-                       c = c1;
-                       c1 = 0;
-                       goto casedot;
-               }
-               break;
-
-       case '"':
-               strcpy(symb, "\"<string>\"");
-               cp = alloc(0);
-               c1 = 0;
-
-               /* "..." */
-               for(;;) {
-                       c = escchar('"', 0, 1);
-                       if(c == EOF)
-                               break;
-                       if(c & ESC) {
-                               cp = allocn(cp, c1, 1);
-                               cp[c1++] = c;
-                       } else {
-                               rune = c;
-                               c = runelen(rune);
-                               cp = allocn(cp, c1, c);
-                               runetochar(cp+c1, &rune);
-                               c1 += c;
-                       }
-               }
-               yylval.sval.l = c1;
-               do {
-                       cp = allocn(cp, c1, 1);
-                       cp[c1++] = 0;
-               } while(c1 & MAXALIGN);
-               yylval.sval.s = cp;
-               return LSTRING;
-
-       caselq:
-               /* L"..." */
-               strcpy(symb, "\"L<string>\"");
-               cp = alloc(0);
-               c1 = 0;
-               for(;;) {
-                       c = escchar('"', 1, 0);
-                       if(c == EOF)
-                               break;
-                       cp = allocn(cp, c1, sizeof(TRune));
-                       *(TRune*)(cp + c1) = c;
-                       c1 += sizeof(TRune);
-               }
-               yylval.sval.l = c1;
-               do {
-                       cp = allocn(cp, c1, sizeof(TRune));
-                       *(TRune*)(cp + c1) = 0;
-                       c1 += sizeof(TRune);
-               } while(c1 & MAXALIGN);
-               yylval.sval.s = cp;
-               return LLSTRING;
-
-       case '\'':
-               /* '.' */
-               c = escchar('\'', 0, 0);
-               if(c == EOF)
-                       c = '\'';
-               c1 = escchar('\'', 0, 0);
-               if(c1 != EOF) {
-                       yyerror("missing '");
-                       peekc = c1;
-               }
-               vv = c;
-               yylval.vval = convvtox(vv, TUCHAR);
-               if(yylval.vval != vv)
-                       yyerror("overflow in character constant: 0x%x", c);
-               else
-               if(c & 0x80){
-                       nearln = lineno;
-                       warn(Z, "sign-extended character constant");
-               }
-               yylval.vval = convvtox(vv, TCHAR);
-               return LCONST;
-
-       case '/':
-               c1 = GETC();
-               if(c1 == '*') {
-                       for(;;) {
-                               c = getr();
-                               while(c == '*') {
-                                       c = getr();
-                                       if(c == '/')
-                                               goto l0;
-                               }
-                               if(c == EOF) {
-                                       yyerror("eof in comment");
-                                       errorexit();
-                               }
-                       }
-               }
-               if(c1 == '/') {
-                       for(;;) {
-                               c = getr();
-                               if(c == '\n')
-                                       goto l0;
-                               if(c == EOF) {
-                                       yyerror("eof in comment");
-                                       errorexit();
-                               }
-                       }
-               }
-               if(c1 == '=')
-                       return LDVE;
-               break;
-
-       case '*':
-               c1 = GETC();
-               if(c1 == '=')
-                       return LMLE;
-               break;
-
-       case '%':
-               c1 = GETC();
-               if(c1 == '=')
-                       return LMDE;
-               break;
-
-       case '+':
-               c1 = GETC();
-               if(c1 == '+')
-                       return LPP;
-               if(c1 == '=')
-                       return LPE;
-               break;
-
-       case '-':
-               c1 = GETC();
-               if(c1 == '-')
-                       return LMM;
-               if(c1 == '=')
-                       return LME;
-               if(c1 == '>')
-                       return LMG;
-               break;
-
-       case '>':
-               c1 = GETC();
-               if(c1 == '>') {
-                       c = LRSH;
-                       c1 = GETC();
-                       if(c1 == '=')
-                               return LRSHE;
-                       break;
-               }
-               if(c1 == '=')
-                       return LGE;
-               break;
-
-       case '<':
-               c1 = GETC();
-               if(c1 == '<') {
-                       c = LLSH;
-                       c1 = GETC();
-                       if(c1 == '=')
-                               return LLSHE;
-                       break;
-               }
-               if(c1 == '=')
-                       return LLE;
-               break;
-
-       case '=':
-               c1 = GETC();
-               if(c1 == '=')
-                       return LEQ;
-               break;
-
-       case '!':
-               c1 = GETC();
-               if(c1 == '=')
-                       return LNE;
-               break;
-
-       case '&':
-               c1 = GETC();
-               if(c1 == '&')
-                       return LANDAND;
-               if(c1 == '=')
-                       return LANDE;
-               break;
-
-       case '|':
-               c1 = GETC();
-               if(c1 == '|')
-                       return LOROR;
-               if(c1 == '=')
-                       return LORE;
-               break;
-
-       case '^':
-               c1 = GETC();
-               if(c1 == '=')
-                       return LXORE;
-               break;
-
-       default:
-               return c;
-       }
-       peekc = c1;
-       return c;
-
-talph:
-       /*
-        * cp is set to symb and some
-        * prefix has been stored
-        */
-       for(;;) {
-               if(c >= Runeself) {
-                       for(c1=0;;) {
-                               cp[c1++] = c;
-                               if(fullrune(cp, c1))
-                                       break;
-                               c = GETC();
-                       }
-                       cp += c1;
-                       c = GETC();
-                       continue;
-               }
-               if(!isalnum(c) && c != '_')
-                       break;
-               *cp++ = c;
-               c = GETC();
-       }
-       *cp = 0;
-       if(debug['L'])
-               print("%L: %s\n", lineno, symb);
-       peekc = c;
-       s = lookup();
-       if(s->macro) {
-               newio();
-               cp = ionext->b;
-               macexpand(s, cp);
-               pushio();
-               ionext->link = iostack;
-               iostack = ionext;
-               fi.p = cp;
-               fi.c = strlen(cp);
-               if(peekc != IGN) {
-                       cp[fi.c++] = peekc;
-                       cp[fi.c] = 0;
-                       peekc = IGN;
-               }
-               goto l0;
-       }
-       yylval.sym = s;
-       if(s->class == CTYPEDEF || s->class == CTYPESTR)
-               return LTYPE;
-       return s->lexical;
-
-tnum:
-       c1 = 0;
-       cp = symb;
-       if(c != '0') {
-               c1 |= Numdec;
-               for(;;) {
-                       *cp++ = c;
-                       c = GETC();
-                       if(isdigit(c))
-                               continue;
-                       goto dc;
-               }
-       }
-       *cp++ = c;
-       c = GETC();
-       if(c == 'x' || c == 'X')
-               for(;;) {
-                       *cp++ = c;
-                       c = GETC();
-                       if(isdigit(c))
-                               continue;
-                       if(c >= 'a' && c <= 'f')
-                               continue;
-                       if(c >= 'A' && c <= 'F')
-                               continue;
-                       if(cp == symb+2)
-                               yyerror("malformed hex constant");
-                       goto ncu;
-               }
-       if(c < '0' || c > '7')
-               goto dc;
-       for(;;) {
-               if(c >= '0' && c <= '7') {
-                       *cp++ = c;
-                       c = GETC();
-                       continue;
-               }
-               goto ncu;
-       }
-
-dc:
-       if(c == '.')
-               goto casedot;
-       if(c == 'e' || c == 'E')
-               goto casee;
-
-ncu:
-       if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
-               c = GETC();
-               c1 |= Numuns;
-               goto ncu;
-       }
-       if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
-               c = GETC();
-               if(c1 & Numlong)
-                       c1 |= Numvlong;
-               c1 |= Numlong;
-               goto ncu;
-       }
-       *cp = 0;
-       peekc = c;
-       if(mpatov(symb, &yylval.vval))
-               yyerror("overflow in constant");
-
-       vv = yylval.vval;
-       if(c1 & Numvlong) {
-               if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
-                       c = LUVLCONST;
-                       t = TUVLONG;
-                       goto nret;
-               }
-               c = LVLCONST;
-               t = TVLONG;
-               goto nret;
-       }
-       if(c1 & Numlong) {
-               if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
-                       c = LULCONST;
-                       t = TULONG;
-                       goto nret;
-               }
-               c = LLCONST;
-               t = TLONG;
-               goto nret;
-       }
-       if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
-               c = LUCONST;
-               t = TUINT;
-               goto nret;
-       }
-       c = LCONST;
-       t = TINT;
-       goto nret;
-
-nret:
-       yylval.vval = convvtox(vv, t);
-       if(yylval.vval != vv){
-               nearln = lineno;
-               warn(Z, "truncated constant: %T %s", types[t], symb);
-       }
-       return c;
-
-casedot:
-       for(;;) {
-               *cp++ = c;
-               c = GETC();
-               if(!isdigit(c))
-                       break;
-       }
-       if(c != 'e' && c != 'E')
-               goto caseout;
-
-casee:
-       *cp++ = 'e';
-       c = GETC();
-       if(c == '+' || c == '-') {
-               *cp++ = c;
-               c = GETC();
-       }
-       if(!isdigit(c))
-               yyerror("malformed fp constant exponent");
-       while(isdigit(c)) {
-               *cp++ = c;
-               c = GETC();
-       }
-
-caseout:
-       if(c == 'L' || c == 'l') {
-               c = GETC();
-               c1 |= Numlong;
-       } else
-       if(c == 'F' || c == 'f') {
-               c = GETC();
-               c1 |= Numflt;
-       }
-       *cp = 0;
-       peekc = c;
-       yylval.dval = strtod(symb, nil);
-       if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
-               yyerror("overflow in float constant");
-               yylval.dval = 0;
-       }
-       if(c1 & Numflt)
-               return LFCONST;
-       return LDCONST;
-}
-
-/*
- * convert a string, s, to vlong in *v
- * return conversion overflow.
- * required syntax is [0[x]]d*
- */
-int
-mpatov(char *s, vlong *v)
-{
-       vlong n, nn;
-       int c;
-
-       n = 0;
-       c = *s;
-       if(c == '0')
-               goto oct;
-       while(c = *s++) {
-               if(c >= '0' && c <= '9')
-                       nn = n*10 + c-'0';
-               else
-                       goto bad;
-               if(n < 0 && nn >= 0)
-                       goto bad;
-               n = nn;
-       }
-       goto out;
-
-oct:
-       s++;
-       c = *s;
-       if(c == 'x' || c == 'X')
-               goto hex;
-       while(c = *s++) {
-               if(c >= '0' || c <= '7')
-                       nn = n*8 + c-'0';
-               else
-                       goto bad;
-               if(n < 0 && nn >= 0)
-                       goto bad;
-               n = nn;
-       }
-       goto out;
-
-hex:
-       s++;
-       while(c = *s++) {
-               if(c >= '0' && c <= '9')
-                       c += 0-'0';
-               else
-               if(c >= 'a' && c <= 'f')
-                       c += 10-'a';
-               else
-               if(c >= 'A' && c <= 'F')
-                       c += 10-'A';
-               else
-                       goto bad;
-               nn = (uvlong)n*16 + c;
-               if(n < 0 && nn >= 0)
-                       goto bad;
-               n = nn;
-       }
-out:
-       *v = n;
-       return 0;
-
-bad:
-       *v = ~0;
-       return 1;
-}
-
-int
-getc(void)
-{
-       int c;
-
-       if(peekc != IGN) {
-               c = peekc;
-               peekc = IGN;
-       } else
-               c = GETC();
-       if(c == '\n')
-               lineno++;
-       if(c == EOF) {
-               yyerror("End of file");
-               errorexit();
-       }
-       return c;
-}
-
-int32
-getr(void)
-{
-       int c, i;
-       char str[UTFmax+1];
-       Rune rune;
-
-
-       c = getc();
-       if(c < Runeself)
-               return c;
-       i = 0;
-       str[i++] = c;
-
-loop:
-       c = getc();
-       str[i++] = c;
-       if(!fullrune(str, i))
-               goto loop;
-       c = chartorune(&rune, str);
-       if(rune == Runeerror && c == 1) {
-               nearln = lineno;
-               diag(Z, "illegal rune in string");
-               for(c=0; c<i; c++)
-                       print(" %.2x", *(uchar*)(str+c));
-               print("\n");
-       }
-       return rune;
-}
-
-int
-getnsc(void)
-{
-       int c;
-
-       if(peekc != IGN) {
-               c = peekc;
-               peekc = IGN;
-       } else
-               c = GETC();
-       for(;;) {
-               if(c >= Runeself || !isspace(c))
-                       return c;
-               if(c == '\n') {
-                       lineno++;
-                       return c;
-               }
-               c = GETC();
-       }
-}
-
-void
-unget(int c)
-{
-
-       peekc = c;
-       if(c == '\n')
-               lineno--;
-}
-
-int32
-escchar(int32 e, int longflg, int escflg)
-{
-       int32 c, l;
-       int i;
-
-loop:
-       c = getr();
-       if(c == '\n') {
-               yyerror("newline in string");
-               return EOF;
-       }
-       if(c != '\\') {
-               if(c == e)
-                       c = EOF;
-               return c;
-       }
-       c = getr();
-       if(c == 'x') {
-               /*
-                * note this is not ansi,
-                * supposed to only accept 2 hex
-                */
-               i = 2;
-               if(longflg)
-                       i = 6;
-               l = 0;
-               for(; i>0; i--) {
-                       c = getc();
-                       if(c >= '0' && c <= '9') {
-                               l = l*16 + c-'0';
-                               continue;
-                       }
-                       if(c >= 'a' && c <= 'f') {
-                               l = l*16 + c-'a' + 10;
-                               continue;
-                       }
-                       if(c >= 'A' && c <= 'F') {
-                               l = l*16 + c-'A' + 10;
-                               continue;
-                       }
-                       unget(c);
-                       break;
-               }
-               if(escflg)
-                       l |= ESC;
-               return l;
-       }
-       if(c >= '0' && c <= '7') {
-               /*
-                * note this is not ansi,
-                * supposed to only accept 3 oct
-                */
-               i = 2;
-               if(longflg)
-                       i = 8;
-               l = c - '0';
-               for(; i>0; i--) {
-                       c = getc();
-                       if(c >= '0' && c <= '7') {
-                               l = l*8 + c-'0';
-                               continue;
-                       }
-                       unget(c);
-               }
-               if(escflg)
-                       l |= ESC;
-               return l;
-       }
-       switch(c)
-       {
-       case '\n':      goto loop;
-       case 'n':       return '\n';
-       case 't':       return '\t';
-       case 'b':       return '\b';
-       case 'r':       return '\r';
-       case 'f':       return '\f';
-       case 'a':       return '\a';
-       case 'v':       return '\v';
-       }
-       return c;
-}
-
-struct
-{
-       char    *name;
-       ushort  lexical;
-       ushort  type;
-} itab[] =
-{
-       "auto",         LAUTO,          0,
-       "break",        LBREAK,         0,
-       "case",         LCASE,          0,
-       "char",         LCHAR,          TCHAR,
-       "const",        LCONSTNT,       0,
-       "continue",     LCONTINUE,      0,
-       "default",      LDEFAULT,       0,
-       "do",           LDO,            0,
-       "double",       LDOUBLE,        TDOUBLE,
-       "else",         LELSE,          0,
-       "enum",         LENUM,          0,
-       "extern",       LEXTERN,        0,
-       "float",        LFLOAT,         TFLOAT,
-       "for",          LFOR,           0,
-       "goto",         LGOTO,          0,
-       "if",           LIF,            0,
-       "inline",       LINLINE,        0,
-       "int",          LINT,           TINT,
-       "long",         LLONG,          TLONG,
-       "PREFETCH",     LPREFETCH,      0,
-       "register",     LREGISTER,      0,
-       "restrict",     LRESTRICT,      0,
-       "return",       LRETURN,        0,
-       "SET",          LSET,           0,
-       "short",        LSHORT,         TSHORT,
-       "signed",       LSIGNED,        0,
-       "signof",       LSIGNOF,        0,
-       "sizeof",       LSIZEOF,        0,
-       "static",       LSTATIC,        0,
-       "struct",       LSTRUCT,        0,
-       "switch",       LSWITCH,        0,
-       "typedef",      LTYPEDEF,       0,
-       "typestr",      LTYPESTR,       0,
-       "union",        LUNION,         0,
-       "unsigned",     LUNSIGNED,      0,
-       "USED",         LUSED,          0,
-       "void",         LVOID,          TVOID,
-       "volatile",     LVOLATILE,      0,
-       "while",        LWHILE,         0,
-       0
-};
-
-void
-cinit(void)
-{
-       Sym *s;
-       int i;
-       Type *t;
-
-       nerrors = 0;
-       lineno = 1;
-       iostack = I;
-       iofree = I;
-       peekc = IGN;
-       nhunk = 0;
-
-       types[TXXX] = T;
-       types[TCHAR] = typ(TCHAR, T);
-       types[TUCHAR] = typ(TUCHAR, T);
-       types[TSHORT] = typ(TSHORT, T);
-       types[TUSHORT] = typ(TUSHORT, T);
-       types[TINT] = typ(TINT, T);
-       types[TUINT] = typ(TUINT, T);
-       types[TLONG] = typ(TLONG, T);
-       types[TULONG] = typ(TULONG, T);
-       types[TVLONG] = typ(TVLONG, T);
-       types[TUVLONG] = typ(TUVLONG, T);
-       types[TFLOAT] = typ(TFLOAT, T);
-       types[TDOUBLE] = typ(TDOUBLE, T);
-       types[TVOID] = typ(TVOID, T);
-       types[TENUM] = typ(TENUM, T);
-       types[TFUNC] = typ(TFUNC, types[TINT]);
-       types[TIND] = typ(TIND, types[TVOID]);
-
-       for(i=0; i<NHASH; i++)
-               hash[i] = S;
-       for(i=0; itab[i].name; i++) {
-               s = slookup(itab[i].name);
-               s->lexical = itab[i].lexical;
-               if(itab[i].type != 0)
-                       s->type = types[itab[i].type];
-       }
-       blockno = 0;
-       autobn = 0;
-       autoffset = 0;
-
-       t = typ(TARRAY, types[TCHAR]);
-       t->width = 0;
-       symstring = slookup(".string");
-       symstring->class = CSTATIC;
-       symstring->dataflag = NOPTR;
-       symstring->type = t;
-
-       t = typ(TARRAY, types[TCHAR]);
-       t->width = 0;
-
-       nodproto = new(OPROTO, Z, Z);
-       dclstack = D;
-
-       fmtinstall('O', Oconv);
-       fmtinstall('T', Tconv);
-       fmtinstall('F', FNconv);
-       fmtinstall('L', Lconv);
-       fmtinstall('Q', Qconv);
-       fmtinstall('|', VBconv);
-       fmtinstall('U', Uconv);
-       fmtinstall('B', Bconv);
-}
-
-int
-filbuf(void)
-{
-       Io *i;
-
-loop:
-       i = iostack;
-       if(i == I)
-               return EOF;
-       if(i->f < 0)
-               goto pop;
-       fi.c = read(i->f, i->b, BUFSIZ) - 1;
-       if(fi.c < 0) {
-               close(i->f);
-               linklinehist(ctxt, lineno, nil, 0);
-               goto pop;
-       }
-       fi.p = i->b + 1;
-       return i->b[0] & 0xff;
-
-pop:
-       iostack = i->link;
-       i->link = iofree;
-       iofree = i;
-       i = iostack;
-       if(i == I)
-               return EOF;
-       fi.p = i->p;
-       fi.c = i->c;
-       if(--fi.c < 0)
-               goto loop;
-       return *fi.p++ & 0xff;
-}
-
-int
-Oconv(Fmt *fp)
-{
-       int a;
-
-       a = va_arg(fp->args, int);
-       if(a < OXXX || a > OEND)
-               return fmtprint(fp, "***badO %d***", a);
-
-       return fmtstrcpy(fp, onames[a]);
-}
-
-int
-Lconv(Fmt *fp)
-{
-       return linklinefmt(ctxt, fp);
-}
-
-int
-Tconv(Fmt *fp)
-{
-       char str[STRINGSZ+20], s[STRINGSZ+20];
-       Type *t, *t1;
-       int et;
-       int32 n;
-
-       str[0] = 0;
-       for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
-               et = t->etype;
-               if(str[0])
-                       strcat(str, " ");
-               if(t->garb&~GINCOMPLETE) {
-                       sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
-                       if(strlen(str) + strlen(s) < STRINGSZ)
-                               strcat(str, s);
-               }
-               sprint(s, "%s", tnames[et]);
-               if(strlen(str) + strlen(s) < STRINGSZ)
-                       strcat(str, s);
-               if(et == TFUNC && (t1 = t->down)) {
-                       sprint(s, "(%T", t1);
-                       if(strlen(str) + strlen(s) < STRINGSZ)
-                               strcat(str, s);
-                       while(t1 = t1->down) {
-                               sprint(s, ", %T", t1);
-                               if(strlen(str) + strlen(s) < STRINGSZ)
-                                       strcat(str, s);
-                       }
-                       if(strlen(str) + strlen(s) < STRINGSZ)
-                               strcat(str, ")");
-               }
-               if(et == TARRAY) {
-                       n = t->width;
-                       if(t->link && t->link->width)
-                               n /= t->link->width;
-                       sprint(s, "[%d]", n);
-                       if(strlen(str) + strlen(s) < STRINGSZ)
-                               strcat(str, s);
-               }
-               if(t->nbits) {
-                       sprint(s, " %d:%d", t->shift, t->nbits);
-                       if(strlen(str) + strlen(s) < STRINGSZ)
-                               strcat(str, s);
-               }
-               if(typesu[et]) {
-                       if(t->tag) {
-                               strcat(str, " ");
-                               if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
-                                       strcat(str, t->tag->name);
-                       } else
-                               strcat(str, " {}");
-                       break;
-               }
-       }
-       return fmtstrcpy(fp, str);
-}
-
-int
-FNconv(Fmt *fp)
-{
-       char *str;
-       Node *n;
-
-       n = va_arg(fp->args, Node*);
-       str = "<indirect>";
-       if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
-               str = n->sym->name;
-       return fmtstrcpy(fp, str);
-}
-
-int
-Qconv(Fmt *fp)
-{
-       char str[STRINGSZ+20], *s;
-       int32 b;
-       int i;
-
-       str[0] = 0;
-       for(b = va_arg(fp->args, int32); b;) {
-               i = bitno(b);
-               if(str[0])
-                       strcat(str, " ");
-               s = qnames[i];
-               if(strlen(str) + strlen(s) >= STRINGSZ)
-                       break;
-               strcat(str, s);
-               b &= ~(1L << i);
-       }
-       return fmtstrcpy(fp, str);
-}
-
-int
-VBconv(Fmt *fp)
-{
-       char str[STRINGSZ];
-       int i, n, t, pc;
-
-       n = va_arg(fp->args, int);
-       pc = 0; /* BUG: was printcol */
-       i = 0;
-       while(pc < n) {
-               t = (pc+4) & ~3;
-               if(t <= n) {
-                       str[i++] = '\t';
-                       pc = t;
-                       continue;
-               }
-               str[i++] = ' ';
-               pc++;
-       }
-       str[i] = 0;
-
-       return fmtstrcpy(fp, str);
-}
-
-int
-Bconv(Fmt *fp)
-{
-       char str[STRINGSZ], ss[STRINGSZ], *s;
-       Bits bits;
-       int i;
-
-       str[0] = 0;
-       bits = va_arg(fp->args, Bits);
-       while(bany(&bits)) {
-               i = bnum(bits);
-               if(str[0])
-                       strcat(str, " ");
-               if(var[i].sym == nil) {
-                       sprint(ss, "$%lld", var[i].offset);
-                       s = ss;
-               } else
-                       s = var[i].sym->name;
-               if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
-                       break;
-               strcat(str, s);
-               bits.b[i/32] &= ~(1L << (i%32));
-       }
-       return fmtstrcpy(fp, str);
-}
-
-void
-setinclude(char *p)
-{
-       int i;
-
-       if(*p != 0) {
-               for(i=1; i < ninclude; i++)
-                       if(strcmp(p, include[i]) == 0)
-                               return;
-
-               if(ninclude%8 == 0)
-                       include = allocn(include, ninclude*sizeof(char *),
-                               8*sizeof(char *));
-               include[ninclude++] = p;
-       }
-}
-
-void*
-alloc(int32 n)
-{
-       void *p;
-
-       p = malloc(n);
-       if(p == nil) {
-               print("alloc out of mem\n");
-               exits("alloc: out of mem");
-       }
-       memset(p, 0, n);
-       return p;
-}
-
-void*
-allocn(void *p, int32 n, int32 d)
-{
-       if(p == nil)
-               return alloc(n+d);
-       p = realloc(p, n+d);
-       if(p == nil) {
-               print("allocn out of mem\n");
-               exits("allocn: out of mem");
-       }
-       if(d > 0)
-               memset((char*)p+n, 0, d);
-       return p;
-}
-
-void
-ensuresymb(int32 n)
-{
-       if(symb == nil) {
-               symb = alloc(NSYMB+1);
-               nsymb = NSYMB;
-       }
-
-       if(n > nsymb) {
-               symb = allocn(symb, nsymb, n+1-nsymb);
-               nsymb = n;
-       }
-}
index e24db1bc0b4c957ca053b1ee1dc95ca164161845..f586aaa20e670994081be7dfd388ba92b8f3aec5 100644 (file)
@@ -220,6 +220,31 @@ slookup(char *s)
        return lookup();
 }
 
+LSym *thetext;
+
+void
+settext(LSym *s)
+{
+       thetext = s;
+}
+
+Sym*
+labellookup(Sym *s)
+{
+       char *p;
+       Sym *lab;
+       
+       if(thetext == nil) {
+               s->labelname = s->name;
+               return s;
+       }
+       p = smprint("%s.%s", thetext->name, s->name);
+       lab = slookup(p);
+       free(p);
+       lab->labelname = s->name;
+       return lab;
+}
+
 Sym*
 lookup(void)
 {
diff --git a/src/cmd/cc/mac.c b/src/cmd/cc/mac.c
deleted file mode 100644 (file)
index b969662..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Inferno utils/cc/mac.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/mac.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "cc.h"
-
-#include       "macbody"
diff --git a/src/cmd/cc/omachcap.c b/src/cmd/cc/omachcap.c
deleted file mode 100644 (file)
index f8fc1d8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Inferno utils/cc/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/machcap.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "cc.h"
-
-/* default, like old cc */
-int
-machcap(Node *n)
-{
-       USED(n);
-       return 0;
-}
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
deleted file mode 100644 (file)
index db9aae9..0000000
+++ /dev/null
@@ -1,622 +0,0 @@
-// Inferno utils/6c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-int
-hasdotdotdot(Type *t)
-{
-       for(t=t->down; t!=T; t=t->down)
-               if(t->etype == TDOT)
-                       return 1;
-       return 0;
-}
-
-vlong
-argsize(int doret)
-{
-       Type *t;
-       int32 s;
-
-//print("t=%T\n", thisfn);
-       s = 0;
-       if(hasdotdotdot(thisfn))
-               s = align(s, thisfn->link, Aarg0, nil);
-       for(t=thisfn->down; t!=T; t=t->down) {
-               switch(t->etype) {
-               case TVOID:
-                       break;
-               case TDOT:
-                       if((textflag & NOSPLIT) == 0)
-                               yyerror("function takes ... without textflag NOSPLIT");
-                       return ArgsSizeUnknown;
-               default:
-                       s = align(s, t, Aarg1, nil);
-                       s = align(s, t, Aarg2, nil);
-                       break;
-               }
-//print("      %d %T\n", s, t);
-       }
-       if(thechar == '6')
-               s = (s+7) & ~7;
-       else
-               s = (s+3) & ~3;
-       if(doret && thisfn->link->etype != TVOID) {
-               s = align(s, thisfn->link, Aarg1, nil);
-               s = align(s, thisfn->link, Aarg2, nil);
-               if(thechar == '6')
-                       s = (s+7) & ~7;
-               else
-                       s = (s+3) & ~3;
-       }
-       return s;
-}
-
-void
-codgen(Node *n, Node *nn)
-{
-       Prog *sp;
-       Node *n1, nod, nod1;
-
-       cursafe = 0;
-       curarg = 0;
-       maxargsafe = 0;
-
-       /*
-        * isolate name
-        */
-       for(n1 = nn;; n1 = n1->left) {
-               if(n1 == Z) {
-                       diag(nn, "can't find function name");
-                       return;
-               }
-               if(n1->op == ONAME)
-                       break;
-       }
-       nearln = nn->lineno;
-
-       p = gtext(n1->sym, stkoff);
-       p->from.sym->cfunc = 1;
-       sp = p;
-
-       /*
-        * isolate first argument
-        */
-       if(REGARG >= 0) {
-               if(typesuv[thisfn->link->etype]) {
-                       nod1 = *nodret->left;
-                       nodreg(&nod, &nod1, REGARG);
-                       gmove(&nod, &nod1);
-               } else
-               if(firstarg && typechlp[firstargtype->etype]) {
-                       nod1 = *nodret->left;
-                       nod1.sym = firstarg;
-                       nod1.type = firstargtype;
-                       nod1.xoffset = align(0, firstargtype, Aarg1, nil);
-                       nod1.etype = firstargtype->etype;
-                       nodreg(&nod, &nod1, REGARG);
-                       gmove(&nod, &nod1);
-               }
-       }
-
-       canreach = 1;
-       warnreach = 1;
-       gen(n);
-       if(canreach && thisfn->link->etype != TVOID)
-               diag(Z, "no return at end of function: %s", n1->sym->name);
-       noretval(3);
-       gbranch(ORETURN);
-
-       if(!debug['N'] || debug['R'] || debug['P'])
-               regopt(sp);
-
-       if(thechar=='6' || thechar=='7')        /* [sic] */
-               maxargsafe = xround(maxargsafe, 8);
-       sp->to.offset += maxargsafe;
-}
-
-void
-supgen(Node *n)
-{
-       int owarn;
-       long spc;
-       Prog *sp;
-
-       if(n == Z)
-               return;
-       suppress++;
-       owarn = warnreach;
-       warnreach = 0;
-       spc = pc;
-       sp = lastp;
-       gen(n);
-       lastp = sp;
-       pc = spc;
-       sp->link = nil;
-       suppress--;
-       warnreach = owarn;
-}
-
-void
-gen(Node *n)
-{
-       Node *l, nod, nod1;
-       Prog *sp, *spc, *spb;
-       Case *cn;
-       long sbc, scc;
-       int snbreak, sncontin;
-       int f, o, oldreach;
-
-loop:
-       if(n == Z)
-               return;
-       nearln = n->lineno;
-       o = n->op;
-       if(debug['G'])
-               if(o != OLIST)
-                       print("%L %O\n", nearln, o);
-
-       if(!canreach) {
-               switch(o) {
-               case OLABEL:
-               case OCASE:
-               case OLIST:
-               case OBREAK:
-               case OFOR:
-               case OWHILE:
-               case ODWHILE:
-                       /* all handled specially - see switch body below */
-                       break;
-               default:
-                       if(warnreach) {
-                               warn(n, "unreachable code %O", o);
-                               warnreach = 0;
-                       }
-               }
-       }
-
-       switch(o) {
-
-       default:
-               complex(n);
-               cgen(n, Z);
-               break;
-
-       case OLIST:
-               gen(n->left);
-
-       rloop:
-               n = n->right;
-               goto loop;
-
-       case ORETURN:
-               canreach = 0;
-               warnreach = !suppress;
-               complex(n);
-               if(n->type == T)
-                       break;
-               l = n->left;
-               if(l == Z) {
-                       noretval(3);
-                       gbranch(ORETURN);
-                       break;
-               }
-               if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) {
-                       regret(&nod, n, thisfn, 2);
-                       sugen(l, &nod, n->type->width);
-                       noretval(3);
-                       gbranch(ORETURN);
-                       break;
-               }
-               if(typecmplx[n->type->etype]) {
-                       sugen(l, nodret, n->type->width);
-                       noretval(3);
-                       gbranch(ORETURN);
-                       break;
-               }
-               regret(&nod1, n, thisfn, 2);
-               nod = nod1;
-               if(nod.op != OREGISTER)
-                       regalloc(&nod, n, Z);
-               cgen(l, &nod);
-               if(nod1.op != OREGISTER)
-                       gmove(&nod, &nod1);
-               regfree(&nod);
-               if(typefd[n->type->etype])
-                       noretval(1);
-               else
-                       noretval(2);
-               gbranch(ORETURN);
-               break;
-
-       case OLABEL:
-               canreach = 1;
-               l = n->left;
-               if(l) {
-                       l->pc = pc;
-                       if(l->label)
-                               patch(l->label, pc);
-               }
-               gbranch(OGOTO); /* prevent self reference in reg */
-               patch(p, pc);
-               goto rloop;
-
-       case OGOTO:
-               canreach = 0;
-               warnreach = !suppress;
-               n = n->left;
-               if(n == Z)
-                       return;
-               if(n->complex == 0) {
-                       diag(Z, "label undefined: %s", n->sym->name);
-                       return;
-               }
-               if(suppress)
-                       return;
-               gbranch(OGOTO);
-               if(n->pc) {
-                       patch(p, n->pc);
-                       return;
-               }
-               if(n->label)
-                       patch(n->label, pc-1);
-               n->label = p;
-               return;
-
-       case OCASE:
-               canreach = 1;
-               l = n->left;
-               if(cases == C)
-                       diag(n, "case/default outside a switch");
-               if(l == Z) {
-                       newcase();
-                       cases->val = 0;
-                       cases->def = 1;
-                       cases->label = pc;
-                       cases->isv = 0;
-                       goto rloop;
-               }
-               complex(l);
-               if(l->type == T)
-                       goto rloop;
-               if(l->op == OCONST)
-               if(typeword[l->type->etype] && l->type->etype != TIND) {
-                       newcase();
-                       cases->val = l->vconst;
-                       cases->def = 0;
-                       cases->label = pc;
-                       cases->isv = typev[l->type->etype];
-                       goto rloop;
-               }
-               diag(n, "case expression must be integer constant");
-               goto rloop;
-
-       case OSWITCH:
-               l = n->left;
-               complex(l);
-               if(l->type == T)
-                       break;
-               if(!typechlvp[l->type->etype] || l->type->etype == TIND) {
-                       diag(n, "switch expression must be integer");
-                       break;
-               }
-
-               gbranch(OGOTO);         /* entry */
-               sp = p;
-
-               cn = cases;
-               cases = C;
-               newcase();
-
-               sbc = breakpc;
-               breakpc = pc;
-               snbreak = nbreak;
-               nbreak = 0;
-               gbranch(OGOTO);
-               spb = p;
-
-               gen(n->right);          /* body */
-               if(canreach){
-                       gbranch(OGOTO);
-                       patch(p, breakpc);
-                       nbreak++;
-               }
-
-               patch(sp, pc);
-               doswit(l);
-               patch(spb, pc);
-
-               cases = cn;
-               breakpc = sbc;
-               canreach = nbreak!=0;
-               if(canreach == 0)
-                       warnreach = !suppress;
-               nbreak = snbreak;
-               break;
-
-       case OWHILE:
-       case ODWHILE:
-               l = n->left;
-               gbranch(OGOTO);         /* entry */
-               sp = p;
-
-               scc = continpc;
-               continpc = pc;
-               gbranch(OGOTO);
-               spc = p;
-
-               sbc = breakpc;
-               breakpc = pc;
-               snbreak = nbreak;
-               nbreak = 0;
-               gbranch(OGOTO);
-               spb = p;
-
-               patch(spc, pc);
-               if(n->op == OWHILE)
-                       patch(sp, pc);
-               bcomplex(l, Z);         /* test */
-               patch(p, breakpc);
-               if(l->op != OCONST || vconst(l) == 0)
-                       nbreak++;
-
-               if(n->op == ODWHILE)
-                       patch(sp, pc);
-               gen(n->right);          /* body */
-               gbranch(OGOTO);
-               patch(p, continpc);
-
-               patch(spb, pc);
-               continpc = scc;
-               breakpc = sbc;
-               canreach = nbreak!=0;
-               if(canreach == 0)
-                       warnreach = !suppress;
-               nbreak = snbreak;
-               break;
-
-       case OFOR:
-               l = n->left;
-               if(!canreach && l->right->left && warnreach) {
-                       warn(n, "unreachable code FOR");
-                       warnreach = 0;
-               }
-               gen(l->right->left);    /* init */
-               gbranch(OGOTO);         /* entry */
-               sp = p;
-
-               /*
-                * if there are no incoming labels in the
-                * body and the top's not reachable, warn
-                */
-               if(!canreach && warnreach && deadheads(n)) {
-                       warn(n, "unreachable code %O", o);
-                       warnreach = 0;
-               }
-
-               scc = continpc;
-               continpc = pc;
-               gbranch(OGOTO);
-               spc = p;
-
-               sbc = breakpc;
-               breakpc = pc;
-               snbreak = nbreak;
-               nbreak = 0;
-               sncontin = ncontin;
-               ncontin = 0;
-               gbranch(OGOTO);
-               spb = p;
-
-               patch(spc, pc);
-               gen(l->right->right);   /* inc */
-               patch(sp, pc);
-               if(l->left != Z) {      /* test */
-                       bcomplex(l->left, Z);
-                       patch(p, breakpc);
-                       if(l->left->op != OCONST || vconst(l->left) == 0)
-                               nbreak++;
-               }
-               canreach = 1;
-               gen(n->right);          /* body */
-               if(canreach){
-                       gbranch(OGOTO);
-                       patch(p, continpc);
-                       ncontin++;
-               }
-               if(!ncontin && l->right->right && warnreach) {
-                       warn(l->right->right, "unreachable FOR inc");
-                       warnreach = 0;
-               }
-
-               patch(spb, pc);
-               continpc = scc;
-               breakpc = sbc;
-               canreach = nbreak!=0;
-               if(canreach == 0)
-                       warnreach = !suppress;
-               nbreak = snbreak;
-               ncontin = sncontin;
-               break;
-
-       case OCONTINUE:
-               if(continpc < 0) {
-                       diag(n, "continue not in a loop");
-                       break;
-               }
-               gbranch(OGOTO);
-               patch(p, continpc);
-               ncontin++;
-               canreach = 0;
-               warnreach = !suppress;
-               break;
-
-       case OBREAK:
-               if(breakpc < 0) {
-                       diag(n, "break not in a loop");
-                       break;
-               }
-               /*
-                * Don't complain about unreachable break statements.
-                * There are breaks hidden in yacc's output and some people
-                * write return; break; in their switch statements out of habit.
-                * However, don't confuse the analysis by inserting an
-                * unreachable reference to breakpc either.
-                */
-               if(!canreach)
-                       break;
-               gbranch(OGOTO);
-               patch(p, breakpc);
-               nbreak++;
-               canreach = 0;
-               warnreach = !suppress;
-               break;
-
-       case OIF:
-               l = n->left;
-               if(bcomplex(l, n->right)) {
-                       if(typefd[l->type->etype])
-                               f = !l->fconst;
-                       else
-                               f = !l->vconst;
-                       if(debug['c'])
-                               print("%L const if %s\n", nearln, f ? "false" : "true");
-                       if(f) {
-                               canreach = 1;
-                               supgen(n->right->left);
-                               oldreach = canreach;
-                               canreach = 1;
-                               gen(n->right->right);
-                               /*
-                                * treat constant ifs as regular ifs for
-                                * reachability warnings.
-                                */
-                               if(!canreach && oldreach && debug['w'] < 2)
-                                       warnreach = 0;
-                       }
-                       else {
-                               canreach = 1;
-                               gen(n->right->left);
-                               oldreach = canreach;
-                               canreach = 1;
-                               supgen(n->right->right);
-                               /*
-                                * treat constant ifs as regular ifs for
-                                * reachability warnings.
-                                */
-                               if(!oldreach && canreach && debug['w'] < 2)
-                                       warnreach = 0;
-                               canreach = oldreach;
-                       }
-               }
-               else {
-                       sp = p;
-                       canreach = 1;
-                       if(n->right->left != Z)
-                               gen(n->right->left);
-                       oldreach = canreach;
-                       canreach = 1;
-                       if(n->right->right != Z) {
-                               gbranch(OGOTO);
-                               patch(sp, pc);
-                               sp = p;
-                               gen(n->right->right);
-                       }
-                       patch(sp, pc);
-                       canreach = canreach || oldreach;
-                       if(canreach == 0)
-                               warnreach = !suppress;
-               }
-               break;
-
-       case OSET:
-       case OUSED:
-       case OPREFETCH:
-               usedset(n->left, o);
-               break;
-       }
-}
-
-void
-usedset(Node *n, int o)
-{
-       if(n->op == OLIST) {
-               usedset(n->left, o);
-               usedset(n->right, o);
-               return;
-       }
-       complex(n);
-       if(o == OPREFETCH) {
-               gprefetch(n);
-               return;
-       }
-       switch(n->op) {
-       case OADDR:     /* volatile */
-               gins(ANOP, n, Z);
-               break;
-       case ONAME:
-               if(o == OSET)
-                       gins(ANOP, Z, n);
-               else
-                       gins(ANOP, n, Z);
-               break;
-       }
-}
-
-int
-bcomplex(Node *n, Node *c)
-{
-       Node *b, nod;
-
-       complex(n);
-       if(n->type != T)
-       if(tcompat(n, T, n->type, tnot))
-               n->type = T;
-       if(n->type == T) {
-               gbranch(OGOTO);
-               return 0;
-       }
-       if(c != Z && n->op == OCONST && deadheads(c))
-               return 1;
-       if(typev[n->type->etype] && machcap(Z)) {
-               b = &nod;
-               b->op = ONE;
-               b->left = n;
-               b->right = new(0, Z, Z);
-               *b->right = *nodconst(0);
-               b->right->type = n->type;
-               b->type = types[TLONG];
-               n = b;
-       }
-       bool64(n);
-       boolgen(n, 1, Z);
-       return 0;
-}
diff --git a/src/cmd/cc/pswt.c b/src/cmd/cc/pswt.c
deleted file mode 100644 (file)
index bae57c6..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-// Inferno utils/6c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-swcmp(const void *a1, const void *a2)
-{
-       C1 *p1, *p2;
-
-       p1 = (C1*)a1;
-       p2 = (C1*)a2;
-       if(p1->val < p2->val)
-               return -1;
-       return p1->val > p2->val;
-}
-
-void
-doswit(Node *n)
-{
-       Case *c;
-       C1 *q, *iq;
-       int32 def, nc, i, isv;
-
-       def = 0;
-       nc = 0;
-       isv = 0;
-       for(c = cases; c->link != C; c = c->link) {
-               if(c->def) {
-                       if(def)
-                               diag(n, "more than one default in switch");
-                       def = c->label;
-                       continue;
-               }
-               isv |= c->isv;
-               nc++;
-       }
-       if(isv && !typev[n->type->etype])
-               warn(n, "32-bit switch expression with 64-bit case constant");
-
-       iq = alloc(nc*sizeof(C1));
-       q = iq;
-       for(c = cases; c->link != C; c = c->link) {
-               if(c->def)
-                       continue;
-               q->label = c->label;
-               if(isv)
-                       q->val = c->val;
-               else
-                       q->val = (int32)c->val; /* cast ensures correct value for 32-bit switch on 64-bit architecture */
-               q++;
-       }
-       qsort(iq, nc, sizeof(C1), swcmp);
-       if(debug['W'])
-       for(i=0; i<nc; i++)
-               print("case %2d: = %.8llux\n", i, (vlong)iq[i].val);
-       for(i=0; i<nc-1; i++)
-               if(iq[i].val == iq[i+1].val)
-                       diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
-       if(def == 0) {
-               def = breakpc;
-               nbreak++;
-       }
-       swit1(iq, nc, def, n);
-}
-
-void
-newcase(void)
-{
-       Case *c;
-
-       c = alloc(sizeof(*c));
-       c->link = cases;
-       cases = c;
-}
-
-int32
-outlstring(TRune *s, int32 n)
-{
-       char buf[sizeof(TRune)];
-       uint c;
-       int i;
-       int32 r;
-
-       if(suppress)
-               return nstring;
-       while(nstring & (sizeof(TRune)-1))
-               outstring("", 1);
-       r = nstring;
-       while(n > 0) {
-               c = *s++;
-               if(align(0, types[TCHAR], Aarg1, nil)) {
-                       for(i = 0; i < sizeof(TRune); i++)
-                               buf[i] = c>>(8*(sizeof(TRune) - i - 1));
-               } else {
-                       for(i = 0; i < sizeof(TRune); i++)
-                               buf[i] = c>>(8*i);
-               }
-               outstring(buf, sizeof(TRune));
-               n -= sizeof(TRune);
-       }
-       return r;
-}
-
-void
-nullwarn(Node *l, Node *r)
-{
-       warn(Z, "result of operation not used");
-       if(l != Z)
-               cgen(l, Z);
-       if(r != Z)
-               cgen(r, Z);
-}
diff --git a/src/cmd/cc/scon.c b/src/cmd/cc/scon.c
deleted file mode 100644 (file)
index b0b9097..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-// Inferno utils/cc/scon.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-static Node*
-acast(Type *t, Node *n)
-{
-       if(n->type->etype != t->etype || n->op == OBIT) {
-               n = new1(OCAST, n, Z);
-               if(nocast(n->left->type, t))
-                       *n = *n->left;
-               n->type = t;
-       }
-       return n;
-}
-
-
-void
-evconst(Node *n)
-{
-       Node *l, *r;
-       int et, isf;
-       vlong v;
-       double d;
-
-       if(n == Z || n->type == T)
-               return;
-
-       et = n->type->etype;
-       isf = typefd[et];
-
-       l = n->left;
-       r = n->right;
-
-       d = 0;
-       v = 0;
-
-       switch(n->op) {
-       default:
-               return;
-
-       case ONEG:
-               if(isf)
-                       d = -l->fconst;
-               else
-                       v = -l->vconst;
-               break;
-
-       case OCOM:
-               v = ~l->vconst;
-               break;
-
-       case OCAST:
-               if(et == TVOID)
-                       return;
-               et = l->type->etype;
-               if(isf) {
-                       if(typefd[et])
-                               d = l->fconst;
-                       else
-                               d = l->vconst;
-               } else {
-                       if(typefd[et])
-                               v = l->fconst;
-                       else
-                               v = convvtox(l->vconst, n->type->etype);
-               }
-               break;
-
-       case OCONST:
-               break;
-
-       case OADD:
-               if(isf)
-                       d = l->fconst + r->fconst;
-               else {
-                       v = l->vconst + r->vconst;
-               }
-               break;
-
-       case OSUB:
-               if(isf)
-                       d = l->fconst - r->fconst;
-               else
-                       v = l->vconst - r->vconst;
-               break;
-
-       case OMUL:
-               if(isf)
-                       d = l->fconst * r->fconst;
-               else {
-                       v = l->vconst * r->vconst;
-               }
-               break;
-
-       case OLMUL:
-               v = (uvlong)l->vconst * (uvlong)r->vconst;
-               break;
-
-
-       case ODIV:
-               if(vconst(r) == 0) {
-                       warn(n, "divide by zero");
-                       return;
-               }
-               if(isf)
-                       d = l->fconst / r->fconst;
-               else
-                       v = l->vconst / r->vconst;
-               break;
-
-       case OLDIV:
-               if(vconst(r) == 0) {
-                       warn(n, "divide by zero");
-                       return;
-               }
-               v = (uvlong)l->vconst / (uvlong)r->vconst;
-               break;
-
-       case OMOD:
-               if(vconst(r) == 0) {
-                       warn(n, "modulo by zero");
-                       return;
-               }
-               v = l->vconst % r->vconst;
-               break;
-
-       case OLMOD:
-               if(vconst(r) == 0) {
-                       warn(n, "modulo by zero");
-                       return;
-               }
-               v = (uvlong)l->vconst % (uvlong)r->vconst;
-               break;
-
-       case OAND:
-               v = l->vconst & r->vconst;
-               break;
-
-       case OOR:
-               v = l->vconst | r->vconst;
-               break;
-
-       case OXOR:
-               v = l->vconst ^ r->vconst;
-               break;
-
-       case OLSHR:
-               if(l->type->width != sizeof(uvlong))
-                       v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst;
-               else
-                       v = (uvlong)l->vconst >> r->vconst;
-               break;
-
-       case OASHR:
-               v = l->vconst >> r->vconst;
-               break;
-
-       case OASHL:
-               v = (uvlong)l->vconst << r->vconst;
-               break;
-
-       case OLO:
-               v = (uvlong)l->vconst < (uvlong)r->vconst;
-               break;
-
-       case OLT:
-               if(typefd[l->type->etype])
-                       v = l->fconst < r->fconst;
-               else
-                       v = l->vconst < r->vconst;
-               break;
-
-       case OHI:
-               v = (uvlong)l->vconst > (uvlong)r->vconst;
-               break;
-
-       case OGT:
-               if(typefd[l->type->etype])
-                       v = l->fconst > r->fconst;
-               else
-                       v = l->vconst > r->vconst;
-               break;
-
-       case OLS:
-               v = (uvlong)l->vconst <= (uvlong)r->vconst;
-               break;
-
-       case OLE:
-               if(typefd[l->type->etype])
-                       v = l->fconst <= r->fconst;
-               else
-                       v = l->vconst <= r->vconst;
-               break;
-
-       case OHS:
-               v = (uvlong)l->vconst >= (uvlong)r->vconst;
-               break;
-
-       case OGE:
-               if(typefd[l->type->etype])
-                       v = l->fconst >= r->fconst;
-               else
-                       v = l->vconst >= r->vconst;
-               break;
-
-       case OEQ:
-               if(typefd[l->type->etype])
-                       v = l->fconst == r->fconst;
-               else
-                       v = l->vconst == r->vconst;
-               break;
-
-       case ONE:
-               if(typefd[l->type->etype])
-                       v = l->fconst != r->fconst;
-               else
-                       v = l->vconst != r->vconst;
-               break;
-
-       case ONOT:
-               if(typefd[l->type->etype])
-                       v = !l->fconst;
-               else
-                       v = !l->vconst;
-               break;
-
-       case OANDAND:
-               if(typefd[l->type->etype])
-                       v = l->fconst && r->fconst;
-               else
-                       v = l->vconst && r->vconst;
-               break;
-
-       case OOROR:
-               if(typefd[l->type->etype])
-                       v = l->fconst || r->fconst;
-               else
-                       v = l->vconst || r->vconst;
-               break;
-       }
-       if(isf) {
-               n->fconst = d;
-       } else {
-               n->vconst = convvtox(v, n->type->etype);
-       }
-       n->oldop = n->op;
-       n->op = OCONST;
-}
-
-void
-acom(Node *n)
-{
-       Type *t;
-       Node *l, *r;
-       int i;
-
-       switch(n->op)
-       {
-
-       case ONAME:
-       case OCONST:
-       case OSTRING:
-       case OINDREG:
-       case OREGISTER:
-               return;
-
-       case ONEG:
-               l = n->left;
-               if(addo(n) && addo(l))
-                       break;
-               acom(l);
-               return;
-
-       case OADD:
-       case OSUB:
-       case OMUL:
-               l = n->left;
-               r = n->right;
-               if(addo(n)) {
-                       if(addo(r))
-                               break;
-                       if(addo(l))
-                               break;
-               }
-               acom(l);
-               acom(r);
-               return;
-
-       default:
-               l = n->left;
-               r = n->right;
-               if(l != Z)
-                       acom(l);
-               if(r != Z)
-                       acom(r);
-               return;
-       }
-
-       /* bust terms out */
-       t = n->type;
-       term[0].mult = 0;
-       term[0].node = Z;
-       nterm = 1;
-       acom1(1, n);
-       if(debug['m'])
-       for(i=0; i<nterm; i++) {
-               print("%d %3lld ", i, term[i].mult);
-               prtree1(term[i].node, 1, 0);
-       }
-       if(nterm < NTERM)
-               acom2(n, t);
-       n->type = t;
-}
-
-int
-acomcmp1(const void *a1, const void *a2)
-{
-       vlong c1, c2;
-       Term *t1, *t2;
-
-       t1 = (Term*)a1;
-       t2 = (Term*)a2;
-       c1 = t1->mult;
-       if(c1 < 0)
-               c1 = -c1;
-       c2 = t2->mult;
-       if(c2 < 0)
-               c2 = -c2;
-       if(c1 > c2)
-               return 1;
-       if(c1 < c2)
-               return -1;
-       c1 = 1;
-       if(t1->mult < 0)
-               c1 = 0;
-       c2 = 1;
-       if(t2->mult < 0)
-               c2 = 0;
-       if(c2 -= c1)
-               return c2;
-       if(t2 > t1)
-               return 1;
-       return -1;
-}
-
-int
-acomcmp2(const void *a1, const void *a2)
-{
-       vlong c1, c2;
-       Term *t1, *t2;
-
-       t1 = (Term*)a1;
-       t2 = (Term*)a2;
-       c1 = t1->mult;
-       c2 = t2->mult;
-       if(c1 > c2)
-               return 1;
-       if(c1 < c2)
-               return -1;
-       if(t2 > t1)
-               return 1;
-       return -1;
-}
-
-void
-acom2(Node *n, Type *t)
-{
-       Node *l, *r;
-       Term trm[NTERM];
-       int et, nt, i, j;
-       vlong c1, c2;
-
-       /*
-        * copy into automatic
-        */
-       c2 = 0;
-       nt = nterm;
-       for(i=0; i<nt; i++)
-               trm[i] = term[i];
-       /*
-        * recur on subtrees
-        */
-       j = 0;
-       for(i=1; i<nt; i++) {
-               c1 = trm[i].mult;
-               if(c1 == 0)
-                       continue;
-               l = trm[i].node;
-               if(l != Z) {
-                       j = 1;
-                       acom(l);
-               }
-       }
-       c1 = trm[0].mult;
-       if(j == 0) {
-               n->oldop = n->op;
-               n->op = OCONST;
-               n->vconst = c1;
-               return;
-       }
-       et = t->etype;
-
-       /*
-        * prepare constant term,
-        * combine it with an addressing term
-        */
-       if(c1 != 0) {
-               l = new1(OCONST, Z, Z);
-               l->type = t;
-               l->vconst = c1;
-               trm[0].mult = 1;
-               for(i=1; i<nt; i++) {
-                       if(trm[i].mult != 1)
-                               continue;
-                       r = trm[i].node;
-                       if(r->op != OADDR)
-                               continue;
-                       r->type = t;
-                       l = new1(OADD, r, l);
-                       l->type = t;
-                       trm[i].mult = 0;
-                       break;
-               }
-               trm[0].node = l;
-       }
-       /*
-        * look for factorable terms
-        * c1*i + c1*c2*j -> c1*(i + c2*j)
-        */
-       qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
-       for(i=nt-1; i>=0; i--) {
-               c1 = trm[i].mult;
-               if(c1 < 0)
-                       c1 = -c1;
-               if(c1 <= 1)
-                       continue;
-               for(j=i+1; j<nt; j++) {
-                       c2 = trm[j].mult;
-                       if(c2 < 0)
-                               c2 = -c2;
-                       if(c2 <= 1)
-                               continue;
-                       if(c2 % c1)
-                               continue;
-                       r = trm[j].node;
-                       if(r->type->etype != et)
-                               r = acast(t, r);
-                       c2 = trm[j].mult/trm[i].mult;
-                       if(c2 != 1 && c2 != -1) {
-                               r = new1(OMUL, r, new(OCONST, Z, Z));
-                               r->type = t;
-                               r->right->type = t;
-                               r->right->vconst = c2;
-                       }
-                       l = trm[i].node;
-                       if(l->type->etype != et)
-                               l = acast(t, l);
-                       r = new1(OADD, l, r);
-                       r->type = t;
-                       if(c2 == -1)
-                               r->op = OSUB;
-                       trm[i].node = r;
-                       trm[j].mult = 0;
-               }
-       }
-       if(debug['m']) {
-               print("\n");
-               for(i=0; i<nt; i++) {
-                       print("%d %3lld ", i, trm[i].mult);
-                       prtree1(trm[i].node, 1, 0);
-               }
-       }
-
-       /*
-        * put it all back together
-        */
-       qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
-       l = Z;
-       for(i=nt-1; i>=0; i--) {
-               c1 = trm[i].mult;
-               if(c1 == 0)
-                       continue;
-               r = trm[i].node;
-               if(r->type->etype != et || r->op == OBIT)
-                       r = acast(t, r);
-               if(c1 != 1 && c1 != -1) {
-                       r = new1(OMUL, r, new(OCONST, Z, Z));
-                       r->type = t;
-                       r->right->type = t;
-                       if(c1 < 0) {
-                               r->right->vconst = -c1;
-                               c1 = -1;
-                       } else {
-                               r->right->vconst = c1;
-                               c1 = 1;
-                       }
-               }
-               if(l == Z) {
-                       l = r;
-                       c2 = c1;
-                       continue;
-               }
-               if(c1 < 0)
-                       if(c2 < 0)
-                               l = new1(OADD, l, r);
-                       else
-                               l = new1(OSUB, l, r);
-               else
-                       if(c2 < 0) {
-                               l = new1(OSUB, r, l);
-                               c2 = 1;
-                       } else
-                               l = new1(OADD, l, r);
-               l->type = t;
-       }
-       if(c2 < 0) {
-               r = new1(OCONST, 0, 0);
-               r->vconst = 0;
-               r->type = t;
-               l = new1(OSUB, r, l);
-               l->type = t;
-       }
-       *n = *l;
-}
-
-void
-acom1(vlong v, Node *n)
-{
-       Node *l, *r;
-
-       if(v == 0 || nterm >= NTERM)
-               return;
-       if(!addo(n)) {
-               if(n->op == OCONST)
-               if(!typefd[n->type->etype]) {
-                       term[0].mult += v*n->vconst;
-                       return;
-               }
-               term[nterm].mult = v;
-               term[nterm].node = n;
-               nterm++;
-               return;
-       }
-       switch(n->op) {
-
-       case OCAST:
-               acom1(v, n->left);
-               break;
-
-       case ONEG:
-               acom1(-v, n->left);
-               break;
-
-       case OADD:
-               acom1(v, n->left);
-               acom1(v, n->right);
-               break;
-
-       case OSUB:
-               acom1(v, n->left);
-               acom1(-v, n->right);
-               break;
-
-       case OMUL:
-               l = n->left;
-               r = n->right;
-               if(l->op == OCONST)
-               if(!typefd[n->type->etype]) {
-                       acom1(v*l->vconst, r);
-                       break;
-               }
-               if(r->op == OCONST)
-               if(!typefd[n->type->etype]) {
-                       acom1(v*r->vconst, l);
-                       break;
-               }
-               break;
-
-       default:
-               diag(n, "not addo");
-       }
-}
-
-int
-addo(Node *n)
-{
-
-       if(n != Z)
-       if(!typefd[n->type->etype])
-       if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
-       switch(n->op) {
-
-       case OCAST:
-               if(nilcast(n->left->type, n->type))
-                       return 1;
-               break;
-
-       case ONEG:
-       case OADD:
-       case OSUB:
-               return 1;
-
-       case OMUL:
-               if(n->left->op == OCONST)
-                       return 1;
-               if(n->right->op == OCONST)
-                       return 1;
-       }
-       return 0;
-}
diff --git a/src/cmd/cc/sub.c b/src/cmd/cc/sub.c
deleted file mode 100644 (file)
index 94c11d0..0000000
+++ /dev/null
@@ -1,2068 +0,0 @@
-// Inferno utils/cc/sub.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/sub.c
-//
-//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
-//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
-//     Portions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//     Portions Copyright Â© 2004,2006 Bruce Ellis
-//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
-//     Revisions Copyright Â© 2000-2007 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include       <u.h>
-#include       "cc.h"
-
-Node*
-new(int t, Node *l, Node *r)
-{
-       Node *n;
-
-       n = alloc(sizeof(*n));
-       n->op = t;
-       n->left = l;
-       n->right = r;
-       if(l && t != OGOTO)
-               n->lineno = l->lineno;
-       else if(r)
-               n->lineno = r->lineno;
-       else
-               n->lineno = lineno;
-       newflag = 1;
-       return n;
-}
-
-Node*
-new1(int o, Node *l, Node *r)
-{
-       Node *n;
-
-       n = new(o, l, r);
-       n->lineno = nearln;
-       return n;
-}
-
-void
-prtree(Node *n, char *s)
-{
-
-       print(" == %s ==\n", s);
-       prtree1(n, 0, 0);
-       print("\n");
-}
-
-void
-prtree1(Node *n, int d, int f)
-{
-       int i;
-
-       if(f)
-       for(i=0; i<d; i++)
-               print("   ");
-       if(n == Z) {
-               print("Z\n");
-               return;
-       }
-       if(n->op == OLIST) {
-               prtree1(n->left, d, 0);
-               prtree1(n->right, d, 1);
-               return;
-       }
-       d++;
-       print("%O", n->op);
-       i = 3;
-       switch(n->op)
-       {
-       case ONAME:
-               print(" \"%F\"", n);
-               print(" %d", n->xoffset);
-               i = 0;
-               break;
-
-       case OINDREG:
-               print(" %d(R%d)", n->xoffset, n->reg);
-               i = 0;
-               break;
-
-       case OREGISTER:
-               if(n->xoffset)
-                       print(" %d+R%d", n->xoffset, n->reg);
-               else
-                       print(" R%d", n->reg);
-               i = 0;
-               break;
-
-       case OSTRING:
-               print(" \"%s\"", n->cstring);
-               i = 0;
-               break;
-
-       case OLSTRING:
-               if(sizeof(TRune) == sizeof(Rune))
-                       print(" \"%S\"", (Rune*)n->rstring);
-               else
-                       print(" \"...\"");
-               i = 0;
-               break;
-
-       case ODOT:
-       case OELEM:
-               print(" \"%F\"", n);
-               break;
-
-       case OCONST:
-               if(typefd[n->type->etype])
-                       print(" \"%.8e\"", n->fconst);
-               else
-                       print(" \"%lld\"", n->vconst);
-               i = 0;
-               break;
-       }
-       if(n->addable != 0)
-               print(" <%d>", n->addable);
-       if(n->type != T)
-               print(" %T", n->type);
-       if(n->complex != 0)
-               print(" (%d)", n->complex);
-       print(" %L\n", n->lineno);
-       if(i & 2)
-               prtree1(n->left, d, 1);
-       if(i & 1)
-               prtree1(n->right, d, 1);
-}
-
-Type*
-typ(int et, Type *d)
-{
-       Type *t;
-
-       t = alloc(sizeof(*t));
-       t->etype = et;
-       t->link = d;
-       t->down = T;
-       t->sym = S;
-       if(et < NTYPE)
-               t->width = ewidth[et];
-       else
-               t->width = -1; // for TDOT or TOLD in prototype
-       t->offset = 0;
-       t->shift = 0;
-       t->nbits = 0;
-       t->garb = 0;
-       return t;
-}
-
-Type*
-copytyp(Type *t)
-{
-       Type *nt;
-
-       nt = typ(TXXX, T);
-       *nt = *t;
-       return nt;
-}
-
-Type*
-garbt(Type *t, int32 b)
-{
-       Type *t1;
-
-       if(b & BGARB) {
-               t1 = copytyp(t);
-               t1->garb = simpleg(b);
-               return t1;
-       }
-       return t;
-}
-
-int
-simpleg(int32 b)
-{
-
-       b &= BGARB;
-       switch(b) {
-       case BCONSTNT:
-               return GCONSTNT;
-       case BVOLATILE:
-               return GVOLATILE;
-       case BVOLATILE|BCONSTNT:
-               return GCONSTNT|GVOLATILE;
-       }
-       return GXXX;
-}
-
-int
-simplec(int32 b)
-{
-
-       b &= BCLASS;
-       switch(b) {
-       case 0:
-       case BREGISTER:
-               return CXXX;
-       case BAUTO:
-       case BAUTO|BREGISTER:
-               return CAUTO;
-       case BEXTERN:
-               return CEXTERN;
-       case BEXTERN|BREGISTER:
-               return CEXREG;
-       case BSTATIC:
-               return CSTATIC;
-       case BTYPEDEF:
-               return CTYPEDEF;
-       case BTYPESTR:
-               return CTYPESTR;
-       }
-       diag(Z, "illegal combination of classes %Q", b);
-       return CXXX;
-}
-
-Type*
-simplet(int32 b)
-{
-
-       b &= ~BCLASS & ~BGARB;
-       switch(b) {
-       case BCHAR:
-       case BCHAR|BSIGNED:
-               return types[TCHAR];
-
-       case BCHAR|BUNSIGNED:
-               return types[TUCHAR];
-
-       case BSHORT:
-       case BSHORT|BINT:
-       case BSHORT|BSIGNED:
-       case BSHORT|BINT|BSIGNED:
-               return types[TSHORT];
-
-       case BUNSIGNED|BSHORT:
-       case BUNSIGNED|BSHORT|BINT:
-               return types[TUSHORT];
-
-       case 0:
-       case BINT:
-       case BINT|BSIGNED:
-       case BSIGNED:
-               return types[TINT];
-
-       case BUNSIGNED:
-       case BUNSIGNED|BINT:
-               return types[TUINT];
-
-       case BLONG:
-       case BLONG|BINT:
-       case BLONG|BSIGNED:
-       case BLONG|BINT|BSIGNED:
-               return types[TLONG];
-
-       case BUNSIGNED|BLONG:
-       case BUNSIGNED|BLONG|BINT:
-               return types[TULONG];
-
-       case BVLONG|BLONG:
-       case BVLONG|BLONG|BINT:
-       case BVLONG|BLONG|BSIGNED:
-       case BVLONG|BLONG|BINT|BSIGNED:
-               return types[TVLONG];
-
-       case BVLONG|BLONG|BUNSIGNED:
-       case BVLONG|BLONG|BINT|BUNSIGNED:
-               return types[TUVLONG];
-
-       case BFLOAT:
-               return types[TFLOAT];
-
-       case BDOUBLE:
-       case BDOUBLE|BLONG:
-       case BFLOAT|BLONG:
-               return types[TDOUBLE];
-
-       case BVOID:
-               return types[TVOID];
-       }
-
-       diag(Z, "illegal combination of types %Q", b);
-       return types[TINT];
-}
-
-int
-stcompat(Node *n, Type *t1, Type *t2, int32 ttab[])
-{
-       int i;
-       uint32 b;
-
-       i = 0;
-       if(t2 != T)
-               i = t2->etype;
-       b = 1L << i;
-       i = 0;
-       if(t1 != T)
-               i = t1->etype;
-       if(b & ttab[i]) {
-               if(ttab == tasign)
-                       if(b == BSTRUCT || b == BUNION)
-                               if(!sametype(t1, t2))
-                                       return 1;
-               if(n->op != OCAST)
-                       if(b == BIND && i == TIND)
-                               if(!sametype(t1, t2))
-                                       return 1;
-               return 0;
-       }
-       return 1;
-}
-
-int
-tcompat(Node *n, Type *t1, Type *t2, int32 ttab[])
-{
-
-       if(stcompat(n, t1, t2, ttab)) {
-               if(t1 == T)
-                       diag(n, "incompatible type: \"%T\" for op \"%O\"",
-                               t2, n->op);
-               else
-                       diag(n, "incompatible types: \"%T\" and \"%T\" for op \"%O\"",
-                               t1, t2, n->op);
-               return 1;
-       }
-       return 0;
-}
-
-void
-makedot(Node *n, Type *t, int32 o)
-{
-       Node *n1, *n2;
-
-       if(t->nbits) {
-               n1 = new(OXXX, Z, Z);
-               *n1 = *n;
-               n->op = OBIT;
-               n->left = n1;
-               n->right = Z;
-               n->type = t;
-               n->addable = n1->left->addable;
-               n = n1;
-       }
-       n->addable = n->left->addable;
-       if(n->addable == 0) {
-               n1 = new1(OCONST, Z, Z);
-               n1->vconst = o;
-               n1->type = types[TLONG];
-               n->right = n1;
-               n->type = t;
-               return;
-       }
-       n->left->type = t;
-       if(o == 0) {
-               *n = *n->left;
-               return;
-       }
-       n->type = t;
-       n1 = new1(OCONST, Z, Z);
-       n1->vconst = o;
-       t = typ(TIND, t);
-       t->width = types[TIND]->width;
-       n1->type = t;
-
-       n2 = new1(OADDR, n->left, Z);
-       n2->type = t;
-
-       n1 = new1(OADD, n1, n2);
-       n1->type = t;
-
-       n->op = OIND;
-       n->left = n1;
-       n->right = Z;
-}
-
-Type*
-dotsearch(Sym *s, Type *t, Node *n, int32 *off)
-{
-       Type *t1, *xt, *rt;
-
-       xt = T;
-
-       /*
-        * look it up by name
-        */
-       for(t1 = t; t1 != T; t1 = t1->down)
-               if(t1->sym == s) {
-                       if(xt != T)
-                               goto ambig;
-                       xt = t1;
-               }
-
-       /*
-        * look it up by type
-        */
-       if(s->class == CTYPEDEF || s->class == CTYPESTR)
-               for(t1 = t; t1 != T; t1 = t1->down)
-                       if(t1->sym == S && typesu[t1->etype])
-                               if(sametype(s->type, t1)) {
-                                       if(xt != T)
-                                               goto ambig;
-                                       xt = t1;
-                               }
-       if(xt != T) {
-               *off = xt->offset;
-               return xt;
-       }
-
-       /*
-        * look it up in unnamed substructures
-        */
-       for(t1 = t; t1 != T; t1 = t1->down)
-               if(t1->sym == S && typesu[t1->etype]){
-                       rt = dotsearch(s, t1->link, n, off);
-                       if(rt != T) {
-                               if(xt != T)
-                                       goto ambig;
-                               xt = rt;
-                               *off += t1->offset;
-                       }
-               }
-       return xt;
-
-ambig:
-       diag(n, "ambiguous structure element: %s", s->name);
-       return xt;
-}
-
-int32
-dotoffset(Type *st, Type *lt, Node *n)
-{
-       Type *t;
-       Sym *g;
-       int32 o, o1;
-
-       o = -1;
-       /*
-        * first try matching at the top level
-        * for matching tag names
-        */
-       g = st->tag;
-       if(g != S)
-               for(t=lt->link; t!=T; t=t->down)
-                       if(t->sym == S)
-                               if(g == t->tag) {
-                                       if(o >= 0)
-                                               goto ambig;
-                                       o = t->offset;
-                               }
-       if(o >= 0)
-               return o;
-
-       /*
-        * second try matching at the top level
-        * for similar types
-        */
-       for(t=lt->link; t!=T; t=t->down)
-               if(t->sym == S)
-                       if(sametype(st, t)) {
-                               if(o >= 0)
-                                       goto ambig;
-                               o = t->offset;
-                       }
-       if(o >= 0)
-               return o;
-
-       /*
-        * last try matching sub-levels
-        */
-       for(t=lt->link; t!=T; t=t->down)
-               if(t->sym == S)
-               if(typesu[t->etype]) {
-                       o1 = dotoffset(st, t, n);
-                       if(o1 >= 0) {
-                               if(o >= 0)
-                                       goto ambig;
-                               o = o1 + t->offset;
-                       }
-               }
-       return o;
-
-ambig:
-       diag(n, "ambiguous unnamed structure element");
-       return o;
-}
-
-/*
- * look into tree for floating point constant expressions
- */
-int
-allfloat(Node *n, int flag)
-{
-
-       if(n != Z) {
-               if(n->type->etype != TDOUBLE)
-                       return 1;
-               switch(n->op) {
-               case OCONST:
-                       if(flag)
-                               n->type = types[TFLOAT];
-                       return 1;
-               case OADD:      /* no need to get more exotic than this */
-               case OSUB:
-               case OMUL:
-               case ODIV:
-                       if(!allfloat(n->right, flag))
-                               break;
-               case OCAST:
-                       if(!allfloat(n->left, flag))
-                               break;
-                       if(flag)
-                               n->type = types[TFLOAT];
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-void
-constas(Node *n, Type *il, Type *ir)
-{
-       Type *l, *r;
-
-       l = il;
-       r = ir;
-
-       if(l == T)
-               return;
-       if(l->garb & GCONSTNT) {
-               warn(n, "assignment to a constant type (%T)", il);
-               return;
-       }
-       if(r == T)
-               return;
-       for(;;) {
-               if(l->etype != TIND || r->etype != TIND)
-                       break;
-               l = l->link;
-               r = r->link;
-               if(l == T || r == T)
-                       break;
-               if(r->garb & GCONSTNT)
-                       if(!(l->garb & GCONSTNT)) {
-                               warn(n, "assignment of a constant pointer type (%T)", ir);
-                               break;
-                       }
-       }
-}
-
-void
-typeext1(Type *st, Node *l)
-{
-       if(st->etype == TFLOAT && allfloat(l, 0))
-               allfloat(l, 1);
-}
-
-void
-typeext(Type *st, Node *l)
-{
-       Type *lt;
-       Node *n1, *n2;
-       int32 o;
-
-       lt = l->type;
-       if(lt == T)
-               return;
-       if(st->etype == TIND && vconst(l) == 0) {
-               l->type = st;
-               l->vconst = 0;
-               return;
-       }
-       typeext1(st, l);
-
-       /*
-        * extension of C
-        * if assign of struct containing unnamed sub-struct
-        * to type of sub-struct, insert the DOT.
-        * if assign of *struct containing unnamed substruct
-        * to type of *sub-struct, insert the add-offset
-        */
-       if(typesu[st->etype] && typesu[lt->etype]) {
-               o = dotoffset(st, lt, l);
-               if(o >= 0) {
-                       n1 = new1(OXXX, Z, Z);
-                       *n1 = *l;
-                       l->op = ODOT;
-                       l->left = n1;
-                       l->right = Z;
-                       makedot(l, st, o);
-               }
-               return;
-       }
-       if(st->etype == TIND && typesu[st->link->etype])
-       if(lt->etype == TIND && typesu[lt->link->etype]) {
-               o = dotoffset(st->link, lt->link, l);
-               if(o >= 0) {
-                       l->type = st;
-                       if(o == 0)
-                               return;
-                       n1 = new1(OXXX, Z, Z);
-                       *n1 = *l;
-                       n2 = new1(OCONST, Z, Z);
-                       n2->vconst = o;
-                       n2->type = st;
-                       l->op = OADD;
-                       l->left = n1;
-                       l->right = n2;
-               }
-               return;
-       }
-}
-
-/*
- * a cast that generates no code
- * (same size move)
- */
-int
-nocast(Type *t1, Type *t2)
-{
-       int i, b;
-
-       if(t1->nbits)
-               return 0;
-       i = 0;
-       if(t2 != T)
-               i = t2->etype;
-       b = 1<<i;
-       i = 0;
-       if(t1 != T)
-               i = t1->etype;
-       if(b & ncast[i])
-               return 1;
-       return 0;
-}
-
-/*
- * a cast that has a noop semantic
- * (small to large, convert)
- */
-int
-nilcast(Type *t1, Type *t2)
-{
-       int et1, et2;
-
-       if(t1 == T)
-               return 0;
-       if(t1->nbits)
-               return 0;
-       if(t2 == T)
-               return 0;
-       et1 = t1->etype;
-       et2 = t2->etype;
-       if(et1 == et2)
-               return 1;
-       if(typefd[et1] && typefd[et2]) {
-               if(ewidth[et1] < ewidth[et2])
-                       return 1;
-               return 0;
-       }
-       if(typechlp[et1] && typechlp[et2]) {
-               if(ewidth[et1] < ewidth[et2])
-                       return 1;
-               return 0;
-       }
-       return 0;
-}
-
-/*
- * "the usual arithmetic conversions are performed"
- */
-void
-arith(Node *n, int f)
-{
-       Type *t1, *t2;
-       int i, j, k;
-       Node *n1;
-       int32 w;
-
-       t1 = n->left->type;
-       if(n->right == Z)
-               t2 = t1;
-       else
-               t2 = n->right->type;
-       i = TXXX;
-       if(t1 != T)
-               i = t1->etype;
-       j = TXXX;
-       if(t2 != T)
-               j = t2->etype;
-       k = tab[i][j];
-       if(k == TIND) {
-               if(i == TIND)
-                       n->type = t1;
-               else
-               if(j == TIND)
-                       n->type = t2;
-       } else {
-               /* convert up to at least int */
-               if(f == 1)
-               while(k < TINT)
-                       k += 2;
-               n->type = types[k];
-       }
-       if(n->op == OSUB)
-       if(i == TIND && j == TIND) {
-               w = n->right->type->link->width;
-               if(w < 1 || n->left->type->link == T || n->left->type->link->width < 1)
-                       goto bad;
-               n->type = types[ewidth[TIND] <= ewidth[TLONG]? TLONG: TVLONG];
-               if(0 && ewidth[TIND] > ewidth[TLONG]){
-                       n1 = new1(OXXX, Z, Z);
-                       *n1 = *n;
-                       n->op = OCAST;
-                       n->left = n1;
-                       n->right = Z;
-                       n->type = types[TLONG];
-               }
-               if(w > 1) {
-                       n1 = new1(OXXX, Z, Z);
-                       *n1 = *n;
-                       n->op = ODIV;
-                       n->left = n1;
-                       n1 = new1(OCONST, Z, Z);
-                       n1->vconst = w;
-                       n1->type = n->type;
-                       n->right = n1;
-                       w = vlog(n1);
-                       if(w >= 0) {
-                               n->op = OASHR;
-                               n1->vconst = w;
-                       }
-               }
-               return;
-       }
-       if(!sametype(n->type, n->left->type)) {
-               n->left = new1(OCAST, n->left, Z);
-               n->left->type = n->type;
-               if(n->type->etype == TIND) {
-                       w = n->type->link->width;
-                       if(w < 1) {
-                               snap(n->type->link);
-                               w = n->type->link->width;
-                               if(w < 1)
-                                       goto bad;
-                       }
-                       if(w > 1) {
-                               n1 = new1(OCONST, Z, Z);
-                               n1->vconst = w;
-                               n1->type = n->type;
-                               n->left = new1(OMUL, n->left, n1);
-                               n->left->type = n->type;
-                       }
-               }
-       }
-       if(n->right != Z)
-       if(!sametype(n->type, n->right->type)) {
-               n->right = new1(OCAST, n->right, Z);
-               n->right->type = n->type;
-               if(n->type->etype == TIND) {
-                       w = n->type->link->width;
-                       if(w < 1) {
-                               snap(n->type->link);
-                               w = n->type->link->width;
-                               if(w < 1)
-                                       goto bad;
-                       }
-                       if(w != 1) {
-                               n1 = new1(OCONST, Z, Z);
-                               n1->vconst = w;
-                               n1->type = n->type;
-                               n->right = new1(OMUL, n->right, n1);
-                               n->right->type = n->type;
-                       }
-               }
-       }
-       return;
-bad:
-       diag(n, "pointer addition not fully declared: %T", n->type->link);
-}
-
-/*
- * try to rewrite shift & mask
- */
-void
-simplifyshift(Node *n)
-{
-       uint32 c3;
-       int o, s1, s2, c1, c2;
-
-       if(!typechlp[n->type->etype])
-               return;
-       switch(n->op) {
-       default:
-               return;
-       case OASHL:
-               s1 = 0;
-               break;
-       case OLSHR:
-               s1 = 1;
-               break;
-       case OASHR:
-               s1 = 2;
-               break;
-       }
-       if(n->right->op != OCONST)
-               return;
-       if(n->left->op != OAND)
-               return;
-       if(n->left->right->op != OCONST)
-               return;
-       switch(n->left->left->op) {
-       default:
-               return;
-       case OASHL:
-               s2 = 0;
-               break;
-       case OLSHR:
-               s2 = 1;
-               break;
-       case OASHR:
-               s2 = 2;
-               break;
-       }
-       if(n->left->left->right->op != OCONST)
-               return;
-
-       c1 = n->right->vconst;
-       c2 = n->left->left->right->vconst;
-       c3 = n->left->right->vconst;
-
-       o = n->op;
-       switch((s1<<3)|s2) {
-       case 000:       /* (((e <<u c2) & c3) <<u c1) */
-               c3 >>= c2;
-               c1 += c2;
-               if(c1 >= 32)
-                       break;
-               goto rewrite1;
-
-       case 002:       /* (((e >>s c2) & c3) <<u c1) */
-               if(topbit(c3) >= (32-c2))
-                       break;
-       case 001:       /* (((e >>u c2) & c3) <<u c1) */
-               if(c1 > c2) {
-                       c3 <<= c2;
-                       c1 -= c2;
-                       o = OASHL;
-                       goto rewrite1;
-               }
-               c3 <<= c1;
-               if(c1 == c2)
-                       goto rewrite0;
-               c1 = c2-c1;
-               o = OLSHR;
-               goto rewrite2;
-
-       case 022:       /* (((e >>s c2) & c3) >>s c1) */
-               if(c2 <= 0)
-                       break;
-       case 012:       /* (((e >>s c2) & c3) >>u c1) */
-               if(topbit(c3) >= (32-c2))
-                       break;
-               goto s11;
-       case 021:       /* (((e >>u c2) & c3) >>s c1) */
-               if(topbit(c3) >= 31 && c2 <= 0)
-                       break;
-               goto s11;
-       case 011:       /* (((e >>u c2) & c3) >>u c1) */
-       s11:
-               c3 <<= c2;
-               c1 += c2;
-               if(c1 >= 32)
-                       break;
-               o = OLSHR;
-               goto rewrite1;
-
-       case 020:       /* (((e <<u c2) & c3) >>s c1) */
-               if(topbit(c3) >= 31)
-                       break;
-       case 010:       /* (((e <<u c2) & c3) >>u c1) */
-               c3 >>= c1;
-               if(c1 == c2)
-                       goto rewrite0;
-               if(c1 > c2) {
-                       c1 -= c2;
-                       goto rewrite2;
-               }
-               c1 = c2 - c1;
-               o = OASHL;
-               goto rewrite2;
-       }
-       return;
-
-rewrite0:      /* get rid of both shifts */
-if(debug['<'])prtree(n, "rewrite0");
-       *n = *n->left;
-       n->left = n->left->left;
-       n->right->vconst = c3;
-       return;
-rewrite1:      /* get rid of lower shift */
-if(debug['<'])prtree(n, "rewrite1");
-       n->left->left = n->left->left->left;
-       n->left->right->vconst = c3;
-       n->right->vconst = c1;
-       n->op = o;
-       return;
-rewrite2:      /* get rid of upper shift */
-if(debug['<'])prtree(n, "rewrite2");
-       *n = *n->left;
-       n->right->vconst = c3;
-       n->left->right->vconst = c1;
-       n->left->op = o;
-}
-
-int
-side(Node *n)
-{
-
-loop:
-       if(n != Z)
-       switch(n->op) {
-       case OCAST:
-       case ONOT:
-       case OADDR:
-       case OIND:
-               n = n->left;
-               goto loop;
-
-       case OCOND:
-               if(side(n->left))
-                       break;
-               n = n->right;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OADD:
-       case OSUB:
-       case OMUL:
-       case OLMUL:
-       case ODIV:
-       case OLDIV:
-       case OLSHR:
-       case OASHL:
-       case OASHR:
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OMOD:
-       case OLMOD:
-       case OANDAND:
-       case OOROR:
-       case OCOMMA:
-       case ODOT:
-               if(side(n->left))
-                       break;
-               n = n->right;
-               goto loop;
-
-       case OSIGN:
-       case OSIZE:
-       case OCONST:
-       case OSTRING:
-       case OLSTRING:
-       case ONAME:
-               return 0;
-       }
-       return 1;
-}
-
-int
-vconst(Node *n)
-{
-       int i;
-
-       if(n == Z)
-               goto no;
-       if(n->op != OCONST)
-               goto no;
-       if(n->type == T)
-               goto no;
-       switch(n->type->etype)
-       {
-       case TFLOAT:
-       case TDOUBLE:
-               i = 100;
-               if(n->fconst > i || n->fconst < -i)
-                       goto no;
-               i = n->fconst;
-               if(i != n->fconst)
-                       goto no;
-               return i;
-
-       case TVLONG:
-       case TUVLONG:
-               i = n->vconst;
-               if(i != n->vconst)
-                       goto no;
-               return i;
-
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-       case TINT:
-       case TUINT:
-       case TLONG:
-       case TULONG:
-       case TIND:
-               i = n->vconst;
-               if(i != n->vconst)
-                       goto no;
-               return i;
-       }
-no:
-       return -159;    /* first uninteresting constant */
-}
-
-/*
- * return log(n) if n is a power of 2 constant
- */
-int
-xlog2(uvlong v)
-{
-       int s, i;
-       uvlong m;
-
-       s = 0;
-       m = MASK(8*sizeof(uvlong));
-       for(i=32; i; i>>=1) {
-               m >>= i;
-               if(!(v & m)) {
-                       v >>= i;
-                       s += i;
-               }
-       }
-       if(v == 1)
-               return s;
-       return -1;
-}
-
-int
-vlog(Node *n)
-{
-       if(n->op != OCONST)
-               goto bad;
-       if(typefd[n->type->etype])
-               goto bad;
-
-       return xlog2(n->vconst);
-
-bad:
-       return -1;
-}
-
-int
-topbit(uint32 v)
-{
-       int i;
-
-       for(i = -1; v; i++)
-               v >>= 1;
-       return i;
-}
-
-/*
- * try to cast a constant down
- * rather than cast a variable up
- * example:
- *     if(c == 'a')
- */
-void
-relcon(Node *l, Node *r)
-{
-       vlong v;
-
-       if(l->op != OCONST)
-               return;
-       if(r->op != OCAST)
-               return;
-       if(!nilcast(r->left->type, r->type))
-               return;
-       switch(r->type->etype) {
-       default:
-               return;
-       case TCHAR:
-       case TUCHAR:
-       case TSHORT:
-       case TUSHORT:
-               v = convvtox(l->vconst, r->type->etype);
-               if(v != l->vconst)
-                       return;
-               break;
-       }
-       l->type = r->left->type;
-       *r = *r->left;
-}
-
-int
-relindex(int o)
-{
-
-       switch(o) {
-       default:
-               diag(Z, "bad in relindex: %O", o);
-       case OEQ: return 0;
-       case ONE: return 1;
-       case OLE: return 2;
-       case OLS: return 3;
-       case OLT: return 4;
-       case OLO: return 5;
-       case OGE: return 6;
-       case OHS: return 7;
-       case OGT: return 8;
-       case OHI: return 9;
-       }
-}
-
-Node*
-invert(Node *n)
-{
-       Node *i;
-
-       if(n == Z || n->op != OLIST)
-               return n;
-       i = n;
-       for(n = n->left; n != Z; n = n->left) {
-               if(n->op != OLIST)
-                       break;
-               i->left = n->right;
-               n->right = i;
-               i = n;
-       }
-       i->left = n;
-       return i;
-}
-
-int
-bitno(int32 b)
-{
-       int i;
-
-       for(i=0; i<32; i++)
-               if(b & (1L<<i))
-                       return i;
-       diag(Z, "bad in bitno");
-       return 0;
-}
-
-int32
-typebitor(int32 a, int32 b)
-{
-       int32 c;
-
-       c = a | b;
-       if(a & b)
-               if((a & b) == BLONG)
-                       c |= BVLONG;            /* long long => vlong */
-               else
-                       warn(Z, "once is enough: %Q", a & b);
-       return c;
-}
-
-void
-diag(Node *n, char *fmt, ...)
-{
-       char buf[STRINGSZ];
-       va_list arg;
-
-       va_start(arg, fmt);
-       vseprint(buf, buf+sizeof(buf), fmt, arg);
-       va_end(arg);
-       Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
-
-       if(debug['X']){
-               Bflush(&diagbuf);
-               abort();
-       }
-       if(n != Z)
-       if(debug['v'])
-               prtree(n, "diagnostic");
-
-       nerrors++;
-       if(nerrors > 10) {
-               Bprint(&diagbuf, "too many errors\n");
-               errorexit();
-       }
-}
-
-void
-warn(Node *n, char *fmt, ...)
-{
-       char buf[STRINGSZ];
-       va_list arg;
-
-       if(debug['w']) {
-               Bprint(&diagbuf, "warning: ");
-               va_start(arg, fmt);
-               vseprint(buf, buf+sizeof(buf), fmt, arg);
-               va_end(arg);
-               Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
-
-               if(n != Z)
-               if(debug['v'])
-                       prtree(n, "warning");
-       }
-}
-
-void
-yyerror(char *fmt, ...)
-{
-       char buf[STRINGSZ];
-       va_list arg;
-
-       /*
-        * hack to intercept message from yaccpar
-        */
-       if(strcmp(fmt, "syntax error") == 0) {
-               yyerror("syntax error, last name: %s", symb);
-               return;
-       }
-       va_start(arg, fmt);
-       vseprint(buf, buf+sizeof(buf), fmt, arg);
-       va_end(arg);
-       Bprint(&diagbuf, "%L %s\n", lineno, buf);
-       nerrors++;
-       if(nerrors > 10) {
-               Bprint(&diagbuf, "too many errors\n");
-               errorexit();
-       }
-}
-
-void
-fatal(Node *n, char *fmt, ...)
-{
-       char buf[STRINGSZ];
-       va_list arg;
-
-       va_start(arg, fmt);
-       vseprint(buf, buf+sizeof(buf), fmt, arg);
-       va_end(arg);
-       Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
-
-       if(debug['X']){
-               Bflush(&diagbuf);
-               abort();
-       }
-       if(n != Z)
-       if(debug['v'])
-               prtree(n, "diagnostic");
-
-       nerrors++;
-       errorexit();
-}
-
-uint32 thash1  = 0x2edab8c9;
-uint32 thash2  = 0x1dc74fb8;
-uint32 thash3  = 0x1f241331;
-uint32 thash[NALLTYPES];
-Init   thashinit[] =
-{
-       TXXX,           0x17527bbd,     0,
-       TCHAR,          0x5cedd32b,     0,
-       TUCHAR,         0x552c4454,     0,
-       TSHORT,         0x63040b4b,     0,
-       TUSHORT,        0x32a45878,     0,
-       TINT,           0x4151d5bd,     0,
-       TUINT,          0x5ae707d6,     0,
-       TLONG,          0x5ef20f47,     0,
-       TULONG,         0x36d8eb8f,     0,
-       TVLONG,         0x6e5e9590,     0,
-       TUVLONG,        0x75910105,     0,
-       TFLOAT,         0x25fd7af1,     0,
-       TDOUBLE,        0x7c40a1b2,     0,
-       TIND,           0x1b832357,     0,
-       TFUNC,          0x6babc9cb,     0,
-       TARRAY,         0x7c50986d,     0,
-       TVOID,          0x44112eff,     0,
-       TSTRUCT,        0x7c2da3bf,     0,
-       TUNION,         0x3eb25e98,     0,
-       TENUM,          0x44b54f61,     0,
-       TFILE,          0x19242ac3,     0,
-       TOLD,           0x22b15988,     0,
-       TDOT,           0x0204f6b3,     0,
-       -1,             0,              0,
-};
-
-char*  bnames[NALIGN];
-Init   bnamesinit[] =
-{
-       Axxx,   0,      "Axxx",
-       Ael1,   0,      "el1",
-       Ael2,   0,      "el2",
-       Asu2,   0,      "su2",
-       Aarg0,  0,      "arg0",
-       Aarg1,  0,      "arg1",
-       Aarg2,  0,      "arg2",
-       Aaut3,  0,      "aut3",
-       -1,     0,      0,
-};
-
-char*  tnames[NALLTYPES];
-Init   tnamesinit[] =
-{
-       TXXX,           0,      "TXXX",
-       TCHAR,          0,      "CHAR",
-       TUCHAR,         0,      "UCHAR",
-       TSHORT,         0,      "SHORT",
-       TUSHORT,        0,      "USHORT",
-       TINT,           0,      "INT",
-       TUINT,          0,      "UINT",
-       TLONG,          0,      "LONG",
-       TULONG,         0,      "ULONG",
-       TVLONG,         0,      "VLONG",
-       TUVLONG,        0,      "UVLONG",
-       TFLOAT,         0,      "FLOAT",
-       TDOUBLE,        0,      "DOUBLE",
-       TIND,           0,      "IND",
-       TFUNC,          0,      "FUNC",
-       TARRAY,         0,      "ARRAY",
-       TVOID,          0,      "VOID",
-       TSTRUCT,        0,      "STRUCT",
-       TUNION,         0,      "UNION",
-       TENUM,          0,      "ENUM",
-       TFILE,          0,      "FILE",
-       TOLD,           0,      "OLD",
-       TDOT,           0,      "DOT",
-       -1,             0,      0,
-};
-
-char*  gnames[NGTYPES];
-Init   gnamesinit[] =
-{
-       GXXX,                   0,      "GXXX",
-       GCONSTNT,               0,      "CONST",
-       GVOLATILE,              0,      "VOLATILE",
-       GVOLATILE|GCONSTNT,     0,      "CONST-VOLATILE",
-       -1,                     0,      0,
-};
-
-char*  qnames[NALLTYPES];
-Init   qnamesinit[] =
-{
-       TXXX,           0,      "TXXX",
-       TCHAR,          0,      "CHAR",
-       TUCHAR,         0,      "UCHAR",
-       TSHORT,         0,      "SHORT",
-       TUSHORT,        0,      "USHORT",
-       TINT,           0,      "INT",
-       TUINT,          0,      "UINT",
-       TLONG,          0,      "LONG",
-       TULONG,         0,      "ULONG",
-       TVLONG,         0,      "VLONG",
-       TUVLONG,        0,      "UVLONG",
-       TFLOAT,         0,      "FLOAT",
-       TDOUBLE,        0,      "DOUBLE",
-       TIND,           0,      "IND",
-       TFUNC,          0,      "FUNC",
-       TARRAY,         0,      "ARRAY",
-       TVOID,          0,      "VOID",
-       TSTRUCT,        0,      "STRUCT",
-       TUNION,         0,      "UNION",
-       TENUM,          0,      "ENUM",
-
-       TAUTO,          0,      "AUTO",
-       TEXTERN,        0,      "EXTERN",
-       TSTATIC,        0,      "STATIC",
-       TTYPEDEF,       0,      "TYPEDEF",
-       TTYPESTR,       0,      "TYPESTR",
-       TREGISTER,      0,      "REGISTER",
-       TCONSTNT,       0,      "CONSTNT",
-       TVOLATILE,      0,      "VOLATILE",
-       TUNSIGNED,      0,      "UNSIGNED",
-       TSIGNED,        0,      "SIGNED",
-       TDOT,           0,      "DOT",
-       TFILE,          0,      "FILE",
-       TOLD,           0,      "OLD",
-       -1,             0,      0,
-};
-char*  cnames[NCTYPES];
-Init   cnamesinit[] =
-{
-       CXXX,           0,      "CXXX",
-       CAUTO,          0,      "AUTO",
-       CEXTERN,        0,      "EXTERN",
-       CGLOBL,         0,      "GLOBL",
-       CSTATIC,        0,      "STATIC",
-       CLOCAL,         0,      "LOCAL",
-       CTYPEDEF,       0,      "TYPEDEF",
-       CTYPESTR,       0,      "TYPESTR",
-       CPARAM,         0,      "PARAM",
-       CSELEM,         0,      "SELEM",
-       CLABEL,         0,      "LABEL",
-       CEXREG,         0,      "EXREG",
-       -1,             0,      0,
-};
-
-char*  onames[OEND+1];
-Init   onamesinit[] =
-{
-       OXXX,           0,      "OXXX",
-       OADD,           0,      "ADD",
-       OADDR,          0,      "ADDR",
-       OAND,           0,      "AND",
-       OANDAND,        0,      "ANDAND",
-       OARRAY,         0,      "ARRAY",
-       OAS,            0,      "AS",
-       OASI,           0,      "ASI",
-       OASADD,         0,      "ASADD",
-       OASAND,         0,      "ASAND",
-       OASASHL,        0,      "ASASHL",
-       OASASHR,        0,      "ASASHR",
-       OASDIV,         0,      "ASDIV",
-       OASHL,          0,      "ASHL",
-       OASHR,          0,      "ASHR",
-       OASLDIV,        0,      "ASLDIV",
-       OASLMOD,        0,      "ASLMOD",
-       OASLMUL,        0,      "ASLMUL",
-       OASLSHR,        0,      "ASLSHR",
-       OASMOD,         0,      "ASMOD",
-       OASMUL,         0,      "ASMUL",
-       OASOR,          0,      "ASOR",
-       OASSUB,         0,      "ASSUB",
-       OASXOR,         0,      "ASXOR",
-       OBIT,           0,      "BIT",
-       OBREAK,         0,      "BREAK",
-       OCASE,          0,      "CASE",
-       OCAST,          0,      "CAST",
-       OCOMMA,         0,      "COMMA",
-       OCOND,          0,      "COND",
-       OCONST,         0,      "CONST",
-       OCONTINUE,      0,      "CONTINUE",
-       ODIV,           0,      "DIV",
-       ODOT,           0,      "DOT",
-       ODOTDOT,        0,      "DOTDOT",
-       ODWHILE,        0,      "DWHILE",
-       OENUM,          0,      "ENUM",
-       OEQ,            0,      "EQ",
-       OEXREG, 0,      "EXREG",
-       OFOR,           0,      "FOR",
-       OFUNC,          0,      "FUNC",
-       OGE,            0,      "GE",
-       OGOTO,          0,      "GOTO",
-       OGT,            0,      "GT",
-       OHI,            0,      "HI",
-       OHS,            0,      "HS",
-       OIF,            0,      "IF",
-       OIND,           0,      "IND",
-       OINDREG,        0,      "INDREG",
-       OINIT,          0,      "INIT",
-       OLABEL,         0,      "LABEL",
-       OLDIV,          0,      "LDIV",
-       OLE,            0,      "LE",
-       OLIST,          0,      "LIST",
-       OLMOD,          0,      "LMOD",
-       OLMUL,          0,      "LMUL",
-       OLO,            0,      "LO",
-       OLS,            0,      "LS",
-       OLSHR,          0,      "LSHR",
-       OLT,            0,      "LT",
-       OMOD,           0,      "MOD",
-       OMUL,           0,      "MUL",
-       ONAME,          0,      "NAME",
-       ONE,            0,      "NE",
-       ONOT,           0,      "NOT",
-       OOR,            0,      "OR",
-       OOROR,          0,      "OROR",
-       OPOSTDEC,       0,      "POSTDEC",
-       OPOSTINC,       0,      "POSTINC",
-       OPREDEC,        0,      "PREDEC",
-       OPREINC,        0,      "PREINC",
-       OPREFETCH,              0,      "PREFETCH",
-       OPROTO,         0,      "PROTO",
-       OREGISTER,      0,      "REGISTER",
-       ORETURN,        0,      "RETURN",
-       OSET,           0,      "SET",
-       OSIGN,          0,      "SIGN",
-       OSIZE,          0,      "SIZE",
-       OSTRING,        0,      "STRING",
-       OLSTRING,       0,      "LSTRING",
-       OSTRUCT,        0,      "STRUCT",
-       OSUB,           0,      "SUB",
-       OSWITCH,        0,      "SWITCH",
-       OUNION,         0,      "UNION",
-       OUSED,          0,      "USED",
-       OWHILE,         0,      "WHILE",
-       OXOR,           0,      "XOR",
-       OPOS,           0,      "POS",
-       ONEG,           0,      "NEG",
-       OCOM,           0,      "COM",
-       OELEM,          0,      "ELEM",
-       OTST,           0,      "TST",
-       OINDEX,         0,      "INDEX",
-       OFAS,           0,      "FAS",
-       OREGPAIR,       0,      "REGPAIR",
-       OROTL,          0,      "ROTL",
-       OEND,           0,      "END",
-       -1,             0,      0,
-};
-
-/*     OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */
-uchar  comrel[12] =
-{
-       ONE, OEQ, OGT, OHI, OGE, OHS, OLT, OLO, OLE, OLS,
-};
-uchar  invrel[12] =
-{
-       OEQ, ONE, OGE, OHS, OGT, OHI, OLE, OLS, OLT, OLO,
-};
-uchar  logrel[12] =
-{
-       OEQ, ONE, OLS, OLS, OLO, OLO, OHS, OHS, OHI, OHI,
-};
-
-uchar  typei[NALLTYPES];
-int    typeiinit[] =
-{
-       TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TVLONG, TUVLONG, -1,
-};
-uchar  typeu[NALLTYPES];
-int    typeuinit[] =
-{
-       TUCHAR, TUSHORT, TUINT, TULONG, TUVLONG, TIND, -1,
-};
-
-uchar  typesuv[NALLTYPES];
-int    typesuvinit[] =
-{
-       TVLONG, TUVLONG, TSTRUCT, TUNION, -1,
-};
-
-uchar  typeilp[NALLTYPES];
-int    typeilpinit[] =
-{
-       TINT, TUINT, TLONG, TULONG, TIND, -1
-};
-
-uchar  typechl[NALLTYPES];
-uchar  typechlv[NALLTYPES];
-uchar  typechlvp[NALLTYPES];
-int    typechlinit[] =
-{
-       TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, -1,
-};
-
-uchar  typechlp[NALLTYPES];
-int    typechlpinit[] =
-{
-       TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TIND, -1,
-};
-
-uchar  typechlpfd[NALLTYPES];
-int    typechlpfdinit[] =
-{
-       TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TFLOAT, TDOUBLE, TIND, -1,
-};
-
-uchar  typec[NALLTYPES];
-int    typecinit[] =
-{
-       TCHAR, TUCHAR, -1
-};
-
-uchar  typeh[NALLTYPES];
-int    typehinit[] =
-{
-       TSHORT, TUSHORT, -1,
-};
-
-uchar  typeil[NALLTYPES];
-int    typeilinit[] =
-{
-       TINT, TUINT, TLONG, TULONG, -1,
-};
-
-uchar  typev[NALLTYPES];
-int    typevinit[] =
-{
-       TVLONG, TUVLONG, -1,
-};
-
-uchar  typefd[NALLTYPES];
-int    typefdinit[] =
-{
-       TFLOAT, TDOUBLE, -1,
-};
-
-uchar  typeaf[NALLTYPES];
-int    typeafinit[] =
-{
-       TFUNC, TARRAY, -1,
-};
-
-uchar  typesu[NALLTYPES];
-int    typesuinit[] =
-{
-       TSTRUCT, TUNION, -1,
-};
-
-int32  tasign[NALLTYPES];
-Init   tasigninit[] =
-{
-       TCHAR,          BNUMBER,        0,
-       TUCHAR,         BNUMBER,        0,
-       TSHORT,         BNUMBER,        0,
-       TUSHORT,        BNUMBER,        0,
-       TINT,           BNUMBER,        0,
-       TUINT,          BNUMBER,        0,
-       TLONG,          BNUMBER,        0,
-       TULONG,         BNUMBER,        0,
-       TVLONG,         BNUMBER,        0,
-       TUVLONG,        BNUMBER,        0,
-       TFLOAT,         BNUMBER,        0,
-       TDOUBLE,        BNUMBER,        0,
-       TIND,           BIND,           0,
-       TSTRUCT,        BSTRUCT,        0,
-       TUNION,         BUNION,         0,
-       -1,             0,              0,
-};
-
-int32  tasadd[NALLTYPES];
-Init   tasaddinit[] =
-{
-       TCHAR,          BNUMBER,        0,
-       TUCHAR,         BNUMBER,        0,
-       TSHORT,         BNUMBER,        0,
-       TUSHORT,        BNUMBER,        0,
-       TINT,           BNUMBER,        0,
-       TUINT,          BNUMBER,        0,
-       TLONG,          BNUMBER,        0,
-       TULONG,         BNUMBER,        0,
-       TVLONG,         BNUMBER,        0,
-       TUVLONG,        BNUMBER,        0,
-       TFLOAT,         BNUMBER,        0,
-       TDOUBLE,        BNUMBER,        0,
-       TIND,           BINTEGER,       0,
-       -1,             0,              0,
-};
-
-int32  tcast[NALLTYPES];
-Init   tcastinit[] =
-{
-       TCHAR,          BNUMBER|BIND|BVOID,     0,
-       TUCHAR,         BNUMBER|BIND|BVOID,     0,
-       TSHORT,         BNUMBER|BIND|BVOID,     0,
-       TUSHORT,        BNUMBER|BIND|BVOID,     0,
-       TINT,           BNUMBER|BIND|BVOID,     0,
-       TUINT,          BNUMBER|BIND|BVOID,     0,
-       TLONG,          BNUMBER|BIND|BVOID,     0,
-       TULONG,         BNUMBER|BIND|BVOID,     0,
-       TVLONG,         BNUMBER|BIND|BVOID,     0,
-       TUVLONG,        BNUMBER|BIND|BVOID,     0,
-       TFLOAT,         BNUMBER|BVOID,          0,
-       TDOUBLE,        BNUMBER|BVOID,          0,
-       TIND,           BINTEGER|BIND|BVOID,    0,
-       TVOID,          BVOID,                  0,
-       TSTRUCT,        BSTRUCT|BVOID,          0,
-       TUNION,         BUNION|BVOID,           0,
-       -1,             0,                      0,
-};
-
-int32  tadd[NALLTYPES];
-Init   taddinit[] =
-{
-       TCHAR,          BNUMBER|BIND,   0,
-       TUCHAR,         BNUMBER|BIND,   0,
-       TSHORT,         BNUMBER|BIND,   0,
-       TUSHORT,        BNUMBER|BIND,   0,
-       TINT,           BNUMBER|BIND,   0,
-       TUINT,          BNUMBER|BIND,   0,
-       TLONG,          BNUMBER|BIND,   0,
-       TULONG,         BNUMBER|BIND,   0,
-       TVLONG,         BNUMBER|BIND,   0,
-       TUVLONG,        BNUMBER|BIND,   0,
-       TFLOAT,         BNUMBER,        0,
-       TDOUBLE,        BNUMBER,        0,
-       TIND,           BINTEGER,       0,
-       -1,             0,              0,
-};
-
-int32  tsub[NALLTYPES];
-Init   tsubinit[] =
-{
-       TCHAR,          BNUMBER,        0,
-       TUCHAR,         BNUMBER,        0,
-       TSHORT,         BNUMBER,        0,
-       TUSHORT,        BNUMBER,        0,
-       TINT,           BNUMBER,        0,
-       TUINT,          BNUMBER,        0,
-       TLONG,          BNUMBER,        0,
-       TULONG,         BNUMBER,        0,
-       TVLONG,         BNUMBER,        0,
-       TUVLONG,        BNUMBER,        0,
-       TFLOAT,         BNUMBER,        0,
-       TDOUBLE,        BNUMBER,        0,
-       TIND,           BINTEGER|BIND,  0,
-       -1,             0,              0,
-};
-
-int32  tmul[NALLTYPES];
-Init   tmulinit[] =
-{
-       TCHAR,          BNUMBER,        0,
-       TUCHAR,         BNUMBER,        0,
-       TSHORT,         BNUMBER,        0,
-       TUSHORT,        BNUMBER,        0,
-       TINT,           BNUMBER,        0,
-       TUINT,          BNUMBER,        0,
-       TLONG,          BNUMBER,        0,
-       TULONG,         BNUMBER,        0,
-       TVLONG,         BNUMBER,        0,
-       TUVLONG,        BNUMBER,        0,
-       TFLOAT,         BNUMBER,        0,
-       TDOUBLE,        BNUMBER,        0,
-       -1,             0,              0,
-};
-
-int32  tand[NALLTYPES];
-Init   tandinit[] =
-{
-       TCHAR,          BINTEGER,       0,
-       TUCHAR,         BINTEGER,       0,
-       TSHORT,         BINTEGER,       0,
-       TUSHORT,        BINTEGER,       0,
-       TINT,           BNUMBER,        0,
-       TUINT,          BNUMBER,        0,
-       TLONG,          BINTEGER,       0,
-       TULONG,         BINTEGER,       0,
-       TVLONG,         BINTEGER,       0,
-       TUVLONG,        BINTEGER,       0,
-       -1,             0,              0,
-};
-
-int32  trel[NALLTYPES];
-Init   trelinit[] =
-{
-       TCHAR,          BNUMBER,        0,
-       TUCHAR,         BNUMBER,        0,
-       TSHORT,         BNUMBER,        0,
-       TUSHORT,        BNUMBER,        0,
-       TINT,           BNUMBER,        0,
-       TUINT,          BNUMBER,        0,
-       TLONG,          BNUMBER,        0,
-       TULONG,         BNUMBER,        0,
-       TVLONG,         BNUMBER,        0,
-       TUVLONG,        BNUMBER,        0,
-       TFLOAT,         BNUMBER,        0,
-       TDOUBLE,        BNUMBER,        0,
-       TIND,           BIND,           0,
-       -1,             0,              0,
-};
-
-int32  tfunct[1] =
-{
-       BFUNC,
-};
-
-int32  tindir[1] =
-{
-       BIND,
-};
-
-int32  tdot[1] =
-{
-       BSTRUCT|BUNION,
-};
-
-int32  tnot[1] =
-{
-       BNUMBER|BIND,
-};
-
-int32  targ[1] =
-{
-       BNUMBER|BIND|BSTRUCT|BUNION,
-};
-
-uchar  tab[NTYPE][NTYPE] =
-{
-/*TXXX*/       { 0,
-               },
-
-/*TCHAR*/      { 0,    TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG,
-                       TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TUCHAR*/     { 0,    TUCHAR, TUCHAR, TUSHORT, TUSHORT, TUINT, TUINT, TULONG,
-                       TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TSHORT*/     { 0,    TSHORT, TUSHORT, TSHORT, TUSHORT, TINT, TUINT, TLONG,
-                       TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TUSHORT*/    { 0,    TUSHORT, TUSHORT, TUSHORT, TUSHORT, TUINT, TUINT, TULONG,
-                       TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TINT*/       { 0,    TINT, TUINT, TINT, TUINT, TINT, TUINT, TLONG,
-                       TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TUINT*/      { 0,    TUINT, TUINT, TUINT, TUINT, TUINT, TUINT, TULONG,
-                       TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TLONG*/      { 0,    TLONG, TULONG, TLONG, TULONG, TLONG, TULONG, TLONG,
-                       TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TULONG*/     { 0,    TULONG, TULONG, TULONG, TULONG, TULONG, TULONG, TULONG,
-                       TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TVLONG*/     { 0,    TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG,
-                       TUVLONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TUVLONG*/    { 0,    TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG,
-                       TUVLONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
-               },
-/*TFLOAT*/     { 0,    TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT,
-                       TFLOAT, TFLOAT, TFLOAT, TFLOAT, TDOUBLE, TIND,
-               },
-/*TDOUBLE*/    { 0,    TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE,
-                       TDOUBLE, TDOUBLE, TDOUBLE, TFLOAT, TDOUBLE, TIND,
-               },
-/*TIND*/       { 0,    TIND, TIND, TIND, TIND, TIND, TIND, TIND,
-                        TIND, TIND, TIND, TIND, TIND, TIND,
-               },
-};
-
-void
-urk(char *name, int max, int i)
-{
-       if(i >= max) {
-               fprint(2, "bad tinit: %s %d>=%d\n", name, i, max);
-               exits("init");
-       }
-}
-
-void
-tinit(void)
-{
-       int *ip;
-       Init *p;
-
-       for(p=thashinit; p->code >= 0; p++) {
-               urk("thash", nelem(thash), p->code);
-               thash[p->code] = p->value;
-       }
-       for(p=bnamesinit; p->code >= 0; p++) {
-               urk("bnames", nelem(bnames), p->code);
-               bnames[p->code] = p->s;
-       }
-       for(p=tnamesinit; p->code >= 0; p++) {
-               urk("tnames", nelem(tnames), p->code);
-               tnames[p->code] = p->s;
-       }
-       for(p=gnamesinit; p->code >= 0; p++) {
-               urk("gnames", nelem(gnames), p->code);
-               gnames[p->code] = p->s;
-       }
-       for(p=qnamesinit; p->code >= 0; p++) {
-               urk("qnames", nelem(qnames), p->code);
-               qnames[p->code] = p->s;
-       }
-       for(p=cnamesinit; p->code >= 0; p++) {
-               urk("cnames", nelem(cnames), p->code);
-               cnames[p->code] = p->s;
-       }
-       for(p=onamesinit; p->code >= 0; p++) {
-               urk("onames", nelem(onames), p->code);
-               onames[p->code] = p->s;
-       }
-       for(ip=typeiinit; *ip>=0; ip++) {
-               urk("typei", nelem(typei), *ip);
-               typei[*ip] = 1;
-       }
-       for(ip=typeuinit; *ip>=0; ip++) {
-               urk("typeu", nelem(typeu), *ip);
-               typeu[*ip] = 1;
-       }
-       for(ip=typesuvinit; *ip>=0; ip++) {
-               urk("typesuv", nelem(typesuv), *ip);
-               typesuv[*ip] = 1;
-       }
-       for(ip=typeilpinit; *ip>=0; ip++) {
-               urk("typeilp", nelem(typeilp), *ip);
-               typeilp[*ip] = 1;
-       }
-       for(ip=typechlinit; *ip>=0; ip++) {
-               urk("typechl", nelem(typechl), *ip);
-               typechl[*ip] = 1;
-               typechlv[*ip] = 1;
-               typechlvp[*ip] = 1;
-       }
-       for(ip=typechlpinit; *ip>=0; ip++) {
-               urk("typechlp", nelem(typechlp), *ip);
-               typechlp[*ip] = 1;
-               typechlvp[*ip] = 1;
-       }
-       for(ip=typechlpfdinit; *ip>=0; ip++) {
-               urk("typechlpfd", nelem(typechlpfd), *ip);
-               typechlpfd[*ip] = 1;
-       }
-       for(ip=typecinit; *ip>=0; ip++) {
-               urk("typec", nelem(typec), *ip);
-               typec[*ip] = 1;
-       }
-       for(ip=typehinit; *ip>=0; ip++) {
-               urk("typeh", nelem(typeh), *ip);
-               typeh[*ip] = 1;
-       }
-       for(ip=typeilinit; *ip>=0; ip++) {
-               urk("typeil", nelem(typeil), *ip);
-               typeil[*ip] = 1;
-       }
-       for(ip=typevinit; *ip>=0; ip++) {
-               urk("typev", nelem(typev), *ip);
-               typev[*ip] = 1;
-               typechlv[*ip] = 1;
-               typechlvp[*ip] = 1;
-       }
-       for(ip=typefdinit; *ip>=0; ip++) {
-               urk("typefd", nelem(typefd), *ip);
-               typefd[*ip] = 1;
-       }
-       for(ip=typeafinit; *ip>=0; ip++) {
-               urk("typeaf", nelem(typeaf), *ip);
-               typeaf[*ip] = 1;
-       }
-       for(ip=typesuinit; *ip >= 0; ip++) {
-               urk("typesu", nelem(typesu), *ip);
-               typesu[*ip] = 1;
-       }
-       for(p=tasigninit; p->code >= 0; p++) {
-               urk("tasign", nelem(tasign), p->code);
-               tasign[p->code] = p->value;
-       }
-       for(p=tasaddinit; p->code >= 0; p++) {
-               urk("tasadd", nelem(tasadd), p->code);
-               tasadd[p->code] = p->value;
-       }
-       for(p=tcastinit; p->code >= 0; p++) {
-               urk("tcast", nelem(tcast), p->code);
-               tcast[p->code] = p->value;
-       }
-       for(p=taddinit; p->code >= 0; p++) {
-               urk("tadd", nelem(tadd), p->code);
-               tadd[p->code] = p->value;
-       }
-       for(p=tsubinit; p->code >= 0; p++) {
-               urk("tsub", nelem(tsub), p->code);
-               tsub[p->code] = p->value;
-       }
-       for(p=tmulinit; p->code >= 0; p++) {
-               urk("tmul", nelem(tmul), p->code);
-               tmul[p->code] = p->value;
-       }
-       for(p=tandinit; p->code >= 0; p++) {
-               urk("tand", nelem(tand), p->code);
-               tand[p->code] = p->value;
-       }
-       for(p=trelinit; p->code >= 0; p++) {
-               urk("trel", nelem(trel), p->code);
-               trel[p->code] = p->value;
-       }
-       
-       /* 32-bit defaults */
-       typeword = typechlp;
-       typecmplx = typesuv;
-}
-
-/*
- * return 1 if it is impossible to jump into the middle of n.
- */
-static int
-deadhead(Node *n, int caseok)
-{
-loop:
-       if(n == Z)
-               return 1;
-       switch(n->op) {
-       case OLIST:
-               if(!deadhead(n->left, caseok))
-                       return 0;
-       rloop:
-               n = n->right;
-               goto loop;
-
-       case ORETURN:
-               break;
-
-       case OLABEL:
-               return 0;
-
-       case OGOTO:
-               break;
-
-       case OCASE:
-               if(!caseok)
-                       return 0;
-               goto rloop;
-
-       case OSWITCH:
-               return deadhead(n->right, 1);
-
-       case OWHILE:
-       case ODWHILE:
-               goto rloop;
-
-       case OFOR:
-               goto rloop;
-
-       case OCONTINUE:
-               break;
-
-       case OBREAK:
-               break;
-
-       case OIF:
-               return deadhead(n->right->left, caseok) && deadhead(n->right->right, caseok);
-
-       case OSET:
-       case OUSED:
-               break;
-       }
-       return 1;
-}
-
-int
-deadheads(Node *c)
-{
-       return deadhead(c->left, 0) && deadhead(c->right, 0);
-}
-
-int
-mixedasop(Type *l, Type *r)
-{
-       return !typefd[l->etype] && typefd[r->etype];
-}
-
-LSym*
-linksym(Sym *s)
-{
-       if(s == nil)
-               return nil;
-       if(s->lsym != nil)
-               return s->lsym;
-       return linklookup(ctxt, s->name, s->class == CSTATIC);
-}
diff --git a/src/cmd/cc/y.tab.c b/src/cmd/cc/y.tab.c
deleted file mode 100644 (file)
index 94932ef..0000000
+++ /dev/null
@@ -1,3822 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* 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 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, 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
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   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.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LORE = 258,
-     LXORE = 259,
-     LANDE = 260,
-     LLSHE = 261,
-     LRSHE = 262,
-     LMDE = 263,
-     LDVE = 264,
-     LMLE = 265,
-     LME = 266,
-     LPE = 267,
-     LOROR = 268,
-     LANDAND = 269,
-     LNE = 270,
-     LEQ = 271,
-     LGE = 272,
-     LLE = 273,
-     LRSH = 274,
-     LLSH = 275,
-     LMG = 276,
-     LPP = 277,
-     LMM = 278,
-     LNAME = 279,
-     LTYPE = 280,
-     LFCONST = 281,
-     LDCONST = 282,
-     LCONST = 283,
-     LLCONST = 284,
-     LUCONST = 285,
-     LULCONST = 286,
-     LVLCONST = 287,
-     LUVLCONST = 288,
-     LSTRING = 289,
-     LLSTRING = 290,
-     LAUTO = 291,
-     LBREAK = 292,
-     LCASE = 293,
-     LCHAR = 294,
-     LCONTINUE = 295,
-     LDEFAULT = 296,
-     LDO = 297,
-     LDOUBLE = 298,
-     LELSE = 299,
-     LEXTERN = 300,
-     LFLOAT = 301,
-     LFOR = 302,
-     LGOTO = 303,
-     LIF = 304,
-     LINT = 305,
-     LLONG = 306,
-     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.  */
-#define LORE 258
-#define LXORE 259
-#define LANDE 260
-#define LLSHE 261
-#define LRSHE 262
-#define LMDE 263
-#define LDVE 264
-#define LMLE 265
-#define LME 266
-#define LPE 267
-#define LOROR 268
-#define LANDAND 269
-#define LNE 270
-#define LEQ 271
-#define LGE 272
-#define LLE 273
-#define LRSH 274
-#define LLSH 275
-#define LMG 276
-#define LPP 277
-#define LMM 278
-#define LNAME 279
-#define LTYPE 280
-#define LFCONST 281
-#define LDCONST 282
-#define LCONST 283
-#define LLCONST 284
-#define LUCONST 285
-#define LULCONST 286
-#define LVLCONST 287
-#define LUVLCONST 288
-#define LSTRING 289
-#define LLSTRING 290
-#define LAUTO 291
-#define LBREAK 292
-#define LCASE 293
-#define LCHAR 294
-#define LCONTINUE 295
-#define LDEFAULT 296
-#define LDO 297
-#define LDOUBLE 298
-#define LELSE 299
-#define LEXTERN 300
-#define LFLOAT 301
-#define LFOR 302
-#define LGOTO 303
-#define LIF 304
-#define LINT 305
-#define LLONG 306
-#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
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 31 "cc.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and cc.h re-#defines getc */
-#include "cc.h"
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 36 "cc.y"
-{
-       Node*   node;
-       Sym*    sym;
-       Type*   type;
-       struct
-       {
-               Type*   t;
-               uchar   c;
-       } tycl;
-       struct
-       {
-               Type*   t1;
-               Type*   t2;
-               Type*   t3;
-               uchar   c;
-       } tyty;
-       struct
-       {
-               char*   s;
-               int32   l;
-       } sval;
-       int32   lval;
-       double  dval;
-       vlong   vval;
-}
-/* Line 193 of yacc.c.  */
-#line 276 "y.tab.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 289 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    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 _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   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 _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  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)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((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
-
-/* 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  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   1188
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  99
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  75
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  247
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  417
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   329
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-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,    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,    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,    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,
-       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,     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,
-       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,     1,     2,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    18,    19,
-      23,    24,    27,    28,    29,    30,    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
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     4,     7,    10,    14,    15,    16,    23,
-      25,    26,    31,    35,    37,    41,    43,    47,    52,    57,
-      60,    64,    66,    67,    72,    76,    77,    82,    84,    88,
-      89,    94,    95,   101,   102,   104,   106,   110,   112,   116,
-     119,   120,   122,   125,   129,   131,   133,   138,   143,   146,
-     150,   154,   156,   160,   164,   167,   170,   173,   177,   179,
-     182,   184,   186,   189,   190,   192,   194,   197,   200,   204,
-     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,   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[] =
-{
-     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.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,   101,   101,   102,   108,   112,   114,   128,   113,   143,
-     148,   147,   155,   158,   159,   166,   167,   171,   175,   184,
-     188,   194,   200,   199,   211,   224,   225,   228,   232,   239,
-     238,   244,   243,   250,   254,   257,   261,   264,   269,   273,
-     282,   285,   288,   293,   298,   301,   302,   306,   312,   316,
-     320,   326,   327,   333,   337,   342,   345,   346,   350,   351,
-     357,   358,   359,   365,   368,   375,   376,   381,   386,   390,
-     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,
-     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,   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,  1053,
-    1059,  1058,  1070,  1078,  1087,  1091,  1086,  1108,  1107,  1116,
-    1122,  1123,  1129,  1132,  1138,  1139,  1140,  1143,  1144,  1150,
-    1151,  1154,  1158,  1162,  1163,  1166,  1167,  1168,  1169,  1170,
-    1171,  1172,  1173,  1174,  1177,  1178,  1179,  1180,  1181,  1182,
-    1183,  1186,  1187,  1188,  1191,  1206,  1218,  1219
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "';'", "','", "'='", "LORE", "LXORE",
-  "LANDE", "LLSHE", "LRSHE", "LMDE", "LDVE", "LMLE", "LME", "LPE", "'?'",
-  "':'", "LOROR", "LANDAND", "'|'", "'^'", "'&'", "LNE", "LEQ", "'<'",
-  "'>'", "LGE", "LLE", "LRSH", "LLSH", "'+'", "'-'", "'*'", "'/'", "'%'",
-  "'.'", "'['", "'('", "LMG", "LPP", "LMM", "LNAME", "LTYPE", "LFCONST",
-  "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", "LPREFETCH", "LREGISTER",
-  "LRETURN", "LSHORT", "LSIZEOF", "LUSED", "LSTATIC", "LSTRUCT", "LSWITCH",
-  "LTYPEDEF", "LTYPESTR", "LUNION", "LUNSIGNED", "LWHILE", "LVOID",
-  "LENUM", "LSIGNED", "LCONSTNT", "LVOLATILE", "LSET", "LSIGNOF",
-  "LRESTRICT", "LINLINE", "')'", "']'", "'{'", "'}'", "'!'", "'~'",
-  "$accept", "prog", "xdecl", "@1", "@2", "xdlist", "@3", "xdecor",
-  "xdecor2", "adecl", "adlist", "@4", "pdecl", "pdlist", "edecl", "@5",
-  "@6", "zedlist", "edlist", "edecor", "abdecor", "abdecor1", "abdecor2",
-  "abdecor3", "init", "qual", "qlist", "ilist", "zarglist", "arglist",
-  "block", "slist", "labels", "label", "stmnt", "forexpr", "ulstmnt", "@7",
-  "@8", "zcexpr", "zexpr", "lexpr", "cexpr", "expr", "xuexpr", "uexpr",
-  "pexpr", "string", "lstring", "zelist", "elist", "sbody", "@9",
-  "zctlist", "types", "tlist", "ctlist", "complex", "@10", "@11", "@12",
-  "@13", "@14", "gctnlist", "zgnlist", "gctname", "gcnlist", "gcname",
-  "enum", "tname", "cname", "gname", "name", "tag", "ltag", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,    59,    44,    61,   258,   259,   260,   261,
-     262,   263,   264,   265,   266,   267,    63,    58,   268,   269,
-     124,    94,    38,   270,   271,    60,    62,   272,   273,   274,
-     275,    43,    45,    42,    47,    37,    46,    91,    40,   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,   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,   329,    41,    93,   123,   125,    33,   126
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       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,   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.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     2,     2,     3,     0,     0,     6,     1,
-       0,     4,     3,     1,     3,     1,     3,     4,     4,     2,
-       3,     1,     0,     4,     3,     0,     4,     1,     3,     0,
-       4,     0,     5,     0,     1,     1,     3,     1,     3,     2,
-       0,     1,     2,     3,     1,     1,     4,     4,     2,     3,
-       3,     1,     3,     3,     2,     2,     2,     3,     1,     2,
-       1,     1,     2,     0,     1,     1,     2,     2,     3,     3,
-       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,
-       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,     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
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       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,
-     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,   177,
-       0,   160,   161,   174,   176,     0,    17,     0,   212,   103,
-       0,    67,    66,    41,    44,    45,    33,     0,    37,     0,
-      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,   326,
-     369,   382,    91,   219,    78,   131,   206,   209,   210,   211,
-     202,   203,   204,   205,   222,   223,   224,   225,   125,   126,
-     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
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -331
-static const yytype_int16 yypact[] =
-{
-    -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[] =
-{
-    -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 -205
-static const yytype_int16 yytable[] =
-{
-      28,    49,    40,   137,   212,    42,    57,    76,    44,    57,
-     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,   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,     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,
-     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
-     186,   173,   174,   175,   176,   177,   178,   179,   180,   181,
-     182,   183,   184,   185,   186,   174,   175,   176,   177,   178,
-     179,   180,   181,   182,   183,   184,   185,   186,   176,   177,
-     178,   179,   180,   181,   182,   183,   184,   185,   186
-};
-
-static const yytype_int16 yycheck[] =
-{
-       1,    27,    14,    91,   131,    17,    30,    58,    20,    33,
-      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,    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,    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,    -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,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    35,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    25,    26,
-      27,    28,    29,    30,    31,    32,    33,    34,    35
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       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,    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,    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)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* 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.  */
-
-#define YYFAIL         goto yyerrlab
-
-#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                                                         \
-    {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#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.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# 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];
-
-  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;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      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 */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-       break;
-    }
-}
-\f
-
-/* 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 look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* 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];
-  char *yymsg = yymsgbuf;
-  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;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  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;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       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
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      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 look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 4:
-#line 109 "cc.y"
-    {
-               dodecl(xdecl, lastclass, lasttype, Z);
-       }
-    break;
-
-  case 6:
-#line 114 "cc.y"
-    {
-               lastdcl = T;
-               firstarg = S;
-               dodecl(xdecl, lastclass, lasttype, (yyvsp[(2) - (2)].node));
-               if(lastdcl == T || lastdcl->etype != TFUNC) {
-                       diag((yyvsp[(2) - (2)].node), "not a function");
-                       lastdcl = types[TFUNC];
-               }
-               thisfn = lastdcl;
-               markdcl();
-               firstdcl = dclstack;
-               argmark((yyvsp[(2) - (2)].node), 0);
-       }
-    break;
-
-  case 7:
-#line 128 "cc.y"
-    {
-               argmark((yyvsp[(2) - (4)].node), 1);
-       }
-    break;
-
-  case 8:
-#line 132 "cc.y"
-    {
-               Node *n;
-
-               n = revertdcl();
-               if(n)
-                       (yyvsp[(6) - (6)].node) = new(OLIST, n, (yyvsp[(6) - (6)].node));
-               if(!debug['a'] && !debug['Z'])
-                       codgen((yyvsp[(6) - (6)].node), (yyvsp[(2) - (6)].node));
-       }
-    break;
-
-  case 9:
-#line 144 "cc.y"
-    {
-               dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 10:
-#line 148 "cc.y"
-    {
-               (yyvsp[(1) - (1)].node) = dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 11:
-#line 152 "cc.y"
-    {
-               doinit((yyvsp[(1) - (4)].node)->sym, (yyvsp[(1) - (4)].node)->type, 0L, (yyvsp[(4) - (4)].node));
-       }
-    break;
-
-  case 14:
-#line 160 "cc.y"
-    {
-               (yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z);
-               (yyval.node)->garb = simpleg((yyvsp[(2) - (3)].lval));
-       }
-    break;
-
-  case 16:
-#line 168 "cc.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-       }
-    break;
-
-  case 17:
-#line 172 "cc.y"
-    {
-               (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
-       }
-    break;
-
-  case 18:
-#line 176 "cc.y"
-    {
-               (yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
-       }
-    break;
-
-  case 19:
-#line 185 "cc.y"
-    {
-               (yyval.node) = dodecl(adecl, lastclass, lasttype, Z);
-       }
-    break;
-
-  case 20:
-#line 189 "cc.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-       }
-    break;
-
-  case 21:
-#line 195 "cc.y"
-    {
-               dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 22:
-#line 200 "cc.y"
-    {
-               (yyvsp[(1) - (1)].node) = dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 23:
-#line 204 "cc.y"
-    {
-               int32 w;
-
-               w = (yyvsp[(1) - (4)].node)->sym->type->width;
-               (yyval.node) = doinit((yyvsp[(1) - (4)].node)->sym, (yyvsp[(1) - (4)].node)->type, 0L, (yyvsp[(4) - (4)].node));
-               (yyval.node) = contig((yyvsp[(1) - (4)].node)->sym, (yyval.node), w);
-       }
-    break;
-
-  case 24:
-#line 212 "cc.y"
-    {
-               (yyval.node) = (yyvsp[(1) - (3)].node);
-               if((yyvsp[(3) - (3)].node) != Z) {
-                       (yyval.node) = (yyvsp[(3) - (3)].node);
-                       if((yyvsp[(1) - (3)].node) != Z)
-                               (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-               }
-       }
-    break;
-
-  case 27:
-#line 229 "cc.y"
-    {
-               dodecl(pdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 29:
-#line 239 "cc.y"
-    {
-               lasttype = (yyvsp[(1) - (1)].type);
-       }
-    break;
-
-  case 31:
-#line 244 "cc.y"
-    {
-               lasttype = (yyvsp[(2) - (2)].type);
-       }
-    break;
-
-  case 33:
-#line 250 "cc.y"
-    {
-               lastfield = 0;
-               edecl(CXXX, lasttype, S);
-       }
-    break;
-
-  case 35:
-#line 258 "cc.y"
-    {
-               dodecl(edecl, CXXX, lasttype, (yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 37:
-#line 265 "cc.y"
-    {
-               lastbit = 0;
-               firstbit = 1;
-       }
-    break;
-
-  case 38:
-#line 270 "cc.y"
-    {
-               (yyval.node) = new(OBIT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 39:
-#line 274 "cc.y"
-    {
-               (yyval.node) = new(OBIT, Z, (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 40:
-#line 282 "cc.y"
-    {
-               (yyval.node) = (Z);
-       }
-    break;
-
-  case 42:
-#line 289 "cc.y"
-    {
-               (yyval.node) = new(OIND, (Z), Z);
-               (yyval.node)->garb = simpleg((yyvsp[(2) - (2)].lval));
-       }
-    break;
-
-  case 43:
-#line 294 "cc.y"
-    {
-               (yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z);
-               (yyval.node)->garb = simpleg((yyvsp[(2) - (3)].lval));
-       }
-    break;
-
-  case 46:
-#line 303 "cc.y"
-    {
-               (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
-       }
-    break;
-
-  case 47:
-#line 307 "cc.y"
-    {
-               (yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
-       }
-    break;
-
-  case 48:
-#line 313 "cc.y"
-    {
-               (yyval.node) = new(OFUNC, (Z), Z);
-       }
-    break;
-
-  case 49:
-#line 317 "cc.y"
-    {
-               (yyval.node) = new(OARRAY, (Z), (yyvsp[(2) - (3)].node));
-       }
-    break;
-
-  case 50:
-#line 321 "cc.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-       }
-    break;
-
-  case 52:
-#line 328 "cc.y"
-    {
-               (yyval.node) = new(OINIT, invert((yyvsp[(2) - (3)].node)), Z);
-       }
-    break;
-
-  case 53:
-#line 334 "cc.y"
-    {
-               (yyval.node) = new(OARRAY, (yyvsp[(2) - (3)].node), Z);
-       }
-    break;
-
-  case 54:
-#line 338 "cc.y"
-    {
-               (yyval.node) = new(OELEM, Z, Z);
-               (yyval.node)->sym = (yyvsp[(2) - (2)].sym);
-       }
-    break;
-
-  case 57:
-#line 347 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node));
-       }
-    break;
-
-  case 59:
-#line 352 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 62:
-#line 360 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 63:
-#line 365 "cc.y"
-    {
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 64:
-#line 369 "cc.y"
-    {
-               (yyval.node) = invert((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 66:
-#line 377 "cc.y"
-    {
-               (yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z);
-               (yyval.node)->type = (yyvsp[(1) - (2)].type);
-       }
-    break;
-
-  case 67:
-#line 382 "cc.y"
-    {
-               (yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z);
-               (yyval.node)->type = (yyvsp[(1) - (2)].type);
-       }
-    break;
-
-  case 68:
-#line 387 "cc.y"
-    {
-               (yyval.node) = new(ODOTDOT, Z, Z);
-       }
-    break;
-
-  case 69:
-#line 391 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 70:
-#line 397 "cc.y"
-    {
-               (yyval.node) = invert((yyvsp[(2) - (3)].node));
-       //      if($2 != Z)
-       //              $$ = new(OLIST, $2, $$);
-               if((yyval.node) == Z)
-                       (yyval.node) = new(OLIST, Z, Z);
-       }
-    break;
-
-  case 71:
-#line 406 "cc.y"
-    {
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 72:
-#line 410 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 73:
-#line 414 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 75:
-#line 421 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 76:
-#line 427 "cc.y"
-    {
-               (yyval.node) = new(OCASE, (yyvsp[(2) - (3)].node), Z);
-       }
-    break;
-
-  case 77:
-#line 431 "cc.y"
-    {
-               (yyval.node) = new(OCASE, Z, Z);
-       }
-    break;
-
-  case 78:
-#line 435 "cc.y"
-    {
-               (yyval.node) = new(OLABEL, dcllabel((yyvsp[(1) - (2)].sym), 1), Z);
-       }
-    break;
-
-  case 79:
-#line 441 "cc.y"
-    {
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 81:
-#line 446 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 83:
-#line 453 "cc.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (2)].node);
-       }
-    break;
-
-  case 85:
-#line 459 "cc.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 86:
-#line 463 "cc.y"
-    {
-               (yyval.node) = revertdcl();
-               if((yyval.node))
-                       (yyval.node) = new(OLIST, (yyval.node), (yyvsp[(2) - (2)].node));
-               else
-                       (yyval.node) = (yyvsp[(2) - (2)].node);
-       }
-    break;
-
-  case 87:
-#line 471 "cc.y"
-    {
-               (yyval.node) = new(OIF, (yyvsp[(3) - (5)].node), new(OLIST, (yyvsp[(5) - (5)].node), Z));
-               if((yyvsp[(5) - (5)].node) == Z)
-                       warn((yyvsp[(3) - (5)].node), "empty if body");
-       }
-    break;
-
-  case 88:
-#line 477 "cc.y"
-    {
-               (yyval.node) = new(OIF, (yyvsp[(3) - (7)].node), new(OLIST, (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)));
-               if((yyvsp[(5) - (7)].node) == Z)
-                       warn((yyvsp[(3) - (7)].node), "empty if body");
-               if((yyvsp[(7) - (7)].node) == Z)
-                       warn((yyvsp[(3) - (7)].node), "empty else body");
-       }
-    break;
-
-  case 89:
-#line 484 "cc.y"
-    { markdcl(); }
-    break;
-
-  case 90:
-#line 485 "cc.y"
-    {
-               (yyval.node) = revertdcl();
-               if((yyval.node)){
-                       if((yyvsp[(4) - (10)].node))
-                               (yyvsp[(4) - (10)].node) = new(OLIST, (yyval.node), (yyvsp[(4) - (10)].node));
-                       else
-                               (yyvsp[(4) - (10)].node) = (yyval.node);
-               }
-               (yyval.node) = new(OFOR, new(OLIST, (yyvsp[(6) - (10)].node), new(OLIST, (yyvsp[(4) - (10)].node), (yyvsp[(8) - (10)].node))), (yyvsp[(10) - (10)].node));
-       }
-    break;
-
-  case 91:
-#line 496 "cc.y"
-    {
-               (yyval.node) = new(OWHILE, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
-       }
-    break;
-
-  case 92:
-#line 500 "cc.y"
-    {
-               (yyval.node) = new(ODWHILE, (yyvsp[(5) - (7)].node), (yyvsp[(2) - (7)].node));
-       }
-    break;
-
-  case 93:
-#line 504 "cc.y"
-    {
-               (yyval.node) = new(ORETURN, (yyvsp[(2) - (3)].node), Z);
-               (yyval.node)->type = thisfn->link;
-       }
-    break;
-
-  case 94:
-#line 509 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->vconst = 0;
-               (yyval.node)->type = types[TINT];
-               (yyvsp[(3) - (5)].node) = new(OSUB, (yyval.node), (yyvsp[(3) - (5)].node));
-
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->vconst = 0;
-               (yyval.node)->type = types[TINT];
-               (yyvsp[(3) - (5)].node) = new(OSUB, (yyval.node), (yyvsp[(3) - (5)].node));
-
-               (yyval.node) = new(OSWITCH, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
-       }
-    break;
-
-  case 95:
-#line 523 "cc.y"
-    {
-               (yyval.node) = new(OBREAK, Z, Z);
-       }
-    break;
-
-  case 96:
-#line 527 "cc.y"
-    {
-               (yyval.node) = new(OCONTINUE, Z, Z);
-       }
-    break;
-
-  case 97:
-#line 531 "cc.y"
-    {
-               (yyval.node) = new(OGOTO, dcllabel((yyvsp[(2) - (3)].sym), 0), Z);
-       }
-    break;
-
-  case 98:
-#line 535 "cc.y"
-    {
-               (yyval.node) = new(OUSED, (yyvsp[(3) - (5)].node), Z);
-       }
-    break;
-
-  case 99:
-#line 539 "cc.y"
-    {
-               (yyval.node) = new(OPREFETCH, (yyvsp[(3) - (5)].node), Z);
-       }
-    break;
-
-  case 100:
-#line 543 "cc.y"
-    {
-               (yyval.node) = new(OSET, (yyvsp[(3) - (5)].node), Z);
-       }
-    break;
-
-  case 101:
-#line 548 "cc.y"
-    {
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 103:
-#line 554 "cc.y"
-    {
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 105:
-#line 561 "cc.y"
-    {
-               (yyval.node) = new(OCAST, (yyvsp[(1) - (1)].node), Z);
-               (yyval.node)->type = types[TLONG];
-       }
-    break;
-
-  case 107:
-#line 569 "cc.y"
-    {
-               (yyval.node) = new(OCOMMA, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 109:
-#line 576 "cc.y"
-    {
-               (yyval.node) = new(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 110:
-#line 580 "cc.y"
-    {
-               (yyval.node) = new(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 111:
-#line 584 "cc.y"
-    {
-               (yyval.node) = new(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 112:
-#line 588 "cc.y"
-    {
-               (yyval.node) = new(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 113:
-#line 592 "cc.y"
-    {
-               (yyval.node) = new(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 114:
-#line 596 "cc.y"
-    {
-               (yyval.node) = new(OASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 115:
-#line 600 "cc.y"
-    {
-               (yyval.node) = new(OASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 116:
-#line 604 "cc.y"
-    {
-               (yyval.node) = new(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 117:
-#line 608 "cc.y"
-    {
-               (yyval.node) = new(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 118:
-#line 612 "cc.y"
-    {
-               (yyval.node) = new(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 119:
-#line 616 "cc.y"
-    {
-               (yyval.node) = new(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 120:
-#line 620 "cc.y"
-    {
-               (yyval.node) = new(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 121:
-#line 624 "cc.y"
-    {
-               (yyval.node) = new(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 122:
-#line 628 "cc.y"
-    {
-               (yyval.node) = new(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 123:
-#line 632 "cc.y"
-    {
-               (yyval.node) = new(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 124:
-#line 636 "cc.y"
-    {
-               (yyval.node) = new(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 125:
-#line 640 "cc.y"
-    {
-               (yyval.node) = new(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 126:
-#line 644 "cc.y"
-    {
-               (yyval.node) = new(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 127:
-#line 648 "cc.y"
-    {
-               (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(OAS, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 129:
-#line 656 "cc.y"
-    {
-               (yyval.node) = new(OASADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 130:
-#line 660 "cc.y"
-    {
-               (yyval.node) = new(OASSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 131:
-#line 664 "cc.y"
-    {
-               (yyval.node) = new(OASMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 132:
-#line 668 "cc.y"
-    {
-               (yyval.node) = new(OASDIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 133:
-#line 672 "cc.y"
-    {
-               (yyval.node) = new(OASMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 134:
-#line 676 "cc.y"
-    {
-               (yyval.node) = new(OASASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 135:
-#line 680 "cc.y"
-    {
-               (yyval.node) = new(OASASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 136:
-#line 684 "cc.y"
-    {
-               (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 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));
-               (yyval.node)->type = lastdcl;
-               (yyval.node)->xcast = 1;
-       }
-    break;
-
-  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));
-               (yyval.node)->type = lastdcl;
-       }
-    break;
-
-  case 143:
-#line 715 "cc.y"
-    {
-               (yyval.node) = new(OIND, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 144:
-#line 719 "cc.y"
-    {
-               (yyval.node) = new(OADDR, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 145:
-#line 723 "cc.y"
-    {
-               (yyval.node) = new(OPOS, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 146:
-#line 727 "cc.y"
-    {
-               (yyval.node) = new(ONEG, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 147:
-#line 731 "cc.y"
-    {
-               (yyval.node) = new(ONOT, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 148:
-#line 735 "cc.y"
-    {
-               (yyval.node) = new(OCOM, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 149:
-#line 739 "cc.y"
-    {
-               (yyval.node) = new(OPREINC, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 150:
-#line 743 "cc.y"
-    {
-               (yyval.node) = new(OPREDEC, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 151:
-#line 747 "cc.y"
-    {
-               (yyval.node) = new(OSIZE, (yyvsp[(2) - (2)].node), Z);
-       }
-    break;
-
-  case 152:
-#line 751 "cc.y"
-    {
-               (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 155:
-#line 767 "cc.y"
-    {
-               (yyval.node) = new(OSIGN, Z, Z);
-               dodecl(NODECL, CXXX, (yyvsp[(3) - (5)].type), (yyvsp[(4) - (5)].node));
-               (yyval.node)->type = lastdcl;
-       }
-    break;
-
-  case 156:
-#line 773 "cc.y"
-    {
-               (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), Z);
-               if((yyvsp[(1) - (4)].node)->op == ONAME)
-               if((yyvsp[(1) - (4)].node)->type == T)
-                       dodecl(xdecl, CXXX, types[TINT], (yyval.node));
-               (yyval.node)->right = invert((yyvsp[(3) - (4)].node));
-       }
-    break;
-
-  case 157:
-#line 781 "cc.y"
-    {
-               (yyval.node) = new(OIND, new(OADD, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)), Z);
-       }
-    break;
-
-  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 159:
-#line 790 "cc.y"
-    {
-               (yyval.node) = new(ODOT, (yyvsp[(1) - (3)].node), Z);
-               (yyval.node)->sym = (yyvsp[(3) - (3)].sym);
-       }
-    break;
-
-  case 160:
-#line 795 "cc.y"
-    {
-               (yyval.node) = new(OPOSTINC, (yyvsp[(1) - (2)].node), Z);
-       }
-    break;
-
-  case 161:
-#line 799 "cc.y"
-    {
-               (yyval.node) = new(OPOSTDEC, (yyvsp[(1) - (2)].node), Z);
-       }
-    break;
-
-  case 163:
-#line 804 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TINT];
-               (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 164:
-#line 811 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TLONG];
-               (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 165:
-#line 818 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TUINT];
-               (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 166:
-#line 825 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TULONG];
-               (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 167:
-#line 832 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TDOUBLE];
-               (yyval.node)->fconst = (yyvsp[(1) - (1)].dval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 168:
-#line 839 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TFLOAT];
-               (yyval.node)->fconst = (yyvsp[(1) - (1)].dval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 169:
-#line 846 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TVLONG];
-               (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 170:
-#line 853 "cc.y"
-    {
-               (yyval.node) = new(OCONST, Z, Z);
-               (yyval.node)->type = types[TUVLONG];
-               (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
-               (yyval.node)->cstring = strdup(symb);
-       }
-    break;
-
-  case 173:
-#line 864 "cc.y"
-    {
-               (yyval.node) = new(OSTRING, Z, Z);
-               (yyval.node)->type = typ(TARRAY, types[TCHAR]);
-               (yyval.node)->type->width = (yyvsp[(1) - (1)].sval).l + 1;
-               (yyval.node)->cstring = (yyvsp[(1) - (1)].sval).s;
-               (yyval.node)->sym = symstring;
-               (yyval.node)->etype = TARRAY;
-               (yyval.node)->class = CSTATIC;
-       }
-    break;
-
-  case 174:
-#line 874 "cc.y"
-    {
-               char *s;
-               int n;
-
-               n = (yyvsp[(1) - (2)].node)->type->width - 1;
-               s = alloc(n+(yyvsp[(2) - (2)].sval).l+MAXALIGN);
-
-               memcpy(s, (yyvsp[(1) - (2)].node)->cstring, n);
-               memcpy(s+n, (yyvsp[(2) - (2)].sval).s, (yyvsp[(2) - (2)].sval).l);
-               s[n+(yyvsp[(2) - (2)].sval).l] = 0;
-
-               (yyval.node) = (yyvsp[(1) - (2)].node);
-               (yyval.node)->type->width += (yyvsp[(2) - (2)].sval).l;
-               (yyval.node)->cstring = s;
-       }
-    break;
-
-  case 175:
-#line 892 "cc.y"
-    {
-               (yyval.node) = new(OLSTRING, Z, Z);
-               (yyval.node)->type = typ(TARRAY, types[TRUNE]);
-               (yyval.node)->type->width = (yyvsp[(1) - (1)].sval).l + sizeof(TRune);
-               (yyval.node)->rstring = (TRune*)(yyvsp[(1) - (1)].sval).s;
-               (yyval.node)->sym = symstring;
-               (yyval.node)->etype = TARRAY;
-               (yyval.node)->class = CSTATIC;
-       }
-    break;
-
-  case 176:
-#line 902 "cc.y"
-    {
-               char *s;
-               int n;
-
-               n = (yyvsp[(1) - (2)].node)->type->width - sizeof(TRune);
-               s = alloc(n+(yyvsp[(2) - (2)].sval).l+MAXALIGN);
-
-               memcpy(s, (yyvsp[(1) - (2)].node)->rstring, n);
-               memcpy(s+n, (yyvsp[(2) - (2)].sval).s, (yyvsp[(2) - (2)].sval).l);
-               *(TRune*)(s+n+(yyvsp[(2) - (2)].sval).l) = 0;
-
-               (yyval.node) = (yyvsp[(1) - (2)].node);
-               (yyval.node)->type->width += (yyvsp[(2) - (2)].sval).l;
-               (yyval.node)->rstring = (TRune*)s;
-       }
-    break;
-
-  case 177:
-#line 919 "cc.y"
-    {
-               (yyval.node) = Z;
-       }
-    break;
-
-  case 180:
-#line 927 "cc.y"
-    {
-               (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 181:
-#line 933 "cc.y"
-    {
-               (yyval.tyty).t1 = strf;
-               (yyval.tyty).t2 = strl;
-               (yyval.tyty).t3 = lasttype;
-               (yyval.tyty).c = lastclass;
-               strf = T;
-               strl = T;
-               lastbit = 0;
-               firstbit = 1;
-               lastclass = CXXX;
-               lasttype = T;
-       }
-    break;
-
-  case 182:
-#line 946 "cc.y"
-    {
-               (yyval.type) = strf;
-               strf = (yyvsp[(2) - (4)].tyty).t1;
-               strl = (yyvsp[(2) - (4)].tyty).t2;
-               lasttype = (yyvsp[(2) - (4)].tyty).t3;
-               lastclass = (yyvsp[(2) - (4)].tyty).c;
-       }
-    break;
-
-  case 183:
-#line 955 "cc.y"
-    {
-               lastclass = CXXX;
-               lasttype = types[TINT];
-       }
-    break;
-
-  case 185:
-#line 963 "cc.y"
-    {
-               (yyval.tycl).t = (yyvsp[(1) - (1)].type);
-               (yyval.tycl).c = CXXX;
-       }
-    break;
-
-  case 186:
-#line 968 "cc.y"
-    {
-               (yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
-               (yyval.tycl).c = CXXX;
-       }
-    break;
-
-  case 187:
-#line 973 "cc.y"
-    {
-               (yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
-               (yyval.tycl).c = simplec((yyvsp[(1) - (1)].lval));
-               (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (1)].lval));
-       }
-    break;
-
-  case 188:
-#line 979 "cc.y"
-    {
-               (yyval.tycl).t = (yyvsp[(1) - (2)].type);
-               (yyval.tycl).c = simplec((yyvsp[(2) - (2)].lval));
-               (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(2) - (2)].lval));
-               if((yyvsp[(2) - (2)].lval) & ~BCLASS & ~BGARB)
-                       diag(Z, "duplicate types given: %T and %Q", (yyvsp[(1) - (2)].type), (yyvsp[(2) - (2)].lval));
-       }
-    break;
-
-  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));
-               (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(2) - (2)].lval));
-       }
-    break;
-
-  case 190:
-#line 993 "cc.y"
-    {
-               (yyval.tycl).t = (yyvsp[(2) - (3)].type);
-               (yyval.tycl).c = simplec((yyvsp[(1) - (3)].lval));
-               (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (3)].lval)|(yyvsp[(3) - (3)].lval));
-       }
-    break;
-
-  case 191:
-#line 999 "cc.y"
-    {
-               (yyval.tycl).t = simplet((yyvsp[(2) - (2)].lval));
-               (yyval.tycl).c = simplec((yyvsp[(1) - (2)].lval));
-               (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (2)].lval));
-       }
-    break;
-
-  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));
-               (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (3)].lval)|(yyvsp[(3) - (3)].lval));
-       }
-    break;
-
-  case 193:
-#line 1013 "cc.y"
-    {
-               (yyval.type) = (yyvsp[(1) - (1)].tycl).t;
-               if((yyvsp[(1) - (1)].tycl).c != CXXX)
-                       diag(Z, "illegal combination of class 4: %s", cnames[(yyvsp[(1) - (1)].tycl).c]);
-       }
-    break;
-
-  case 194:
-#line 1021 "cc.y"
-    {
-               lasttype = (yyvsp[(1) - (1)].tycl).t;
-               lastclass = (yyvsp[(1) - (1)].tycl).c;
-       }
-    break;
-
-  case 195:
-#line 1028 "cc.y"
-    {
-               dotag((yyvsp[(2) - (2)].sym), TSTRUCT, 0);
-               (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
-       }
-    break;
-
-  case 196:
-#line 1033 "cc.y"
-    {
-               dotag((yyvsp[(2) - (2)].sym), TSTRUCT, autobn);
-       }
-    break;
-
-  case 197:
-#line 1037 "cc.y"
-    {
-               (yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
-               if((yyval.type)->link != T)
-                       diag(Z, "redeclare tag: %s", (yyvsp[(2) - (4)].sym)->name);
-               (yyval.type)->link = (yyvsp[(4) - (4)].type);
-               sualign((yyval.type));
-       }
-    break;
-
-  case 198:
-#line 1045 "cc.y"
-    {
-               diag(Z, "struct must have tag");
-               taggen++;
-               sprint(symb, "_%d_", taggen);
-               (yyval.type) = dotag(lookup(), TSTRUCT, autobn);
-               (yyval.type)->link = (yyvsp[(2) - (2)].type);
-               sualign((yyval.type));
-       }
-    break;
-
-  case 199:
-#line 1054 "cc.y"
-    {
-               dotag((yyvsp[(2) - (2)].sym), TUNION, 0);
-               (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
-       }
-    break;
-
-  case 200:
-#line 1059 "cc.y"
-    {
-               dotag((yyvsp[(2) - (2)].sym), TUNION, autobn);
-       }
-    break;
-
-  case 201:
-#line 1063 "cc.y"
-    {
-               (yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
-               if((yyval.type)->link != T)
-                       diag(Z, "redeclare tag: %s", (yyvsp[(2) - (4)].sym)->name);
-               (yyval.type)->link = (yyvsp[(4) - (4)].type);
-               sualign((yyval.type));
-       }
-    break;
-
-  case 202:
-#line 1071 "cc.y"
-    {
-               taggen++;
-               sprint(symb, "_%d_", taggen);
-               (yyval.type) = dotag(lookup(), TUNION, autobn);
-               (yyval.type)->link = (yyvsp[(2) - (2)].type);
-               sualign((yyval.type));
-       }
-    break;
-
-  case 203:
-#line 1079 "cc.y"
-    {
-               dotag((yyvsp[(2) - (2)].sym), TENUM, 0);
-               (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
-               if((yyval.type)->link == T)
-                       (yyval.type)->link = types[TINT];
-               (yyval.type) = (yyval.type)->link;
-       }
-    break;
-
-  case 204:
-#line 1087 "cc.y"
-    {
-               dotag((yyvsp[(2) - (2)].sym), TENUM, autobn);
-       }
-    break;
-
-  case 205:
-#line 1091 "cc.y"
-    {
-               en.tenum = T;
-               en.cenum = T;
-       }
-    break;
-
-  case 206:
-#line 1096 "cc.y"
-    {
-               (yyval.type) = (yyvsp[(2) - (7)].sym)->suetag;
-               if((yyval.type)->link != T)
-                       diag(Z, "redeclare tag: %s", (yyvsp[(2) - (7)].sym)->name);
-               if(en.tenum == T) {
-                       diag(Z, "enum type ambiguous: %s", (yyvsp[(2) - (7)].sym)->name);
-                       en.tenum = types[TINT];
-               }
-               (yyval.type)->link = en.tenum;
-               (yyval.type) = en.tenum;
-       }
-    break;
-
-  case 207:
-#line 1108 "cc.y"
-    {
-               en.tenum = T;
-               en.cenum = T;
-       }
-    break;
-
-  case 208:
-#line 1113 "cc.y"
-    {
-               (yyval.type) = en.tenum;
-       }
-    break;
-
-  case 209:
-#line 1117 "cc.y"
-    {
-               (yyval.type) = tcopy((yyvsp[(1) - (1)].sym)->type);
-       }
-    break;
-
-  case 211:
-#line 1124 "cc.y"
-    {
-               (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
-       }
-    break;
-
-  case 212:
-#line 1129 "cc.y"
-    {
-               (yyval.lval) = 0;
-       }
-    break;
-
-  case 213:
-#line 1133 "cc.y"
-    {
-               (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
-       }
-    break;
-
-  case 218:
-#line 1145 "cc.y"
-    {
-               (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
-       }
-    break;
-
-  case 221:
-#line 1155 "cc.y"
-    {
-               doenum((yyvsp[(1) - (1)].sym), Z);
-       }
-    break;
-
-  case 222:
-#line 1159 "cc.y"
-    {
-               doenum((yyvsp[(1) - (3)].sym), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 225:
-#line 1166 "cc.y"
-    { (yyval.lval) = BCHAR; }
-    break;
-
-  case 226:
-#line 1167 "cc.y"
-    { (yyval.lval) = BSHORT; }
-    break;
-
-  case 227:
-#line 1168 "cc.y"
-    { (yyval.lval) = BINT; }
-    break;
-
-  case 228:
-#line 1169 "cc.y"
-    { (yyval.lval) = BLONG; }
-    break;
-
-  case 229:
-#line 1170 "cc.y"
-    { (yyval.lval) = BSIGNED; }
-    break;
-
-  case 230:
-#line 1171 "cc.y"
-    { (yyval.lval) = BUNSIGNED; }
-    break;
-
-  case 231:
-#line 1172 "cc.y"
-    { (yyval.lval) = BFLOAT; }
-    break;
-
-  case 232:
-#line 1173 "cc.y"
-    { (yyval.lval) = BDOUBLE; }
-    break;
-
-  case 233:
-#line 1174 "cc.y"
-    { (yyval.lval) = BVOID; }
-    break;
-
-  case 234:
-#line 1177 "cc.y"
-    { (yyval.lval) = BAUTO; }
-    break;
-
-  case 235:
-#line 1178 "cc.y"
-    { (yyval.lval) = BSTATIC; }
-    break;
-
-  case 236:
-#line 1179 "cc.y"
-    { (yyval.lval) = BEXTERN; }
-    break;
-
-  case 237:
-#line 1180 "cc.y"
-    { (yyval.lval) = BTYPEDEF; }
-    break;
-
-  case 238:
-#line 1181 "cc.y"
-    { (yyval.lval) = BTYPESTR; }
-    break;
-
-  case 239:
-#line 1182 "cc.y"
-    { (yyval.lval) = BREGISTER; }
-    break;
-
-  case 240:
-#line 1183 "cc.y"
-    { (yyval.lval) = 0; }
-    break;
-
-  case 241:
-#line 1186 "cc.y"
-    { (yyval.lval) = BCONSTNT; }
-    break;
-
-  case 242:
-#line 1187 "cc.y"
-    { (yyval.lval) = BVOLATILE; }
-    break;
-
-  case 243:
-#line 1188 "cc.y"
-    { (yyval.lval) = 0; }
-    break;
-
-  case 244:
-#line 1192 "cc.y"
-    {
-               (yyval.node) = new(ONAME, Z, Z);
-               if((yyvsp[(1) - (1)].sym)->class == CLOCAL)
-                       (yyvsp[(1) - (1)].sym) = mkstatic((yyvsp[(1) - (1)].sym));
-               (yyval.node)->sym = (yyvsp[(1) - (1)].sym);
-               (yyval.node)->type = (yyvsp[(1) - (1)].sym)->type;
-               (yyval.node)->etype = TVOID;
-               if((yyval.node)->type != T)
-                       (yyval.node)->etype = (yyval.node)->type->etype;
-               (yyval.node)->xoffset = (yyvsp[(1) - (1)].sym)->offset;
-               (yyval.node)->class = (yyvsp[(1) - (1)].sym)->class;
-               (yyvsp[(1) - (1)].sym)->aused = 1;
-       }
-    break;
-
-  case 245:
-#line 1207 "cc.y"
-    {
-               (yyval.node) = new(ONAME, Z, Z);
-               (yyval.node)->sym = (yyvsp[(1) - (1)].sym);
-               (yyval.node)->type = (yyvsp[(1) - (1)].sym)->type;
-               (yyval.node)->etype = TVOID;
-               if((yyval.node)->type != T)
-                       (yyval.node)->etype = (yyval.node)->type->etype;
-               (yyval.node)->xoffset = (yyvsp[(1) - (1)].sym)->offset;
-               (yyval.node)->class = (yyvsp[(1) - (1)].sym)->class;
-       }
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 3607 "y.tab.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++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.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-       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;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  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);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-#line 1220 "cc.y"
-
-
diff --git a/src/cmd/cc/y.tab.h b/src/cmd/cc/y.tab.h
deleted file mode 100644 (file)
index 32daca9..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* 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 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, 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
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   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
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LORE = 258,
-     LXORE = 259,
-     LANDE = 260,
-     LLSHE = 261,
-     LRSHE = 262,
-     LMDE = 263,
-     LDVE = 264,
-     LMLE = 265,
-     LME = 266,
-     LPE = 267,
-     LOROR = 268,
-     LANDAND = 269,
-     LNE = 270,
-     LEQ = 271,
-     LGE = 272,
-     LLE = 273,
-     LRSH = 274,
-     LLSH = 275,
-     LMG = 276,
-     LPP = 277,
-     LMM = 278,
-     LNAME = 279,
-     LTYPE = 280,
-     LFCONST = 281,
-     LDCONST = 282,
-     LCONST = 283,
-     LLCONST = 284,
-     LUCONST = 285,
-     LULCONST = 286,
-     LVLCONST = 287,
-     LUVLCONST = 288,
-     LSTRING = 289,
-     LLSTRING = 290,
-     LAUTO = 291,
-     LBREAK = 292,
-     LCASE = 293,
-     LCHAR = 294,
-     LCONTINUE = 295,
-     LDEFAULT = 296,
-     LDO = 297,
-     LDOUBLE = 298,
-     LELSE = 299,
-     LEXTERN = 300,
-     LFLOAT = 301,
-     LFOR = 302,
-     LGOTO = 303,
-     LIF = 304,
-     LINT = 305,
-     LLONG = 306,
-     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.  */
-#define LORE 258
-#define LXORE 259
-#define LANDE 260
-#define LLSHE 261
-#define LRSHE 262
-#define LMDE 263
-#define LDVE 264
-#define LMLE 265
-#define LME 266
-#define LPE 267
-#define LOROR 268
-#define LANDAND 269
-#define LNE 270
-#define LEQ 271
-#define LGE 272
-#define LLE 273
-#define LRSH 274
-#define LLSH 275
-#define LMG 276
-#define LPP 277
-#define LMM 278
-#define LNAME 279
-#define LTYPE 280
-#define LFCONST 281
-#define LDCONST 282
-#define LCONST 283
-#define LLCONST 284
-#define LUCONST 285
-#define LULCONST 286
-#define LVLCONST 287
-#define LUVLCONST 288
-#define LSTRING 289
-#define LLSTRING 290
-#define LAUTO 291
-#define LBREAK 292
-#define LCASE 293
-#define LCHAR 294
-#define LCONTINUE 295
-#define LDEFAULT 296
-#define LDO 297
-#define LDOUBLE 298
-#define LELSE 299
-#define LEXTERN 300
-#define LFLOAT 301
-#define LFOR 302
-#define LGOTO 303
-#define LIF 304
-#define LINT 305
-#define LLONG 306
-#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
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 36 "cc.y"
-{
-       Node*   node;
-       Sym*    sym;
-       Type*   type;
-       struct
-       {
-               Type*   t;
-               uchar   c;
-       } tycl;
-       struct
-       {
-               Type*   t1;
-               Type*   t2;
-               Type*   t3;
-               uchar   c;
-       } tyty;
-       struct
-       {
-               char*   s;
-               int32   l;
-       } sval;
-       int32   lval;
-       double  dval;
-       vlong   vval;
-}
-/* Line 1529 of yacc.c.  */
-#line 223 "y.tab.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
index 17b0cdd167019cb2fa2f8f7df040755a6247074c..28ded816d5ba1d7881ecf78ba59edb56a79d16f4 100644 (file)
@@ -130,15 +130,23 @@ func usage() {
 }
 
 var ptrSizeMap = map[string]int64{
-       "386":   4,
-       "amd64": 8,
-       "arm":   4,
+       "386":       4,
+       "amd64":     8,
+       "arm":       4,
+       "ppc64":     8,
+       "ppc64le":   8,
+       "power64":   8,
+       "power64le": 8,
 }
 
 var intSizeMap = map[string]int64{
-       "386":   4,
-       "amd64": 8,
-       "arm":   4,
+       "386":       4,
+       "amd64":     8,
+       "arm":       4,
+       "ppc64":     8,
+       "ppc64le":   8,
+       "power64":   8,
+       "power64le": 8,
 }
 
 var cPrefix string
@@ -147,6 +155,7 @@ 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 dynpackage = flag.String("dynpackage", "main", "set Go package for dynobj output")
 var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
 
 // These flags are for bootstrapping a new Go implementation,
index d92bed9bf014ca9268eb8d970a08c193bd911031..78ecfd3974a0df92534fe76a4334b07176d8eb90 100644 (file)
@@ -13,6 +13,7 @@ import (
        "go/ast"
        "go/printer"
        "go/token"
+       "io"
        "os"
        "sort"
        "strings"
@@ -23,8 +24,15 @@ var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
 // writeDefs creates output files to be compiled by 6g, 6c, and gcc.
 // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
 func (p *Package) writeDefs() {
-       fgo2 := creat(*objDir + "_cgo_gotypes.go")
-       fc := creat(*objDir + "_cgo_defun.c")
+       var fgo2, fc io.Writer
+       f := creat(*objDir + "_cgo_gotypes.go")
+       defer f.Close()
+       fgo2 = f
+       if *gccgo {
+               f := creat(*objDir + "_cgo_defun.c")
+               defer f.Close()
+               fc = f
+       }
        fm := creat(*objDir + "_cgo_main.c")
 
        var gccgoInit bytes.Buffer
@@ -34,7 +42,7 @@ func (p *Package) writeDefs() {
                fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
                if k == "LDFLAGS" && !*gccgo {
                        for _, arg := range v {
-                               fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
+                               fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
                        }
                }
        }
@@ -88,7 +96,6 @@ func (p *Package) writeDefs() {
        if *gccgo {
                fmt.Fprint(fc, p.cPrologGccgo())
        } else {
-               fmt.Fprint(fc, cProlog)
                fmt.Fprint(fgo2, goProlog)
        }
 
@@ -104,42 +111,42 @@ func (p *Package) writeDefs() {
                if !cVars[n.C] {
                        fmt.Fprintf(fm, "extern char %s[];\n", n.C)
                        fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
-
-                       if !*gccgo {
-                               fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
+                       if *gccgo {
+                               fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
+                       } else {
+                               fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
+                               fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
+                               fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
                        }
-
-                       fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
-
                        cVars[n.C] = true
                }
-               var amp string
+
                var node ast.Node
                if n.Kind == "var" {
-                       amp = "&"
                        node = &ast.StarExpr{X: n.Type.Go}
                } else if n.Kind == "fpvar" {
                        node = n.Type.Go
-                       if *gccgo {
-                               amp = "&"
-                       }
                } else {
                        panic(fmt.Errorf("invalid var kind %q", n.Kind))
                }
                if *gccgo {
                        fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
-                       fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
-               } else {
-                       fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
-                       fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
+                       fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
+                       fmt.Fprintf(fc, "\n")
                }
-               fmt.Fprintf(fc, "\n")
 
                fmt.Fprintf(fgo2, "var %s ", n.Mangle)
                conf.Fprint(fgo2, fset, node)
+               if !*gccgo {
+                       fmt.Fprintf(fgo2, " = (")
+                       conf.Fprint(fgo2, fset, node)
+                       fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
+               }
                fmt.Fprintf(fgo2, "\n")
        }
-       fmt.Fprintf(fc, "\n")
+       if *gccgo {
+               fmt.Fprintf(fc, "\n")
+       }
 
        for _, key := range nameKeys(p.Name) {
                n := p.Name[key]
@@ -169,9 +176,6 @@ func (p *Package) writeDefs() {
                fmt.Fprint(fc, init)
                fmt.Fprintln(fc, "}")
        }
-
-       fgo2.Close()
-       fc.Close()
 }
 
 func dynimport(obj string) {
@@ -184,13 +188,15 @@ func dynimport(obj string) {
                stdout = f
        }
 
+       fmt.Fprintf(stdout, "package %s\n", *dynpackage)
+
        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]))
+                                       fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
                                }
                        }
                }
@@ -203,14 +209,14 @@ func dynimport(obj string) {
                        if s.Version != "" {
                                targ += "#" + s.Version
                        }
-                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
+                       fmt.Fprintf(stdout, "//go: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 cgo_import_dynamic _ _ %q\n", l)
+                       fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
                }
                return
        }
@@ -224,14 +230,14 @@ func dynimport(obj string) {
                        if len(s) > 0 && s[0] == '_' {
                                s = s[1:]
                        }
-                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
+                       fmt.Fprintf(stdout, "//go: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 cgo_import_dynamic _ _ %q\n", l)
+                       fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
                }
                return
        }
@@ -244,7 +250,7 @@ func dynimport(obj string) {
                for _, s := range sym {
                        ss := strings.Split(s, ":")
                        name := strings.Split(ss[0], "@")[0]
-                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
+                       fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
                }
                return
        }
@@ -304,7 +310,7 @@ func (p *Package) structType(n *Name) (string, int64) {
        return buf.String(), off
 }
 
-func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
+func (p *Package) writeDefsFunc(fc, fgo2 io.Writer, n *Name) {
        name := n.Go
        gtype := n.FuncType.Go
        void := gtype.Results == nil || len(gtype.Results.List) == 0
@@ -397,10 +403,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
        }
 
        // C wrapper calls into gcc, passing a pointer to the argument frame.
-       fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
-       fmt.Fprintf(fc, "void %s(void*);\n", cname)
-       fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
-       fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
+       fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
+       fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
+       fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
+       fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
 
        nret := 0
        if !void {
@@ -412,7 +418,6 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
        }
 
        fmt.Fprint(fgo2, "\n")
-       fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
        conf.Fprint(fgo2, fset, d)
        fmt.Fprint(fgo2, " {\n")
 
@@ -626,7 +631,7 @@ func (p *Package) packedAttribute() string {
 
 // Write out the various stubs we need to support functions exported
 // from Go so that they are callable from C.
-func (p *Package) writeExports(fgo2, fc, fm *os.File) {
+func (p *Package) writeExports(fgo2, fc, fm io.Writer) {
        fgcc := creat(*objDir + "_cgo_export.c")
        fgcch := creat(*objDir + "_cgo_export.h")
 
@@ -763,15 +768,15 @@ 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 cgo_export_dynamic %s\n", goname)
-               fmt.Fprintf(fc, "extern void Â·%s();\n\n", goname)
-               fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
-               fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
-               fmt.Fprintf(fc, "void\n")
-               fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
-               fmt.Fprintf(fc, "{\n")
-               fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
-               fmt.Fprintf(fc, "}\n")
+               fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
+               fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
+               fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
+               fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
+               fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
+               fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
+               // The indirect here is converting from a Go function pointer to a C function pointer.
+               fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
+               fmt.Fprintf(fgo2, "}\n")
 
                fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
 
@@ -817,7 +822,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 }
 
 // Write out the C header allowing C code to call exported gccgo functions.
-func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
+func (p *Package) writeGccgoExports(fgo2, fc, fm io.Writer) {
        fgcc := creat(*objDir + "_cgo_export.c")
        fgcch := creat(*objDir + "_cgo_export.h")
 
@@ -1164,60 +1169,39 @@ char *CString(_GoString_);
 void *_CMalloc(size_t);
 `
 
-const cProlog = `
-#include "runtime.h"
-#include "cgocall.h"
-#include "textflag.h"
-
-#pragma dataflag NOPTR
-static void *cgocall_errno = runtime·cgocall_errno;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
-
-#pragma dataflag NOPTR
-static void *runtime_gostring = runtime·gostring;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gostring = &runtime_gostring;
-
-#pragma dataflag NOPTR
-static void *runtime_gostringn = runtime·gostringn;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gostringn = &runtime_gostringn;
-
-#pragma dataflag NOPTR
-static void *runtime_gobytes = runtime·gobytes;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gobytes = &runtime_gobytes;
-
-#pragma dataflag NOPTR
-static void *runtime_cmalloc = runtime·cmalloc;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
-
-void Â·_Cerrno(void*, int32);
-`
-
 const goProlog = `
-var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
-var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
+//go:linkname _cgo_runtime_cgocall_errno runtime.cgocall_errno
+func _cgo_runtime_cgocall_errno(unsafe.Pointer, uintptr) int32
+
+//go:linkname _cgo_runtime_cmalloc runtime.cmalloc
+func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
+
+//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
+func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
 `
 
 const goStringDef = `
-var _cgo_runtime_gostring func(*_Ctype_char) string
+//go:linkname _cgo_runtime_gostring runtime.gostring
+func _cgo_runtime_gostring(*_Ctype_char) string
+
 func _Cfunc_GoString(p *_Ctype_char) string {
        return _cgo_runtime_gostring(p)
 }
 `
 
 const goStringNDef = `
-var _cgo_runtime_gostringn func(*_Ctype_char, int) string
+//go:linkname _cgo_runtime_gostringn runtime.gostringn
+func _cgo_runtime_gostringn(*_Ctype_char, int) string
+
 func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
        return _cgo_runtime_gostringn(p, int(l))
 }
 `
 
 const goBytesDef = `
-var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
+//go:linkname _cgo_runtime_gobytes runtime.gobytes
+func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
+
 func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
        return _cgo_runtime_gobytes(p, int(l))
 }
index d638ae4ebedb407714307f3b5f4bc04225f7b42d..bfb3d15b826b9f2799106cb3accafe4de9d5c70a 100644 (file)
@@ -39,7 +39,7 @@ static void dopack(char*, char*, char**, int);
 static char *findgoversion(void);
 
 // The known architecture letters.
-static char *gochars = "5668";
+static char *gochars = "566899";
 
 // The known architectures.
 static char *okgoarch[] = {
@@ -48,6 +48,8 @@ static char *okgoarch[] = {
        "amd64",
        "amd64p32",
        "386",
+       "power64",
+       "power64le",
 };
 
 // The known operating systems.
@@ -344,6 +346,7 @@ static char *oldtool[] = {
        "5a", "5c", "5g", "5l",
        "6a", "6c", "6g", "6l",
        "8a", "8c", "8g", "8l",
+       "9a", "9c", "9g", "9l",
        "6cov",
        "6nm",
        "6prof",
@@ -521,10 +524,7 @@ static struct {
                "anames5.c",
                "anames6.c",
                "anames8.c",
-       }},
-       {"cmd/cc", {
-               "-pgen.c",
-               "-pswt.c",
+               "anames9.c",
        }},
        {"cmd/gc", {
                "-cplx.c",
@@ -534,21 +534,6 @@ static struct {
                "-y1.tab.c",  // makefile dreg
                "opnames.h",
        }},
-       {"cmd/5c", {
-               "../cc/pgen.c",
-               "../cc/pswt.c",
-               "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
-       }},
-       {"cmd/6c", {
-               "../cc/pgen.c",
-               "../cc/pswt.c",
-               "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
-       }},
-       {"cmd/8c", {
-               "../cc/pgen.c",
-               "../cc/pswt.c",
-               "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
-       }},
        {"cmd/5g", {
                "../gc/cplx.c",
                "../gc/pgen.c",
@@ -573,6 +558,14 @@ static struct {
                "../gc/popt.h",
                "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
        }},
+       {"cmd/9g", {
+               "../gc/cplx.c",
+               "../gc/pgen.c",
+               "../gc/plive.c",
+               "../gc/popt.c",
+               "../gc/popt.h",
+               "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
+       }},
        {"cmd/5l", {
                "../ld/*",
        }},
@@ -582,6 +575,9 @@ static struct {
        {"cmd/8l", {
                "../ld/*",
        }},
+       {"cmd/9l", {
+               "../ld/*",
+       }},
        {"cmd/go", {
                "zdefaultcc.go",
        }},
@@ -591,12 +587,10 @@ static struct {
                "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/lib9.a",
        }},
        {"runtime", {
-               "zaexperiment.h", // must sort above zasm
-               "zasm_$GOOS_$GOARCH.h",
+               "zaexperiment.h",
                "zsys_$GOOS_$GOARCH.s",
                "zgoarch_$GOARCH.go",
                "zgoos_$GOOS.go",
-               "zruntime_defs_$GOOS_$GOARCH.go",
                "zversion.go",
        }},
 };
@@ -618,12 +612,9 @@ static struct {
        {"anames5.c", mkanames},
        {"anames6.c", mkanames},
        {"anames8.c", mkanames},
-       {"zasm_", mkzasm},
+       {"anames9.c", mkanames},
        {"zdefaultcc.go", mkzdefaultcc},
        {"zsys_", mkzsys},
-       {"zgoarch_", mkzgoarch},
-       {"zgoos_", mkzgoos},
-       {"zruntime_defs_", mkzruntimedefs},
        {"zversion.go", mkzversion},
        {"zaexperiment.h", mkzexperiment},
 
@@ -638,7 +629,7 @@ install(char *dir)
 {
        char *name, *p, *elem, *prefix, *exe;
        bool islib, ispkg, isgo, stale, ispackcmd;
-       Buf b, b1, path, final_path, final_name;
+       Buf b, b1, path, final_path, final_name, archive;
        Vec compile, files, link, go, missing, clean, lib, extra;
        Time ttarg, t;
        int i, j, k, n, doclean, targ;
@@ -655,6 +646,7 @@ install(char *dir)
        binit(&path);
        binit(&final_path);
        binit(&final_name);
+       binit(&archive);
        vinit(&compile);
        vinit(&files);
        vinit(&link);
@@ -698,7 +690,7 @@ install(char *dir)
                splitfields(&ldargs, bstr(&b));
        }
 
-       islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
+       islib = hasprefix(dir, "lib") || streq(dir, "cmd/gc");
        ispkg = !islib && !hasprefix(dir, "cmd/");
        isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
 
@@ -877,17 +869,6 @@ install(char *dir)
 
        // For package runtime, copy some files into the work space.
        if(streq(dir, "runtime")) {
-               copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir),
-                       bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
-               copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
-                       bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
-               p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
-               if(isfile(p))
-                       copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
-               copyfile(bpathf(&b, "%s/os_GOOS.h", workdir),
-                       bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
-               copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir),
-                       bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
                copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
                        bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
                copyfile(bpathf(&b, "%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch),
@@ -921,14 +902,6 @@ install(char *dir)
        built:;
        }
 
-       // One more copy for package runtime.
-       // The last batch was required for the generators.
-       // This one is generated.
-       if(streq(dir, "runtime")) {
-               copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
-                       bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
-       }
-
        if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
                // We've generated the right files; the go command can do the build.
                if(vflag > 1)
@@ -936,6 +909,42 @@ install(char *dir)
                goto nobuild;
        }
 
+       if(isgo) {
+               // The next loop will compile individual non-Go files.
+               // Hand the Go files to the compiler en masse.
+               // For package runtime, this writes go_asm.h, which
+               // the assembly files will need.
+               vreset(&compile);
+               vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
+
+               bpathf(&b, "%s/_go_.a", workdir);
+               vadd(&compile, "-pack");
+               vadd(&compile, "-o");
+               vadd(&compile, bstr(&b));
+               vadd(&clean, bstr(&b));
+               if(!ispackcmd)
+                       vadd(&link, bstr(&b));
+               else
+                       bwriteb(&archive, &b);
+
+               vadd(&compile, "-p");
+               if(hasprefix(dir, "cmd/"))
+                       vadd(&compile, "main");
+               else
+                       vadd(&compile, dir);
+
+               if(streq(dir, "runtime")) {
+                       vadd(&compile, "-+");
+                       vadd(&compile, "-asmhdr");
+                       bpathf(&b1, "%s/go_asm.h", workdir);
+                       vadd(&compile, bstr(&b1));
+               }
+
+               vcopy(&compile, go.p, go.len);
+
+               runv(nil, bstr(&path), CheckExit, &compile);
+       }
+
        // Compile the files.
        for(i=0; i<files.len; i++) {
                if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
@@ -1049,38 +1058,10 @@ install(char *dir)
        }
        bgwait();
 
-       if(isgo) {
-               // The last loop was compiling individual files.
-               // Hand the Go files to the compiler en masse.
-               vreset(&compile);
-               vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
-
-               bpathf(&b, "%s/_go_.a", workdir);
-               vadd(&compile, "-pack");
-               vadd(&compile, "-o");
-               vadd(&compile, bstr(&b));
-               vadd(&clean, bstr(&b));
-               if(!ispackcmd)
-                       vadd(&link, bstr(&b));
-
-               vadd(&compile, "-p");
-               if(hasprefix(dir, "pkg/"))
-                       vadd(&compile, dir+4);
-               else
-                       vadd(&compile, "main");
-
-               if(streq(dir, "runtime"))
-                       vadd(&compile, "-+");
-
-               vcopy(&compile, go.p, go.len);
-
-               runv(nil, bstr(&path), CheckExit, &compile);
-
-               if(ispackcmd) {
-                       xremove(link.p[targ]);
-                       dopack(link.p[targ], bstr(&b), &link.p[targ+1], link.len - (targ+1));
-                       goto nobuild;
-               }
+       if(isgo && ispackcmd) {
+               xremove(link.p[targ]);
+               dopack(link.p[targ], bstr(&archive), &link.p[targ+1], link.len - (targ+1));
+               goto nobuild;
        }
 
        if(!islib && !isgo) {
@@ -1094,17 +1075,7 @@ install(char *dir)
        xremove(link.p[targ]);
 
        runv(nil, nil, CheckExit, &link);
-
 nobuild:
-       // In package runtime, we install runtime.h and cgocall.h too,
-       // for use by cgo compilation.
-       if(streq(dir, "runtime")) {
-               copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
-                       bpathf(&b1, "%s/src/runtime/cgocall.h", goroot), 0);
-               copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
-                       bpathf(&b1, "%s/src/runtime/runtime.h", goroot), 0);
-       }
-
 
 out:
        for(i=0; i<clean.len; i++)
@@ -1113,6 +1084,7 @@ out:
        bfree(&b);
        bfree(&b1);
        bfree(&path);
+       bfree(&archive);
        vfree(&compile);
        vfree(&files);
        vfree(&link);
@@ -1156,12 +1128,26 @@ shouldbuild(char *file, char *dir)
        
        // Check file name for GOOS or GOARCH.
        name = lastelem(file);
-       for(i=0; i<nelem(okgoos); i++)
-               if(contains(name, okgoos[i]) && !streq(okgoos[i], goos))
+       for(i=0; i<nelem(okgoos); i++) {
+               if(streq(okgoos[i], goos))
+                       continue;
+               p = xstrstr(name, okgoos[i]);
+               if(p == nil)
+                       continue;
+               p += xstrlen(okgoos[i]);
+               if(*p == '.' || *p == '_' || *p == '\0')
                        return 0;
-       for(i=0; i<nelem(okgoarch); i++)
-               if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch))
+       }
+       for(i=0; i<nelem(okgoarch); i++) {
+               if(streq(okgoarch[i], goarch))
+                       continue;
+               p = xstrstr(name, okgoarch[i]);
+               if(p == nil)
+                       continue;
+               p += xstrlen(okgoarch[i]);
+               if(*p == '.' || *p == '_' || *p == '\0')
                        return 0;
+       }
 
        // Omit test files.
        if(contains(name, "_test"))
@@ -1286,11 +1272,9 @@ static char *buildorder[] = {
        "libbio",
        "liblink",
 
-       "cmd/cc",  // must be before c
        "cmd/gc",  // must be before g
-       "cmd/%sl",  // must be before a, c, g
+       "cmd/%sl",  // must be before a, g
        "cmd/%sa",
-       "cmd/%sc",
        "cmd/%sg",
 
        // The dependency order here was copied from a buildscript
@@ -1347,18 +1331,17 @@ static char *buildorder[] = {
 static char *cleantab[] = {
        // Commands and C libraries.
        "cmd/5a",
-       "cmd/5c",
        "cmd/5g",
        "cmd/5l",
        "cmd/6a",
-       "cmd/6c",
        "cmd/6g",
        "cmd/6l",
        "cmd/8a",
-       "cmd/8c",
        "cmd/8g",
        "cmd/8l",
-       "cmd/cc",
+       "cmd/9a",
+       "cmd/9g",
+       "cmd/9l",
        "cmd/gc",
        "cmd/go",       
        "lib9",
@@ -1434,12 +1417,13 @@ clean(void)
                        xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
        }
 
-       // remove src/runtime/z* unconditionally
+       // remove src/runtime/z* unconditionally,
+       // except leave zgoos and zgoarch, now maintained with go generate.
        vreset(&dir);
        bpathf(&path, "%s/src/runtime", goroot);
        xreaddir(&dir, bstr(&path));
        for(j=0; j<dir.len; j++) {
-               if(hasprefix(dir.p[j], "z"))
+               if(hasprefix(dir.p[j], "z") && !hasprefix(dir.p[j], "zg"))
                        xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
        }
 
index 66adf6857c707fc181eadb8add296b63cd4b0ad7..64434d51e16852112ee26aa63a503a0b3fa7bdaf 100644 (file)
@@ -63,22 +63,36 @@ gcopnames(char *dir, char *file)
        vfree(&fields);
 }
 
-// mkanames reads [568].out.h and writes anames[568].c
+static int
+xatoi(char *s, char **end)
+{
+       int val = 0;
+       for(; *s && *s >= '0' && *s <= '9'; ++s)
+               val = val * 10 + (*s - '0');
+       *end = s;
+       return val;
+}
+
+// mkanames reads [5689].out.h and writes anames[5689].c
 // The format is much the same as the Go opcodes above.
-// it also writes out cnames array for C_* constants.
+// It also writes out cnames array for C_* constants and the dnames
+// array for D_* constants.
 void
 mkanames(char *dir, char *file)
 {
-       int i, j, ch;
+       int i, j, ch, n, unknown;
        Buf in, b, out, out2;
        Vec lines;
-       char *p;
+       char *p, *p2;
+       Vec dnames[128];
 
        binit(&b);
        binit(&in);
        binit(&out);
        binit(&out2);
        vinit(&lines);
+       for(i=0; i<nelem(dnames); i++)
+               vinit(&dnames[i]);
 
        ch = file[xstrlen(file)-3];
        bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
@@ -87,10 +101,12 @@ mkanames(char *dir, char *file)
        
        // Include link.h so that the extern declaration there is
        // checked against the non-extern declaration we are generating.
+       bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
        bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
        bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
        bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
        bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
+       bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
        bwritestr(&out, bprintf(&b, "\n"));
 
        bwritestr(&out, bprintf(&b, "char*      anames%c[] = {\n", ch));
@@ -127,6 +143,69 @@ mkanames(char *dir, char *file)
        if(j>0)
                bwriteb(&out, &out2);
 
+       j=unknown=0;
+       n=-1;
+       for(i=0; i<lines.len; i++) {
+               if(hasprefix(lines.p[i], "\tD_")) {
+                       p = xstrstr(lines.p[i], ",");
+                       if(p)
+                               *p = '\0';
+                       p = xstrstr(lines.p[i], "\n");
+                       if(p)
+                               *p = '\0';
+
+                       // Parse explicit value, if any
+                       p = xstrstr(lines.p[i], "=");
+                       if(p) {
+                               // Skip space after '='
+                               p2 = p + 1;
+                               while(*p2 == ' ' || *p2 == '\t')
+                                       p2++;
+                               n = xatoi(p2, &p2);
+                               // We can't do anything about
+                               // non-numeric values or anything that
+                               // follows
+                               while(*p2 == ' ' || *p2 == '\t')
+                                       p2++;
+                               if(*p2 != 0) {
+                                       unknown = 1;
+                                       continue;
+                               }
+                               // Truncate space before '='
+                               while(*(p-1) == ' ' || *(p-1) == '\t')
+                                       p--;
+                               *p = '\0';
+                               unknown = 0;
+                       } else {
+                               n++;
+                       }
+
+                       if(unknown || n >= nelem(dnames))
+                               continue;
+
+                       p = lines.p[i] + 3;
+                       if(xstrcmp(p, "LAST") == 0)
+                               continue;
+                       vadd(&dnames[n], p);
+                       j++;
+               }
+       }
+       if(j>0){
+               bwritestr(&out, bprintf(&b, "char*      dnames%c[D_LAST] = {\n", ch));
+               for(i=0; i<nelem(dnames); i++) {
+                       if(dnames[i].len == 0)
+                               continue;
+                       bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
+                       for(j=0; j<dnames[i].len; j++) {
+                               if(j != 0)
+                                       bwritestr(&out, "/");
+                               bwritestr(&out, dnames[i].p[j]);
+                       }
+                       bwritestr(&out, "\",\n");
+               }
+               bwritestr(&out, "};\n");
+       }
+
        writefile(&out, file, 0);
 
        bfree(&b);
@@ -134,4 +213,6 @@ mkanames(char *dir, char *file)
        bfree(&out);
        bfree(&out2);
        vfree(&lines);
+       for(i=0; i<nelem(dnames); i++)
+               vfree(&dnames[i]);
 }
index bb774e05fcf429a2aabcbe512de470647e82fd74..38e99e11628fcd45d8d74b549365a9da93006d1e 100644 (file)
@@ -67,227 +67,8 @@ mkzexperiment(char *dir, char *file)
        bfree(&exp);
 }
 
-// mkzgoarch writes zgoarch_$GOARCH.go:
-//
-//     package runtime
-//     const theGoarch = <goarch>
-//
-void
-mkzgoarch(char *dir, char *file)
-{
-       Buf b, out;
-
-       USED(dir);
-       
-       binit(&b);
-       binit(&out);
-       
-       bwritestr(&out, bprintf(&b,
-               "// auto generated by go tool dist\n"
-               "\n"
-               "package runtime\n"
-               "\n"
-               "const theGoarch = `%s`\n", goarch));
-
-       writefile(&out, file, 0);
-       
-       bfree(&b);
-       bfree(&out);
-}
-
-// mkzgoos writes zgoos_$GOOS.go:
-//
-//     package runtime
-//     const theGoos = <goos>
-//
-void
-mkzgoos(char *dir, char *file)
-{
-       Buf b, out;
-
-       USED(dir);
-       
-       binit(&b);
-       binit(&out);
-
-       bwritestr(&out, "// auto generated by go tool dist\n\n");
-
-       if(streq(goos, "linux")) {
-               bwritestr(&out, "// +build !android\n\n");
-       }
-       
-       bwritestr(&out, bprintf(&b,
-               "package runtime\n"
-               "\n"
-               "const theGoos = `%s`\n", goos));
-
-       writefile(&out, file, 0);
-       
-       bfree(&b);
-       bfree(&out);
-}
-
-static struct {
-       char *goarch;
-       char *goos;
-       char *hdr;
-} zasmhdr[] = {
-       {"386", "",
-               "#define        get_tls(r)      MOVL TLS, r\n"
-               "#define        g(r)    0(r)(TLS*1)\n"
-       },
-       {"amd64p32", "",
-               "#define        get_tls(r)      MOVL TLS, r\n"
-               "#define        g(r)    0(r)(TLS*1)\n"
-       },
-       {"amd64", "",
-               "#define        get_tls(r)      MOVQ TLS, r\n"
-               "#define        g(r)    0(r)(TLS*1)\n"
-       },      
-
-       {"arm", "",
-       "#define        LR      R14\n"
-       },
-};
-
 #define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
 
-// mkzasm writes zasm_$GOOS_$GOARCH.h,
-// which contains struct offsets for use by
-// assembly files.  It also writes a copy to the work space
-// under the name zasm_GOOS_GOARCH.h (no expansion).
-// 
-void
-mkzasm(char *dir, char *file)
-{
-       int i, n;
-       char *aggr, *p;
-       Buf in, b, b1, out, exp;
-       Vec argv, lines, fields;
-
-       binit(&in);
-       binit(&b);
-       binit(&b1);
-       binit(&out);
-       binit(&exp);
-       vinit(&argv);
-       vinit(&lines);
-       vinit(&fields);
-       
-       bwritestr(&out, "// auto generated by go tool dist\n\n");
-       if(streq(goos, "linux")) {
-               bwritestr(&out, "// +build !android\n\n");
-       }
-       
-       for(i=0; i<nelem(zasmhdr); i++) {
-               if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
-                       bwritestr(&out, zasmhdr[i].hdr);
-                       goto ok;
-               }
-       }
-       fatal("unknown $GOOS/$GOARCH in mkzasm");
-ok:
-
-       copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
-               bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
-
-       // Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
-       // to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to
-       // report compilation failures (the -o redirects all messages, unfortunately).
-       vreset(&argv);
-       vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
-       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, "-I");
-       vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
-       vadd(&argv, "-n");
-       vadd(&argv, "-a");
-       vadd(&argv, "-o");
-       vadd(&argv, bpathf(&b, "%s/proc.acid", workdir));
-       vadd(&argv, "proc.c");
-       runv(nil, dir, CheckExit, &argv);
-       readfile(&in, bpathf(&b, "%s/proc.acid", workdir));
-       
-       // Convert input like
-       //      aggr G
-       //      {
-       //              Gobuf 24 sched;
-       //              'Y' 48 stack0;
-       //      }
-       //      StackMin = 128;
-       // into output like
-       //      #define g_sched 24
-       //      #define g_stack0 48
-       //      #define const_StackMin 128
-       aggr = nil;
-       splitlines(&lines, bstr(&in));
-       for(i=0; i<lines.len; i++) {
-               splitfields(&fields, lines.p[i]);
-               if(fields.len == 2 && streq(fields.p[0], "aggr")) {
-                       if(streq(fields.p[1], "G"))
-                               aggr = "g";
-                       else if(streq(fields.p[1], "M"))
-                               aggr = "m";
-                       else if(streq(fields.p[1], "P"))
-                               aggr = "p";
-                       else if(streq(fields.p[1], "Gobuf"))
-                               aggr = "gobuf";
-                       else if(streq(fields.p[1], "LibCall"))
-                               aggr = "libcall";
-                       else if(streq(fields.p[1], "WinCallbackContext"))
-                               aggr = "cbctxt";
-                       else if(streq(fields.p[1], "SEH"))
-                               aggr = "seh";
-                       else if(streq(fields.p[1], "Alg"))
-                               aggr = "alg";
-                       else if(streq(fields.p[1], "Panic"))
-                               aggr = "panic";
-                       else if(streq(fields.p[1], "Stack"))
-                               aggr = "stack";
-               }
-               if(hasprefix(lines.p[i], "}"))
-                       aggr = nil;
-               if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
-                       n = fields.len;
-                       p = fields.p[n-1];
-                       if(p[xstrlen(p)-1] == ';')
-                               p[xstrlen(p)-1] = '\0';
-                       bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
-               }
-               if(fields.len == 3 && streq(fields.p[1], "=")) { // generated from enumerated constants
-                       p = fields.p[2];
-                       if(p[xstrlen(p)-1] == ';')
-                               p[xstrlen(p)-1] = '\0';
-                       bwritestr(&out, bprintf(&b, "#define const_%s %s\n", fields.p[0], p));
-               }
-       }
-
-       // Some #defines that are used for .c files.
-       if(streq(goos, "windows")) {
-               bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB));
-       }
-       
-       xgetenv(&exp, "GOEXPERIMENT");
-       bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
-       
-       // Write both to file and to workdir/zasm_GOOS_GOARCH.h.
-       writefile(&out, file, 0);
-       writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);
-
-       bfree(&in);
-       bfree(&b);
-       bfree(&b1);
-       bfree(&out);
-       bfree(&exp);
-       vfree(&argv);
-       vfree(&lines);
-       vfree(&fields);
-}
-
 // mkzsys writes zsys_$GOOS_$GOARCH.s,
 // which contains arch or os specific asm code.
 // 
@@ -326,143 +107,3 @@ mkzsys(char *dir, char *file)
        
        bfree(&out);
 }
-
-static char *runtimedefs[] = {
-       "defs.c",
-       "malloc.c",
-       "mcache.c",
-       "mgc0.c",
-       "proc.c",
-       "parfor.c",
-       "stack.c",
-};
-
-// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
-// which contains Go struct definitions equivalent to the C ones.
-// Mostly we just write the output of 6c -q to the file.
-// However, we run it on multiple files, so we have to delete
-// the duplicated definitions, and we don't care about the funcs,
-// so we delete those too.
-// 
-void
-mkzruntimedefs(char *dir, char *file)
-{
-       int i, skip;
-       char *p;
-       Buf in, b, b1, out;
-       Vec argv, lines, fields, seen;
-       
-       binit(&in);
-       binit(&b);
-       binit(&b1);
-       binit(&out);
-       vinit(&argv);
-       vinit(&lines);
-       vinit(&fields);
-       vinit(&seen);
-       
-       bwritestr(&out, "// auto generated by go tool dist\n"
-               "\n");
-
-       if(streq(goos, "linux")) {
-               bwritestr(&out, "// +build !android\n\n");
-       }
-       
-       bwritestr(&out,
-               "package runtime\n"
-               "import \"unsafe\"\n"
-               "var _ unsafe.Pointer\n"
-               "\n"
-       );
-
-       // Do not emit definitions for these.
-       vadd(&seen, "true");
-       vadd(&seen, "false");
-       vadd(&seen, "raceenabled");
-       vadd(&seen, "allgs");
-       
-       // Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
-       // on each of the runtimedefs C files.
-       vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
-       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, "-I");
-       vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
-       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(nil, dir, CheckExit, &argv);
-               readfile(&b, bpathf(&b1, "%s/runtimedefs", workdir));
-               bwriteb(&in, &b);
-       }
-       argv.p[argv.len-1] = p;
-               
-       // Process the aggregate output.
-       skip = 0;
-       splitlines(&lines, bstr(&in));
-       for(i=0; i<lines.len; i++) {
-               p = lines.p[i];
-               // Drop comment and func lines.
-               if(hasprefix(p, "//") || hasprefix(p, "func"))
-                       continue;
-               
-               // Note beginning of type or var decl, which can be multiline.
-               // Remove duplicates.  The linear check of seen here makes the
-               // whole processing quadratic in aggregate, but there are only
-               // about 100 declarations, so this is okay (and simple).
-               if(hasprefix(p, "type ") || hasprefix(p, "var ") || hasprefix(p, "const ")) {
-                       splitfields(&fields, p);
-                       if(fields.len < 2)
-                               continue;
-                       if(find(fields.p[1], seen.p, seen.len) >= 0) {
-                               if(streq(fields.p[fields.len-1], "{"))
-                                       skip = 1;  // skip until }
-                               continue;
-                       }
-                       vadd(&seen, fields.p[1]);
-               }
-
-               // Const lines are printed in original case (usually upper). Add a leading _ as needed.
-               if(hasprefix(p, "const ")) {
-                       if('A' <= p[6] && p[6] <= 'Z')
-                               bwritestr(&out, "const _");
-                       else
-                               bwritestr(&out, "const ");
-                       bwritestr(&out, p+6);
-                       continue;
-               }
-
-               if(skip) {
-                       if(hasprefix(p, "}"))
-                               skip = 0;
-                       continue;
-               }
-               
-               bwritestr(&out, p);
-       }
-
-       // Some windows specific const.
-       if(streq(goos, "windows")) {
-               bwritestr(&out, bprintf(&b, "const cb_max = %d\n", MAXWINCB));
-       }
-       
-       writefile(&out, file, 0);
-
-       bfree(&in);
-       bfree(&b);
-       bfree(&b1);
-       bfree(&out);
-       vfree(&argv);
-       vfree(&lines);
-       vfree(&fields);
-       vfree(&seen);
-}
index 4a78684b44ad5cd46da1bcecf2214ebeab299767..893ed5cdd2c6d42ab2fd9636466190d0b35278f6 100644 (file)
@@ -708,6 +708,10 @@ main(int argc, char **argv)
                        gohostarch = "386";
                else if(contains(u.machine, "arm"))
                        gohostarch = "arm";
+               else if(contains(u.machine, "ppc64le"))
+                       gohostarch = "power64le";
+               else if(contains(u.machine, "ppc64"))
+                       gohostarch = "power64";
                else
                        fatal("unknown architecture: %s", u.machine);
        }
index 2e79f6f1de3f6b467cadd22961bb9125db57ce21..fe9a168dcd17bb81aa0733084a4f9b706943a269 100644 (file)
@@ -95,11 +95,11 @@ int
 bnum(Bits a)
 {
        int i;
-       int32 b;
+       uint64 b;
 
        for(i=0; i<BITS; i++)
                if(b = a.b[i])
-                       return 32*i + bitno(b);
+                       return 64*i + bitno(b);
        fatal("bad in bnum");
        return 0;
 }
@@ -110,27 +110,35 @@ blsh(uint n)
        Bits c;
 
        c = zbits;
-       c.b[n/32] = 1L << (n%32);
+       c.b[n/64] = 1LL << (n%64);
        return c;
 }
 
-/*
 int
-bset(Bits a, uint n)
+btest(Bits *a, uint n)
 {
-       if(a.b[n/32] & (1L << (n%32)))
-               return 1;
-       return 0;
+       return (a->b[n/64] & (1LL << (n%64))) != 0;
+}
+
+void
+biset(Bits *a, uint n)
+{
+       a->b[n/64] |= 1LL << (n%64);
+}
+
+void
+biclr(Bits *a, uint n)
+{
+       a->b[n/64] &= ~(1LL << (n%64));
 }
-*/
 
 int
-bitno(int32 b)
+bitno(uint64 b)
 {
        int i;
 
-       for(i=0; i<32; i++)
-               if(b & (1L<<i))
+       for(i=0; i<64; i++)
+               if(b & (1LL<<i))
                        return i;
        fatal("bad in bitno");
        return 0;
@@ -157,7 +165,7 @@ Qconv(Fmt *fp)
                        if(var[i].offset != 0)
                                fmtprint(fp, "%+lld", (vlong)var[i].offset);
                }
-               bits.b[i/32] &= ~(1L << (i%32));
+               biclr(&bits, i);
        }
        return 0;
 }
index da5984cebf864958bd29c4b0acfe78b8b06c8000..aeee552362f2826bb7a4edf1626366f731869455 100644 (file)
@@ -7,6 +7,8 @@
 #include       "go.h"
 #include       "y.tab.h"
 
+static NodeList *asmlist;
+
 static void    dumpexporttype(Type *t);
 
 // Mark n's symbol as exported
@@ -68,6 +70,11 @@ autoexport(Node *n, int ctxt)
        // -A is for cmd/gc/mkbuiltin script, so export everything
        if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
                exportsym(n);
+       if(asmhdr && n->sym->pkg == localpkg && !(n->sym->flags & SymAsm)) {
+               n->sym->flags |= SymAsm;
+               asmlist = list(asmlist, n);
+       }
+               
 }
 
 static void
@@ -519,3 +526,37 @@ importtype(Type *pt, Type *t)
        if(debug['E'])
                print("import type %T %lT\n", pt, t);
 }
+
+void
+dumpasmhdr(void)
+{
+       Biobuf *b;
+       NodeList *l;
+       Node *n;
+       Type *t;
+
+       b = Bopen(asmhdr, OWRITE);
+       if(b == nil)
+               fatal("open %s: %r", asmhdr);
+       Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", thechar, localpkg->name);
+       for(l=asmlist; l; l=l->next) {
+               n = l->n;
+               if(isblanksym(n->sym))
+                       continue;
+               switch(n->op) {
+               case OLITERAL:
+                       Bprint(b, "#define const_%s %#V\n", n->sym->name, &n->val);
+                       break;
+               case OTYPE:
+                       t = n->type;
+                       if(t->etype != TSTRUCT || t->map != T || t->funarg)
+                               break;
+                       for(t=t->type; t != T; t=t->down)
+                               if(!isblanksym(t->sym))
+                                       Bprint(b, "#define %s_%s %d\n", n->sym->name, t->sym->name, (int)t->width);
+                       break;
+               }
+       }
+       
+       Bterm(b);
+}
index 965a0550d3683b64c097e8a6f07bb586d4180504..6e326961d8f0ccad1e6709d562b66d93c689d757 100644 (file)
@@ -382,6 +382,7 @@ enum
        SymExported     = 1<<2, // already written out by export
        SymUniq         = 1<<3,
        SymSiggen       = 1<<4,
+       SymAsm          = 1<<5,
 };
 
 struct Sym
@@ -393,6 +394,7 @@ struct      Sym
        int32   npkg;   // number of imported packages with this name
        uint32  uniqgen;
        Pkg*    importdef;      // where imported definition was found
+       char*   linkname;       // link name
 
        // saved and restored by dcopy
        Pkg*    pkg;
@@ -704,13 +706,13 @@ enum
        Ecomplit = 1<<11,       // type in composite literal
 };
 
-#define        BITS    5
-#define        NVAR    (BITS*sizeof(uint32)*8)
+#define        BITS    3
+#define        NVAR    (BITS*sizeof(uint64)*8)
 
 typedef        struct  Bits    Bits;
 struct Bits
 {
-       uint32  b[BITS];
+       uint64  b[BITS];
 };
 
 EXTERN Bits    zbits;
@@ -860,6 +862,8 @@ EXTERN      int32   lexlineno;
 EXTERN int32   lineno;
 EXTERN int32   prevlineno;
 
+EXTERN Fmt     pragcgobuf;
+
 EXTERN char*   infile;
 EXTERN char*   outfile;
 EXTERN Biobuf* bout;
@@ -890,6 +894,7 @@ 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*    rawpkg; // fake package for raw symbol names
 EXTERN Pkg*    phash[128];
 EXTERN int     tptr;           // either TPTR32 or TPTR64
 extern char*   runtimeimport;
@@ -897,6 +902,7 @@ extern      char*   unsafeimport;
 EXTERN char*   myimportpath;
 EXTERN Idir*   idirs;
 EXTERN char*   localimport;
+EXTERN char*   asmhdr;
 
 EXTERN Type*   types[NTYPE];
 EXTERN Type*   idealstring;
@@ -1027,12 +1033,14 @@ int     Qconv(Fmt *fp);
 Bits   band(Bits a, Bits b);
 int    bany(Bits *a);
 int    beq(Bits a, Bits b);
-int    bitno(int32 b);
+int    bitno(uint64 b);
 Bits   blsh(uint n);
 Bits   bnot(Bits a);
 int    bnum(Bits a);
 Bits   bor(Bits a, Bits b);
-int    bset(Bits a, uint n);
+int    btest(Bits *a, uint n);
+void   biset(Bits *a, uint n);
+void   biclr(Bits *a, uint n);
 
 /*
  *     bv.c
@@ -1145,6 +1153,7 @@ void      escapes(NodeList*);
  */
 void   autoexport(Node *n, int ctxt);
 void   dumpexport(void);
+void   dumpasmhdr(void);
 int    exportname(char *s);
 void   exportsym(Node *n);
 void    importconst(Sym *s, Type *t, Node *n);
index 523ba37aa7b1ed1d99d477bca5a0aa6407436ac8..2bd7adfb64e57e579c5ae84d7197ab87c8ed93b6 100644 (file)
@@ -17,6 +17,8 @@ extern int yychar;
 int yyprev;
 int yylast;
 
+static int     imported_unsafe;
+
 static void    lexinit(void);
 static void    lexinit1(void);
 static void    lexfini(void);
@@ -271,6 +273,9 @@ main(int argc, char *argv[])
                flag_largemodel = 1;
 
        setexp();
+       
+       fmtstrinit(&pragcgobuf);
+       quotefmtinstall();
 
        outfile = nil;
        flagcount("+", "compiling runtime", &compiling_runtime);
@@ -289,6 +294,7 @@ main(int argc, char *argv[])
        flagcount("S", "print assembly listing", &debug['S']);
        flagfn0("V", "print compiler version", doversion);
        flagcount("W", "debug parse tree after type checking", &debug['W']);
+       flagstr("asmhdr", "file: write assembly header to named file", &asmhdr);
        flagcount("complete", "compiling complete package (no C or assembly)", &pure_go);
        flagstr("d", "list: print debug information about items in list", &debugstr);
        flagcount("e", "no limit on number of errors reported", &debug['e']);
@@ -403,6 +409,8 @@ main(int argc, char *argv[])
 
                block = 1;
                iota = -1000000;
+               
+               imported_unsafe = 0;
 
                yyparse();
                if(nsyntaxerrors != 0)
@@ -509,6 +517,9 @@ main(int argc, char *argv[])
                errorexit();
 
        dumpobj();
+       
+       if(asmhdr)
+               dumpasmhdr();
 
        if(nerrors+nsavederrors)
                errorexit();
@@ -724,6 +735,7 @@ importfile(Val *f, int line)
                }
                importpkg = mkpkg(f->u.sval);
                cannedimports("unsafe.6", unsafeimport);
+               imported_unsafe = 1;
                return;
        }
        
@@ -1501,6 +1513,20 @@ caseout:
        return LLITERAL;
 }
 
+static void pragcgo(char*);
+
+static int
+more(char **pp)
+{
+       char *p;
+       
+       p = *pp;
+       while(yy_isspace(*p))
+               p++;
+       *pp = p;
+       return *p != '\0';
+}
+
 /*
  * read and interpret syntax that looks like
  * //line parse.y:15
@@ -1583,9 +1609,39 @@ go:
                        *cp++ = c;
        }
        *cp = 0;
+       
+       if(strncmp(lexbuf, "go:cgo_", 7) == 0)
+               pragcgo(lexbuf);
+       
        ep = strchr(lexbuf, ' ');
        if(ep != nil)
                *ep = 0;
+       
+       if(strcmp(lexbuf, "go:linkname") == 0) {
+               if(!imported_unsafe)
+                       yyerror("//go:linkname only allowed in Go files that import \"unsafe\"");
+               if(ep == nil) {
+                       yyerror("usage: //go:linkname localname linkname");
+                       goto out;
+               }
+               cp = ep+1;
+               while(yy_isspace(*cp))
+                       cp++;
+               ep = strchr(cp, ' ');
+               if(ep == nil) {
+                       yyerror("usage: //go:linkname localname linkname");
+                       goto out;
+               }
+               *ep++ = 0;
+               while(yy_isspace(*ep))
+                       ep++;
+               if(*ep == 0) {
+                       yyerror("usage: //go:linkname localname linkname");
+                       goto out;
+               }
+               lookup(cp)->linkname = strdup(ep);
+               goto out;
+       }       
 
        if(strcmp(lexbuf, "go:nointerface") == 0 && fieldtrack_enabled) {
                nointerface = 1;
@@ -1604,6 +1660,150 @@ out:
        return c;
 }
 
+static char*
+getimpsym(char **pp)
+{
+       char *p, *start;
+       
+       more(pp); // skip spaces
+
+       p = *pp;
+       if(*p == '\0' || *p == '"')
+               return nil;
+       
+       start = p;
+       while(*p != '\0' && !yy_isspace(*p) && *p != '"')
+               p++;
+       if(*p != '\0')
+               *p++ = '\0';
+       
+       *pp = p;
+       return start;
+}
+
+static char*
+getquoted(char **pp)
+{
+       char *p, *start;
+       
+       more(pp); // skip spaces
+       
+       p = *pp;
+       if(*p != '"')
+               return nil;
+       p++;
+       
+       start = p;
+       while(*p != '"') {
+               if(*p == '\0')
+                       return nil;
+               p++;
+       }
+       *p++ = '\0';
+       *pp = p;
+       return start;
+}
+
+// Copied nearly verbatim from the C compiler's #pragma parser.
+// TODO: Rewrite more cleanly once the compiler is written in Go.
+static void
+pragcgo(char *text)
+{
+       char *local, *remote, *p, *q, *verb;
+       
+       for(q=text; *q != '\0' && *q != ' '; q++)
+               ;
+       if(*q == ' ')
+               *q++ = '\0';
+       
+       verb = text+3; // skip "go:"
+
+       if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
+               p = getquoted(&q);
+               if(p == nil)
+                       goto err1;
+               fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
+               goto out;
+       
+       err1:
+               yyerror("usage: //go:cgo_dynamic_linker \"path\"");
+               goto out;
+       }       
+
+       if(strcmp(verb, "dynexport") == 0)
+               verb = "cgo_export_dynamic";
+       if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
+               local = getimpsym(&q);
+               if(local == nil)
+                       goto err2;
+               if(!more(&q)) {
+                       fmtprint(&pragcgobuf, "%s %q\n", verb, local);
+                       goto out;
+               }
+               remote = getimpsym(&q);
+               if(remote == nil)
+                       goto err2;
+               fmtprint(&pragcgobuf, "%s %q %q\n", verb, local, remote);
+               goto out;
+       
+       err2:
+               yyerror("usage: //go:%s local [remote]", verb);
+               goto out;
+       }
+       
+       if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
+               local = getimpsym(&q);
+               if(local == nil)
+                       goto err3;
+               if(!more(&q)) {
+                       fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local);
+                       goto out;
+               }
+               remote = getimpsym(&q);
+               if(remote == nil)
+                       goto err3;
+               if(!more(&q)) {
+                       fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local, remote);
+                       goto out;
+               }
+               p = getquoted(&q);
+               if(p == nil)    
+                       goto err3;
+               fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local, remote, p);
+               goto out;
+       
+       err3:
+               yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]");
+               goto out;
+       }
+       
+       if(strcmp(verb, "cgo_import_static") == 0) {
+               local = getimpsym(&q);
+               if(local == nil || more(&q))
+                       goto err4;
+               fmtprint(&pragcgobuf, "cgo_import_static %q\n", local);
+               goto out;
+               
+       err4:
+               yyerror("usage: //go:cgo_import_static local");
+               goto out;
+       }
+       
+       if(strcmp(verb, "cgo_ldflag") == 0) {
+               p = getquoted(&q);
+               if(p == nil)
+                       goto err5;
+               fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
+               goto out;
+
+       err5:
+               yyerror("usage: //go:cgo_ldflag \"arg\"");
+               goto out;
+       }
+
+out:;
+}
+
 int32
 yylex(void)
 {
index b752a13ced5cdc8f8b37dd35027fa96e48cb26ea..7e4e97854a8748e8c40c56daed1f9abffb42bd97 100644 (file)
@@ -67,6 +67,16 @@ dumpobj(void)
                startobj = Boffset(bout);
                Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
        }
+       
+       if(pragcgobuf.to > pragcgobuf.start) {
+               if(writearchive) {
+                       // write empty export section; must be before cgo section
+                       Bprint(bout, "\n$$\n\n$$\n\n");
+               }
+               Bprint(bout, "\n$$  // cgo\n");
+               Bprint(bout, "%s\n$$\n\n", fmtstrflush(&pragcgobuf));
+       }
+
 
        Bprint(bout, "\n!\n");
 
@@ -153,6 +163,8 @@ linksym(Sym *s)
                return s->lsym;
        if(isblanksym(s))
                s->lsym = linklookup(ctxt, "_", 0);
+       else if(s->linkname != nil)
+               s->lsym = linklookup(ctxt, s->linkname, 0);
        else {
                p = smprint("%s.%s", s->pkg->prefix, s->name);
                s->lsym = linklookup(ctxt, p, 0);
index 39028e3f88900942567721782c653d6035614d36..259cec85a31531b6bafb04b1348466113b0bb67f 100644 (file)
@@ -471,7 +471,7 @@ allocauto(Prog* ptxt)
                stksize = rnd(stksize, n->type->align);
                if(haspointers(n->type))
                        stkptrsize = stksize;
-               if(thechar == '5')
+               if(thechar == '5' || thechar == '9')
                        stksize = rnd(stksize, widthptr);
                if(stksize >= (1ULL<<31)) {
                        setlineno(curfn);
@@ -528,7 +528,7 @@ cgen_checknil(Node *n)
                dump("checknil", n);
                fatal("bad checknil");
        }
-       if((thechar == '5' && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
+       if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
                regalloc(&reg, types[tptr], n);
                cgen(n, &reg);
                gins(ACHECKNIL, &reg, N);
index 0feb2c710ac439dc736cdaa820bdb7c019a92821..3bfa69b1f02084078f8e1ea6b7444bc08d858933 100644 (file)
@@ -1092,7 +1092,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
        case TCOMPLEX64:
        case TCOMPLEX128:
                for(i = 0; i < t->width; i++) {
-                       bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar
+                       bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar (BitsScalar)
                }
                *xoffset += t->width;
                break;
@@ -1105,7 +1105,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
        case TMAP:
                if((*xoffset & (widthptr-1)) != 0)
                        fatal("twobitwalktype1: invalid alignment, %T", t);
-               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr
+               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr (BitsPointer)
                *xoffset += t->width;
                break;
 
@@ -1113,7 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
                // struct { byte *str; intgo len; }
                if((*xoffset & (widthptr-1)) != 0)
                        fatal("twobitwalktype1: invalid alignment, %T", t);
-               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
+               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
                *xoffset += t->width;
                break;
 
@@ -1123,15 +1123,8 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
                // struct { Type *type; union { void *ptr, uintptr val } data; }
                if((*xoffset & (widthptr-1)) != 0)
                        fatal("twobitwalktype1: invalid alignment, %T", t);
-               bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 0);
-               bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1); // 3 = multiword
-               // next word contains 2 = Iface, 3 = Eface
-               if(isnilinter(t)) {
-                       bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 2);
-                       bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3);
-               } else {
-                       bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3);
-               }
+               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
+               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 3); // 2 = live ptr in second slot (BitsPointer)
                *xoffset += t->width;
                break;
 
@@ -1144,7 +1137,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
                        // struct { byte *array; uintgo len; uintgo cap; }
                        if((*xoffset & (widthptr-1)) != 0)
                                fatal("twobitwalktype1: invalid TARRAY alignment, %T", t);
-                       bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
+                       bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
                        *xoffset += t->width;
                } else
                        for(i = 0; i < t->bound; i++)
index b2ff2fbc5efa012a9f61868ea7b06b9f24600371..4155953be1238b7e1d02a5beff03a089f9a30c28 100644 (file)
@@ -1318,7 +1318,7 @@ gengcmask(Type *t, uint8 gcmask[16])
 {
        Bvec *vec;
        vlong xoffset, nptr, i, j;
-       int  half, mw;
+       int  half;
        uint8 bits, *pos;
 
        memset(gcmask, 0, 16);
@@ -1335,7 +1335,6 @@ gengcmask(Type *t, uint8 gcmask[16])
        pos = (uint8*)gcmask;
        nptr = (t->width+widthptr-1)/widthptr;
        half = 0;
-       mw = 0;
        // If number of words is odd, repeat the mask.
        // This makes simpler handling of arrays in runtime.
        for(j=0; j<=(nptr%2); j++) {
@@ -1344,9 +1343,8 @@ gengcmask(Type *t, uint8 gcmask[16])
                        // Some fake types (e.g. Hmap) has missing fileds.
                        // twobitwalktype1 generates BitsDead for that holes,
                        // replace BitsDead with BitsScalar.
-                       if(!mw && bits == BitsDead)
+                       if(bits == BitsDead)
                                bits = BitsScalar;
-                       mw = !mw && bits == BitsMultiWord;
                        bits <<= 2;
                        if(half)
                                bits <<= 4;
@@ -1525,11 +1523,9 @@ gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
                *xoffset += t->width;
                break;
        case TINTER:
-               proggendata(g, BitsMultiWord);
-               if(isnilinter(t))
-                       proggendata(g, BitsEface);
-               else
-                       proggendata(g, BitsIface);
+               // Assuming IfacePointerOnly=1.
+               proggendata(g, BitsPointer);
+               proggendata(g, BitsPointer);
                *xoffset += t->width;
                break;
        case TARRAY:
index c3bc5af3b8d888c98bbf0f96980c279f02b111fa..5e369b69578a22f6ff774976215fae49af6464bb 100644 (file)
@@ -3802,39 +3802,25 @@ checknil(Node *x, NodeList **init)
 
 /*
  * Can this type be stored directly in an interface word?
+ * Yes, if the representation is a single pointer.
  */
 int
 isdirectiface(Type *t)
 {
-       // Setting IfacePointerOnly = 1 changes the
-       // interface representation so that the data word
-       // in an interface value must always be a pointer.
-       // Setting it to 0 uses the original representation,
-       // where the data word can hold a pointer or any
-       // non-pointer value no bigger than a pointer.
-       enum {
-               IfacePointerOnly = 1,
-       };
-
-       if(IfacePointerOnly) {
-               switch(t->etype) {
-               case TPTR32:
-               case TPTR64:
-               case TCHAN:
-               case TMAP:
-               case TFUNC:
-               case TUNSAFEPTR:
-                       return 1;
-               case TARRAY:
-                       // Array of 1 direct iface type can be direct.
-                       return t->bound == 1 && isdirectiface(t->type);
-               case TSTRUCT:
-                       // Struct with 1 field of direct iface type can be direct.
-                       return t->type != T && t->type->down == T && isdirectiface(t->type->type);
-               }
-               return 0;
+       switch(t->etype) {
+       case TPTR32:
+       case TPTR64:
+       case TCHAN:
+       case TMAP:
+       case TFUNC:
+       case TUNSAFEPTR:
+               return 1;
+       case TARRAY:
+               // Array of 1 direct iface type can be direct.
+               return t->bound == 1 && isdirectiface(t->type);
+       case TSTRUCT:
+               // Struct with 1 field of direct iface type can be direct.
+               return t->type != T && t->type->down == T && isdirectiface(t->type->type);
        }
-       
-       dowidth(t);
-       return t->width <= widthptr;
+       return 0;
 }
index ff9b362083e7892bc920bc02fd142719a618cf52..77f9c80f916319e8b51a368b8a373b8f1861787c 100644 (file)
@@ -1766,7 +1766,6 @@ walkprint(Node *nn, NodeList **init)
        int notfirst, et, op;
        NodeList *calls;
 
-       on = nil;
        op = nn->op;
        all = nn->list;
        calls = nil;
@@ -3301,6 +3300,9 @@ walkrotate(Node **np)
        int w, sl, sr, s;
        Node *l, *r;
        Node *n;
+
+       if(thechar == '9')
+               return;
        
        n = *np;
 
@@ -3426,6 +3428,10 @@ walkdiv(Node **np, NodeList **init)
        Type *twide;
        Magic m;
 
+       // TODO(minux)
+       if(thechar == '9')
+               return;
+
        n = *np;
        if(n->right->op != OLITERAL)
                return;
index 1dd4314da659aaacb9fec30f2b738fd7a7e2bdeb..5dcaa04a172b96020a52a13e11dfbee319bf52f0 100644 (file)
@@ -813,7 +813,7 @@ func (b *builder) build(a *action) (err error) {
        }
 
        if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
-               !hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") {
+               !hasString(a.p.SFiles, "zsys_"+buildContext.GOOS+"_"+buildContext.GOARCH+".s") {
                return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
        }
 
@@ -941,7 +941,7 @@ func (b *builder) build(a *action) (err error) {
        inc := b.includeArgs("-I", a.deps)
 
        // Compile Go.
-       ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, inc, gofiles)
+       ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, len(sfiles) > 0, inc, gofiles)
        if len(out) > 0 {
                b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
                if err != nil {
@@ -1550,7 +1550,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, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
+       gc(b *builder, p *Package, archive, obj string, asmhdr bool, 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
@@ -1587,7 +1587,7 @@ func (noToolchain) linker() string {
        return ""
 }
 
-func (noToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
+func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
        return "", nil, noCompiler()
 }
 
@@ -1623,7 +1623,7 @@ func (gcToolchain) linker() string {
        return tool(archChar + "l")
 }
 
-func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
        if archive != "" {
                ofile = archive
        } else {
@@ -1660,6 +1660,9 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []
        if ofile == archive {
                args = append(args, "-pack")
        }
+       if asmhdr {
+               args = append(args, "-asmhdr", obj+"go_asm.h")
+       }
        for _, f := range gofiles {
                args = append(args, mkAbs(p.Dir, f))
        }
@@ -1824,18 +1827,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
 }
 
 func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
-       inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
-       cfile = mkAbs(p.Dir, cfile)
-       warn := []string{"-w"}
-       if p.usesSwig() {
-               // When using SWIG, this compiler is only used to
-               // compile the C files generated by SWIG.
-               // We don't want warnings.
-               // See issue 9065 for details.
-               warn = nil
-       }
-       args := stringList(tool(archChar+"c"), "-F", "-V", warn, "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
-       return b.run(p.Dir, p.ImportPath, nil, args)
+       return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile))
 }
 
 // The Gccgo toolchain.
@@ -1859,7 +1851,7 @@ func (gccgoToolchain) linker() string {
        return gccgoBin
 }
 
-func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
        out := "_go_.o"
        ofile = obj + out
        gcargs := []string{"-g"}
@@ -2225,11 +2217,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
        outGo = append(outGo, gofiles...)
 
        // cc _cgo_defun.c
-       defunObj := obj + "_cgo_defun." + objExt
-       if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
-               return nil, nil, err
+       _, gccgo := buildToolchain.(gccgoToolchain)
+       if gccgo {
+               defunObj := obj + "_cgo_defun." + objExt
+               if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
+                       return nil, nil, err
+               }
+               outObj = append(outObj, defunObj)
        }
-       outObj = append(outObj, defunObj)
 
        // gcc
        var linkobj []string
@@ -2343,20 +2338,15 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
        }
 
        // cgo -dynimport
-       importC := obj + "_cgo_import.c"
+       importGo := obj + "_cgo_import.go"
        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, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
-               return nil, nil, err
-       }
-
-       // cc _cgo_import.ARCH
-       importObj := obj + "_cgo_import." + objExt
-       if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil {
+       if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil {
                return nil, nil, err
        }
+       outGo = append(outGo, importGo)
 
        ofile := obj + "_all.o"
        var gccObjs, nonGccObjs []string
@@ -2390,7 +2380,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
        // 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 = stringList(importObj, nonGccObjs, ofile)
+       outObj = stringList(nonGccObjs, ofile)
 
        return outGo, outObj, nil
 }
@@ -2526,7 +2516,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
 
        p := goFilesPackage(srcs)
 
-       if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil {
+       if _, _, e := buildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil {
                return "32", nil
        }
        return "64", nil
index 61847546a33d5ba95fedb5967283e7068950b377..92c6fb57cea0ac261c37af7178f0bf7f8ae6043e 100644 (file)
@@ -445,11 +445,11 @@ blk(LSym *start, int64 addr, int64 size)
                        continue;
                if(sym->value >= eaddr)
                        break;
+               ctxt->cursym = sym;
                if(sym->value < addr) {
                        diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
                        errorexit();
                }
-               ctxt->cursym = sym;
                for(; addr < sym->value; addr++)
                        cput(0);
                p = sym->p;
@@ -463,6 +463,8 @@ blk(LSym *start, int64 addr, int64 size)
                        diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size);
                        errorexit();
                }
+               if(sym->value+sym->size >= eaddr)
+                       break;
        }
 
        for(; addr < eaddr; addr++)
index 5b5833db5dce4910af085f3b3011a680ed93cc38..ad35df7400329c7efa1f96b0d069ee80aaf39796 100644 (file)
@@ -10,8 +10,8 @@ Ld is the portable code for a modified version of the Plan 9 linker.  The origin
 
        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
+It reads object files (.5, .6, .8, .9 files) and writes a binary named for the
+architecture (5.out, 6.out, 8.out, 9.out) by default (if $GOOS is windows, a .exe suffix
 will be appended).
 
 Major changes include:
@@ -22,7 +22,7 @@ Original options are listed on the manual page linked above.
 
 Usage:
        go tool 6l [flags] mainObj
-Substitute 6l with 8l or 5l as appropriate.
+Substitute 6l with 5l, 8l or 9l as appropriate.
 
 Options new in this version:
 
index a3ba523253c250386bfbf12e23e8fff3d25ebd5c..fbb5699bdb6489e72a3026d83fd400516f91af5a 100644 (file)
@@ -2189,7 +2189,7 @@ dwarfaddshstrings(LSym *shstrtab)
        elfstrdbg[ElfStrDebugStr]      = addstring(shstrtab, ".debug_str");
        elfstrdbg[ElfStrGDBScripts]    = addstring(shstrtab, ".debug_gdb_scripts");
        if(linkmode == LinkExternal) {
-               if(thechar == '6') {
+               if(thechar == '6' || thechar == '9') {
                        elfstrdbg[ElfStrRelDebugInfo] = addstring(shstrtab, ".rela.debug_info");
                        elfstrdbg[ElfStrRelDebugAranges] = addstring(shstrtab, ".rela.debug_aranges");
                        elfstrdbg[ElfStrRelDebugLine] = addstring(shstrtab, ".rela.debug_line");
@@ -2244,7 +2244,7 @@ dwarfaddelfrelocheader(int elfstr, ElfShdr *shdata, vlong off, vlong size)
        ElfShdr *sh;
 
        sh = newElfShdr(elfstrdbg[elfstr]);
-       if(thechar == '6') {
+       if(thechar == '6' || thechar == '9') {
                sh->type = SHT_RELA;
        } else {
                sh->type = SHT_REL;
index 3196961f35c2124ecb6fe162bdbc092632082e99..6ac6b6ee82ee12a944a336d65fce49cfe4276d84 100644 (file)
@@ -45,6 +45,7 @@ elfinit(void)
        switch(thechar) {
        // 64-bit architectures
        case '6':
+       case '9':
                elf64 = 1;
                hdr.phoff = ELF64HDRSIZE;       /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
                hdr.shoff = ELF64HDRSIZE;       /* Will move as we add PHeaders */
@@ -678,7 +679,7 @@ elfdynhash(void)
                elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0));
        }
 
-       if(thechar == '6') {
+       if(thechar == '6' || thechar == '9') {
                sy = linklookup(ctxt, ".rela.plt", 0);
                if(sy->size > 0) {
                        elfwritedynent(s, DT_PLTREL, DT_RELA);
@@ -804,7 +805,7 @@ elfshreloc(Section *sect)
        if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
                return nil;
 
-       if(thechar == '6') {
+       if(thechar == '6' || thechar == '9') {
                prefix = ".rela";
                typ = SHT_RELA;
        } else {
@@ -931,7 +932,7 @@ doelf(void)
                debug['s'] = 0;
                debug['d'] = 1;
 
-               if(thechar == '6') {
+               if(thechar == '6' || thechar == '9') {
                        addstring(shstrtab, ".rela.text");
                        addstring(shstrtab, ".rela.rodata");
                        addstring(shstrtab, ".rela.typelink");
@@ -954,7 +955,7 @@ doelf(void)
 
        if(flag_shared) {
                addstring(shstrtab, ".init_array");
-               if(thechar == '6')
+               if(thechar == '6' || thechar == '9')
                        addstring(shstrtab, ".rela.init_array");
                else
                        addstring(shstrtab, ".rel.init_array");
@@ -975,7 +976,7 @@ doelf(void)
                addstring(shstrtab, ".dynamic");
                addstring(shstrtab, ".dynsym");
                addstring(shstrtab, ".dynstr");
-               if(thechar == '6') {
+               if(thechar == '6' || thechar == '9') {
                        addstring(shstrtab, ".rela");
                        addstring(shstrtab, ".rela.plt");
                } else {
@@ -990,7 +991,7 @@ doelf(void)
                s = linklookup(ctxt, ".dynsym", 0);
                s->type = SELFROSECT;
                s->reachable = 1;
-               if(thechar == '6')
+               if(thechar == '6' || thechar == '9')
                        s->size += ELF64SYMSIZE;
                else
                        s->size += ELF32SYMSIZE;
@@ -1004,7 +1005,7 @@ doelf(void)
                dynstr = s;
 
                /* relocation table */
-               if(thechar == '6')
+               if(thechar == '6' || thechar == '9')
                        s = linklookup(ctxt, ".rela", 0);
                else
                        s = linklookup(ctxt, ".rel", 0);
@@ -1031,7 +1032,7 @@ doelf(void)
                
                elfsetupplt();
                
-               if(thechar == '6')
+               if(thechar == '6' || thechar == '9')
                        s = linklookup(ctxt, ".rela.plt", 0);
                else
                        s = linklookup(ctxt, ".rel.plt", 0);
@@ -1056,13 +1057,13 @@ doelf(void)
                 */
                elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0));
                elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0));
-               if(thechar == '6')
+               if(thechar == '6' || thechar == '9')
                        elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
                else
                        elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
                elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0));
                elfwritedynentsymsize(s, DT_STRSZ, linklookup(ctxt, ".dynstr", 0));
-               if(thechar == '6') {
+               if(thechar == '6' || thechar == '9') {
                        elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0));
                        elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0));
                        elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
@@ -1148,6 +1149,9 @@ asmbelf(vlong symo)
        case '8':
                eh->machine = EM_386;
                break;
+       case '9':
+               eh->machine = EM_PPC64;
+               break;
        }
 
        startva = INITTEXT - HEADR;
@@ -1488,7 +1492,10 @@ elfobj:
                eh->ident[EI_CLASS] = ELFCLASS64;
        else
                eh->ident[EI_CLASS] = ELFCLASS32;
-       eh->ident[EI_DATA] = ELFDATA2LSB;
+       if(ctxt->arch->endian == BigEndian)
+               eh->ident[EI_DATA] = ELFDATA2MSB;
+       else
+               eh->ident[EI_DATA] = ELFDATA2LSB;
        eh->ident[EI_VERSION] = EV_CURRENT;
 
        if(linkmode == LinkExternal)
index b5d0819493f2a5ffcc89e6bfc2fcffff6aa8c81f..ec8e7c4eaf123fc92110c2d9b129dcc86937fb7d 100644 (file)
@@ -436,6 +436,12 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
                        return;
                }
                break;
+       case '9':
+               if(obj->machine != ElfMachPower64 || hdr->ident[4] != ElfClass64) {
+                       diag("%s: elf object but not power64", pn);
+                       return;
+               }
+               break;
        }
 
        // load section list into memory.
index f889aba8a98db5a033742180a6c6eb1846b51097..64608d226ece43196a831abd54dc6fc295bcfb65 100644 (file)
@@ -594,6 +594,7 @@ hostlink(void)
                argv[argc++] = "-m32";
                break;
        case '6':
+       case '9':
                argv[argc++] = "-m64";
                break;
        case '5':
@@ -1033,7 +1034,7 @@ static LSym *newstack;
 
 enum
 {
-       HasLinkRegister = (thechar == '5'),
+       HasLinkRegister = (thechar == '5' || thechar == '9'),
 };
 
 // TODO: Record enough information in new object files to
@@ -1042,7 +1043,7 @@ enum
 static int
 callsize(void)
 {
-       if(thechar == '5')
+       if(HasLinkRegister)
                return 0;
        return RegSize;
 }
@@ -1052,7 +1053,7 @@ dostkcheck(void)
 {
        Chain ch;
        LSym *s;
-       
+
        morestack = linklookup(ctxt, "runtime.morestack", 0);
        newstack = linklookup(ctxt, "runtime.newstack", 0);
 
@@ -1076,19 +1077,19 @@ dostkcheck(void)
                        continue;
 
                if(s->nosplit) {
-               ctxt->cursym = s;
-               ch.sym = s;
-               stkcheck(&ch, 0);
-       }
+                       ctxt->cursym = s;
+                       ch.sym = s;
+                       stkcheck(&ch, 0);
+               }
        }
        for(s = ctxt->textp; s != nil; s = s->next) {
                if(!s->nosplit) {
-               ctxt->cursym = s;
-               ch.sym = s;
-               stkcheck(&ch, 0);
+                       ctxt->cursym = s;
+                       ch.sym = s;
+                       stkcheck(&ch, 0);
+               }
        }
 }
-}
 
 static int
 stkcheck(Chain *up, int depth)
@@ -1106,7 +1107,7 @@ stkcheck(Chain *up, int depth)
        // function at top of safe zone once.
        if(limit == StackLimit-callsize()) {
                if(s->stkcheck)
-               return 0;
+                       return 0;
                s->stkcheck = 1;
        }
        
@@ -1154,6 +1155,7 @@ stkcheck(Chain *up, int depth)
                        switch(r->type) {
                        case R_CALL:
                        case R_CALLARM:
+                       case R_CALLPOWER:
                                // Direct call.
                                ch.limit = limit - pcsp.value - callsize();
                                ch.sym = r->sym;
@@ -1164,8 +1166,8 @@ stkcheck(Chain *up, int depth)
                                // to StackLimit beyond the frame size.
                                if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
                                        limit = StackLimit + s->locals;
-                                       if(thechar == '5')
-                                               limit += 4; // saved LR
+                                       if(HasLinkRegister)
+                                               limit += RegSize;
                                }
                                break;
 
@@ -1184,7 +1186,7 @@ stkcheck(Chain *up, int depth)
                                break;
                        }
                }
-               }
+       }
                
        return 0;
 }
@@ -1213,7 +1215,7 @@ stkprint(Chain *ch, int limit)
                else
                        print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
        } else {
-               stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
+               stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
                if(!HasLinkRegister)
                        print("\t%d\ton entry to %s\n", ch->limit, name);
        }
@@ -1533,7 +1535,7 @@ callgraph(void)
                        r = &s->r[i];
                        if(r->sym == nil)
                                continue;
-                       if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT)
+                       if((r->type == R_CALL || r->type == R_CALLARM || r->type == R_CALLPOWER) && r->sym->type == STEXT)
                                Bprint(&bso, "%s calls %s\n", s->name, r->sym->name);
                }
        }
index fe7e10e466691249f8dee517a7a3ad3c7c5114c2..ffb20b3a55be523549dcf846ba35a0d7867fe746 100644 (file)
@@ -44,6 +44,7 @@ machoinit(void)
        switch(thechar) {
        // 64-bit architectures
        case '6':
+       case '9':
                macho64 = 1;
                break;
 
index 156270c8fabcd57f108486abde69f6604bba2574..c3a72c3cf6eea533d0eacdd4dbc6d94743d76856 100644 (file)
@@ -78,6 +78,7 @@ putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
 {
        switch(thechar) {
        case '6':
+       case '9':
                LPUT(off);
                cput(info);
                cput(other);
index 2bb74663c352d0dbaef1e95aa5e7952b4cd37a0a..bd09ae9f933b00d3664ce2d93c76fb279e9b63ca 100644 (file)
@@ -101,6 +101,10 @@ func testDisasm(t *testing.T, flags ...string) {
 }
 
 func TestDisasm(t *testing.T) {
+       switch runtime.GOARCH {
+       case "power64", "power64le":
+               t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
+       }
        testDisasm(t)
 }
 
@@ -109,5 +113,9 @@ func TestDisasmExtld(t *testing.T) {
        case "plan9", "windows":
                t.Skipf("skipping on %s", runtime.GOOS)
        }
+       switch runtime.GOARCH {
+       case "power64", "power64le":
+               t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH)
+       }
        testDisasm(t, "-ldflags=-linkmode=external")
 }
index cde296c79448275abd58877e6fe4218f2c67da7e..46e9d5735d179cecc5bf65a89b04f4d15bfe83c8 100644 (file)
@@ -1414,6 +1414,184 @@ var rppcStrings = []intName{
 func (i R_PPC) String() string   { return stringName(uint32(i), rppcStrings, false) }
 func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) }
 
+// Relocation types for PowerPC 64.
+type R_PPC64 int
+
+const (
+       R_PPC64_NONE               R_PPC64 = 0
+       R_PPC64_ADDR32             R_PPC64 = 1
+       R_PPC64_ADDR24             R_PPC64 = 2
+       R_PPC64_ADDR16             R_PPC64 = 3
+       R_PPC64_ADDR16_LO          R_PPC64 = 4
+       R_PPC64_ADDR16_HI          R_PPC64 = 5
+       R_PPC64_ADDR16_HA          R_PPC64 = 6
+       R_PPC64_ADDR14             R_PPC64 = 7
+       R_PPC64_ADDR14_BRTAKEN     R_PPC64 = 8
+       R_PPC64_ADDR14_BRNTAKEN    R_PPC64 = 9
+       R_PPC64_REL24              R_PPC64 = 10
+       R_PPC64_REL14              R_PPC64 = 11
+       R_PPC64_REL14_BRTAKEN      R_PPC64 = 12
+       R_PPC64_REL14_BRNTAKEN     R_PPC64 = 13
+       R_PPC64_GOT16              R_PPC64 = 14
+       R_PPC64_GOT16_LO           R_PPC64 = 15
+       R_PPC64_GOT16_HI           R_PPC64 = 16
+       R_PPC64_GOT16_HA           R_PPC64 = 17
+       R_PPC64_JMP_SLOT           R_PPC64 = 21
+       R_PPC64_REL32              R_PPC64 = 26
+       R_PPC64_ADDR64             R_PPC64 = 38
+       R_PPC64_ADDR16_HIGHER      R_PPC64 = 39
+       R_PPC64_ADDR16_HIGHERA     R_PPC64 = 40
+       R_PPC64_ADDR16_HIGHEST     R_PPC64 = 41
+       R_PPC64_ADDR16_HIGHESTA    R_PPC64 = 42
+       R_PPC64_REL64              R_PPC64 = 44
+       R_PPC64_TOC16              R_PPC64 = 47
+       R_PPC64_TOC16_LO           R_PPC64 = 48
+       R_PPC64_TOC16_HI           R_PPC64 = 49
+       R_PPC64_TOC16_HA           R_PPC64 = 50
+       R_PPC64_TOC                R_PPC64 = 51
+       R_PPC64_ADDR16_DS          R_PPC64 = 56
+       R_PPC64_ADDR16_LO_DS       R_PPC64 = 57
+       R_PPC64_GOT16_DS           R_PPC64 = 58
+       R_PPC64_GOT16_LO_DS        R_PPC64 = 59
+       R_PPC64_TOC16_DS           R_PPC64 = 63
+       R_PPC64_TOC16_LO_DS        R_PPC64 = 64
+       R_PPC64_TLS                R_PPC64 = 67
+       R_PPC64_DTPMOD64           R_PPC64 = 68
+       R_PPC64_TPREL16            R_PPC64 = 69
+       R_PPC64_TPREL16_LO         R_PPC64 = 70
+       R_PPC64_TPREL16_HI         R_PPC64 = 71
+       R_PPC64_TPREL16_HA         R_PPC64 = 72
+       R_PPC64_TPREL64            R_PPC64 = 73
+       R_PPC64_DTPREL16           R_PPC64 = 74
+       R_PPC64_DTPREL16_LO        R_PPC64 = 75
+       R_PPC64_DTPREL16_HI        R_PPC64 = 76
+       R_PPC64_DTPREL16_HA        R_PPC64 = 77
+       R_PPC64_DTPREL64           R_PPC64 = 78
+       R_PPC64_GOT_TLSGD16        R_PPC64 = 79
+       R_PPC64_GOT_TLSGD16_LO     R_PPC64 = 80
+       R_PPC64_GOT_TLSGD16_HI     R_PPC64 = 81
+       R_PPC64_GOT_TLSGD16_HA     R_PPC64 = 82
+       R_PPC64_GOT_TLSLD16        R_PPC64 = 83
+       R_PPC64_GOT_TLSLD16_LO     R_PPC64 = 84
+       R_PPC64_GOT_TLSLD16_HI     R_PPC64 = 85
+       R_PPC64_GOT_TLSLD16_HA     R_PPC64 = 86
+       R_PPC64_GOT_TPREL16_DS     R_PPC64 = 87
+       R_PPC64_GOT_TPREL16_LO_DS  R_PPC64 = 88
+       R_PPC64_GOT_TPREL16_HI     R_PPC64 = 89
+       R_PPC64_GOT_TPREL16_HA     R_PPC64 = 90
+       R_PPC64_GOT_DTPREL16_DS    R_PPC64 = 91
+       R_PPC64_GOT_DTPREL16_LO_DS R_PPC64 = 92
+       R_PPC64_GOT_DTPREL16_HI    R_PPC64 = 93
+       R_PPC64_GOT_DTPREL16_HA    R_PPC64 = 94
+       R_PPC64_TPREL16_DS         R_PPC64 = 95
+       R_PPC64_TPREL16_LO_DS      R_PPC64 = 96
+       R_PPC64_TPREL16_HIGHER     R_PPC64 = 97
+       R_PPC64_TPREL16_HIGHERA    R_PPC64 = 98
+       R_PPC64_TPREL16_HIGHEST    R_PPC64 = 99
+       R_PPC64_TPREL16_HIGHESTA   R_PPC64 = 100
+       R_PPC64_DTPREL16_DS        R_PPC64 = 101
+       R_PPC64_DTPREL16_LO_DS     R_PPC64 = 102
+       R_PPC64_DTPREL16_HIGHER    R_PPC64 = 103
+       R_PPC64_DTPREL16_HIGHERA   R_PPC64 = 104
+       R_PPC64_DTPREL16_HIGHEST   R_PPC64 = 105
+       R_PPC64_DTPREL16_HIGHESTA  R_PPC64 = 106
+       R_PPC64_TLSGD              R_PPC64 = 107
+       R_PPC64_TLSLD              R_PPC64 = 108
+       R_PPC64_REL16              R_PPC64 = 249
+       R_PPC64_REL16_LO           R_PPC64 = 250
+       R_PPC64_REL16_HI           R_PPC64 = 251
+       R_PPC64_REL16_HA           R_PPC64 = 252
+)
+
+var rppc64Strings = []intName{
+       {0, "R_PPC64_NONE"},
+       {1, "R_PPC64_ADDR32"},
+       {2, "R_PPC64_ADDR24"},
+       {3, "R_PPC64_ADDR16"},
+       {4, "R_PPC64_ADDR16_LO"},
+       {5, "R_PPC64_ADDR16_HI"},
+       {6, "R_PPC64_ADDR16_HA"},
+       {7, "R_PPC64_ADDR14"},
+       {8, "R_PPC64_ADDR14_BRTAKEN"},
+       {9, "R_PPC64_ADDR14_BRNTAKEN"},
+       {10, "R_PPC64_REL24"},
+       {11, "R_PPC64_REL14"},
+       {12, "R_PPC64_REL14_BRTAKEN"},
+       {13, "R_PPC64_REL14_BRNTAKEN"},
+       {14, "R_PPC64_GOT16"},
+       {15, "R_PPC64_GOT16_LO"},
+       {16, "R_PPC64_GOT16_HI"},
+       {17, "R_PPC64_GOT16_HA"},
+       {21, "R_PPC64_JMP_SLOT"},
+       {26, "R_PPC64_REL32"},
+       {38, "R_PPC64_ADDR64"},
+       {39, "R_PPC64_ADDR16_HIGHER"},
+       {40, "R_PPC64_ADDR16_HIGHERA"},
+       {41, "R_PPC64_ADDR16_HIGHEST"},
+       {42, "R_PPC64_ADDR16_HIGHESTA"},
+       {44, "R_PPC64_REL64"},
+       {47, "R_PPC64_TOC16"},
+       {48, "R_PPC64_TOC16_LO"},
+       {49, "R_PPC64_TOC16_HI"},
+       {50, "R_PPC64_TOC16_HA"},
+       {51, "R_PPC64_TOC"},
+       {56, "R_PPC64_ADDR16_DS"},
+       {57, "R_PPC64_ADDR16_LO_DS"},
+       {58, "R_PPC64_GOT16_DS"},
+       {59, "R_PPC64_GOT16_LO_DS"},
+       {63, "R_PPC64_TOC16_DS"},
+       {64, "R_PPC64_TOC16_LO_DS"},
+       {67, "R_PPC64_TLS"},
+       {68, "R_PPC64_DTPMOD64"},
+       {69, "R_PPC64_TPREL16"},
+       {70, "R_PPC64_TPREL16_LO"},
+       {71, "R_PPC64_TPREL16_HI"},
+       {72, "R_PPC64_TPREL16_HA"},
+       {73, "R_PPC64_TPREL64"},
+       {74, "R_PPC64_DTPREL16"},
+       {75, "R_PPC64_DTPREL16_LO"},
+       {76, "R_PPC64_DTPREL16_HI"},
+       {77, "R_PPC64_DTPREL16_HA"},
+       {78, "R_PPC64_DTPREL64"},
+       {79, "R_PPC64_GOT_TLSGD16"},
+       {80, "R_PPC64_GOT_TLSGD16_LO"},
+       {81, "R_PPC64_GOT_TLSGD16_HI"},
+       {82, "R_PPC64_GOT_TLSGD16_HA"},
+       {83, "R_PPC64_GOT_TLSLD16"},
+       {84, "R_PPC64_GOT_TLSLD16_LO"},
+       {85, "R_PPC64_GOT_TLSLD16_HI"},
+       {86, "R_PPC64_GOT_TLSLD16_HA"},
+       {87, "R_PPC64_GOT_TPREL16_DS"},
+       {88, "R_PPC64_GOT_TPREL16_LO_DS"},
+       {89, "R_PPC64_GOT_TPREL16_HI"},
+       {90, "R_PPC64_GOT_TPREL16_HA"},
+       {91, "R_PPC64_GOT_DTPREL16_DS"},
+       {92, "R_PPC64_GOT_DTPREL16_LO_DS"},
+       {93, "R_PPC64_GOT_DTPREL16_HI"},
+       {94, "R_PPC64_GOT_DTPREL16_HA"},
+       {95, "R_PPC64_TPREL16_DS"},
+       {96, "R_PPC64_TPREL16_LO_DS"},
+       {97, "R_PPC64_TPREL16_HIGHER"},
+       {98, "R_PPC64_TPREL16_HIGHERA"},
+       {99, "R_PPC64_TPREL16_HIGHEST"},
+       {100, "R_PPC64_TPREL16_HIGHESTA"},
+       {101, "R_PPC64_DTPREL16_DS"},
+       {102, "R_PPC64_DTPREL16_LO_DS"},
+       {103, "R_PPC64_DTPREL16_HIGHER"},
+       {104, "R_PPC64_DTPREL16_HIGHERA"},
+       {105, "R_PPC64_DTPREL16_HIGHEST"},
+       {106, "R_PPC64_DTPREL16_HIGHESTA"},
+       {107, "R_PPC64_TLSGD"},
+       {108, "R_PPC64_TLSLD"},
+       {249, "R_PPC64_REL16"},
+       {250, "R_PPC64_REL16_LO"},
+       {251, "R_PPC64_REL16_HI"},
+       {252, "R_PPC64_REL16_HA"},
+}
+
+func (i R_PPC64) String() string   { return stringName(uint32(i), rppc64Strings, false) }
+func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) }
+
 // Relocation types for SPARC.
 type R_SPARC int
 
index de8a3a24fe9584a3424daee4dcfb2574f3176443..74d1db306c78868111e5b5d882bc372c9b8f9cc8 100644 (file)
@@ -532,6 +532,9 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
        if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 {
                return f.applyRelocationsARM64(dst, rels)
        }
+       if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 {
+               return f.applyRelocationsPPC64(dst, rels)
+       }
 
        return errors.New("not implemented")
 }
@@ -671,6 +674,51 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
        return nil
 }
 
+func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
+       // 24 is the size of Rela64.
+       if len(rels)%24 != 0 {
+               return errors.New("length of relocation section is not a multiple of 24")
+       }
+
+       symbols, _, err := f.getSymbols(SHT_SYMTAB)
+       if err != nil {
+               return err
+       }
+
+       b := bytes.NewReader(rels)
+       var rela Rela64
+
+       for b.Len() > 0 {
+               binary.Read(b, f.ByteOrder, &rela)
+               symNo := rela.Info >> 32
+               t := R_PPC64(rela.Info & 0xffff)
+
+               if symNo == 0 || symNo > uint64(len(symbols)) {
+                       continue
+               }
+               sym := &symbols[symNo-1]
+               if SymType(sym.Info&0xf) != STT_SECTION {
+                       // We don't handle non-section relocations for now.
+                       continue
+               }
+
+               switch t {
+               case R_PPC64_ADDR64:
+                       if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+                               continue
+                       }
+                       f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
+               case R_PPC64_ADDR32:
+                       if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+                               continue
+                       }
+                       f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
+               }
+       }
+
+       return nil
+}
+
 func (f *File) DWARF() (*dwarf.Data, error) {
        // There are many other DWARF sections, but these
        // are the required ones, and the debug/dwarf package
@@ -693,7 +741,7 @@ func (f *File) DWARF() (*dwarf.Data, error) {
        // If there's a relocation table for .debug_info, we have to process it
        // now otherwise the data in .debug_info is invalid for x86-64 objects.
        rela := f.Section(".rela.debug_info")
-       if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64) {
+       if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64 || f.Machine == EM_PPC64) {
                data, err := rela.Data()
                if err != nil {
                        return nil, err
index 5e5ba52f3993a4ee79b84dd5c9e01501c4b8c5d1..d57aaab0ec2630fe7c8420792b2a920bb7e23818 100644 (file)
@@ -266,6 +266,12 @@ var relocationTests = []relocationTest{
                        {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x24)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
                },
        },
+       {
+               "testdata/go-relocation-test-gcc482-ppc64le.obj",
+               []relocationTestEntry{
+                       {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+               },
+       },
        {
                "testdata/go-relocation-test-clang-x86.obj",
                []relocationTestEntry{
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj b/src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
new file mode 100644 (file)
index 0000000..dad7445
Binary files /dev/null and b/src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj differ
index 7a51cf3c0607617fb746ae0c3315da5ba128c5d4..ed79df2939f59b749648553c5bbf2990010c6cfb 100644 (file)
@@ -1384,6 +1384,8 @@ func ArchChar(goarch string) (string, error) {
                return "6", nil
        case "arm":
                return "5", nil
+       case "power64", "power64le":
+               return "9", nil
        }
        return "", errors.New("unsupported GOARCH " + goarch)
 }
index 965f873dfb7afeffb509e66ee0fd139b71492196..2ab53bb9ccbdc3813f5dbc854561f2649ca037d5 100644 (file)
@@ -5,4 +5,4 @@
 package build
 
 const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
-const goarchList = "386 amd64 amd64p32 arm "
+const goarchList = "386 amd64 amd64p32 arm power64 power64le "
index c3fdcd685c5c74f50bda58032cd19438ff5d134c..1c7f806c605652547314d9404b32ae26e78da275 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 arm
+// +build 386 arm power64 power64le
 
 package crc32
 
index 428eb9442bff8f343dee3343f9a98ec42494881e..7971022b56b399f61ecad0ad05922ac8e3fda597 100644 (file)
@@ -1543,9 +1543,8 @@ static vlong      vaddr(Link*, Addr*, Reloc*);
 static int
 isextern(LSym *s)
 {
-       // All the Solaris dynamic imports from libc.so begin with "libc·", which
-       // the compiler rewrites to "libc." by the time liblink gets it.
-       return strncmp(s->name, "libc.", 5) == 0;
+       // All the Solaris dynamic imports from libc.so begin with "libc_".
+       return strncmp(s->name, "libc_", 5) == 0;
 }
 
 // single-instruction no-ops of various lengths.
diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c
new file mode 100644 (file)
index 0000000..3c125b3
--- /dev/null
@@ -0,0 +1,2783 @@
+// cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Instruction layout.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/9l/9.out.h"
+#include "../runtime/stack.h"
+
+enum {
+       FuncAlign = 8,
+};
+
+enum {
+       r0iszero = 1,
+};
+
+typedef        struct  Optab   Optab;
+
+struct Optab
+{
+       short   as;
+       uchar   a1;
+       uchar   a2;
+       uchar   a3;
+       uchar   a4;
+       char    type;
+       char    size;
+       char    param;
+};
+
+static Optab   optab[] = {
+       { ATEXT,        C_LEXT, C_NONE, C_NONE,         C_LCON,          0, 0, 0 },
+       { ATEXT,        C_LEXT, C_REG, C_NONE,  C_LCON,          0, 0, 0 },
+       { ATEXT,        C_LEXT, C_NONE, C_LCON,         C_LCON,          0, 0, 0 },
+       { ATEXT,        C_LEXT, C_REG, C_LCON,  C_LCON,          0, 0, 0 },
+       { ATEXT,        C_ADDR, C_NONE, C_NONE,         C_LCON,          0, 0, 0 },
+       { ATEXT,        C_ADDR, C_REG, C_NONE,  C_LCON,          0, 0, 0 },
+       { ATEXT,        C_ADDR, C_NONE, C_LCON,         C_LCON,          0, 0, 0 },
+       { ATEXT,        C_ADDR, C_REG, C_LCON,  C_LCON,          0, 0, 0 },
+
+       /* move register */
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_REG,           1, 4, 0 },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_REG,          12, 4, 0 },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_REG,          13, 4, 0 },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_REG,           12, 4, 0 },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_REG,           13, 4, 0 },
+
+       { AADD,         C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },
+       { AADD,         C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
+       { AADD,         C_ADDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
+       { AADD,         C_ADDCON,C_NONE, C_NONE, C_REG,          4, 4, 0 },
+       { AADD,         C_UCON, C_REG, C_NONE,  C_REG,          20, 4, 0 },
+       { AADD,         C_UCON, C_NONE, C_NONE,         C_REG,          20, 4, 0 },
+       { AADD,         C_LCON, C_REG, C_NONE,  C_REG,          22, 12, 0 },
+       { AADD,         C_LCON, C_NONE, C_NONE,         C_REG,          22, 12, 0 },
+
+       { AADDC,        C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },
+       { AADDC,        C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
+       { AADDC,        C_ADDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
+       { AADDC,        C_ADDCON,C_NONE, C_NONE, C_REG,          4, 4, 0 },
+       { AADDC,        C_LCON, C_REG, C_NONE,  C_REG,          22, 12, 0 },
+       { AADDC,        C_LCON, C_NONE, C_NONE,         C_REG,          22, 12, 0 },
+
+       { AAND,         C_REG,  C_REG, C_NONE,  C_REG,          6, 4, 0 },      /* logical, no literal */
+       { AAND,         C_REG,  C_NONE, C_NONE,         C_REG,          6, 4, 0 },
+       { AANDCC,       C_REG,  C_REG, C_NONE,  C_REG,          6, 4, 0 },
+       { AANDCC,       C_REG,  C_NONE, C_NONE,         C_REG,          6, 4, 0 },
+
+       { AANDCC,       C_ANDCON,C_NONE, C_NONE, C_REG,         58, 4, 0 },
+       { AANDCC,       C_ANDCON,C_REG, C_NONE,         C_REG,          58, 4, 0 },
+       { AANDCC,       C_UCON, C_NONE, C_NONE,         C_REG,          59, 4, 0 },
+       { AANDCC,       C_UCON, C_REG, C_NONE,  C_REG,          59, 4, 0 },
+       { AANDCC,       C_LCON, C_NONE, C_NONE,         C_REG,          23, 12, 0 },
+       { AANDCC,       C_LCON, C_REG, C_NONE,  C_REG,          23, 12, 0 },
+
+       { AMULLW,       C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },
+       { AMULLW,       C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
+       { AMULLW,       C_ADDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
+       { AMULLW,       C_ADDCON,C_NONE, C_NONE, C_REG,          4, 4, 0 },
+       { AMULLW,       C_ANDCON,C_REG, C_NONE,         C_REG,           4, 4, 0 },
+       { AMULLW,       C_ANDCON,       C_NONE, C_NONE, C_REG,   4, 4, 0 },
+       { AMULLW,       C_LCON, C_REG,  C_NONE, C_REG,          22, 12, 0},
+       { AMULLW,       C_LCON, C_NONE, C_NONE, C_REG,          22, 12, 0},
+
+       { ASUBC,        C_REG,  C_REG, C_NONE,  C_REG,           10, 4, 0 },
+       { ASUBC,        C_REG,  C_NONE, C_NONE,         C_REG,           10, 4, 0 },
+       { ASUBC,        C_REG,  C_NONE, C_ADDCON,       C_REG,   27, 4, 0 },
+       { ASUBC,        C_REG,  C_NONE, C_LCON, C_REG,          28, 12, 0},
+
+       { AOR,          C_REG,  C_REG, C_NONE,  C_REG,          6, 4, 0 },      /* logical, literal not cc (or/xor) */
+       { AOR,          C_REG,  C_NONE, C_NONE,         C_REG,          6, 4, 0 },
+       { AOR,          C_ANDCON, C_NONE, C_NONE,  C_REG,       58, 4, 0 },
+       { AOR,          C_ANDCON, C_REG, C_NONE,  C_REG,                58, 4, 0 },
+       { AOR,          C_UCON, C_NONE, C_NONE,  C_REG,         59, 4, 0 },
+       { AOR,          C_UCON, C_REG, C_NONE,  C_REG,          59, 4, 0 },
+       { AOR,          C_LCON, C_NONE, C_NONE,         C_REG,          23, 12, 0 },
+       { AOR,          C_LCON, C_REG, C_NONE,  C_REG,          23, 12, 0 },
+
+       { ADIVW,        C_REG,  C_REG, C_NONE,  C_REG,           2, 4, 0 },     /* op r1[,r2],r3 */
+       { ADIVW,        C_REG,  C_NONE, C_NONE,         C_REG,           2, 4, 0 },
+       { ASUB, C_REG,  C_REG, C_NONE,  C_REG,           10, 4, 0 },    /* op r2[,r1],r3 */
+       { ASUB, C_REG,  C_NONE, C_NONE,         C_REG,           10, 4, 0 },
+
+       { ASLW, C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
+       { ASLW, C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
+       { ASLD, C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
+       { ASLD, C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
+       { ASLD, C_SCON, C_REG, C_NONE,  C_REG,          25, 4, 0 },
+       { ASLD, C_SCON, C_NONE, C_NONE, C_REG,          25, 4, 0 },
+       { ASLW, C_SCON, C_REG, C_NONE,  C_REG,          57, 4, 0 },
+       { ASLW, C_SCON, C_NONE, C_NONE,         C_REG,          57, 4, 0 },
+
+       { ASRAW,        C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
+       { ASRAW,        C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
+       { ASRAW,        C_SCON, C_REG, C_NONE,  C_REG,          56, 4, 0 },
+       { ASRAW,        C_SCON, C_NONE, C_NONE,         C_REG,          56, 4, 0 },
+       { ASRAD,        C_REG,  C_NONE, C_NONE,         C_REG,           6, 4, 0 },
+       { ASRAD,        C_REG,  C_REG, C_NONE,  C_REG,           6, 4, 0 },
+       { ASRAD,        C_SCON, C_REG, C_NONE,  C_REG,          56, 4, 0 },
+       { ASRAD,        C_SCON, C_NONE, C_NONE,         C_REG,          56, 4, 0 },
+
+       { ARLWMI,       C_SCON, C_REG, C_LCON,  C_REG,          62, 4, 0 },
+       { ARLWMI,       C_REG,  C_REG, C_LCON,  C_REG,          63, 4, 0 },
+       { ARLDMI,       C_SCON, C_REG, C_LCON,  C_REG,          30, 4, 0 },
+
+       { ARLDC,        C_SCON, C_REG, C_LCON,  C_REG,          29, 4, 0 },
+       { ARLDCL,       C_SCON, C_REG, C_LCON,  C_REG,          29, 4, 0 },
+       { ARLDCL,       C_REG,  C_REG,  C_LCON, C_REG,          14, 4, 0 },
+       { ARLDCL, C_REG,        C_NONE, C_LCON, C_REG,          14, 4, 0 },
+
+       { AFADD,        C_FREG, C_NONE, C_NONE,         C_FREG,          2, 4, 0 },
+       { AFADD,        C_FREG, C_REG, C_NONE,  C_FREG,          2, 4, 0 },
+       { AFABS,        C_FREG, C_NONE, C_NONE,         C_FREG,         33, 4, 0 },
+       { AFABS,        C_NONE, C_NONE, C_NONE,         C_FREG,         33, 4, 0 },
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_FREG,         33, 4, 0 },
+
+       { AFMADD,       C_FREG, C_REG, C_FREG,  C_FREG,          34, 4, 0 },
+       { AFMUL,        C_FREG, C_NONE, C_NONE,         C_FREG,          32, 4, 0 },
+       { AFMUL,        C_FREG, C_REG, C_NONE,  C_FREG,          32, 4, 0 },
+
+       /* store, short offset */
+       { AMOVD,        C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVW,        C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVWZ,       C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVBZ,       C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVBZU,      C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVB,        C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVBU,       C_REG,  C_REG, C_NONE,  C_ZOREG,         7, 4, REGZERO },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_SEXT,          7, 4, REGSB },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_SAUTO,         7, 4, REGSP },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+       { AMOVBZU,      C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+       { AMOVBU,       C_REG,  C_NONE, C_NONE,         C_SOREG,         7, 4, REGZERO },
+
+       /* load, short offset */
+       { AMOVD,        C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
+       { AMOVW,        C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
+       { AMOVWZ,       C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
+       { AMOVBZ,       C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
+       { AMOVBZU,      C_ZOREG,C_REG, C_NONE,  C_REG,           8, 4, REGZERO },
+       { AMOVB,        C_ZOREG,C_REG, C_NONE,  C_REG,          9, 8, REGZERO },
+       { AMOVBU,       C_ZOREG,C_REG, C_NONE,  C_REG,          9, 8, REGZERO },
+       { AMOVD,        C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
+       { AMOVW,        C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
+       { AMOVWZ,       C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
+       { AMOVBZ,       C_SEXT, C_NONE, C_NONE,         C_REG,           8, 4, REGSB },
+       { AMOVB,        C_SEXT, C_NONE, C_NONE,         C_REG,          9, 8, REGSB },
+       { AMOVD,        C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
+       { AMOVW,        C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
+       { AMOVWZ,       C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
+       { AMOVBZ,       C_SAUTO,C_NONE, C_NONE,         C_REG,           8, 4, REGSP },
+       { AMOVB,        C_SAUTO,C_NONE, C_NONE,         C_REG,          9, 8, REGSP },
+       { AMOVD,        C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
+       { AMOVW,        C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
+       { AMOVWZ,       C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
+       { AMOVBZ,       C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
+       { AMOVBZU,      C_SOREG,C_NONE, C_NONE,         C_REG,           8, 4, REGZERO },
+       { AMOVB,        C_SOREG,C_NONE, C_NONE,         C_REG,          9, 8, REGZERO },
+       { AMOVBU,       C_SOREG,C_NONE, C_NONE,         C_REG,          9, 8, REGZERO },
+
+       /* store, long offset */
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
+       { AMOVBZ,       C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
+       { AMOVB,        C_REG,  C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
+
+       /* load, long offset */
+       { AMOVD,        C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
+       { AMOVW,        C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
+       { AMOVWZ,       C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
+       { AMOVBZ,       C_LEXT, C_NONE, C_NONE,         C_REG,          36, 8, REGSB },
+       { AMOVB,        C_LEXT, C_NONE, C_NONE,         C_REG,          37, 12, REGSB },
+       { AMOVD,        C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
+       { AMOVW,        C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
+       { AMOVWZ,       C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
+       { AMOVBZ,       C_LAUTO,C_NONE, C_NONE,         C_REG,          36, 8, REGSP },
+       { AMOVB,        C_LAUTO,C_NONE, C_NONE,         C_REG,          37, 12, REGSP },
+       { AMOVD,        C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
+       { AMOVW,        C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
+       { AMOVWZ,       C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
+       { AMOVBZ,       C_LOREG,C_NONE, C_NONE,         C_REG,          36, 8, REGZERO },
+       { AMOVB,        C_LOREG,C_NONE, C_NONE,         C_REG,          37, 12, REGZERO },
+       { AMOVD,        C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
+       { AMOVW,        C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
+       { AMOVWZ,       C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
+       { AMOVBZ,       C_ADDR, C_NONE, C_NONE,         C_REG,          75, 8, 0 },
+       { AMOVB,        C_ADDR, C_NONE, C_NONE,         C_REG,          76, 12, 0 },
+
+       /* load constant */
+       { AMOVD,        C_SECON,C_NONE, C_NONE,         C_REG,           3, 4, REGSB },
+       { AMOVD,        C_SACON,C_NONE, C_NONE,         C_REG,           3, 4, REGSP },
+       { AMOVD,        C_LECON,C_NONE, C_NONE,         C_REG,          26, 8, REGSB }, 
+       { AMOVD,        C_LACON,C_NONE, C_NONE,         C_REG,          26, 8, REGSP },
+       { AMOVD,        C_ADDCON,C_NONE, C_NONE, C_REG,          3, 4, REGZERO },
+       { AMOVW,        C_SECON,C_NONE, C_NONE,         C_REG,           3, 4, REGSB }, /* TO DO: check */
+       { AMOVW,        C_SACON,C_NONE, C_NONE,         C_REG,           3, 4, REGSP },
+       { AMOVW,        C_LECON,C_NONE, C_NONE,         C_REG,          26, 8, REGSB }, 
+       { AMOVW,        C_LACON,C_NONE, C_NONE,         C_REG,          26, 8, REGSP },
+       { AMOVW,        C_ADDCON,C_NONE, C_NONE, C_REG,          3, 4, REGZERO },
+       { AMOVWZ,       C_SECON,C_NONE, C_NONE,         C_REG,           3, 4, REGSB }, /* TO DO: check */
+       { AMOVWZ,       C_SACON,C_NONE, C_NONE,         C_REG,           3, 4, REGSP },
+       { AMOVWZ,       C_LECON,C_NONE, C_NONE,         C_REG,          26, 8, REGSB }, 
+       { AMOVWZ,       C_LACON,C_NONE, C_NONE,         C_REG,          26, 8, REGSP },
+       { AMOVWZ,       C_ADDCON,C_NONE, C_NONE, C_REG,          3, 4, REGZERO },
+
+       /* load unsigned/long constants (TO DO: check) */
+       { AMOVD,        C_UCON, C_NONE, C_NONE,  C_REG,         3, 4, REGZERO },
+       { AMOVD,        C_LCON, C_NONE, C_NONE,         C_REG,          19, 8, 0 },
+       { AMOVW,        C_UCON, C_NONE, C_NONE,  C_REG,         3, 4, REGZERO },
+       { AMOVW,        C_LCON, C_NONE, C_NONE,         C_REG,          19, 8, 0 },
+       { AMOVWZ,       C_UCON, C_NONE, C_NONE,  C_REG,         3, 4, REGZERO },
+       { AMOVWZ,       C_LCON, C_NONE, C_NONE,         C_REG,          19, 8, 0 },
+
+       { AMOVHBR,      C_ZOREG,        C_REG, C_NONE, C_REG,           45, 4, 0 },
+       { AMOVHBR,      C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0 },
+       { AMOVHBR,      C_REG,  C_REG, C_NONE,  C_ZOREG,                44, 4, 0 },
+       { AMOVHBR,      C_REG,  C_NONE, C_NONE, C_ZOREG,                44, 4, 0 },
+
+       { ASYSCALL,     C_NONE, C_NONE, C_NONE,         C_NONE,          5, 4, 0 },
+       { ASYSCALL,     C_REG,  C_NONE, C_NONE,         C_NONE,          77, 12, 0 },
+       { ASYSCALL,     C_SCON, C_NONE, C_NONE,         C_NONE,          77, 12, 0 },
+
+       { ABEQ,         C_NONE, C_NONE, C_NONE,         C_SBRA,         16, 4, 0 },
+       { ABEQ,         C_CREG, C_NONE, C_NONE,         C_SBRA,         16, 4, 0 },
+
+       { ABR,          C_NONE, C_NONE, C_NONE,         C_LBRA,         11, 4, 0 },
+
+       { ABC,          C_SCON, C_REG, C_NONE,  C_SBRA,         16, 4, 0 },
+       { ABC,          C_SCON, C_REG, C_NONE,  C_LBRA,         17, 4, 0 },
+
+       { ABR,          C_NONE, C_NONE, C_NONE,         C_LR,           18, 4, 0 },
+       { ABR,          C_NONE, C_NONE, C_NONE,         C_CTR,          18, 4, 0 },
+       { ABR,          C_REG,  C_NONE, C_NONE,         C_CTR,          18, 4, 0 },
+       { ABR,          C_NONE, C_NONE, C_NONE,         C_ZOREG,                15, 8, 0 },
+
+       { ABC,          C_NONE, C_REG, C_NONE,  C_LR,           18, 4, 0 },
+       { ABC,          C_NONE, C_REG, C_NONE,  C_CTR,          18, 4, 0 },
+       { ABC,          C_SCON, C_REG, C_NONE,  C_LR,           18, 4, 0 },
+       { ABC,          C_SCON, C_REG, C_NONE,  C_CTR,          18, 4, 0 },
+       { ABC,          C_NONE, C_NONE, C_NONE,         C_ZOREG,                15, 8, 0 },
+
+       { AFMOVD,       C_SEXT, C_NONE, C_NONE,         C_FREG,         8, 4, REGSB },
+       { AFMOVD,       C_SAUTO,C_NONE, C_NONE,         C_FREG,         8, 4, REGSP },
+       { AFMOVD,       C_SOREG,C_NONE, C_NONE,         C_FREG,         8, 4, REGZERO },
+
+       { AFMOVD,       C_LEXT, C_NONE, C_NONE,         C_FREG,         36, 8, REGSB },
+       { AFMOVD,       C_LAUTO,C_NONE, C_NONE,         C_FREG,         36, 8, REGSP },
+       { AFMOVD,       C_LOREG,C_NONE, C_NONE,         C_FREG,         36, 8, REGZERO },
+       { AFMOVD,       C_ADDR, C_NONE, C_NONE,         C_FREG,         75, 8, 0 },
+
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_SEXT,         7, 4, REGSB },
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_SAUTO,        7, 4, REGSP },
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_SOREG,        7, 4, REGZERO },
+
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_LEXT,         35, 8, REGSB },
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_LAUTO,        35, 8, REGSP },
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_LOREG,        35, 8, REGZERO },
+       { AFMOVD,       C_FREG, C_NONE, C_NONE,         C_ADDR,         74, 8, 0 },
+
+       { ASYNC,                C_NONE, C_NONE, C_NONE,         C_NONE,         46, 4, 0 },
+       { AWORD,        C_LCON, C_NONE, C_NONE,         C_NONE,         40, 4, 0 },
+       { ADWORD,       C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0 },
+       { ADWORD,       C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0 },
+
+       { AADDME,       C_REG,  C_NONE, C_NONE,         C_REG,          47, 4, 0 },
+
+       { AEXTSB,       C_REG,  C_NONE, C_NONE,         C_REG,          48, 4, 0 },
+       { AEXTSB,       C_NONE, C_NONE, C_NONE,         C_REG,          48, 4, 0 },
+
+       { ANEG,         C_REG,  C_NONE, C_NONE,         C_REG,          47, 4, 0 },
+       { ANEG,         C_NONE, C_NONE, C_NONE,         C_REG,          47, 4, 0 },
+
+       { AREM,         C_REG,  C_NONE, C_NONE,         C_REG,          50, 12, 0 },
+       { AREM,         C_REG,  C_REG, C_NONE,  C_REG,          50, 12, 0 },
+       { AREMU,                C_REG,  C_NONE, C_NONE,         C_REG,          50, 16, 0 },
+       { AREMU,                C_REG,  C_REG, C_NONE,  C_REG,          50, 16, 0 },
+       { AREMD,                C_REG,  C_NONE, C_NONE,         C_REG,          51, 12, 0 },
+       { AREMD,                C_REG,  C_REG, C_NONE,  C_REG,          51, 12, 0 },
+       { AREMDU,               C_REG,  C_NONE, C_NONE,         C_REG,          51, 12, 0 },
+       { AREMDU,               C_REG,  C_REG, C_NONE,  C_REG,          51, 12, 0 },
+
+       { AMTFSB0,      C_SCON, C_NONE, C_NONE,         C_NONE,         52, 4, 0 },
+       { AMOVFL, C_FPSCR, C_NONE, C_NONE,      C_FREG,         53, 4, 0 },
+       { AMOVFL, C_FREG, C_NONE, C_NONE,       C_FPSCR,                64, 4, 0 },
+       { AMOVFL, C_FREG, C_NONE, C_LCON,       C_FPSCR,                64, 4, 0 },
+       { AMOVFL,       C_LCON, C_NONE, C_NONE, C_FPSCR,                65, 4, 0 },
+
+       { AMOVD,        C_MSR,  C_NONE, C_NONE,         C_REG,          54, 4, 0 },             /* mfmsr */
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_MSR,          54, 4, 0 },             /* mtmsrd */
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_MSR,          54, 4, 0 },             /* mtmsr */
+
+       /* 64-bit special registers */
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_SPR,          66, 4, 0 },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_LR,           66, 4, 0 },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_CTR,          66, 4, 0 },
+       { AMOVD,        C_REG,  C_NONE, C_NONE,         C_XER,          66, 4, 0 },
+       { AMOVD,        C_SPR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+       { AMOVD,        C_LR,   C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+       { AMOVD,        C_CTR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+       { AMOVD,        C_XER,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+
+       /* 32-bit special registers (gloss over sign-extension or not?) */
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_SPR,          66, 4, 0 },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_CTR,          66, 4, 0 },
+       { AMOVW,        C_REG,  C_NONE, C_NONE,         C_XER,          66, 4, 0 },
+       { AMOVW,        C_SPR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+       { AMOVW,        C_XER,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_SPR,          66, 4, 0 },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_CTR,          66, 4, 0 },
+       { AMOVWZ,       C_REG,  C_NONE, C_NONE,         C_XER,          66, 4, 0 },
+       { AMOVWZ,       C_SPR,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+       { AMOVWZ,       C_XER,  C_NONE, C_NONE,         C_REG,          66, 4, 0 },
+
+       { AMOVFL,       C_FPSCR, C_NONE, C_NONE,        C_CREG,         73, 4, 0 },
+       { AMOVFL,       C_CREG, C_NONE, C_NONE,         C_CREG,         67, 4, 0 },
+       { AMOVW,        C_CREG, C_NONE, C_NONE,         C_REG,          68, 4, 0 },
+       { AMOVWZ,       C_CREG, C_NONE, C_NONE,         C_REG,          68, 4, 0 },
+       { AMOVFL,       C_REG, C_NONE, C_LCON, C_CREG,          69, 4, 0 },
+       { AMOVFL,       C_REG, C_NONE, C_NONE, C_CREG,          69, 4, 0 },
+       { AMOVW,        C_REG, C_NONE, C_NONE, C_CREG,          69, 4, 0 },
+       { AMOVWZ,       C_REG, C_NONE, C_NONE, C_CREG,          69, 4, 0 },
+
+       { ACMP, C_REG,  C_NONE, C_NONE,         C_REG,  70, 4, 0 },
+       { ACMP, C_REG,  C_REG, C_NONE,  C_REG,  70, 4, 0 },
+       { ACMP, C_REG,  C_NONE, C_NONE, C_ADDCON,       71, 4, 0 },
+       { ACMP, C_REG,  C_REG, C_NONE,  C_ADDCON,       71, 4, 0 },
+
+       { ACMPU,        C_REG,  C_NONE, C_NONE,         C_REG,  70, 4, 0 },
+       { ACMPU,        C_REG,  C_REG, C_NONE,  C_REG,  70, 4, 0 },
+       { ACMPU,        C_REG,  C_NONE, C_NONE, C_ANDCON,       71, 4, 0 },
+       { ACMPU,        C_REG,  C_REG, C_NONE,  C_ANDCON,       71, 4, 0 },
+
+       { AFCMPO,       C_FREG, C_NONE, C_NONE,         C_FREG, 70, 4, 0 },
+       { AFCMPO,       C_FREG, C_REG, C_NONE,  C_FREG, 70, 4, 0 },
+
+       { ATW,          C_LCON, C_REG, C_NONE,  C_REG,          60, 4, 0 },
+       { ATW,          C_LCON, C_REG, C_NONE,  C_ADDCON,       61, 4, 0 },
+
+       { ADCBF,        C_ZOREG, C_NONE, C_NONE,  C_NONE,       43, 4, 0 },
+       { ADCBF,        C_ZOREG, C_REG, C_NONE,  C_NONE,        43, 4, 0 },
+
+       { AECOWX,       C_REG,  C_REG, C_NONE,  C_ZOREG,        44, 4, 0 },
+       { AECIWX,       C_ZOREG, C_REG, C_NONE,  C_REG,         45, 4, 0 },
+       { AECOWX,       C_REG,  C_NONE, C_NONE,         C_ZOREG,        44, 4, 0 },
+       { AECIWX,       C_ZOREG, C_NONE, C_NONE,  C_REG,                45, 4, 0 },
+
+       { AEIEIO,       C_NONE, C_NONE, C_NONE,         C_NONE,         46, 4, 0 },
+       { ATLBIE,       C_REG, C_NONE, C_NONE,          C_NONE,         49, 4, 0 },
+       { ATLBIE,       C_SCON, C_NONE, C_NONE, C_REG,  49, 4, 0 },
+       { ASLBMFEE, C_REG, C_NONE, C_NONE,      C_REG,  55, 4, 0 },
+       { ASLBMTE, C_REG, C_NONE, C_NONE,       C_REG,  55, 4, 0 },
+
+       { ASTSW,        C_REG,  C_NONE, C_NONE,         C_ZOREG,        44, 4, 0 },
+       { ASTSW,        C_REG,  C_NONE, C_LCON,         C_ZOREG,        41, 4, 0 },
+       { ALSW, C_ZOREG, C_NONE, C_NONE,  C_REG,                45, 4, 0 },
+       { ALSW, C_ZOREG, C_NONE, C_LCON,  C_REG,                42, 4, 0 },
+
+       { AUNDEF,       C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0 },
+       { AUSEFIELD,    C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
+       { APCDATA,      C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0 },
+       { AFUNCDATA,    C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0 },
+       { ANOP,         C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
+
+       { ADUFFZERO,    C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 },  // same as ABR/ABL
+       { ADUFFCOPY,    C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 },  // same as ABR/ABL
+
+       { AXXX,         C_NONE, C_NONE, C_NONE,         C_NONE,          0, 4, 0 },
+};
+
+static int ocmp(const void *, const void *);
+static int cmp(int, int);
+static void buildop(Link*);
+static void prasm(Prog *);
+static int isint32(vlong);
+static int isuint32(uvlong);
+static int aclass(Link*, Addr*);
+static Optab* oplook(Link*, Prog*);
+static void asmout(Link*, Prog*, Optab*, int32*);
+static vlong vregoff(Link*, Addr*);
+static int32 regoff(Link*, Addr*);
+static int32 oprrr(Link*, int);
+static int32 opirr(Link*, int);
+static int32 opload(Link*, int);
+static int32 opstore(Link*, int);
+static int32 oploadx(Link*, int);
+static int32 opstorex(Link*, int);
+static int getmask(uchar*, uint32);
+static void maskgen(Link*, Prog*, uchar*, uint32);
+static int getmask64(uchar*, uvlong);
+static void maskgen64(Link*, Prog*, uchar*, uvlong);
+static uint32 loadu32(int, vlong);
+static void addaddrreloc(Link*, LSym*, int*, int*);
+
+static struct
+{
+       Optab*  start;
+       Optab*  stop;
+} oprange[ALAST];
+
+static uchar   xcmp[C_NCLASS][C_NCLASS];
+
+
+void
+span9(Link *ctxt, LSym *cursym)
+{
+       Prog *p, *q;
+       Optab *o;
+       int m, bflag;
+       vlong c, otxt;
+       int32 out[6], i, j;
+       uchar *bp, *cast;
+
+       p = cursym->text;
+       if(p == nil || p->link == nil) // handle external functions and ELF section symbols
+               return;
+       ctxt->cursym = cursym;
+       ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8;
+
+       if(oprange[AANDN].start == nil)
+               buildop(ctxt);
+
+       c = 0;  
+       p->pc = c;
+
+       for(p = p->link; p != nil; p = p->link) {
+               ctxt->curp = p;
+               p->pc = c;
+               o = oplook(ctxt, p);
+               m = o->size;
+               if(m == 0) {
+                       if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA)
+                               ctxt->diag("zero-width instruction\n%P", p);
+                       continue;
+               }
+               c += m;
+       }
+       cursym->size = c;
+
+       /*
+        * if any procedure is large enough to
+        * generate a large SBRA branch, then
+        * generate extra passes putting branches
+        * around jmps to fix. this is rare.
+        */
+       bflag = 1;
+       while(bflag) {
+               if(ctxt->debugvlog)
+                       Bprint(ctxt->bso, "%5.2f span1\n", cputime());
+               bflag = 0;
+               c = 0;
+               for(p = cursym->text->link; p != nil; p = p->link) {
+                       p->pc = c;
+                       o = oplook(ctxt, p);
+
+                       // very large conditional branches
+                       if((o->type == 16 || o->type == 17) && p->pcond) {
+                               otxt = p->pcond->pc - c;
+                               if(otxt < -(1L<<15)+10 || otxt >= (1L<<15)-10) {
+                                       q = ctxt->arch->prg();
+                                       q->link = p->link;
+                                       p->link = q;
+                                       q->as = ABR;
+                                       q->to.type = D_BRANCH;
+                                       q->pcond = p->pcond;
+                                       p->pcond = q;
+                                       q = ctxt->arch->prg();
+                                       q->link = p->link;
+                                       p->link = q;
+                                       q->as = ABR;
+                                       q->to.type = D_BRANCH;
+                                       q->pcond = q->link->link;
+                                       //addnop(p->link);
+                                       //addnop(p);
+                                       bflag = 1;
+                               }
+                       }
+
+                       m = o->size;
+                       if(m == 0) {
+                               if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA)
+                                       ctxt->diag("zero-width instruction\n%P", p);
+                               continue;
+                       }
+                       c += m;
+               }
+               cursym->size = c;
+       }
+
+       c += -c&(FuncAlign-1);
+       cursym->size = c;
+
+       /*
+        * lay out the code, emitting code and data relocations.
+        */
+       if(ctxt->tlsg == nil)
+               ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0);
+
+       symgrow(ctxt, cursym, cursym->size);
+
+       bp = cursym->p;
+       for(p = cursym->text->link; p != nil; p = p->link) {
+               ctxt->pc = p->pc;
+               ctxt->curp = p;
+               o = oplook(ctxt, p);
+               if(o->size > 4*nelem(out))
+                       sysfatal("out array in span9 is too small, need at least %d for %P", o->size/4, p);
+               asmout(ctxt, p, o, out);
+               for(i=0; i<o->size/4; i++) {
+                       cast = (uchar*)&out[i];
+                       for(j=0; j<4; j++)
+                               *bp++ = cast[inuxi4[j]];
+               }
+       }
+}
+
+static int
+isint32(vlong v)
+{
+       return (int32)v == v;
+}
+
+static int
+isuint32(uvlong v)
+{
+       return (uint32)v == v;
+}
+
+static int
+aclass(Link *ctxt, Addr *a)
+{
+       LSym *s;
+
+       switch(a->type) {
+       case D_NONE:
+               return C_NONE;
+
+       case D_REG:
+               return C_REG;
+
+       case D_FREG:
+               return C_FREG;
+
+       case D_CREG:
+               return C_CREG;
+
+       case D_SPR:
+               if(a->offset == D_LR)
+                       return C_LR;
+               if(a->offset == D_XER)
+                       return C_XER;
+               if(a->offset == D_CTR)
+                       return C_CTR;
+               return C_SPR;
+
+       case D_DCR:
+               return C_SPR;
+
+       case D_FPSCR:
+               return C_FPSCR;
+
+       case D_MSR:
+               return C_MSR;
+
+       case D_OREG:
+               switch(a->name) {
+               case D_EXTERN:
+               case D_STATIC:
+                       if(a->sym == nil)
+                               break;
+                       ctxt->instoffset = a->offset;
+                       if(a->sym != nil) // use relocation
+                               return C_ADDR;
+                       return C_LEXT;
+               case D_AUTO:
+                       ctxt->instoffset = ctxt->autosize + a->offset;
+                       if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
+                               return C_SAUTO;
+                       return C_LAUTO;
+               case D_PARAM:
+                       ctxt->instoffset = ctxt->autosize + a->offset + 8L;
+                       if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
+                               return C_SAUTO;
+                       return C_LAUTO;
+               case D_NONE:
+                       ctxt->instoffset = a->offset;
+                       if(ctxt->instoffset == 0)
+                               return C_ZOREG;
+                       if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
+                               return C_SOREG;
+                       return C_LOREG;
+               }
+               return C_GOK;
+
+       case D_OPT:
+               ctxt->instoffset = a->offset & 31L;
+               if(a->name == D_NONE)
+                       return C_SCON;
+               return C_GOK;
+
+       case D_CONST:
+               switch(a->name) {
+               case D_NONE:
+                       ctxt->instoffset = a->offset;
+                       if(a->reg != NREG) {
+                               if(-BIG <= ctxt->instoffset && ctxt->instoffset <= BIG)
+                                       return C_SACON;
+                               return C_LACON;
+                       }
+               consize:
+                       if(ctxt->instoffset >= 0) {
+                               if(ctxt->instoffset == 0)
+                                       return C_ZCON;
+                               if(ctxt->instoffset <= 0x7fff)
+                                       return C_SCON;
+                               if(ctxt->instoffset <= 0xffff)
+                                       return C_ANDCON;
+                               if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset))      /* && (instoffset & (1<<31)) == 0) */
+                                       return C_UCON;
+                               if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset))
+                                       return C_LCON;
+                               return C_DCON;
+                       }
+                       if(ctxt->instoffset >= -0x8000)
+                               return C_ADDCON;
+                       if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset))
+                               return C_UCON;
+                       if(isint32(ctxt->instoffset))
+                               return C_LCON;
+                       return C_DCON;
+
+               case D_EXTERN:
+               case D_STATIC:
+                       s = a->sym;
+                       if(s == nil)
+                               break;
+                       if(s->type == SCONST) {
+                               ctxt->instoffset = s->value + a->offset;
+                               goto consize;
+                       }
+                       ctxt->instoffset = s->value + a->offset;
+                       /* not sure why this barfs */
+                       return C_LCON;
+
+               case D_AUTO:
+                       ctxt->instoffset = ctxt->autosize + a->offset;
+                       if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
+                               return C_SACON;
+                       return C_LACON;
+
+               case D_PARAM:
+                       ctxt->instoffset = ctxt->autosize + a->offset + 8L;
+                       if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG)
+                               return C_SACON;
+                       return C_LACON;
+               }
+               return C_GOK;
+
+       case D_BRANCH:
+               return C_SBRA;
+       }
+       return C_GOK;
+}
+
+static void
+prasm(Prog *p)
+{
+       print("%P\n", p);
+}
+
+static Optab*
+oplook(Link *ctxt, Prog *p)
+{
+       int a1, a2, a3, a4, r;
+       uchar *c1, *c3, *c4;
+       Optab *o, *e;
+
+       a1 = p->optab;
+       if(a1)
+               return optab+(a1-1);
+       a1 = p->from.class;
+       if(a1 == 0) {
+               a1 = aclass(ctxt, &p->from) + 1;
+               p->from.class = a1;
+       }
+       a1--;
+       a3 = p->from3.class;
+       if(a3 == 0) {
+               a3 = aclass(ctxt, &p->from3) + 1;
+               p->from3.class = a3;
+       }
+       a3--;
+       a4 = p->to.class;
+       if(a4 == 0) {
+               a4 = aclass(ctxt, &p->to) + 1;
+               p->to.class = a4;
+       }
+       a4--;
+       a2 = C_NONE;
+       if(p->reg != NREG)
+               a2 = C_REG;
+//print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4);
+       r = p->as;
+       o = oprange[r].start;
+       if(o == 0)
+               o = oprange[r].stop; /* just generate an error */
+       e = oprange[r].stop;
+       c1 = xcmp[a1];
+       c3 = xcmp[a3];
+       c4 = xcmp[a4];
+       for(; o<e; o++)
+               if(o->a2 == a2)
+               if(c1[o->a1])
+               if(c3[o->a3])
+               if(c4[o->a4]) {
+                       p->optab = (o-optab)+1;
+                       return o;
+               }
+       ctxt->diag("illegal combination %A %^ %^ %^ %^",
+               p->as, a1, a2, a3, a4);
+       prasm(p);
+       if(o == 0)
+               o = optab;
+       return o;
+}
+
+static int
+cmp(int a, int b)
+{
+
+       if(a == b)
+               return 1;
+       switch(a) {
+       case C_LCON:
+               if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON)
+                       return 1;
+               break;
+       case C_ADDCON:
+               if(b == C_ZCON || b == C_SCON)
+                       return 1;
+               break;
+       case C_ANDCON:
+               if(b == C_ZCON || b == C_SCON)
+                       return 1;
+               break;
+       case C_SPR:
+               if(b == C_LR || b == C_XER || b == C_CTR)
+                       return 1;
+               break;
+       case C_UCON:
+               if(b == C_ZCON)
+                       return 1;
+               break;
+       case C_SCON:
+               if(b == C_ZCON)
+                       return 1;
+               break;
+       case C_LACON:
+               if(b == C_SACON)
+                       return 1;
+               break;
+       case C_LBRA:
+               if(b == C_SBRA)
+                       return 1;
+               break;
+       case C_LEXT:
+               if(b == C_SEXT)
+                       return 1;
+               break;
+       case C_LAUTO:
+               if(b == C_SAUTO)
+                       return 1;
+               break;
+       case C_REG:
+               if(b == C_ZCON)
+                       return r0iszero;
+               break;
+       case C_LOREG:
+               if(b == C_ZOREG || b == C_SOREG)
+                       return 1;
+               break;
+       case C_SOREG:
+               if(b == C_ZOREG)
+                       return 1;
+               break;
+
+       case C_ANY:
+               return 1;
+       }
+       return 0;
+}
+
+static int
+ocmp(const void *a1, const void *a2)
+{
+       const Optab *p1, *p2;
+       int n;
+
+       p1 = a1;
+       p2 = a2;
+       n = p1->as - p2->as;
+       if(n)
+               return n;
+       n = p1->a1 - p2->a1;
+       if(n)
+               return n;
+       n = p1->a2 - p2->a2;
+       if(n)
+               return n;
+       n = p1->a3 - p2->a3;
+       if(n)
+               return n;
+       n = p1->a4 - p2->a4;
+       if(n)
+               return n;
+       return 0;
+}
+
+static void
+buildop(Link *ctxt)
+{
+       int i, n, r;
+
+       for(i=0; i<C_NCLASS; i++)
+               for(n=0; n<C_NCLASS; n++)
+                       xcmp[i][n] = cmp(n, i);
+       for(n=0; optab[n].as != AXXX; n++)
+               ;
+       qsort(optab, n, sizeof(optab[0]), ocmp);
+       for(i=0; i<n; i++) {
+               r = optab[i].as;
+               oprange[r].start = optab+i;
+               while(optab[i].as == r)
+                       i++;
+               oprange[r].stop = optab+i;
+               i--;
+               
+               switch(r)
+               {
+               default:
+                       ctxt->diag("unknown op in build: %A", r);
+                       sysfatal("bad code");
+               case ADCBF:     /* unary indexed: op (b+a); op (b) */
+                       oprange[ADCBI] = oprange[r];
+                       oprange[ADCBST] = oprange[r];
+                       oprange[ADCBT] = oprange[r];
+                       oprange[ADCBTST] = oprange[r];
+                       oprange[ADCBZ] = oprange[r];
+                       oprange[AICBI] = oprange[r];
+                       break;
+               case AECOWX:    /* indexed store: op s,(b+a); op s,(b) */
+                       oprange[ASTWCCC] = oprange[r];
+                       oprange[ASTDCCC] = oprange[r];
+                       break;
+               case AREM:      /* macro */
+                       oprange[AREMCC] = oprange[r];
+                       oprange[AREMV] = oprange[r];
+                       oprange[AREMVCC] = oprange[r];
+                       break;
+               case AREMU:
+                       oprange[AREMU] = oprange[r];
+                       oprange[AREMUCC] = oprange[r];
+                       oprange[AREMUV] = oprange[r];
+                       oprange[AREMUVCC] = oprange[r];
+                       break;
+               case AREMD:
+                       oprange[AREMDCC] = oprange[r];
+                       oprange[AREMDV] = oprange[r];
+                       oprange[AREMDVCC] = oprange[r];
+                       break;
+               case AREMDU:
+                       oprange[AREMDU] = oprange[r];
+                       oprange[AREMDUCC] = oprange[r];
+                       oprange[AREMDUV] = oprange[r];
+                       oprange[AREMDUVCC] = oprange[r];
+                       break;
+               case ADIVW:     /* op Rb[,Ra],Rd */
+                       oprange[AMULHW] = oprange[r];
+                       oprange[AMULHWCC] = oprange[r];
+                       oprange[AMULHWU] = oprange[r];
+                       oprange[AMULHWUCC] = oprange[r];
+                       oprange[AMULLWCC] = oprange[r];
+                       oprange[AMULLWVCC] = oprange[r];
+                       oprange[AMULLWV] = oprange[r];
+                       oprange[ADIVWCC] = oprange[r];
+                       oprange[ADIVWV] = oprange[r];
+                       oprange[ADIVWVCC] = oprange[r];
+                       oprange[ADIVWU] = oprange[r];
+                       oprange[ADIVWUCC] = oprange[r];
+                       oprange[ADIVWUV] = oprange[r];
+                       oprange[ADIVWUVCC] = oprange[r];
+                       oprange[AADDCC] = oprange[r];
+                       oprange[AADDCV] = oprange[r];
+                       oprange[AADDCVCC] = oprange[r];
+                       oprange[AADDV] = oprange[r];
+                       oprange[AADDVCC] = oprange[r];
+                       oprange[AADDE] = oprange[r];
+                       oprange[AADDECC] = oprange[r];
+                       oprange[AADDEV] = oprange[r];
+                       oprange[AADDEVCC] = oprange[r];
+                       oprange[ACRAND] = oprange[r];
+                       oprange[ACRANDN] = oprange[r];
+                       oprange[ACREQV] = oprange[r];
+                       oprange[ACRNAND] = oprange[r];
+                       oprange[ACRNOR] = oprange[r];
+                       oprange[ACROR] = oprange[r];
+                       oprange[ACRORN] = oprange[r];
+                       oprange[ACRXOR] = oprange[r];
+                       oprange[AMULHD] = oprange[r];
+                       oprange[AMULHDCC] = oprange[r];
+                       oprange[AMULHDU] = oprange[r];
+                       oprange[AMULHDUCC] = oprange[r];
+                       oprange[AMULLD] = oprange[r];
+                       oprange[AMULLDCC] = oprange[r];
+                       oprange[AMULLDVCC] = oprange[r];
+                       oprange[AMULLDV] = oprange[r];
+                       oprange[ADIVD] = oprange[r];
+                       oprange[ADIVDCC] = oprange[r];
+                       oprange[ADIVDVCC] = oprange[r];
+                       oprange[ADIVDV] = oprange[r];
+                       oprange[ADIVDU] = oprange[r];
+                       oprange[ADIVDUCC] = oprange[r];
+                       oprange[ADIVDUVCC] = oprange[r];
+                       oprange[ADIVDUCC] = oprange[r];
+                       break;
+               case AMOVBZ:    /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */
+                       oprange[AMOVH] = oprange[r];
+                       oprange[AMOVHZ] = oprange[r];
+                       break;
+               case AMOVBZU:   /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */
+                       oprange[AMOVHU] = oprange[r];
+                       oprange[AMOVHZU] = oprange[r];
+                       oprange[AMOVWU] = oprange[r];
+                       oprange[AMOVWZU] = oprange[r];
+                       oprange[AMOVDU] = oprange[r];
+                       oprange[AMOVMW] = oprange[r];
+                       break;
+               case AAND:      /* logical op Rb,Rs,Ra; no literal */
+                       oprange[AANDN] = oprange[r];
+                       oprange[AANDNCC] = oprange[r];
+                       oprange[AEQV] = oprange[r];
+                       oprange[AEQVCC] = oprange[r];
+                       oprange[ANAND] = oprange[r];
+                       oprange[ANANDCC] = oprange[r];
+                       oprange[ANOR] = oprange[r];
+                       oprange[ANORCC] = oprange[r];
+                       oprange[AORCC] = oprange[r];
+                       oprange[AORN] = oprange[r];
+                       oprange[AORNCC] = oprange[r];
+                       oprange[AXORCC] = oprange[r];
+                       break;
+               case AADDME:    /* op Ra, Rd */
+                       oprange[AADDMECC] = oprange[r];
+                       oprange[AADDMEV] = oprange[r];
+                       oprange[AADDMEVCC] = oprange[r];
+                       oprange[AADDZE] = oprange[r];
+                       oprange[AADDZECC] = oprange[r];
+                       oprange[AADDZEV] = oprange[r];
+                       oprange[AADDZEVCC] = oprange[r];
+                       oprange[ASUBME] = oprange[r];
+                       oprange[ASUBMECC] = oprange[r];
+                       oprange[ASUBMEV] = oprange[r];
+                       oprange[ASUBMEVCC] = oprange[r];
+                       oprange[ASUBZE] = oprange[r];
+                       oprange[ASUBZECC] = oprange[r];
+                       oprange[ASUBZEV] = oprange[r];
+                       oprange[ASUBZEVCC] = oprange[r];
+                       break;
+               case AADDC:
+                       oprange[AADDCCC] = oprange[r];
+                       break;
+               case ABEQ:
+                       oprange[ABGE] = oprange[r];
+                       oprange[ABGT] = oprange[r];
+                       oprange[ABLE] = oprange[r];
+                       oprange[ABLT] = oprange[r];
+                       oprange[ABNE] = oprange[r];
+                       oprange[ABVC] = oprange[r];
+                       oprange[ABVS] = oprange[r];
+                       break;
+               case ABR:
+                       oprange[ABL] = oprange[r];
+                       break;
+               case ABC:
+                       oprange[ABCL] = oprange[r];
+                       break;
+               case AEXTSB:    /* op Rs, Ra */
+                       oprange[AEXTSBCC] = oprange[r];
+                       oprange[AEXTSH] = oprange[r];
+                       oprange[AEXTSHCC] = oprange[r];
+                       oprange[ACNTLZW] = oprange[r];
+                       oprange[ACNTLZWCC] = oprange[r];
+                       oprange[ACNTLZD] = oprange[r];
+                       oprange[AEXTSW] = oprange[r];
+                       oprange[AEXTSWCC] = oprange[r];
+                       oprange[ACNTLZDCC] = oprange[r];
+                       break;
+               case AFABS:     /* fop [s,]d */
+                       oprange[AFABSCC] = oprange[r];
+                       oprange[AFNABS] = oprange[r];
+                       oprange[AFNABSCC] = oprange[r];
+                       oprange[AFNEG] = oprange[r];
+                       oprange[AFNEGCC] = oprange[r];
+                       oprange[AFRSP] = oprange[r];
+                       oprange[AFRSPCC] = oprange[r];
+                       oprange[AFCTIW] = oprange[r];
+                       oprange[AFCTIWCC] = oprange[r];
+                       oprange[AFCTIWZ] = oprange[r];
+                       oprange[AFCTIWZCC] = oprange[r];
+                       oprange[AFCTID] = oprange[r];
+                       oprange[AFCTIDCC] = oprange[r];
+                       oprange[AFCTIDZ] = oprange[r];
+                       oprange[AFCTIDZCC] = oprange[r];
+                       oprange[AFCFID] = oprange[r];
+                       oprange[AFCFIDCC] = oprange[r];
+                       oprange[AFRES] = oprange[r];
+                       oprange[AFRESCC] = oprange[r];
+                       oprange[AFRSQRTE] = oprange[r];
+                       oprange[AFRSQRTECC] = oprange[r];
+                       oprange[AFSQRT] = oprange[r];
+                       oprange[AFSQRTCC] = oprange[r];
+                       oprange[AFSQRTS] = oprange[r];
+                       oprange[AFSQRTSCC] = oprange[r];
+                       break;
+               case AFADD:
+                       oprange[AFADDS] = oprange[r];
+                       oprange[AFADDCC] = oprange[r];
+                       oprange[AFADDSCC] = oprange[r];
+                       oprange[AFDIV] = oprange[r];
+                       oprange[AFDIVS] = oprange[r];
+                       oprange[AFDIVCC] = oprange[r];
+                       oprange[AFDIVSCC] = oprange[r];
+                       oprange[AFSUB] = oprange[r];
+                       oprange[AFSUBS] = oprange[r];
+                       oprange[AFSUBCC] = oprange[r];
+                       oprange[AFSUBSCC] = oprange[r];
+                       break;
+               case AFMADD:
+                       oprange[AFMADDCC] = oprange[r];
+                       oprange[AFMADDS] = oprange[r];
+                       oprange[AFMADDSCC] = oprange[r];
+                       oprange[AFMSUB] = oprange[r];
+                       oprange[AFMSUBCC] = oprange[r];
+                       oprange[AFMSUBS] = oprange[r];
+                       oprange[AFMSUBSCC] = oprange[r];
+                       oprange[AFNMADD] = oprange[r];
+                       oprange[AFNMADDCC] = oprange[r];
+                       oprange[AFNMADDS] = oprange[r];
+                       oprange[AFNMADDSCC] = oprange[r];
+                       oprange[AFNMSUB] = oprange[r];
+                       oprange[AFNMSUBCC] = oprange[r];
+                       oprange[AFNMSUBS] = oprange[r];
+                       oprange[AFNMSUBSCC] = oprange[r];
+                       oprange[AFSEL] = oprange[r];
+                       oprange[AFSELCC] = oprange[r];
+                       break;
+               case AFMUL:
+                       oprange[AFMULS] = oprange[r];
+                       oprange[AFMULCC] = oprange[r];
+                       oprange[AFMULSCC] = oprange[r];
+                       break;
+               case AFCMPO:
+                       oprange[AFCMPU] = oprange[r];
+                       break;
+               case AMTFSB0:
+                       oprange[AMTFSB0CC] = oprange[r];
+                       oprange[AMTFSB1] = oprange[r];
+                       oprange[AMTFSB1CC] = oprange[r];
+                       break;
+               case ANEG:      /* op [Ra,] Rd */
+                       oprange[ANEGCC] = oprange[r];
+                       oprange[ANEGV] = oprange[r];
+                       oprange[ANEGVCC] = oprange[r];
+                       break;
+               case AOR:       /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */
+                       oprange[AXOR] = oprange[r];
+                       break;
+               case ASLW:
+                       oprange[ASLWCC] = oprange[r];
+                       oprange[ASRW] = oprange[r];
+                       oprange[ASRWCC] = oprange[r];
+                       break;
+               case ASLD:
+                       oprange[ASLDCC] = oprange[r];
+                       oprange[ASRD] = oprange[r];
+                       oprange[ASRDCC] = oprange[r];
+                       break;
+               case ASRAW:     /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+                       oprange[ASRAWCC] = oprange[r];
+                       break;
+               case ASRAD:     /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */
+                       oprange[ASRADCC] = oprange[r];
+                       break;
+               case ASUB:      /* SUB Ra,Rb,Rd => subf Rd,ra,rb */
+                       oprange[ASUB] = oprange[r];
+                       oprange[ASUBCC] = oprange[r];
+                       oprange[ASUBV] = oprange[r];
+                       oprange[ASUBVCC] = oprange[r];
+                       oprange[ASUBCCC] = oprange[r];
+                       oprange[ASUBCV] = oprange[r];
+                       oprange[ASUBCVCC] = oprange[r];
+                       oprange[ASUBE] = oprange[r];
+                       oprange[ASUBECC] = oprange[r];
+                       oprange[ASUBEV] = oprange[r];
+                       oprange[ASUBEVCC] = oprange[r];
+                       break;
+               case ASYNC:
+                       oprange[AISYNC] = oprange[r];
+                       oprange[APTESYNC] = oprange[r];
+                       oprange[ATLBSYNC] = oprange[r];
+                       break;
+               case ARLWMI:
+                       oprange[ARLWMICC] = oprange[r];
+                       oprange[ARLWNM] = oprange[r];
+                       oprange[ARLWNMCC] = oprange[r];
+                       break;
+               case ARLDMI:
+                       oprange[ARLDMICC] = oprange[r];
+                       break;
+               case ARLDC:
+                       oprange[ARLDCCC] = oprange[r];
+                       break;
+               case ARLDCL:
+                       oprange[ARLDCR] = oprange[r];
+                       oprange[ARLDCLCC] = oprange[r];
+                       oprange[ARLDCRCC] = oprange[r];
+                       break;
+               case AFMOVD:
+                       oprange[AFMOVDCC] = oprange[r];
+                       oprange[AFMOVDU] = oprange[r];
+                       oprange[AFMOVS] = oprange[r];
+                       oprange[AFMOVSU] = oprange[r];
+                       break;
+               case AECIWX:
+                       oprange[ALWAR] = oprange[r];
+                       oprange[ALDAR] = oprange[r];
+                       break;
+               case ASYSCALL:  /* just the op; flow of control */
+                       oprange[ARFI] = oprange[r];
+                       oprange[ARFCI] = oprange[r];
+                       oprange[ARFID] = oprange[r];
+                       oprange[AHRFID] = oprange[r];
+                       break;
+               case AMOVHBR:
+                       oprange[AMOVWBR] = oprange[r];
+                       break;
+               case ASLBMFEE:
+                       oprange[ASLBMFEV] = oprange[r];
+                       break;
+               case ATW:
+                       oprange[ATD] = oprange[r];
+                       break;
+               case ATLBIE:
+                       oprange[ASLBIE] = oprange[r];
+                       oprange[ATLBIEL] = oprange[r];
+                       break;
+               case AEIEIO:
+                       oprange[ASLBIA] = oprange[r];
+                       break;
+               case ACMP:
+                       oprange[ACMPW] = oprange[r];
+                       break;
+               case ACMPU:
+                       oprange[ACMPWU] = oprange[r];
+                       break;
+               case AADD:
+               case AANDCC:    /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */
+               case ALSW:
+               case AMOVW:     /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */
+               case AMOVWZ:    /* load/store/move word with zero extension; move 32-bit literals  */
+               case AMOVD:     /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */
+               case AMOVB:     /* macro: move byte with sign extension */
+               case AMOVBU:    /* macro: move byte with sign extension & update */
+               case AMOVFL:
+               case AMULLW:    /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */
+               case ASUBC:     /* op r1,$s,r3; op r1[,r2],r3 */
+               case ASTSW:
+               case ASLBMTE:
+               case AWORD:
+               case ADWORD:
+               case ANOP:
+               case ATEXT:
+               case AUNDEF:
+               case AUSEFIELD:
+               case AFUNCDATA:
+               case APCDATA:
+               case ADUFFZERO:
+               case ADUFFCOPY:
+                       break;
+               }
+       }
+}
+
+#define        OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))
+#define        OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))
+#define        OP(o,xo) OPVCC((o),(xo),0,0)
+
+/* the order is dest, a/s, b/imm for both arithmetic and logical operations */
+#define        AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
+#define        AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))
+#define        LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
+#define        LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))
+#define        OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))
+#define        OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))
+#define        OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))
+#define        OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
+                                       (((mb)&31L)<<6)|(((me)&31L)<<1))
+
+#define        OP_ADD  OPVCC(31,266,0,0)
+#define        OP_ADDI OPVCC(14,0,0,0)
+#define        OP_ADDIS OPVCC(15,0,0,0)
+#define        OP_ANDI OPVCC(28,0,0,0)
+#define        OP_EXTSB        OPVCC(31,954,0,0)
+#define        OP_EXTSH OPVCC(31,922,0,0)
+#define        OP_EXTSW OPVCC(31,986,0,0)
+#define        OP_MCRF OPVCC(19,0,0,0)
+#define        OP_MCRFS OPVCC(63,64,0,0)
+#define        OP_MCRXR OPVCC(31,512,0,0)
+#define        OP_MFCR OPVCC(31,19,0,0)
+#define        OP_MFFS OPVCC(63,583,0,0)
+#define        OP_MFMSR OPVCC(31,83,0,0)
+#define        OP_MFSPR OPVCC(31,339,0,0)
+#define        OP_MFSR OPVCC(31,595,0,0)
+#define        OP_MFSRIN       OPVCC(31,659,0,0)
+#define        OP_MTCRF OPVCC(31,144,0,0)
+#define        OP_MTFSF OPVCC(63,711,0,0)
+#define        OP_MTFSFI OPVCC(63,134,0,0)
+#define        OP_MTMSR OPVCC(31,146,0,0)
+#define        OP_MTMSRD OPVCC(31,178,0,0)
+#define        OP_MTSPR OPVCC(31,467,0,0)
+#define        OP_MTSR OPVCC(31,210,0,0)
+#define        OP_MTSRIN       OPVCC(31,242,0,0)
+#define        OP_MULLW OPVCC(31,235,0,0)
+#define        OP_MULLD OPVCC(31,233,0,0)
+#define        OP_OR   OPVCC(31,444,0,0)
+#define        OP_ORI  OPVCC(24,0,0,0)
+#define        OP_ORIS OPVCC(25,0,0,0)
+#define        OP_RLWINM       OPVCC(21,0,0,0)
+#define        OP_SUBF OPVCC(31,40,0,0)
+#define        OP_RLDIC        OPVCC(30,4,0,0)
+#define        OP_RLDICR       OPVCC(30,2,0,0)
+#define        OP_RLDICL       OPVCC(30,0,0,0)
+
+#define        oclass(v)       ((v).class-1)
+
+// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
+static void
+addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2)
+{
+       Reloc *rel;
+
+       rel = addrel(ctxt->cursym);
+       rel->off = ctxt->pc;
+       rel->siz = 8;
+       rel->sym = s;
+       rel->add = ((uvlong)*o1<<32) | (uint32)*o2;
+       rel->type = R_ADDRPOWER;
+}
+
+/*
+ * 32-bit masks
+ */
+static int
+getmask(uchar *m, uint32 v)
+{
+       int i;
+
+       m[0] = m[1] = 0;
+       if(v != ~0U && v & (1<<31) && v & 1){   /* MB > ME */
+               if(getmask(m, ~v)){
+                       i = m[0]; m[0] = m[1]+1; m[1] = i-1;
+                       return 1;
+               }
+               return 0;
+       }
+       for(i=0; i<32; i++)
+               if(v & (1<<(31-i))){
+                       m[0] = i;
+                       do {
+                               m[1] = i;
+                       } while(++i<32 && (v & (1<<(31-i))) != 0);
+                       for(; i<32; i++)
+                               if(v & (1<<(31-i)))
+                                       return 0;
+                       return 1;
+               }
+       return 0;
+}
+
+static void
+maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v)
+{
+       if(!getmask(m, v))
+               ctxt->diag("cannot generate mask #%lux\n%P", v, p);
+}
+
+/*
+ * 64-bit masks (rldic etc)
+ */
+static int
+getmask64(uchar *m, uvlong v)
+{
+       int i;
+
+       m[0] = m[1] = 0;
+       for(i=0; i<64; i++)
+               if(v & ((uvlong)1<<(63-i))){
+                       m[0] = i;
+                       do {
+                               m[1] = i;
+                       } while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0);
+                       for(; i<64; i++)
+                               if(v & ((uvlong)1<<(63-i)))
+                                       return 0;
+                       return 1;
+               }
+       return 0;
+}
+
+static void
+maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v)
+{
+       if(!getmask64(m, v))
+               ctxt->diag("cannot generate mask #%llux\n%P", v, p);
+}
+
+static uint32
+loadu32(int r, vlong d)
+{
+       int32 v;
+
+       v = d>>16;
+       if(isuint32(d))
+               return LOP_IRR(OP_ORIS, r, REGZERO, v);
+       return AOP_IRR(OP_ADDIS, r, REGZERO, v);
+}
+
+static uint16
+high16adjusted(int32 d)
+{
+       if(d & 0x8000)
+               return (d>>16) + 1;
+       return d>>16;
+}
+
+static void
+asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
+{
+       int32 o1, o2, o3, o4, o5, v, t;
+       vlong d;
+       int r, a;
+       uchar mask[2];
+       Reloc *rel;
+
+       o1 = 0;
+       o2 = 0;
+       o3 = 0;
+       o4 = 0;
+       o5 = 0;
+
+//print("%P => case %d\n", p, o->type);
+       switch(o->type) {
+       default:
+               ctxt->diag("unknown type %d", o->type);
+               prasm(p);
+               break;
+
+       case 0:         /* pseudo ops */
+               break;
+
+       case 1:         /* mov r1,r2 ==> OR Rs,Rs,Ra */
+               if(p->to.reg == REGZERO && p->from.type == D_CONST) {
+                       v = regoff(ctxt, &p->from);
+                       if(r0iszero && v != 0) {
+                               //nerrors--;
+                               ctxt->diag("literal operation on R0\n%P", p);
+                       }
+                       o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
+                       break;
+               }
+               o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
+               break;
+
+       case 2:         /* int/cr/fp op Rb,[Ra],Rd */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
+               break;
+
+       case 3:         /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
+               d = vregoff(ctxt, &p->from);
+               v = d;
+               r = p->from.reg;
+               if(r == NREG)
+                       r = o->param;
+               if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))
+                       ctxt->diag("literal operation on R0\n%P", p);
+               a = OP_ADDI;
+               if(o->a1 == C_UCON) {
+                       if((d&0xffff) != 0)
+                               sysfatal("invalid handling of %P", p);
+                       v >>= 16;
+                       if(r == REGZERO && isuint32(d)){
+                               o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v);
+                               break;
+                       }
+                       a = OP_ADDIS;
+               } else {
+                       if((int16)d != d)
+                               sysfatal("invalid handling of %P", p);
+               }
+               o1 = AOP_IRR(a, p->to.reg, r, v);
+               break;
+
+       case 4:         /* add/mul $scon,[r1],r2 */
+               v = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               if(r0iszero && p->to.reg == 0)
+                       ctxt->diag("literal operation on R0\n%P", p);
+               if((int16)v != v)
+                       sysfatal("mishandled instruction %P", p);
+               o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
+               break;
+
+       case 5:         /* syscall */
+               o1 = oprrr(ctxt, p->as);
+               break;
+
+       case 6:         /* logical op Rb,[Rs,]Ra; no literal */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
+               break;
+
+       case 7:         /* mov r, soreg ==> stw o(r) */
+               r = p->to.reg;
+               if(r == NREG)
+                       r = o->param;
+               v = regoff(ctxt, &p->to);
+               if(p->to.type == D_OREG && p->reg != NREG) {
+                       if(v)
+                               ctxt->diag("illegal indexed instruction\n%P", p);
+                       o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r);
+               } else {
+                       if((int16)v != v)
+                               sysfatal("mishandled instruction %P", p);       
+                       o1 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, r, v);
+               }
+               break;
+
+       case 8:         /* mov soreg, r ==> lbz/lhz/lwz o(r) */
+               r = p->from.reg;
+               if(r == NREG)
+                       r = o->param;
+               v = regoff(ctxt, &p->from);
+               if(p->from.type == D_OREG && p->reg != NREG) {
+                       if(v)
+                               ctxt->diag("illegal indexed instruction\n%P", p);
+                       o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
+               } else {
+                       if((int16)v != v)
+                               sysfatal("mishandled instruction %P", p);
+                       o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
+               }
+               break;
+
+       case 9:         /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
+               r = p->from.reg;
+               if(r == NREG)
+                       r = o->param;
+               v = regoff(ctxt, &p->from);
+               if(p->from.type == D_OREG && p->reg != NREG) {
+                       if(v)
+                               ctxt->diag("illegal indexed instruction\n%P", p);
+                       o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r);
+               } else
+                       o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v);
+               o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
+               break;
+
+       case 10:                /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r);
+               break;
+
+       case 11:        /* br/bl lbra */
+               v = 0;
+               if(p->pcond) {
+                       v = p->pcond->pc - p->pc;
+                       if(v & 03) {
+                               ctxt->diag("odd branch target address\n%P", p);
+                               v &= ~03;
+                       }
+                       if(v < -(1L<<25) || v >= (1L<<24))
+                               ctxt->diag("branch too far\n%P", p);
+               }
+               o1 = OP_BR(opirr(ctxt, p->as), v, 0);
+               if(p->to.sym != nil) {
+                       rel = addrel(ctxt->cursym);
+                       rel->off = ctxt->pc;
+                       rel->siz = 4;
+                       rel->sym = p->to.sym;
+                       v += p->to.offset;
+                       if(v & 03) {
+                               ctxt->diag("odd branch target address\n%P", p);
+                               v &= ~03;
+                       }
+                       rel->add = o1 | (v & 0x03FFFFFC);
+                       rel->type = R_CALLPOWER;
+               }
+               break;
+
+       case 12:        /* movb r,r (extsb); movw r,r (extsw) */
+               if(p->to.reg == REGZERO && p->from.type == D_CONST) {
+                       v = regoff(ctxt, &p->from);
+                       if(r0iszero && v != 0) {
+                               ctxt->diag("literal operation on R0\n%P", p);
+                       }
+                       o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
+                       break;
+               }
+               if(p->as == AMOVW)
+                       o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0);
+               else
+                       o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
+               break;
+
+       case 13:        /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
+               if(p->as == AMOVBZ)
+                       o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
+               else if(p->as == AMOVH)
+                       o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
+               else if(p->as == AMOVHZ)
+                       o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
+               else if(p->as == AMOVWZ)
+                       o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5);        /* MB=32 */
+               else
+                       ctxt->diag("internal: bad mov[bhw]z\n%P", p);
+               break;
+
+       case 14:        /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               d = vregoff(ctxt, &p->from3);
+               maskgen64(ctxt, p, mask, d);
+               switch(p->as){
+               case ARLDCL: case ARLDCLCC:
+                       a = mask[0];    /* MB */
+                       if(mask[1] != 63)
+                               ctxt->diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p);
+                       break;
+               case ARLDCR: case ARLDCRCC:
+                       a = mask[1];    /* ME */
+                       if(mask[0] != 0)
+                               ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p);
+                       break;
+               default:
+                       ctxt->diag("unexpected op in rldc case\n%P", p);
+                       a = 0;
+               }
+               o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg);
+               o1 |= (a&31L)<<6;
+               if(a & 0x20)
+                       o1 |= 1<<5;     /* mb[5] is top bit */
+               break;
+
+       case 17:        /* bc bo,bi,lbra (same for now) */
+       case 16:        /* bc bo,bi,sbra */
+               a = 0;
+               if(p->from.type == D_CONST)
+                       a = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = 0;
+               v = 0;
+               if(p->pcond)
+                       v = p->pcond->pc - p->pc;
+               if(v & 03) {
+                       ctxt->diag("odd branch target address\n%P", p);
+                       v &= ~03;
+               }
+               if(v < -(1L<<16) || v >= (1L<<15))
+                       ctxt->diag("branch too far\n%P", p);
+               o1 = OP_BC(opirr(ctxt, p->as), a, r, v, 0);
+               break;
+
+       case 15:        /* br/bl (r) => mov r,lr; br/bl (lr) */
+               if(p->as == ABC || p->as == ABCL)
+                       v = regoff(ctxt, &p->to)&31L;
+               else
+                       v = 20; /* unconditional */
+               r = p->reg;
+               if(r == NREG)
+                       r = 0;
+               o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
+               o2 = OPVCC(19, 16, 0, 0);
+               if(p->as == ABL || p->as == ABCL)
+                       o2 |= 1;
+               o2 = OP_BCR(o2, v, r);
+               break;
+
+       case 18:        /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
+               if(p->as == ABC || p->as == ABCL)
+                       v = regoff(ctxt, &p->from)&31L;
+               else
+                       v = 20; /* unconditional */
+               r = p->reg;
+               if(r == NREG)
+                       r = 0;
+               switch(oclass(p->to)) {
+               case C_CTR:
+                       o1 = OPVCC(19, 528, 0, 0);
+                       break;
+               case C_LR:
+                       o1 = OPVCC(19, 16, 0, 0);
+                       break;
+               default:
+                       ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p);
+                       v = 0;
+               }
+               if(p->as == ABL || p->as == ABCL)
+                       o1 |= 1;
+               o1 = OP_BCR(o1, v, r);
+               break;
+
+       case 19:        /* mov $lcon,r ==> cau+or */
+               d = vregoff(ctxt, &p->from);
+               if(p->from.sym == nil) {
+                       o1 = loadu32(p->to.reg, d);
+                       o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (int32)d);
+               } else {
+                       o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(d));
+                       o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, d);
+                       addaddrreloc(ctxt, p->from.sym, &o1, &o2);
+               }
+               //if(dlm) reloc(&p->from, p->pc, 0);
+               break;
+
+       case 20:        /* add $ucon,,r */
+               v = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))
+                       ctxt->diag("literal operation on R0\n%P", p);
+               o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);
+               break;
+
+       case 22:        /* add $lcon,r1,r2 ==> cau+or+add */    /* could do add/sub more efficiently */
+               if(p->to.reg == REGTMP || p->reg == REGTMP)
+                       ctxt->diag("cant synthesize large constant\n%P", p);
+               d = vregoff(ctxt, &p->from);
+               o1 = loadu32(REGTMP, d);
+               o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
+               if(p->from.sym != nil)
+                       ctxt->diag("%P is not supported", p);
+               //if(dlm) reloc(&p->from, p->pc, 0);
+               break;
+
+       case 23:        /* and $lcon,r1,r2 ==> cau+or+and */    /* masks could be done using rlnm etc. */
+               if(p->to.reg == REGTMP || p->reg == REGTMP)
+                       ctxt->diag("cant synthesize large constant\n%P", p);
+               d = vregoff(ctxt, &p->from);
+               o1 = loadu32(REGTMP, d);
+               o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r);
+               if(p->from.sym != nil)
+                       ctxt->diag("%P is not supported", p);
+               //if(dlm) reloc(&p->from, p->pc, 0);
+               break;
+/*24*/
+
+       case 25:        /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
+               v = regoff(ctxt, &p->from);
+               if(v < 0)
+                       v = 0;
+               else if(v > 63)
+                       v = 63;
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               switch(p->as){
+               case ASLD: case ASLDCC:
+                       a = 63-v;
+                       o1 = OP_RLDICR;
+                       break;
+               case ASRD: case ASRDCC:
+                       a = v;
+                       v = 64-v;
+                       o1 = OP_RLDICL;
+                       break;
+               default:
+                       ctxt->diag("unexpected op in sldi case\n%P", p);
+                       a = 0;
+                       o1 = 0;
+               }
+               o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F));
+               o1 |= (a&31L)<<6;
+               if(v & 0x20)
+                       o1 |= 1<<1;
+               if(a & 0x20)
+                       o1 |= 1<<5;     /* mb[5] is top bit */
+               if(p->as == ASLDCC || p->as == ASRDCC)
+                       o1 |= 1;        /* Rc */
+               break;
+
+       case 26:        /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
+               if(p->to.reg == REGTMP)
+                       ctxt->diag("can't synthesize large constant\n%P", p);
+               v = regoff(ctxt, &p->from);
+               if(v & 0x8000L)
+                       v += 0x10000L;
+               r = p->from.reg;
+               if(r == NREG)
+                       r = o->param;
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
+               o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
+               break;
+
+       case 27:                /* subc ra,$simm,rd => subfic rd,ra,$simm */
+               v = regoff(ctxt, &p->from3);
+               r = p->from.reg;
+               o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
+               break;
+
+       case 28:        /* subc r1,$lcon,r2 ==> cau+or+subfc */
+               if(p->to.reg == REGTMP || p->from.reg == REGTMP)
+                       ctxt->diag("can't synthesize large constant\n%P", p);
+               v = regoff(ctxt, &p->from3);
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
+               o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
+               o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, REGTMP);
+               if(p->from.sym != nil)
+                       ctxt->diag("%P is not supported", p);
+               //if(dlm) reloc(&p->from3, p->pc, 0);
+               break;
+
+       case 29:        /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
+               v = regoff(ctxt, &p->from);
+               d = vregoff(ctxt, &p->from3);
+               maskgen64(ctxt, p, mask, d);
+               switch(p->as){
+               case ARLDC: case ARLDCCC:
+                       a = mask[0];    /* MB */
+                       if(mask[1] != (63-v))
+                               ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
+                       break;
+               case ARLDCL: case ARLDCLCC:
+                       a = mask[0];    /* MB */
+                       if(mask[1] != 63)
+                               ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
+                       break;
+               case ARLDCR: case ARLDCRCC:
+                       a = mask[1];    /* ME */
+                       if(mask[0] != 0)
+                               ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
+                       break;
+               default:
+                       ctxt->diag("unexpected op in rldic case\n%P", p);
+                       a = 0;
+               }
+               o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F));
+               o1 |= (a&31L)<<6;
+               if(v & 0x20)
+                       o1 |= 1<<1;
+               if(a & 0x20)
+                       o1 |= 1<<5;     /* mb[5] is top bit */
+               break;
+
+       case 30:        /* rldimi $sh,s,$mask,a */
+               v = regoff(ctxt, &p->from);
+               d = vregoff(ctxt, &p->from3);
+               maskgen64(ctxt, p, mask, d);
+               if(mask[1] != (63-v))
+                       ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
+               o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F));
+               o1 |= (mask[0]&31L)<<6;
+               if(v & 0x20)
+                       o1 |= 1<<1;
+               if(mask[0] & 0x20)
+                       o1 |= 1<<5;     /* mb[5] is top bit */
+               break;
+
+       case 31:        /* dword */
+               d = vregoff(ctxt, &p->from);
+               if(ctxt->arch->endian == BigEndian) {
+                       o1 = d>>32;
+                       o2 = d;
+               } else {
+                       o1 = d;
+                       o2 = d>>32;
+               }
+               if(p->from.sym != nil) {
+                       rel = addrel(ctxt->cursym);
+                       rel->off = ctxt->pc;
+                       rel->siz = 8;
+                       rel->sym = p->from.sym;
+                       rel->add = p->from.offset;
+                       rel->type = R_ADDR;
+                       o1 = o2 = 0;
+               }
+               break;
+
+       case 32:        /* fmul frc,fra,frd */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
+               break;
+
+       case 33:        /* fabs [frb,]frd; fmr. frb,frd */
+               r = p->from.reg;
+               if(oclass(p->from) == C_NONE)
+                       r = p->to.reg;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, r);
+               break;
+
+       case 34:        /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6);
+               break;
+
+       case 35:        /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
+               v = regoff(ctxt, &p->to);
+               if(v & 0x8000L)
+                       v += 0x10000L;
+               r = p->to.reg;
+               if(r == NREG)
+                       r = o->param;
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
+               o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
+               break;
+
+       case 36:        /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
+               v = regoff(ctxt, &p->from);
+               if(v & 0x8000L)
+                       v += 0x10000L;
+               r = p->from.reg;
+               if(r == NREG)
+                       r = o->param;
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
+               o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
+               break;
+
+       case 37:        /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
+               v = regoff(ctxt, &p->from);
+               if(v & 0x8000L)
+                       v += 0x10000L;
+               r = p->from.reg;
+               if(r == NREG)
+                       r = o->param;
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
+               o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
+               o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
+               break;
+
+       case 40:        /* word */
+               o1 = regoff(ctxt, &p->from);
+               break;
+
+       case 41:        /* stswi */
+               o1 = AOP_RRR(opirr(ctxt, p->as), p->from.reg, p->to.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
+               break;
+
+       case 42:        /* lswi */
+               o1 = AOP_RRR(opirr(ctxt, p->as), p->to.reg, p->from.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11);
+               break;
+
+       case 43:        /* unary indexed source: dcbf (b); dcbf (a+b) */
+               r = p->reg;
+               if(r == NREG)
+                       r = 0;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg);
+               break;
+
+       case 44:        /* indexed store */
+               r = p->reg;
+               if(r == NREG)
+                       r = 0;
+               o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg);
+               break;
+       case 45:        /* indexed load */
+               r = p->reg;
+               if(r == NREG)
+                       r = 0;
+               o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg);
+               break;
+
+       case 46:        /* plain op */
+               o1 = oprrr(ctxt, p->as);
+               break;
+
+       case 47:        /* op Ra, Rd; also op [Ra,] Rd */
+               r = p->from.reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
+               break;
+
+       case 48:        /* op Rs, Ra */
+               r = p->from.reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0);
+               break;
+
+       case 49:        /* op Rb; op $n, Rb */
+               if(p->from.type != D_REG){      /* tlbie $L, rB */
+                       v = regoff(ctxt, &p->from) & 1;
+                       o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21);
+               }else
+                       o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->from.reg);
+               break;
+
+       case 50:        /* rem[u] r1[,r2],r3 */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               v = oprrr(ctxt, p->as);
+               t = v & ((1<<10)|1);    /* OE|Rc */
+               o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
+               o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
+               o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
+               if(p->as == AREMU) {
+                       o4 = o3;
+                       /* Clear top 32 bits */
+                       o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | (1<<5);
+               }
+               break;
+
+       case 51:        /* remd[u] r1[,r2],r3 */
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               v = oprrr(ctxt, p->as);
+               t = v & ((1<<10)|1);    /* OE|Rc */
+               o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
+               o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg);
+               o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
+               break;
+
+       case 52:        /* mtfsbNx cr(n) */
+               v = regoff(ctxt, &p->from)&31L;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0);
+               break;
+
+       case 53:        /* mffsX ,fr1 */
+               o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
+               break;
+
+       case 54:        /* mov msr,r1; mov r1, msr*/
+               if(oclass(p->from) == C_REG){
+                       if(p->as == AMOVD)
+                               o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0);
+                       else
+                               o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
+               }else
+                       o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
+               break;
+
+       case 55:        /* op Rb, Rd */
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, p->from.reg);
+               break;
+
+       case 56:        /* sra $sh,[s,]a; srd $sh,[s,]a */
+               v = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L);
+               if(p->as == ASRAD && (v&0x20))
+                       o1 |= 1<<1;     /* mb[5] */
+               break;
+
+       case 57:        /* slw $sh,[s,]a -> rlwinm ... */
+               v = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               /*
+                * Let user (gs) shoot himself in the foot. 
+                * qc has already complained.
+                *
+               if(v < 0 || v > 31)
+                       ctxt->diag("illegal shift %ld\n%P", v, p);
+                */
+               if(v < 0)
+                       v = 0;
+               else if(v > 32)
+                       v = 32;
+               if(p->as == ASRW || p->as == ASRWCC) {  /* shift right */
+                       mask[0] = v;
+                       mask[1] = 31;
+                       v = 32-v;
+               } else {
+                       mask[0] = 0;
+                       mask[1] = 31-v;
+               }
+               o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
+               if(p->as == ASLWCC || p->as == ASRWCC)
+                       o1 |= 1;        /* Rc */
+               break;
+
+       case 58:                /* logical $andcon,[s],a */
+               v = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v);
+               break;
+
+       case 59:        /* or/and $ucon,,r */
+               v = regoff(ctxt, &p->from);
+               r = p->reg;
+               if(r == NREG)
+                       r = p->to.reg;
+               o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16);     /* oris, xoris, andis */
+               break;
+
+       case 60:        /* tw to,a,b */
+               r = regoff(ctxt, &p->from)&31L;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->reg, p->to.reg);
+               break;
+
+       case 61:        /* tw to,a,$simm */
+               r = regoff(ctxt, &p->from)&31L;
+               v = regoff(ctxt, &p->to);
+               o1 = AOP_IRR(opirr(ctxt, p->as), r, p->reg, v);
+               break;
+
+       case 62:        /* rlwmi $sh,s,$mask,a */
+               v = regoff(ctxt, &p->from);
+               maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
+               o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, v);
+               o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
+               break;
+
+       case 63:        /* rlwmi b,s,$mask,a */
+               maskgen(ctxt, p, mask, regoff(ctxt, &p->from3));
+               o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, p->from.reg);
+               o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
+               break;
+
+       case 64:        /* mtfsf fr[, $m] {,fpcsr} */
+               if(p->from3.type != D_NONE)
+                       v = regoff(ctxt, &p->from3)&255L;
+               else
+                       v = 255;
+               o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
+               break;
+
+       case 65:        /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
+               if(p->to.reg == NREG)
+                       ctxt->diag("must specify FPSCR(n)\n%P", p);
+               o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12);
+               break;
+
+       case 66:        /* mov spr,r1; mov r1,spr, also dcr */
+               if(p->from.type == D_REG) {
+                       r = p->from.reg;
+                       v = p->to.offset;
+                       if(p->to.type == D_DCR)
+                               o1 = OPVCC(31,451,0,0); /* mtdcr */
+                       else
+                               o1 = OPVCC(31,467,0,0); /* mtspr */
+               } else {
+                       r = p->to.reg;
+                       v = p->from.offset;
+                       if(p->from.type == D_DCR)
+                               o1 = OPVCC(31,323,0,0); /* mfdcr */
+                       else
+                               o1 = OPVCC(31,339,0,0); /* mfspr */
+               }
+               o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
+               break;
+
+       case 67:        /* mcrf crfD,crfS */
+               if(p->from.type != D_CREG || p->from.reg == NREG ||
+                  p->to.type != D_CREG || p->to.reg == NREG)
+                       ctxt->diag("illegal CR field number\n%P", p);
+               o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
+               break;
+
+       case 68:        /* mfcr rD; mfocrf CRM,rD */
+               if(p->from.type == D_CREG && p->from.reg != NREG){
+                       v = 1<<(7-(p->to.reg&7));       /* CR(n) */
+                       o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12);     /* new form, mfocrf */
+               }else
+                       o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0); /* old form, whole register */
+               break;
+
+       case 69:        /* mtcrf CRM,rS */
+               if(p->from3.type != D_NONE) {
+                       if(p->to.reg != NREG)
+                               ctxt->diag("can't use both mask and CR(n)\n%P", p);
+                       v = regoff(ctxt, &p->from3) & 0xff;
+               } else {
+                       if(p->to.reg == NREG)
+                               v = 0xff;       /* CR */
+                       else
+                               v = 1<<(7-(p->to.reg&7));       /* CR(n) */
+               }
+               o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
+               break;
+
+       case 70:        /* [f]cmp r,r,cr*/
+               if(p->reg == NREG)
+                       r = 0;
+               else
+                       r = (p->reg&7)<<2;
+               o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg);
+               break;
+
+       case 71:        /* cmp[l] r,i,cr*/
+               if(p->reg == NREG)
+                       r = 0;
+               else
+                       r = (p->reg&7)<<2;
+               o1 = AOP_RRR(opirr(ctxt, p->as), r, p->from.reg, 0) | (regoff(ctxt, &p->to)&0xffff);
+               break;
+
+       case 72:        /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
+               o1 = AOP_RRR(oprrr(ctxt, p->as), p->from.reg, 0, p->to.reg);
+               break;
+
+       case 73:        /* mcrfs crfD,crfS */
+               if(p->from.type != D_FPSCR || p->from.reg == NREG ||
+                  p->to.type != D_CREG || p->to.reg == NREG)
+                       ctxt->diag("illegal FPSCR/CR field number\n%P", p);
+               o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
+               break;
+
+       case 77:        /* syscall $scon, syscall Rx */
+               if(p->from.type == D_CONST) {
+                       if(p->from.offset > BIG || p->from.offset < -BIG)
+                               ctxt->diag("illegal syscall, sysnum too large: %P", p);
+                       o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset);
+               } else if(p->from.type == D_REG) {
+                       o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg);
+               } else {
+                       ctxt->diag("illegal syscall: %P", p);
+                       o1 = 0x7fe00008; // trap always
+               }
+               o2 = oprrr(ctxt, p->as);
+               o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO); // XOR R0, R0
+               break;
+
+       case 78:        /* undef */
+               o1 = 0; /* "An instruction consisting entirely of binary 0s is guaranteed
+                          always to be an illegal instruction."  */
+               break;
+
+       /* relocation operations */
+
+       case 74:
+               v = regoff(ctxt, &p->to);
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
+               o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v);
+               addaddrreloc(ctxt, p->to.sym, &o1, &o2);
+               //if(dlm) reloc(&p->to, p->pc, 1);
+               break;
+
+       case 75:
+               v = regoff(ctxt, &p->from);
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
+               o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
+               addaddrreloc(ctxt, p->from.sym, &o1, &o2);
+               //if(dlm) reloc(&p->from, p->pc, 1);
+               break;
+
+       case 76:
+               v = regoff(ctxt, &p->from);
+               o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v));
+               o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v);
+               addaddrreloc(ctxt, p->from.sym, &o1, &o2);
+               o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
+               //if(dlm) reloc(&p->from, p->pc, 1);
+               break;
+
+       }
+
+       out[0] = o1;
+       out[1] = o2;
+       out[2] = o3;
+       out[3] = o4;
+       out[4] = o5;
+       return;
+}
+
+static vlong
+vregoff(Link *ctxt, Addr *a)
+{
+
+       ctxt->instoffset = 0;
+       aclass(ctxt, a);
+       return ctxt->instoffset;
+}
+
+static int32
+regoff(Link *ctxt, Addr *a)
+{
+       return vregoff(ctxt, a);
+}
+
+static int32
+oprrr(Link *ctxt, int a)
+{
+       switch(a) {
+       case AADD:      return OPVCC(31,266,0,0);
+       case AADDCC:    return OPVCC(31,266,0,1);
+       case AADDV:     return OPVCC(31,266,1,0);
+       case AADDVCC:   return OPVCC(31,266,1,1);
+       case AADDC:     return OPVCC(31,10,0,0);
+       case AADDCCC:   return OPVCC(31,10,0,1);
+       case AADDCV:    return OPVCC(31,10,1,0);
+       case AADDCVCC:  return OPVCC(31,10,1,1);
+       case AADDE:     return OPVCC(31,138,0,0);
+       case AADDECC:   return OPVCC(31,138,0,1);
+       case AADDEV:    return OPVCC(31,138,1,0);
+       case AADDEVCC:  return OPVCC(31,138,1,1);
+       case AADDME:    return OPVCC(31,234,0,0);
+       case AADDMECC:  return OPVCC(31,234,0,1);
+       case AADDMEV:   return OPVCC(31,234,1,0);
+       case AADDMEVCC: return OPVCC(31,234,1,1);
+       case AADDZE:    return OPVCC(31,202,0,0);
+       case AADDZECC:  return OPVCC(31,202,0,1);
+       case AADDZEV:   return OPVCC(31,202,1,0);
+       case AADDZEVCC: return OPVCC(31,202,1,1);
+
+       case AAND:      return OPVCC(31,28,0,0);
+       case AANDCC:    return OPVCC(31,28,0,1);
+       case AANDN:     return OPVCC(31,60,0,0);
+       case AANDNCC:   return OPVCC(31,60,0,1);
+
+       case ACMP:      return OPVCC(31,0,0,0)|(1<<21); /* L=1 */
+       case ACMPU:     return OPVCC(31,32,0,0)|(1<<21);
+       case ACMPW:     return OPVCC(31,0,0,0); /* L=0 */
+       case ACMPWU:    return OPVCC(31,32,0,0);
+
+       case ACNTLZW:   return OPVCC(31,26,0,0);
+       case ACNTLZWCC: return OPVCC(31,26,0,1);
+       case ACNTLZD:           return OPVCC(31,58,0,0);
+       case ACNTLZDCC: return OPVCC(31,58,0,1);
+
+       case ACRAND:    return OPVCC(19,257,0,0);
+       case ACRANDN:   return OPVCC(19,129,0,0);
+       case ACREQV:    return OPVCC(19,289,0,0);
+       case ACRNAND:   return OPVCC(19,225,0,0);
+       case ACRNOR:    return OPVCC(19,33,0,0);
+       case ACROR:     return OPVCC(19,449,0,0);
+       case ACRORN:    return OPVCC(19,417,0,0);
+       case ACRXOR:    return OPVCC(19,193,0,0);
+
+       case ADCBF:     return OPVCC(31,86,0,0);
+       case ADCBI:     return OPVCC(31,470,0,0);
+       case ADCBST:    return OPVCC(31,54,0,0);
+       case ADCBT:     return OPVCC(31,278,0,0);
+       case ADCBTST:   return OPVCC(31,246,0,0);
+       case ADCBZ:     return OPVCC(31,1014,0,0);
+
+       case AREM:
+       case ADIVW:     return OPVCC(31,491,0,0);
+       case AREMCC:
+       case ADIVWCC:   return OPVCC(31,491,0,1);
+       case AREMV:
+       case ADIVWV:    return OPVCC(31,491,1,0);
+       case AREMVCC:
+       case ADIVWVCC:  return OPVCC(31,491,1,1);
+       case AREMU:
+       case ADIVWU:    return OPVCC(31,459,0,0);
+       case AREMUCC:
+       case ADIVWUCC:  return OPVCC(31,459,0,1);
+       case AREMUV:
+       case ADIVWUV:   return OPVCC(31,459,1,0);
+       case AREMUVCC:
+       case ADIVWUVCC: return OPVCC(31,459,1,1);
+
+       case AREMD:
+       case ADIVD:     return OPVCC(31,489,0,0);
+       case AREMDCC:
+       case ADIVDCC:   return OPVCC(31,489,0,1);
+       case AREMDV:
+       case ADIVDV:    return OPVCC(31,489,1,0);
+       case AREMDVCC:
+       case ADIVDVCC:  return OPVCC(31,489,1,1);
+       case AREMDU:
+       case ADIVDU:    return OPVCC(31,457,0,0);
+       case AREMDUCC:
+       case ADIVDUCC:  return OPVCC(31,457,0,1);
+       case AREMDUV:
+       case ADIVDUV:   return OPVCC(31,457,1,0);
+       case AREMDUVCC:
+       case ADIVDUVCC: return OPVCC(31,457,1,1);
+
+       case AEIEIO:    return OPVCC(31,854,0,0);
+
+       case AEQV:      return OPVCC(31,284,0,0);
+       case AEQVCC:    return OPVCC(31,284,0,1);
+
+       case AEXTSB:    return OPVCC(31,954,0,0);
+       case AEXTSBCC:  return OPVCC(31,954,0,1);
+       case AEXTSH:    return OPVCC(31,922,0,0);
+       case AEXTSHCC:  return OPVCC(31,922,0,1);
+       case AEXTSW:    return OPVCC(31,986,0,0);
+       case AEXTSWCC:  return OPVCC(31,986,0,1);
+
+       case AFABS:     return OPVCC(63,264,0,0);
+       case AFABSCC:   return OPVCC(63,264,0,1);
+       case AFADD:     return OPVCC(63,21,0,0);
+       case AFADDCC:   return OPVCC(63,21,0,1);
+       case AFADDS:    return OPVCC(59,21,0,0);
+       case AFADDSCC:  return OPVCC(59,21,0,1);
+       case AFCMPO:    return OPVCC(63,32,0,0);
+       case AFCMPU:    return OPVCC(63,0,0,0);
+       case AFCFID:    return OPVCC(63,846,0,0);
+       case AFCFIDCC:  return OPVCC(63,846,0,1);
+       case AFCTIW:    return OPVCC(63,14,0,0);
+       case AFCTIWCC:  return OPVCC(63,14,0,1);
+       case AFCTIWZ:   return OPVCC(63,15,0,0);
+       case AFCTIWZCC: return OPVCC(63,15,0,1);
+       case AFCTID:    return OPVCC(63,814,0,0);
+       case AFCTIDCC:  return OPVCC(63,814,0,1);
+       case AFCTIDZ:   return OPVCC(63,815,0,0);
+       case AFCTIDZCC: return OPVCC(63,815,0,1);
+       case AFDIV:     return OPVCC(63,18,0,0);
+       case AFDIVCC:   return OPVCC(63,18,0,1);
+       case AFDIVS:    return OPVCC(59,18,0,0);
+       case AFDIVSCC:  return OPVCC(59,18,0,1);
+       case AFMADD:    return OPVCC(63,29,0,0);
+       case AFMADDCC:  return OPVCC(63,29,0,1);
+       case AFMADDS:   return OPVCC(59,29,0,0);
+       case AFMADDSCC: return OPVCC(59,29,0,1);
+       case AFMOVS:
+       case AFMOVD:    return OPVCC(63,72,0,0);        /* load */
+       case AFMOVDCC:  return OPVCC(63,72,0,1);
+       case AFMSUB:    return OPVCC(63,28,0,0);
+       case AFMSUBCC:  return OPVCC(63,28,0,1);
+       case AFMSUBS:   return OPVCC(59,28,0,0);
+       case AFMSUBSCC: return OPVCC(59,28,0,1);
+       case AFMUL:     return OPVCC(63,25,0,0);
+       case AFMULCC:   return OPVCC(63,25,0,1);
+       case AFMULS:    return OPVCC(59,25,0,0);
+       case AFMULSCC:  return OPVCC(59,25,0,1);
+       case AFNABS:    return OPVCC(63,136,0,0);
+       case AFNABSCC:  return OPVCC(63,136,0,1);
+       case AFNEG:     return OPVCC(63,40,0,0);
+       case AFNEGCC:   return OPVCC(63,40,0,1);
+       case AFNMADD:   return OPVCC(63,31,0,0);
+       case AFNMADDCC: return OPVCC(63,31,0,1);
+       case AFNMADDS:  return OPVCC(59,31,0,0);
+       case AFNMADDSCC:        return OPVCC(59,31,0,1);
+       case AFNMSUB:   return OPVCC(63,30,0,0);
+       case AFNMSUBCC: return OPVCC(63,30,0,1);
+       case AFNMSUBS:  return OPVCC(59,30,0,0);
+       case AFNMSUBSCC:        return OPVCC(59,30,0,1);
+       case AFRES:     return OPVCC(59,24,0,0);
+       case AFRESCC:   return OPVCC(59,24,0,1);
+       case AFRSP:     return OPVCC(63,12,0,0);
+       case AFRSPCC:   return OPVCC(63,12,0,1);
+       case AFRSQRTE:  return OPVCC(63,26,0,0);
+       case AFRSQRTECC:        return OPVCC(63,26,0,1);
+       case AFSEL:     return OPVCC(63,23,0,0);
+       case AFSELCC:   return OPVCC(63,23,0,1);
+       case AFSQRT:    return OPVCC(63,22,0,0);
+       case AFSQRTCC:  return OPVCC(63,22,0,1);
+       case AFSQRTS:   return OPVCC(59,22,0,0);
+       case AFSQRTSCC: return OPVCC(59,22,0,1);
+       case AFSUB:     return OPVCC(63,20,0,0);
+       case AFSUBCC:   return OPVCC(63,20,0,1);
+       case AFSUBS:    return OPVCC(59,20,0,0);
+       case AFSUBSCC:  return OPVCC(59,20,0,1);
+
+       case AICBI:     return OPVCC(31,982,0,0);
+       case AISYNC:    return OPVCC(19,150,0,0);
+
+       case AMTFSB0:   return OPVCC(63,70,0,0);
+       case AMTFSB0CC: return OPVCC(63,70,0,1);
+       case AMTFSB1:   return OPVCC(63,38,0,0);
+       case AMTFSB1CC: return OPVCC(63,38,0,1);
+
+       case AMULHW:    return OPVCC(31,75,0,0);
+       case AMULHWCC:  return OPVCC(31,75,0,1);
+       case AMULHWU:   return OPVCC(31,11,0,0);
+       case AMULHWUCC: return OPVCC(31,11,0,1);
+       case AMULLW:    return OPVCC(31,235,0,0);
+       case AMULLWCC:  return OPVCC(31,235,0,1);
+       case AMULLWV:   return OPVCC(31,235,1,0);
+       case AMULLWVCC: return OPVCC(31,235,1,1);
+
+       case AMULHD:    return OPVCC(31,73,0,0);
+       case AMULHDCC:  return OPVCC(31,73,0,1);
+       case AMULHDU:   return OPVCC(31,9,0,0);
+       case AMULHDUCC: return OPVCC(31,9,0,1);
+       case AMULLD:    return OPVCC(31,233,0,0);
+       case AMULLDCC:  return OPVCC(31,233,0,1);
+       case AMULLDV:   return OPVCC(31,233,1,0);
+       case AMULLDVCC: return OPVCC(31,233,1,1);
+
+       case ANAND:     return OPVCC(31,476,0,0);
+       case ANANDCC:   return OPVCC(31,476,0,1);
+       case ANEG:      return OPVCC(31,104,0,0);
+       case ANEGCC:    return OPVCC(31,104,0,1);
+       case ANEGV:     return OPVCC(31,104,1,0);
+       case ANEGVCC:   return OPVCC(31,104,1,1);
+       case ANOR:      return OPVCC(31,124,0,0);
+       case ANORCC:    return OPVCC(31,124,0,1);
+       case AOR:       return OPVCC(31,444,0,0);
+       case AORCC:     return OPVCC(31,444,0,1);
+       case AORN:      return OPVCC(31,412,0,0);
+       case AORNCC:    return OPVCC(31,412,0,1);
+
+       case ARFI:      return OPVCC(19,50,0,0);
+       case ARFCI:     return OPVCC(19,51,0,0);
+       case ARFID:     return OPVCC(19,18,0,0);
+       case AHRFID: return OPVCC(19,274,0,0);
+
+       case ARLWMI:    return OPVCC(20,0,0,0);
+       case ARLWMICC: return OPVCC(20,0,0,1);
+       case ARLWNM:    return OPVCC(23,0,0,0);
+       case ARLWNMCC:  return OPVCC(23,0,0,1);
+
+       case ARLDCL:    return OPVCC(30,8,0,0);
+       case ARLDCR:    return OPVCC(30,9,0,0);
+
+       case ASYSCALL:  return OPVCC(17,1,0,0);
+
+       case ASLW:      return OPVCC(31,24,0,0);
+       case ASLWCC:    return OPVCC(31,24,0,1);
+       case ASLD:      return OPVCC(31,27,0,0);
+       case ASLDCC:    return OPVCC(31,27,0,1);
+
+       case ASRAW:     return OPVCC(31,792,0,0);
+       case ASRAWCC:   return OPVCC(31,792,0,1);
+       case ASRAD:     return OPVCC(31,794,0,0);
+       case ASRADCC:   return OPVCC(31,794,0,1);
+
+       case ASRW:      return OPVCC(31,536,0,0);
+       case ASRWCC:    return OPVCC(31,536,0,1);
+       case ASRD:      return OPVCC(31,539,0,0);
+       case ASRDCC:    return OPVCC(31,539,0,1);
+
+       case ASUB:      return OPVCC(31,40,0,0);
+       case ASUBCC:    return OPVCC(31,40,0,1);
+       case ASUBV:     return OPVCC(31,40,1,0);
+       case ASUBVCC:   return OPVCC(31,40,1,1);
+       case ASUBC:     return OPVCC(31,8,0,0);
+       case ASUBCCC:   return OPVCC(31,8,0,1);
+       case ASUBCV:    return OPVCC(31,8,1,0);
+       case ASUBCVCC:  return OPVCC(31,8,1,1);
+       case ASUBE:     return OPVCC(31,136,0,0);
+       case ASUBECC:   return OPVCC(31,136,0,1);
+       case ASUBEV:    return OPVCC(31,136,1,0);
+       case ASUBEVCC:  return OPVCC(31,136,1,1);
+       case ASUBME:    return OPVCC(31,232,0,0);
+       case ASUBMECC:  return OPVCC(31,232,0,1);
+       case ASUBMEV:   return OPVCC(31,232,1,0);
+       case ASUBMEVCC: return OPVCC(31,232,1,1);
+       case ASUBZE:    return OPVCC(31,200,0,0);
+       case ASUBZECC:  return OPVCC(31,200,0,1);
+       case ASUBZEV:   return OPVCC(31,200,1,0);
+       case ASUBZEVCC: return OPVCC(31,200,1,1);
+
+       case ASYNC:     return OPVCC(31,598,0,0);
+       case APTESYNC:  return OPVCC(31,598,0,0) | (2<<21);
+
+       case ATLBIE:    return OPVCC(31,306,0,0);
+       case ATLBIEL:   return OPVCC(31,274,0,0);
+       case ATLBSYNC:  return OPVCC(31,566,0,0);
+       case ASLBIA:    return OPVCC(31,498,0,0);
+       case ASLBIE:    return OPVCC(31,434,0,0);
+       case ASLBMFEE:  return OPVCC(31,915,0,0);
+       case ASLBMFEV:  return OPVCC(31,851,0,0);
+       case ASLBMTE:           return OPVCC(31,402,0,0);
+
+       case ATW:       return OPVCC(31,4,0,0);
+       case ATD:       return OPVCC(31,68,0,0);
+
+       case AXOR:      return OPVCC(31,316,0,0);
+       case AXORCC:    return OPVCC(31,316,0,1);
+       }
+       ctxt->diag("bad r/r opcode %A", a);
+       return 0;
+}
+
+static int32
+opirr(Link *ctxt, int a)
+{
+       switch(a) {
+       case AADD:      return OPVCC(14,0,0,0);
+       case AADDC:     return OPVCC(12,0,0,0);
+       case AADDCCC:   return OPVCC(13,0,0,0);
+       case AADD+AEND: return OPVCC(15,0,0,0);         /* ADDIS/CAU */
+
+       case AANDCC:    return OPVCC(28,0,0,0);
+       case AANDCC+AEND:       return OPVCC(29,0,0,0);         /* ANDIS./ANDIU. */
+
+       case ABR:       return OPVCC(18,0,0,0);
+       case ABL:       return OPVCC(18,0,0,0) | 1;
+       case ADUFFZERO: return OPVCC(18,0,0,0) | 1;
+       case ADUFFCOPY: return OPVCC(18,0,0,0) | 1;
+       case ABC:       return OPVCC(16,0,0,0);
+       case ABCL:      return OPVCC(16,0,0,0) | 1;
+
+       case ABEQ:      return AOP_RRR(16<<26,12,2,0);
+       case ABGE:      return AOP_RRR(16<<26,4,0,0);
+       case ABGT:      return AOP_RRR(16<<26,12,1,0);
+       case ABLE:      return AOP_RRR(16<<26,4,1,0);
+       case ABLT:      return AOP_RRR(16<<26,12,0,0);
+       case ABNE:      return AOP_RRR(16<<26,4,2,0);
+       case ABVC:      return AOP_RRR(16<<26,4,3,0);
+       case ABVS:      return AOP_RRR(16<<26,12,3,0);
+
+       case ACMP:      return OPVCC(11,0,0,0)|(1<<21); /* L=1 */
+       case ACMPU:     return OPVCC(10,0,0,0)|(1<<21);
+       case ACMPW:     return OPVCC(11,0,0,0); /* L=0 */
+       case ACMPWU:    return OPVCC(10,0,0,0);
+       case ALSW:      return OPVCC(31,597,0,0);
+
+       case AMULLW:    return OPVCC(7,0,0,0);
+
+       case AOR:       return OPVCC(24,0,0,0);
+       case AOR+AEND:  return OPVCC(25,0,0,0);         /* ORIS/ORIU */
+
+       case ARLWMI:    return OPVCC(20,0,0,0);         /* rlwimi */
+       case ARLWMICC:  return OPVCC(20,0,0,1);
+       case ARLDMI:    return OPVCC(30,0,0,0) | (3<<2);        /* rldimi */
+       case ARLDMICC:  return OPVCC(30,0,0,1) | (3<<2);
+
+       case ARLWNM:    return OPVCC(21,0,0,0);         /* rlwinm */
+       case ARLWNMCC:  return OPVCC(21,0,0,1);
+
+       case ARLDCL:    return OPVCC(30,0,0,0);         /* rldicl */
+       case ARLDCLCC:  return OPVCC(30,0,0,1);
+       case ARLDCR:    return OPVCC(30,1,0,0);         /* rldicr */
+       case ARLDCRCC:  return OPVCC(30,1,0,1);
+       case ARLDC:     return OPVCC(30,0,0,0) | (2<<2);
+       case ARLDCCC:   return OPVCC(30,0,0,1) | (2<<2);
+
+       case ASRAW:     return OPVCC(31,824,0,0);
+       case ASRAWCC:   return OPVCC(31,824,0,1);
+       case ASRAD:     return OPVCC(31,(413<<1),0,0);
+       case ASRADCC:   return OPVCC(31,(413<<1),0,1);
+
+       case ASTSW:     return OPVCC(31,725,0,0);
+
+       case ASUBC:     return OPVCC(8,0,0,0);
+
+       case ATW:       return OPVCC(3,0,0,0);
+       case ATD:       return OPVCC(2,0,0,0);
+
+       case AXOR:      return OPVCC(26,0,0,0);         /* XORIL */
+       case AXOR+AEND: return OPVCC(27,0,0,0);         /* XORIU */
+       }
+       ctxt->diag("bad opcode i/r %A", a);
+       return 0;
+}
+
+/*
+ * load o(a),d
+ */
+static int32
+opload(Link *ctxt, int a)
+{
+       switch(a) {
+       case AMOVD:     return OPVCC(58,0,0,0); /* ld */
+       case AMOVDU:    return OPVCC(58,0,0,1); /* ldu */
+       case AMOVWZ:    return OPVCC(32,0,0,0);         /* lwz */
+       case AMOVWZU:   return OPVCC(33,0,0,0);         /* lwzu */
+       case AMOVW:             return OPVCC(58,0,0,0)|(1<<1);  /* lwa */
+       /* no AMOVWU */
+       case AMOVB:
+       case AMOVBZ:    return OPVCC(34,0,0,0);         /* load */
+       case AMOVBU:
+       case AMOVBZU:   return OPVCC(35,0,0,0);
+       case AFMOVD:    return OPVCC(50,0,0,0);
+       case AFMOVDU:   return OPVCC(51,0,0,0);
+       case AFMOVS:    return OPVCC(48,0,0,0);
+       case AFMOVSU:   return OPVCC(49,0,0,0);
+       case AMOVH:     return OPVCC(42,0,0,0);
+       case AMOVHU:    return OPVCC(43,0,0,0);
+       case AMOVHZ:    return OPVCC(40,0,0,0);
+       case AMOVHZU:   return OPVCC(41,0,0,0);
+       case AMOVMW:    return OPVCC(46,0,0,0); /* lmw */
+       }
+       ctxt->diag("bad load opcode %A", a);
+       return 0;
+}
+
+/*
+ * indexed load a(b),d
+ */
+static int32
+oploadx(Link *ctxt, int a)
+{
+       switch(a) {
+       case AMOVWZ: return OPVCC(31,23,0,0);   /* lwzx */
+       case AMOVWZU:   return OPVCC(31,55,0,0); /* lwzux */
+       case AMOVW:     return OPVCC(31,341,0,0);       /* lwax */
+       case AMOVWU:    return OPVCC(31,373,0,0);       /* lwaux */
+       case AMOVB:
+       case AMOVBZ: return OPVCC(31,87,0,0);   /* lbzx */
+       case AMOVBU:
+       case AMOVBZU: return OPVCC(31,119,0,0); /* lbzux */
+       case AFMOVD:    return OPVCC(31,599,0,0);       /* lfdx */
+       case AFMOVDU:   return OPVCC(31,631,0,0);       /*  lfdux */
+       case AFMOVS:    return OPVCC(31,535,0,0);       /* lfsx */
+       case AFMOVSU:   return OPVCC(31,567,0,0);       /* lfsux */
+       case AMOVH:     return OPVCC(31,343,0,0);       /* lhax */
+       case AMOVHU:    return OPVCC(31,375,0,0);       /* lhaux */
+       case AMOVHBR:   return OPVCC(31,790,0,0);       /* lhbrx */
+       case AMOVWBR:   return OPVCC(31,534,0,0);       /* lwbrx */
+       case AMOVHZ:    return OPVCC(31,279,0,0);       /* lhzx */
+       case AMOVHZU:   return OPVCC(31,311,0,0);       /* lhzux */
+       case AECIWX:    return OPVCC(31,310,0,0);       /* eciwx */
+       case ALWAR:     return OPVCC(31,20,0,0);        /* lwarx */
+       case ALDAR:     return OPVCC(31,84,0,0);
+       case ALSW:      return OPVCC(31,533,0,0);       /* lswx */
+       case AMOVD:     return OPVCC(31,21,0,0);        /* ldx */
+       case AMOVDU:    return OPVCC(31,53,0,0);        /* ldux */
+       }
+       ctxt->diag("bad loadx opcode %A", a);
+       return 0;
+}
+
+/*
+ * store s,o(d)
+ */
+static int32
+opstore(Link *ctxt, int a)
+{
+       switch(a) {
+       case AMOVB:
+       case AMOVBZ:    return OPVCC(38,0,0,0); /* stb */
+       case AMOVBU:
+       case AMOVBZU:   return OPVCC(39,0,0,0); /* stbu */
+       case AFMOVD:    return OPVCC(54,0,0,0); /* stfd */
+       case AFMOVDU:   return OPVCC(55,0,0,0); /* stfdu */
+       case AFMOVS:    return OPVCC(52,0,0,0); /* stfs */
+       case AFMOVSU:   return OPVCC(53,0,0,0); /* stfsu */
+       case AMOVHZ:
+       case AMOVH:     return OPVCC(44,0,0,0); /* sth */
+       case AMOVHZU:
+       case AMOVHU:    return OPVCC(45,0,0,0); /* sthu */
+       case AMOVMW:    return OPVCC(47,0,0,0); /* stmw */
+       case ASTSW:     return OPVCC(31,725,0,0);       /* stswi */
+       case AMOVWZ:
+       case AMOVW:     return OPVCC(36,0,0,0); /* stw */
+       case AMOVWZU:
+       case AMOVWU:    return OPVCC(37,0,0,0); /* stwu */
+       case AMOVD:     return OPVCC(62,0,0,0); /* std */
+       case AMOVDU:    return OPVCC(62,0,0,1); /* stdu */
+       }
+       ctxt->diag("unknown store opcode %A", a);
+       return 0;
+}
+
+/*
+ * indexed store s,a(b)
+ */
+static int32
+opstorex(Link *ctxt, int a)
+{
+       switch(a) {
+       case AMOVB:
+       case AMOVBZ:    return OPVCC(31,215,0,0);       /* stbx */
+       case AMOVBU:
+       case AMOVBZU:   return OPVCC(31,247,0,0);       /* stbux */
+       case AFMOVD:    return OPVCC(31,727,0,0);       /* stfdx */
+       case AFMOVDU:   return OPVCC(31,759,0,0);       /* stfdux */
+       case AFMOVS:    return OPVCC(31,663,0,0);       /* stfsx */
+       case AFMOVSU:   return OPVCC(31,695,0,0);       /* stfsux */
+       case AMOVHZ:
+       case AMOVH:     return OPVCC(31,407,0,0);       /* sthx */
+       case AMOVHBR:   return OPVCC(31,918,0,0);       /* sthbrx */
+       case AMOVHZU:
+       case AMOVHU:    return OPVCC(31,439,0,0);       /* sthux */
+       case AMOVWZ:
+       case AMOVW:     return OPVCC(31,151,0,0);       /* stwx */
+       case AMOVWZU:
+       case AMOVWU:    return OPVCC(31,183,0,0);       /* stwux */
+       case ASTSW:     return OPVCC(31,661,0,0);       /* stswx */
+       case AMOVWBR:   return OPVCC(31,662,0,0);       /* stwbrx */
+       case ASTWCCC:   return OPVCC(31,150,0,1);       /* stwcx. */
+       case ASTDCCC:   return OPVCC(31,214,0,1);       /* stwdx. */
+       case AECOWX:    return OPVCC(31,438,0,0);       /* ecowx */
+       case AMOVD:     return OPVCC(31,149,0,0);       /* stdx */
+       case AMOVDU:    return OPVCC(31,181,0,0);       /* stdux */
+       }
+       ctxt->diag("unknown storex opcode %A", a);
+       return 0;
+}
+
index 0635fdf1feb55d45c65cabd6f8a639c7e7417225..54cce4aa4b0573cdc7bb96f54abfbfadea4cb941 100644 (file)
@@ -82,6 +82,19 @@ Pconv(Fmt *fp)
 
        p = va_arg(fp->args, Prog*);
        bigP = p;
+
+       if(fp->flags & FmtSharp) {
+               char *s = str;
+               s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
+               if(p->from.type != D_NONE)
+                       s += sprint(s, " from={%#D}", &p->from);
+               if(p->reg)
+                       s += sprint(s, " reg=%d", p->reg);
+               if(p->to.type != D_NONE)
+                       s += sprint(s, " to={%#D}", &p->to);
+               return fmtstrcpy(fp, str);
+       }
+
        switch(p->as) {
        case ADATA:
                sprint(str, "%.5lld (%L)        %A      %D/%d,%D",
@@ -126,6 +139,31 @@ Dconv(Fmt *fp)
        a = va_arg(fp->args, Addr*);
        i = a->type;
 
+       if(fp->flags & FmtSharp) {
+               char *s = str;
+               s += sprint(s, "type=");
+               if(i == D_NONE) {
+                       sprint(s, "NONE");
+                       goto brk;
+               }
+               if(i >= D_INDIR) {
+                       i -= D_INDIR;
+                       s += sprint(s, "INDIR+");
+               }
+               if(i >= 0 && i < D_LAST && dnames6[i] != nil)
+                       s += sprint(s, "%s ", dnames6[i]);
+               else
+                       s += sprint(s, "%d ", i);
+               s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
+               if(a->class != 0)
+                       s += sprint(s, " class=%s", cnames9[(int)a->class]);
+               if(a->sym != nil)
+                       s += sprint(s, " sym=%s", a->sym->name);
+               if(a->type == D_BRANCH && a->u.branch != nil)
+                       s += sprint(s, " branch=%.5lld", a->u.branch->pc);
+               goto brk;
+       }
+
        if(fp->flags & FmtLong) {
                if(i == D_CONST)
                        sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
diff --git a/src/liblink/list9.c b/src/liblink/list9.c
new file mode 100644 (file)
index 0000000..5436e36
--- /dev/null
@@ -0,0 +1,451 @@
+// cmd/9l/list.c from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/9l/9.out.h"
+
+enum
+{
+       STRINGSZ        = 1000,
+};
+
+static int     Aconv(Fmt*);
+static int     Dconv(Fmt*);
+static int     Pconv(Fmt*);
+static int     Rconv(Fmt*);
+static int     DSconv(Fmt*);
+static int     Mconv(Fmt*);
+static int     DRconv(Fmt*);
+
+//
+// Format conversions
+//     %A int          Opcodes (instruction mnemonics)
+//
+//     %D Addr*        Addresses (instruction operands)
+//             Flags: "%lD": seperate the high and low words of a constant by "-"
+//
+//     %P Prog*        Instructions
+//
+//     %R int          Registers
+//
+//     %$ char*        String constant addresses (for internal use only)
+//     %^ int          C_* classes (for liblink internal use)
+
+#pragma        varargck        type    "$"     char*
+#pragma        varargck        type    "M"     Addr*
+
+void
+listinit9(void)
+{
+       fmtinstall('A', Aconv);
+       fmtinstall('D', Dconv);
+       fmtinstall('P', Pconv);
+       fmtinstall('R', Rconv);
+
+       // for liblink internal use
+       fmtinstall('^', DRconv);
+
+       // for internal use
+       fmtinstall('$', DSconv);
+       fmtinstall('M', Mconv);
+}
+
+static Prog*   bigP;
+
+static int
+Pconv(Fmt *fp)
+{
+       char str[STRINGSZ], *s;
+       Prog *p;
+       int a;
+
+       p = va_arg(fp->args, Prog*);
+       bigP = p;
+       a = p->as;
+
+       if(fp->flags & FmtSharp) {
+               s = str;
+               s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
+               if(p->from.type != D_NONE)
+                       s += sprint(s, " from={%#D}", &p->from);
+               if(p->reg)
+                       s += sprint(s, " reg=%d", p->reg);
+               if(p->from3.type != D_NONE)
+                       s += sprint(s, " from3={%#D}", &p->from3);
+               if(p->to.type != D_NONE)
+                       s += sprint(s, " to={%#D}", &p->to);
+               return fmtstrcpy(fp, str);
+       }
+
+       if(a == ADATA || a == AINIT || a == ADYNT)
+               sprint(str, "%.5lld (%L)        %A      %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
+       else if(a == ATEXT) {
+               if(p->reg != 0)
+                       sprint(str, "%.5lld (%L)        %A      %D,%d,%lD", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
+               else
+                       sprint(str, "%.5lld (%L)        %A      %D,%lD", p->pc, p->lineno, a, &p->from, &p->to);
+       } else if(a == AGLOBL) {
+               if(p->reg != 0)
+                       sprint(str, "%.5lld (%L)        %A      %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
+               else
+                       sprint(str, "%.5lld (%L)        %A      %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
+       } else {
+               s = str;
+               if(p->mark & NOSCHED)
+                       s += sprint(s, "*");
+               if(p->reg == NREG && p->from3.type == D_NONE)
+                       sprint(s, "%.5lld (%L)  %A      %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
+               else
+               if(a != ATEXT && p->from.type == D_OREG) {
+                       sprint(s, "%.5lld (%L)  %A      %lld(R%d+R%d),%D", p->pc, p->lineno, a,
+                               p->from.offset, p->from.reg, p->reg, &p->to);
+               } else
+               if(p->to.type == D_OREG) {
+                       sprint(s, "%.5lld (%L)  %A      %D,%lld(R%d+R%d)", p->pc, p->lineno, a,
+                                       &p->from, p->to.offset, p->to.reg, p->reg);
+               } else {
+                       s += sprint(s, "%.5lld (%L)     %A      %D", p->pc, p->lineno, a, &p->from);
+                       if(p->reg != NREG)
+                               s += sprint(s, ",%c%d", p->from.type==D_FREG?'F':'R', p->reg);
+                       if(p->from3.type != D_NONE)
+                               s += sprint(s, ",%D", &p->from3);
+                       sprint(s, ",%D", &p->to);
+               }
+               if(p->spadj != 0)
+                       return fmtprint(fp, "%s # spadj=%d", str, p->spadj);
+       }
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Aconv(Fmt *fp)
+{
+       char *s;
+       int a;
+
+       a = va_arg(fp->args, int);
+       s = "???";
+       if(a >= AXXX && a < ALAST)
+               s = anames9[a];
+       return fmtstrcpy(fp, s);
+}
+
+static int
+Dconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Addr *a;
+       int32 v;
+
+       a = va_arg(fp->args, Addr*);
+
+       if(fp->flags & FmtSharp) {
+               char *s = str;
+               if(a->type == D_NONE) {
+                       sprint(s, "type=NONE");
+                       goto ret;
+               }
+               if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
+                       s += sprint(s, "type=%s ", dnames9[a->type]);
+               else
+                       s += sprint(s, "type=%d ", a->type);
+               if(a->name >= 0 && a->name < D_LAST && dnames9[a->name] != nil)
+                       s += sprint(s, "name=%s ", dnames9[a->name]);
+               else
+                       s += sprint(s, "name=%d ", a->name);
+               s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
+               if(a->class != 0)
+                       s += sprint(s, " class=%s", cnames9[a->class]);
+               if(a->reg != NREG)
+                       s += sprint(s, " reg=%d", a->reg);
+               if(a->sym != nil)
+                       s += sprint(s, " sym=%s", a->sym->name);
+               if(a->type == D_BRANCH && a->u.branch != nil)
+                       s += sprint(s, " branch=%.5lld", a->u.branch->pc);
+               goto ret;
+       }
+
+       if(fp->flags & FmtLong) {
+               if(a->type == D_CONST)
+                       sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
+               else {
+                       // ATEXT dst is not constant
+                       sprint(str, "!!%D", a);
+               }
+               goto ret;
+       }
+
+       switch(a->type) {
+       default:
+               sprint(str, "GOK-type(%d)", a->type);
+               break;
+
+       case D_NONE:
+               str[0] = 0;
+               if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
+                       sprint(str, "%M(R%d)(NONE)", a, a->reg);
+               break;
+
+       case D_CONST:
+       case D_DCONST:
+               if(a->reg != NREG)
+                       sprint(str, "$%M(R%d)", a, a->reg);
+               else
+                       sprint(str, "$%M", a);
+               break;
+
+       case D_OREG:
+               if(a->reg != NREG)
+                       sprint(str, "%M(R%d)", a, a->reg);
+               else
+                       sprint(str, "%M", a);
+               break;
+
+       case D_REG:
+               sprint(str, "R%d", a->reg);
+               if(a->name != D_NONE || a->sym != nil)
+                       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 != nil)
+                       sprint(str, "%M(F%d)(REG)", a, a->reg);
+               break;
+
+       case D_CREG:
+               if(a->reg == NREG)
+                       strcpy(str, "CR");
+               else
+                       sprint(str, "CR%d", a->reg);
+               if(a->name != D_NONE || a->sym != nil)
+                       sprint(str, "%M(C%d)(REG)", a, a->reg);
+               break;
+
+       case D_SPR:
+               if(a->name == D_NONE && a->sym == nil) {
+                       switch((ulong)a->offset) {
+                       case D_XER: sprint(str, "XER"); break;
+                       case D_LR: sprint(str, "LR"); break;
+                       case D_CTR: sprint(str, "CTR"); break;
+                       default: sprint(str, "SPR(%lld)", a->offset); break;
+                       }
+                       break;
+               }
+               sprint(str, "SPR-GOK(%d)", a->reg);
+               if(a->name != D_NONE || a->sym != nil)
+                       sprint(str, "%M(SPR-GOK%d)(REG)", a, a->reg);
+               break;
+
+       case D_DCR:
+               if(a->name == D_NONE && a->sym == nil) {
+                       sprint(str, "DCR(%lld)", a->offset);
+                       break;
+               }
+               sprint(str, "DCR-GOK(%d)", a->reg);
+               if(a->name != D_NONE || a->sym != nil)
+                       sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg);
+               break;
+
+       case D_OPT:
+               sprint(str, "OPT(%d)", a->reg);
+               break;
+
+       case D_FPSCR:
+               if(a->reg == NREG)
+                       strcpy(str, "FPSCR");
+               else
+                       sprint(str, "FPSCR(%d)", a->reg);
+               break;
+
+       case D_MSR:
+               sprint(str, "MSR");
+               break;
+
+       case D_BRANCH:
+               if(bigP->pcond != nil) {
+                       v = bigP->pcond->pc;
+                       //if(v >= INITTEXT)
+                       //      v -= INITTEXT-HEADR;
+                       if(a->sym != nil)
+                               sprint(str, "%s+%.5ux(BRANCH)", a->sym->name, v);
+                       else
+                               sprint(str, "%.5ux(BRANCH)", v);
+               } else if(a->u.branch != nil)
+                       sprint(str, "%lld", a->u.branch->pc);
+               else if(a->sym != nil)
+                       sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
+               else
+                       sprint(str, "%lld(APC)", a->offset);
+               break;
+
+       case D_FCONST:
+               //sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
+               sprint(str, "$%.17g", a->u.dval);
+               break;
+
+       case D_SCONST:
+               sprint(str, "$\"%$\"", a->u.sval);
+               break;
+       }
+
+ret:
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Mconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       Addr *a;
+       LSym *s;
+       int32 l;
+
+       a = va_arg(fp->args, Addr*);
+       s = a->sym;
+       //if(s == nil) {
+       //      l = a->offset;
+       //      if((vlong)l != a->offset)
+       //              sprint(str, "0x%llux", a->offset);
+       //      else
+       //              sprint(str, "%lld", a->offset);
+       //      goto out;
+       //}
+       switch(a->name) {
+       default:
+               sprint(str, "GOK-name(%d)", a->name);
+               break;
+
+       case D_NONE:
+               l = a->offset;
+               if((vlong)l != a->offset)
+                       sprint(str, "0x%llux", a->offset);
+               else
+                       sprint(str, "%lld", a->offset);
+               break;
+
+       case D_EXTERN:
+               if(a->offset != 0)
+                       sprint(str, "%s+%lld(SB)", s->name, a->offset);
+               else
+                       sprint(str, "%s(SB)", s->name);
+               break;
+
+       case D_STATIC:
+               sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
+               break;
+
+       case D_AUTO:
+               if(s == nil)
+                       sprint(str, "%lld(SP)", -a->offset);
+               else
+                       sprint(str, "%s-%lld(SP)", s->name, -a->offset);
+               break;
+
+       case D_PARAM:
+               if(s == nil)
+                       sprint(str, "%lld(FP)", a->offset);
+               else
+                       sprint(str, "%s+%lld(FP)", s->name, a->offset);
+               break;
+       }
+//out:
+       return fmtstrcpy(fp, str);
+}
+
+static int
+Rconv(Fmt *fp)
+{
+       char str[STRINGSZ];
+       int r;
+
+       r = va_arg(fp->args, int);
+       if(r < NREG)
+               sprint(str, "r%d", r);
+       else
+               sprint(str, "f%d", r-NREG);
+       return fmtstrcpy(fp, str);
+}
+
+static int
+DRconv(Fmt *fp)
+{
+       char *s;
+       int a;
+
+       a = va_arg(fp->args, int);
+       s = "C_??";
+       if(a >= C_NONE && a <= C_NCLASS)
+               s = cnames9[a];
+       return fmtstrcpy(fp, s);
+}
+
+static int
+DSconv(Fmt *fp)
+{
+       int i, c;
+       char str[STRINGSZ], *p, *a;
+
+       a = va_arg(fp->args, char*);
+       p = str;
+       for(i=0; i<sizeof(int32); i++) {
+               c = a[i] & 0xff;
+               if(c >= 'a' && c <= 'z' ||
+                  c >= 'A' && c <= 'Z' ||
+                  c >= '0' && c <= '9' ||
+                  c == ' ' || c == '%') {
+                       *p++ = c;
+                       continue;
+               }
+               *p++ = '\\';
+               switch(c) {
+               case 0:
+                       *p++ = 'z';
+                       continue;
+               case '\\':
+               case '"':
+                       *p++ = c;
+                       continue;
+               case '\n':
+                       *p++ = 'n';
+                       continue;
+               case '\t':
+                       *p++ = 't';
+                       continue;
+               }
+               *p++ = (c>>6) + '0';
+               *p++ = ((c>>3) & 7) + '0';
+               *p++ = (c & 7) + '0';
+       }
+       *p = 0;
+       return fmtstrcpy(fp, str);
+}
diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c
new file mode 100644 (file)
index 0000000..10a1f16
--- /dev/null
@@ -0,0 +1,1083 @@
+// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/9l/9.out.h"
+#include "../runtime/stack.h"
+#include "../runtime/funcdata.h"
+
+static Prog zprg = {
+       .as = AGOK,
+       .reg = NREG,
+       .from = {
+               .name = D_NONE,
+               .type = D_NONE,
+               .reg = NREG,
+       },
+       .from3 = {
+               .name = D_NONE,
+               .type = D_NONE,
+               .reg = NREG,
+       },
+       .to = {
+               .name = D_NONE,
+               .type = D_NONE,
+               .reg = NREG,
+       },
+};
+
+static int
+symtype(Addr *a)
+{
+       return a->name;
+}
+
+static int
+isdata(Prog *p)
+{
+       return p->as == ADATA || p->as == AGLOBL;
+}
+
+static int
+iscall(Prog *p)
+{
+       return p->as == ABL;
+}
+
+static int
+datasize(Prog *p)
+{
+       return p->reg;
+}
+
+static int
+textflag(Prog *p)
+{
+       return p->reg;
+}
+
+static void
+settextflag(Prog *p, int f)
+{
+       p->reg = f;
+}
+
+static void
+progedit(Link *ctxt, Prog *p)
+{
+       char literal[64];
+       LSym *s;
+
+       USED(ctxt);
+
+       p->from.class = 0;
+       p->to.class = 0;
+
+       // Rewrite BR/BL to symbol as D_BRANCH.
+       switch(p->as) {
+       case ABR:
+       case ABL:
+       case ARETURN:
+       case ADUFFZERO:
+       case ADUFFCOPY:
+               if(p->to.sym != nil)
+                       p->to.type = D_BRANCH;
+               break;
+       }
+
+       // Rewrite float constants to values stored in memory.
+       switch(p->as) {
+       case AFMOVS:
+               if(p->from.type == D_FCONST) {
+                       int32 i32;
+                       float32 f32;
+                       f32 = p->from.u.dval;
+                       memmove(&i32, &f32, 4);
+                       sprint(literal, "$f32.%08ux", (uint32)i32);
+                       s = linklookup(ctxt, literal, 0);
+                       s->size = 4;
+                       p->from.type = D_OREG;
+                       p->from.sym = s;
+                       p->from.name = D_EXTERN;
+                       p->from.offset = 0;
+               }
+               break;
+       case AFMOVD:
+               if(p->from.type == D_FCONST) {
+                       int64 i64;
+                       memmove(&i64, &p->from.u.dval, 8);
+                       sprint(literal, "$f64.%016llux", (uvlong)i64);
+                       s = linklookup(ctxt, literal, 0);
+                       s->size = 8;
+                       p->from.type = D_OREG;
+                       p->from.sym = s;
+                       p->from.name = D_EXTERN;
+                       p->from.offset = 0;
+               }
+               break;
+       case AMOVD:
+               if(p->from.type == D_CONST && p->from.name == D_NONE && (int64)(uint32)p->from.offset != p->from.offset) {
+                       sprint(literal, "$i64.%016llux", (uvlong)p->from.offset);
+                       s = linklookup(ctxt, literal, 0);
+                       s->size = 8;
+                       p->from.type = D_OREG;
+                       p->from.sym = s;
+                       p->from.name = D_EXTERN;
+                       p->from.offset = 0;
+               }
+       }
+
+       // Rewrite SUB constants into ADD.
+       switch(p->as) {
+       case ASUBC:
+               if(p->from.type == D_CONST) {
+                       p->from.offset = -p->from.offset;
+                       p->as = AADDC;
+               }
+               break;
+
+       case ASUBCCC:
+               if(p->from.type == D_CONST) {
+                       p->from.offset = -p->from.offset;
+                       p->as = AADDCCC;
+               }
+               break;
+
+       case ASUB:
+               if(p->from.type == D_CONST) {
+                       p->from.offset = -p->from.offset;
+                       p->as = AADD;
+               }
+               break;
+       }
+}
+
+static Prog*   stacksplit(Link*, Prog*, int32, int);
+
+static void
+parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
+{
+       *textstksiz = arg & 0xffffffffLL;
+       if(*textstksiz & 0x80000000LL)
+               *textstksiz = -(-*textstksiz & 0xffffffffLL);
+
+       *textarg = (arg >> 32) & 0xffffffffLL;
+       if(*textarg & 0x80000000LL)
+               *textarg = 0;
+       *textarg = (*textarg+7) & ~7LL;
+}
+
+static void
+addstacksplit(Link *ctxt, LSym *cursym)
+{
+       Prog *p, *q, *p1, *p2, *q1;
+       int o, mov, aoffset;
+       vlong textstksiz, textarg;
+       int32 autosize;
+
+       if(ctxt->symmorestack[0] == nil) {
+               ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0);
+               ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
+               // TODO(minux): add morestack short-cuts with small fixed frame-size.
+       }
+
+       ctxt->cursym = cursym;
+
+       if(cursym->text == nil || cursym->text->link == nil)
+               return;                         
+
+       p = cursym->text;
+       parsetextconst(p->to.offset, &textstksiz, &textarg);
+       
+       cursym->args = p->to.offset>>32;
+       cursym->locals = textstksiz;
+
+       /*
+        * find leaf subroutines
+        * strip NOPs
+        * expand RET
+        * expand BECOME pseudo
+        */
+
+       if(ctxt->debugvlog)
+               Bprint(ctxt->bso, "%5.2f noops\n", cputime());
+       Bflush(ctxt->bso);
+
+       q = nil;
+       for(p = cursym->text; p != nil; p = p->link) {
+               switch(p->as) {
+               /* too hard, just leave alone */
+               case ATEXT:
+                       q = p;
+                       p->mark |= LABEL|LEAF|SYNC;
+                       if(p->link)
+                               p->link->mark |= LABEL;
+                       break;
+
+               case ANOR:
+                       q = p;
+                       if(p->to.type == D_REG)
+                               if(p->to.reg == REGZERO)
+                                       p->mark |= LABEL|SYNC;
+                       break;
+
+               case ALWAR:
+               case ASTWCCC:
+               case AECIWX:
+               case AECOWX:
+               case AEIEIO:
+               case AICBI:
+               case AISYNC:
+               case ATLBIE:
+               case ATLBIEL:
+               case ASLBIA:
+               case ASLBIE:
+               case ASLBMFEE:
+               case ASLBMFEV:
+               case ASLBMTE:
+               case ADCBF:
+               case ADCBI:
+               case ADCBST:
+               case ADCBT:
+               case ADCBTST:
+               case ADCBZ:
+               case ASYNC:
+               case ATLBSYNC:
+               case APTESYNC:
+               case ATW:
+               case AWORD:
+               case ARFI:
+               case ARFCI:
+               case ARFID:
+               case AHRFID:
+                       q = p;
+                       p->mark |= LABEL|SYNC;
+                       continue;
+
+               case AMOVW:
+               case AMOVWZ:
+               case AMOVD:
+                       q = p;
+                       switch(p->from.type) {
+                       case D_MSR:
+                       case D_SPR:
+                       case D_FPSCR:
+                       case D_CREG:
+                       case D_DCR:
+                               p->mark |= LABEL|SYNC;
+                       }
+                       switch(p->to.type) {
+                       case D_MSR:
+                       case D_SPR:
+                       case D_FPSCR:
+                       case D_CREG:
+                       case D_DCR:
+                               p->mark |= LABEL|SYNC;
+                       }
+                       continue;
+
+               case AFABS:
+               case AFABSCC:
+               case AFADD:
+               case AFADDCC:
+               case AFCTIW:
+               case AFCTIWCC:
+               case AFCTIWZ:
+               case AFCTIWZCC:
+               case AFDIV:
+               case AFDIVCC:
+               case AFMADD:
+               case AFMADDCC:
+               case AFMOVD:
+               case AFMOVDU:
+               /* case AFMOVDS: */
+               case AFMOVS:
+               case AFMOVSU:
+               /* case AFMOVSD: */
+               case AFMSUB:
+               case AFMSUBCC:
+               case AFMUL:
+               case AFMULCC:
+               case AFNABS:
+               case AFNABSCC:
+               case AFNEG:
+               case AFNEGCC:
+               case AFNMADD:
+               case AFNMADDCC:
+               case AFNMSUB:
+               case AFNMSUBCC:
+               case AFRSP:
+               case AFRSPCC:
+               case AFSUB:
+               case AFSUBCC:
+                       q = p;
+                       p->mark |= FLOAT;
+                       continue;
+
+               case ABL:
+               case ABCL:
+               case ADUFFZERO:
+               case ADUFFCOPY:
+                       cursym->text->mark &= ~LEAF;
+
+               case ABC:
+               case ABEQ:
+               case ABGE:
+               case ABGT:
+               case ABLE:
+               case ABLT:
+               case ABNE:
+               case ABR:
+               case ABVC:
+               case ABVS:
+                       p->mark |= BRANCH;
+                       q = p;
+                       q1 = p->pcond;
+                       if(q1 != nil) {
+                               while(q1->as == ANOP) {
+                                       q1 = q1->link;
+                                       p->pcond = q1;
+                               }
+                               if(!(q1->mark & LEAF))
+                                       q1->mark |= LABEL;
+                       } else
+                               p->mark |= LABEL;
+                       q1 = p->link;
+                       if(q1 != nil)
+                               q1->mark |= LABEL;
+                       continue;
+
+               case AFCMPO:
+               case AFCMPU:
+                       q = p;
+                       p->mark |= FCMP|FLOAT;
+                       continue;
+
+               case ARETURN:
+                       q = p;
+                       if(p->link != nil)
+                               p->link->mark |= LABEL;
+                       continue;
+
+               case ANOP:
+                       q1 = p->link;
+                       q->link = q1;           /* q is non-nop */
+                       q1->mark |= p->mark;
+                       continue;
+
+               default:
+                       q = p;
+                       continue;
+               }
+       }
+
+       autosize = 0;
+       for(p = cursym->text; p != nil; p = p->link) {
+               o = p->as;
+               switch(o) {
+               case ATEXT:
+                       mov = AMOVD;
+                       aoffset = 0;
+                       autosize = textstksiz + 8;
+                       if((p->mark & LEAF) && autosize <= 8)
+                               autosize = 0;
+                       else
+                               if(autosize & 4)
+                                       autosize += 4;
+                       p->to.offset = (p->to.offset & (0xffffffffull<<32)) | (uint32)(autosize-8);
+
+                       if(!(p->reg & NOSPLIT))
+                               p = stacksplit(ctxt, p, autosize, !(cursym->text->reg&NEEDCTXT)); // emit split check
+
+                       q = p;
+                       if(autosize) {
+                               /* use MOVDU to adjust R1 when saving R31, if autosize is small */
+                               if(!(cursym->text->mark & LEAF) && autosize >= -BIG && autosize <= BIG) {
+                                       mov = AMOVDU;
+                                       aoffset = -autosize;
+                               } else {
+                                       q = appendp(ctxt, p);
+                                       q->as = AADD;
+                                       q->lineno = p->lineno;
+                                       q->from.type = D_CONST;
+                                       q->from.offset = -autosize;
+                                       q->to.type = D_REG;
+                                       q->to.reg = REGSP;
+                                       q->spadj = +autosize;
+                               }
+                       } else
+                       if(!(cursym->text->mark & LEAF)) {
+                               if(ctxt->debugvlog) {
+                                       Bprint(ctxt->bso, "save suppressed in: %s\n",
+                                               cursym->name);
+                                       Bflush(ctxt->bso);
+                               }
+                               cursym->text->mark |= LEAF;
+                       }
+
+                       if(cursym->text->mark & LEAF) {
+                               cursym->leaf = 1;
+                               break;
+                       }
+
+                       q = appendp(ctxt, q);
+                       q->as = AMOVD;
+                       q->lineno = p->lineno;
+                       q->from.type = D_SPR;
+                       q->from.offset = D_LR;
+                       q->to.type = D_REG;
+                       q->to.reg = REGTMP;
+
+                       q = appendp(ctxt, q);
+                       q->as = mov;
+                       q->lineno = p->lineno;
+                       q->from.type = D_REG;
+                       q->from.reg = REGTMP;
+                       q->to.type = D_OREG;
+                       q->to.offset = aoffset;
+                       q->to.reg = REGSP;
+                       if(q->as == AMOVDU)
+                               q->spadj = -aoffset;
+
+                       if(cursym->text->reg & WRAPPER) {
+                               // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+                               //
+                               //      MOVD g_panic(g), R3
+                               //      CMP R0, R3
+                               //      BEQ end
+                               //      MOVD panic_argp(R3), R4
+                               //      ADD $(autosize+8), R1, R5
+                               //      CMP R4, R5
+                               //      BNE end
+                               //      ADD $8, R1, R6
+                               //      MOVD R6, panic_argp(R3)
+                               // end:
+                               //      NOP
+                               //
+                               // The NOP is needed to give the jumps somewhere to land.
+                               // It is a liblink NOP, not a Power64 NOP: it encodes to 0 instruction bytes.
+
+
+                               q = appendp(ctxt, q);
+                               q->as = AMOVD;
+                               q->from.type = D_OREG;
+                               q->from.reg = REGG;
+                               q->from.offset = 4*ctxt->arch->ptrsize; // G.panic
+                               q->to.type = D_REG;
+                               q->to.reg = 3;
+
+                               q = appendp(ctxt, q);
+                               q->as = ACMP;
+                               q->from.type = D_REG;
+                               q->from.reg = 0;
+                               q->to.type = D_REG;
+                               q->to.reg = 3;
+
+                               q = appendp(ctxt, q);
+                               q->as = ABEQ;
+                               q->to.type = D_BRANCH;
+                               p1 = q;
+
+                               q = appendp(ctxt, q);
+                               q->as = AMOVD;
+                               q->from.type = D_OREG;
+                               q->from.reg = 3;
+                               q->from.offset = 0; // Panic.argp
+                               q->to.type = D_REG;
+                               q->to.reg = 4;
+
+                               q = appendp(ctxt, q);
+                               q->as = AADD;
+                               q->from.type = D_CONST;
+                               q->from.offset = autosize+8;
+                               q->reg = REGSP;
+                               q->to.type = D_REG;
+                               q->to.reg = 5;
+
+                               q = appendp(ctxt, q);
+                               q->as = ACMP;
+                               q->from.type = D_REG;
+                               q->from.reg = 4;
+                               q->to.type = D_REG;
+                               q->to.reg = 5;
+
+                               q = appendp(ctxt, q);
+                               q->as = ABNE;
+                               q->to.type = D_BRANCH;
+                               p2 = q;
+
+                               q = appendp(ctxt, q);
+                               q->as = AADD;
+                               q->from.type = D_CONST;
+                               q->from.offset = 8;
+                               q->reg = REGSP;
+                               q->to.type = D_REG;
+                               q->to.reg = 6;
+
+                               q = appendp(ctxt, q);
+                               q->as = AMOVD;
+                               q->from.type = D_REG;
+                               q->from.reg = 6;
+                               q->to.type = D_OREG;
+                               q->to.reg = 3;
+                               q->to.offset = 0; // Panic.argp
+
+                               q = appendp(ctxt, q);
+                               q->as = ANOP;
+                               p1->pcond = q;
+                               p2->pcond = q;
+                       }
+
+                       break;
+
+               case ARETURN:
+                       if(p->from.type == D_CONST) {
+                               ctxt->diag("using BECOME (%P) is not supported!", p);
+                               break;
+                       }
+                       if(p->to.sym) { // retjmp
+                               p->as = ABR;
+                               p->to.type = D_BRANCH;
+                               break;
+                       }
+                       if(cursym->text->mark & LEAF) {
+                               if(!autosize) {
+                                       p->as = ABR;
+                                       p->from = zprg.from;
+                                       p->to.type = D_SPR;
+                                       p->to.offset = D_LR;
+                                       p->mark |= BRANCH;
+                                       break;
+                               }
+
+                               p->as = AADD;
+                               p->from.type = D_CONST;
+                               p->from.offset = autosize;
+                               p->to.type = D_REG;
+                               p->to.reg = REGSP;
+                               p->spadj = -autosize;
+
+                               q = ctxt->arch->prg();
+                               q->as = ABR;
+                               q->lineno = p->lineno;
+                               q->to.type = D_SPR;
+                               q->to.offset = D_LR;
+                               q->mark |= BRANCH;
+                               q->spadj = +autosize;
+
+                               q->link = p->link;
+                               p->link = q;
+                               break;
+                       }
+
+                       p->as = AMOVD;
+                       p->from.type = D_OREG;
+                       p->from.offset = 0;
+                       p->from.reg = REGSP;
+                       p->to.type = D_REG;
+                       p->to.reg = REGTMP;
+
+                       q = ctxt->arch->prg();
+                       q->as = AMOVD;
+                       q->lineno = p->lineno;
+                       q->from.type = D_REG;
+                       q->from.reg = REGTMP;
+                       q->to.type = D_SPR;
+                       q->to.offset = D_LR;
+
+                       q->link = p->link;
+                       p->link = q;
+                       p = q;
+
+                       if(autosize) {
+                               q = ctxt->arch->prg();
+                               q->as = AADD;
+                               q->lineno = p->lineno;
+                               q->from.type = D_CONST;
+                               q->from.offset = autosize;
+                               q->to.type = D_REG;
+                               q->to.reg = REGSP;
+                               q->spadj = -autosize;
+
+                               q->link = p->link;
+                               p->link = q;
+                       }
+
+                       q1 = ctxt->arch->prg();
+                       q1->as = ABR;
+                       q1->lineno = p->lineno;
+                       q1->to.type = D_SPR;
+                       q1->to.offset = D_LR;
+                       q1->mark |= BRANCH;
+                       q1->spadj = +autosize;
+
+                       q1->link = q->link;
+                       q->link = q1;
+                       break;
+
+               case AADD:
+                       if(p->to.type == D_REG && p->to.reg == REGSP && p->from.type == D_CONST)
+                               p->spadj = -p->from.offset;
+                       break;
+               }
+       }
+
+#if 0 // instruction scheduling
+       if(debug['Q'] == 0)
+               return;
+
+       curtext = nil;
+       q = nil;        /* p - 1 */
+       q1 = firstp;    /* top of block */
+       o = 0;          /* count of instructions */
+       for(p = firstp; p != nil; p = p1) {
+               p1 = p->link;
+               o++;
+               if(p->mark & NOSCHED){
+                       if(q1 != p){
+                               sched(q1, q);
+                       }
+                       for(; p != nil; p = p->link){
+                               if(!(p->mark & NOSCHED))
+                                       break;
+                               q = p;
+                       }
+                       p1 = p;
+                       q1 = p;
+                       o = 0;
+                       continue;
+               }
+               if(p->mark & (LABEL|SYNC)) {
+                       if(q1 != p)
+                               sched(q1, q);
+                       q1 = p;
+                       o = 1;
+               }
+               if(p->mark & (BRANCH|SYNC)) {
+                       sched(q1, p);
+                       q1 = p1;
+                       o = 0;
+               }
+               if(o >= NSCHED) {
+                       sched(q1, p);
+                       q1 = p1;
+                       o = 0;
+               }
+               q = p;
+       }
+#endif
+}
+
+static Prog*
+stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
+{
+       Prog *q, *q1;
+
+       // MOVD g_stackguard(g), R3
+       p = appendp(ctxt, p);
+       p->as = AMOVD;
+       p->from.type = D_OREG;
+       p->from.reg = REGG;
+       p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
+       if(ctxt->cursym->cfunc)
+               p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
+       p->to.type = D_REG;
+       p->to.reg = 3;
+
+       q = nil;
+       if(framesize <= StackSmall) {
+               // small stack: SP < stackguard
+               //      CMP     stackguard, SP
+               p = appendp(ctxt, p);
+               p->as = ACMPU;
+               p->from.type = D_REG;
+               p->from.reg = 3;
+               p->to.type = D_REG;
+               p->to.reg = REGSP;
+       } else if(framesize <= StackBig) {
+               // large stack: SP-framesize < stackguard-StackSmall
+               //      ADD $-framesize, SP, R4
+               //      CMP stackguard, R4
+               p = appendp(ctxt, p);
+               p->as = AADD;
+               p->from.type = D_CONST;
+               p->from.offset = -framesize;
+               p->reg = REGSP;
+               p->to.type = D_REG;
+               p->to.reg = 4;
+
+               p = appendp(ctxt, p);
+               p->as = ACMPU;
+               p->from.type = D_REG;
+               p->from.reg = 3;
+               p->to.type = D_REG;
+               p->to.reg = 4;
+       } else {
+               // Such a large stack we need to protect against wraparound.
+               // If SP is close to zero:
+               //      SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
+               // The +StackGuard on both sides is required to keep the left side positive:
+               // SP is allowed to be slightly below stackguard. See stack.h.
+               //
+               // Preemption sets stackguard to StackPreempt, a very large value.
+               // That breaks the math above, so we have to check for that explicitly.
+               //      // stackguard is R3
+               //      CMP     R3, $StackPreempt
+               //      BEQ     label-of-call-to-morestack
+               //      ADD     $StackGuard, SP, R4
+               //      SUB     R3, R4
+               //      MOVD    $(framesize+(StackGuard-StackSmall)), R31
+               //      CMPU    R31, R4
+               p = appendp(ctxt, p);
+               p->as = ACMP;
+               p->from.type = D_REG;
+               p->from.reg = 3;
+               p->to.type = D_CONST;
+               p->to.offset = StackPreempt;
+
+               q = p = appendp(ctxt, p);
+               p->as = ABEQ;
+               p->to.type = D_BRANCH;
+
+               p = appendp(ctxt, p);
+               p->as = AADD;
+               p->from.type = D_CONST;
+               p->from.offset = StackGuard;
+               p->reg = REGSP;
+               p->to.type = D_REG;
+               p->to.reg = 4;
+
+               p = appendp(ctxt, p);
+               p->as = ASUB;
+               p->from.type = D_REG;
+               p->from.reg = 3;
+               p->to.type = D_REG;
+               p->to.reg = 4;
+
+               p = appendp(ctxt, p);
+               p->as = AMOVD;
+               p->from.type = D_CONST;
+               p->from.offset = framesize + StackGuard - StackSmall;
+               p->to.type = D_REG;
+               p->to.reg = REGTMP;
+
+               p = appendp(ctxt, p);
+               p->as = ACMPU;
+               p->from.type = D_REG;
+               p->from.reg = REGTMP;
+               p->to.type = D_REG;
+               p->to.reg = 4;
+       }
+
+       // q1: BLT      done
+       q1 = p = appendp(ctxt, p);
+       p->as = ABLT;
+       p->to.type = D_BRANCH;
+
+       // MOVD LR, R5
+       p = appendp(ctxt, p);
+       p->as = AMOVD;
+       p->from.type = D_SPR;
+       p->from.offset = D_LR;
+       p->to.type = D_REG;
+       p->to.reg = 5;
+       if(q)
+               q->pcond = p;
+
+       // BL   runtime.morestack(SB)
+       p = appendp(ctxt, p);
+       p->as = ABL;
+       p->to.type = D_BRANCH;
+       if(ctxt->cursym->cfunc)
+               p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+       else
+               p->to.sym = ctxt->symmorestack[noctxt];
+
+       // BR   start
+       p = appendp(ctxt, p);
+       p->as = ABR;
+       p->to.type = D_BRANCH;
+       p->pcond = ctxt->cursym->text->link;
+
+       // placeholder for q1's jump target
+       p = appendp(ctxt, p);
+       p->as = ANOP; // zero-width place holder
+       q1->pcond = p;
+
+       return p;
+}
+
+static void xfol(Link*, Prog*, Prog**);
+
+static void
+follow(Link *ctxt, LSym *s)
+{
+       Prog *firstp, *lastp;
+
+       ctxt->cursym = s;
+
+       firstp = ctxt->arch->prg();
+       lastp = firstp;
+       xfol(ctxt, s->text, &lastp);
+       lastp->link = nil;
+       s->text = firstp->link;
+}
+
+static int
+relinv(int a)
+{
+
+       switch(a) {
+       case ABEQ:      return ABNE;
+       case ABNE:      return ABEQ;
+
+       case ABGE:      return ABLT;
+       case ABLT:      return ABGE;
+
+       case ABGT:      return ABLE;
+       case ABLE:      return ABGT;
+
+       case ABVC:      return ABVS;
+       case ABVS:      return ABVC;
+       }
+       return 0;
+}
+
+static void
+xfol(Link *ctxt, Prog *p, Prog **last)
+{
+       Prog *q, *r;
+       int a, b, i;
+
+loop:
+       if(p == nil)
+               return;
+       a = p->as;
+       if(a == ABR) {
+               q = p->pcond;
+               if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
+                       p->mark |= FOLL;
+                       (*last)->link = p;
+                       *last = p;
+                       p = p->link;
+                       xfol(ctxt, p, last);
+                       p = q;
+                       if(p && !(p->mark & FOLL))
+                               goto loop;
+                       return;
+               }
+               if(q != nil) {
+                       p->mark |= FOLL;
+                       p = q;
+                       if(!(p->mark & FOLL))
+                               goto loop;
+               }
+       }
+       if(p->mark & FOLL) {
+               for(i=0,q=p; i<4; i++,q=q->link) {
+                       if(q == *last || (q->mark&NOSCHED))
+                               break;
+                       b = 0;          /* set */
+                       a = q->as;
+                       if(a == ANOP) {
+                               i--;
+                               continue;
+                       }
+                       if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID)
+                               goto copy;
+                       if(!q->pcond || (q->pcond->mark&FOLL))
+                               continue;
+                       b = relinv(a);
+                       if(!b)
+                               continue;
+               copy:
+                       for(;;) {
+                               r = ctxt->arch->prg();
+                               *r = *p;
+                               if(!(r->mark&FOLL))
+                                       print("cant happen 1\n");
+                               r->mark |= FOLL;
+                               if(p != q) {
+                                       p = p->link;
+                                       (*last)->link = r;
+                                       *last = r;
+                                       continue;
+                               }
+                               (*last)->link = r;
+                               *last = r;
+                               if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID)
+                                       return;
+                               r->as = b;
+                               r->pcond = p->link;
+                               r->link = p->pcond;
+                               if(!(r->link->mark&FOLL))
+                                       xfol(ctxt, r->link, last);
+                               if(!(r->pcond->mark&FOLL))
+                                       print("cant happen 2\n");
+                               return;
+                       }
+               }
+
+               a = ABR;
+               q = ctxt->arch->prg();
+               q->as = a;
+               q->lineno = p->lineno;
+               q->to.type = D_BRANCH;
+               q->to.offset = p->pc;
+               q->pcond = p;
+               p = q;
+       }
+       p->mark |= FOLL;
+       (*last)->link = p;
+       *last = p;
+       if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID){
+               if(p->mark & NOSCHED){
+                       p = p->link;
+                       goto loop;
+               }
+               return;
+       }
+       if(p->pcond != nil)
+       if(a != ABL && p->link != nil) {
+               xfol(ctxt, p->link, last);
+               p = p->pcond;
+               if(p == nil || (p->mark&FOLL))
+                       return;
+               goto loop;
+       }
+       p = p->link;
+       goto loop;
+}
+
+static Prog*
+prg(void)
+{
+       Prog *p;
+
+       p = emallocz(sizeof(*p));
+       *p = zprg;
+       return p;
+}
+
+LinkArch linkpower64 = {
+       .name = "power64",
+       .thechar = '9',
+       .endian = BigEndian,
+
+       .addstacksplit = addstacksplit,
+       .assemble = span9,
+       .datasize = datasize,
+       .follow = follow,
+       .iscall = iscall,
+       .isdata = isdata,
+       .prg = prg,
+       .progedit = progedit,
+       .settextflag = settextflag,
+       .symtype = symtype,
+       .textflag = textflag,
+
+       .minlc = 4,
+       .ptrsize = 8,
+       .regsize = 8,
+
+       .D_ADDR = D_ADDR,
+       .D_AUTO = D_AUTO,
+       .D_BRANCH = D_BRANCH,
+       .D_CONST = D_CONST,
+       .D_EXTERN = D_EXTERN,
+       .D_FCONST = D_FCONST,
+       .D_NONE = D_NONE,
+       .D_PARAM = D_PARAM,
+       .D_SCONST = D_SCONST,
+       .D_STATIC = D_STATIC,
+       .D_OREG = D_OREG,
+
+       .ACALL = ABL,
+       .ADATA = ADATA,
+       .AEND = AEND,
+       .AFUNCDATA = AFUNCDATA,
+       .AGLOBL = AGLOBL,
+       .AJMP = ABR,
+       .ANOP = ANOP,
+       .APCDATA = APCDATA,
+       .ARET = ARETURN,
+       .ATEXT = ATEXT,
+       .ATYPE = ATYPE,
+       .AUSEFIELD = AUSEFIELD,
+};
+
+LinkArch linkpower64le = {
+       .name = "power64le",
+       .thechar = '9',
+       .endian = LittleEndian,
+
+       .addstacksplit = addstacksplit,
+       .assemble = span9,
+       .datasize = datasize,
+       .follow = follow,
+       .iscall = iscall,
+       .isdata = isdata,
+       .prg = prg,
+       .progedit = progedit,
+       .settextflag = settextflag,
+       .symtype = symtype,
+       .textflag = textflag,
+
+       .minlc = 4,
+       .ptrsize = 8,
+       .regsize = 8,
+
+       .D_ADDR = D_ADDR,
+       .D_AUTO = D_AUTO,
+       .D_BRANCH = D_BRANCH,
+       .D_CONST = D_CONST,
+       .D_EXTERN = D_EXTERN,
+       .D_FCONST = D_FCONST,
+       .D_NONE = D_NONE,
+       .D_PARAM = D_PARAM,
+       .D_SCONST = D_SCONST,
+       .D_STATIC = D_STATIC,
+       .D_OREG = D_OREG,
+
+       .ACALL = ABL,
+       .ADATA = ADATA,
+       .AEND = AEND,
+       .AFUNCDATA = AFUNCDATA,
+       .AGLOBL = AGLOBL,
+       .AJMP = ABR,
+       .ANOP = ANOP,
+       .APCDATA = APCDATA,
+       .ARET = ARETURN,
+       .ATEXT = ATEXT,
+       .ATYPE = ATYPE,
+       .AUSEFIELD = AUSEFIELD,
+};
index b2478ec17847f9d130587f7cd39455e7881be5c9..aa701f459ed014c576ff2a6efadc4b703635f438 100644 (file)
@@ -142,6 +142,8 @@ writeobj(Link *ctxt, Biobuf *b)
        edata = nil;
        for(pl = ctxt->plist; pl != nil; pl = pl->link) {
                for(p = pl->firstpc; p != nil; p = plink) {
+                       if(ctxt->debugasm && ctxt->debugvlog)
+                               print("obj: %p %P\n", p, p);
                        plink = p->link;
                        p->link = nil;
 
@@ -365,7 +367,10 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
                        name = "";
                        if(r->sym != nil)
                                name = r->sym->name;
-                       Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
+                       if(ctxt->arch->thechar == '5' || ctxt->arch->thechar == '9')
+                               Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%llux\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
+                       else
+                               Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
                }
        }
 
@@ -546,9 +551,10 @@ ldobjfile(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn)
 static void
 readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
 {
-       int i, j, c, t, v, n, size, dupok;
+       int i, j, c, t, v, n, ndata, nreloc, size, dupok;
        static int ndup;
        char *name;
+       uchar *data;
        Reloc *r;
        LSym *s, *dup, *typ;
        Pcln *pc;
@@ -564,12 +570,24 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
        dupok = rdint(f);
        dupok &= 1;
        size = rdint(f);
+       typ = rdsym(ctxt, f, pkg);
+       rddata(f, &data, &ndata);
+       nreloc = rdint(f);
        
        if(v != 0)
                v = ctxt->version;
        s = linklookup(ctxt, name, v);
        dup = nil;
        if(s->type != 0 && s->type != SXREF) {
+               if((t == SDATA || t == SBSS || t == SNOPTRBSS) && ndata == 0 && nreloc == 0) {
+                       if(s->size < size)
+                               s->size = size;
+                       if(typ != nil && s->gotype == nil)
+                               s->gotype = typ;
+                       return;
+               }
+               if((s->type == SDATA || s->type == SBSS || s->type == SNOPTRBSS) && s->np == 0 && s->nr == 0)
+                       goto overwrite;
                if(s->type != SBSS && s->type != SNOPTRBSS && !dupok && !s->dupok)
                        sysfatal("duplicate symbol %s (types %d and %d) in %s and %s", s->name, s->type, t, s->file, pn);
                if(s->np > 0) {
@@ -577,28 +595,30 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
                        s = linknewsym(ctxt, ".dup", ndup++); // scratch
                }
        }
+overwrite:
        s->file = pkg;
        s->dupok = dupok;
        if(t == SXREF)
                sysfatal("bad sxref");
        if(t == 0)
                sysfatal("missing type for %s in %s", name, pn);
+       if(t == SBSS && (s->type == SRODATA || s->type == SNOPTRBSS))
+               t = s->type;
        s->type = t;
        if(s->size < size)
                s->size = size;
-       typ = rdsym(ctxt, f, pkg);
        if(typ != nil) // if bss sym defined multiple times, take type from any one def
                s->gotype = typ;
        if(dup != nil && typ != nil)
                dup->gotype = typ;
-       rddata(f, &s->p, &s->np);
+       s->p = data;
+       s->np = ndata;
        s->maxp = s->np;
-       n = rdint(f);
-       if(n > 0) {
-               s->r = emallocz(n * sizeof s->r[0]);
-               s->nr = n;
-               s->maxr = n;
-               for(i=0; i<n; i++) {
+       if(nreloc > 0) {
+               s->r = emallocz(nreloc * sizeof s->r[0]);
+               s->nr = nreloc;
+               s->maxr = nreloc;
+               for(i=0; i<nreloc; i++) {
                        r = &s->r[i];
                        r->off = rdint(f);
                        r->siz = rdint(f);
@@ -777,7 +797,7 @@ rdsym(Link *ctxt, Biobuf *f, char *pkg)
                        s->type = SRODATA;
                        adduint32(ctxt, s, i32);
                        s->reachable = 0;
-               } else if(strncmp(s->name, "$f64.", 5) == 0) {
+               } else if(strncmp(s->name, "$f64.", 5) == 0 || strncmp(s->name, "$i64.", 5) == 0) {
                        int64 i64;
                        i64 = strtoull(s->name+5, nil, 16);
                        s->type = SRODATA;
diff --git a/src/liblink/sched9.c b/src/liblink/sched9.c
new file mode 100644 (file)
index 0000000..a9083df
--- /dev/null
@@ -0,0 +1,835 @@
+// cmd/9l/sched.c from Vita Nuova.
+//
+//     Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//     Portions Copyright Â© 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright Â© 1997-1999 Vita Nuova Limited
+//     Portions Copyright Â© 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright Â© 2004,2006 Bruce Ellis
+//     Portions Copyright Â© 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright Â© 2000-2008 Lucent Technologies Inc. and others
+//     Portions Copyright Â© 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// +build ignore
+
+#include       "l.h"
+
+enum
+{
+       E_ICC   = 1<<0,
+       E_FCC   = 1<<1,
+       E_MEM   = 1<<2,
+       E_MEMSP = 1<<3, /* uses offset and size */
+       E_MEMSB = 1<<4, /* uses offset and size */
+       E_LR    = 1<<5,
+       E_CR = 1<<6,
+       E_CTR = 1<<7,
+       E_XER = 1<<8,
+
+       E_CR0 = 0xF<<0,
+       E_CR1 = 0xF<<4,
+
+       ANYMEM  = E_MEM|E_MEMSP|E_MEMSB,
+       ALL     = ~0,
+};
+
+typedef        struct  Sch     Sch;
+typedef        struct  Dep     Dep;
+
+struct Dep
+{
+       ulong   ireg;
+       ulong   freg;
+       ulong   cc;
+       ulong   cr;
+};
+struct Sch
+{
+       Prog    p;
+       Dep     set;
+       Dep     used;
+       long    soffset;
+       char    size;
+       char    comp;
+};
+
+void   regused(Sch*, Prog*);
+int    depend(Sch*, Sch*);
+int    conflict(Sch*, Sch*);
+int    offoverlap(Sch*, Sch*);
+void   dumpbits(Sch*, Dep*);
+
+void
+sched(Prog *p0, Prog *pe)
+{
+       Prog *p, *q;
+       Sch sch[NSCHED], *s, *t, *u, *se, stmp;
+
+       if(!debug['Q'])
+               return;
+       /*
+        * build side structure
+        */
+       s = sch;
+       for(p=p0;; p=p->link) {
+               memset(s, 0, sizeof(*s));
+               s->p = *p;
+               regused(s, p);
+               if(debug['X']) {
+                       Bprint(&bso, "%P\tset", &s->p);
+                       dumpbits(s, &s->set);
+                       Bprint(&bso, "; used");
+                       dumpbits(s, &s->used);
+                       if(s->comp)
+                               Bprint(&bso, "; compound");
+                       if(s->p.mark & LOAD)
+                               Bprint(&bso, "; load");
+                       if(s->p.mark & BRANCH)
+                               Bprint(&bso, "; branch");
+                       if(s->p.mark & FCMP)
+                               Bprint(&bso, "; fcmp");
+                       Bprint(&bso, "\n");
+               }
+               s++;
+               if(p == pe)
+                       break;
+       }
+       se = s;
+
+       for(s=se-1; s>=sch; s--) {
+
+               /*
+                * load delay. interlocked.
+                */
+               if(s->p.mark & LOAD) {
+                       if(s >= se-1)
+                               continue;
+                       if(!conflict(s, (s+1)))
+                               continue;
+                       /*
+                        * s is load, s+1 is immediate use of result
+                        * t is the trial instruction to insert between s and s+1
+                        */
+                       for(t=s-1; t>=sch; t--) {
+                               if(t->p.mark & BRANCH)
+                                       goto no2;
+                               if(t->p.mark & FCMP)
+                                       if((s+1)->p.mark & BRANCH)
+                                               goto no2;
+                               if(t->p.mark & LOAD)
+                                       if(conflict(t, (s+1)))
+                                               goto no2;
+                               for(u=t+1; u<=s; u++)
+                                       if(depend(u, t))
+                                               goto no2;
+                               goto out2;
+                       no2:;
+                       }
+                       if(debug['X'])
+                               Bprint(&bso, "?l%P\n", &s->p);
+                       continue;
+               out2:
+                       if(debug['X']) {
+                               Bprint(&bso, "!l%P\n", &t->p);
+                               Bprint(&bso, "%P\n", &s->p);
+                       }
+                       stmp = *t;
+                       memmove(t, t+1, (uchar*)s - (uchar*)t);
+                       *s = stmp;
+                       s--;
+                       continue;
+               }
+
+               /*
+                * fop2 delay.
+                */
+               if(s->p.mark & FCMP) {
+                       if(s >= se-1)
+                               continue;
+                       if(!((s+1)->p.mark & BRANCH))
+                               continue;
+                       /* t is the trial instruction to use */
+                       for(t=s-1; t>=sch; t--) {
+                               for(u=t+1; u<=s; u++)
+                                       if(depend(u, t))
+                                               goto no3;
+                               goto out3;
+                       no3:;
+                       }
+                       if(debug['X'])
+                               Bprint(&bso, "?f%P\n", &s->p);
+                       continue;
+               out3:
+                       if(debug['X']) {
+                               Bprint(&bso, "!f%P\n", &t->p);
+                               Bprint(&bso, "%P\n", &s->p);
+                       }
+                       stmp = *t;
+                       memmove(t, t+1, (uchar*)s - (uchar*)t);
+                       *s = stmp;
+                       s--;
+                       continue;
+               }
+       }
+
+       /*
+        * put it all back
+        */
+       for(s=sch, p=p0; s<se; s++, p=q) {
+               q = p->link;
+               if(q != s->p.link) {
+                       *p = s->p;
+                       p->link = q;
+               }
+       }
+       if(debug['X'])
+               Bprint(&bso, "\n");
+}
+
+void
+regused(Sch *s, Prog *realp)
+{
+       int c, ar, ad, ld, sz, nr, upd;
+       ulong m;
+       Prog *p;
+
+       p = &s->p;
+       s->comp = compound(p);
+       if(s->comp) {
+               s->set.ireg |= 1<<REGTMP;
+               s->used.ireg |= 1<<REGTMP;
+       }
+       ar = 0;         /* dest is really reference */
+       ad = 0;         /* source/dest is really address */
+       ld = 0;         /* opcode is load instruction */
+       sz = 32*4;              /* size of load/store for overlap computation */
+       nr = 0; /* source/dest is not really reg */
+       upd = 0;        /* move with update; changes reg */
+
+/*
+ * flags based on opcode
+ */
+       switch(p->as) {
+       case ATEXT:
+               curtext = realp;
+               autosize = p->to.offset + 8;
+               ad = 1;
+               break;
+       case ABL:
+               s->set.cc |= E_LR;
+               ar = 1;
+               ad = 1;
+               break;
+       case ABR:
+               ar = 1;
+               ad = 1;
+               break;
+       case ACMP:
+       case ACMPU:
+       case ACMPW:
+       case ACMPWU:
+               s->set.cc |= E_ICC;
+               if(p->reg == 0)
+                       s->set.cr |= E_CR0;
+               else
+                       s->set.cr |= (0xF<<((p->reg&7)*4));
+               ar = 1;
+               break;
+       case AFCMPO:
+       case AFCMPU:
+               s->set.cc |= E_FCC;
+               if(p->reg == 0)
+                       s->set.cr |= E_CR0;
+               else
+                       s->set.cr |= (0xF<<((p->reg&7)*4));
+               ar = 1;
+               break;
+       case ACRAND:
+       case ACRANDN:
+       case ACREQV:
+       case ACRNAND:
+       case ACRNOR:
+       case ACROR:
+       case ACRORN:
+       case ACRXOR:
+               s->used.cr |= 1<<p->from.reg;
+               s->set.cr |= 1<<p->to.reg;
+               nr = 1;
+               break;
+       case ABCL:      /* tricky */
+               s->used.cc |= E_FCC|E_ICC;
+               s->used.cr = ALL;
+               s->set.cc |= E_LR;
+               ar = 1;
+               break;
+       case ABC:               /* tricky */
+               s->used.cc |= E_FCC|E_ICC;
+               s->used.cr = ALL;
+               ar = 1;
+               break;
+       case ABEQ:
+       case ABGE:
+       case ABGT:
+       case ABLE:
+       case ABLT:
+       case ABNE:
+       case ABVC:
+       case ABVS:
+               s->used.cc |= E_ICC;
+               s->used.cr |= E_CR0;
+               ar = 1;
+               break;
+       case ALSW:
+       case AMOVMW:
+               /* could do better */
+               sz = 32*4;
+               ld = 1;
+               break;
+       case AMOVBU:
+       case AMOVBZU:
+               upd = 1;
+               sz = 1;
+               ld = 1;
+               break;
+       case AMOVB:
+       case AMOVBZ:
+               sz = 1;
+               ld = 1;
+               break;
+       case AMOVHU:
+       case AMOVHZU:
+               upd = 1;
+               sz = 2;
+               ld = 1;
+               break;
+       case AMOVH:
+       case AMOVHBR:
+       case AMOVHZ:
+               sz = 2;
+               ld = 1;
+               break;
+       case AFMOVSU:
+       case AMOVWU:
+       case AMOVWZU:
+               upd = 1;
+               sz = 4;
+               ld = 1;
+               break;
+       case AFMOVS:
+       case AMOVW:
+       case AMOVWZ:
+       case AMOVWBR:
+       case ALWAR:
+               sz = 4;
+               ld = 1;
+               break;
+       case AFMOVDU:
+               upd = 1;
+               sz = 8;
+               ld = 1;
+               break;
+       case AFMOVD:
+               sz = 8;
+               ld = 1;
+               break;
+       case AFMOVDCC:
+               sz = 8;
+               ld = 1;
+               s->set.cc |= E_FCC;
+               s->set.cr |= E_CR1;
+               break;
+       case AMOVFL:
+       case AMOVCRFS:
+       case AMTFSB0:
+       case AMTFSB0CC:
+       case AMTFSB1:
+       case AMTFSB1CC:
+               s->set.ireg = ALL;
+               s->set.freg = ALL;
+               s->set.cc = ALL;
+               s->set.cr = ALL;
+               break;
+       case AADDCC:
+       case AADDVCC:
+       case AADDCCC:
+       case AADDCVCC:
+       case AADDMECC:
+       case AADDMEVCC:
+       case AADDECC:
+       case AADDEVCC:
+       case AADDZECC:
+       case AADDZEVCC:
+       case AANDCC:
+       case AANDNCC:
+       case ACNTLZWCC:
+       case ADIVWCC:
+       case ADIVWVCC:
+       case ADIVWUCC:
+       case ADIVWUVCC:
+       case AEQVCC:
+       case AEXTSBCC:
+       case AEXTSHCC:
+       case AMULHWCC:
+       case AMULHWUCC:
+       case AMULLWCC:
+       case AMULLWVCC:
+       case ANANDCC:
+       case ANEGCC:
+       case ANEGVCC:
+       case ANORCC:
+       case AORCC:
+       case AORNCC:
+       case AREMCC:
+       case AREMVCC:
+       case AREMUCC:
+       case AREMUVCC:
+       case ARLWMICC:
+       case ARLWNMCC:
+       case ASLWCC:
+       case ASRAWCC:
+       case ASRWCC:
+       case ASTWCCC:
+       case ASUBCC:
+       case ASUBVCC:
+       case ASUBCCC:
+       case ASUBCVCC:
+       case ASUBMECC:
+       case ASUBMEVCC:
+       case ASUBECC:
+       case ASUBEVCC:
+       case ASUBZECC:
+       case ASUBZEVCC:
+       case AXORCC:
+               s->set.cc |= E_ICC;
+               s->set.cr |= E_CR0;
+               break;
+       case AFABSCC:
+       case AFADDCC:
+       case AFADDSCC:
+       case AFCTIWCC:
+       case AFCTIWZCC:
+       case AFDIVCC:
+       case AFDIVSCC:
+       case AFMADDCC:
+       case AFMADDSCC:
+       case AFMSUBCC:
+       case AFMSUBSCC:
+       case AFMULCC:
+       case AFMULSCC:
+       case AFNABSCC:
+       case AFNEGCC:
+       case AFNMADDCC:
+       case AFNMADDSCC:
+       case AFNMSUBCC:
+       case AFNMSUBSCC:
+       case AFRSPCC:
+       case AFSUBCC:
+       case AFSUBSCC:
+               s->set.cc |= E_FCC;
+               s->set.cr |= E_CR1;
+               break;
+       }
+
+/*
+ * flags based on 'to' field
+ */
+       c = p->to.class;
+       if(c == 0) {
+               c = aclass(&p->to) + 1;
+               p->to.class = c;
+       }
+       c--;
+       switch(c) {
+       default:
+               print("unknown class %d %D\n", c, &p->to);
+
+       case C_NONE:
+       case C_ZCON:
+       case C_SCON:
+       case C_UCON:
+       case C_LCON:
+       case C_ADDCON:
+       case C_ANDCON:
+       case C_SBRA:
+       case C_LBRA:
+               break;
+       case C_CREG:
+               c = p->to.reg;
+               if(c == NREG)
+                       s->set.cr = ALL;
+               else
+                       s->set.cr |= (0xF << ((p->from.reg&7)*4));
+               s->set.cc = ALL;
+               break;
+       case C_SPR:
+       case C_FPSCR:
+       case C_MSR:
+       case C_XER:
+               s->set.ireg = ALL;
+               s->set.freg = ALL;
+               s->set.cc = ALL;
+               s->set.cr = ALL;
+               break;
+       case C_LR:
+               s->set.cc |= E_LR;
+               break;
+       case C_CTR:
+               s->set.cc |= E_CTR;
+               break;
+       case C_ZOREG:
+       case C_SOREG:
+       case C_LOREG:
+               c = p->to.reg;
+               s->used.ireg |= 1<<c;
+               if(upd)
+                       s->set.ireg |= 1<<c;
+               if(ad)
+                       break;
+               s->size = sz;
+               s->soffset = regoff(&p->to);
+
+               m = ANYMEM;
+               if(c == REGSB)
+                       m = E_MEMSB;
+               if(c == REGSP)
+                       m = E_MEMSP;
+
+               if(ar)
+                       s->used.cc |= m;
+               else
+                       s->set.cc |= m;
+               break;
+       case C_SACON:
+       case C_LACON:
+               s->used.ireg |= 1<<REGSP;
+               if(upd)
+                       s->set.ireg |= 1<<c;
+               break;
+       case C_SECON:
+       case C_LECON:
+               s->used.ireg |= 1<<REGSB;
+               if(upd)
+                       s->set.ireg |= 1<<c;
+               break;
+       case C_REG:
+               if(nr)
+                       break;
+               if(ar)
+                       s->used.ireg |= 1<<p->to.reg;
+               else
+                       s->set.ireg |= 1<<p->to.reg;
+               break;
+       case C_FREG:
+               if(ar)
+                       s->used.freg |= 1<<p->to.reg;
+               else
+                       s->set.freg |= 1<<p->to.reg;
+               break;
+       case C_SAUTO:
+       case C_LAUTO:
+               s->used.ireg |= 1<<REGSP;
+               if(upd)
+                       s->set.ireg |= 1<<c;
+               if(ad)
+                       break;
+               s->size = sz;
+               s->soffset = regoff(&p->to);
+
+               if(ar)
+                       s->used.cc |= E_MEMSP;
+               else
+                       s->set.cc |= E_MEMSP;
+               break;
+       case C_SEXT:
+       case C_LEXT:
+               s->used.ireg |= 1<<REGSB;
+               if(upd)
+                       s->set.ireg |= 1<<c;
+               if(ad)
+                       break;
+               s->size = sz;
+               s->soffset = regoff(&p->to);
+
+               if(ar)
+                       s->used.cc |= E_MEMSB;
+               else
+                       s->set.cc |= E_MEMSB;
+               break;
+       }
+
+/*
+ * flags based on 'from' field
+ */
+       c = p->from.class;
+       if(c == 0) {
+               c = aclass(&p->from) + 1;
+               p->from.class = c;
+       }
+       c--;
+       switch(c) {
+       default:
+               print("unknown class %d %D\n", c, &p->from);
+
+       case C_NONE:
+       case C_ZCON:
+       case C_SCON:
+       case C_UCON:
+       case C_LCON:
+       case C_ADDCON:
+       case C_ANDCON:
+       case C_SBRA:
+       case C_LBRA:
+               c = p->from.reg;
+               if(c != NREG)
+                       s->used.ireg |= 1<<c;
+               break;
+       case C_CREG:
+               c = p->from.reg;
+               if(c == NREG)
+                       s->used.cr = ALL;
+               else
+                       s->used.cr |= (0xF << ((p->from.reg&7)*4));
+               s->used.cc = ALL;
+               break;
+       case C_SPR:
+       case C_FPSCR:
+       case C_MSR:
+       case C_XER:
+               s->set.ireg = ALL;
+               s->set.freg = ALL;
+               s->set.cc = ALL;
+               s->set.cr = ALL;
+               break;
+       case C_LR:
+               s->used.cc |= E_LR;
+               break;
+       case C_CTR:
+               s->used.cc |= E_CTR;
+               break;
+       case C_ZOREG:
+       case C_SOREG:
+       case C_LOREG:
+               c = p->from.reg;
+               s->used.ireg |= 1<<c;
+               if(ld)
+                       p->mark |= LOAD;
+               if(ad)
+                       break;
+               s->size = sz;
+               s->soffset = regoff(&p->from);
+
+               m = ANYMEM;
+               if(c == REGSB)
+                       m = E_MEMSB;
+               if(c == REGSP)
+                       m = E_MEMSP;
+
+               s->used.cc |= m;
+               break;
+       case C_SACON:
+       case C_LACON:
+               s->used.ireg |= 1<<REGSP;
+               break;
+       case C_SECON:
+       case C_LECON:
+               s->used.ireg |= 1<<REGSB;
+               break;
+       case C_REG:
+               if(nr)
+                       break;
+               s->used.ireg |= 1<<p->from.reg;
+               break;
+       case C_FREG:
+               s->used.freg |= 1<<p->from.reg;
+               break;
+       case C_SAUTO:
+       case C_LAUTO:
+               s->used.ireg |= 1<<REGSP;
+               if(ld)
+                       p->mark |= LOAD;
+               if(ad)
+                       break;
+               s->size = sz;
+               s->soffset = regoff(&p->from);
+
+               s->used.cc |= E_MEMSP;
+               break;
+       case C_SEXT:
+       case C_LEXT:
+               s->used.ireg |= 1<<REGSB;
+               if(ld)
+                       p->mark |= LOAD;
+               if(ad)
+                       break;
+               s->size = sz;
+               s->soffset = regoff(&p->from);
+
+               s->used.cc |= E_MEMSB;
+               break;
+       }
+       
+       c = p->reg;
+       if(c != NREG) {
+               if(p->from.type == D_FREG || p->to.type == D_FREG)
+                       s->used.freg |= 1<<c;
+               else
+                       s->used.ireg |= 1<<c;
+       }
+}
+
+/*
+ * test to see if 2 instrictions can be
+ * interchanged without changing semantics
+ */
+int
+depend(Sch *sa, Sch *sb)
+{
+       ulong x;
+
+       if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
+               return 1;
+       if(sb->set.ireg & sa->used.ireg)
+               return 1;
+
+       if(sa->set.freg & (sb->set.freg|sb->used.freg))
+               return 1;
+       if(sb->set.freg & sa->used.freg)
+               return 1;
+
+       if(sa->set.cr & (sb->set.cr|sb->used.cr))
+               return 1;
+       if(sb->set.cr & sa->used.cr)
+               return 1;
+
+
+       x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
+               (sb->set.cc & sa->used.cc);
+       if(x) {
+               /*
+                * allow SB and SP to pass each other.
+                * allow SB to pass SB iff doffsets are ok
+                * anything else conflicts
+                */
+               if(x != E_MEMSP && x != E_MEMSB)
+                       return 1;
+               x = sa->set.cc | sb->set.cc |
+                       sa->used.cc | sb->used.cc;
+               if(x & E_MEM)
+                       return 1;
+               if(offoverlap(sa, sb))
+                       return 1;
+       }
+
+       return 0; 
+}
+
+int
+offoverlap(Sch *sa, Sch *sb)
+{
+
+       if(sa->soffset < sb->soffset) {
+               if(sa->soffset+sa->size > sb->soffset)
+                       return 1;
+               return 0;
+       }
+       if(sb->soffset+sb->size > sa->soffset)
+               return 1;
+       return 0;
+}
+
+/*
+ * test 2 adjacent instructions
+ * and find out if inserted instructions
+ * are desired to prevent stalls.
+ * first instruction is a load instruction.
+ */
+int
+conflict(Sch *sa, Sch *sb)
+{
+
+       if(sa->set.ireg & sb->used.ireg)
+               return 1;
+       if(sa->set.freg & sb->used.freg)
+               return 1;
+       if(sa->set.cr & sb->used.cr)
+               return 1;
+       return 0;
+}
+
+int
+compound(Prog *p)
+{
+       Optab *o;
+
+       o = oplook(p);
+       if(o->size != 4)
+               return 1;
+       if(p->to.type == D_REG && p->to.reg == REGSB)
+               return 1;
+       return 0;
+}
+
+void
+dumpbits(Sch *s, Dep *d)
+{
+       int i;
+
+       for(i=0; i<32; i++)
+               if(d->ireg & (1<<i))
+                       Bprint(&bso, " R%d", i);
+       for(i=0; i<32; i++)
+               if(d->freg & (1<<i))
+                       Bprint(&bso, " F%d", i);
+       for(i=0; i<32; i++)
+               if(d->cr & (1<<i))
+                       Bprint(&bso, " C%d", i);
+       for(i=0; i<32; i++)
+               switch(d->cc & (1<<i)) {
+               default:
+                       break;
+               case E_ICC:
+                       Bprint(&bso, " ICC");
+                       break;
+               case E_FCC:
+                       Bprint(&bso, " FCC");
+                       break;
+               case E_LR:
+                       Bprint(&bso, " LR");
+                       break;
+               case E_CR:
+                       Bprint(&bso, " CR");
+                       break;
+               case E_CTR:
+                       Bprint(&bso, " CTR");
+                       break;
+               case E_XER:
+                       Bprint(&bso, " XER");
+                       break;
+               case E_MEM:
+                       Bprint(&bso, " MEM%d", s->size);
+                       break;
+               case E_MEMSB:
+                       Bprint(&bso, " SB%d", s->size);
+                       break;
+               case E_MEMSP:
+                       Bprint(&bso, " SP%d", s->size);
+                       break;
+               }
+}
diff --git a/src/math/abs_power64x.s b/src/math/abs_power64x.s
new file mode 100644 (file)
index 0000000..3ba8201
--- /dev/null
@@ -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.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+TEXT Â·Abs(SB),NOSPLIT,$0-16
+       MOVD    x+0(FP), R3
+       MOVD    $((1<<63)-1), R4
+       AND     R4, R3
+       MOVD    R3, ret+8(FP)
+       RETURN
diff --git a/src/math/big/arith_power64x.s b/src/math/big/arith_power64x.s
new file mode 100644 (file)
index 0000000..c33a920
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+// This file provides fast assembly versions for the elementary
+// arithmetic operations on vectors implemented in arith.go.
+
+TEXT Â·mulWW(SB),NOSPLIT,$0
+       BR Â·mulWW_g(SB)
+
+TEXT Â·divWW(SB),NOSPLIT,$0
+       BR Â·divWW_g(SB)
+
+TEXT Â·addVV(SB),NOSPLIT,$0
+       BR Â·addVV_g(SB)
+
+TEXT Â·subVV(SB),NOSPLIT,$0
+       BR Â·subVV_g(SB)
+
+TEXT Â·addVW(SB),NOSPLIT,$0
+       BR Â·addVW_g(SB)
+
+TEXT Â·subVW(SB),NOSPLIT,$0
+       BR Â·subVW_g(SB)
+
+TEXT Â·shlVU(SB),NOSPLIT,$0
+       BR Â·shlVU_g(SB)
+
+TEXT Â·shrVU(SB),NOSPLIT,$0
+       BR Â·shrVU_g(SB)
+
+TEXT Â·mulAddVWW(SB),NOSPLIT,$0
+       BR Â·mulAddVWW_g(SB)
+
+TEXT Â·addMulVVW(SB),NOSPLIT,$0
+       BR Â·addMulVVW_g(SB)
+
+TEXT Â·divWVW(SB),NOSPLIT,$0
+       BR Â·divWVW_g(SB)
+
+TEXT Â·bitLen(SB),NOSPLIT,$0
+       BR Â·bitLen_g(SB)
diff --git a/src/math/stubs_power64x.s b/src/math/stubs_power64x.s
new file mode 100644 (file)
index 0000000..36b7625
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+TEXT Â·Asin(SB),NOSPLIT,$0
+       BR Â·asin(SB)
+
+TEXT Â·Acos(SB),NOSPLIT,$0
+       BR Â·acos(SB)
+
+TEXT Â·Atan2(SB),NOSPLIT,$0
+       BR Â·atan2(SB)
+
+TEXT Â·Atan(SB),NOSPLIT,$0
+       BR Â·atan(SB)
+
+TEXT Â·Dim(SB),NOSPLIT,$0
+       BR Â·dim(SB)
+
+TEXT Â·Min(SB),NOSPLIT,$0
+       BR Â·min(SB)
+
+TEXT Â·Max(SB),NOSPLIT,$0
+       BR Â·max(SB)
+
+TEXT Â·Exp2(SB),NOSPLIT,$0
+       BR Â·exp2(SB)
+
+TEXT Â·Expm1(SB),NOSPLIT,$0
+       BR Â·expm1(SB)
+
+TEXT Â·Exp(SB),NOSPLIT,$0
+       BR Â·exp(SB)
+
+TEXT Â·Floor(SB),NOSPLIT,$0
+       BR Â·floor(SB)
+
+TEXT Â·Ceil(SB),NOSPLIT,$0
+       BR Â·ceil(SB)
+
+TEXT Â·Trunc(SB),NOSPLIT,$0
+       BR Â·trunc(SB)
+
+TEXT Â·Frexp(SB),NOSPLIT,$0
+       BR Â·frexp(SB)
+
+TEXT Â·Hypot(SB),NOSPLIT,$0
+       BR Â·hypot(SB)
+
+TEXT Â·Ldexp(SB),NOSPLIT,$0
+       BR Â·ldexp(SB)
+
+TEXT Â·Log10(SB),NOSPLIT,$0
+       BR Â·log10(SB)
+
+TEXT Â·Log2(SB),NOSPLIT,$0
+       BR Â·log2(SB)
+
+TEXT Â·Log1p(SB),NOSPLIT,$0
+       BR Â·log1p(SB)
+
+TEXT Â·Log(SB),NOSPLIT,$0
+       BR Â·log(SB)
+
+TEXT Â·Modf(SB),NOSPLIT,$0
+       BR Â·modf(SB)
+
+TEXT Â·Mod(SB),NOSPLIT,$0
+       BR Â·mod(SB)
+
+TEXT Â·Remainder(SB),NOSPLIT,$0
+       BR Â·remainder(SB)
+
+TEXT Â·Sincos(SB),NOSPLIT,$0
+       BR Â·sincos(SB)
+
+TEXT Â·Sin(SB),NOSPLIT,$0
+       BR Â·sin(SB)
+
+TEXT Â·Cos(SB),NOSPLIT,$0
+       BR Â·cos(SB)
+
+TEXT Â·Sqrt(SB),NOSPLIT,$0
+       BR Â·sqrt(SB)
+
+TEXT Â·Tan(SB),NOSPLIT,$0
+       BR Â·tan(SB)
index d54c284b5e9d90be76d6cb37e4aa79b74204d49b..1826c37fbd19585952aabe222ac95a6af307253b 100644 (file)
@@ -4,13 +4,19 @@
 
 // Assembly to get into package runtime without using exported symbols.
 
-// +build amd64 amd64p32 arm 386
+// +build amd64 amd64p32 arm 386 power64 power64le
 
 #include "textflag.h"
 
 #ifdef GOARCH_arm
 #define JMP B
 #endif
+#ifdef GOARCH_power64
+#define JMP BR
+#endif
+#ifdef GOARCH_power64le
+#define JMP BR
+#endif
 
 TEXT Â·signal_disable(SB),NOSPLIT,$0
        JMP runtime·signal_disable(SB)
index 268a9e319f6758adfc0cac38cdb179f64c0795a0..c62f227f435a880716cf2da90e57459ec1d9d44e 100644 (file)
@@ -1052,6 +1052,11 @@ func TestChan(t *testing.T) {
                ok = cv.TrySend(ValueOf(6))
                if !ok {
                        t.Errorf("TrySend on empty chan failed")
+                       select {
+                       case x := <-c:
+                               t.Errorf("TrySend failed but it did send %d", x)
+                       default:
+                       }
                } else {
                        if i = <-c; i != 6 {
                                t.Errorf("TrySend 6, recv %d", i)
diff --git a/src/reflect/asm_power64x.s b/src/reflect/asm_power64x.s
new file mode 100644 (file)
index 0000000..4720638
--- /dev/null
@@ -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 power64 power64le
+
+#include "textflag.h"
+#include "funcdata.h"
+
+// makeFuncStub is the code half of the function returned by MakeFunc.
+// See the comment on the declaration of makeFuncStub in makefunc.go
+// for more details.
+// No arg size here, runtime pulls arg map out of the func value.
+TEXT Â·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+       NO_LOCAL_POINTERS
+       MOVD    R11, 8(R1)
+       MOVD    $argframe+0(FP), R3
+       MOVD    R3, 16(R1)
+       BL      Â·callReflect(SB)
+       RETURN
+
+// methodValueCall is the code half of the function returned by makeMethodValue.
+// See the comment on the declaration of methodValueCall in makefunc.go
+// for more details.
+// No arg size here; runtime pulls arg map out of the func value.
+TEXT Â·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+       NO_LOCAL_POINTERS
+       MOVD    R11, 8(R1)
+       MOVD    $argframe+0(FP), R3
+       MOVD    R3, 16(R1)
+       BL      Â·callMethod(SB)
+       RETURN
index 572e611fa9d122227e620c4c9e4778ecaf06ca49..e05a3f9d173d989936ec8d2b0c066c86a8217e56 100644 (file)
@@ -1533,12 +1533,8 @@ func (gc *gcProg) appendProg(t *rtype) {
                        gc.appendProg(e)
                }
        case Interface:
-               gc.appendWord(bitsMultiWord)
-               if t.NumMethod() == 0 {
-                       gc.appendWord(bitsEface)
-               } else {
-                       gc.appendWord(bitsIface)
-               }
+               gc.appendWord(bitsPointer)
+               gc.appendWord(bitsPointer)
        case Struct:
                c := t.NumField()
                for i := 0; i < c; i++ {
@@ -1592,9 +1588,8 @@ func (gc *gcProg) align(a uintptr) {
 
 // These constants must stay in sync with ../runtime/mgc0.h.
 const (
-       bitsScalar    = 1
-       bitsPointer   = 2
-       bitsMultiWord = 3
+       bitsScalar  = 1
+       bitsPointer = 2
 
        bitsIface = 2
        bitsEface = 3
index 5f20451a2d379be95b4b87aca655c3fa4289fe53..6b9ecc33c299c3f7ebfd386c412beb3ab8c7e63a 100755 (executable)
@@ -255,8 +255,8 @@ rm -f runtest
 [ "$GOOS" == nacl ] ||
 (
 echo
-echo '# Checking API compatibility.'
-time go run $GOROOT/src/cmd/api/run.go || exit 1
+echo '# SKIPPING API CHECK UNTIL ALL SYSTEMS BUILD.'
+time go run $GOROOT/src/cmd/api/run.go || exit 1
 ) || exit $?
 
 echo
index e9ed59503ffbf8fe705a4a256d02b98a083d8493..e367bc5b2f4d23986ef39cb4f068de30282b7670 100644 (file)
@@ -314,9 +314,6 @@ const hashRandomBytes = 32
 
 var aeskeysched [hashRandomBytes]byte
 
-//go:noescape
-func get_random_data(rnd *unsafe.Pointer, n *int32)
-
 func init() {
        if theGoos == "nacl" {
                return
diff --git a/src/runtime/arch1_386.go b/src/runtime/arch1_386.go
new file mode 100644 (file)
index 0000000..a73e207
--- /dev/null
@@ -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.
+
+package runtime
+
+const (
+       thechar           = '8'
+       _BigEndian        = 0
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64
+       _PhysPageSize     = goos_nacl*65536 + (1-goos_nacl)*4096 // 4k normally; 64k on NaCl
+       _PCQuantum        = 1
+       _Int64Align       = 4
+)
diff --git a/src/runtime/arch1_amd64.go b/src/runtime/arch1_amd64.go
new file mode 100644 (file)
index 0000000..794b7f6
--- /dev/null
@@ -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.
+
+package runtime
+
+const (
+       thechar           = '6'
+       _BigEndian        = 0
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64 + (goos_plan9|goos_solaris|goos_windows)*16
+       _PhysPageSize     = 4096
+       _PCQuantum        = 1
+       _Int64Align       = 8
+)
diff --git a/src/runtime/arch1_arm.go b/src/runtime/arch1_arm.go
new file mode 100644 (file)
index 0000000..6662eae
--- /dev/null
@@ -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.
+
+package runtime
+
+const (
+       thechar           = '5'
+       _BigEndian        = 0
+       _CacheLineSize    = 32
+       _RuntimeGogoBytes = 60
+       _PhysPageSize     = 65536*goos_nacl + 4096*(1-goos_nacl)
+       _PCQuantum        = 4
+       _Int64Align       = 4
+)
diff --git a/src/runtime/arch1_power64.go b/src/runtime/arch1_power64.go
new file mode 100644 (file)
index 0000000..01e2b70
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       thechar           = '9'
+       _BigEndian        = 1
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64
+       _PhysPageSize     = 65536
+       _PCQuantum        = 4
+       _Int64Align       = 8
+)
diff --git a/src/runtime/arch1_power64le.go b/src/runtime/arch1_power64le.go
new file mode 100644 (file)
index 0000000..6580732
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       thechar           = '9'
+       _BigEndian        = 0
+       _CacheLineSize    = 64
+       _RuntimeGogoBytes = 64
+       _PhysPageSize     = 65536
+       _PCQuantum        = 4
+       _Int64Align       = 8
+)
diff --git a/src/runtime/arch_386.h b/src/runtime/arch_386.h
deleted file mode 100644 (file)
index 75a5ba7..0000000
+++ /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.
-
-enum {
-       thechar = '8',
-       BigEndian = 0,
-       CacheLineSize = 64,
-       RuntimeGogoBytes = 64,
-#ifdef GOOS_nacl
-       PhysPageSize = 65536,
-#else
-       PhysPageSize = 4096,
-#endif
-       PCQuantum = 1,
-       Int64Align = 4
-};
diff --git a/src/runtime/arch_amd64.h b/src/runtime/arch_amd64.h
deleted file mode 100644 (file)
index d7b81ee..0000000
+++ /dev/null
@@ -1,25 +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.
-
-enum {
-       thechar = '6',
-       BigEndian = 0,
-       CacheLineSize = 64,
-#ifdef GOOS_solaris
-       RuntimeGogoBytes = 80,
-#else
-#ifdef GOOS_windows
-       RuntimeGogoBytes = 80,
-#else
-#ifdef GOOS_plan9
-       RuntimeGogoBytes = 80,
-#else
-       RuntimeGogoBytes = 64,
-#endif // Plan 9
-#endif // Windows
-#endif // Solaris
-       PhysPageSize = 4096,
-       PCQuantum = 1,
-       Int64Align = 8
-};
diff --git a/src/runtime/arch_arm.h b/src/runtime/arch_arm.h
deleted file mode 100644 (file)
index 637a334..0000000
+++ /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.
-
-enum {
-       thechar = '5',
-       BigEndian = 0,
-       CacheLineSize = 32,
-       RuntimeGogoBytes = 60,
-#ifdef GOOS_nacl
-       PhysPageSize = 65536,
-#else
-       PhysPageSize = 4096,
-#endif
-       PCQuantum = 4,
-       Int64Align = 4
-};
diff --git a/src/runtime/arch_power64.go b/src/runtime/arch_power64.go
new file mode 100644 (file)
index 0000000..270cd7b
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type uintreg uint64
+type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/arch_power64le.go b/src/runtime/arch_power64le.go
new file mode 100644 (file)
index 0000000..270cd7b
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type uintreg uint64
+type intptr int64 // TODO(rsc): remove
index e6d782f37eedd10d8029ea32883ab3ee6c87a046..f1c812b90f73c632496047db0ac9664338f9f063 100644 (file)
@@ -12,3 +12,8 @@ DATA runtime·no_pointers_stackmap+0x00(SB)/4, $2
 DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0
 GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8
 
+TEXT runtime·nop(SB),NOSPLIT,$0-0
+       RET
+
+GLOBL runtime·mheap_(SB), NOPTR, $0
+GLOBL runtime·memstats(SB), NOPTR, $0
index b4b81d7397eb03f169aa527eab2d639cb6deb20a..a02bb5556f37b783fc0ddc8f4e23f34fba9212c8 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
@@ -49,7 +50,7 @@ nocpuinfo:
        // update stackguard after _cgo_init
        MOVL    $runtime·g0(SB), CX
        MOVL    (g_stack+stack_lo)(CX), AX
-       ADDL    $const_StackGuard, AX
+       ADDL    $const__StackGuard, AX
        MOVL    AX, g_stackguard0(CX)
        MOVL    AX, g_stackguard1(CX)
 
@@ -199,62 +200,49 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
        JMP     AX
        RET
 
-// switchtoM is a dummy routine that onM leaves at the bottom
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
 // of the G stack.  We need to distinguish the routine that
 // lives at the bottom of the G stack from the one that lives
-// at the top of the M stack because the one at the top of
-// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
        RET
 
-// func onM_signalok(fn func())
-TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-4
+       MOVL    fn+0(FP), DI    // DI = fn
        get_tls(CX)
        MOVL    g(CX), AX       // AX = g
        MOVL    g_m(AX), BX     // BX = m
+
        MOVL    m_gsignal(BX), DX       // DX = gsignal
        CMPL    AX, DX
-       JEQ     ongsignal
-       JMP     runtime·onM(SB)
-
-ongsignal:
-       MOVL    fn+0(FP), DI    // DI = fn
-       MOVL    DI, DX
-       MOVL    0(DI), DI
-       CALL    DI
-       RET
-
-// func onM(fn func())
-TEXT runtime·onM(SB), NOSPLIT, $0-4
-       MOVL    fn+0(FP), DI    // DI = fn
-       get_tls(CX)
-       MOVL    g(CX), AX       // AX = g
-       MOVL    g_m(AX), BX     // BX = m
+       JEQ     noswitch
 
        MOVL    m_g0(BX), DX    // DX = g0
        CMPL    AX, DX
-       JEQ     onm
+       JEQ     noswitch
 
        MOVL    m_curg(BX), BP
        CMPL    AX, BP
-       JEQ     oncurg
+       JEQ     switch
        
-       // Not g0, not curg. Must be gsignal, but that's not allowed.
+       // Bad: g is not gsignal, not g0, not curg. What is it?
        // Hide call from linker nosplit analysis.
-       MOVL    $runtime·badonm(SB), AX
+       MOVL    $runtime·badsystemstack(SB), AX
        CALL    AX
 
-oncurg:
+switch:
        // save our state in g->sched.  Pretend to
-       // be switchtoM if the G stack is scanned.
-       MOVL    $runtime·switchtoM(SB), (g_sched+gobuf_pc)(AX)
+       // be systemstack_switch if the G stack is scanned.
+       MOVL    $runtime·systemstack_switch(SB), (g_sched+gobuf_pc)(AX)
        MOVL    SP, (g_sched+gobuf_sp)(AX)
        MOVL    AX, (g_sched+gobuf_g)(AX)
 
        // switch to g0
        MOVL    DX, g(CX)
        MOVL    (g_sched+gobuf_sp)(DX), BX
-       // make it look like mstart called onM on g0, to stop traceback
+       // make it look like mstart called systemstack on g0, to stop traceback
        SUBL    $4, BX
        MOVL    $runtime·mstart(SB), DX
        MOVL    DX, 0(BX)
@@ -275,8 +263,8 @@ oncurg:
        MOVL    $0, (g_sched+gobuf_sp)(AX)
        RET
 
-onm:
-       // already on m stack, just call directly
+noswitch:
+       // already on system stack, just call directly
        MOVL    DI, DX
        MOVL    0(DI), DI
        CALL    DI
@@ -486,11 +474,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-21
        MOVL    new_hi+16(FP), CX
        LOCK
        CMPXCHG8B       0(BP)
-       JNZ     cas64_fail
+       JNZ     fail
        MOVL    $1, AX
        MOVB    AX, ret+20(FP)
        RET
-cas64_fail:
+fail:
        MOVL    $0, AX
        MOVB    AX, ret+20(FP)
        RET
@@ -502,7 +490,7 @@ cas64_fail:
 //             return 1;
 //     }else
 //             return 0;
-TEXT runtime·casp(SB), NOSPLIT, $0-13
+TEXT runtime·casp1(SB), NOSPLIT, $0-13
        MOVL    ptr+0(FP), BX
        MOVL    old+4(FP), AX
        MOVL    new+8(FP), CX
@@ -537,7 +525,7 @@ TEXT runtime·xchg(SB), NOSPLIT, $0-12
        MOVL    AX, ret+8(FP)
        RET
 
-TEXT runtime·xchgp(SB), NOSPLIT, $0-12
+TEXT runtime·xchgp1(SB), NOSPLIT, $0-12
        MOVL    ptr+0(FP), BX
        MOVL    new+4(FP), AX
        XCHGL   AX, 0(BX)
@@ -555,7 +543,7 @@ again:
        JNZ     again
        RET
 
-TEXT runtime·atomicstorep(SB), NOSPLIT, $0-8
+TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8
        MOVL    ptr+0(FP), BX
        MOVL    val+4(FP), AX
        XCHGL   AX, 0(BX)
@@ -740,7 +728,7 @@ needm:
        // the same SP back to m->sched.sp. That seems redundant,
        // but if an unrecovered panic happens, unwindm will
        // restore the g->sched.sp from the stack location
-       // and then onM will try to use it. If we don't set it here,
+       // and then systemstack will try to use it. If we don't set it here,
        // that restored SP will be uninitialized (typically 0) and
        // will not be usable.
        MOVL    m_g0(BP), SI
@@ -1356,29 +1344,29 @@ TEXT strings·IndexByte(SB),NOSPLIT,$0
 //   AX = 1/0/-1
 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
        CMPL    SI, DI
-       JEQ     cmp_allsame
+       JEQ     allsame
        CMPL    BX, DX
        MOVL    DX, BP
        CMOVLLT BX, BP // BP = min(alen, blen)
        CMPL    BP, $4
-       JB      cmp_small
+       JB      small
        TESTL   $0x4000000, runtime·cpuid_edx(SB) // check for sse2
-       JE      cmp_mediumloop
-cmp_largeloop:
+       JE      mediumloop
+largeloop:
        CMPL    BP, $16
-       JB      cmp_mediumloop
+       JB      mediumloop
        MOVOU   (SI), X0
        MOVOU   (DI), X1
        PCMPEQB X0, X1
        PMOVMSKB X1, AX
        XORL    $0xffff, AX     // convert EQ to NE
-       JNE     cmp_diff16      // branch if at least one byte is not equal
+       JNE     diff16  // branch if at least one byte is not equal
        ADDL    $16, SI
        ADDL    $16, DI
        SUBL    $16, BP
-       JMP     cmp_largeloop
+       JMP     largeloop
 
-cmp_diff16:
+diff16:
        BSFL    AX, BX  // index of first byte that differs
        XORL    AX, AX
        MOVB    (SI)(BX*1), CX
@@ -1387,25 +1375,25 @@ cmp_diff16:
        LEAL    -1(AX*2), AX    // convert 1/0 to +1/-1
        RET
 
-cmp_mediumloop:
+mediumloop:
        CMPL    BP, $4
-       JBE     cmp_0through4
+       JBE     _0through4
        MOVL    (SI), AX
        MOVL    (DI), CX
        CMPL    AX, CX
-       JNE     cmp_diff4
+       JNE     diff4
        ADDL    $4, SI
        ADDL    $4, DI
        SUBL    $4, BP
-       JMP     cmp_mediumloop
+       JMP     mediumloop
 
-cmp_0through4:
+_0through4:
        MOVL    -4(SI)(BP*1), AX
        MOVL    -4(DI)(BP*1), CX
        CMPL    AX, CX
-       JEQ     cmp_allsame
+       JEQ     allsame
 
-cmp_diff4:
+diff4:
        BSWAPL  AX      // reverse order of bytes
        BSWAPL  CX
        XORL    AX, CX  // find bit differences
@@ -1416,37 +1404,37 @@ cmp_diff4:
        RET
 
        // 0-3 bytes in common
-cmp_small:
+small:
        LEAL    (BP*8), CX
        NEGL    CX
-       JEQ     cmp_allsame
+       JEQ     allsame
 
        // load si
        CMPB    SI, $0xfc
-       JA      cmp_si_high
+       JA      si_high
        MOVL    (SI), SI
-       JMP     cmp_si_finish
-cmp_si_high:
+       JMP     si_finish
+si_high:
        MOVL    -4(SI)(BP*1), SI
        SHRL    CX, SI
-cmp_si_finish:
+si_finish:
        SHLL    CX, SI
 
        // same for di
        CMPB    DI, $0xfc
-       JA      cmp_di_high
+       JA      di_high
        MOVL    (DI), DI
-       JMP     cmp_di_finish
-cmp_di_high:
+       JMP     di_finish
+di_high:
        MOVL    -4(DI)(BP*1), DI
        SHRL    CX, DI
-cmp_di_finish:
+di_finish:
        SHLL    CX, DI
 
        BSWAPL  SI      // reverse order of bytes
        BSWAPL  DI
        XORL    SI, DI  // find bit differences
-       JEQ     cmp_allsame
+       JEQ     allsame
        BSRL    DI, CX  // index of highest bit difference
        SHRL    CX, SI  // move a's bit to bottom
        ANDL    $1, SI  // mask bit
@@ -1455,7 +1443,7 @@ cmp_di_finish:
 
        // all the bytes in common are the same, so we just need
        // to compare the lengths.
-cmp_allsame:
+allsame:
        XORL    AX, AX
        XORL    CX, CX
        CMPL    BX, DX
@@ -2290,3 +2278,10 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
 TEXT runtime·goexit(SB),NOSPLIT,$0-0
        BYTE    $0x90   // NOP
        CALL    runtime·goexit1(SB)    // does not return
+
+TEXT runtime·getg(SB),NOSPLIT,$0-4
+       get_tls(CX)
+       MOVL    g(CX), AX
+       MOVL    AX, ret+0(FP)
+       RET
+
index 39d7c78f23346f9ed87259f324811d4c8b6538ba..6e3f5ff6ca91d96eaaa18c3fea53c9eb4b726735 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
@@ -47,7 +48,7 @@ nocpuinfo:
        // update stackguard after _cgo_init
        MOVQ    $runtime·g0(SB), CX
        MOVQ    (g_stack+stack_lo)(CX), AX
-       ADDQ    $const_StackGuard, AX
+       ADDQ    $const__StackGuard, AX
        MOVQ    AX, g_stackguard0(CX)
        MOVQ    AX, g_stackguard1(CX)
 
@@ -189,55 +190,41 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8
        JMP     AX
        RET
 
-// switchtoM is a dummy routine that onM leaves at the bottom
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
 // of the G stack.  We need to distinguish the routine that
 // lives at the bottom of the G stack from the one that lives
-// at the top of the M stack because the one at the top of
-// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
        RET
 
-// func onM_signalok(fn func())
-TEXT runtime·onM_signalok(SB), NOSPLIT, $0-8
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-8
+       MOVQ    fn+0(FP), DI    // DI = fn
        get_tls(CX)
        MOVQ    g(CX), AX       // AX = g
        MOVQ    g_m(AX), BX     // BX = m
+
        MOVQ    m_gsignal(BX), DX       // DX = gsignal
        CMPQ    AX, DX
-       JEQ     ongsignal
-       JMP     runtime·onM(SB)
-
-ongsignal:
-       MOVQ    fn+0(FP), DI    // DI = fn
-       MOVQ    DI, DX
-       MOVQ    0(DI), DI
-       CALL    DI
-       RET
-
-// func onM(fn func())
-TEXT runtime·onM(SB), NOSPLIT, $0-8
-       MOVQ    fn+0(FP), DI    // DI = fn
-       get_tls(CX)
-       MOVQ    g(CX), AX       // AX = g
-       MOVQ    g_m(AX), BX     // BX = m
+       JEQ     noswitch
 
        MOVQ    m_g0(BX), DX    // DX = g0
        CMPQ    AX, DX
-       JEQ     onm
+       JEQ     noswitch
 
        MOVQ    m_curg(BX), BP
        CMPQ    AX, BP
-       JEQ     oncurg
+       JEQ     switch
        
-       // Not g0, not curg. Must be gsignal, but that's not allowed.
-       // Hide call from linker nosplit analysis.
-       MOVQ    $runtime·badonm(SB), AX
+       // Bad: g is not gsignal, not g0, not curg. What is it?
+       MOVQ    $runtime·badsystemstack(SB), AX
        CALL    AX
 
-oncurg:
+switch:
        // save our state in g->sched.  Pretend to
-       // be switchtoM if the G stack is scanned.
-       MOVQ    $runtime·switchtoM(SB), BP
+       // be systemstack_switch if the G stack is scanned.
+       MOVQ    $runtime·systemstack_switch(SB), BP
        MOVQ    BP, (g_sched+gobuf_pc)(AX)
        MOVQ    SP, (g_sched+gobuf_sp)(AX)
        MOVQ    AX, (g_sched+gobuf_g)(AX)
@@ -245,7 +232,7 @@ oncurg:
        // switch to g0
        MOVQ    DX, g(CX)
        MOVQ    (g_sched+gobuf_sp)(DX), BX
-       // make it look like mstart called onM on g0, to stop traceback
+       // make it look like mstart called systemstack on g0, to stop traceback
        SUBQ    $8, BX
        MOVQ    $runtime·mstart(SB), DX
        MOVQ    DX, 0(BX)
@@ -266,7 +253,7 @@ oncurg:
        MOVQ    $0, (g_sched+gobuf_sp)(AX)
        RET
 
-onm:
+noswitch:
        // already on m stack, just call directly
        MOVQ    DI, DX
        MOVQ    0(DI), DI
@@ -461,11 +448,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25
        MOVQ    new+16(FP), CX
        LOCK
        CMPXCHGQ        CX, 0(BX)
-       JNZ     cas64_fail
+       JNZ     fail
        MOVL    $1, AX
        MOVB    AX, ret+24(FP)
        RET
-cas64_fail:
+fail:
        MOVL    $0, AX
        MOVB    AX, ret+24(FP)
        RET
@@ -489,7 +476,7 @@ TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
 //             return 1;
 //     } else
 //             return 0;
-TEXT runtime·casp(SB), NOSPLIT, $0-25
+TEXT runtime·casp1(SB), NOSPLIT, $0-25
        MOVQ    ptr+0(FP), BX
        MOVQ    old+8(FP), AX
        MOVQ    new+16(FP), CX
@@ -541,7 +528,7 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24
        MOVQ    AX, ret+16(FP)
        RET
 
-TEXT runtime·xchgp(SB), NOSPLIT, $0-24
+TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
        MOVQ    ptr+0(FP), BX
        MOVQ    new+8(FP), AX
        XCHGQ   AX, 0(BX)
@@ -559,7 +546,7 @@ again:
        JNZ     again
        RET
 
-TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16
+TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
        MOVQ    ptr+0(FP), BX
        MOVQ    val+8(FP), AX
        XCHGQ   AX, 0(BX)
@@ -726,7 +713,7 @@ needm:
        // the same SP back to m->sched.sp. That seems redundant,
        // but if an unrecovered panic happens, unwindm will
        // restore the g->sched.sp from the stack location
-       // and then onM will try to use it. If we don't set it here,
+       // and then systemstack will try to use it. If we don't set it here,
        // that restored SP will be uninitialized (typically 0) and
        // will not be usable.
        MOVQ    m_g0(BP), SI
@@ -890,24 +877,24 @@ TEXT runtime·aeshashbody(SB),NOSPLIT,$0-32
        MOVO    runtime·aeskeysched+0(SB), X2
        MOVO    runtime·aeskeysched+16(SB), X3
        CMPQ    CX, $16
-       JB      aessmall
-aesloop:
+       JB      small
+loop:
        CMPQ    CX, $16
-       JBE     aesloopend
+       JBE     loopend
        MOVOU   (AX), X1
        AESENC  X2, X0
        AESENC  X1, X0
        SUBQ    $16, CX
        ADDQ    $16, AX
-       JMP     aesloop
+       JMP     loop
 // 1-16 bytes remaining
-aesloopend:
+loopend:
        // This load may overlap with the previous load above.
        // We'll hash some bytes twice, but that's ok.
        MOVOU   -16(AX)(CX*1), X1
        JMP     partial
 // 0-15 bytes
-aessmall:
+small:
        TESTQ   CX, CX
        JE      finalize        // 0 bytes
 
@@ -1050,18 +1037,18 @@ TEXT runtime·eqstring(SB),NOSPLIT,$0-33
        MOVQ    s1len+8(FP), AX
        MOVQ    s2len+24(FP), BX
        CMPQ    AX, BX
-       JNE     different
+       JNE     noteq
        MOVQ    s1str+0(FP), SI
        MOVQ    s2str+16(FP), DI
        CMPQ    SI, DI
-       JEQ     same
+       JEQ     eq
        CALL    runtime·memeqbody(SB)
        MOVB    AX, v+32(FP)
        RET
-same:
+eq:
        MOVB    $1, v+32(FP)
        RET
-different:
+noteq:
        MOVB    $0, v+32(FP)
        RET
 
@@ -1184,29 +1171,29 @@ TEXT runtime·cmpbytes(SB),NOSPLIT,$0-56
 //   AX = 1/0/-1
 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
        CMPQ    SI, DI
-       JEQ     cmp_allsame
+       JEQ     allsame
        CMPQ    BX, DX
        MOVQ    DX, BP
        CMOVQLT BX, BP // BP = min(alen, blen) = # of bytes to compare
        CMPQ    BP, $8
-       JB      cmp_small
+       JB      small
 
-cmp_loop:
+loop:
        CMPQ    BP, $16
-       JBE     cmp_0through16
+       JBE     _0through16
        MOVOU   (SI), X0
        MOVOU   (DI), X1
        PCMPEQB X0, X1
        PMOVMSKB X1, AX
        XORQ    $0xffff, AX     // convert EQ to NE
-       JNE     cmp_diff16      // branch if at least one byte is not equal
+       JNE     diff16  // branch if at least one byte is not equal
        ADDQ    $16, SI
        ADDQ    $16, DI
        SUBQ    $16, BP
-       JMP     cmp_loop
+       JMP     loop
        
        // AX = bit mask of differences
-cmp_diff16:
+diff16:
        BSFQ    AX, BX  // index of first byte that differs
        XORQ    AX, AX
        MOVB    (SI)(BX*1), CX
@@ -1216,21 +1203,21 @@ cmp_diff16:
        RET
 
        // 0 through 16 bytes left, alen>=8, blen>=8
-cmp_0through16:
+_0through16:
        CMPQ    BP, $8
-       JBE     cmp_0through8
+       JBE     _0through8
        MOVQ    (SI), AX
        MOVQ    (DI), CX
        CMPQ    AX, CX
-       JNE     cmp_diff8
-cmp_0through8:
+       JNE     diff8
+_0through8:
        MOVQ    -8(SI)(BP*1), AX
        MOVQ    -8(DI)(BP*1), CX
        CMPQ    AX, CX
-       JEQ     cmp_allsame
+       JEQ     allsame
 
        // AX and CX contain parts of a and b that differ.
-cmp_diff8:
+diff8:
        BSWAPQ  AX      // reverse order of bytes
        BSWAPQ  CX
        XORQ    AX, CX
@@ -1241,44 +1228,44 @@ cmp_diff8:
        RET
 
        // 0-7 bytes in common
-cmp_small:
+small:
        LEAQ    (BP*8), CX      // bytes left -> bits left
        NEGQ    CX              //  - bits lift (== 64 - bits left mod 64)
-       JEQ     cmp_allsame
+       JEQ     allsame
 
        // load bytes of a into high bytes of AX
        CMPB    SI, $0xf8
-       JA      cmp_si_high
+       JA      si_high
        MOVQ    (SI), SI
-       JMP     cmp_si_finish
-cmp_si_high:
+       JMP     si_finish
+si_high:
        MOVQ    -8(SI)(BP*1), SI
        SHRQ    CX, SI
-cmp_si_finish:
+si_finish:
        SHLQ    CX, SI
 
        // load bytes of b in to high bytes of BX
        CMPB    DI, $0xf8
-       JA      cmp_di_high
+       JA      di_high
        MOVQ    (DI), DI
-       JMP     cmp_di_finish
-cmp_di_high:
+       JMP     di_finish
+di_high:
        MOVQ    -8(DI)(BP*1), DI
        SHRQ    CX, DI
-cmp_di_finish:
+di_finish:
        SHLQ    CX, DI
 
        BSWAPQ  SI      // reverse order of bytes
        BSWAPQ  DI
        XORQ    SI, DI  // find bit differences
-       JEQ     cmp_allsame
+       JEQ     allsame
        BSRQ    DI, CX  // index of highest bit difference
        SHRQ    CX, SI  // move a's bit to bottom
        ANDQ    $1, SI  // mask bit
        LEAQ    -1(SI*2), AX // 1/0 => +1/-1
        RET
 
-cmp_allsame:
+allsame:
        XORQ    AX, AX
        XORQ    CX, CX
        CMPQ    BX, DX
@@ -1313,7 +1300,7 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0
        MOVQ SI, DI
 
        CMPQ BX, $16
-       JLT indexbyte_small
+       JLT small
 
        // round up to first 16-byte boundary
        TESTQ $15, SI
@@ -1371,7 +1358,7 @@ failure:
        RET
 
 // handle for lengths < 16
-indexbyte_small:
+small:
        MOVQ BX, CX
        REPN; SCASB
        JZ success
@@ -2235,3 +2222,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
 TEXT runtime·goexit(SB),NOSPLIT,$0-0
        BYTE    $0x90   // NOP
        CALL    runtime·goexit1(SB)    // does not return
+
+TEXT runtime·getg(SB),NOSPLIT,$0-8
+       get_tls(CX)
+       MOVQ    g(CX), AX
+       MOVQ    AX, ret+0(FP)
+       RET
index a1116b5d471ed35a44bd7a7a5c6d5c6d6816fc18..b8370efd363cf7effa885d30d92dd69443e70d31 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
@@ -164,55 +165,42 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
        JMP     AX
        RET
 
-// switchtoM is a dummy routine that onM leaves at the bottom
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
 // of the G stack.  We need to distinguish the routine that
 // lives at the bottom of the G stack from the one that lives
-// at the top of the M stack because the one at the top of
-// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
        RET
 
-// func onM_signalok(fn func())
-TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-4
+       MOVL    fn+0(FP), DI    // DI = fn
        get_tls(CX)
        MOVL    g(CX), AX       // AX = g
        MOVL    g_m(AX), BX     // BX = m
+
        MOVL    m_gsignal(BX), DX       // DX = gsignal
        CMPL    AX, DX
-       JEQ     ongsignal
-       JMP     runtime·onM(SB)
-
-ongsignal:
-       MOVL    fn+0(FP), DI    // DI = fn
-       MOVL    DI, DX
-       MOVL    0(DI), DI
-       CALL    DI
-       RET
-
-// func onM(fn func())
-TEXT runtime·onM(SB), NOSPLIT, $0-4
-       MOVL    fn+0(FP), DI    // DI = fn
-       get_tls(CX)
-       MOVL    g(CX), AX       // AX = g
-       MOVL    g_m(AX), BX     // BX = m
+       JEQ     noswitch
 
        MOVL    m_g0(BX), DX    // DX = g0
        CMPL    AX, DX
-       JEQ     onm
+       JEQ     noswitch
 
        MOVL    m_curg(BX), R8
        CMPL    AX, R8
-       JEQ     oncurg
+       JEQ     switch
        
        // Not g0, not curg. Must be gsignal, but that's not allowed.
        // Hide call from linker nosplit analysis.
-       MOVL    $runtime·badonm(SB), AX
+       MOVL    $runtime·badsystemstack(SB), AX
        CALL    AX
 
-oncurg:
+switch:
        // save our state in g->sched.  Pretend to
-       // be switchtoM if the G stack is scanned.
-       MOVL    $runtime·switchtoM(SB), SI
+       // be systemstack_switch if the G stack is scanned.
+       MOVL    $runtime·systemstack_switch(SB), SI
        MOVL    SI, (g_sched+gobuf_pc)(AX)
        MOVL    SP, (g_sched+gobuf_sp)(AX)
        MOVL    AX, (g_sched+gobuf_g)(AX)
@@ -236,7 +224,7 @@ oncurg:
        MOVL    $0, (g_sched+gobuf_sp)(AX)
        RET
 
-onm:
+noswitch:
        // already on m stack, just call directly
        MOVL    DI, DX
        MOVL    0(DI), DI
@@ -444,11 +432,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25
        MOVQ    new+16(FP), CX
        LOCK
        CMPXCHGQ        CX, 0(BX)
-       JNZ     cas64_fail
+       JNZ     fail
        MOVL    $1, AX
        MOVB    AX, ret+24(FP)
        RET
-cas64_fail:
+fail:
        MOVL    $0, AX
        MOVB    AX, ret+24(FP)
        RET
@@ -460,7 +448,7 @@ cas64_fail:
 //             return 1;
 //     } else
 //             return 0;
-TEXT runtime·casp(SB), NOSPLIT, $0-17
+TEXT runtime·casp1(SB), NOSPLIT, $0-17
        MOVL    ptr+0(FP), BX
        MOVL    old+4(FP), AX
        MOVL    new+8(FP), CX
@@ -512,7 +500,7 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24
        MOVQ    AX, ret+16(FP)
        RET
 
-TEXT runtime·xchgp(SB), NOSPLIT, $0-12
+TEXT runtime·xchgp1(SB), NOSPLIT, $0-12
        MOVL    ptr+0(FP), BX
        MOVL    new+4(FP), AX
        XCHGL   AX, 0(BX)
@@ -530,7 +518,7 @@ again:
        JNZ     again
        RET
 
-TEXT runtime·atomicstorep(SB), NOSPLIT, $0-8
+TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8
        MOVL    ptr+0(FP), BX
        MOVL    val+4(FP), AX
        XCHGL   AX, 0(BX)
@@ -834,29 +822,29 @@ TEXT runtime·cmpbytes(SB),NOSPLIT,$0-28
 //   AX = 1/0/-1
 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
        CMPQ    SI, DI
-       JEQ     cmp_allsame
+       JEQ     allsame
        CMPQ    BX, DX
        MOVQ    DX, R8
        CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare
        CMPQ    R8, $8
-       JB      cmp_small
+       JB      small
 
-cmp_loop:
+loop:
        CMPQ    R8, $16
-       JBE     cmp_0through16
+       JBE     _0through16
        MOVOU   (SI), X0
        MOVOU   (DI), X1
        PCMPEQB X0, X1
        PMOVMSKB X1, AX
        XORQ    $0xffff, AX     // convert EQ to NE
-       JNE     cmp_diff16      // branch if at least one byte is not equal
+       JNE     diff16  // branch if at least one byte is not equal
        ADDQ    $16, SI
        ADDQ    $16, DI
        SUBQ    $16, R8
-       JMP     cmp_loop
+       JMP     loop
        
        // AX = bit mask of differences
-cmp_diff16:
+diff16:
        BSFQ    AX, BX  // index of first byte that differs
        XORQ    AX, AX
        ADDQ    BX, SI
@@ -868,23 +856,23 @@ cmp_diff16:
        RET
 
        // 0 through 16 bytes left, alen>=8, blen>=8
-cmp_0through16:
+_0through16:
        CMPQ    R8, $8
-       JBE     cmp_0through8
+       JBE     _0through8
        MOVQ    (SI), AX
        MOVQ    (DI), CX
        CMPQ    AX, CX
-       JNE     cmp_diff8
-cmp_0through8:
+       JNE     diff8
+_0through8:
        ADDQ    R8, SI
        ADDQ    R8, DI
        MOVQ    -8(SI), AX
        MOVQ    -8(DI), CX
        CMPQ    AX, CX
-       JEQ     cmp_allsame
+       JEQ     allsame
 
        // AX and CX contain parts of a and b that differ.
-cmp_diff8:
+diff8:
        BSWAPQ  AX      // reverse order of bytes
        BSWAPQ  CX
        XORQ    AX, CX
@@ -895,46 +883,46 @@ cmp_diff8:
        RET
 
        // 0-7 bytes in common
-cmp_small:
+small:
        LEAQ    (R8*8), CX      // bytes left -> bits left
        NEGQ    CX              //  - bits lift (== 64 - bits left mod 64)
-       JEQ     cmp_allsame
+       JEQ     allsame
 
        // load bytes of a into high bytes of AX
        CMPB    SI, $0xf8
-       JA      cmp_si_high
+       JA      si_high
        MOVQ    (SI), SI
-       JMP     cmp_si_finish
-cmp_si_high:
+       JMP     si_finish
+si_high:
        ADDQ    R8, SI
        MOVQ    -8(SI), SI
        SHRQ    CX, SI
-cmp_si_finish:
+si_finish:
        SHLQ    CX, SI
 
        // load bytes of b in to high bytes of BX
        CMPB    DI, $0xf8
-       JA      cmp_di_high
+       JA      di_high
        MOVQ    (DI), DI
-       JMP     cmp_di_finish
-cmp_di_high:
+       JMP     di_finish
+di_high:
        ADDQ    R8, DI
        MOVQ    -8(DI), DI
        SHRQ    CX, DI
-cmp_di_finish:
+di_finish:
        SHLQ    CX, DI
 
        BSWAPQ  SI      // reverse order of bytes
        BSWAPQ  DI
        XORQ    SI, DI  // find bit differences
-       JEQ     cmp_allsame
+       JEQ     allsame
        BSRQ    DI, CX  // index of highest bit difference
        SHRQ    CX, SI  // move a's bit to bottom
        ANDQ    $1, SI  // mask bit
        LEAQ    -1(SI*2), AX // 1/0 => +1/-1
        RET
 
-cmp_allsame:
+allsame:
        XORQ    AX, AX
        XORQ    CX, CX
        CMPQ    BX, DX
@@ -969,7 +957,7 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0
        MOVL SI, DI
 
        CMPL BX, $16
-       JLT indexbyte_small
+       JLT small
 
        // round up to first 16-byte boundary
        TESTL $15, SI
@@ -1027,7 +1015,7 @@ failure:
        RET
 
 // handle for lengths < 16
-indexbyte_small:
+small:
        MOVL BX, CX
        REPN; SCASB
        JZ success
@@ -1085,3 +1073,9 @@ TEXT runtime·return0(SB), NOSPLIT, $0
 TEXT runtime·goexit(SB),NOSPLIT,$0-0
        BYTE    $0x90   // NOP
        CALL    runtime·goexit1(SB)    // does not return
+
+TEXT runtime·getg(SB),NOSPLIT,$0-4
+       get_tls(CX)
+       MOVL    g(CX), AX
+       MOVL    AX, ret+0(FP)
+       RET
index 0f3b5eeb8bd338d7087c4d969367443ea57a3670..583c7ba50115606230793c4fe1e56c60032dc847 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
@@ -54,7 +55,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$-4
 nocgo:
        // update stackguard after _cgo_init
        MOVW    (g_stack+stack_lo)(g), R0
-       ADD     $const_StackGuard, R0
+       ADD     $const__StackGuard, R0
        MOVW    R0, g_stackguard0(g)
        MOVW    R0, g_stackguard1(g)
 
@@ -190,53 +191,42 @@ TEXT runtime·mcall(SB),NOSPLIT,$-4-4
        B       runtime·badmcall2(SB)
        RET
 
-// switchtoM is a dummy routine that onM leaves at the bottom
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
 // of the G stack.  We need to distinguish the routine that
 // lives at the bottom of the G stack from the one that lives
-// at the top of the M stack because the one at the top of
-// the M stack terminates the stack walk (see topofstack()).
-TEXT runtime·switchtoM(SB),NOSPLIT,$0-0
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
        MOVW    $0, R0
        BL      (R0) // clobber lr to ensure push {lr} is kept
        RET
 
-// func onM_signalok(fn func())
-TEXT runtime·onM_signalok(SB), NOSPLIT, $-4-4
-       MOVW    g_m(g), R1
-       MOVW    m_gsignal(R1), R2
-       CMP     g, R2
-       B.EQ    ongsignal
-       B       runtime·onM(SB)
-
-ongsignal:
-       MOVW    fn+0(FP), R0
-       MOVW    R0, R7
-       MOVW    0(R0), R0
-       BL      (R0)
-       RET
-
-// func onM(fn func())
-TEXT runtime·onM(SB),NOSPLIT,$0-4
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB),NOSPLIT,$0-4
        MOVW    fn+0(FP), R0    // R0 = fn
        MOVW    g_m(g), R1      // R1 = m
 
+       MOVW    m_gsignal(R1), R2       // R2 = gsignal
+       CMP     g, R2
+       B.EQ    noswitch
+
        MOVW    m_g0(R1), R2    // R2 = g0
        CMP     g, R2
-       B.EQ    onm
+       B.EQ    noswitch
 
        MOVW    m_curg(R1), R3
        CMP     g, R3
-       B.EQ    oncurg
+       B.EQ    switch
 
-       // Not g0, not curg. Must be gsignal, but that's not allowed.
+       // Bad: g is not gsignal, not g0, not curg. What is it?
        // Hide call from linker nosplit analysis.
-       MOVW    $runtime·badonm(SB), R0
+       MOVW    $runtime·badsystemstack(SB), R0
        BL      (R0)
 
-oncurg:
+switch:
        // save our state in g->sched.  Pretend to
-       // be switchtoM if the G stack is scanned.
-       MOVW    $runtime·switchtoM(SB), R3
+       // be systemstack_switch if the G stack is scanned.
+       MOVW    $runtime·systemstack_switch(SB), R3
        ADD     $4, R3, R3 // get past push {lr}
        MOVW    R3, (g_sched+gobuf_pc)(g)
        MOVW    SP, (g_sched+gobuf_sp)(g)
@@ -249,7 +239,7 @@ oncurg:
        BL      setg<>(SB)
        MOVW    R5, R0
        MOVW    (g_sched+gobuf_sp)(R2), R3
-       // make it look like mstart called onM on g0, to stop traceback
+       // make it look like mstart called systemstack on g0, to stop traceback
        SUB     $4, R3, R3
        MOVW    $runtime·mstart(SB), R4
        MOVW    R4, 0(R3)
@@ -269,7 +259,7 @@ oncurg:
        MOVW    R3, (g_sched+gobuf_sp)(g)
        RET
 
-onm:
+noswitch:
        MOVW    R0, R7
        MOVW    0(R0), R0
        BL      (R0)
@@ -492,7 +482,7 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0
        MOVW    g_m(g), R8
        MOVW    m_g0(R8), R3
        CMP     R3, g
-       BEQ     asmcgocall_g0
+       BEQ     g0
        BL      gosave<>(SB)
        MOVW    R0, R5
        MOVW    R3, R0
@@ -501,7 +491,7 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0
        MOVW    (g_sched+gobuf_sp)(g), R13
 
        // Now on a scheduling stack (a pthread-created stack).
-asmcgocall_g0:
+g0:
        SUB     $24, R13
        BIC     $0x7, R13       // alignment for gcc ABI
        MOVW    R4, 20(R13) // save old g
@@ -564,7 +554,7 @@ TEXT        Â·cgocallback_gofunc(SB),NOSPLIT,$8-12
        // the same SP back to m->sched.sp. That seems redundant,
        // but if an unrecovered panic happens, unwindm will
        // restore the g->sched.sp from the stack location
-       // and then onM will try to use it. If we don't set it here,
+       // and then systemstack will try to use it. If we don't set it here,
        // that restored SP will be uninitialized (typically 0) and
        // will not be usable.
        MOVW    g_m(g), R8
@@ -751,13 +741,13 @@ TEXT runtime·memeq(SB),NOSPLIT,$-4-13
        ADD     R1, R3, R6
        MOVW    $1, R0
        MOVB    R0, ret+12(FP)
-_next2:
+loop:
        CMP     R1, R6
        RET.EQ
        MOVBU.P 1(R1), R4
        MOVBU.P 1(R2), R5
        CMP     R4, R5
-       BEQ     _next2
+       BEQ     loop
 
        MOVW    $0, R0
        MOVB    R0, ret+12(FP)
@@ -780,13 +770,13 @@ TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
        CMP     R2, R3
        RET.EQ
        ADD     R2, R0, R6
-_eqnext:
+loop:
        CMP     R2, R6
        RET.EQ
        MOVBU.P 1(R2), R4
        MOVBU.P 1(R3), R5
        CMP     R4, R5
-       BEQ     _eqnext
+       BEQ     loop
        MOVB    R7, v+16(FP)
        RET
 
@@ -801,26 +791,26 @@ TEXT bytes·Equal(SB),NOSPLIT,$0
        MOVW    b_len+16(FP), R3
        
        CMP     R1, R3          // unequal lengths are not equal
-       B.NE    _notequal
+       B.NE    notequal
 
        MOVW    a+0(FP), R0
        MOVW    b+12(FP), R2
        ADD     R0, R1          // end
 
-_byteseq_next:
+loop:
        CMP     R0, R1
-       B.EQ    _equal          // reached the end
+       B.EQ    equal           // reached the end
        MOVBU.P 1(R0), R4
        MOVBU.P 1(R2), R5
        CMP     R4, R5
-       B.EQ    _byteseq_next
+       B.EQ    loop
 
-_notequal:
+notequal:
        MOVW    $0, R0
        MOVBU   R0, ret+24(FP)
        RET
 
-_equal:
+equal:
        MOVW    $1, R0
        MOVBU   R0, ret+24(FP)
        RET
@@ -1326,3 +1316,7 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8
 TEXT runtime·goexit(SB),NOSPLIT,$-4-0
        MOVW    R0, R0  // NOP
        BL      runtime·goexit1(SB)    // does not return
+
+TEXT runtime·getg(SB),NOSPLIT,$-4-4
+       MOVW    g, ret+0(FP)
+       RET
diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s
new file mode 100644 (file)
index 0000000..3f2ab6d
--- /dev/null
@@ -0,0 +1,979 @@
+// Copyright 2014 The Go 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 power64 power64le
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
+       // initialize essential registers
+       BL      runtime·reginit(SB)
+
+       SUB     $24, R1
+       MOVW    R3, 8(R1) // argc
+       MOVD    R4, 16(R1) // argv
+
+       // create istack out of the given (operating system) stack.
+       // _cgo_init may update stackguard.
+       MOVD    $runtime·g0(SB), g
+       MOVD    $(-64*1024), R31
+       ADD     R31, R1, R3
+       MOVD    R3, g_stackguard0(g)
+       MOVD    R3, g_stackguard1(g)
+       MOVD    R3, (g_stack+stack_lo)(g)
+       MOVD    R1, (g_stack+stack_hi)(g)
+
+       // TODO: if there is a _cgo_init, call it.
+       // TODO: add TLS
+
+       // set the per-goroutine and per-mach "registers"
+       MOVD    $runtime·m0(SB), R3
+
+       // save m->g0 = g0
+       MOVD    g, m_g0(R3)
+       // save m0 to g0->m
+       MOVD    R3, g_m(g)
+
+       BL      runtime·check(SB)
+
+       // args are already prepared
+       BL      runtime·args(SB)
+       BL      runtime·osinit(SB)
+       BL      runtime·schedinit(SB)
+
+       // create a new goroutine to start program
+       MOVD    $runtime·main·f(SB), R3               // entry
+       MOVDU   R3, -8(R1)
+       MOVDU   R0, -8(R1)
+       MOVDU   R0, -8(R1)
+       BL      runtime·newproc(SB)
+       ADD     $24, R1
+
+       // start this M
+       BL      runtime·mstart(SB)
+
+       MOVD    R0, 1(R0)
+       RETURN
+
+DATA   runtime·main·f+0(SB)/8,$runtime·main(SB)
+GLOBL  runtime·main·f(SB),RODATA,$8
+
+TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
+       MOVD    R0, 2(R0) // TODO: TD
+       RETURN
+
+TEXT runtime·asminit(SB),NOSPLIT,$-8-0
+       RETURN
+
+TEXT runtime·reginit(SB),NOSPLIT,$-8-0
+       // set R0 to zero, it's expected by the toolchain
+       XOR R0, R0
+       // initialize essential FP registers
+       FMOVD   $4503601774854144.0, F27
+       FMOVD   $0.5, F29
+       FSUB    F29, F29, F28
+       FADD    F29, F29, F30
+       FADD    F30, F30, F31
+       RETURN
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), NOSPLIT, $-8-8
+       MOVD    buf+0(FP), R3
+       MOVD    R1, gobuf_sp(R3)
+       MOVD    LR, R31
+       MOVD    R31, gobuf_pc(R3)
+       MOVD    g, gobuf_g(R3)
+       MOVD    R0, gobuf_lr(R3)
+       MOVD    R0, gobuf_ret(R3)
+       MOVD    R0, gobuf_ctxt(R3)
+       RETURN
+
+// void gogo(Gobuf*)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), NOSPLIT, $-8-8
+       MOVD    buf+0(FP), R5
+       MOVD    gobuf_g(R5), g  // make sure g is not nil
+       MOVD    0(g), R4
+       MOVD    gobuf_sp(R5), R1
+       MOVD    gobuf_lr(R5), R31
+       MOVD    R31, LR
+       MOVD    gobuf_ret(R5), R3
+       MOVD    gobuf_ctxt(R5), R11
+       MOVD    R0, gobuf_sp(R5)
+       MOVD    R0, gobuf_ret(R5)
+       MOVD    R0, gobuf_lr(R5)
+       MOVD    R0, gobuf_ctxt(R5)
+       CMP     R0, R0 // set condition codes for == test, needed by stack split
+       MOVD    gobuf_pc(R5), R31
+       MOVD    R31, CTR
+       BR      (CTR)
+
+// void mcall(fn func(*g))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return.  It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), NOSPLIT, $-8-8
+       // Save caller state in g->sched
+       MOVD    R1, (g_sched+gobuf_sp)(g)
+       MOVD    LR, R31
+       MOVD    R31, (g_sched+gobuf_pc)(g)
+       MOVD    R0, (g_sched+gobuf_lr)(g)
+       MOVD    g, (g_sched+gobuf_g)(g)
+
+       // Switch to m->g0 & its stack, call fn.
+       MOVD    g, R3
+       MOVD    g_m(g), R8
+       MOVD    m_g0(R8), g
+       CMP     g, R3
+       BNE     2(PC)
+       BR      runtime·badmcall(SB)
+       MOVD    fn+0(FP), R11                   // context
+       MOVD    0(R11), R4                      // code pointer
+       MOVD    R4, CTR
+       MOVD    (g_sched+gobuf_sp)(g), R1       // sp = m->g0->sched.sp
+       MOVDU   R3, -8(R1)
+       MOVDU   R0, -8(R1)
+       BL      (CTR)
+       BR      runtime·badmcall2(SB)
+
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
+// of the G stack.  We need to distinguish the routine that
+// lives at the bottom of the G stack from the one that lives
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
+       UNDEF
+       BL      (LR)    // make sure this function is not leaf
+       RETURN
+
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-8
+       MOVD    fn+0(FP), R3    // R3 = fn
+       MOVD    R3, R11         // context
+       MOVD    g_m(g), R4      // R4 = m
+
+       MOVD    m_gsignal(R4), R5       // R5 = gsignal
+       CMP     g, R5
+       BEQ     noswitch
+
+       MOVD    m_g0(R4), R5    // R5 = g0
+       CMP     g, R5
+       BEQ     noswitch
+
+       MOVD    m_curg(R4), R6
+       CMP     g, R6
+       BEQ     switch
+
+       // Bad: g is not gsignal, not g0, not curg. What is it?
+       // Hide call from linker nosplit analysis.
+       MOVD    $runtime·badsystemstack(SB), R3
+       MOVD    R3, CTR
+       BL      (CTR)
+
+switch:
+       // save our state in g->sched.  Pretend to
+       // be systemstack_switch if the G stack is scanned.
+       MOVD    $runtime·systemstack_switch(SB), R6
+       ADD     $8, R6  // get past prologue
+       MOVD    R6, (g_sched+gobuf_pc)(g)
+       MOVD    R1, (g_sched+gobuf_sp)(g)
+       MOVD    R0, (g_sched+gobuf_lr)(g)
+       MOVD    g, (g_sched+gobuf_g)(g)
+
+       // switch to g0
+       MOVD    R5, g
+       MOVD    (g_sched+gobuf_sp)(g), R3
+       // make it look like mstart called systemstack on g0, to stop traceback
+       SUB     $8, R3
+       MOVD    $runtime·mstart(SB), R4
+       MOVD    R4, 0(R3)
+       MOVD    R3, R1
+
+       // call target function
+       MOVD    0(R11), R3      // code pointer
+       MOVD    R3, CTR
+       BL      (CTR)
+
+       // switch back to g
+       MOVD    g_m(g), R3
+       MOVD    m_curg(R3), g
+       MOVD    (g_sched+gobuf_sp)(g), R1
+       MOVD    R0, (g_sched+gobuf_sp)(g)
+       RETURN
+
+noswitch:
+       // already on m stack, just call directly
+       MOVD    0(R11), R3      // code pointer
+       MOVD    R3, CTR
+       BL      (CTR)
+       RETURN
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+// Caller has already loaded:
+// R3: framesize, R4: argsize, R5: LR
+//
+// The traceback routines see morestack on a g0 as being
+// the top of a stack (for example, morestack calling newstack
+// calling the scheduler calling newm calling gc), so we must
+// record an argument size. For that purpose, it has no arguments.
+TEXT runtime·morestack(SB),NOSPLIT,$-8-0
+       // Cannot grow scheduler stack (m->g0).
+       MOVD    g_m(g), R7
+       MOVD    m_g0(R7), R8
+       CMP     g, R8
+       BNE     2(PC)
+       BL      runtime·abort(SB)
+
+       // Cannot grow signal stack (m->gsignal).
+       MOVD    m_gsignal(R7), R8
+       CMP     g, R8
+       BNE     2(PC)
+       BL      runtime·abort(SB)
+
+       // Called from f.
+       // Set g->sched to context in f.
+       MOVD    R11, (g_sched+gobuf_ctxt)(g)
+       MOVD    R1, (g_sched+gobuf_sp)(g)
+       MOVD    LR, R8
+       MOVD    R8, (g_sched+gobuf_pc)(g)
+       MOVD    R5, (g_sched+gobuf_lr)(g)
+
+       // Called from f.
+       // Set m->morebuf to f's caller.
+       MOVD    R5, (m_morebuf+gobuf_pc)(R7)    // f's caller's PC
+       MOVD    R1, (m_morebuf+gobuf_sp)(R7)    // f's caller's SP
+       MOVD    g, (m_morebuf+gobuf_g)(R7)
+
+       // Call newstack on m->g0's stack.
+       MOVD    m_g0(R7), g
+       MOVD    (g_sched+gobuf_sp)(g), R1
+       BL      runtime·newstack(SB)
+
+       // Not reached, but make sure the return PC from the call to newstack
+       // is still in this function, and not the beginning of the next.
+       UNDEF
+
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
+       MOVD    R0, R11
+       BR      runtime·morestack(SB)
+
+// reflectcall: call a function with the given argument list
+// func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
+// we don't have variable-sized frames, so we use a small number
+// of constant-sized-frame functions to encode a few bits of size in the pc.
+// Caution: ugly multiline assembly macros in your future!
+
+#define DISPATCH(NAME,MAXSIZE)         \
+       MOVD    $MAXSIZE, R31;          \
+       CMP     R3, R31;                \
+       BGT     4(PC);                  \
+       MOVD    $NAME(SB), R31; \
+       MOVD    R31, CTR;               \
+       BR      (CTR)
+// Note: can't just "BR NAME(SB)" - bad inlining results.
+
+TEXT Â·reflectcall(SB), NOSPLIT, $-8-24
+       MOVWZ n+16(FP), R3
+       DISPATCH(runtime·call16, 16)
+       DISPATCH(runtime·call32, 32)
+       DISPATCH(runtime·call64, 64)
+       DISPATCH(runtime·call128, 128)
+       DISPATCH(runtime·call256, 256)
+       DISPATCH(runtime·call512, 512)
+       DISPATCH(runtime·call1024, 1024)
+       DISPATCH(runtime·call2048, 2048)
+       DISPATCH(runtime·call4096, 4096)
+       DISPATCH(runtime·call8192, 8192)
+       DISPATCH(runtime·call16384, 16384)
+       DISPATCH(runtime·call32768, 32768)
+       DISPATCH(runtime·call65536, 65536)
+       DISPATCH(runtime·call131072, 131072)
+       DISPATCH(runtime·call262144, 262144)
+       DISPATCH(runtime·call524288, 524288)
+       DISPATCH(runtime·call1048576, 1048576)
+       DISPATCH(runtime·call2097152, 2097152)
+       DISPATCH(runtime·call4194304, 4194304)
+       DISPATCH(runtime·call8388608, 8388608)
+       DISPATCH(runtime·call16777216, 16777216)
+       DISPATCH(runtime·call33554432, 33554432)
+       DISPATCH(runtime·call67108864, 67108864)
+       DISPATCH(runtime·call134217728, 134217728)
+       DISPATCH(runtime·call268435456, 268435456)
+       DISPATCH(runtime·call536870912, 536870912)
+       DISPATCH(runtime·call1073741824, 1073741824)
+       MOVD    $runtime·badreflectcall(SB), R31
+       MOVD    R31, CTR
+       BR      (CTR)
+
+#define CALLFN(NAME,MAXSIZE)                   \
+TEXT NAME(SB), WRAPPER, $MAXSIZE-24;           \
+       NO_LOCAL_POINTERS;                      \
+       /* copy arguments to stack */           \
+       MOVD    arg+8(FP), R3;                  \
+       MOVWZ   n+16(FP), R4;                   \
+       MOVD    R1, R5;                         \
+       ADD     $(8-1), R5;                     \
+       SUB     $1, R3;                         \
+       ADD     R5, R4;                         \
+       CMP     R5, R4;                         \
+       BEQ     4(PC);                          \
+       MOVBZU  1(R3), R6;                      \
+       MOVBZU  R6, 1(R5);                      \
+       BR      -4(PC);                         \
+       /* call function */                     \
+       MOVD    f+0(FP), R11;                   \
+       MOVD    (R11), R31;                     \
+       MOVD    R31, CTR;                       \
+       PCDATA  $PCDATA_StackMapIndex, $0;      \
+       BL      (CTR);                          \
+       /* copy return values back */           \
+       MOVD    arg+8(FP), R3;                  \
+       MOVWZ   n+16(FP), R4;                   \
+       MOVWZ   retoffset+20(FP), R6;           \
+       MOVD    R1, R5;                         \
+       ADD     R6, R5;                         \
+       ADD     R6, R3;                         \
+       SUB     R6, R4;                         \
+       ADD     $(8-1), R5;                     \
+       SUB     $1, R3;                         \
+       ADD     R5, R4;                         \
+       CMP     R5, R4;                         \
+       BEQ     4(PC);                          \
+       MOVBZU  1(R5), R6;                      \
+       MOVBZU  R6, 1(R3);                      \
+       BR      -4(PC);                         \
+       RETURN
+
+CALLFN(·call16, 16)
+CALLFN(·call32, 32)
+CALLFN(·call64, 64)
+CALLFN(·call128, 128)
+CALLFN(·call256, 256)
+CALLFN(·call512, 512)
+CALLFN(·call1024, 1024)
+CALLFN(·call2048, 2048)
+CALLFN(·call4096, 4096)
+CALLFN(·call8192, 8192)
+CALLFN(·call16384, 16384)
+CALLFN(·call32768, 32768)
+CALLFN(·call65536, 65536)
+CALLFN(·call131072, 131072)
+CALLFN(·call262144, 262144)
+CALLFN(·call524288, 524288)
+CALLFN(·call1048576, 1048576)
+CALLFN(·call2097152, 2097152)
+CALLFN(·call4194304, 4194304)
+CALLFN(·call8388608, 8388608)
+CALLFN(·call16777216, 16777216)
+CALLFN(·call33554432, 33554432)
+CALLFN(·call67108864, 67108864)
+CALLFN(·call134217728, 134217728)
+CALLFN(·call268435456, 268435456)
+CALLFN(·call536870912, 536870912)
+CALLFN(·call1073741824, 1073741824)
+
+// bool cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+//     if(*val == old){
+//             *val = new;
+//             return 1;
+//     } else
+//             return 0;
+TEXT runtime·cas(SB), NOSPLIT, $0-17
+       MOVD    ptr+0(FP), R3
+       MOVWZ   old+8(FP), R4
+       MOVWZ   new+12(FP), R5
+cas_again:
+       SYNC
+       LWAR    (R3), R6
+       CMPW    R6, R4
+       BNE     cas_fail
+       STWCCC  R5, (R3)
+       BNE     cas_again
+       MOVD    $1, R3
+       SYNC
+       ISYNC
+       MOVB    R3, ret+16(FP)
+       RETURN
+cas_fail:
+       MOVD    $0, R3
+       BR      -5(PC)
+
+// bool        runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+//     if(*val == *old){
+//             *val = new;
+//             return 1;
+//     } else {
+//             return 0;
+//     }
+TEXT runtime·cas64(SB), NOSPLIT, $0-25
+       MOVD    ptr+0(FP), R3
+       MOVD    old+8(FP), R4
+       MOVD    new+16(FP), R5
+cas64_again:
+       SYNC
+       LDAR    (R3), R6
+       CMP     R6, R4
+       BNE     cas64_fail
+       STDCCC  R5, (R3)
+       BNE     cas64_again
+       MOVD    $1, R3
+       SYNC
+       ISYNC
+       MOVB    R3, ret+24(FP)
+       RETURN
+cas64_fail:
+       MOVD    $0, R3
+       BR      -5(PC)
+
+TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
+       BR      runtime·cas64(SB)
+
+TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
+       BR      runtime·atomicload64(SB)
+
+TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
+       BR      runtime·atomicload64(SB)
+
+TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
+       BR      runtime·atomicstore64(SB)
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+//     if(*val == old){
+//             *val = new;
+//             return 1;
+//     } else
+//             return 0;
+TEXT runtime·casp1(SB), NOSPLIT, $0-25
+       BR runtime·cas64(SB)
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+//     *val += delta;
+//     return *val;
+TEXT runtime·xadd(SB), NOSPLIT, $0-20
+       MOVD    ptr+0(FP), R4
+       MOVW    delta+8(FP), R5
+       SYNC
+       LWAR    (R4), R3
+       ADD     R5, R3
+       STWCCC  R3, (R4)
+       BNE     -4(PC)
+       SYNC
+       ISYNC
+       MOVW    R3, ret+16(FP)
+       RETURN
+
+TEXT runtime·xadd64(SB), NOSPLIT, $0-24
+       MOVD    ptr+0(FP), R4
+       MOVD    delta+8(FP), R5
+       SYNC
+       LDAR    (R4), R3
+       ADD     R5, R3
+       STDCCC  R3, (R4)
+       BNE     -4(PC)
+       SYNC
+       ISYNC
+       MOVD    R3, ret+16(FP)
+       RETURN
+
+TEXT runtime·xchg(SB), NOSPLIT, $0-20
+       MOVD    ptr+0(FP), R4
+       MOVW    new+8(FP), R5
+       SYNC
+       LWAR    (R4), R3
+       STWCCC  R5, (R4)
+       BNE     -3(PC)
+       SYNC
+       ISYNC
+       MOVW    R3, ret+16(FP)
+       RETURN
+
+TEXT runtime·xchg64(SB), NOSPLIT, $0-24
+       MOVD    ptr+0(FP), R4
+       MOVD    new+8(FP), R5
+       SYNC
+       LDAR    (R4), R3
+       STDCCC  R5, (R4)
+       BNE     -3(PC)
+       SYNC
+       ISYNC
+       MOVD    R3, ret+16(FP)
+       RETURN
+
+TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
+       BR      runtime·xchg64(SB)
+
+TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
+       BR      runtime·xchg64(SB)
+
+TEXT runtime·procyield(SB),NOSPLIT,$0-0
+       RETURN
+
+TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
+       BR      runtime·atomicstore64(SB)
+
+TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
+       MOVD    ptr+0(FP), R3
+       MOVW    val+8(FP), R4
+       SYNC
+       MOVW    R4, 0(R3)
+       RETURN
+
+TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
+       MOVD    ptr+0(FP), R3
+       MOVD    val+8(FP), R4
+       SYNC
+       MOVD    R4, 0(R3)
+       RETURN
+
+// void        runtime·atomicor8(byte volatile*, byte);
+TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
+       MOVD    ptr+0(FP), R3
+       MOVBZ   val+8(FP), R4
+       // Align ptr down to 4 bytes so we can use 32-bit load/store.
+       // R5 = (R3 << 0) & ~3
+       RLDCR   $0, R3, $~3, R5
+       // Compute val shift.
+#ifdef GOARCH_power64
+       // Big endian.  ptr = ptr ^ 3
+       XOR     $3, R3
+#endif
+       // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
+       RLDC    $3, R3, $(3*8), R6
+       // Shift val for aligned ptr.  R4 = val << R6
+       SLD     R6, R4, R4
+
+atomicor8_again:
+       SYNC
+       LWAR    (R5), R6
+       OR      R4, R6
+       STWCCC  R6, (R5)
+       BNE     atomicor8_again
+       SYNC
+       ISYNC
+       RETURN
+
+// void jmpdefer(fv, sp);
+// called from deferreturn.
+// 1. grab stored LR for caller
+// 2. sub 4 bytes to get back to BL deferreturn
+// 3. BR to fn
+TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
+       MOVD    0(R1), R31
+       SUB     $4, R31
+       MOVD    R31, LR
+
+       MOVD    fv+0(FP), R11
+       MOVD    argp+8(FP), R1
+       SUB     $8, R1
+       MOVD    0(R11), R3
+       MOVD    R3, CTR
+       BR      (CTR)
+
+// Save state of caller into g->sched. Smashes R31.
+TEXT gosave<>(SB),NOSPLIT,$-8
+       MOVD    LR, R31
+       MOVD    R31, (g_sched+gobuf_pc)(g)
+       MOVD    R1, (g_sched+gobuf_sp)(g)
+       MOVD    R0, (g_sched+gobuf_lr)(g)
+       MOVD    R0, (g_sched+gobuf_ret)(g)
+       MOVD    R0, (g_sched+gobuf_ctxt)(g)
+       RETURN
+
+// 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 Â·asmcgocall(SB),NOSPLIT,$0-16
+       MOVD    R0, 21(R0)
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
+TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
+       MOVD    R0, 22(R0)
+
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.c for more details.
+TEXT Â·cgocallback_gofunc(SB),NOSPLIT,$8-24
+       MOVD    R0, 23(R0)
+
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB), NOSPLIT, $0-8
+       MOVD    R0, 24(R0)
+
+// void setg_gcc(G*); set g called from gcc.
+TEXT setg_gcc<>(SB),NOSPLIT,$0
+       MOVD    R0, 25(R0)
+
+TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-16
+       MOVD    0(R1), R3
+       MOVD    R3, ret+8(FP)
+       RETURN
+
+TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16
+       MOVD    0(R1), R3
+       MOVD    R3,ret+8(FP)
+       RETURN
+
+TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
+       MOVD    pc+8(FP), R3
+       MOVD    R3, 0(R1)               // set calling pc
+       RETURN
+
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
+       MOVD    argp+0(FP), R3
+       SUB     $8, R3
+       MOVD    R3, ret+8(FP)
+       RETURN
+
+// func gogetcallersp(p unsafe.Pointer) uintptr
+TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
+       MOVD    sp+0(FP), R3
+       SUB     $8, R3
+       MOVD    R3,ret+8(FP)
+       RETURN
+
+TEXT runtime·abort(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R0
+       UNDEF
+
+#define        TBRL    268
+#define        TBRU    269             /* Time base Upper/Lower */
+
+// int64 runtime·cputicks(void)
+TEXT runtime·cputicks(SB),NOSPLIT,$0-8
+       MOVW    SPR(TBRU), R4
+       MOVW    SPR(TBRL), R3
+       MOVW    SPR(TBRU), R5
+       CMPW    R4, R5
+       BNE     -4(PC)
+       SLD     $32, R5
+       OR      R5, R3
+       MOVD    R3, ret+0(FP)
+       RETURN
+
+// AES hashing not implemented for Power
+TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+
+TEXT runtime·memeq(SB),NOSPLIT,$-8-25
+       MOVD    a+0(FP), R3
+       MOVD    b+8(FP), R4
+       MOVD    size+16(FP), R5
+       SUB     $1, R3
+       SUB     $1, R4
+       ADD     R3, R5, R8
+loop:
+       CMP     R3, R8
+       BNE     test
+       MOVD    $1, R3
+       MOVB    R3, ret+24(FP)
+       RETURN
+test:
+       MOVBZU  1(R3), R6
+       MOVBZU  1(R4), R7
+       CMP     R6, R7
+       BEQ     loop
+
+       MOVB    R0, ret+24(FP)
+       RETURN
+
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
+       MOVD    s1len+8(FP), R4
+       MOVD    s2len+24(FP), R5
+       CMP     R4, R5
+       BNE     noteq
+
+       MOVD    s1str+0(FP), R3
+       MOVD    s2str+16(FP), R4
+       SUB     $1, R3
+       SUB     $1, R4
+       ADD     R3, R5, R8
+loop:
+       CMP     R3, R8
+       BNE     4(PC)
+       MOVD    $1, R3
+       MOVB    R3, ret+32(FP)
+       RETURN
+       MOVBZU  1(R3), R6
+       MOVBZU  1(R4), R7
+       CMP     R6, R7
+       BEQ     loop
+noteq:
+       MOVB    R0, ret+32(FP)
+       RETURN
+
+// TODO: share code with memeq?
+TEXT bytes·Equal(SB),NOSPLIT,$0-49
+       MOVD    a_len+8(FP), R3
+       MOVD    b_len+32(FP), R4
+
+       CMP     R3, R4          // unequal lengths are not equal
+       BNE     noteq
+
+       MOVD    a+0(FP), R5
+       MOVD    b+24(FP), R6
+       SUB     $1, R5
+       SUB     $1, R6
+       ADD     R5, R3          // end-1
+
+loop:
+       CMP     R5, R3
+       BEQ     equal           // reached the end
+       MOVBZU  1(R5), R4
+       MOVBZU  1(R6), R7
+       CMP     R4, R7
+       BEQ     loop
+
+noteq:
+       MOVBZ   R0, ret+48(FP)
+       RETURN
+
+equal:
+       MOVD    $1, R3
+       MOVBZ   R3, ret+48(FP)
+       RETURN
+
+TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
+       MOVD    s+0(FP), R3
+       MOVD    s_len+8(FP), R4
+       MOVBZ   c+24(FP), R5    // byte to find
+       MOVD    R3, R6          // store base for later
+       SUB     $1, R3
+       ADD     R3, R4          // end-1
+
+loop:
+       CMP     R3, R4
+       BEQ     notfound
+       MOVBZU  1(R3), R7
+       CMP     R7, R5
+       BNE     loop
+
+       SUB     R6, R3          // remove base
+       MOVD    R3, ret+32(FP)
+       RETURN
+
+notfound:
+       MOVD    $-1, R3
+       MOVD    R3, ret+32(FP)
+       RETURN
+
+TEXT strings·IndexByte(SB),NOSPLIT,$0
+       MOVD    p+0(FP), R3
+       MOVD    b_len+8(FP), R4
+       MOVBZ   c+16(FP), R5    // byte to find
+       MOVD    R3, R6          // store base for later
+       SUB     $1, R3
+       ADD     R3, R4          // end-1
+
+loop:
+       CMP     R3, R4
+       BEQ     notfound
+       MOVBZU  1(R3), R7
+       CMP     R7, R5
+       BNE     loop
+
+       SUB     R6, R3          // remove base
+       MOVD    R3, ret+24(FP)
+       RETURN
+
+notfound:
+       MOVD    $-1, R3
+       MOVD    R3, ret+24(FP)
+       RETURN
+
+
+// A Duff's device for zeroing memory.
+// The compiler jumps to computed addresses within
+// this routine to zero chunks of memory.  Do not
+// change this code without also changing the code
+// in ../../cmd/9g/ggen.c:/^clearfat.
+// R0: always zero
+// R3 (aka REGRT1): ptr to memory to be zeroed - 8
+// On return, R3 points to the last zeroed dword.
+TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       MOVDU   R0, 8(R3)
+       RETURN
+
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+       MOVD    g_m(g), R4
+       MOVWZ   m_fastrand(R4), R3
+       ADD     R3, R3
+       CMPW    R3, $0
+       BGE     2(PC)
+       XOR     $0x88888eef, R3
+       MOVW    R3, m_fastrand(R4)
+       MOVW    R3, ret+0(FP)
+       RETURN
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+       MOVW    $0, R3
+       RETURN
+
+// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
+// Must obey the gcc calling convention.
+TEXT _cgo_topofstack(SB),NOSPLIT,$0
+       MOVD    R0, 26(R0)
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-8-0
+       MOVD    R0, R0  // NOP
+       BL      runtime·goexit1(SB)    // does not return
+
+TEXT runtime·getg(SB),NOSPLIT,$-8-8
+       MOVD    g, ret+0(FP)
+       RETURN
diff --git a/src/runtime/atomic_386.c b/src/runtime/atomic_386.c
deleted file mode 100644 (file)
index 82d36f2..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "textflag.h"
-
-#pragma textflag NOSPLIT
-uint32
-runtime·atomicload(uint32 volatile* addr)
-{
-       return *addr;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·atomicloadp(void* volatile* addr)
-{
-       return *addr;
-}
-
-#pragma textflag NOSPLIT
-uint64
-runtime·xadd64(uint64 volatile* addr, int64 v)
-{
-       uint64 old;
-
-       do
-               old = *addr;
-       while(!runtime·cas64(addr, old, old+v));
-
-       return old+v;
-}
-
-#pragma textflag NOSPLIT
-uint64
-runtime·xchg64(uint64 volatile* addr, uint64 v)
-{
-       uint64 old;
-
-       do
-               old = *addr;
-       while(!runtime·cas64(addr, old, v));
-
-       return old;
-}
diff --git a/src/runtime/atomic_386.go b/src/runtime/atomic_386.go
new file mode 100644 (file)
index 0000000..5563432
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// The calls to nop are to keep these functions from being inlined.
+// If they are inlined we have no guarantee that later rewrites of the
+// code by optimizers will preserve the relative order of memory accesses.
+
+//go:nosplit
+func atomicload(ptr *uint32) uint32 {
+       nop()
+       return *ptr
+}
+
+//go:nosplit
+func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
+       nop()
+       return *(*unsafe.Pointer)(ptr)
+}
+
+//go:nosplit
+func xadd64(ptr *uint64, delta int64) uint64 {
+       for {
+               old := *ptr
+               if cas64(ptr, old, old+uint64(delta)) {
+                       return old + uint64(delta)
+               }
+       }
+}
+
+//go:nosplit
+func xchg64(ptr *uint64, new uint64) uint64 {
+       for {
+               old := *ptr
+               if cas64(ptr, old, new) {
+                       return old
+               }
+       }
+}
+
+//go:noescape
+func xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func xchg(ptr *uint32, new uint32) uint32
+
+// xchgp cannot have a go:noescape annotation, because
+// while ptr does not escape, new does. If new is marked as
+// not escaping, the compiler will make incorrect escape analysis
+// decisions about the value being xchg'ed.
+// Instead, make xchgp a wrapper around the actual atomic.
+// When calling the wrapper we mark ptr as noescape explicitly.
+
+//go:nosplit
+func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
+       return xchgp1(noescape(ptr), new)
+}
+
+func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func atomicload64(ptr *uint64) uint64
+
+//go:noescape
+func atomicor8(ptr *uint8, val uint8)
+
+//go:noescape
+func cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func atomicstore(ptr *uint32, val uint32)
+
+//go:noescape
+func atomicstore64(ptr *uint64, val uint64)
+
+// atomicstorep cannot have a go:noescape annotation.
+// See comment above for xchgp.
+
+//go:nosplit
+func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
+       atomicstorep1(noescape(ptr), new)
+}
+
+func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/atomic_amd64x.c b/src/runtime/atomic_amd64x.c
deleted file mode 100644 (file)
index 7be57ac..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build amd64 amd64p32
-
-#include "runtime.h"
-#include "textflag.h"
-
-#pragma textflag NOSPLIT
-uint32
-runtime·atomicload(uint32 volatile* addr)
-{
-       return *addr;
-}
-
-#pragma textflag NOSPLIT
-uint64
-runtime·atomicload64(uint64 volatile* addr)
-{
-       return *addr;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·atomicloadp(void* volatile* addr)
-{
-       return *addr;
-}
diff --git a/src/runtime/atomic_amd64x.go b/src/runtime/atomic_amd64x.go
new file mode 100644 (file)
index 0000000..f2dd584
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 amd64p32
+
+package runtime
+
+import "unsafe"
+
+// The calls to nop are to keep these functions from being inlined.
+// If they are inlined we have no guarantee that later rewrites of the
+// code by optimizers will preserve the relative order of memory accesses.
+
+//go:nosplit
+func atomicload(ptr *uint32) uint32 {
+       nop()
+       return *ptr
+}
+
+//go:nosplit
+func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
+       nop()
+       return *(*unsafe.Pointer)(ptr)
+}
+
+//go:nosplit
+func atomicload64(ptr *uint64) uint64 {
+       nop()
+       return *ptr
+}
+
+//go:noescape
+func xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func xchg64(ptr *uint64, new uint64) uint64
+
+// xchgp cannot have a go:noescape annotation, because
+// while ptr does not escape, new does. If new is marked as
+// not escaping, the compiler will make incorrect escape analysis
+// decisions about the value being xchg'ed.
+// Instead, make xchgp a wrapper around the actual atomic.
+// When calling the wrapper we mark ptr as noescape explicitly.
+
+//go:nosplit
+func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
+       return xchgp1(noescape(ptr), new)
+}
+
+func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func atomicor8(ptr *uint8, val uint8)
+
+//go:noescape
+func cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func atomicstore(ptr *uint32, val uint32)
+
+//go:noescape
+func atomicstore64(ptr *uint64, val uint64)
+
+// atomicstorep cannot have a go:noescape annotation.
+// See comment above for xchgp.
+
+//go:nosplit
+func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
+       atomicstorep1(noescape(ptr), new)
+}
+
+func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
index b1632cdd167fc08e2bc114cb5868e4e5ef3ab4d1..fd55a0aca85927609532f6d1e5963d376ca55c61 100644 (file)
@@ -85,7 +85,7 @@ func atomicstore(addr *uint32, v uint32) {
 //go:nosplit
 func cas64(addr *uint64, old, new uint64) bool {
        var ok bool
-       onM(func() {
+       systemstack(func() {
                lock(addrLock(addr))
                if *addr == old {
                        *addr = new
@@ -99,7 +99,7 @@ func cas64(addr *uint64, old, new uint64) bool {
 //go:nosplit
 func xadd64(addr *uint64, delta int64) uint64 {
        var r uint64
-       onM(func() {
+       systemstack(func() {
                lock(addrLock(addr))
                r = *addr + uint64(delta)
                *addr = r
@@ -111,7 +111,7 @@ func xadd64(addr *uint64, delta int64) uint64 {
 //go:nosplit
 func xchg64(addr *uint64, v uint64) uint64 {
        var r uint64
-       onM(func() {
+       systemstack(func() {
                lock(addrLock(addr))
                r = *addr
                *addr = v
@@ -123,7 +123,7 @@ func xchg64(addr *uint64, v uint64) uint64 {
 //go:nosplit
 func atomicload64(addr *uint64) uint64 {
        var r uint64
-       onM(func() {
+       systemstack(func() {
                lock(addrLock(addr))
                r = *addr
                unlock(addrLock(addr))
@@ -133,7 +133,7 @@ func atomicload64(addr *uint64) uint64 {
 
 //go:nosplit
 func atomicstore64(addr *uint64, v uint64) {
-       onM(func() {
+       systemstack(func() {
                lock(addrLock(addr))
                *addr = v
                unlock(addrLock(addr))
similarity index 52%
rename from src/runtime/atomic.go
rename to src/runtime/atomic_power64x.go
index 7e9d9b3aadc45bb897489360f03e7e73e7522767..a0dcf514b50b6b2dca2a7017925888054bcb8fc0 100644 (file)
@@ -1,8 +1,8 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
+// Copyright 2014 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !arm
+// +build power64 power64le
 
 package runtime
 
@@ -20,8 +20,19 @@ func xchg(ptr *uint32, new uint32) uint32
 //go:noescape
 func xchg64(ptr *uint64, new uint64) uint64
 
-//go:noescape
-func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
+// xchgp cannot have a go:noescape annotation, because
+// while ptr does not escape, new does. If new is marked as
+// not escaping, the compiler will make incorrect escape analysis
+// decisions about the value being xchg'ed.
+// Instead, make xchgp a wrapper around the actual atomic.
+// When calling the wrapper we mark ptr as noescape explicitly.
+
+//go:nosplit
+func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
+       return xchgp1(noescape(ptr), new)
+}
+
+func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
 
 //go:noescape
 func xchguintptr(ptr *uintptr, new uintptr) uintptr
@@ -47,5 +58,12 @@ func atomicstore(ptr *uint32, val uint32)
 //go:noescape
 func atomicstore64(ptr *uint64, val uint64)
 
-//go:noescape
-func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer)
+// atomicstorep cannot have a go:noescape annotation.
+// See comment above for xchgp.
+
+//go:nosplit
+func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
+       atomicstorep1(noescape(ptr), new)
+}
+
+func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/atomic_power64x.s b/src/runtime/atomic_power64x.s
new file mode 100644 (file)
index 0000000..e728717
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+// uint32 runtime·atomicload(uint32 volatile* addr)
+TEXT Â·atomicload(SB),NOSPLIT,$-8-12
+       MOVD    0(FP), R3
+       SYNC
+       MOVWZ   0(R3), R3
+       CMPW    R3, R3, CR7
+       BC      4, 30, 1(PC) // bne- cr7,0x4
+       ISYNC
+       MOVW    R3, ret+8(FP)
+       RETURN
+
+// uint64 runtime·atomicload64(uint64 volatile* addr)
+TEXT Â·atomicload64(SB),NOSPLIT,$-8-16
+       MOVD    0(FP), R3
+       SYNC
+       MOVD    0(R3), R3
+       CMP     R3, R3, CR7
+       BC      4, 30, 1(PC) // bne- cr7,0x4
+       ISYNC
+       MOVD    R3, ret+8(FP)
+       RETURN
+
+// void *runtime·atomicloadp(void *volatile *addr)
+TEXT Â·atomicloadp(SB),NOSPLIT,$-8-16
+       MOVD    0(FP), R3
+       SYNC
+       MOVD    0(R3), R3
+       CMP     R3, R3, CR7
+       BC      4, 30, 1(PC) // bne- cr7,0x4
+       ISYNC
+       MOVD    R3, ret+8(FP)
+       RETURN
diff --git a/src/runtime/cgo.go b/src/runtime/cgo.go
new file mode 100644 (file)
index 0000000..7e6b253
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//go:cgo_export_static main
+
+// Filled in by runtime/cgo when linked into binary.
+
+//go:linkname _cgo_init _cgo_init
+//go:linkname _cgo_malloc _cgo_malloc
+//go:linkname _cgo_free _cgo_free
+//go:linkname _cgo_thread_start _cgo_thread_start
+
+var (
+       _cgo_init         unsafe.Pointer
+       _cgo_malloc       unsafe.Pointer
+       _cgo_free         unsafe.Pointer
+       _cgo_thread_start unsafe.Pointer
+)
diff --git a/src/runtime/cgo/callbacks.c b/src/runtime/cgo/callbacks.c
deleted file mode 100644 (file)
index 282beee..0000000
+++ /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.
-
-#include "../runtime.h"
-#include "../cgocall.h"
-#include "textflag.h"
-
-// These utility functions are available to be called from code
-// compiled with gcc via crosscall2.
-
-// The declaration of crosscall2 is:
-//   void crosscall2(void (*fn)(void *, int), void *, int);
-// 
-// We need to export the symbol crosscall2 in order to support
-// callbacks from shared libraries. This applies regardless of
-// linking mode.
-#pragma cgo_export_static crosscall2
-#pragma cgo_export_dynamic crosscall2
-
-// Allocate memory.  This allocates the requested number of bytes in
-// memory controlled by the Go runtime.  The allocated memory will be
-// zeroed.  You are responsible for ensuring that the Go garbage
-// collector can see a pointer to the allocated memory for as long as
-// it is valid, e.g., by storing a pointer in a local variable in your
-// C function, or in memory allocated by the Go runtime.  If the only
-// pointers are in a C global variable or in memory allocated via
-// malloc, then the Go garbage collector may collect the memory.
-
-// Call like this in code compiled with gcc:
-//   struct { size_t len; void *ret; } a;
-//   a.len = /* number of bytes to allocate */;
-//   crosscall2(_cgo_allocate, &a, sizeof a);
-//   /* Here a.ret is a pointer to the allocated memory.  */
-
-void runtime·_cgo_allocate_internal(void);
-
-#pragma cgo_export_static _cgo_allocate
-#pragma cgo_export_dynamic _cgo_allocate
-#pragma textflag NOSPLIT
-void
-_cgo_allocate(void *a, int32 n)
-{
-       runtime·cgocallback((void(*)(void))runtime·_cgo_allocate_internal, a, n);
-}
-
-// Panic.  The argument is converted into a Go string.
-
-// Call like this in code compiled with gcc:
-//   struct { const char *p; } a;
-//   a.p = /* string to pass to panic */;
-//   crosscall2(_cgo_panic, &a, sizeof a);
-//   /* The function call will not return.  */
-
-void runtime·_cgo_panic_internal(void);
-
-#pragma cgo_export_static _cgo_panic
-#pragma cgo_export_dynamic _cgo_panic
-#pragma textflag NOSPLIT
-void
-_cgo_panic(void *a, int32 n)
-{
-       runtime·cgocallback((void(*)(void))runtime·_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;
-
-#pragma cgo_export_static _cgo_topofstack
-#pragma cgo_export_dynamic _cgo_topofstack
diff --git a/src/runtime/cgo/callbacks.go b/src/runtime/cgo/callbacks.go
new file mode 100644 (file)
index 0000000..1e8b590
--- /dev/null
@@ -0,0 +1,95 @@
+// 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 cgo
+
+import "unsafe"
+
+// These utility functions are available to be called from code
+// compiled with gcc via crosscall2.
+
+// cgocallback is defined in runtime
+//go:linkname _runtime_cgocallback runtime.cgocallback
+func _runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
+
+// The declaration of crosscall2 is:
+//   void crosscall2(void (*fn)(void *, int), void *, int);
+//
+// We need to export the symbol crosscall2 in order to support
+// callbacks from shared libraries. This applies regardless of
+// linking mode.
+//go:cgo_export_static crosscall2
+//go:cgo_export_dynamic crosscall2
+
+// Allocate memory.  This allocates the requested number of bytes in
+// memory controlled by the Go runtime.  The allocated memory will be
+// zeroed.  You are responsible for ensuring that the Go garbage
+// collector can see a pointer to the allocated memory for as long as
+// it is valid, e.g., by storing a pointer in a local variable in your
+// C function, or in memory allocated by the Go runtime.  If the only
+// pointers are in a C global variable or in memory allocated via
+// malloc, then the Go garbage collector may collect the memory.
+
+// Call like this in code compiled with gcc:
+//   struct { size_t len; void *ret; } a;
+//   a.len = /* number of bytes to allocate */;
+//   crosscall2(_cgo_allocate, &a, sizeof a);
+//   /* Here a.ret is a pointer to the allocated memory.  */
+
+//go:linkname _runtime_cgo_allocate_internal runtime._cgo_allocate_internal
+var _runtime_cgo_allocate_internal byte
+
+//go:linkname _cgo_allocate _cgo_allocate
+//go:cgo_export_static _cgo_allocate
+//go:cgo_export_dynamic _cgo_allocate
+//go:nosplit
+func _cgo_allocate(a unsafe.Pointer, n int32) {
+       _runtime_cgocallback(unsafe.Pointer(&_runtime_cgo_allocate_internal), a, uintptr(n))
+}
+
+// Panic.  The argument is converted into a Go string.
+
+// Call like this in code compiled with gcc:
+//   struct { const char *p; } a;
+//   a.p = /* string to pass to panic */;
+//   crosscall2(_cgo_panic, &a, sizeof a);
+//   /* The function call will not return.  */
+
+//go:linkname _runtime_cgo_panic_internal runtime._cgo_panic_internal
+var _runtime_cgo_panic_internal byte
+
+//go:linkname _cgo_panic _cgo_panic
+//go:cgo_export_static _cgo_panic
+//go:cgo_export_dynamic _cgo_panic
+//go:nosplit
+func _cgo_panic(a unsafe.Pointer, n int32) {
+       _runtime_cgocallback(unsafe.Pointer(&_runtime_cgo_panic_internal), a, uintptr(n))
+}
+
+//go:cgo_import_static x_cgo_init
+//go:linkname x_cgo_init x_cgo_init
+//go:linkname _cgo_init _cgo_init
+var x_cgo_init byte
+var _cgo_init = &x_cgo_init
+
+//go:cgo_import_static x_cgo_malloc
+//go:linkname x_cgo_malloc x_cgo_malloc
+//go:linkname _cgo_malloc _cgo_malloc
+var x_cgo_malloc byte
+var _cgo_malloc = &x_cgo_malloc
+
+//go:cgo_import_static x_cgo_free
+//go:linkname x_cgo_free x_cgo_free
+//go:linkname _cgo_free _cgo_free
+var x_cgo_free byte
+var _cgo_free = &x_cgo_free
+
+//go:cgo_import_static x_cgo_thread_start
+//go:linkname x_cgo_thread_start x_cgo_thread_start
+//go:linkname _cgo_thread_start _cgo_thread_start
+var x_cgo_thread_start byte
+var _cgo_thread_start = &x_cgo_thread_start
+
+//go:cgo_export_static _cgo_topofstack
+//go:cgo_export_dynamic _cgo_topofstack
similarity index 64%
rename from src/runtime/cgo/dragonfly.c
rename to src/runtime/cgo/dragonfly.go
index c233c8ba9a3c14e85b31f00aabbf4271150ae7fc..69d52b5b2f97a4945431acddd247a368c16a52f7 100644 (file)
@@ -4,16 +4,16 @@
 
 // +build dragonfly
 
-#include "textflag.h"
+package cgo
+
+import _ "unsafe" // for go:linkname
 
 // Supply environ and __progname, because we don't
 // link against the standard DragonFly crt0.o and the
 // libc dynamic library needs them.
 
-#pragma dataflag NOPTR
-char *environ[1];
-#pragma dataflag NOPTR
-char *__progname;
+//go:linkname _environ environ
+//go:linkname _progname __progname
 
-#pragma dynexport environ environ
-#pragma dynexport __progname __progname
+var _environ uintptr
+var _progname uintptr
similarity index 58%
rename from src/runtime/cgo/freebsd.c
rename to src/runtime/cgo/freebsd.go
index 4876b2abe47641df4ccd17ba9cf581b5414c341f..99cf3fbcaba7943c7aeaa1db30e83d114881b533 100644 (file)
@@ -4,16 +4,19 @@
 
 // +build freebsd
 
-#include "textflag.h"
+package cgo
+
+import _ "unsafe" // for go:linkname
 
 // Supply environ and __progname, because we don't
 // link against the standard FreeBSD crt0.o and the
 // libc dynamic library needs them.
 
-#pragma dataflag NOPTR
-char *environ[1];
-#pragma dataflag NOPTR
-char *__progname;
+//go:linkname _environ environ
+//go:linkname _progname __progname
+
+//go:cgo_export_dynamic environ
+//go:cgo_export_dynamic __progname
 
-#pragma dynexport environ environ
-#pragma dynexport __progname __progname
+var _environ uintptr
+var _progname uintptr
similarity index 71%
rename from src/runtime/cgo/iscgo.c
rename to src/runtime/cgo/iscgo.go
index 0907a19581006d33358775484641c3674334deca..61cba73d2221a6768d965fd64401977fbc6c14d3 100644 (file)
@@ -9,7 +9,12 @@
 // correctly, and sometimes they break.  This variable is a
 // backup: it depends only on old C style static linking rules.
 
-#include "../runtime.h"
+package cgo
 
-bool runtime·iscgo = 1;
-uint32 runtime·needextram = 1;  // create an extra M on first cgo call
+import _ "unsafe" // for go:linkname
+
+//go:linkname _iscgo runtime.iscgo
+var _iscgo bool = true
+
+//go:linkname _needextram runtime.needextram
+var _needextram uint32 = 1 // create an extra M on first cgo call
similarity index 64%
rename from src/runtime/cgo/netbsd.c
rename to src/runtime/cgo/netbsd.go
index 076cc87f12a7c70798c8f1fe0aca00630ac2d22a..ac6b18a93271eccaba2f9a0711ebfc28067da43d 100644 (file)
@@ -4,16 +4,16 @@
 
 // +build netbsd
 
-#include "textflag.h"
+package cgo
+
+import _ "unsafe" // for go:linkname
 
 // Supply environ and __progname, because we don't
 // link against the standard NetBSD crt0.o and the
 // libc dynamic library needs them.
 
-#pragma dataflag NOPTR
-char *environ[1];
-#pragma dataflag NOPTR
-char *__progname;
+//go:linkname _environ environ
+//go:linkname _progname __progname
 
-#pragma dynexport environ environ
-#pragma dynexport __progname __progname
+var _environ uintptr
+var _progname uintptr
similarity index 53%
rename from src/runtime/cgo/openbsd.c
rename to src/runtime/cgo/openbsd.go
index 476649544dff3cc27eb0111a0bec89940ed0872b..61af3a8e749694ee2807652978093cb1d5c0cc79 100644 (file)
@@ -4,24 +4,28 @@
 
 // +build openbsd
 
-#include "textflag.h"
+package cgo
+
+import _ "unsafe" // for go:linkname
 
 // Supply environ, __progname and __guard_local, because
 // we don't link against the standard OpenBSD crt0.o and
 // the libc dynamic library needs them.
 
-#pragma dataflag NOPTR
-char *environ[1];
-#pragma dataflag NOPTR
-char *__progname;
-long __guard_local;
+//go:linkname _environ environ
+//go:linkname _progname __progname
+//go:linkname _guard_local __guard_local
+
+var _environ uintptr
+var _progname uintptr
+var _guard_local uintptr
 
-#pragma dynexport environ environ
-#pragma dynexport __progname __progname
+//go:cgo_export_dynamic environ environ
+//go:cgo_export_dynamic __progname __progname
 
 // This is normally marked as hidden and placed in the
 // .openbsd.randomdata section.
-#pragma dynexport __guard_local __guard_local
+//go:cgo_export_dynamic __guard_local __guard_local
 
 // We override pthread_create to support PT_TLS.
-#pragma dynexport pthread_create pthread_create
+//go:cgo_export_dynamic pthread_create pthread_create
diff --git a/src/runtime/cgo/setenv.c b/src/runtime/cgo/setenv.c
deleted file mode 100644 (file)
index 76d88cb..0000000
+++ /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.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd
-
-#pragma cgo_import_static x_cgo_setenv
-#pragma cgo_import_static x_cgo_unsetenv
-
-void x_cgo_setenv(char**);
-void (*runtime·_cgo_setenv)(char**) = x_cgo_setenv;
-void x_cgo_unsetenv(char**);
-void (*runtime·_cgo_unsetenv)(char**) = x_cgo_unsetenv;
diff --git a/src/runtime/cgo/setenv.go b/src/runtime/cgo/setenv.go
new file mode 100644 (file)
index 0000000..97c8c6a
--- /dev/null
@@ -0,0 +1,21 @@
+// 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 dragonfly freebsd linux netbsd openbsd
+
+package cgo
+
+import _ "unsafe" // for go:linkname
+
+//go:cgo_import_static x_cgo_setenv
+//go:linkname x_cgo_setenv x_cgo_setenv
+//go:linkname _cgo_setenv runtime._cgo_setenv
+var x_cgo_setenv byte
+var _cgo_setenv = &x_cgo_setenv
+
+//go:cgo_import_static x_cgo_unsetenv
+//go:linkname x_cgo_unsetenv x_cgo_unsetenv
+//go:linkname _cgo_unsetenv runtime._cgo_unsetenv
+var x_cgo_unsetenv byte
+var _cgo_unsetenv = &x_cgo_unsetenv
index 7fd91469eb17038f2f1ff90086afbed29d508c1f..258cabfc8321cfb91735ee913f255cc362d84028 100644 (file)
@@ -103,7 +103,7 @@ func cgocall_errno(fn, arg unsafe.Pointer) int32 {
 
        // Create an extra M for callbacks on threads not created by Go on first cgo call.
        if needextram == 1 && cas(&needextram, 1, 0) {
-               onM(newextram)
+               systemstack(newextram)
        }
 
        /*
@@ -127,9 +127,9 @@ func cgocall_errno(fn, arg unsafe.Pointer) int32 {
         * so it is safe to call while "in a system call", outside
         * the $GOMAXPROCS accounting.
         */
-       entersyscall()
+       entersyscall(0)
        errno := asmcgocall_errno(fn, arg)
-       exitsyscall()
+       exitsyscall(0)
 
        return errno
 }
@@ -153,17 +153,13 @@ func endcgo(mp *m) {
 
 // Helper functions for cgo code.
 
-// Filled by schedinit from corresponding C variables,
-// which are in turn filled in by dynamic linker when Cgo is available.
-var cgoMalloc, cgoFree unsafe.Pointer
-
 func cmalloc(n uintptr) unsafe.Pointer {
        var args struct {
                n   uint64
                ret unsafe.Pointer
        }
        args.n = uint64(n)
-       cgocall(cgoMalloc, unsafe.Pointer(&args))
+       cgocall(_cgo_malloc, unsafe.Pointer(&args))
        if args.ret == nil {
                gothrow("C malloc failed")
        }
@@ -171,7 +167,7 @@ func cmalloc(n uintptr) unsafe.Pointer {
 }
 
 func cfree(p unsafe.Pointer) {
-       cgocall(cgoFree, p)
+       cgocall(_cgo_free, p)
 }
 
 // Call from C back to Go.
@@ -189,17 +185,17 @@ func cgocallbackg() {
        // save syscall* and let reentersyscall restore them.
        savedsp := unsafe.Pointer(gp.syscallsp)
        savedpc := gp.syscallpc
-       exitsyscall() // coming out of cgo call
+       exitsyscall(0) // coming out of cgo call
        cgocallbackg1()
        // going back to cgo call
-       reentersyscall(savedpc, savedsp)
+       reentersyscall(savedpc, uintptr(savedsp))
 }
 
 func cgocallbackg1() {
        gp := getg()
        if gp.m.needextram {
                gp.m.needextram = false
-               onM(newextram)
+               systemstack(newextram)
        }
 
        // Add entry to defer stack in case of panic.
index 0eb87df74f759dc81ce3ab804f152754de541adc..330422ad0908d6ab5391e8dd0e8e83ca4a94539b 100644 (file)
@@ -26,7 +26,7 @@ func makechan(t *chantype, size int64) *hchan {
        if hchanSize%maxAlign != 0 || elem.align > maxAlign {
                gothrow("makechan: bad alignment")
        }
-       if size < 0 || int64(uintptr(size)) != size || (elem.size > 0 && uintptr(size) > (maxmem-hchanSize)/uintptr(elem.size)) {
+       if size < 0 || int64(uintptr(size)) != size || (elem.size > 0 && uintptr(size) > (_MaxMem-hchanSize)/uintptr(elem.size)) {
                panic("makechan: size out of range")
        }
 
diff --git a/src/runtime/chan.h b/src/runtime/chan.h
deleted file mode 100644 (file)
index c34ff15..0000000
+++ /dev/null
@@ -1,68 +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.
-
-#define        MAXALIGN        8
-
-typedef        struct  WaitQ   WaitQ;
-typedef        struct  Select  Select;
-typedef        struct  Scase   Scase;
-
-struct WaitQ
-{
-       SudoG*  first;
-       SudoG*  last;
-};
-
-struct Hchan
-{
-       uintgo  qcount;                 // total data in the q
-       uintgo  dataqsiz;               // size of the circular q
-       byte*   buf;
-       uint16  elemsize;
-       uint32  closed;
-       Type*   elemtype;               // element type
-       uintgo  sendx;                  // send index
-       uintgo  recvx;                  // receive index
-       WaitQ   recvq;                  // list of recv waiters
-       WaitQ   sendq;                  // list of send waiters
-       Mutex   lock;
-};
-
-// Buffer follows Hchan immediately in memory.
-// chanbuf(c, i) is pointer to the i'th slot in the buffer.
-#define chanbuf(c, i) ((byte*)((c)->buf)+(uintptr)(c)->elemsize*(i))
-
-enum
-{
-       debug = 0,
-
-       // Scase.kind
-       CaseRecv,
-       CaseSend,
-       CaseDefault,
-};
-
-// Known to compiler.
-// Changes here must also be made in src/cmd/gc/select.c's selecttype.
-struct Scase
-{
-       void*   elem;                   // data element
-       Hchan*  chan;                   // chan
-       uintptr pc;                     // return pc
-       uint16  kind;
-       uint16  so;                     // vararg of selected bool
-       bool*   receivedp;              // pointer to received bool (recv2)
-       int64   releasetime;
-};
-
-// Known to compiler.
-// Changes here must also be made in src/cmd/gc/select.c's selecttype.
-struct Select
-{
-       uint16  tcase;                  // total count of scase[]
-       uint16  ncase;                  // currently filled scase[]
-       uint16* pollorder;              // case poll order
-       Hchan** lockorder;              // channel lock order
-       Scase   scase[1];               // one per case (in order of appearance)
-};
diff --git a/src/runtime/chan1.go b/src/runtime/chan1.go
new file mode 100644 (file)
index 0000000..000775b
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//#define      MAXALIGN        8
+
+type waitq struct {
+       first *sudog
+       last  *sudog
+}
+
+type hchan struct {
+       qcount   uint // total data in the q
+       dataqsiz uint // size of the circular q
+       buf      *byte
+       elemsize uint16
+       closed   uint32
+       elemtype *_type // element type
+       sendx    uint   // send index
+       recvx    uint   // receive index
+       recvq    waitq  // list of recv waiters
+       sendq    waitq  // list of send waiters
+       lock     mutex
+}
+
+// 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)->buf)+(uintptr)(c)->elemsize*(i))
+
+const (
+       // scase.kind
+       _CaseRecv = iota
+       _CaseSend
+       _CaseDefault
+)
+
+// Known to compiler.
+// Changes here must also be made in src/cmd/gc/select.c's selecttype.
+type scase struct {
+       elem        unsafe.Pointer // data element
+       _chan       *hchan         // chan
+       pc          uintptr        // return pc
+       kind        uint16
+       so          uint16 // vararg of selected bool
+       receivedp   *bool  // pointer to received bool (recv2)
+       releasetime int64
+}
+
+// Known to compiler.
+// Changes here must also be made in src/cmd/gc/select.c's selecttype.
+type _select struct {
+       tcase     uint16   // total count of scase[]
+       ncase     uint16   // currently filled scase[]
+       pollorder *uint16  // case poll order
+       lockorder **hchan  // channel lock order
+       scase     [1]scase // one per case (in order of appearance)
+}
index ec50f8947090a22a26bd822bae8b53e31c0d549f..73f1161a50de5d91c257fbb1ce2f24a0ef5b7f73 100644 (file)
@@ -4,28 +4,47 @@
 
 package runtime
 
+func isposinf(f float64) bool { return f > maxFloat64 }
+func isneginf(f float64) bool { return f < -maxFloat64 }
+func isnan(f float64) bool    { return f != f }
+
+func nan() float64 {
+       var f float64 = 0
+       return f / f
+}
+
+func posinf() float64 {
+       var f float64 = maxFloat64
+       return f * f
+}
+
+func neginf() float64 {
+       var f float64 = maxFloat64
+       return -f * f
+}
+
 func complex128div(n complex128, d complex128) complex128 {
        // Special cases as in C99.
-       ninf := real(n) == posinf || real(n) == neginf ||
-               imag(n) == posinf || imag(n) == neginf
-       dinf := real(d) == posinf || real(d) == neginf ||
-               imag(d) == posinf || imag(d) == neginf
+       ninf := isposinf(real(n)) || isneginf(real(n)) ||
+               isposinf(imag(n)) || isneginf(imag(n))
+       dinf := isposinf(real(d)) || isneginf(real(d)) ||
+               isposinf(imag(d)) || isneginf(imag(d))
 
-       nnan := !ninf && (real(n) != real(n) || imag(n) != imag(n))
-       dnan := !dinf && (real(d) != real(d) || imag(d) != imag(d))
+       nnan := !ninf && (isnan(real(n)) || isnan(imag(n)))
+       dnan := !dinf && (isnan(real(d)) || isnan(imag(d)))
 
        switch {
        case nnan || dnan:
-               return complex(nan, nan)
+               return complex(nan(), nan())
        case ninf && !dinf:
-               return complex(posinf, posinf)
+               return complex(posinf(), posinf())
        case !ninf && dinf:
                return complex(0, 0)
        case real(d) == 0 && imag(d) == 0:
                if real(n) == 0 && imag(n) == 0 {
-                       return complex(nan, nan)
+                       return complex(nan(), nan())
                } else {
-                       return complex(posinf, posinf)
+                       return complex(posinf(), posinf())
                }
        default:
                // Standard complex arithmetic, factored to avoid unnecessary overflow.
index 8b1c1c632752993ecb400f5312fc99fa94067fd3..d56678e21f603e760283f968d77be1aa583ad118 100644 (file)
@@ -101,12 +101,10 @@ var (
        eod = [3]uintptr{0, 1, 0}
 )
 
-func setcpuprofilerate_m() // proc.c
-
 func setcpuprofilerate(hz int32) {
-       g := getg()
-       g.m.scalararg[0] = uintptr(hz)
-       onM(setcpuprofilerate_m)
+       systemstack(func() {
+               setcpuprofilerate_m(hz)
+       })
 }
 
 // lostProfileData is a no-op function used in profiles
diff --git a/src/runtime/cputicks.go b/src/runtime/cputicks.go
new file mode 100644 (file)
index 0000000..e0593d5
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !arm
+
+package runtime
+
+// careful: cputicks is not guaranteed to be monotonic!  In particular, we have
+// noticed drift between cpus on certain os/arch combinations.  See issue 8976.
+func cputicks() int64
index 4414dd55d2380341efb147daca7de4dff4da9dfe..105b79cfefebc3d3f4cad554a76139d9ca1e49b9 100644 (file)
@@ -6,18 +6,6 @@ package runtime
 
 import "unsafe"
 
-// Breakpoint executes a breakpoint trap.
-func Breakpoint()
-
-// LockOSThread wires the calling goroutine to its current operating system thread.
-// Until the calling goroutine exits or calls UnlockOSThread, it will always
-// execute in that thread, and no other goroutine can.
-func LockOSThread()
-
-// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
-// If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
-func UnlockOSThread()
-
 // GOMAXPROCS sets the maximum number of CPUs that can be executing
 // simultaneously and returns the previous setting.  If n < 1, it does not
 // change the current setting.
@@ -37,14 +25,14 @@ func GOMAXPROCS(n int) int {
        semacquire(&worldsema, false)
        gp := getg()
        gp.m.gcing = 1
-       onM(stoptheworld)
+       systemstack(stoptheworld)
 
        // newprocs will be processed by starttheworld
        newprocs = int32(n)
 
        gp.m.gcing = 0
        semrelease(&worldsema)
-       onM(starttheworld)
+       systemstack(starttheworld)
        return ret
 }
 
@@ -66,5 +54,3 @@ func NumCgoCall() int64 {
 func NumGoroutine() int {
        return int(gcount())
 }
-
-func gcount() int32
index d56274f2dc7576e117b824f4f26cf7b9a1aa602f..1e883b72c0d3c25e9e0a90d6be8728ef762528c6 100644 (file)
@@ -7,6 +7,12 @@
 #ifdef GOARCH_arm
 #define JMP B
 #endif
+#ifdef GOARCH_power64
+#define JMP BR
+#endif
+#ifdef GOARCH_power64le
+#define JMP BR
+#endif
 
 TEXT Â·setMaxStack(SB),NOSPLIT,$0-0
   JMP runtime·setMaxStack(SB)
diff --git a/src/runtime/defs.c b/src/runtime/defs.c
deleted file mode 100644 (file)
index b0a9b20..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file is compiled by cmd/dist to obtain debug information
-// about the given header files.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "type.h"
-#include "race.h"
-#include "chan.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
index 392cc4ab58e6aafaf51b09eaf68f7dbd4ae54c96..87c6e02a41c7be5d969e7276ae62e0d226aaf3bd 100644 (file)
@@ -15,12 +15,14 @@ package runtime
 /*
 #include <ucontext.h>
 #include <fcntl.h>
+#include <asm/signal.h>
 */
 import "C"
 
 const (
-       O_RDONLY  = C.O_RDONLY
-       O_CLOEXEC = C.O_CLOEXEC
+       O_RDONLY    = C.O_RDONLY
+       O_CLOEXEC   = C.O_CLOEXEC
+       SA_RESTORER = C.SA_RESTORER
 )
 
 type Usigset C.__sigset_t
diff --git a/src/runtime/defs1_netbsd_386.go b/src/runtime/defs1_netbsd_386.go
new file mode 100644 (file)
index 0000000..e39fd04
--- /dev/null
@@ -0,0 +1,171 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_netbsd.go defs_netbsd_386.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = 0x0
+       _EVFILT_WRITE = 0x1
+)
+
+type sigaltstackt struct {
+       ss_sp    *byte
+       ss_size  uint32
+       ss_flags int32
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type siginfo struct {
+       _signo  int32
+       _code   int32
+       _errno  int32
+       _reason [20]byte
+}
+
+type stackt struct {
+       ss_sp    *byte
+       ss_size  uint32
+       ss_flags int32
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int32
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int32
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type mcontextt struct {
+       __gregs     [19]int32
+       __fpregs    [644]byte
+       _mc_tlsbase int32
+}
+
+type ucontextt struct {
+       uc_flags    uint32
+       uc_link     *ucontextt
+       uc_sigmask  sigset
+       uc_stack    stackt
+       uc_mcontext mcontextt
+       __uc_pad    [4]int32
+}
+
+type keventt struct {
+       ident  uint32
+       filter uint32
+       flags  uint32
+       fflags uint32
+       data   int64
+       udata  *byte
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_netbsd.go defs_netbsd_386.go
+
+const (
+       _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/runtime/defs1_netbsd_amd64.go b/src/runtime/defs1_netbsd_amd64.go
new file mode 100644 (file)
index 0000000..cca701e
--- /dev/null
@@ -0,0 +1,183 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = 0x0
+       _EVFILT_WRITE = 0x1
+)
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_size   uint64
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type siginfo struct {
+       _signo  int32
+       _code   int32
+       _errno  int32
+       _pad    int32
+       _reason [24]byte
+}
+
+type stackt struct {
+       ss_sp     *byte
+       ss_size   uint64
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+type timeval struct {
+       tv_sec    int64
+       tv_usec   int32
+       pad_cgo_0 [4]byte
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type mcontextt struct {
+       __gregs     [26]uint64
+       _mc_tlsbase uint64
+       __fpregs    [512]int8
+}
+
+type ucontextt struct {
+       uc_flags    uint32
+       pad_cgo_0   [4]byte
+       uc_link     *ucontextt
+       uc_sigmask  sigset
+       uc_stack    stackt
+       uc_mcontext mcontextt
+}
+
+type keventt struct {
+       ident     uint64
+       filter    uint32
+       flags     uint32
+       fflags    uint32
+       pad_cgo_0 [4]byte
+       data      int64
+       udata     *byte
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go
+
+const (
+       _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/runtime/defs1_netbsd_arm.go b/src/runtime/defs1_netbsd_arm.go
new file mode 100644 (file)
index 0000000..54ddf38
--- /dev/null
@@ -0,0 +1,170 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = 0x0
+       _EVFILT_WRITE = 0x1
+)
+
+type sigaltstackt struct {
+       ss_sp    *byte
+       ss_size  uint32
+       ss_flags int32
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type siginfo struct {
+       _signo  int32
+       _code   int32
+       _errno  int32
+       _reason [20]byte
+}
+
+type stackt struct {
+       ss_sp    *byte
+       ss_size  uint32
+       ss_flags int32
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int32
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int32
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type mcontextt struct {
+       __gregs [17]uint32
+       __fpu   [4 + 8*32 + 4]byte // EABI
+       // __fpu [4+4*33+4]byte // not EABI
+       _mc_tlsbase uint32
+}
+
+type ucontextt struct {
+       uc_flags    uint32
+       uc_link     *ucontextt
+       uc_sigmask  sigset
+       uc_stack    stackt
+       uc_mcontext mcontextt
+       __uc_pad    [2]int32
+}
+
+type keventt struct {
+       ident  uint32
+       filter uint32
+       flags  uint32
+       fflags uint32
+       data   int64
+       udata  *byte
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go
+
+const (
+       _REG_R0   = 0x0
+       _REG_R1   = 0x1
+       _REG_R2   = 0x2
+       _REG_R3   = 0x3
+       _REG_R4   = 0x4
+       _REG_R5   = 0x5
+       _REG_R6   = 0x6
+       _REG_R7   = 0x7
+       _REG_R8   = 0x8
+       _REG_R9   = 0x9
+       _REG_R10  = 0xa
+       _REG_R11  = 0xb
+       _REG_R12  = 0xc
+       _REG_R13  = 0xd
+       _REG_R14  = 0xe
+       _REG_R15  = 0xf
+       _REG_CPSR = 0x10
+)
diff --git a/src/runtime/defs1_solaris_amd64.go b/src/runtime/defs1_solaris_amd64.go
new file mode 100644 (file)
index 0000000..3bb6f69
--- /dev/null
@@ -0,0 +1,245 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_solaris.go defs_solaris_amd64.go
+
+package runtime
+
+const (
+       _EINTR       = 0x4
+       _EBADF       = 0x9
+       _EFAULT      = 0xe
+       _EAGAIN      = 0xb
+       _ETIMEDOUT   = 0x91
+       _EWOULDBLOCK = 0xb
+       _EINPROGRESS = 0x96
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x100
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_FREE = 0x5
+
+       _SA_SIGINFO = 0x8
+       _SA_RESTART = 0x4
+       _SA_ONSTACK = 0x1
+
+       _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    = 0x15
+       _SIGSTOP   = 0x17
+       _SIGTSTP   = 0x18
+       _SIGCONT   = 0x19
+       _SIGCHLD   = 0x12
+       _SIGTTIN   = 0x1a
+       _SIGTTOU   = 0x1b
+       _SIGIO     = 0x16
+       _SIGXCPU   = 0x1e
+       _SIGXFSZ   = 0x1f
+       _SIGVTALRM = 0x1c
+       _SIGPROF   = 0x1d
+       _SIGWINCH  = 0x14
+       _SIGUSR1   = 0x10
+       _SIGUSR2   = 0x11
+
+       _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
+
+       __SC_NPROCESSORS_ONLN = 0xf
+
+       _PTHREAD_CREATE_DETACHED = 0x40
+
+       _FORK_NOSIGCHLD = 0x1
+       _FORK_WAITPID   = 0x2
+
+       _MAXHOSTNAMELEN = 0x100
+
+       _O_NONBLOCK = 0x80
+       _FD_CLOEXEC = 0x1
+       _F_GETFL    = 0x3
+       _F_SETFL    = 0x4
+       _F_SETFD    = 0x2
+
+       _POLLIN  = 0x1
+       _POLLOUT = 0x4
+       _POLLHUP = 0x10
+       _POLLERR = 0x8
+
+       _PORT_SOURCE_FD = 0x4
+)
+
+type semt struct {
+       sem_count uint32
+       sem_type  uint16
+       sem_magic uint16
+       sem_pad1  [3]uint64
+       sem_pad2  [2]uint64
+}
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_size   uint64
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type sigset struct {
+       __sigbits [4]uint32
+}
+
+type stackt struct {
+       ss_sp     *byte
+       ss_size   uint64
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type siginfo struct {
+       si_signo int32
+       si_code  int32
+       si_errno int32
+       si_pad   int32
+       __data   [240]byte
+}
+
+type sigactiont struct {
+       sa_flags  int32
+       pad_cgo_0 [4]byte
+       _funcptr  [8]byte
+       sa_mask   sigset
+}
+
+type fpregset struct {
+       fp_reg_set [528]byte
+}
+
+type mcontext struct {
+       gregs  [28]int64
+       fpregs fpregset
+}
+
+type ucontext struct {
+       uc_flags    uint64
+       uc_link     *ucontext
+       uc_sigmask  sigset
+       uc_stack    stackt
+       pad_cgo_0   [8]byte
+       uc_mcontext mcontext
+       uc_filler   [5]int64
+       pad_cgo_1   [8]byte
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type portevent struct {
+       portev_events int32
+       portev_source uint16
+       portev_pad    uint16
+       portev_object uint64
+       portev_user   *byte
+}
+
+type pthread uint32
+type pthreadattr struct {
+       __pthread_attrp *byte
+}
+
+type stat struct {
+       st_dev     uint64
+       st_ino     uint64
+       st_mode    uint32
+       st_nlink   uint32
+       st_uid     uint32
+       st_gid     uint32
+       st_rdev    uint64
+       st_size    int64
+       st_atim    timespec
+       st_mtim    timespec
+       st_ctim    timespec
+       st_blksize int32
+       pad_cgo_0  [4]byte
+       st_blocks  int64
+       st_fstype  [16]int8
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_solaris.go defs_solaris_amd64.go
+
+const (
+       _REG_RDI    = 0x8
+       _REG_RSI    = 0x9
+       _REG_RDX    = 0xc
+       _REG_RCX    = 0xd
+       _REG_R8     = 0x7
+       _REG_R9     = 0x6
+       _REG_R10    = 0x5
+       _REG_R11    = 0x4
+       _REG_R12    = 0x3
+       _REG_R13    = 0x2
+       _REG_R14    = 0x1
+       _REG_R15    = 0x0
+       _REG_RBP    = 0xa
+       _REG_RBX    = 0xb
+       _REG_RAX    = 0xe
+       _REG_GS     = 0x17
+       _REG_FS     = 0x16
+       _REG_ES     = 0x18
+       _REG_DS     = 0x19
+       _REG_TRAPNO = 0xf
+       _REG_ERR    = 0x10
+       _REG_RIP    = 0x11
+       _REG_CS     = 0x12
+       _REG_RFLAGS = 0x13
+       _REG_RSP    = 0x14
+       _REG_SS     = 0x15
+)
diff --git a/src/runtime/defs3_linux.go b/src/runtime/defs3_linux.go
new file mode 100644 (file)
index 0000000..3551a4f
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo -cdefs
+
+GOARCH=power64 cgo -cdefs defs_linux.go defs3_linux.go > defs_linux_power64.h
+*/
+
+package runtime
+
+/*
+#define size_t __kernel_size_t
+#define sigset_t __sigset_t // rename the sigset_t here otherwise cgo will complain about "inconsistent definitions for C.sigset_t"
+#define        _SYS_TYPES_H    // avoid inclusion of sys/types.h
+#include <asm/ucontext.h>
+#include <asm-generic/fcntl.h>
+*/
+import "C"
+
+const (
+       O_RDONLY    = C.O_RDONLY
+       O_CLOEXEC   = C.O_CLOEXEC
+       SA_RESTORER = 0 // unused
+)
+
+type Usigset C.__sigset_t
+
+// types used in sigcontext
+type Ptregs C.struct_pt_regs
+type Gregset C.elf_gregset_t
+type FPregset C.elf_fpregset_t
+type Vreg C.elf_vrreg_t
+
+type SigaltstackT C.struct_sigaltstack
+
+// PPC64 uses sigcontext in place of mcontext in ucontext.
+// see http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/powerpc/include/uapi/asm/ucontext.h
+type Sigcontext C.struct_sigcontext
+type Ucontext C.struct_ucontext
diff --git a/src/runtime/defs_android_arm.h b/src/runtime/defs_android_arm.h
deleted file mode 100644 (file)
index 3611b3a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// TODO: Generate using cgo like defs_linux_{386,amd64}.h
-
-#include "defs_linux_arm.h"
diff --git a/src/runtime/defs_darwin_386.go b/src/runtime/defs_darwin_386.go
new file mode 100644 (file)
index 0000000..cf4812f
--- /dev/null
@@ -0,0 +1,382 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_darwin.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x1000
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+       _MADV_FREE     = 0x5
+
+       _MACH_MSG_TYPE_MOVE_RECEIVE   = 0x10
+       _MACH_MSG_TYPE_MOVE_SEND      = 0x11
+       _MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12
+       _MACH_MSG_TYPE_COPY_SEND      = 0x13
+       _MACH_MSG_TYPE_MAKE_SEND      = 0x14
+       _MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15
+       _MACH_MSG_TYPE_COPY_RECEIVE   = 0x16
+
+       _MACH_MSG_PORT_DESCRIPTOR         = 0x0
+       _MACH_MSG_OOL_DESCRIPTOR          = 0x1
+       _MACH_MSG_OOL_PORTS_DESCRIPTOR    = 0x2
+       _MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3
+
+       _MACH_MSGH_BITS_COMPLEX = 0x80000000
+
+       _MACH_SEND_MSG  = 0x1
+       _MACH_RCV_MSG   = 0x2
+       _MACH_RCV_LARGE = 0x4
+
+       _MACH_SEND_TIMEOUT   = 0x10
+       _MACH_SEND_INTERRUPT = 0x40
+       _MACH_SEND_ALWAYS    = 0x10000
+       _MACH_SEND_TRAILER   = 0x20000
+       _MACH_RCV_TIMEOUT    = 0x100
+       _MACH_RCV_NOTIFY     = 0x200
+       _MACH_RCV_INTERRUPT  = 0x400
+       _MACH_RCV_OVERWRITE  = 0x1000
+
+       _NDR_PROTOCOL_2_0      = 0x0
+       _NDR_INT_BIG_ENDIAN    = 0x0
+       _NDR_INT_LITTLE_ENDIAN = 0x1
+       _NDR_FLOAT_IEEE        = 0x0
+       _NDR_CHAR_ASCII        = 0x0
+
+       _SA_SIGINFO   = 0x40
+       _SA_RESTART   = 0x2
+       _SA_ONSTACK   = 0x1
+       _SA_USERTRAMP = 0x100
+       _SA_64REGSET  = 0x200
+
+       _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 = 0x7
+       _FPE_INTOVF = 0x8
+       _FPE_FLTDIV = 0x1
+       _FPE_FLTOVF = 0x2
+       _FPE_FLTUND = 0x3
+       _FPE_FLTRES = 0x4
+       _FPE_FLTINV = 0x5
+       _FPE_FLTSUB = 0x6
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0x40
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type machbody struct {
+       msgh_descriptor_count uint32
+}
+
+type machheader struct {
+       msgh_bits        uint32
+       msgh_size        uint32
+       msgh_remote_port uint32
+       msgh_local_port  uint32
+       msgh_reserved    uint32
+       msgh_id          int32
+}
+
+type machndr struct {
+       mig_vers     uint8
+       if_vers      uint8
+       reserved1    uint8
+       mig_encoding uint8
+       int_rep      uint8
+       char_rep     uint8
+       float_rep    uint8
+       reserved2    uint8
+}
+
+type machport struct {
+       name        uint32
+       pad1        uint32
+       pad2        uint16
+       disposition uint8
+       _type       uint8
+}
+
+type stackt struct {
+       ss_sp    *byte
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type sigactiont struct {
+       __sigaction_u [4]byte
+       sa_tramp      unsafe.Pointer
+       sa_mask       uint32
+       sa_flags      int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   *byte
+       si_value  [4]byte
+       si_band   int32
+       __pad     [7]uint32
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+type fpcontrol struct {
+       pad_cgo_0 [2]byte
+}
+
+type fpstatus struct {
+       pad_cgo_0 [2]byte
+}
+
+type regmmst struct {
+       mmst_reg  [10]int8
+       mmst_rsrv [6]int8
+}
+
+type regxmm struct {
+       xmm_reg [16]int8
+}
+
+type regs64 struct {
+       rax    uint64
+       rbx    uint64
+       rcx    uint64
+       rdx    uint64
+       rdi    uint64
+       rsi    uint64
+       rbp    uint64
+       rsp    uint64
+       r8     uint64
+       r9     uint64
+       r10    uint64
+       r11    uint64
+       r12    uint64
+       r13    uint64
+       r14    uint64
+       r15    uint64
+       rip    uint64
+       rflags uint64
+       cs     uint64
+       fs     uint64
+       gs     uint64
+}
+
+type floatstate64 struct {
+       fpu_reserved  [2]int32
+       fpu_fcw       fpcontrol
+       fpu_fsw       fpstatus
+       fpu_ftw       uint8
+       fpu_rsrv1     uint8
+       fpu_fop       uint16
+       fpu_ip        uint32
+       fpu_cs        uint16
+       fpu_rsrv2     uint16
+       fpu_dp        uint32
+       fpu_ds        uint16
+       fpu_rsrv3     uint16
+       fpu_mxcsr     uint32
+       fpu_mxcsrmask uint32
+       fpu_stmm0     regmmst
+       fpu_stmm1     regmmst
+       fpu_stmm2     regmmst
+       fpu_stmm3     regmmst
+       fpu_stmm4     regmmst
+       fpu_stmm5     regmmst
+       fpu_stmm6     regmmst
+       fpu_stmm7     regmmst
+       fpu_xmm0      regxmm
+       fpu_xmm1      regxmm
+       fpu_xmm2      regxmm
+       fpu_xmm3      regxmm
+       fpu_xmm4      regxmm
+       fpu_xmm5      regxmm
+       fpu_xmm6      regxmm
+       fpu_xmm7      regxmm
+       fpu_xmm8      regxmm
+       fpu_xmm9      regxmm
+       fpu_xmm10     regxmm
+       fpu_xmm11     regxmm
+       fpu_xmm12     regxmm
+       fpu_xmm13     regxmm
+       fpu_xmm14     regxmm
+       fpu_xmm15     regxmm
+       fpu_rsrv4     [96]int8
+       fpu_reserved1 int32
+}
+
+type exceptionstate64 struct {
+       trapno     uint16
+       cpu        uint16
+       err        uint32
+       faultvaddr uint64
+}
+
+type mcontext64 struct {
+       es exceptionstate64
+       ss regs64
+       fs floatstate64
+}
+
+type regs32 struct {
+       eax    uint32
+       ebx    uint32
+       ecx    uint32
+       edx    uint32
+       edi    uint32
+       esi    uint32
+       ebp    uint32
+       esp    uint32
+       ss     uint32
+       eflags uint32
+       eip    uint32
+       cs     uint32
+       ds     uint32
+       es     uint32
+       fs     uint32
+       gs     uint32
+}
+
+type floatstate32 struct {
+       fpu_reserved  [2]int32
+       fpu_fcw       fpcontrol
+       fpu_fsw       fpstatus
+       fpu_ftw       uint8
+       fpu_rsrv1     uint8
+       fpu_fop       uint16
+       fpu_ip        uint32
+       fpu_cs        uint16
+       fpu_rsrv2     uint16
+       fpu_dp        uint32
+       fpu_ds        uint16
+       fpu_rsrv3     uint16
+       fpu_mxcsr     uint32
+       fpu_mxcsrmask uint32
+       fpu_stmm0     regmmst
+       fpu_stmm1     regmmst
+       fpu_stmm2     regmmst
+       fpu_stmm3     regmmst
+       fpu_stmm4     regmmst
+       fpu_stmm5     regmmst
+       fpu_stmm6     regmmst
+       fpu_stmm7     regmmst
+       fpu_xmm0      regxmm
+       fpu_xmm1      regxmm
+       fpu_xmm2      regxmm
+       fpu_xmm3      regxmm
+       fpu_xmm4      regxmm
+       fpu_xmm5      regxmm
+       fpu_xmm6      regxmm
+       fpu_xmm7      regxmm
+       fpu_rsrv4     [224]int8
+       fpu_reserved1 int32
+}
+
+type exceptionstate32 struct {
+       trapno     uint16
+       cpu        uint16
+       err        uint32
+       faultvaddr uint32
+}
+
+type mcontext32 struct {
+       es exceptionstate32
+       ss regs32
+       fs floatstate32
+}
+
+type ucontext struct {
+       uc_onstack  int32
+       uc_sigmask  uint32
+       uc_stack    stackt
+       uc_link     *ucontext
+       uc_mcsize   uint32
+       uc_mcontext *mcontext32
+}
+
+type keventt struct {
+       ident  uint32
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int32
+       udata  *byte
+}
diff --git a/src/runtime/defs_darwin_386.h b/src/runtime/defs_darwin_386.h
deleted file mode 100644 (file)
index 0e0b4fb..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_darwin.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x1000,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_DONTNEED   = 0x4,
-       MADV_FREE       = 0x5,
-
-       MACH_MSG_TYPE_MOVE_RECEIVE      = 0x10,
-       MACH_MSG_TYPE_MOVE_SEND         = 0x11,
-       MACH_MSG_TYPE_MOVE_SEND_ONCE    = 0x12,
-       MACH_MSG_TYPE_COPY_SEND         = 0x13,
-       MACH_MSG_TYPE_MAKE_SEND         = 0x14,
-       MACH_MSG_TYPE_MAKE_SEND_ONCE    = 0x15,
-       MACH_MSG_TYPE_COPY_RECEIVE      = 0x16,
-
-       MACH_MSG_PORT_DESCRIPTOR                = 0x0,
-       MACH_MSG_OOL_DESCRIPTOR                 = 0x1,
-       MACH_MSG_OOL_PORTS_DESCRIPTOR           = 0x2,
-       MACH_MSG_OOL_VOLATILE_DESCRIPTOR        = 0x3,
-
-       MACH_MSGH_BITS_COMPLEX  = 0x80000000,
-
-       MACH_SEND_MSG   = 0x1,
-       MACH_RCV_MSG    = 0x2,
-       MACH_RCV_LARGE  = 0x4,
-
-       MACH_SEND_TIMEOUT       = 0x10,
-       MACH_SEND_INTERRUPT     = 0x40,
-       MACH_SEND_ALWAYS        = 0x10000,
-       MACH_SEND_TRAILER       = 0x20000,
-       MACH_RCV_TIMEOUT        = 0x100,
-       MACH_RCV_NOTIFY         = 0x200,
-       MACH_RCV_INTERRUPT      = 0x400,
-       MACH_RCV_OVERWRITE      = 0x1000,
-
-       NDR_PROTOCOL_2_0        = 0x0,
-       NDR_INT_BIG_ENDIAN      = 0x0,
-       NDR_INT_LITTLE_ENDIAN   = 0x1,
-       NDR_FLOAT_IEEE          = 0x0,
-       NDR_CHAR_ASCII          = 0x0,
-
-       SA_SIGINFO      = 0x40,
-       SA_RESTART      = 0x2,
-       SA_ONSTACK      = 0x1,
-       SA_USERTRAMP    = 0x100,
-       SA_64REGSET     = 0x200,
-
-       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      = 0x7,
-       FPE_INTOVF      = 0x8,
-       FPE_FLTDIV      = 0x1,
-       FPE_FLTOVF      = 0x2,
-       FPE_FLTUND      = 0x3,
-       FPE_FLTRES      = 0x4,
-       FPE_FLTINV      = 0x5,
-       FPE_FLTSUB      = 0x6,
-
-       BUS_ADRALN      = 0x1,
-       BUS_ADRERR      = 0x2,
-       BUS_OBJERR      = 0x3,
-
-       SEGV_MAPERR     = 0x1,
-       SEGV_ACCERR     = 0x2,
-
-       ITIMER_REAL     = 0x0,
-       ITIMER_VIRTUAL  = 0x1,
-       ITIMER_PROF     = 0x2,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0x40,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct MachBody MachBody;
-typedef struct MachHeader MachHeader;
-typedef struct MachNDR MachNDR;
-typedef struct MachPort MachPort;
-typedef struct StackT StackT;
-typedef struct SigactionT SigactionT;
-typedef struct Siginfo Siginfo;
-typedef struct Timeval Timeval;
-typedef struct Itimerval Itimerval;
-typedef struct Timespec Timespec;
-typedef struct FPControl FPControl;
-typedef struct FPStatus FPStatus;
-typedef struct RegMMST RegMMST;
-typedef struct RegXMM RegXMM;
-typedef struct Regs64 Regs64;
-typedef struct FloatState64 FloatState64;
-typedef struct ExceptionState64 ExceptionState64;
-typedef struct Mcontext64 Mcontext64;
-typedef struct Regs32 Regs32;
-typedef struct FloatState32 FloatState32;
-typedef struct ExceptionState32 ExceptionState32;
-typedef struct Mcontext32 Mcontext32;
-typedef struct Ucontext Ucontext;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct MachBody {
-       uint32  msgh_descriptor_count;
-};
-struct MachHeader {
-       uint32  msgh_bits;
-       uint32  msgh_size;
-       uint32  msgh_remote_port;
-       uint32  msgh_local_port;
-       uint32  msgh_reserved;
-       int32   msgh_id;
-};
-struct MachNDR {
-       uint8   mig_vers;
-       uint8   if_vers;
-       uint8   reserved1;
-       uint8   mig_encoding;
-       uint8   int_rep;
-       uint8   char_rep;
-       uint8   float_rep;
-       uint8   reserved2;
-};
-struct MachPort {
-       uint32  name;
-       uint32  pad1;
-       uint16  pad2;
-       uint8   disposition;
-       uint8   type;
-};
-
-struct StackT {
-       byte    *ss_sp;
-       uint32  ss_size;
-       int32   ss_flags;
-};
-typedef        byte    Sighandler[4];
-
-struct SigactionT {
-       byte    __sigaction_u[4];
-       void    *sa_tramp;
-       uint32  sa_mask;
-       int32   sa_flags;
-};
-
-typedef        byte    Sigval[4];
-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];
-       int32   si_band;
-       uint32  __pad[7];
-};
-struct Timeval {
-       int32   tv_sec;
-       int32   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-struct Timespec {
-       int32   tv_sec;
-       int32   tv_nsec;
-};
-
-struct FPControl {
-       byte    Pad_cgo_0[2];
-};
-struct FPStatus {
-       byte    Pad_cgo_0[2];
-};
-struct RegMMST {
-       int8    mmst_reg[10];
-       int8    mmst_rsrv[6];
-};
-struct RegXMM {
-       int8    xmm_reg[16];
-};
-
-struct Regs64 {
-       uint64  rax;
-       uint64  rbx;
-       uint64  rcx;
-       uint64  rdx;
-       uint64  rdi;
-       uint64  rsi;
-       uint64  rbp;
-       uint64  rsp;
-       uint64  r8;
-       uint64  r9;
-       uint64  r10;
-       uint64  r11;
-       uint64  r12;
-       uint64  r13;
-       uint64  r14;
-       uint64  r15;
-       uint64  rip;
-       uint64  rflags;
-       uint64  cs;
-       uint64  fs;
-       uint64  gs;
-};
-struct FloatState64 {
-       int32   fpu_reserved[2];
-       FPControl       fpu_fcw;
-       FPStatus        fpu_fsw;
-       uint8   fpu_ftw;
-       uint8   fpu_rsrv1;
-       uint16  fpu_fop;
-       uint32  fpu_ip;
-       uint16  fpu_cs;
-       uint16  fpu_rsrv2;
-       uint32  fpu_dp;
-       uint16  fpu_ds;
-       uint16  fpu_rsrv3;
-       uint32  fpu_mxcsr;
-       uint32  fpu_mxcsrmask;
-       RegMMST fpu_stmm0;
-       RegMMST fpu_stmm1;
-       RegMMST fpu_stmm2;
-       RegMMST fpu_stmm3;
-       RegMMST fpu_stmm4;
-       RegMMST fpu_stmm5;
-       RegMMST fpu_stmm6;
-       RegMMST fpu_stmm7;
-       RegXMM  fpu_xmm0;
-       RegXMM  fpu_xmm1;
-       RegXMM  fpu_xmm2;
-       RegXMM  fpu_xmm3;
-       RegXMM  fpu_xmm4;
-       RegXMM  fpu_xmm5;
-       RegXMM  fpu_xmm6;
-       RegXMM  fpu_xmm7;
-       RegXMM  fpu_xmm8;
-       RegXMM  fpu_xmm9;
-       RegXMM  fpu_xmm10;
-       RegXMM  fpu_xmm11;
-       RegXMM  fpu_xmm12;
-       RegXMM  fpu_xmm13;
-       RegXMM  fpu_xmm14;
-       RegXMM  fpu_xmm15;
-       int8    fpu_rsrv4[96];
-       int32   fpu_reserved1;
-};
-struct ExceptionState64 {
-       uint16  trapno;
-       uint16  cpu;
-       uint32  err;
-       uint64  faultvaddr;
-};
-struct Mcontext64 {
-       ExceptionState64        es;
-       Regs64  ss;
-       FloatState64    fs;
-};
-
-struct Regs32 {
-       uint32  eax;
-       uint32  ebx;
-       uint32  ecx;
-       uint32  edx;
-       uint32  edi;
-       uint32  esi;
-       uint32  ebp;
-       uint32  esp;
-       uint32  ss;
-       uint32  eflags;
-       uint32  eip;
-       uint32  cs;
-       uint32  ds;
-       uint32  es;
-       uint32  fs;
-       uint32  gs;
-};
-struct FloatState32 {
-       int32   fpu_reserved[2];
-       FPControl       fpu_fcw;
-       FPStatus        fpu_fsw;
-       uint8   fpu_ftw;
-       uint8   fpu_rsrv1;
-       uint16  fpu_fop;
-       uint32  fpu_ip;
-       uint16  fpu_cs;
-       uint16  fpu_rsrv2;
-       uint32  fpu_dp;
-       uint16  fpu_ds;
-       uint16  fpu_rsrv3;
-       uint32  fpu_mxcsr;
-       uint32  fpu_mxcsrmask;
-       RegMMST fpu_stmm0;
-       RegMMST fpu_stmm1;
-       RegMMST fpu_stmm2;
-       RegMMST fpu_stmm3;
-       RegMMST fpu_stmm4;
-       RegMMST fpu_stmm5;
-       RegMMST fpu_stmm6;
-       RegMMST fpu_stmm7;
-       RegXMM  fpu_xmm0;
-       RegXMM  fpu_xmm1;
-       RegXMM  fpu_xmm2;
-       RegXMM  fpu_xmm3;
-       RegXMM  fpu_xmm4;
-       RegXMM  fpu_xmm5;
-       RegXMM  fpu_xmm6;
-       RegXMM  fpu_xmm7;
-       int8    fpu_rsrv4[224];
-       int32   fpu_reserved1;
-};
-struct ExceptionState32 {
-       uint16  trapno;
-       uint16  cpu;
-       uint32  err;
-       uint32  faultvaddr;
-};
-struct Mcontext32 {
-       ExceptionState32        es;
-       Regs32  ss;
-       FloatState32    fs;
-};
-
-struct Ucontext {
-       int32   uc_onstack;
-       uint32  uc_sigmask;
-       StackT  uc_stack;
-       Ucontext        *uc_link;
-       uint32  uc_mcsize;
-       Mcontext32      *uc_mcontext;
-};
-
-struct KeventT {
-       uint32  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int32   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_darwin_amd64.go b/src/runtime/defs_darwin_amd64.go
new file mode 100644 (file)
index 0000000..2cd4c0c
--- /dev/null
@@ -0,0 +1,385 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_darwin.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x1000
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+       _MADV_FREE     = 0x5
+
+       _MACH_MSG_TYPE_MOVE_RECEIVE   = 0x10
+       _MACH_MSG_TYPE_MOVE_SEND      = 0x11
+       _MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12
+       _MACH_MSG_TYPE_COPY_SEND      = 0x13
+       _MACH_MSG_TYPE_MAKE_SEND      = 0x14
+       _MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15
+       _MACH_MSG_TYPE_COPY_RECEIVE   = 0x16
+
+       _MACH_MSG_PORT_DESCRIPTOR         = 0x0
+       _MACH_MSG_OOL_DESCRIPTOR          = 0x1
+       _MACH_MSG_OOL_PORTS_DESCRIPTOR    = 0x2
+       _MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3
+
+       _MACH_MSGH_BITS_COMPLEX = 0x80000000
+
+       _MACH_SEND_MSG  = 0x1
+       _MACH_RCV_MSG   = 0x2
+       _MACH_RCV_LARGE = 0x4
+
+       _MACH_SEND_TIMEOUT   = 0x10
+       _MACH_SEND_INTERRUPT = 0x40
+       _MACH_SEND_ALWAYS    = 0x10000
+       _MACH_SEND_TRAILER   = 0x20000
+       _MACH_RCV_TIMEOUT    = 0x100
+       _MACH_RCV_NOTIFY     = 0x200
+       _MACH_RCV_INTERRUPT  = 0x400
+       _MACH_RCV_OVERWRITE  = 0x1000
+
+       _NDR_PROTOCOL_2_0      = 0x0
+       _NDR_INT_BIG_ENDIAN    = 0x0
+       _NDR_INT_LITTLE_ENDIAN = 0x1
+       _NDR_FLOAT_IEEE        = 0x0
+       _NDR_CHAR_ASCII        = 0x0
+
+       _SA_SIGINFO   = 0x40
+       _SA_RESTART   = 0x2
+       _SA_ONSTACK   = 0x1
+       _SA_USERTRAMP = 0x100
+       _SA_64REGSET  = 0x200
+
+       _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 = 0x7
+       _FPE_INTOVF = 0x8
+       _FPE_FLTDIV = 0x1
+       _FPE_FLTOVF = 0x2
+       _FPE_FLTUND = 0x3
+       _FPE_FLTRES = 0x4
+       _FPE_FLTINV = 0x5
+       _FPE_FLTSUB = 0x6
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0x40
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type machbody struct {
+       msgh_descriptor_count uint32
+}
+
+type machheader struct {
+       msgh_bits        uint32
+       msgh_size        uint32
+       msgh_remote_port uint32
+       msgh_local_port  uint32
+       msgh_reserved    uint32
+       msgh_id          int32
+}
+
+type machndr struct {
+       mig_vers     uint8
+       if_vers      uint8
+       reserved1    uint8
+       mig_encoding uint8
+       int_rep      uint8
+       char_rep     uint8
+       float_rep    uint8
+       reserved2    uint8
+}
+
+type machport struct {
+       name        uint32
+       pad1        uint32
+       pad2        uint16
+       disposition uint8
+       _type       uint8
+}
+
+type stackt struct {
+       ss_sp     *byte
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type sigactiont struct {
+       __sigaction_u [8]byte
+       sa_tramp      unsafe.Pointer
+       sa_mask       uint32
+       sa_flags      int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   *byte
+       si_value  [8]byte
+       si_band   int64
+       __pad     [7]uint64
+}
+
+type timeval struct {
+       tv_sec    int64
+       tv_usec   int32
+       pad_cgo_0 [4]byte
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+type fpcontrol struct {
+       pad_cgo_0 [2]byte
+}
+
+type fpstatus struct {
+       pad_cgo_0 [2]byte
+}
+
+type regmmst struct {
+       mmst_reg  [10]int8
+       mmst_rsrv [6]int8
+}
+
+type regxmm struct {
+       xmm_reg [16]int8
+}
+
+type regs64 struct {
+       rax    uint64
+       rbx    uint64
+       rcx    uint64
+       rdx    uint64
+       rdi    uint64
+       rsi    uint64
+       rbp    uint64
+       rsp    uint64
+       r8     uint64
+       r9     uint64
+       r10    uint64
+       r11    uint64
+       r12    uint64
+       r13    uint64
+       r14    uint64
+       r15    uint64
+       rip    uint64
+       rflags uint64
+       cs     uint64
+       fs     uint64
+       gs     uint64
+}
+
+type floatstate64 struct {
+       fpu_reserved  [2]int32
+       fpu_fcw       fpcontrol
+       fpu_fsw       fpstatus
+       fpu_ftw       uint8
+       fpu_rsrv1     uint8
+       fpu_fop       uint16
+       fpu_ip        uint32
+       fpu_cs        uint16
+       fpu_rsrv2     uint16
+       fpu_dp        uint32
+       fpu_ds        uint16
+       fpu_rsrv3     uint16
+       fpu_mxcsr     uint32
+       fpu_mxcsrmask uint32
+       fpu_stmm0     regmmst
+       fpu_stmm1     regmmst
+       fpu_stmm2     regmmst
+       fpu_stmm3     regmmst
+       fpu_stmm4     regmmst
+       fpu_stmm5     regmmst
+       fpu_stmm6     regmmst
+       fpu_stmm7     regmmst
+       fpu_xmm0      regxmm
+       fpu_xmm1      regxmm
+       fpu_xmm2      regxmm
+       fpu_xmm3      regxmm
+       fpu_xmm4      regxmm
+       fpu_xmm5      regxmm
+       fpu_xmm6      regxmm
+       fpu_xmm7      regxmm
+       fpu_xmm8      regxmm
+       fpu_xmm9      regxmm
+       fpu_xmm10     regxmm
+       fpu_xmm11     regxmm
+       fpu_xmm12     regxmm
+       fpu_xmm13     regxmm
+       fpu_xmm14     regxmm
+       fpu_xmm15     regxmm
+       fpu_rsrv4     [96]int8
+       fpu_reserved1 int32
+}
+
+type exceptionstate64 struct {
+       trapno     uint16
+       cpu        uint16
+       err        uint32
+       faultvaddr uint64
+}
+
+type mcontext64 struct {
+       es        exceptionstate64
+       ss        regs64
+       fs        floatstate64
+       pad_cgo_0 [4]byte
+}
+
+type regs32 struct {
+       eax    uint32
+       ebx    uint32
+       ecx    uint32
+       edx    uint32
+       edi    uint32
+       esi    uint32
+       ebp    uint32
+       esp    uint32
+       ss     uint32
+       eflags uint32
+       eip    uint32
+       cs     uint32
+       ds     uint32
+       es     uint32
+       fs     uint32
+       gs     uint32
+}
+
+type floatstate32 struct {
+       fpu_reserved  [2]int32
+       fpu_fcw       fpcontrol
+       fpu_fsw       fpstatus
+       fpu_ftw       uint8
+       fpu_rsrv1     uint8
+       fpu_fop       uint16
+       fpu_ip        uint32
+       fpu_cs        uint16
+       fpu_rsrv2     uint16
+       fpu_dp        uint32
+       fpu_ds        uint16
+       fpu_rsrv3     uint16
+       fpu_mxcsr     uint32
+       fpu_mxcsrmask uint32
+       fpu_stmm0     regmmst
+       fpu_stmm1     regmmst
+       fpu_stmm2     regmmst
+       fpu_stmm3     regmmst
+       fpu_stmm4     regmmst
+       fpu_stmm5     regmmst
+       fpu_stmm6     regmmst
+       fpu_stmm7     regmmst
+       fpu_xmm0      regxmm
+       fpu_xmm1      regxmm
+       fpu_xmm2      regxmm
+       fpu_xmm3      regxmm
+       fpu_xmm4      regxmm
+       fpu_xmm5      regxmm
+       fpu_xmm6      regxmm
+       fpu_xmm7      regxmm
+       fpu_rsrv4     [224]int8
+       fpu_reserved1 int32
+}
+
+type exceptionstate32 struct {
+       trapno     uint16
+       cpu        uint16
+       err        uint32
+       faultvaddr uint32
+}
+
+type mcontext32 struct {
+       es exceptionstate32
+       ss regs32
+       fs floatstate32
+}
+
+type ucontext struct {
+       uc_onstack  int32
+       uc_sigmask  uint32
+       uc_stack    stackt
+       uc_link     *ucontext
+       uc_mcsize   uint64
+       uc_mcontext *mcontext64
+}
+
+type keventt struct {
+       ident  uint64
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int64
+       udata  *byte
+}
diff --git a/src/runtime/defs_darwin_amd64.h b/src/runtime/defs_darwin_amd64.h
deleted file mode 100644 (file)
index 4bf83c1..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_darwin.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x1000,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_DONTNEED   = 0x4,
-       MADV_FREE       = 0x5,
-
-       MACH_MSG_TYPE_MOVE_RECEIVE      = 0x10,
-       MACH_MSG_TYPE_MOVE_SEND         = 0x11,
-       MACH_MSG_TYPE_MOVE_SEND_ONCE    = 0x12,
-       MACH_MSG_TYPE_COPY_SEND         = 0x13,
-       MACH_MSG_TYPE_MAKE_SEND         = 0x14,
-       MACH_MSG_TYPE_MAKE_SEND_ONCE    = 0x15,
-       MACH_MSG_TYPE_COPY_RECEIVE      = 0x16,
-
-       MACH_MSG_PORT_DESCRIPTOR                = 0x0,
-       MACH_MSG_OOL_DESCRIPTOR                 = 0x1,
-       MACH_MSG_OOL_PORTS_DESCRIPTOR           = 0x2,
-       MACH_MSG_OOL_VOLATILE_DESCRIPTOR        = 0x3,
-
-       MACH_MSGH_BITS_COMPLEX  = 0x80000000,
-
-       MACH_SEND_MSG   = 0x1,
-       MACH_RCV_MSG    = 0x2,
-       MACH_RCV_LARGE  = 0x4,
-
-       MACH_SEND_TIMEOUT       = 0x10,
-       MACH_SEND_INTERRUPT     = 0x40,
-       MACH_SEND_ALWAYS        = 0x10000,
-       MACH_SEND_TRAILER       = 0x20000,
-       MACH_RCV_TIMEOUT        = 0x100,
-       MACH_RCV_NOTIFY         = 0x200,
-       MACH_RCV_INTERRUPT      = 0x400,
-       MACH_RCV_OVERWRITE      = 0x1000,
-
-       NDR_PROTOCOL_2_0        = 0x0,
-       NDR_INT_BIG_ENDIAN      = 0x0,
-       NDR_INT_LITTLE_ENDIAN   = 0x1,
-       NDR_FLOAT_IEEE          = 0x0,
-       NDR_CHAR_ASCII          = 0x0,
-
-       SA_SIGINFO      = 0x40,
-       SA_RESTART      = 0x2,
-       SA_ONSTACK      = 0x1,
-       SA_USERTRAMP    = 0x100,
-       SA_64REGSET     = 0x200,
-
-       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      = 0x7,
-       FPE_INTOVF      = 0x8,
-       FPE_FLTDIV      = 0x1,
-       FPE_FLTOVF      = 0x2,
-       FPE_FLTUND      = 0x3,
-       FPE_FLTRES      = 0x4,
-       FPE_FLTINV      = 0x5,
-       FPE_FLTSUB      = 0x6,
-
-       BUS_ADRALN      = 0x1,
-       BUS_ADRERR      = 0x2,
-       BUS_OBJERR      = 0x3,
-
-       SEGV_MAPERR     = 0x1,
-       SEGV_ACCERR     = 0x2,
-
-       ITIMER_REAL     = 0x0,
-       ITIMER_VIRTUAL  = 0x1,
-       ITIMER_PROF     = 0x2,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0x40,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct MachBody MachBody;
-typedef struct MachHeader MachHeader;
-typedef struct MachNDR MachNDR;
-typedef struct MachPort MachPort;
-typedef struct StackT StackT;
-typedef struct SigactionT SigactionT;
-typedef struct Siginfo Siginfo;
-typedef struct Timeval Timeval;
-typedef struct Itimerval Itimerval;
-typedef struct Timespec Timespec;
-typedef struct FPControl FPControl;
-typedef struct FPStatus FPStatus;
-typedef struct RegMMST RegMMST;
-typedef struct RegXMM RegXMM;
-typedef struct Regs64 Regs64;
-typedef struct FloatState64 FloatState64;
-typedef struct ExceptionState64 ExceptionState64;
-typedef struct Mcontext64 Mcontext64;
-typedef struct Regs32 Regs32;
-typedef struct FloatState32 FloatState32;
-typedef struct ExceptionState32 ExceptionState32;
-typedef struct Mcontext32 Mcontext32;
-typedef struct Ucontext Ucontext;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct MachBody {
-       uint32  msgh_descriptor_count;
-};
-struct MachHeader {
-       uint32  msgh_bits;
-       uint32  msgh_size;
-       uint32  msgh_remote_port;
-       uint32  msgh_local_port;
-       uint32  msgh_reserved;
-       int32   msgh_id;
-};
-struct MachNDR {
-       uint8   mig_vers;
-       uint8   if_vers;
-       uint8   reserved1;
-       uint8   mig_encoding;
-       uint8   int_rep;
-       uint8   char_rep;
-       uint8   float_rep;
-       uint8   reserved2;
-};
-struct MachPort {
-       uint32  name;
-       uint32  pad1;
-       uint16  pad2;
-       uint8   disposition;
-       uint8   type;
-};
-
-struct StackT {
-       byte    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-typedef        byte    Sighandler[8];
-
-struct SigactionT {
-       byte    __sigaction_u[8];
-       void    *sa_tramp;
-       uint32  sa_mask;
-       int32   sa_flags;
-};
-
-typedef        byte    Sigval[8];
-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[8];
-       int64   si_band;
-       uint64  __pad[7];
-};
-struct Timeval {
-       int64   tv_sec;
-       int32   tv_usec;
-       byte    Pad_cgo_0[4];
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-
-struct FPControl {
-       byte    Pad_cgo_0[2];
-};
-struct FPStatus {
-       byte    Pad_cgo_0[2];
-};
-struct RegMMST {
-       int8    mmst_reg[10];
-       int8    mmst_rsrv[6];
-};
-struct RegXMM {
-       int8    xmm_reg[16];
-};
-
-struct Regs64 {
-       uint64  rax;
-       uint64  rbx;
-       uint64  rcx;
-       uint64  rdx;
-       uint64  rdi;
-       uint64  rsi;
-       uint64  rbp;
-       uint64  rsp;
-       uint64  r8;
-       uint64  r9;
-       uint64  r10;
-       uint64  r11;
-       uint64  r12;
-       uint64  r13;
-       uint64  r14;
-       uint64  r15;
-       uint64  rip;
-       uint64  rflags;
-       uint64  cs;
-       uint64  fs;
-       uint64  gs;
-};
-struct FloatState64 {
-       int32   fpu_reserved[2];
-       FPControl       fpu_fcw;
-       FPStatus        fpu_fsw;
-       uint8   fpu_ftw;
-       uint8   fpu_rsrv1;
-       uint16  fpu_fop;
-       uint32  fpu_ip;
-       uint16  fpu_cs;
-       uint16  fpu_rsrv2;
-       uint32  fpu_dp;
-       uint16  fpu_ds;
-       uint16  fpu_rsrv3;
-       uint32  fpu_mxcsr;
-       uint32  fpu_mxcsrmask;
-       RegMMST fpu_stmm0;
-       RegMMST fpu_stmm1;
-       RegMMST fpu_stmm2;
-       RegMMST fpu_stmm3;
-       RegMMST fpu_stmm4;
-       RegMMST fpu_stmm5;
-       RegMMST fpu_stmm6;
-       RegMMST fpu_stmm7;
-       RegXMM  fpu_xmm0;
-       RegXMM  fpu_xmm1;
-       RegXMM  fpu_xmm2;
-       RegXMM  fpu_xmm3;
-       RegXMM  fpu_xmm4;
-       RegXMM  fpu_xmm5;
-       RegXMM  fpu_xmm6;
-       RegXMM  fpu_xmm7;
-       RegXMM  fpu_xmm8;
-       RegXMM  fpu_xmm9;
-       RegXMM  fpu_xmm10;
-       RegXMM  fpu_xmm11;
-       RegXMM  fpu_xmm12;
-       RegXMM  fpu_xmm13;
-       RegXMM  fpu_xmm14;
-       RegXMM  fpu_xmm15;
-       int8    fpu_rsrv4[96];
-       int32   fpu_reserved1;
-};
-struct ExceptionState64 {
-       uint16  trapno;
-       uint16  cpu;
-       uint32  err;
-       uint64  faultvaddr;
-};
-struct Mcontext64 {
-       ExceptionState64        es;
-       Regs64  ss;
-       FloatState64    fs;
-       byte    Pad_cgo_0[4];
-};
-
-struct Regs32 {
-       uint32  eax;
-       uint32  ebx;
-       uint32  ecx;
-       uint32  edx;
-       uint32  edi;
-       uint32  esi;
-       uint32  ebp;
-       uint32  esp;
-       uint32  ss;
-       uint32  eflags;
-       uint32  eip;
-       uint32  cs;
-       uint32  ds;
-       uint32  es;
-       uint32  fs;
-       uint32  gs;
-};
-struct FloatState32 {
-       int32   fpu_reserved[2];
-       FPControl       fpu_fcw;
-       FPStatus        fpu_fsw;
-       uint8   fpu_ftw;
-       uint8   fpu_rsrv1;
-       uint16  fpu_fop;
-       uint32  fpu_ip;
-       uint16  fpu_cs;
-       uint16  fpu_rsrv2;
-       uint32  fpu_dp;
-       uint16  fpu_ds;
-       uint16  fpu_rsrv3;
-       uint32  fpu_mxcsr;
-       uint32  fpu_mxcsrmask;
-       RegMMST fpu_stmm0;
-       RegMMST fpu_stmm1;
-       RegMMST fpu_stmm2;
-       RegMMST fpu_stmm3;
-       RegMMST fpu_stmm4;
-       RegMMST fpu_stmm5;
-       RegMMST fpu_stmm6;
-       RegMMST fpu_stmm7;
-       RegXMM  fpu_xmm0;
-       RegXMM  fpu_xmm1;
-       RegXMM  fpu_xmm2;
-       RegXMM  fpu_xmm3;
-       RegXMM  fpu_xmm4;
-       RegXMM  fpu_xmm5;
-       RegXMM  fpu_xmm6;
-       RegXMM  fpu_xmm7;
-       int8    fpu_rsrv4[224];
-       int32   fpu_reserved1;
-};
-struct ExceptionState32 {
-       uint16  trapno;
-       uint16  cpu;
-       uint32  err;
-       uint32  faultvaddr;
-};
-struct Mcontext32 {
-       ExceptionState32        es;
-       Regs32  ss;
-       FloatState32    fs;
-};
-
-struct Ucontext {
-       int32   uc_onstack;
-       uint32  uc_sigmask;
-       StackT  uc_stack;
-       Ucontext        *uc_link;
-       uint64  uc_mcsize;
-       Mcontext64      *uc_mcontext;
-};
-
-struct KeventT {
-       uint64  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_dragonfly_386.go b/src/runtime/defs_dragonfly_386.go
new file mode 100644 (file)
index 0000000..1768dba
--- /dev/null
@@ -0,0 +1,190 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_dragonfly.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+       _EBUSY  = 0x10
+       _EAGAIN = 0x23
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type rtprio struct {
+       _type uint16
+       prio  uint16
+}
+
+type lwpparams struct {
+       _type unsafe.Pointer
+       arg   *byte
+       stack *byte
+       tid1  *int32
+       tid2  *int32
+}
+
+type sigaltstackt struct {
+       ss_sp    *int8
+       ss_size  uint32
+       ss_flags int32
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type stackt struct {
+       ss_sp    *int8
+       ss_size  uint32
+       ss_flags int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   *byte
+       si_value  [4]byte
+       si_band   int32
+       __spare__ [7]int32
+}
+
+type mcontext struct {
+       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_xflags   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_fpregs   [128]int32
+       __spare__   [16]int32
+}
+
+type ucontext struct {
+       uc_sigmask  sigset
+       uc_mcontext mcontext
+       uc_link     *ucontext
+       uc_stack    stackt
+       __spare__   [8]int32
+}
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint32
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int32
+       udata  *byte
+}
diff --git a/src/runtime/defs_dragonfly_386.h b/src/runtime/defs_dragonfly_386.h
deleted file mode 100644 (file)
index f86b9c6..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_dragonfly.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-       EBUSY   = 0x10,
-       EAGAIN  = 0x23,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct Rtprio Rtprio;
-typedef struct Lwpparams Lwpparams;
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct Rtprio {
-       uint16  type;
-       uint16  prio;
-};
-struct Lwpparams {
-       void    *func;
-       byte    *arg;
-       byte    *stack;
-       int32   *tid1;
-       int32   *tid2;
-};
-struct SigaltstackT {
-       int8    *ss_sp;
-       uint32  ss_size;
-       int32   ss_flags;
-};
-struct Sigset {
-       uint32  __bits[4];
-};
-struct StackT {
-       int8    *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];
-       int32   si_band;
-       int32   __spare__[7];
-};
-
-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_xflags;
-       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_fpregs[128];
-       int32   __spare__[16];
-};
-struct Ucontext {
-       Sigset  uc_sigmask;
-       Mcontext        uc_mcontext;
-       Ucontext        *uc_link;
-       StackT  uc_stack;
-       int32   __spare__[8];
-};
-
-struct Timespec {
-       int32   tv_sec;
-       int32   tv_nsec;
-};
-struct Timeval {
-       int32   tv_sec;
-       int32   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct KeventT {
-       uint32  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int32   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_dragonfly_amd64.go b/src/runtime/defs_dragonfly_amd64.go
new file mode 100644 (file)
index 0000000..3ac10b0
--- /dev/null
@@ -0,0 +1,208 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_dragonfly.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+       _EBUSY  = 0x10
+       _EAGAIN = 0x23
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type rtprio struct {
+       _type uint16
+       prio  uint16
+}
+
+type lwpparams struct {
+       start_func uintptr
+       arg        unsafe.Pointer
+       stack      uintptr
+       tid1       unsafe.Pointer // *int32
+       tid2       unsafe.Pointer // *int32
+}
+
+type sigaltstackt struct {
+       ss_sp     uintptr
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type stackt struct {
+       ss_sp     uintptr
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   uint64
+       si_value  [8]byte
+       si_band   int64
+       __spare__ [7]int32
+       pad_cgo_0 [4]byte
+}
+
+type mcontext struct {
+       mc_onstack  uint64
+       mc_rdi      uint64
+       mc_rsi      uint64
+       mc_rdx      uint64
+       mc_rcx      uint64
+       mc_r8       uint64
+       mc_r9       uint64
+       mc_rax      uint64
+       mc_rbx      uint64
+       mc_rbp      uint64
+       mc_r10      uint64
+       mc_r11      uint64
+       mc_r12      uint64
+       mc_r13      uint64
+       mc_r14      uint64
+       mc_r15      uint64
+       mc_xflags   uint64
+       mc_trapno   uint64
+       mc_addr     uint64
+       mc_flags    uint64
+       mc_err      uint64
+       mc_rip      uint64
+       mc_cs       uint64
+       mc_rflags   uint64
+       mc_rsp      uint64
+       mc_ss       uint64
+       mc_len      uint32
+       mc_fpformat uint32
+       mc_ownedfp  uint32
+       mc_reserved uint32
+       mc_unused   [8]uint32
+       mc_fpregs   [256]int32
+}
+
+type ucontext struct {
+       uc_sigmask  sigset
+       pad_cgo_0   [48]byte
+       uc_mcontext mcontext
+       uc_link     *ucontext
+       uc_stack    stackt
+       __spare__   [8]int32
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint64
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int64
+       udata  *byte
+}
diff --git a/src/runtime/defs_dragonfly_amd64.h b/src/runtime/defs_dragonfly_amd64.h
deleted file mode 100644 (file)
index 6715552..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_dragonfly.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-       EBUSY   = 0x10,
-       EAGAIN  = 0x23,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct Rtprio Rtprio;
-typedef struct Lwpparams Lwpparams;
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct Rtprio {
-       uint16  type;
-       uint16  prio;
-};
-struct Lwpparams {
-       void    *func;
-       byte    *arg;
-       byte    *stack;
-       int32   *tid1;
-       int32   *tid2;
-};
-struct SigaltstackT {
-       int8    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-struct Sigset {
-       uint32  __bits[4];
-};
-struct StackT {
-       int8    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-
-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[8];
-       int64   si_band;
-       int32   __spare__[7];
-       byte    Pad_cgo_0[4];
-};
-
-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;
-       int64   mc_xflags;
-       int64   mc_trapno;
-       int64   mc_addr;
-       int64   mc_flags;
-       int64   mc_err;
-       int64   mc_rip;
-       int64   mc_cs;
-       int64   mc_rflags;
-       int64   mc_rsp;
-       int64   mc_ss;
-       uint32  mc_len;
-       uint32  mc_fpformat;
-       uint32  mc_ownedfp;
-       uint32  mc_reserved;
-       uint32  mc_unused[8];
-       int32   mc_fpregs[256];
-};
-struct Ucontext {
-       Sigset  uc_sigmask;
-       byte    Pad_cgo_0[48];
-       Mcontext        uc_mcontext;
-       Ucontext        *uc_link;
-       StackT  uc_stack;
-       int32   __spare__[8];
-};
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct KeventT {
-       uint64  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_freebsd_386.go b/src/runtime/defs_freebsd_386.go
new file mode 100644 (file)
index 0000000..6938c18
--- /dev/null
@@ -0,0 +1,213 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_freebsd.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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_UINT         = 0xb
+       _UMTX_OP_WAIT_UINT_PRIVATE = 0xf
+       _UMTX_OP_WAKE              = 0x3
+       _UMTX_OP_WAKE_PRIVATE      = 0x10
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0x40
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type rtprio struct {
+       _type uint16
+       prio  uint16
+}
+
+type thrparam struct {
+       start_func uintptr
+       arg        unsafe.Pointer
+       stack_base uintptr
+       stack_size uintptr
+       tls_base   unsafe.Pointer
+       tls_size   uintptr
+       child_tid  unsafe.Pointer // *int32
+       parent_tid *int32
+       flags      int32
+       rtp        *rtprio
+       spare      [3]uintptr
+}
+
+type sigaltstackt struct {
+       ss_sp    *int8
+       ss_size  uint32
+       ss_flags int32
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type stackt struct {
+       ss_sp    uintptr
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   uintptr
+       si_value  [4]byte
+       _reason   [32]byte
+}
+
+type mcontext struct {
+       mc_onstack       uint32
+       mc_gs            uint32
+       mc_fs            uint32
+       mc_es            uint32
+       mc_ds            uint32
+       mc_edi           uint32
+       mc_esi           uint32
+       mc_ebp           uint32
+       mc_isp           uint32
+       mc_ebx           uint32
+       mc_edx           uint32
+       mc_ecx           uint32
+       mc_eax           uint32
+       mc_trapno        uint32
+       mc_err           uint32
+       mc_eip           uint32
+       mc_cs            uint32
+       mc_eflags        uint32
+       mc_esp           uint32
+       mc_ss            uint32
+       mc_len           uint32
+       mc_fpformat      uint32
+       mc_ownedfp       uint32
+       mc_flags         uint32
+       mc_fpstate       [128]uint32
+       mc_fsbase        uint32
+       mc_gsbase        uint32
+       mc_xfpustate     uint32
+       mc_xfpustate_len uint32
+       mc_spare2        [4]uint32
+}
+
+type ucontext struct {
+       uc_sigmask  sigset
+       uc_mcontext mcontext
+       uc_link     *ucontext
+       uc_stack    stackt
+       uc_flags    int32
+       __spare__   [4]int32
+       pad_cgo_0   [12]byte
+}
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = int32(x)
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint32
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int32
+       udata  *byte
+}
diff --git a/src/runtime/defs_freebsd_386.h b/src/runtime/defs_freebsd_386.h
deleted file mode 100644 (file)
index 156dccb..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_freebsd.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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_UINT               = 0xb,
-       UMTX_OP_WAIT_UINT_PRIVATE       = 0xf,
-       UMTX_OP_WAKE                    = 0x3,
-       UMTX_OP_WAKE_PRIVATE            = 0x10,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0x40,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct Rtprio Rtprio;
-typedef struct ThrParam ThrParam;
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct Rtprio {
-       uint16  type;
-       uint16  prio;
-};
-struct ThrParam {
-       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];
-};
-struct SigaltstackT {
-       int8    *ss_sp;
-       uint32  ss_size;
-       int32   ss_flags;
-};
-struct Sigset {
-       uint32  __bits[4];
-};
-struct StackT {
-       int8    *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 {
-       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_flags;
-       int32   mc_fpstate[128];
-       int32   mc_fsbase;
-       int32   mc_gsbase;
-       int32   mc_xfpustate;
-       int32   mc_xfpustate_len;
-       int32   mc_spare2[4];
-};
-struct Ucontext {
-       Sigset  uc_sigmask;
-       Mcontext        uc_mcontext;
-       Ucontext        *uc_link;
-       StackT  uc_stack;
-       int32   uc_flags;
-       int32   __spare__[4];
-       byte    Pad_cgo_0[12];
-};
-
-struct Timespec {
-       int32   tv_sec;
-       int32   tv_nsec;
-};
-struct Timeval {
-       int32   tv_sec;
-       int32   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct KeventT {
-       uint32  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int32   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_freebsd_amd64.go b/src/runtime/defs_freebsd_amd64.go
new file mode 100644 (file)
index 0000000..de98e7a
--- /dev/null
@@ -0,0 +1,224 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_freebsd.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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_UINT         = 0xb
+       _UMTX_OP_WAIT_UINT_PRIVATE = 0xf
+       _UMTX_OP_WAKE              = 0x3
+       _UMTX_OP_WAKE_PRIVATE      = 0x10
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0x40
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type rtprio struct {
+       _type uint16
+       prio  uint16
+}
+
+type thrparam struct {
+       start_func uintptr
+       arg        unsafe.Pointer
+       stack_base uintptr
+       stack_size uintptr
+       tls_base   unsafe.Pointer
+       tls_size   uintptr
+       child_tid  unsafe.Pointer // *int64
+       parent_tid *int64
+       flags      int32
+       pad_cgo_0  [4]byte
+       rtp        *rtprio
+       spare      [3]uintptr
+}
+
+type sigaltstackt struct {
+       ss_sp     *int8
+       ss_size   uint64
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type stackt struct {
+       ss_sp     uintptr
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   uint64
+       si_value  [8]byte
+       _reason   [40]byte
+}
+
+type mcontext struct {
+       mc_onstack       uint64
+       mc_rdi           uint64
+       mc_rsi           uint64
+       mc_rdx           uint64
+       mc_rcx           uint64
+       mc_r8            uint64
+       mc_r9            uint64
+       mc_rax           uint64
+       mc_rbx           uint64
+       mc_rbp           uint64
+       mc_r10           uint64
+       mc_r11           uint64
+       mc_r12           uint64
+       mc_r13           uint64
+       mc_r14           uint64
+       mc_r15           uint64
+       mc_trapno        uint32
+       mc_fs            uint16
+       mc_gs            uint16
+       mc_addr          uint64
+       mc_flags         uint32
+       mc_es            uint16
+       mc_ds            uint16
+       mc_err           uint64
+       mc_rip           uint64
+       mc_cs            uint64
+       mc_rflags        uint64
+       mc_rsp           uint64
+       mc_ss            uint64
+       mc_len           uint64
+       mc_fpformat      uint64
+       mc_ownedfp       uint64
+       mc_fpstate       [64]uint64
+       mc_fsbase        uint64
+       mc_gsbase        uint64
+       mc_xfpustate     uint64
+       mc_xfpustate_len uint64
+       mc_spare         [4]uint64
+}
+
+type ucontext struct {
+       uc_sigmask  sigset
+       uc_mcontext mcontext
+       uc_link     *ucontext
+       uc_stack    stackt
+       uc_flags    int32
+       __spare__   [4]int32
+       pad_cgo_0   [12]byte
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint64
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int64
+       udata  *byte
+}
diff --git a/src/runtime/defs_freebsd_amd64.h b/src/runtime/defs_freebsd_amd64.h
deleted file mode 100644 (file)
index 4ba8956..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_freebsd.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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_UINT               = 0xb,
-       UMTX_OP_WAIT_UINT_PRIVATE       = 0xf,
-       UMTX_OP_WAKE                    = 0x3,
-       UMTX_OP_WAKE_PRIVATE            = 0x10,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0x40,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct Rtprio Rtprio;
-typedef struct ThrParam ThrParam;
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct Rtprio {
-       uint16  type;
-       uint16  prio;
-};
-struct ThrParam {
-       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];
-};
-struct SigaltstackT {
-       int8    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-struct Sigset {
-       uint32  __bits[4];
-};
-struct StackT {
-       int8    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-
-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[8];
-       byte    _reason[40];
-};
-
-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_xfpustate;
-       int64   mc_xfpustate_len;
-       int64   mc_spare[4];
-};
-struct Ucontext {
-       Sigset  uc_sigmask;
-       Mcontext        uc_mcontext;
-       Ucontext        *uc_link;
-       StackT  uc_stack;
-       int32   uc_flags;
-       int32   __spare__[4];
-       byte    Pad_cgo_0[12];
-};
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct KeventT {
-       uint64  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_freebsd_arm.go b/src/runtime/defs_freebsd_arm.go
new file mode 100644 (file)
index 0000000..744330f
--- /dev/null
@@ -0,0 +1,186 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_freebsd.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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_UINT         = 0xb
+       _UMTX_OP_WAIT_UINT_PRIVATE = 0xf
+       _UMTX_OP_WAKE              = 0x3
+       _UMTX_OP_WAKE_PRIVATE      = 0x10
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0x40
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type rtprio struct {
+       _type uint16
+       prio  uint16
+}
+
+type thrparam struct {
+       start_func uintptr
+       arg        unsafe.Pointer
+       stack_base uintptr
+       stack_size uintptr
+       tls_base   unsafe.Pointer
+       tls_size   uintptr
+       child_tid  unsafe.Pointer // *int32
+       parent_tid *int32
+       flags      int32
+       rtp        *rtprio
+       spare      [3]uintptr
+}
+
+type sigaltstackt struct {
+       ss_sp    *uint8
+       ss_size  uint32
+       ss_flags int32
+}
+
+type sigset struct {
+       __bits [4]uint32
+}
+
+type stackt struct {
+       ss_sp    uintptr
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   uintptr
+       si_value  [4]byte
+       _reason   [32]byte
+}
+
+type mcontext struct {
+       __gregs [17]uint32
+       __fpu   [140]byte
+}
+
+type ucontext struct {
+       uc_sigmask  sigset
+       uc_mcontext mcontext
+       uc_link     *ucontext
+       uc_stack    stackt
+       uc_flags    int32
+       __spare__   [4]int32
+}
+
+type timespec struct {
+       tv_sec    int64
+       tv_nsec   int32
+       pad_cgo_0 [4]byte
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+type timeval struct {
+       tv_sec    int64
+       tv_usec   int32
+       pad_cgo_0 [4]byte
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint32
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int32
+       udata  *byte
+}
diff --git a/src/runtime/defs_freebsd_arm.h b/src/runtime/defs_freebsd_arm.h
deleted file mode 100644 (file)
index 17deba6..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_freebsd.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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_UINT               = 0xb,
-       UMTX_OP_WAIT_UINT_PRIVATE       = 0xf,
-       UMTX_OP_WAKE                    = 0x3,
-       UMTX_OP_WAKE_PRIVATE            = 0x10,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0x40,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct Rtprio Rtprio;
-typedef struct ThrParam ThrParam;
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#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 SigaltstackT {
-       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;
-       byte    Pad_cgo_0[4];
-};
-struct Timeval {
-       int64   tv_sec;
-       int32   tv_usec;
-       byte    Pad_cgo_0[4];
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct KeventT {
-       uint32  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int32   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
index 8657dbb0ecf3db72674bc9b0672d7a197e81f9eb..553366a50ba6c5adc70f4cf1cb390d0bf363bb86 100644 (file)
@@ -20,6 +20,7 @@ package runtime
 // headers for things like ucontext_t, so that happens in
 // a separate file, defs1.go.
 
+#define        _SYS_TYPES_H    // avoid inclusion of sys/types.h
 #include <asm/posix_types.h>
 #define size_t __kernel_size_t
 #include <asm/signal.h>
@@ -28,7 +29,7 @@ package runtime
 #include <asm-generic/errno.h>
 #include <asm-generic/poll.h>
 #include <linux/eventpoll.h>
-#undef size_t
+#include <linux/time.h>
 */
 import "C"
 
@@ -48,10 +49,9 @@ const (
 
        MADV_DONTNEED = C.MADV_DONTNEED
 
-       SA_RESTART  = C.SA_RESTART
-       SA_ONSTACK  = C.SA_ONSTACK
-       SA_RESTORER = C.SA_RESTORER
-       SA_SIGINFO  = C.SA_SIGINFO
+       SA_RESTART = C.SA_RESTART
+       SA_ONSTACK = C.SA_ONSTACK
+       SA_SIGINFO = C.SA_SIGINFO
 
        SIGHUP    = C.SIGHUP
        SIGINT    = C.SIGINT
@@ -116,6 +116,7 @@ const (
        EPOLL_CTL_MOD = C.EPOLL_CTL_MOD
 )
 
+type Sigset C.sigset_t
 type Timespec C.struct_timespec
 type Timeval C.struct_timeval
 type Sigaction C.struct_sigaction
diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go
new file mode 100644 (file)
index 0000000..f55924b
--- /dev/null
@@ -0,0 +1,218 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs2_linux.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x20
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+
+       _SA_RESTART  = 0x10000000
+       _SA_ONSTACK  = 0x8000000
+       _SA_RESTORER = 0x4000000
+       _SA_SIGINFO  = 0x4
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGBUS    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGUSR1   = 0xa
+       _SIGSEGV   = 0xb
+       _SIGUSR2   = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGSTKFLT = 0x10
+       _SIGCHLD   = 0x11
+       _SIGCONT   = 0x12
+       _SIGSTOP   = 0x13
+       _SIGTSTP   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGURG    = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGIO     = 0x1d
+       _SIGPWR    = 0x1e
+       _SIGSYS    = 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
+
+       _O_RDONLY  = 0x0
+       _O_CLOEXEC = 0x80000
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+type fpreg struct {
+       significand [4]uint16
+       exponent    uint16
+}
+
+type fpxreg struct {
+       significand [4]uint16
+       exponent    uint16
+       padding     [3]uint16
+}
+
+type xmmreg struct {
+       element [4]uint32
+}
+
+type fpstate struct {
+       cw        uint32
+       sw        uint32
+       tag       uint32
+       ipoff     uint32
+       cssel     uint32
+       dataoff   uint32
+       datasel   uint32
+       _st       [8]fpreg
+       status    uint16
+       magic     uint16
+       _fxsr_env [6]uint32
+       mxcsr     uint32
+       reserved  uint32
+       _fxsr_st  [8]fpxreg
+       _xmm      [8]xmmreg
+       padding1  [44]uint32
+       anon0     [48]byte
+}
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = int32(x)
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = x
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint32
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint32
+}
+
+type sigaltstackt struct {
+       ss_sp    *byte
+       ss_flags int32
+       ss_size  uintptr
+}
+
+type sigcontext struct {
+       gs            uint16
+       __gsh         uint16
+       fs            uint16
+       __fsh         uint16
+       es            uint16
+       __esh         uint16
+       ds            uint16
+       __dsh         uint16
+       edi           uint32
+       esi           uint32
+       ebp           uint32
+       esp           uint32
+       ebx           uint32
+       edx           uint32
+       ecx           uint32
+       eax           uint32
+       trapno        uint32
+       err           uint32
+       eip           uint32
+       cs            uint16
+       __csh         uint16
+       eflags        uint32
+       esp_at_signal uint32
+       ss            uint16
+       __ssh         uint16
+       fpstate       *fpstate
+       oldmask       uint32
+       cr2           uint32
+}
+
+type ucontext struct {
+       uc_flags    uint32
+       uc_link     *ucontext
+       uc_stack    sigaltstackt
+       uc_mcontext sigcontext
+       uc_sigmask  uint32
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events uint32
+       data   [8]byte // to match amd64
+}
diff --git a/src/runtime/defs_linux_386.h b/src/runtime/defs_linux_386.h
deleted file mode 100644 (file)
index 24a05d8..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs2_linux.go
-
-
-enum {
-       EINTR   = 0x4,
-       EAGAIN  = 0xb,
-       ENOMEM  = 0xc,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x20,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_DONTNEED   = 0x4,
-
-       SA_RESTART      = 0x10000000,
-       SA_ONSTACK      = 0x8000000,
-       SA_RESTORER     = 0x4000000,
-       SA_SIGINFO      = 0x4,
-
-       SIGHUP          = 0x1,
-       SIGINT          = 0x2,
-       SIGQUIT         = 0x3,
-       SIGILL          = 0x4,
-       SIGTRAP         = 0x5,
-       SIGABRT         = 0x6,
-       SIGBUS          = 0x7,
-       SIGFPE          = 0x8,
-       SIGKILL         = 0x9,
-       SIGUSR1         = 0xa,
-       SIGSEGV         = 0xb,
-       SIGUSR2         = 0xc,
-       SIGPIPE         = 0xd,
-       SIGALRM         = 0xe,
-       SIGSTKFLT       = 0x10,
-       SIGCHLD         = 0x11,
-       SIGCONT         = 0x12,
-       SIGSTOP         = 0x13,
-       SIGTSTP         = 0x14,
-       SIGTTIN         = 0x15,
-       SIGTTOU         = 0x16,
-       SIGURG          = 0x17,
-       SIGXCPU         = 0x18,
-       SIGXFSZ         = 0x19,
-       SIGVTALRM       = 0x1a,
-       SIGPROF         = 0x1b,
-       SIGWINCH        = 0x1c,
-       SIGIO           = 0x1d,
-       SIGPWR          = 0x1e,
-       SIGSYS          = 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,
-
-       O_RDONLY        = 0x0,
-       O_CLOEXEC       = 0x80000,
-
-       EPOLLIN         = 0x1,
-       EPOLLOUT        = 0x4,
-       EPOLLERR        = 0x8,
-       EPOLLHUP        = 0x10,
-       EPOLLRDHUP      = 0x2000,
-       EPOLLET         = -0x80000000,
-       EPOLL_CLOEXEC   = 0x80000,
-       EPOLL_CTL_ADD   = 0x1,
-       EPOLL_CTL_DEL   = 0x2,
-       EPOLL_CTL_MOD   = 0x3,
-};
-
-typedef struct Fpreg Fpreg;
-typedef struct Fpxreg Fpxreg;
-typedef struct Xmmreg Xmmreg;
-typedef struct Fpstate Fpstate;
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct SigactionT SigactionT;
-typedef struct Siginfo Siginfo;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Sigcontext Sigcontext;
-typedef struct Ucontext Ucontext;
-typedef struct Itimerval Itimerval;
-typedef struct EpollEvent EpollEvent;
-
-#pragma pack on
-
-struct Fpreg {
-       uint16  significand[4];
-       uint16  exponent;
-};
-struct Fpxreg {
-       uint16  significand[4];
-       uint16  exponent;
-       uint16  padding[3];
-};
-struct Xmmreg {
-       uint32  element[4];
-};
-struct Fpstate {
-       uint32  cw;
-       uint32  sw;
-       uint32  tag;
-       uint32  ipoff;
-       uint32  cssel;
-       uint32  dataoff;
-       uint32  datasel;
-       Fpreg   _st[8];
-       uint16  status;
-       uint16  magic;
-       uint32  _fxsr_env[6];
-       uint32  mxcsr;
-       uint32  reserved;
-       Fpxreg  _fxsr_st[8];
-       Xmmreg  _xmm[8];
-       uint32  padding1[44];
-       byte    anon0[48];
-};
-struct Timespec {
-       int32   tv_sec;
-       int32   tv_nsec;
-};
-struct Timeval {
-       int32   tv_sec;
-       int32   tv_usec;
-};
-struct SigactionT {
-       void    *k_sa_handler;
-       uint32  sa_flags;
-       void    *sa_restorer;
-       uint64  sa_mask;
-};
-struct Siginfo {
-       int32   si_signo;
-       int32   si_errno;
-       int32   si_code;
-       byte    _sifields[116];
-};
-struct SigaltstackT {
-       byte    *ss_sp;
-       int32   ss_flags;
-       uint32  ss_size;
-};
-struct Sigcontext {
-       uint16  gs;
-       uint16  __gsh;
-       uint16  fs;
-       uint16  __fsh;
-       uint16  es;
-       uint16  __esh;
-       uint16  ds;
-       uint16  __dsh;
-       uint32  edi;
-       uint32  esi;
-       uint32  ebp;
-       uint32  esp;
-       uint32  ebx;
-       uint32  edx;
-       uint32  ecx;
-       uint32  eax;
-       uint32  trapno;
-       uint32  err;
-       uint32  eip;
-       uint16  cs;
-       uint16  __csh;
-       uint32  eflags;
-       uint32  esp_at_signal;
-       uint16  ss;
-       uint16  __ssh;
-       Fpstate *fpstate;
-       uint32  oldmask;
-       uint32  cr2;
-};
-struct Ucontext {
-       uint32  uc_flags;
-       Ucontext        *uc_link;
-       SigaltstackT    uc_stack;
-       Sigcontext      uc_mcontext;
-       uint32  uc_sigmask;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-struct EpollEvent {
-       uint32  events;
-       byte    data[8]; // to match amd64
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go
new file mode 100644 (file)
index 0000000..a73f475
--- /dev/null
@@ -0,0 +1,253 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs1_linux.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x20
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+
+       _SA_RESTART  = 0x10000000
+       _SA_ONSTACK  = 0x8000000
+       _SA_RESTORER = 0x4000000
+       _SA_SIGINFO  = 0x4
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGBUS    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGUSR1   = 0xa
+       _SIGSEGV   = 0xb
+       _SIGUSR2   = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGSTKFLT = 0x10
+       _SIGCHLD   = 0x11
+       _SIGCONT   = 0x12
+       _SIGSTOP   = 0x13
+       _SIGTSTP   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGURG    = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGIO     = 0x1d
+       _SIGPWR    = 0x1e
+       _SIGSYS    = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint64
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint64
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events uint32
+       data   [8]byte // unaligned uintptr
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs1_linux.go
+
+const (
+       _O_RDONLY  = 0x0
+       _O_CLOEXEC = 0x80000
+)
+
+type usigset struct {
+       __val [16]uint64
+}
+
+type fpxreg struct {
+       significand [4]uint16
+       exponent    uint16
+       padding     [3]uint16
+}
+
+type xmmreg struct {
+       element [4]uint32
+}
+
+type fpstate struct {
+       cwd       uint16
+       swd       uint16
+       ftw       uint16
+       fop       uint16
+       rip       uint64
+       rdp       uint64
+       mxcsr     uint32
+       mxcr_mask uint32
+       _st       [8]fpxreg
+       _xmm      [16]xmmreg
+       padding   [24]uint32
+}
+
+type fpxreg1 struct {
+       significand [4]uint16
+       exponent    uint16
+       padding     [3]uint16
+}
+
+type xmmreg1 struct {
+       element [4]uint32
+}
+
+type fpstate1 struct {
+       cwd       uint16
+       swd       uint16
+       ftw       uint16
+       fop       uint16
+       rip       uint64
+       rdp       uint64
+       mxcsr     uint32
+       mxcr_mask uint32
+       _st       [8]fpxreg1
+       _xmm      [16]xmmreg1
+       padding   [24]uint32
+}
+
+type fpreg1 struct {
+       significand [4]uint16
+       exponent    uint16
+}
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+       ss_size   uintptr
+}
+
+type mcontext struct {
+       gregs       [23]uint64
+       fpregs      *fpstate
+       __reserved1 [8]uint64
+}
+
+type ucontext struct {
+       uc_flags     uint64
+       uc_link      *ucontext
+       uc_stack     sigaltstackt
+       uc_mcontext  mcontext
+       uc_sigmask   usigset
+       __fpregs_mem fpstate
+}
+
+type sigcontext struct {
+       r8          uint64
+       r9          uint64
+       r10         uint64
+       r11         uint64
+       r12         uint64
+       r13         uint64
+       r14         uint64
+       r15         uint64
+       rdi         uint64
+       rsi         uint64
+       rbp         uint64
+       rbx         uint64
+       rdx         uint64
+       rax         uint64
+       rcx         uint64
+       rsp         uint64
+       rip         uint64
+       eflags      uint64
+       cs          uint16
+       gs          uint16
+       fs          uint16
+       __pad0      uint16
+       err         uint64
+       trapno      uint64
+       oldmask     uint64
+       cr2         uint64
+       fpstate     *fpstate1
+       __reserved1 [8]uint64
+}
diff --git a/src/runtime/defs_linux_amd64.h b/src/runtime/defs_linux_amd64.h
deleted file mode 100644 (file)
index 14616df..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_linux.go defs1_linux.go
-
-
-enum {
-       EINTR   = 0x4,
-       EAGAIN  = 0xb,
-       ENOMEM  = 0xc,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x20,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_DONTNEED   = 0x4,
-
-       SA_RESTART      = 0x10000000,
-       SA_ONSTACK      = 0x8000000,
-       SA_RESTORER     = 0x4000000,
-       SA_SIGINFO      = 0x4,
-
-       SIGHUP          = 0x1,
-       SIGINT          = 0x2,
-       SIGQUIT         = 0x3,
-       SIGILL          = 0x4,
-       SIGTRAP         = 0x5,
-       SIGABRT         = 0x6,
-       SIGBUS          = 0x7,
-       SIGFPE          = 0x8,
-       SIGKILL         = 0x9,
-       SIGUSR1         = 0xa,
-       SIGSEGV         = 0xb,
-       SIGUSR2         = 0xc,
-       SIGPIPE         = 0xd,
-       SIGALRM         = 0xe,
-       SIGSTKFLT       = 0x10,
-       SIGCHLD         = 0x11,
-       SIGCONT         = 0x12,
-       SIGSTOP         = 0x13,
-       SIGTSTP         = 0x14,
-       SIGTTIN         = 0x15,
-       SIGTTOU         = 0x16,
-       SIGURG          = 0x17,
-       SIGXCPU         = 0x18,
-       SIGXFSZ         = 0x19,
-       SIGVTALRM       = 0x1a,
-       SIGPROF         = 0x1b,
-       SIGWINCH        = 0x1c,
-       SIGIO           = 0x1d,
-       SIGPWR          = 0x1e,
-       SIGSYS          = 0x1f,
-
-       FPE_INTDIV      = 0x1,
-       FPE_INTOVF      = 0x2,
-       FPE_FLTDIV      = 0x3,
-       FPE_FLTOVF      = 0x4,
-       FPE_FLTUND      = 0x5,
-       FPE_FLTRES      = 0x6,
-       FPE_FLTINV      = 0x7,
-       FPE_FLTSUB      = 0x8,
-
-       BUS_ADRALN      = 0x1,
-       BUS_ADRERR      = 0x2,
-       BUS_OBJERR      = 0x3,
-
-       SEGV_MAPERR     = 0x1,
-       SEGV_ACCERR     = 0x2,
-
-       ITIMER_REAL     = 0x0,
-       ITIMER_VIRTUAL  = 0x1,
-       ITIMER_PROF     = 0x2,
-
-       EPOLLIN         = 0x1,
-       EPOLLOUT        = 0x4,
-       EPOLLERR        = 0x8,
-       EPOLLHUP        = 0x10,
-       EPOLLRDHUP      = 0x2000,
-       EPOLLET         = -0x80000000,
-       EPOLL_CLOEXEC   = 0x80000,
-       EPOLL_CTL_ADD   = 0x1,
-       EPOLL_CTL_DEL   = 0x2,
-       EPOLL_CTL_MOD   = 0x3,
-};
-
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct SigactionT SigactionT;
-typedef struct Siginfo Siginfo;
-typedef struct Itimerval Itimerval;
-typedef struct EpollEvent EpollEvent;
-
-#pragma pack on
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct SigactionT {
-       void    *sa_handler;
-       uint64  sa_flags;
-       void    *sa_restorer;
-       uint64  sa_mask;
-};
-struct Siginfo {
-       int32   si_signo;
-       int32   si_errno;
-       int32   si_code;
-       byte    Pad_cgo_0[4];
-       byte    _sifields[112];
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-struct EpollEvent {
-       uint32  events;
-       byte    data[8]; // unaligned uintptr
-};
-
-
-#pragma pack off
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_linux.go defs1_linux.go
-
-
-enum {
-       O_RDONLY        = 0x0,
-       O_CLOEXEC       = 0x80000,
-};
-
-typedef struct Usigset Usigset;
-typedef struct Fpxreg Fpxreg;
-typedef struct Xmmreg Xmmreg;
-typedef struct Fpstate Fpstate;
-typedef struct Fpxreg1 Fpxreg1;
-typedef struct Xmmreg1 Xmmreg1;
-typedef struct Fpstate1 Fpstate1;
-typedef struct Fpreg1 Fpreg1;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Mcontext Mcontext;
-typedef struct Ucontext Ucontext;
-typedef struct Sigcontext Sigcontext;
-
-#pragma pack on
-
-struct Usigset {
-       uint64  __val[16];
-};
-struct Fpxreg {
-       uint16  significand[4];
-       uint16  exponent;
-       uint16  padding[3];
-};
-struct Xmmreg {
-       uint32  element[4];
-};
-struct Fpstate {
-       uint16  cwd;
-       uint16  swd;
-       uint16  ftw;
-       uint16  fop;
-       uint64  rip;
-       uint64  rdp;
-       uint32  mxcsr;
-       uint32  mxcr_mask;
-       Fpxreg  _st[8];
-       Xmmreg  _xmm[16];
-       uint32  padding[24];
-};
-struct Fpxreg1 {
-       uint16  significand[4];
-       uint16  exponent;
-       uint16  padding[3];
-};
-struct Xmmreg1 {
-       uint32  element[4];
-};
-struct Fpstate1 {
-       uint16  cwd;
-       uint16  swd;
-       uint16  ftw;
-       uint16  fop;
-       uint64  rip;
-       uint64  rdp;
-       uint32  mxcsr;
-       uint32  mxcr_mask;
-       Fpxreg1 _st[8];
-       Xmmreg1 _xmm[16];
-       uint32  padding[24];
-};
-struct Fpreg1 {
-       uint16  significand[4];
-       uint16  exponent;
-};
-struct SigaltstackT {
-       byte    *ss_sp;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-       uint64  ss_size;
-};
-struct Mcontext {
-       int64   gregs[23];
-       Fpstate *fpregs;
-       uint64  __reserved1[8];
-};
-struct Ucontext {
-       uint64  uc_flags;
-       Ucontext        *uc_link;
-       SigaltstackT    uc_stack;
-       Mcontext        uc_mcontext;
-       Usigset uc_sigmask;
-       Fpstate __fpregs_mem;
-};
-struct Sigcontext {
-       uint64  r8;
-       uint64  r9;
-       uint64  r10;
-       uint64  r11;
-       uint64  r12;
-       uint64  r13;
-       uint64  r14;
-       uint64  r15;
-       uint64  rdi;
-       uint64  rsi;
-       uint64  rbp;
-       uint64  rbx;
-       uint64  rdx;
-       uint64  rax;
-       uint64  rcx;
-       uint64  rsp;
-       uint64  rip;
-       uint64  eflags;
-       uint16  cs;
-       uint16  gs;
-       uint16  fs;
-       uint16  __pad0;
-       uint64  err;
-       uint64  trapno;
-       uint64  oldmask;
-       uint64  cr2;
-       Fpstate1        *fpstate;
-       uint64  __reserved1[8];
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_linux_arm.go b/src/runtime/defs_linux_arm.go
new file mode 100644 (file)
index 0000000..c3a6e2f
--- /dev/null
@@ -0,0 +1,168 @@
+package runtime
+
+// Constants
+const (
+       _EINTR  = 0x4
+       _ENOMEM = 0xc
+       _EAGAIN = 0xb
+
+       _PROT_NONE      = 0
+       _PROT_READ      = 0x1
+       _PROT_WRITE     = 0x2
+       _PROT_EXEC      = 0x4
+       _MAP_ANON       = 0x20
+       _MAP_PRIVATE    = 0x2
+       _MAP_FIXED      = 0x10
+       _MADV_DONTNEED  = 0x4
+       _SA_RESTART     = 0x10000000
+       _SA_ONSTACK     = 0x8000000
+       _SA_RESTORER    = 0 // unused on ARM
+       _SA_SIGINFO     = 0x4
+       _SIGHUP         = 0x1
+       _SIGINT         = 0x2
+       _SIGQUIT        = 0x3
+       _SIGILL         = 0x4
+       _SIGTRAP        = 0x5
+       _SIGABRT        = 0x6
+       _SIGBUS         = 0x7
+       _SIGFPE         = 0x8
+       _SIGKILL        = 0x9
+       _SIGUSR1        = 0xa
+       _SIGSEGV        = 0xb
+       _SIGUSR2        = 0xc
+       _SIGPIPE        = 0xd
+       _SIGALRM        = 0xe
+       _SIGSTKFLT      = 0x10
+       _SIGCHLD        = 0x11
+       _SIGCONT        = 0x12
+       _SIGSTOP        = 0x13
+       _SIGTSTP        = 0x14
+       _SIGTTIN        = 0x15
+       _SIGTTOU        = 0x16
+       _SIGURG         = 0x17
+       _SIGXCPU        = 0x18
+       _SIGXFSZ        = 0x19
+       _SIGVTALRM      = 0x1a
+       _SIGPROF        = 0x1b
+       _SIGWINCH       = 0x1c
+       _SIGIO          = 0x1d
+       _SIGPWR         = 0x1e
+       _SIGSYS         = 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_PROF    = 0x2
+       _ITIMER_VIRTUAL = 0x1
+       _O_RDONLY       = 0
+       _O_CLOEXEC      = 02000000
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = int32(x)
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = x
+}
+
+type sigaltstackt struct {
+       ss_sp    *byte
+       ss_flags int32
+       ss_size  uintptr
+}
+
+type sigcontext struct {
+       trap_no       uint32
+       error_code    uint32
+       oldmask       uint32
+       r0            uint32
+       r1            uint32
+       r2            uint32
+       r3            uint32
+       r4            uint32
+       r5            uint32
+       r6            uint32
+       r7            uint32
+       r8            uint32
+       r9            uint32
+       r10           uint32
+       fp            uint32
+       ip            uint32
+       sp            uint32
+       lr            uint32
+       pc            uint32
+       cpsr          uint32
+       fault_address uint32
+}
+
+type ucontext struct {
+       uc_flags    uint32
+       uc_link     *ucontext
+       uc_stack    sigaltstackt
+       uc_mcontext sigcontext
+       uc_sigmask  uint32
+       __unused    [31]int32
+       uc_regspace [128]uint32
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint32
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint32
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type epollevent struct {
+       events uint32
+       _pad   uint32
+       data   [8]byte // to match amd64
+}
diff --git a/src/runtime/defs_linux_arm.h b/src/runtime/defs_linux_arm.h
deleted file mode 100644 (file)
index 50b3c91..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-// TODO: Generate using cgo like defs_linux_{386,amd64}.h
-
-// Constants
-enum {
-       EINTR  = 0x4,
-       ENOMEM = 0xc,
-       EAGAIN = 0xb,
-
-       PROT_NONE = 0,
-       PROT_READ = 0x1,
-       PROT_WRITE = 0x2,
-       PROT_EXEC = 0x4,
-       MAP_ANON = 0x20,
-       MAP_PRIVATE = 0x2,
-       MAP_FIXED = 0x10,
-       MADV_DONTNEED = 0x4,
-       SA_RESTART = 0x10000000,
-       SA_ONSTACK = 0x8000000,
-       SA_RESTORER = 0, // unused on ARM
-       SA_SIGINFO = 0x4,
-       SIGHUP = 0x1,
-       SIGINT = 0x2,
-       SIGQUIT = 0x3,
-       SIGILL = 0x4,
-       SIGTRAP = 0x5,
-       SIGABRT = 0x6,
-       SIGBUS = 0x7,
-       SIGFPE = 0x8,
-       SIGKILL = 0x9,
-       SIGUSR1 = 0xa,
-       SIGSEGV = 0xb,
-       SIGUSR2 = 0xc,
-       SIGPIPE = 0xd,
-       SIGALRM = 0xe,
-       SIGSTKFLT = 0x10,
-       SIGCHLD = 0x11,
-       SIGCONT = 0x12,
-       SIGSTOP = 0x13,
-       SIGTSTP = 0x14,
-       SIGTTIN = 0x15,
-       SIGTTOU = 0x16,
-       SIGURG = 0x17,
-       SIGXCPU = 0x18,
-       SIGXFSZ = 0x19,
-       SIGVTALRM = 0x1a,
-       SIGPROF = 0x1b,
-       SIGWINCH = 0x1c,
-       SIGIO = 0x1d,
-       SIGPWR = 0x1e,
-       SIGSYS = 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_PROF = 0x2,
-       ITIMER_VIRTUAL = 0x1,
-       O_RDONLY = 0,
-       O_CLOEXEC = 02000000,
-
-       EPOLLIN         = 0x1,
-       EPOLLOUT        = 0x4,
-       EPOLLERR        = 0x8,
-       EPOLLHUP        = 0x10,
-       EPOLLRDHUP      = 0x2000,
-       EPOLLET         = -0x80000000,
-       EPOLL_CLOEXEC   = 0x80000,
-       EPOLL_CTL_ADD   = 0x1,
-       EPOLL_CTL_DEL   = 0x2,
-       EPOLL_CTL_MOD   = 0x3,
-};
-
-// Types
-#pragma pack on
-
-typedef struct Timespec Timespec;
-struct Timespec {
-       int32 tv_sec;
-       int32 tv_nsec;
-};
-
-typedef struct SigaltstackT SigaltstackT;
-struct SigaltstackT {
-       void *ss_sp;
-       int32 ss_flags;
-       uint32 ss_size;
-};
-
-typedef struct Sigcontext Sigcontext;
-struct Sigcontext {
-       uint32 trap_no;
-       uint32 error_code;
-       uint32 oldmask;
-       uint32 arm_r0;
-       uint32 arm_r1;
-       uint32 arm_r2;
-       uint32 arm_r3;
-       uint32 arm_r4;
-       uint32 arm_r5;
-       uint32 arm_r6;
-       uint32 arm_r7;
-       uint32 arm_r8;
-       uint32 arm_r9;
-       uint32 arm_r10;
-       uint32 arm_fp;
-       uint32 arm_ip;
-       uint32 arm_sp;
-       uint32 arm_lr;
-       uint32 arm_pc;
-       uint32 arm_cpsr;
-       uint32 fault_address;
-};
-
-typedef struct Ucontext Ucontext;
-struct Ucontext {
-       uint32 uc_flags;
-       Ucontext *uc_link;
-       SigaltstackT uc_stack;
-       Sigcontext uc_mcontext;
-       uint32 uc_sigmask;
-       int32 __unused[31];
-       uint32 uc_regspace[128];
-};
-
-typedef struct Timeval Timeval;
-struct Timeval {
-       int32 tv_sec;
-       int32 tv_usec;
-};
-
-typedef struct Itimerval Itimerval;
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-typedef struct Siginfo Siginfo;
-struct Siginfo {
-       int32 si_signo;
-       int32 si_errno;
-       int32 si_code;
-       uint8 _sifields[4];
-};
-
-typedef struct SigactionT SigactionT;
-struct SigactionT {
-       void *sa_handler;
-       uint32 sa_flags;
-       void *sa_restorer;
-       uint64 sa_mask;
-};
-
-typedef struct EpollEvent EpollEvent;
-struct EpollEvent {
-       uint32  events;
-       uint32  _pad;
-       byte    data[8]; // to match amd64
-};
-#pragma pack off
diff --git a/src/runtime/defs_linux_power64.go b/src/runtime/defs_linux_power64.go
new file mode 100644 (file)
index 0000000..f90b848
--- /dev/null
@@ -0,0 +1,198 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x20
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+
+       _SA_RESTART = 0x10000000
+       _SA_ONSTACK = 0x8000000
+       _SA_SIGINFO = 0x4
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGBUS    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGUSR1   = 0xa
+       _SIGSEGV   = 0xb
+       _SIGUSR2   = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGSTKFLT = 0x10
+       _SIGCHLD   = 0x11
+       _SIGCONT   = 0x12
+       _SIGSTOP   = 0x13
+       _SIGTSTP   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGURG    = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGIO     = 0x1d
+       _SIGPWR    = 0x1e
+       _SIGSYS    = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+//struct Sigset {
+//     uint64  sig[1];
+//};
+//typedef uint64 Sigset;
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint64
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint64
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events    uint32
+       pad_cgo_0 [4]byte
+       data      [8]byte // unaligned uintptr
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+const (
+       _O_RDONLY    = 0x0
+       _O_CLOEXEC   = 0x80000
+       _SA_RESTORER = 0
+)
+
+type ptregs struct {
+       gpr       [32]uint64
+       nip       uint64
+       msr       uint64
+       orig_gpr3 uint64
+       ctr       uint64
+       link      uint64
+       xer       uint64
+       ccr       uint64
+       softe     uint64
+       trap      uint64
+       dar       uint64
+       dsisr     uint64
+       result    uint64
+}
+
+type vreg struct {
+       u [4]uint32
+}
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+       ss_size   uintptr
+}
+
+type sigcontext struct {
+       _unused     [4]uint64
+       signal      int32
+       _pad0       int32
+       handler     uint64
+       oldmask     uint64
+       regs        *ptregs
+       gp_regs     [48]uint64
+       fp_regs     [33]float64
+       v_regs      *vreg
+       vmx_reserve [101]int64
+}
+
+type ucontext struct {
+       uc_flags    uint64
+       uc_link     *ucontext
+       uc_stack    sigaltstackt
+       uc_sigmask  uint64
+       __unused    [15]uint64
+       uc_mcontext sigcontext
+}
diff --git a/src/runtime/defs_linux_power64le.go b/src/runtime/defs_linux_power64le.go
new file mode 100644 (file)
index 0000000..f90b848
--- /dev/null
@@ -0,0 +1,198 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x20
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+
+       _SA_RESTART = 0x10000000
+       _SA_ONSTACK = 0x8000000
+       _SA_SIGINFO = 0x4
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGBUS    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGUSR1   = 0xa
+       _SIGSEGV   = 0xb
+       _SIGUSR2   = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGSTKFLT = 0x10
+       _SIGCHLD   = 0x11
+       _SIGCONT   = 0x12
+       _SIGSTOP   = 0x13
+       _SIGTSTP   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGURG    = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGIO     = 0x1d
+       _SIGPWR    = 0x1e
+       _SIGSYS    = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+//struct Sigset {
+//     uint64  sig[1];
+//};
+//typedef uint64 Sigset;
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+       sa_handler  uintptr
+       sa_flags    uint64
+       sa_restorer uintptr
+       sa_mask     uint64
+}
+
+type siginfo struct {
+       si_signo int32
+       si_errno int32
+       si_code  int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint64
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events    uint32
+       pad_cgo_0 [4]byte
+       data      [8]byte // unaligned uintptr
+}
+
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+const (
+       _O_RDONLY    = 0x0
+       _O_CLOEXEC   = 0x80000
+       _SA_RESTORER = 0
+)
+
+type ptregs struct {
+       gpr       [32]uint64
+       nip       uint64
+       msr       uint64
+       orig_gpr3 uint64
+       ctr       uint64
+       link      uint64
+       xer       uint64
+       ccr       uint64
+       softe     uint64
+       trap      uint64
+       dar       uint64
+       dsisr     uint64
+       result    uint64
+}
+
+type vreg struct {
+       u [4]uint32
+}
+
+type sigaltstackt struct {
+       ss_sp     *byte
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+       ss_size   uintptr
+}
+
+type sigcontext struct {
+       _unused     [4]uint64
+       signal      int32
+       _pad0       int32
+       handler     uint64
+       oldmask     uint64
+       regs        *ptregs
+       gp_regs     [48]uint64
+       fp_regs     [33]float64
+       v_regs      *vreg
+       vmx_reserve [101]int64
+}
+
+type ucontext struct {
+       uc_flags    uint64
+       uc_link     *ucontext
+       uc_stack    sigaltstackt
+       uc_sigmask  uint64
+       __unused    [15]uint64
+       uc_mcontext sigcontext
+}
diff --git a/src/runtime/defs_nacl_386.go b/src/runtime/defs_nacl_386.go
new file mode 100644 (file)
index 0000000..4988829
--- /dev/null
@@ -0,0 +1,42 @@
+package runtime
+
+const (
+       // These values are referred to in the source code
+       // but really don't matter. Even so, use the standard numbers.
+       _SIGSEGV = 11
+       _SIGPROF = 27
+)
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int32
+}
+
+type excregs386 struct {
+       eax    uint32
+       ecx    uint32
+       edx    uint32
+       ebx    uint32
+       esp    uint32
+       ebp    uint32
+       esi    uint32
+       edi    uint32
+       eip    uint32
+       eflags uint32
+}
+
+type exccontext struct {
+       size                    uint32
+       portable_context_offset uint32
+       portable_context_size   uint32
+       arch                    uint32
+       regs_size               uint32
+       reserved                [11]uint32
+       regs                    excregs386
+}
+
+type excportablecontext struct {
+       pc uint32
+       sp uint32
+       fp uint32
+}
diff --git a/src/runtime/defs_nacl_386.h b/src/runtime/defs_nacl_386.h
deleted file mode 100644 (file)
index e8fbb38..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Created by hand, not machine generated.
-
-enum
-{
-       // These values are referred to in the source code
-       // but really don't matter. Even so, use the standard numbers.
-       SIGSEGV = 11,
-       SIGPROF = 27,
-};
-
-typedef struct Siginfo Siginfo;
-
-// native_client/src/trusted/service_runtime/include/machine/_types.h
-typedef struct Timespec Timespec;
-
-struct Timespec
-{
-       int64 tv_sec;
-       int32 tv_nsec;
-};
-
-// native_client/src/trusted/service_runtime/nacl_exception.h
-// native_client/src/include/nacl/nacl_exception.h
-
-typedef struct ExcContext ExcContext;
-typedef struct ExcPortable ExcPortable;
-typedef struct ExcRegs386 ExcRegs386;
-
-struct ExcRegs386
-{
-       uint32  eax;
-       uint32  ecx;
-       uint32  edx;
-       uint32  ebx;
-       uint32  esp;
-       uint32  ebp;
-       uint32  esi;
-       uint32  edi;
-       uint32  eip;
-       uint32  eflags;
-};
-
-struct ExcContext
-{
-       uint32  size;
-       uint32  portable_context_offset;
-       uint32  portable_context_size;
-       uint32  arch;
-       uint32  regs_size;
-       uint32  reserved[11];
-       ExcRegs386      regs;
-};
-
-struct ExcPortableContext
-{
-       uint32  pc;
-       uint32  sp;
-       uint32  fp;
-};
diff --git a/src/runtime/defs_nacl_amd64p32.go b/src/runtime/defs_nacl_amd64p32.go
new file mode 100644 (file)
index 0000000..add11fe
--- /dev/null
@@ -0,0 +1,63 @@
+package runtime
+
+const (
+       // These values are referred to in the source code
+       // but really don't matter. Even so, use the standard numbers.
+       _SIGSEGV = 11
+       _SIGPROF = 27
+)
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int32
+}
+
+type excregs386 struct {
+       eax    uint32
+       ecx    uint32
+       edx    uint32
+       ebx    uint32
+       esp    uint32
+       ebp    uint32
+       esi    uint32
+       edi    uint32
+       eip    uint32
+       eflags uint32
+}
+
+type excregsamd64 struct {
+       rax    uint64
+       rcx    uint64
+       rdx    uint64
+       rbx    uint64
+       rsp    uint64
+       rbp    uint64
+       rsi    uint64
+       rdi    uint64
+       r8     uint64
+       r9     uint64
+       r10    uint64
+       r11    uint64
+       r12    uint64
+       r13    uint64
+       r14    uint64
+       r15    uint64
+       rip    uint64
+       rflags uint32
+}
+
+type exccontext struct {
+       size                    uint32
+       portable_context_offset uint32
+       portable_context_size   uint32
+       arch                    uint32
+       regs_size               uint32
+       reserved                [11]uint32
+       regs                    excregsamd64
+}
+
+type excportablecontext struct {
+       pc uint32
+       sp uint32
+       fp uint32
+}
diff --git a/src/runtime/defs_nacl_amd64p32.h b/src/runtime/defs_nacl_amd64p32.h
deleted file mode 100644 (file)
index 45663d4..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Created by hand, not machine generated.
-
-enum
-{
-       // These values are referred to in the source code
-       // but really don't matter. Even so, use the standard numbers.
-       SIGSEGV = 11,
-       SIGPROF = 27,
-};
-
-typedef struct Siginfo Siginfo;
-
-
-// native_client/src/trusted/service_runtime/include/machine/_types.h
-typedef struct Timespec Timespec;
-
-struct Timespec
-{
-       int64 tv_sec;
-       int32 tv_nsec;
-};
-
-// native_client/src/trusted/service_runtime/nacl_exception.h
-// native_client/src/include/nacl/nacl_exception.h
-
-typedef struct ExcContext ExcContext;
-typedef struct ExcPortable ExcPortable;
-typedef struct ExcRegs386 ExcRegs386;
-typedef struct ExcRegsAmd64 ExcRegsAmd64;
-
-struct ExcRegs386
-{
-       uint32  eax;
-       uint32  ecx;
-       uint32  edx;
-       uint32  ebx;
-       uint32  esp;
-       uint32  ebp;
-       uint32  esi;
-       uint32  edi;
-       uint32  eip;
-       uint32  eflags;
-};
-
-struct ExcRegsAmd64
-{
-       uint64  rax;
-       uint64  rcx;
-       uint64  rdx;
-       uint64  rbx;
-       uint64  rsp;
-       uint64  rbp;
-       uint64  rsi;
-       uint64  rdi;
-       uint64  r8;
-       uint64  r9;
-       uint64  r10;
-       uint64  r11;
-       uint64  r12;
-       uint64  r13;
-       uint64  r14;
-       uint64  r15;
-       uint64  rip;
-       uint32  rflags;
-};
-
-struct ExcContext
-{
-       uint32  size;
-       uint32  portable_context_offset;
-       uint32  portable_context_size;
-       uint32  arch;
-       uint32  regs_size;
-       uint32  reserved[11];
-       union {
-               ExcRegs386      regs;
-               ExcRegsAmd64    regs64;
-       } regs;
-};
-
-struct ExcPortableContext
-{
-       uint32  pc;
-       uint32  sp;
-       uint32  fp;
-};
diff --git a/src/runtime/defs_nacl_arm.go b/src/runtime/defs_nacl_arm.go
new file mode 100644 (file)
index 0000000..c983cff
--- /dev/null
@@ -0,0 +1,49 @@
+package runtime
+
+const (
+       // These values are referred to in the source code
+       // but really don't matter. Even so, use the standard numbers.
+       _SIGSEGV = 11
+       _SIGPROF = 27
+)
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int32
+}
+
+type excregsarm struct {
+       r0   uint32
+       r1   uint32
+       r2   uint32
+       r3   uint32
+       r4   uint32
+       r5   uint32
+       r6   uint32
+       r7   uint32
+       r8   uint32
+       r9   uint32 // the value reported here is undefined.
+       r10  uint32
+       r11  uint32
+       r12  uint32
+       sp   uint32 /* r13 */
+       lr   uint32 /* r14 */
+       pc   uint32 /* r15 */
+       cpsr uint32
+}
+
+type exccontext struct {
+       size                    uint32
+       portable_context_offset uint32
+       portable_context_size   uint32
+       arch                    uint32
+       regs_size               uint32
+       reserved                [11]uint32
+       regs                    excregsarm
+}
+
+type excportablecontext struct {
+       pc uint32
+       sp uint32
+       fp uint32
+}
diff --git a/src/runtime/defs_nacl_arm.h b/src/runtime/defs_nacl_arm.h
deleted file mode 100644 (file)
index 9ce07cc..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Created by hand, not machine generated.
-
-enum
-{
-       // These values are referred to in the source code
-       // but really don't matter. Even so, use the standard numbers.
-       SIGSEGV = 11,
-       SIGPROF = 27,
-};
-
-typedef struct Siginfo Siginfo;
-
-// native_client/src/trusted/service_runtime/include/machine/_types.h
-typedef struct Timespec Timespec;
-
-struct Timespec
-{
-       int64 tv_sec;
-       int32 tv_nsec;
-};
-
-// native_client/src/trusted/service_runtime/nacl_exception.h
-// native_client/src/include/nacl/nacl_exception.h
-
-typedef struct ExcContext ExcContext;
-typedef struct ExcPortable ExcPortable;
-typedef struct ExcRegsARM ExcRegsARM;
-
-struct ExcRegsARM
-{
-       uint32  r0;
-       uint32  r1;
-       uint32  r2;
-       uint32  r3;
-       uint32  r4;
-       uint32  r5;
-       uint32  r6;
-       uint32  r7;
-       uint32  r8;
-       uint32  r9;     // the value reported here is undefined.
-       uint32  r10;
-       uint32  r11;
-       uint32  r12;
-       uint32  sp;     /* r13 */
-       uint32  lr;     /* r14 */
-       uint32  pc;     /* r15 */
-       uint32  cpsr;
-};
-
-struct ExcContext
-{
-       uint32  size;
-       uint32  portable_context_offset;
-       uint32  portable_context_size;
-       uint32  arch;
-       uint32  regs_size;
-       uint32  reserved[11];
-       ExcRegsARM      regs;
-};
-
-struct ExcPortableContext
-{
-       uint32  pc;
-       uint32  sp;
-       uint32  fp;
-};
diff --git a/src/runtime/defs_netbsd_386.h b/src/runtime/defs_netbsd_386.h
deleted file mode 100644 (file)
index fd87804..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_netbsd.go defs_netbsd_386.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = 0x0,
-       EVFILT_WRITE    = 0x1,
-};
-
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct SigaltstackT {
-       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 {
-       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];
-};
-
-struct KeventT {
-       uint32  ident;
-       uint32  filter;
-       uint32  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#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/runtime/defs_netbsd_amd64.h b/src/runtime/defs_netbsd_amd64.h
deleted file mode 100644 (file)
index dac94b1..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = 0x0,
-       EVFILT_WRITE    = 0x1,
-};
-
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct SigaltstackT {
-       byte    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-struct Sigset {
-       uint32  __bits[4];
-};
-struct Siginfo {
-       int32   _signo;
-       int32   _code;
-       int32   _errno;
-       int32   _pad;
-       byte    _reason[24];
-};
-
-struct StackT {
-       byte    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int32   tv_usec;
-       byte    Pad_cgo_0[4];
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-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;
-};
-
-struct KeventT {
-       uint64  ident;
-       uint32  filter;
-       uint32  flags;
-       uint32  fflags;
-       byte    Pad_cgo_0[4];
-       int64   data;
-       byte    *udata;
-};
-
-
-#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/runtime/defs_netbsd_arm.h b/src/runtime/defs_netbsd_arm.h
deleted file mode 100644 (file)
index 70f34af..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_RECEIPT      = 0,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = 0x0,
-       EVFILT_WRITE    = 0x1,
-};
-
-typedef struct SigaltstackT SigaltstackT;
-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;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct SigaltstackT {
-       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];
-};
-
-struct KeventT {
-       uint32  ident;
-       uint32  filter;
-       uint32  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go
-
-
-enum {
-       REG_R0          = 0x0,
-       REG_R1          = 0x1,
-       REG_R2          = 0x2,
-       REG_R3          = 0x3,
-       REG_R4          = 0x4,
-       REG_R5          = 0x5,
-       REG_R6          = 0x6,
-       REG_R7          = 0x7,
-       REG_R8          = 0x8,
-       REG_R9          = 0x9,
-       REG_R10         = 0xa,
-       REG_R11         = 0xb,
-       REG_R12         = 0xc,
-       REG_R13         = 0xd,
-       REG_R14         = 0xe,
-       REG_R15         = 0xf,
-       REG_CPSR        = 0x10,
-};
-
diff --git a/src/runtime/defs_openbsd_386.go b/src/runtime/defs_openbsd_386.go
new file mode 100644 (file)
index 0000000..4b60158
--- /dev/null
@@ -0,0 +1,170 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_openbsd.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type tforkt struct {
+       tf_tcb   unsafe.Pointer
+       tf_tid   *int32
+       tf_stack uintptr
+}
+
+type sigaltstackt struct {
+       ss_sp    uintptr
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type sigcontext struct {
+       sc_gs       uint32
+       sc_fs       uint32
+       sc_es       uint32
+       sc_ds       uint32
+       sc_edi      uint32
+       sc_esi      uint32
+       sc_ebp      uint32
+       sc_ebx      uint32
+       sc_edx      uint32
+       sc_ecx      uint32
+       sc_eax      uint32
+       sc_eip      uint32
+       sc_cs       uint32
+       sc_eflags   uint32
+       sc_esp      uint32
+       sc_ss       uint32
+       __sc_unused uint32
+       sc_mask     uint32
+       sc_trapno   uint32
+       sc_err      uint32
+       sc_fpstate  unsafe.Pointer
+}
+
+type siginfo struct {
+       si_signo int32
+       si_code  int32
+       si_errno int32
+       _data    [116]byte
+}
+
+type stackt struct {
+       ss_sp    uintptr
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int32
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = x
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int32
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint32
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int64
+       udata  *byte
+}
diff --git a/src/runtime/defs_openbsd_386.h b/src/runtime/defs_openbsd_386.h
deleted file mode 100644 (file)
index 6b77e00..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_openbsd.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct TforkT TforkT;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Sigcontext Sigcontext;
-typedef struct Siginfo Siginfo;
-typedef struct StackT StackT;
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct Itimerval Itimerval;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct TforkT {
-       byte    *tf_tcb;
-       int32   *tf_tid;
-       byte    *tf_stack;
-};
-
-struct SigaltstackT {
-       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_unused;
-       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];
-
-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 KeventT {
-       uint32  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_openbsd_amd64.go b/src/runtime/defs_openbsd_amd64.go
new file mode 100644 (file)
index 0000000..3c27c91
--- /dev/null
@@ -0,0 +1,181 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_openbsd.go
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _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
+
+       _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
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type tforkt struct {
+       tf_tcb   unsafe.Pointer
+       tf_tid   *int32
+       tf_stack uintptr
+}
+
+type sigaltstackt struct {
+       ss_sp     uintptr
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type sigcontext struct {
+       sc_rdi      uint64
+       sc_rsi      uint64
+       sc_rdx      uint64
+       sc_rcx      uint64
+       sc_r8       uint64
+       sc_r9       uint64
+       sc_r10      uint64
+       sc_r11      uint64
+       sc_r12      uint64
+       sc_r13      uint64
+       sc_r14      uint64
+       sc_r15      uint64
+       sc_rbp      uint64
+       sc_rbx      uint64
+       sc_rax      uint64
+       sc_gs       uint64
+       sc_fs       uint64
+       sc_es       uint64
+       sc_ds       uint64
+       sc_trapno   uint64
+       sc_err      uint64
+       sc_rip      uint64
+       sc_cs       uint64
+       sc_rflags   uint64
+       sc_rsp      uint64
+       sc_ss       uint64
+       sc_fpstate  unsafe.Pointer
+       __sc_unused int32
+       sc_mask     int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_code   int32
+       si_errno  int32
+       pad_cgo_0 [4]byte
+       _data     [120]byte
+}
+
+type stackt struct {
+       ss_sp     uintptr
+       ss_size   uintptr
+       ss_flags  int32
+       pad_cgo_0 [4]byte
+}
+
+type timespec struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+       tv_sec  int64
+       tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = int64(x)
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type keventt struct {
+       ident  uint64
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int64
+       udata  *byte
+}
diff --git a/src/runtime/defs_openbsd_amd64.h b/src/runtime/defs_openbsd_amd64.h
deleted file mode 100644 (file)
index 761e8e4..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_openbsd.go
-
-
-enum {
-       EINTR   = 0x4,
-       EFAULT  = 0xe,
-
-       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,
-
-       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,
-
-       EV_ADD          = 0x1,
-       EV_DELETE       = 0x2,
-       EV_CLEAR        = 0x20,
-       EV_ERROR        = 0x4000,
-       EVFILT_READ     = -0x1,
-       EVFILT_WRITE    = -0x2,
-};
-
-typedef struct TforkT TforkT;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Sigcontext Sigcontext;
-typedef struct Siginfo Siginfo;
-typedef struct StackT StackT;
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct Itimerval Itimerval;
-typedef struct KeventT KeventT;
-
-#pragma pack on
-
-struct TforkT {
-       byte    *tf_tcb;
-       int32   *tf_tid;
-       byte    *tf_stack;
-};
-
-struct SigaltstackT {
-       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_unused;
-       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];
-
-struct StackT {
-       byte    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct KeventT {
-       uint64  ident;
-       int16   filter;
-       uint16  flags;
-       uint32  fflags;
-       int64   data;
-       byte    *udata;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_plan9_386.go b/src/runtime/defs_plan9_386.go
new file mode 100644 (file)
index 0000000..170506b
--- /dev/null
@@ -0,0 +1,23 @@
+package runtime
+
+type ureg struct {
+       di    uint32 /* general registers */
+       si    uint32 /* ... */
+       bp    uint32 /* ... */
+       nsp   uint32
+       bx    uint32 /* ... */
+       dx    uint32 /* ... */
+       cx    uint32 /* ... */
+       ax    uint32 /* ... */
+       gs    uint32 /* data segments */
+       fs    uint32 /* ... */
+       es    uint32 /* ... */
+       ds    uint32 /* ... */
+       trap  uint32 /* trap _type */
+       ecode uint32 /* error code (or zero) */
+       pc    uint32 /* pc */
+       cs    uint32 /* old context */
+       flags uint32 /* old flags */
+       sp    uint32
+       ss    uint32 /* old stack segment */
+}
diff --git a/src/runtime/defs_plan9_386.h b/src/runtime/defs_plan9_386.h
deleted file mode 100644 (file)
index a762b85..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#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 */
-       uint32  sp;
-       uint32  ss;             /* old stack segment */
-};
diff --git a/src/runtime/defs_plan9_amd64.go b/src/runtime/defs_plan9_amd64.go
new file mode 100644 (file)
index 0000000..17becfb
--- /dev/null
@@ -0,0 +1,32 @@
+package runtime
+
+type ureg struct {
+       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 uint64
+
+       ds uint16
+       es uint16
+       fs uint16
+       gs uint16
+
+       _type uint64
+       error uint64 /* error code (or zero) */
+       ip    uint64 /* pc */
+       cs    uint64 /* old context */
+       flags uint64 /* old flags */
+       sp    uint64 /* sp */
+       ss    uint64 /* old stack segment */
+}
diff --git a/src/runtime/defs_plan9_amd64.h b/src/runtime/defs_plan9_amd64.h
deleted file mode 100644 (file)
index 20bca47..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#define PAGESIZE 0x1000
-
-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/runtime/defs_solaris_amd64.h b/src/runtime/defs_solaris_amd64.h
deleted file mode 100644 (file)
index cb1cfea..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_solaris.go defs_solaris_amd64.go
-
-
-enum {
-       EINTR           = 0x4,
-       EBADF           = 0x9,
-       EFAULT          = 0xe,
-       EAGAIN          = 0xb,
-       ETIMEDOUT       = 0x91,
-       EWOULDBLOCK     = 0xb,
-       EINPROGRESS     = 0x96,
-
-       PROT_NONE       = 0x0,
-       PROT_READ       = 0x1,
-       PROT_WRITE      = 0x2,
-       PROT_EXEC       = 0x4,
-
-       MAP_ANON        = 0x100,
-       MAP_PRIVATE     = 0x2,
-       MAP_FIXED       = 0x10,
-
-       MADV_FREE       = 0x5,
-
-       SA_SIGINFO      = 0x8,
-       SA_RESTART      = 0x4,
-       SA_ONSTACK      = 0x1,
-
-       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          = 0x15,
-       SIGSTOP         = 0x17,
-       SIGTSTP         = 0x18,
-       SIGCONT         = 0x19,
-       SIGCHLD         = 0x12,
-       SIGTTIN         = 0x1a,
-       SIGTTOU         = 0x1b,
-       SIGIO           = 0x16,
-       SIGXCPU         = 0x1e,
-       SIGXFSZ         = 0x1f,
-       SIGVTALRM       = 0x1c,
-       SIGPROF         = 0x1d,
-       SIGWINCH        = 0x14,
-       SIGUSR1         = 0x10,
-       SIGUSR2         = 0x11,
-
-       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,
-
-       _SC_NPROCESSORS_ONLN    = 0xf,
-
-       PTHREAD_CREATE_DETACHED = 0x40,
-
-       FORK_NOSIGCHLD  = 0x1,
-       FORK_WAITPID    = 0x2,
-
-       MAXHOSTNAMELEN  = 0x100,
-
-       O_NONBLOCK      = 0x80,
-       FD_CLOEXEC      = 0x1,
-       F_GETFL         = 0x3,
-       F_SETFL         = 0x4,
-       F_SETFD         = 0x2,
-
-       POLLIN  = 0x1,
-       POLLOUT = 0x4,
-       POLLHUP = 0x10,
-       POLLERR = 0x8,
-
-       PORT_SOURCE_FD  = 0x4,
-};
-
-typedef struct SemT SemT;
-typedef struct SigaltstackT SigaltstackT;
-typedef struct Sigset Sigset;
-typedef struct StackT StackT;
-typedef struct Siginfo Siginfo;
-typedef struct SigactionT SigactionT;
-typedef struct Fpregset Fpregset;
-typedef struct Mcontext Mcontext;
-typedef struct Ucontext Ucontext;
-typedef struct Timespec Timespec;
-typedef struct Timeval Timeval;
-typedef struct Itimerval Itimerval;
-typedef struct PortEvent PortEvent;
-typedef struct PthreadAttr PthreadAttr;
-typedef struct Stat Stat;
-
-#pragma pack on
-
-struct SemT {
-       uint32  sem_count;
-       uint16  sem_type;
-       uint16  sem_magic;
-       uint64  sem_pad1[3];
-       uint64  sem_pad2[2];
-};
-
-struct SigaltstackT {
-       byte    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-struct Sigset {
-       uint32  __sigbits[4];
-};
-struct StackT {
-       byte    *ss_sp;
-       uint64  ss_size;
-       int32   ss_flags;
-       byte    Pad_cgo_0[4];
-};
-
-struct Siginfo {
-       int32   si_signo;
-       int32   si_code;
-       int32   si_errno;
-       int32   si_pad;
-       byte    __data[240];
-};
-struct SigactionT {
-       int32   sa_flags;
-       byte    Pad_cgo_0[4];
-       byte    _funcptr[8];
-       Sigset  sa_mask;
-};
-
-struct Fpregset {
-       byte    fp_reg_set[528];
-};
-struct Mcontext {
-       int64   gregs[28];
-       Fpregset        fpregs;
-};
-struct Ucontext {
-       uint64  uc_flags;
-       Ucontext        *uc_link;
-       Sigset  uc_sigmask;
-       StackT  uc_stack;
-       byte    Pad_cgo_0[8];
-       Mcontext        uc_mcontext;
-       int64   uc_filler[5];
-       byte    Pad_cgo_1[8];
-};
-
-struct Timespec {
-       int64   tv_sec;
-       int64   tv_nsec;
-};
-struct Timeval {
-       int64   tv_sec;
-       int64   tv_usec;
-};
-struct Itimerval {
-       Timeval it_interval;
-       Timeval it_value;
-};
-
-struct PortEvent {
-       int32   portev_events;
-       uint16  portev_source;
-       uint16  portev_pad;
-       uint64  portev_object;
-       byte    *portev_user;
-};
-typedef        uint32  Pthread;
-struct PthreadAttr {
-       byte    *__pthread_attrp;
-};
-
-struct Stat {
-       uint64  st_dev;
-       uint64  st_ino;
-       uint32  st_mode;
-       uint32  st_nlink;
-       uint32  st_uid;
-       uint32  st_gid;
-       uint64  st_rdev;
-       int64   st_size;
-       Timespec        st_atim;
-       Timespec        st_mtim;
-       Timespec        st_ctim;
-       int32   st_blksize;
-       byte    Pad_cgo_0[4];
-       int64   st_blocks;
-       int8    st_fstype[16];
-};
-
-
-#pragma pack off
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_solaris.go defs_solaris_amd64.go
-
-
-enum {
-       REG_RDI         = 0x8,
-       REG_RSI         = 0x9,
-       REG_RDX         = 0xc,
-       REG_RCX         = 0xd,
-       REG_R8          = 0x7,
-       REG_R9          = 0x6,
-       REG_R10         = 0x5,
-       REG_R11         = 0x4,
-       REG_R12         = 0x3,
-       REG_R13         = 0x2,
-       REG_R14         = 0x1,
-       REG_R15         = 0x0,
-       REG_RBP         = 0xa,
-       REG_RBX         = 0xb,
-       REG_RAX         = 0xe,
-       REG_GS          = 0x17,
-       REG_FS          = 0x16,
-       REG_ES          = 0x18,
-       REG_DS          = 0x19,
-       REG_TRAPNO      = 0xf,
-       REG_ERR         = 0x10,
-       REG_RIP         = 0x11,
-       REG_CS          = 0x12,
-       REG_RFLAGS      = 0x13,
-       REG_RSP         = 0x14,
-       REG_SS          = 0x15,
-};
-
diff --git a/src/runtime/defs_windows_386.go b/src/runtime/defs_windows_386.go
new file mode 100644 (file)
index 0000000..abec2d8
--- /dev/null
@@ -0,0 +1,109 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_windows.go
+
+package runtime
+
+const (
+       _PROT_NONE  = 0
+       _PROT_READ  = 1
+       _PROT_WRITE = 2
+       _PROT_EXEC  = 4
+
+       _MAP_ANON    = 1
+       _MAP_PRIVATE = 2
+
+       _DUPLICATE_SAME_ACCESS   = 0x2
+       _THREAD_PRIORITY_HIGHEST = 0x2
+
+       _SIGINT           = 0x2
+       _CTRL_C_EVENT     = 0x0
+       _CTRL_BREAK_EVENT = 0x1
+
+       _CONTEXT_CONTROL = 0x10001
+       _CONTEXT_FULL    = 0x10007
+
+       _EXCEPTION_ACCESS_VIOLATION     = 0xc0000005
+       _EXCEPTION_BREAKPOINT           = 0x80000003
+       _EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d
+       _EXCEPTION_FLT_DIVIDE_BY_ZERO   = 0xc000008e
+       _EXCEPTION_FLT_INEXACT_RESULT   = 0xc000008f
+       _EXCEPTION_FLT_OVERFLOW         = 0xc0000091
+       _EXCEPTION_FLT_UNDERFLOW        = 0xc0000093
+       _EXCEPTION_INT_DIVIDE_BY_ZERO   = 0xc0000094
+       _EXCEPTION_INT_OVERFLOW         = 0xc0000095
+
+       _INFINITE     = 0xffffffff
+       _WAIT_TIMEOUT = 0x102
+
+       _EXCEPTION_CONTINUE_EXECUTION = -0x1
+       _EXCEPTION_CONTINUE_SEARCH    = 0x0
+)
+
+type systeminfo struct {
+       anon0                       [4]byte
+       dwpagesize                  uint32
+       lpminimumapplicationaddress *byte
+       lpmaximumapplicationaddress *byte
+       dwactiveprocessormask       uint32
+       dwnumberofprocessors        uint32
+       dwprocessortype             uint32
+       dwallocationgranularity     uint32
+       wprocessorlevel             uint16
+       wprocessorrevision          uint16
+}
+
+type exceptionrecord struct {
+       exceptioncode        uint32
+       exceptionflags       uint32
+       exceptionrecord      *exceptionrecord
+       exceptionaddress     *byte
+       numberparameters     uint32
+       exceptioninformation [15]uint32
+}
+
+type floatingsavearea struct {
+       controlword   uint32
+       statusword    uint32
+       tagword       uint32
+       erroroffset   uint32
+       errorselector uint32
+       dataoffset    uint32
+       dataselector  uint32
+       registerarea  [80]uint8
+       cr0npxstate   uint32
+}
+
+type context struct {
+       contextflags      uint32
+       dr0               uint32
+       dr1               uint32
+       dr2               uint32
+       dr3               uint32
+       dr6               uint32
+       dr7               uint32
+       floatsave         floatingsavearea
+       seggs             uint32
+       segfs             uint32
+       seges             uint32
+       segds             uint32
+       edi               uint32
+       esi               uint32
+       ebx               uint32
+       edx               uint32
+       ecx               uint32
+       eax               uint32
+       ebp               uint32
+       eip               uint32
+       segcs             uint32
+       eflags            uint32
+       esp               uint32
+       segss             uint32
+       extendedregisters [512]uint8
+}
+
+type overlapped struct {
+       internal     uint32
+       internalhigh uint32
+       anon0        [8]byte
+       hevent       *byte
+}
diff --git a/src/runtime/defs_windows_386.h b/src/runtime/defs_windows_386.h
deleted file mode 100644 (file)
index 2317c04..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_windows.go
-
-
-enum {
-       PROT_NONE       = 0,
-       PROT_READ       = 1,
-       PROT_WRITE      = 2,
-       PROT_EXEC       = 4,
-
-       MAP_ANON        = 1,
-       MAP_PRIVATE     = 2,
-
-       DUPLICATE_SAME_ACCESS   = 0x2,
-       THREAD_PRIORITY_HIGHEST = 0x2,
-
-       SIGINT                  = 0x2,
-       CTRL_C_EVENT            = 0x0,
-       CTRL_BREAK_EVENT        = 0x1,
-
-       CONTEXT_CONTROL = 0x10001,
-       CONTEXT_FULL    = 0x10007,
-
-       EXCEPTION_ACCESS_VIOLATION      = 0xc0000005,
-       EXCEPTION_BREAKPOINT            = 0x80000003,
-       EXCEPTION_FLT_DENORMAL_OPERAND  = 0xc000008d,
-       EXCEPTION_FLT_DIVIDE_BY_ZERO    = 0xc000008e,
-       EXCEPTION_FLT_INEXACT_RESULT    = 0xc000008f,
-       EXCEPTION_FLT_OVERFLOW          = 0xc0000091,
-       EXCEPTION_FLT_UNDERFLOW         = 0xc0000093,
-       EXCEPTION_INT_DIVIDE_BY_ZERO    = 0xc0000094,
-       EXCEPTION_INT_OVERFLOW          = 0xc0000095,
-
-       INFINITE        = 0xffffffff,
-       WAIT_TIMEOUT    = 0x102,
-
-       EXCEPTION_CONTINUE_EXECUTION    = -0x1,
-       EXCEPTION_CONTINUE_SEARCH       = 0x0,
-};
-
-typedef struct SystemInfo SystemInfo;
-typedef struct ExceptionRecord ExceptionRecord;
-typedef struct FloatingSaveArea FloatingSaveArea;
-typedef struct M128a M128a;
-typedef struct Context Context;
-typedef struct Overlapped Overlapped;
-
-#pragma pack on
-
-struct SystemInfo {
-       byte    anon0[4];
-       uint32  dwPageSize;
-       byte    *lpMinimumApplicationAddress;
-       byte    *lpMaximumApplicationAddress;
-       uint32  dwActiveProcessorMask;
-       uint32  dwNumberOfProcessors;
-       uint32  dwProcessorType;
-       uint32  dwAllocationGranularity;
-       uint16  wProcessorLevel;
-       uint16  wProcessorRevision;
-};
-struct ExceptionRecord {
-       uint32  ExceptionCode;
-       uint32  ExceptionFlags;
-       ExceptionRecord *ExceptionRecord;
-       byte    *ExceptionAddress;
-       uint32  NumberParameters;
-       uint32  ExceptionInformation[15];
-};
-struct FloatingSaveArea {
-       uint32  ControlWord;
-       uint32  StatusWord;
-       uint32  TagWord;
-       uint32  ErrorOffset;
-       uint32  ErrorSelector;
-       uint32  DataOffset;
-       uint32  DataSelector;
-       uint8   RegisterArea[80];
-       uint32  Cr0NpxState;
-};
-struct Context {
-       uint32  ContextFlags;
-       uint32  Dr0;
-       uint32  Dr1;
-       uint32  Dr2;
-       uint32  Dr3;
-       uint32  Dr6;
-       uint32  Dr7;
-       FloatingSaveArea        FloatSave;
-       uint32  SegGs;
-       uint32  SegFs;
-       uint32  SegEs;
-       uint32  SegDs;
-       uint32  Edi;
-       uint32  Esi;
-       uint32  Ebx;
-       uint32  Edx;
-       uint32  Ecx;
-       uint32  Eax;
-       uint32  Ebp;
-       uint32  Eip;
-       uint32  SegCs;
-       uint32  EFlags;
-       uint32  Esp;
-       uint32  SegSs;
-       uint8   ExtendedRegisters[512];
-};
-struct Overlapped {
-       uint32  Internal;
-       uint32  InternalHigh;
-       byte    anon0[8];
-       byte    *hEvent;
-};
-
-
-#pragma pack off
diff --git a/src/runtime/defs_windows_amd64.go b/src/runtime/defs_windows_amd64.go
new file mode 100644 (file)
index 0000000..81b1359
--- /dev/null
@@ -0,0 +1,124 @@
+// created by cgo -cdefs and then converted to Go
+// cgo -cdefs defs_windows.go
+
+package runtime
+
+const (
+       _PROT_NONE  = 0
+       _PROT_READ  = 1
+       _PROT_WRITE = 2
+       _PROT_EXEC  = 4
+
+       _MAP_ANON    = 1
+       _MAP_PRIVATE = 2
+
+       _DUPLICATE_SAME_ACCESS   = 0x2
+       _THREAD_PRIORITY_HIGHEST = 0x2
+
+       _SIGINT           = 0x2
+       _CTRL_C_EVENT     = 0x0
+       _CTRL_BREAK_EVENT = 0x1
+
+       _CONTEXT_CONTROL = 0x100001
+       _CONTEXT_FULL    = 0x10000b
+
+       _EXCEPTION_ACCESS_VIOLATION     = 0xc0000005
+       _EXCEPTION_BREAKPOINT           = 0x80000003
+       _EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d
+       _EXCEPTION_FLT_DIVIDE_BY_ZERO   = 0xc000008e
+       _EXCEPTION_FLT_INEXACT_RESULT   = 0xc000008f
+       _EXCEPTION_FLT_OVERFLOW         = 0xc0000091
+       _EXCEPTION_FLT_UNDERFLOW        = 0xc0000093
+       _EXCEPTION_INT_DIVIDE_BY_ZERO   = 0xc0000094
+       _EXCEPTION_INT_OVERFLOW         = 0xc0000095
+
+       _INFINITE     = 0xffffffff
+       _WAIT_TIMEOUT = 0x102
+
+       _EXCEPTION_CONTINUE_EXECUTION = -0x1
+       _EXCEPTION_CONTINUE_SEARCH    = 0x0
+)
+
+type systeminfo struct {
+       anon0                       [4]byte
+       dwpagesize                  uint32
+       lpminimumapplicationaddress *byte
+       lpmaximumapplicationaddress *byte
+       dwactiveprocessormask       uint64
+       dwnumberofprocessors        uint32
+       dwprocessortype             uint32
+       dwallocationgranularity     uint32
+       wprocessorlevel             uint16
+       wprocessorrevision          uint16
+}
+
+type exceptionrecord struct {
+       exceptioncode        uint32
+       exceptionflags       uint32
+       exceptionrecord      *exceptionrecord
+       exceptionaddress     *byte
+       numberparameters     uint32
+       pad_cgo_0            [4]byte
+       exceptioninformation [15]uint64
+}
+
+type m128a struct {
+       low  uint64
+       high int64
+}
+
+type context struct {
+       p1home               uint64
+       p2home               uint64
+       p3home               uint64
+       p4home               uint64
+       p5home               uint64
+       p6home               uint64
+       contextflags         uint32
+       mxcsr                uint32
+       segcs                uint16
+       segds                uint16
+       seges                uint16
+       segfs                uint16
+       seggs                uint16
+       segss                uint16
+       eflags               uint32
+       dr0                  uint64
+       dr1                  uint64
+       dr2                  uint64
+       dr3                  uint64
+       dr6                  uint64
+       dr7                  uint64
+       rax                  uint64
+       rcx                  uint64
+       rdx                  uint64
+       rbx                  uint64
+       rsp                  uint64
+       rbp                  uint64
+       rsi                  uint64
+       rdi                  uint64
+       r8                   uint64
+       r9                   uint64
+       r10                  uint64
+       r11                  uint64
+       r12                  uint64
+       r13                  uint64
+       r14                  uint64
+       r15                  uint64
+       rip                  uint64
+       anon0                [512]byte
+       vectorregister       [26]m128a
+       vectorcontrol        uint64
+       debugcontrol         uint64
+       lastbranchtorip      uint64
+       lastbranchfromrip    uint64
+       lastexceptiontorip   uint64
+       lastexceptionfromrip uint64
+}
+
+type overlapped struct {
+       internal     uint64
+       internalhigh uint64
+       anon0        [8]byte
+       hevent       *byte
+}
diff --git a/src/runtime/defs_windows_amd64.h b/src/runtime/defs_windows_amd64.h
deleted file mode 100644 (file)
index 7f37a7a..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_windows.go
-
-
-enum {
-       PROT_NONE       = 0,
-       PROT_READ       = 1,
-       PROT_WRITE      = 2,
-       PROT_EXEC       = 4,
-
-       MAP_ANON        = 1,
-       MAP_PRIVATE     = 2,
-
-       DUPLICATE_SAME_ACCESS   = 0x2,
-       THREAD_PRIORITY_HIGHEST = 0x2,
-
-       SIGINT                  = 0x2,
-       CTRL_C_EVENT            = 0x0,
-       CTRL_BREAK_EVENT        = 0x1,
-
-       CONTEXT_CONTROL = 0x100001,
-       CONTEXT_FULL    = 0x10000b,
-
-       EXCEPTION_ACCESS_VIOLATION      = 0xc0000005,
-       EXCEPTION_BREAKPOINT            = 0x80000003,
-       EXCEPTION_FLT_DENORMAL_OPERAND  = 0xc000008d,
-       EXCEPTION_FLT_DIVIDE_BY_ZERO    = 0xc000008e,
-       EXCEPTION_FLT_INEXACT_RESULT    = 0xc000008f,
-       EXCEPTION_FLT_OVERFLOW          = 0xc0000091,
-       EXCEPTION_FLT_UNDERFLOW         = 0xc0000093,
-       EXCEPTION_INT_DIVIDE_BY_ZERO    = 0xc0000094,
-       EXCEPTION_INT_OVERFLOW          = 0xc0000095,
-
-       INFINITE        = 0xffffffff,
-       WAIT_TIMEOUT    = 0x102,
-
-       EXCEPTION_CONTINUE_EXECUTION    = -0x1,
-       EXCEPTION_CONTINUE_SEARCH       = 0x0,
-};
-
-typedef struct SystemInfo SystemInfo;
-typedef struct ExceptionRecord ExceptionRecord;
-typedef struct FloatingSaveArea FloatingSaveArea;
-typedef struct M128a M128a;
-typedef struct Context Context;
-typedef struct Overlapped Overlapped;
-
-#pragma pack on
-
-struct SystemInfo {
-       byte    anon0[4];
-       uint32  dwPageSize;
-       byte    *lpMinimumApplicationAddress;
-       byte    *lpMaximumApplicationAddress;
-       uint64  dwActiveProcessorMask;
-       uint32  dwNumberOfProcessors;
-       uint32  dwProcessorType;
-       uint32  dwAllocationGranularity;
-       uint16  wProcessorLevel;
-       uint16  wProcessorRevision;
-};
-struct ExceptionRecord {
-       uint32  ExceptionCode;
-       uint32  ExceptionFlags;
-       ExceptionRecord *ExceptionRecord;
-       byte    *ExceptionAddress;
-       uint32  NumberParameters;
-       byte    Pad_cgo_0[4];
-       uint64  ExceptionInformation[15];
-};
-struct M128a {
-       uint64  Low;
-       int64   High;
-};
-struct Context {
-       uint64  P1Home;
-       uint64  P2Home;
-       uint64  P3Home;
-       uint64  P4Home;
-       uint64  P5Home;
-       uint64  P6Home;
-       uint32  ContextFlags;
-       uint32  MxCsr;
-       uint16  SegCs;
-       uint16  SegDs;
-       uint16  SegEs;
-       uint16  SegFs;
-       uint16  SegGs;
-       uint16  SegSs;
-       uint32  EFlags;
-       uint64  Dr0;
-       uint64  Dr1;
-       uint64  Dr2;
-       uint64  Dr3;
-       uint64  Dr6;
-       uint64  Dr7;
-       uint64  Rax;
-       uint64  Rcx;
-       uint64  Rdx;
-       uint64  Rbx;
-       uint64  Rsp;
-       uint64  Rbp;
-       uint64  Rsi;
-       uint64  Rdi;
-       uint64  R8;
-       uint64  R9;
-       uint64  R10;
-       uint64  R11;
-       uint64  R12;
-       uint64  R13;
-       uint64  R14;
-       uint64  R15;
-       uint64  Rip;
-       byte    anon0[512];
-       M128a   VectorRegister[26];
-       uint64  VectorControl;
-       uint64  DebugControl;
-       uint64  LastBranchToRip;
-       uint64  LastBranchFromRip;
-       uint64  LastExceptionToRip;
-       uint64  LastExceptionFromRip;
-};
-struct Overlapped {
-       uint64  Internal;
-       uint64  InternalHigh;
-       byte    anon0[8];
-       byte    *hEvent;
-};
-
-
-#pragma pack off
index dd57872d7c7affff8e893101cf899350424cbebf..03c7a5a4af265a1718f2ce6ab60dd64567d4821f 100644 (file)
@@ -8,8 +8,6 @@ package runtime
 
 import "unsafe"
 
-func environ() []string
-
 func getenv(s *byte) *byte {
        val := gogetenv(gostringnocopy(s))
        if val == "" {
@@ -32,13 +30,13 @@ func gogetenv(key string) string {
        return ""
 }
 
-var _cgo_setenv uintptr   // pointer to C function
-var _cgo_unsetenv uintptr // pointer to C function
+var _cgo_setenv unsafe.Pointer   // pointer to C function
+var _cgo_unsetenv unsafe.Pointer // pointer to C function
 
 // Update the C environment if cgo is loaded.
 // Called from syscall.Setenv.
 func syscall_setenv_c(k string, v string) {
-       if _cgo_setenv == 0 {
+       if _cgo_setenv == nil {
                return
        }
        arg := [2]unsafe.Pointer{cstring(k), cstring(v)}
@@ -48,7 +46,7 @@ func syscall_setenv_c(k string, v string) {
 // Update the C environment if cgo is loaded.
 // Called from syscall.unsetenv.
 func syscall_unsetenv_c(k string) {
-       if _cgo_unsetenv == 0 {
+       if _cgo_unsetenv == nil {
                return
        }
        arg := [1]unsafe.Pointer{cstring(k)}
index be352557fbd17b531622b05e748c5c8692493988..e871236e48f92d13372a27c762f2b502f3a5afe7 100644 (file)
@@ -34,21 +34,11 @@ func lfstackpush_m()
 func lfstackpop_m()
 
 func LFStackPush(head *uint64, node *LFNode) {
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(head)
-       mp.ptrarg[1] = unsafe.Pointer(node)
-       onM(lfstackpush_m)
-       releasem(mp)
+       lfstackpush(head, (*lfnode)(unsafe.Pointer(node)))
 }
 
 func LFStackPop(head *uint64) *LFNode {
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(head)
-       onM(lfstackpop_m)
-       node := (*LFNode)(unsafe.Pointer(mp.ptrarg[0]))
-       mp.ptrarg[0] = nil
-       releasem(mp)
-       return node
+       return (*LFNode)(unsafe.Pointer(lfstackpop(head)))
 }
 
 type ParFor struct {
@@ -68,69 +58,49 @@ func parfordo_m()
 func parforiters_m()
 
 func NewParFor(nthrmax uint32) *ParFor {
-       mp := acquirem()
-       mp.scalararg[0] = uintptr(nthrmax)
-       onM(newparfor_m)
-       desc := (*ParFor)(mp.ptrarg[0])
-       mp.ptrarg[0] = nil
-       releasem(mp)
+       var desc *ParFor
+       systemstack(func() {
+               desc = (*ParFor)(unsafe.Pointer(parforalloc(nthrmax)))
+       })
        return desc
 }
 
 func ParForSetup(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32)) {
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(desc)
-       mp.ptrarg[1] = unsafe.Pointer(ctx)
-       mp.ptrarg[2] = unsafe.Pointer(funcPC(body)) // TODO(rsc): Should be a scalar.
-       mp.scalararg[0] = uintptr(nthr)
-       mp.scalararg[1] = uintptr(n)
-       mp.scalararg[2] = 0
-       if wait {
-               mp.scalararg[2] = 1
-       }
-       onM(parforsetup_m)
-       releasem(mp)
+       systemstack(func() {
+               parforsetup((*parfor)(unsafe.Pointer(desc)), nthr, n, unsafe.Pointer(ctx), wait,
+                       *(*func(*parfor, uint32))(unsafe.Pointer(&body)))
+       })
 }
 
 func ParForDo(desc *ParFor) {
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(desc)
-       onM(parfordo_m)
-       releasem(mp)
+       systemstack(func() {
+               parfordo((*parfor)(unsafe.Pointer(desc)))
+       })
 }
 
 func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) {
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(desc)
-       mp.scalararg[0] = uintptr(tid)
-       onM(parforiters_m)
-       begin := uint32(mp.scalararg[0])
-       end := uint32(mp.scalararg[1])
-       releasem(mp)
-       return begin, end
+       desc1 := (*parfor)(unsafe.Pointer(desc))
+       pos := desc_thr_index(desc1, tid).pos
+       return uint32(pos), uint32(pos >> 32)
 }
 
-// in mgc0.c
-//go:noescape
-func getgcmask(data unsafe.Pointer, typ *_type, array **byte, len *uint)
-
 func GCMask(x interface{}) (ret []byte) {
        e := (*eface)(unsafe.Pointer(&x))
        s := (*slice)(unsafe.Pointer(&ret))
-       onM(func() {
-               getgcmask(e.data, e._type, &s.array, &s.len)
+       systemstack(func() {
+               var len uintptr
+               getgcmask(e.data, e._type, &s.array, &len)
+               s.len = uint(len)
                s.cap = s.len
        })
        return
 }
 
-func testSchedLocalQueue()
-func testSchedLocalQueueSteal()
 func RunSchedLocalQueueTest() {
-       onM(testSchedLocalQueue)
+       systemstack(testSchedLocalQueue)
 }
 func RunSchedLocalQueueStealTest() {
-       onM(testSchedLocalQueueSteal)
+       systemstack(testSchedLocalQueueSteal)
 }
 
 var HaveGoodHash = haveGoodHash
@@ -149,13 +119,9 @@ func GogoBytes() int32 {
        return _RuntimeGogoBytes
 }
 
-// in string.c
-//go:noescape
-func gostringw(w *uint16) string
-
 // entry point for testing
 func GostringW(w []uint16) (s string) {
-       onM(func() {
+       systemstack(func() {
                s = gostringw(&w[0])
        })
        return
index 6cc5df810cd6b94f12b3e11fb3206902c2f85785..34fdeb2b418779c77b7c95c6890cc003920de86e 100644 (file)
@@ -112,7 +112,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
        if xpc > f.entry && (g == nil || g.entry != funcPC(sigpanic)) {
                xpc--
        }
-       line = int(funcline(f, xpc, &file))
+       file, line32 := funcline(f, xpc)
+       line = int(line32)
        ok = true
        return
 }
diff --git a/src/runtime/float.c b/src/runtime/float.c
deleted file mode 100644 (file)
index 42082e4..0000000
+++ /dev/null
@@ -1,10 +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"
-
-// used as float64 via runtime· names
-uint64 Â·nan           = 0x7FF8000000000001ULL;
-uint64 Â·posinf        = 0x7FF0000000000000ULL;
-uint64 Â·neginf        = 0xFFF0000000000000ULL;
index d6c14fcb41a60044f74ae8b181d827bf21d99e1f..ce62dabe3e151802129b7c180db8c2625ea0222e 100644 (file)
@@ -3,9 +3,10 @@
 // license that can be found in the LICENSE file.
 
 // This file defines the IDs for PCDATA and FUNCDATA instructions
-// in Go binaries. It is included by both C and assembly, so it must
-// be written using #defines. It is included by the runtime package
-// as well as the compilers.
+// in Go binaries. It is included by assembly sources, so it must
+// be written using #defines.
+//
+// The Go compiler also #includes this file, for now.
 //
 // symtab.go also contains a copy of these constants.
 
@@ -50,8 +51,7 @@
 
 /*c2go
 enum {
-       PCDATA_ArgSize = 0,
-       PCDATA_StackMapIndex = 1,
+       PCDATA_StackMapIndex = 0,
        FUNCDATA_ArgsPointerMaps = 0,
        FUNCDATA_LocalsPointerMaps = 1,
        FUNCDATA_DeadValueMaps = 2,
index f57fc52b8d5185b7b23fd9d3a0ea9468805af7fa..b85249a5489d6ef11bee3d1446244ef3488e1ada 100644 (file)
@@ -44,9 +44,9 @@ func TestFutexsleep(t *testing.T) {
        start := time.Now()
        for _, tt := range futexsleepTests {
                go func(tt futexsleepTest) {
-                       runtime.Entersyscall()
+                       runtime.Entersyscall(0)
                        runtime.Futexsleep(&tt.mtx, tt.mtx, tt.ns)
-                       runtime.Exitsyscall()
+                       runtime.Exitsyscall(0)
                        tt.ch <- tt
                }(tt)
        }
index 88f6703f97df8f21d3a12c9b4c8fafa6c1cf007d..2b45c8184d5882bb8b8374806320cca5be1241f6 100644 (file)
@@ -62,12 +62,10 @@ func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) {
 func nonStackInfo(mask []byte) []byte {
        // BitsDead is replaced with BitsScalar everywhere except stacks.
        mask1 := make([]byte, len(mask))
-       mw := false
        for i, v := range mask {
-               if !mw && v == BitsDead {
+               if v == BitsDead {
                        v = BitsScalar
                }
-               mw = !mw && v == BitsMultiWord
                mask1[i] = v
        }
        return mask1
@@ -84,7 +82,6 @@ const (
        BitsDead = iota
        BitsScalar
        BitsPointer
-       BitsMultiWord
 )
 
 const (
@@ -137,7 +134,7 @@ func infoBigStruct() []byte {
                        BitsScalar, BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64
                        BitsPointer, BitsDead, // i string
                }
-       case "amd64":
+       case "amd64", "power64", "power64le":
                return []byte{
                        BitsPointer,                        // q *int
                        BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte
@@ -188,6 +185,6 @@ var (
 
        infoString = []byte{BitsPointer, BitsDead}
        infoSlice  = []byte{BitsPointer, BitsDead, BitsDead}
-       infoEface  = []byte{BitsMultiWord, BitsEface}
-       infoIface  = []byte{BitsMultiWord, BitsIface}
+       infoEface  = []byte{BitsPointer, BitsPointer}
+       infoIface  = []byte{BitsPointer, BitsPointer}
 )
diff --git a/src/runtime/gengoos.go b/src/runtime/gengoos.go
new file mode 100644 (file)
index 0000000..029575b
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "log"
+       "strconv"
+       "strings"
+)
+
+var gooses, goarches []string
+
+func main() {
+       data, err := ioutil.ReadFile("../go/build/syslist.go")
+       if err != nil {
+               log.Fatal(err)
+       }
+       const (
+               goosPrefix   = `const goosList = `
+               goarchPrefix = `const goarchList = `
+       )
+       for _, line := range strings.Split(string(data), "\n") {
+               if strings.HasPrefix(line, goosPrefix) {
+                       text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix))
+                       if err != nil {
+                               log.Fatalf("parsing goosList %#q: %v", strings.TrimPrefix(line, goosPrefix), err)
+                       }
+                       gooses = strings.Fields(text)
+               }
+               if strings.HasPrefix(line, goarchPrefix) {
+                       text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix))
+                       if err != nil {
+                               log.Fatal("parsing goarchList: %v", err)
+                       }
+                       goarches = strings.Fields(text)
+               }
+       }
+
+       for _, target := range gooses {
+               var buf bytes.Buffer
+               fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
+               fmt.Fprintf(&buf, "// +build %s\n\n", target) // usually redundant, but not always; see linux vs android
+               fmt.Fprintf(&buf, "package runtime\n\n")
+               fmt.Fprintf(&buf, "const theGoos = `%s`\n\n", target)
+               for _, goos := range gooses {
+                       value := 0
+                       if goos == target {
+                               value = 1
+                       }
+                       fmt.Fprintf(&buf, "const goos_%s = %d\n", goos, value)
+               }
+               err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       }
+
+       for _, target := range goarches {
+               var buf bytes.Buffer
+               fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
+               fmt.Fprintf(&buf, "package runtime\n\n")
+               fmt.Fprintf(&buf, "const theGoarch = `%s`\n\n", target)
+               for _, goarch := range goarches {
+                       value := 0
+                       if goarch == target {
+                               value = 1
+                       }
+                       fmt.Fprintf(&buf, "const goarch_%s = %d\n", goarch, value)
+               }
+               err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
+               if err != nil {
+                       log.Fatal(err)
+               }
+       }
+}
diff --git a/src/runtime/go_tls.h b/src/runtime/go_tls.h
new file mode 100644 (file)
index 0000000..6a707cf
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifdef GOARCH_arm
+#define LR R14
+#endif
+
+#ifdef GOARCH_amd64
+#define        get_tls(r)      MOVQ TLS, r
+#define        g(r)    0(r)(TLS*1)
+#endif
+
+#ifdef GOARCH_amd64p32
+#define        get_tls(r)      MOVL TLS, r
+#define        g(r)    0(r)(TLS*1)
+#endif
+
+#ifdef GOARCH_386
+#define        get_tls(r)      MOVL TLS, r
+#define        g(r)    0(r)(TLS*1)
+#endif
diff --git a/src/runtime/heapdump.c b/src/runtime/heapdump.c
deleted file mode 100644 (file)
index 7eba8c0..0000000
+++ /dev/null
@@ -1,864 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Implementation of runtime/debug.WriteHeapDump.  Writes all
-// objects in the heap plus additional info (roots, threads,
-// finalizers, etc.) to a file.
-
-// The format of the dumped file is described at
-// http://golang.org/s/go14heapdump.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "mgc0.h"
-#include "type.h"
-#include "typekind.h"
-#include "funcdata.h"
-#include "zaexperiment.h"
-#include "textflag.h"
-
-extern byte runtime·data[];
-extern byte runtime·edata[];
-extern byte runtime·bss[];
-extern byte runtime·ebss[];
-
-enum {
-       FieldKindEol = 0,
-       FieldKindPtr = 1,
-       FieldKindIface = 2,
-       FieldKindEface = 3,
-
-       TagEOF = 0,
-       TagObject = 1,
-       TagOtherRoot = 2,
-       TagType = 3,
-       TagGoRoutine = 4,
-       TagStackFrame = 5,
-       TagParams = 6,
-       TagFinalizer = 7,
-       TagItab = 8,
-       TagOSThread = 9,
-       TagMemStats = 10,
-       TagQueuedFinalizer = 11,
-       TagData = 12,
-       TagBss = 13,
-       TagDefer = 14,
-       TagPanic = 15,
-       TagMemProf = 16,
-       TagAllocSample = 17,
-};
-
-static uintptr* playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg);
-static void dumpfields(BitVector bv);
-static void dumpbvtypes(BitVector *bv, byte *base);
-static BitVector makeheapobjbv(byte *p, uintptr size);
-
-// fd to write the dump to.
-static uintptr dumpfd;
-
-#pragma dataflag NOPTR /* tmpbuf not a heap pointer at least */
-static byte    *tmpbuf;
-static uintptr tmpbufsize;
-
-// buffer of pending write data
-enum {
-       BufSize = 4096,
-};
-#pragma dataflag NOPTR
-static byte buf[BufSize];
-static uintptr nbuf;
-
-static void
-write(byte *data, uintptr len)
-{
-       if(len + nbuf <= BufSize) {
-               runtime·memmove(buf + nbuf, data, len);
-               nbuf += len;
-               return;
-       }
-       runtime·write(dumpfd, buf, nbuf);
-       if(len >= BufSize) {
-               runtime·write(dumpfd, data, len);
-               nbuf = 0;
-       } else {
-               runtime·memmove(buf, data, len);
-               nbuf = len;
-       }
-}
-
-static void
-flush(void)
-{
-       runtime·write(dumpfd, buf, nbuf);
-       nbuf = 0;
-}
-
-// Cache of types that have been serialized already.
-// We use a type's hash field to pick a bucket.
-// Inside a bucket, we keep a list of types that
-// have been serialized so far, most recently used first.
-// Note: when a bucket overflows we may end up
-// serializing a type more than once.  That's ok.
-enum {
-       TypeCacheBuckets = 256, // must be a power of 2
-       TypeCacheAssoc = 4,
-};
-typedef struct TypeCacheBucket TypeCacheBucket;
-struct TypeCacheBucket {
-       Type *t[TypeCacheAssoc];
-};
-#pragma dataflag NOPTR /* only initialized and used while world is stopped */
-static TypeCacheBucket typecache[TypeCacheBuckets];
-
-// dump a uint64 in a varint format parseable by encoding/binary
-static void
-dumpint(uint64 v)
-{
-       byte buf[10];
-       int32 n;
-       n = 0;
-       while(v >= 0x80) {
-               buf[n++] = v | 0x80;
-               v >>= 7;
-       }
-       buf[n++] = v;
-       write(buf, n);
-}
-
-static void
-dumpbool(bool b)
-{
-       dumpint(b ? 1 : 0);
-}
-
-// dump varint uint64 length followed by memory contents
-static void
-dumpmemrange(byte *data, uintptr len)
-{
-       dumpint(len);
-       write(data, len);
-}
-
-static void
-dumpstr(String s)
-{
-       dumpmemrange(s.str, s.len);
-}
-
-static void
-dumpcstr(int8 *c)
-{
-       dumpmemrange((byte*)c, runtime·findnull((byte*)c));
-}
-
-// dump information for a type
-static void
-dumptype(Type *t)
-{
-       TypeCacheBucket *b;
-       int32 i, j;
-
-       if(t == nil) {
-               return;
-       }
-
-       // If we've definitely serialized the type before,
-       // no need to do it again.
-       b = &typecache[t->hash & (TypeCacheBuckets-1)];
-       if(t == b->t[0]) return;
-       for(i = 1; i < TypeCacheAssoc; i++) {
-               if(t == b->t[i]) {
-                       // Move-to-front
-                       for(j = i; j > 0; j--) {
-                               b->t[j] = b->t[j-1];
-                       }
-                       b->t[0] = t;
-                       return;
-               }
-       }
-       // Might not have been dumped yet.  Dump it and
-       // remember we did so.
-       for(j = TypeCacheAssoc-1; j > 0; j--) {
-               b->t[j] = b->t[j-1];
-       }
-       b->t[0] = t;
-       
-       // dump the type
-       dumpint(TagType);
-       dumpint((uintptr)t);
-       dumpint(t->size);
-       if(t->x == nil || t->x->pkgPath == nil || t->x->name == nil) {
-               dumpstr(*t->string);
-       } else {
-               dumpint(t->x->pkgPath->len + 1 + t->x->name->len);
-               write(t->x->pkgPath->str, t->x->pkgPath->len);
-               write((byte*)".", 1);
-               write(t->x->name->str, t->x->name->len);
-       }
-       dumpbool((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0);
-}
-
-// dump an object
-static void
-dumpobj(byte *obj, uintptr size, BitVector bv)
-{
-       dumpbvtypes(&bv, obj);
-       dumpint(TagObject);
-       dumpint((uintptr)obj);
-       dumpmemrange(obj, size);
-       dumpfields(bv);
-}
-
-static void
-dumpotherroot(int8 *description, byte *to)
-{
-       dumpint(TagOtherRoot);
-       dumpcstr(description);
-       dumpint((uintptr)to);
-}
-
-static void
-dumpfinalizer(byte *obj, FuncVal *fn, Type* fint, PtrType *ot)
-{
-       dumpint(TagFinalizer);
-       dumpint((uintptr)obj);
-       dumpint((uintptr)fn);
-       dumpint((uintptr)fn->fn);
-       dumpint((uintptr)fint);
-       dumpint((uintptr)ot);
-}
-
-typedef struct ChildInfo ChildInfo;
-struct ChildInfo {
-       // Information passed up from the callee frame about
-       // the layout of the outargs region.
-       uintptr argoff;     // where the arguments start in the frame
-       uintptr arglen;     // size of args region
-       BitVector args;    // if args.n >= 0, pointer map of args region
-
-       byte *sp;           // callee sp
-       uintptr depth;      // depth in call stack (0 == most recent)
-};
-
-// dump kinds & offsets of interesting fields in bv
-static void
-dumpbv(BitVector *bv, uintptr offset)
-{
-       uintptr i;
-
-       for(i = 0; i < bv->n; i += BitsPerPointer) {
-               switch(bv->bytedata[i/8] >> i%8 & 3) {
-               case BitsDead:
-                       // BitsDead has already been processed in makeheapobjbv.
-                       // We should only see it in stack maps, in which case we should continue processing.
-                       break;
-               case BitsScalar:
-                       break;
-               case BitsPointer:
-                       dumpint(FieldKindPtr);
-                       dumpint(offset + i / BitsPerPointer * PtrSize);
-                       break;
-               case BitsMultiWord:
-                       switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) {
-                       default:
-                               runtime·throw("unexpected garbage collection bits");
-                       case BitsIface:
-                               dumpint(FieldKindIface);
-                               dumpint(offset + i / BitsPerPointer * PtrSize);
-                               i += BitsPerPointer;
-                               break;
-                       case BitsEface:
-                               dumpint(FieldKindEface);
-                               dumpint(offset + i / BitsPerPointer * PtrSize);
-                               i += BitsPerPointer;
-                               break;
-                       }
-               }
-       }
-}
-
-static bool
-dumpframe(Stkframe *s, void *arg)
-{
-       Func *f;
-       ChildInfo *child;
-       uintptr pc, off, size;
-       int32 pcdata;
-       StackMap *stackmap;
-       int8 *name;
-       BitVector bv;
-
-       child = (ChildInfo*)arg;
-       f = s->fn;
-
-       // Figure out what we can about our stack map
-       pc = s->pc;
-       if(pc != f->entry)
-               pc--;
-       pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, pc);
-       if(pcdata == -1) {
-               // We do not have a valid pcdata value but there might be a
-               // stackmap for this function.  It is likely that we are looking
-               // at the function prologue, assume so and hope for the best.
-               pcdata = 0;
-       }
-       stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
-
-       // Dump any types we will need to resolve Efaces.
-       if(child->args.n >= 0)
-               dumpbvtypes(&child->args, (byte*)s->sp + child->argoff);
-       if(stackmap != nil && stackmap->n > 0) {
-               bv = runtime·stackmapdata(stackmap, pcdata);
-               dumpbvtypes(&bv, (byte*)(s->varp - bv.n / BitsPerPointer * PtrSize));
-       } else {
-               bv.n = -1;
-       }
-
-       // Dump main body of stack frame.
-       dumpint(TagStackFrame);
-       dumpint(s->sp); // lowest address in frame
-       dumpint(child->depth); // # of frames deep on the stack
-       dumpint((uintptr)child->sp); // sp of child, or 0 if bottom of stack
-       dumpmemrange((byte*)s->sp, s->fp - s->sp);  // frame contents
-       dumpint(f->entry);
-       dumpint(s->pc);
-       dumpint(s->continpc);
-       name = runtime·funcname(f);
-       if(name == nil)
-               name = "unknown function";
-       dumpcstr(name);
-
-       // Dump fields in the outargs section
-       if(child->args.n >= 0) {
-               dumpbv(&child->args, child->argoff);
-       } else {
-               // conservative - everything might be a pointer
-               for(off = child->argoff; off < child->argoff + child->arglen; off += PtrSize) {
-                       dumpint(FieldKindPtr);
-                       dumpint(off);
-               }
-       }
-
-       // Dump fields in the local vars section
-       if(stackmap == nil) {
-               // No locals information, dump everything.
-               for(off = child->arglen; off < s->varp - s->sp; off += PtrSize) {
-                       dumpint(FieldKindPtr);
-                       dumpint(off);
-               }
-       } else if(stackmap->n < 0) {
-               // Locals size information, dump just the locals.
-               size = -stackmap->n;
-               for(off = s->varp - size - s->sp; off <  s->varp - s->sp; off += PtrSize) {
-                       dumpint(FieldKindPtr);
-                       dumpint(off);
-               }
-       } else if(stackmap->n > 0) {
-               // Locals bitmap information, scan just the pointers in
-               // locals.
-               dumpbv(&bv, s->varp - bv.n / BitsPerPointer * PtrSize - s->sp);
-       }
-       dumpint(FieldKindEol);
-
-       // Record arg info for parent.
-       child->argoff = s->argp - s->fp;
-       child->arglen = s->arglen;
-       child->sp = (byte*)s->sp;
-       child->depth++;
-       stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
-       if(stackmap != nil)
-               child->args = runtime·stackmapdata(stackmap, pcdata);
-       else
-               child->args.n = -1;
-       return true;
-}
-
-static void
-dumpgoroutine(G *gp)
-{
-       uintptr sp, pc, lr;
-       ChildInfo child;
-       Defer *d;
-       Panic *p;
-       bool (*fn)(Stkframe*, void*);
-
-       if(gp->syscallsp != (uintptr)nil) {
-               sp = gp->syscallsp;
-               pc = gp->syscallpc;
-               lr = 0;
-       } else {
-               sp = gp->sched.sp;
-               pc = gp->sched.pc;
-               lr = gp->sched.lr;
-       }
-
-       dumpint(TagGoRoutine);
-       dumpint((uintptr)gp);
-       dumpint((uintptr)sp);
-       dumpint(gp->goid);
-       dumpint(gp->gopc);
-       dumpint(runtime·readgstatus(gp));
-       dumpbool(gp->issystem);
-       dumpbool(false);  // isbackground
-       dumpint(gp->waitsince);
-       dumpstr(gp->waitreason);
-       dumpint((uintptr)gp->sched.ctxt);
-       dumpint((uintptr)gp->m);
-       dumpint((uintptr)gp->defer);
-       dumpint((uintptr)gp->panic);
-
-       // dump stack
-       child.args.n = -1;
-       child.arglen = 0;
-       child.sp = nil;
-       child.depth = 0;
-       fn = dumpframe;
-       runtime·gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, &fn, &child, 0);
-
-       // dump defer & panic records
-       for(d = gp->defer; d != nil; d = d->link) {
-               dumpint(TagDefer);
-               dumpint((uintptr)d);
-               dumpint((uintptr)gp);
-               dumpint((uintptr)d->argp);
-               dumpint((uintptr)d->pc);
-               dumpint((uintptr)d->fn);
-               dumpint((uintptr)d->fn->fn);
-               dumpint((uintptr)d->link);
-       }
-       for (p = gp->panic; p != nil; p = p->link) {
-               dumpint(TagPanic);
-               dumpint((uintptr)p);
-               dumpint((uintptr)gp);
-               dumpint((uintptr)p->arg.type);
-               dumpint((uintptr)p->arg.data);
-               dumpint(0); // was p->defer, no longer recorded
-               dumpint((uintptr)p->link);
-       }
-}
-
-static void
-dumpgs(void)
-{
-       G *gp;
-       uint32 i;
-       uint32 status;
-
-       // goroutines & stacks
-       for(i = 0; i < runtime·allglen; i++) {
-               gp = runtime·allg[i];
-               status = runtime·readgstatus(gp); // The world is stopped so gp will not be in a scan state.
-               switch(status){
-               default:
-                       runtime·printf("runtime: unexpected G.status %d\n", status);
-                       runtime·throw("dumpgs in STW - bad status");
-               case Gdead:
-                       break;
-               case Grunnable:
-               case Gsyscall:
-               case Gwaiting:
-                       dumpgoroutine(gp);
-                       break;
-               }
-       }
-}
-
-static void
-finq_callback(FuncVal *fn, byte *obj, uintptr nret, Type *fint, PtrType *ot)
-{
-       dumpint(TagQueuedFinalizer);
-       dumpint((uintptr)obj);
-       dumpint((uintptr)fn);
-       dumpint((uintptr)fn->fn);
-       dumpint((uintptr)fint);
-       dumpint((uintptr)ot);
-       USED(&nret);
-}
-
-
-static void
-dumproots(void)
-{
-       MSpan *s, **allspans;
-       uint32 spanidx;
-       Special *sp;
-       SpecialFinalizer *spf;
-       byte *p;
-
-       // data segment
-       dumpbvtypes(&runtime·gcdatamask, runtime·data);
-       dumpint(TagData);
-       dumpint((uintptr)runtime·data);
-       dumpmemrange(runtime·data, runtime·edata - runtime·data);
-       dumpfields(runtime·gcdatamask);
-
-       // bss segment
-       dumpbvtypes(&runtime·gcbssmask, runtime·bss);
-       dumpint(TagBss);
-       dumpint((uintptr)runtime·bss);
-       dumpmemrange(runtime·bss, runtime·ebss - runtime·bss);
-       dumpfields(runtime·gcbssmask);
-
-       // MSpan.types
-       allspans = runtime·mheap.allspans;
-       for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
-               s = allspans[spanidx];
-               if(s->state == MSpanInUse) {
-                       // Finalizers
-                       for(sp = s->specials; sp != nil; sp = sp->next) {
-                               if(sp->kind != KindSpecialFinalizer)
-                                       continue;
-                               spf = (SpecialFinalizer*)sp;
-                               p = (byte*)((s->start << PageShift) + spf->special.offset);
-                               dumpfinalizer(p, spf->fn, spf->fint, spf->ot);
-                       }
-               }
-       }
-
-       // Finalizer queue
-       runtime·iterate_finq(finq_callback);
-}
-
-// Bit vector of free marks.   
-// Needs to be as big as the largest number of objects per span.       
-#pragma dataflag NOPTR
-static byte free[PageSize/8];  
-
-static void
-dumpobjs(void)
-{
-       uintptr i, j, size, n;
-       MSpan *s;
-       MLink *l;
-       byte *p;
-
-       for(i = 0; i < runtime·mheap.nspan; i++) {
-               s = runtime·mheap.allspans[i];
-               if(s->state != MSpanInUse)
-                       continue;
-               p = (byte*)(s->start << PageShift);
-               size = s->elemsize;
-               n = (s->npages << PageShift) / size;
-               if(n > nelem(free))     
-                       runtime·throw("free array doesn't have enough entries");       
-               for(l = s->freelist; l != nil; l = l->next)
-                       free[((byte*)l - p) / size] = true;     
-               for(j = 0; j < n; j++, p += size) {
-                       if(free[j]) {   
-                               free[j] = false;        
-                               continue;       
-                       }
-                       dumpobj(p, size, makeheapobjbv(p, size));
-               }
-       }
-}
-
-static void
-dumpparams(void)
-{
-       byte *x;
-
-       dumpint(TagParams);
-       x = (byte*)1;
-       if(*(byte*)&x == 1)
-               dumpbool(false); // little-endian ptrs
-       else
-               dumpbool(true); // big-endian ptrs
-       dumpint(PtrSize);
-       dumpint((uintptr)runtime·mheap.arena_start);
-       dumpint((uintptr)runtime·mheap.arena_used);
-       dumpint(thechar);
-       dumpcstr(GOEXPERIMENT);
-       dumpint(runtime·ncpu);
-}
-
-static void
-itab_callback(Itab *tab)
-{
-       Type *t;
-
-       t = tab->type;
-       // Dump a map from itab* to the type of its data field.
-       // We want this map so we can deduce types of interface referents.
-       if((t->kind & KindDirectIface) == 0) {
-               // indirect - data slot is a pointer to t.
-               dumptype(t->ptrto);
-               dumpint(TagItab);
-               dumpint((uintptr)tab);
-               dumpint((uintptr)t->ptrto);
-       } else if((t->kind & KindNoPointers) == 0) {
-               // t is pointer-like - data slot is a t.
-               dumptype(t);
-               dumpint(TagItab);
-               dumpint((uintptr)tab);
-               dumpint((uintptr)t);
-       } else {
-               // Data slot is a scalar.  Dump type just for fun.
-               // With pointer-only interfaces, this shouldn't happen.
-               dumptype(t);
-               dumpint(TagItab);
-               dumpint((uintptr)tab);
-               dumpint((uintptr)t);
-       }
-}
-
-static void
-dumpitabs(void)
-{
-       void (*fn)(Itab*);
-       
-       fn = itab_callback;
-       runtime·iterate_itabs(&fn);
-}
-
-static void
-dumpms(void)
-{
-       M *mp;
-
-       for(mp = runtime·allm; mp != nil; mp = mp->alllink) {
-               dumpint(TagOSThread);
-               dumpint((uintptr)mp);
-               dumpint(mp->id);
-               dumpint(mp->procid);
-       }
-}
-
-static void
-dumpmemstats(void)
-{
-       int32 i;
-
-       dumpint(TagMemStats);
-       dumpint(mstats.alloc);
-       dumpint(mstats.total_alloc);
-       dumpint(mstats.sys);
-       dumpint(mstats.nlookup);
-       dumpint(mstats.nmalloc);
-       dumpint(mstats.nfree);
-       dumpint(mstats.heap_alloc);
-       dumpint(mstats.heap_sys);
-       dumpint(mstats.heap_idle);
-       dumpint(mstats.heap_inuse);
-       dumpint(mstats.heap_released);
-       dumpint(mstats.heap_objects);
-       dumpint(mstats.stacks_inuse);
-       dumpint(mstats.stacks_sys);
-       dumpint(mstats.mspan_inuse);
-       dumpint(mstats.mspan_sys);
-       dumpint(mstats.mcache_inuse);
-       dumpint(mstats.mcache_sys);
-       dumpint(mstats.buckhash_sys);
-       dumpint(mstats.gc_sys);
-       dumpint(mstats.other_sys);
-       dumpint(mstats.next_gc);
-       dumpint(mstats.last_gc);
-       dumpint(mstats.pause_total_ns);
-       for(i = 0; i < 256; i++)
-               dumpint(mstats.pause_ns[i]);
-       dumpint(mstats.numgc);
-}
-
-static void
-dumpmemprof_callback(Bucket *b, uintptr nstk, uintptr *stk, uintptr size, uintptr allocs, uintptr frees)
-{
-       uintptr i, pc;
-       Func *f;
-       byte buf[20];
-       String file;
-       int32 line;
-
-       dumpint(TagMemProf);
-       dumpint((uintptr)b);
-       dumpint(size);
-       dumpint(nstk);
-       for(i = 0; i < nstk; i++) {
-               pc = stk[i];
-               f = runtime·findfunc(pc);
-               if(f == nil) {
-                       runtime·snprintf(buf, sizeof(buf), "%X", (uint64)pc);
-                       dumpcstr((int8*)buf);
-                       dumpcstr("?");
-                       dumpint(0);
-               } else {
-                       dumpcstr(runtime·funcname(f));
-                       // TODO: Why do we need to back up to a call instruction here?
-                       // Maybe profiler should do this.
-                       if(i > 0 && pc > f->entry) {
-                               if(thechar == '6' || thechar == '8')
-                                       pc--;
-                               else
-                                       pc -= 4; // arm, etc
-                       }
-                       line = runtime·funcline(f, pc, &file);
-                       dumpstr(file);
-                       dumpint(line);
-               }
-       }
-       dumpint(allocs);
-       dumpint(frees);
-}
-
-static void
-dumpmemprof(void)
-{
-       MSpan *s, **allspans;
-       uint32 spanidx;
-       Special *sp;
-       SpecialProfile *spp;
-       byte *p;
-       void (*fn)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr);
-       
-       fn = dumpmemprof_callback;
-       runtime·iterate_memprof(&fn);
-
-       allspans = runtime·mheap.allspans;
-       for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
-               s = allspans[spanidx];
-               if(s->state != MSpanInUse)
-                       continue;
-               for(sp = s->specials; sp != nil; sp = sp->next) {
-                       if(sp->kind != KindSpecialProfile)
-                               continue;
-                       spp = (SpecialProfile*)sp;
-                       p = (byte*)((s->start << PageShift) + spp->special.offset);
-                       dumpint(TagAllocSample);
-                       dumpint((uintptr)p);
-                       dumpint((uintptr)spp->b);
-               }
-       }
-}
-
-static void
-mdump(void)
-{
-       byte *hdr;
-       uintptr i;
-       MSpan *s;
-
-       // make sure we're done sweeping
-       for(i = 0; i < runtime·mheap.nspan; i++) {
-               s = runtime·mheap.allspans[i];
-               if(s->state == MSpanInUse)
-                       runtime·MSpan_EnsureSwept(s);
-       }
-
-       runtime·memclr((byte*)&typecache[0], sizeof(typecache));
-       hdr = (byte*)"go1.4 heap dump\n";
-       write(hdr, runtime·findnull(hdr));
-       dumpparams();
-       dumpitabs();
-       dumpobjs();
-       dumpgs();
-       dumpms();
-       dumproots();
-       dumpmemstats();
-       dumpmemprof();
-       dumpint(TagEOF);
-       flush();
-}
-
-void
-runtime·writeheapdump_m(void)
-{
-       uintptr fd;
-       
-       fd = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-
-       runtime·casgstatus(g->m->curg, Grunning, Gwaiting);
-       g->waitreason = runtime·gostringnocopy((byte*)"dumping heap");
-
-       // Update stats so we can dump them.
-       // As a side effect, flushes all the MCaches so the MSpan.freelist
-       // lists contain all the free objects.
-       runtime·updatememstats(nil);
-
-       // Set dump file.
-       dumpfd = fd;
-
-       // Call dump routine.
-       mdump();
-
-       // Reset dump file.
-       dumpfd = 0;
-       if(tmpbuf != nil) {
-               runtime·SysFree(tmpbuf, tmpbufsize, &mstats.other_sys);
-               tmpbuf = nil;
-               tmpbufsize = 0;
-       }
-
-       runtime·casgstatus(g->m->curg, Gwaiting, Grunning);
-}
-
-// dumpint() the kind & offset of each field in an object.
-static void
-dumpfields(BitVector bv)
-{
-       dumpbv(&bv, 0);
-       dumpint(FieldKindEol);
-}
-
-// The heap dump reader needs to be able to disambiguate
-// Eface entries.  So it needs to know every type that might
-// appear in such an entry.  The following routine accomplishes that.
-
-// Dump all the types that appear in the type field of
-// any Eface described by this bit vector.
-static void
-dumpbvtypes(BitVector *bv, byte *base)
-{
-       uintptr i;
-
-       for(i = 0; i < bv->n; i += BitsPerPointer) {
-               if((bv->bytedata[i/8] >> i%8 & 3) != BitsMultiWord)
-                       continue;
-               switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) {
-               default:
-                       runtime·throw("unexpected garbage collection bits");
-               case BitsIface:
-                       i += BitsPerPointer;
-                       break;
-               case BitsEface:
-                       dumptype(*(Type**)(base + i / BitsPerPointer * PtrSize));
-                       i += BitsPerPointer;
-                       break;
-               }
-       }
-}
-
-static BitVector
-makeheapobjbv(byte *p, uintptr size)
-{
-       uintptr off, nptr, i;
-       byte shift, *bitp, bits;
-       bool mw;
-
-       // Extend the temp buffer if necessary.
-       nptr = size/PtrSize;
-       if(tmpbufsize < nptr*BitsPerPointer/8+1) {
-               if(tmpbuf != nil)
-                       runtime·SysFree(tmpbuf, tmpbufsize, &mstats.other_sys);
-               tmpbufsize = nptr*BitsPerPointer/8+1;
-               tmpbuf = runtime·sysAlloc(tmpbufsize, &mstats.other_sys);
-               if(tmpbuf == nil)
-                       runtime·throw("heapdump: out of memory");
-       }
-
-       // Copy and compact the bitmap.
-       mw = false;
-       for(i = 0; i < nptr; i++) {
-               off = (uintptr*)(p + i*PtrSize) - (uintptr*)runtime·mheap.arena_start;
-               bitp = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
-               shift = (off % wordsPerBitmapByte) * gcBits;
-               bits = (*bitp >> (shift + 2)) & BitsMask;
-               if(!mw && bits == BitsDead)
-                       break;  // end of heap object
-               mw = !mw && bits == BitsMultiWord;
-               tmpbuf[i*BitsPerPointer/8] &= ~(BitsMask<<((i*BitsPerPointer)%8));
-               tmpbuf[i*BitsPerPointer/8] |= bits<<((i*BitsPerPointer)%8);
-       }
-       return (BitVector){i*BitsPerPointer, tmpbuf};
-}
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go
new file mode 100644 (file)
index 0000000..0c1a60c
--- /dev/null
@@ -0,0 +1,729 @@
+// Copyright 2014 The Go 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 runtime/debug.WriteHeapDump.  Writes all
+// objects in the heap plus additional info (roots, threads,
+// finalizers, etc.) to a file.
+
+// The format of the dumped file is described at
+// http://golang.org/s/go14heapdump.
+
+package runtime
+
+import "unsafe"
+
+const (
+       fieldKindEol       = 0
+       fieldKindPtr       = 1
+       fieldKindIface     = 2
+       fieldKindEface     = 3
+       tagEOF             = 0
+       tagObject          = 1
+       tagOtherRoot       = 2
+       tagType            = 3
+       tagGoroutine       = 4
+       tagStackFrame      = 5
+       tagParams          = 6
+       tagFinalizer       = 7
+       tagItab            = 8
+       tagOSThread        = 9
+       tagMemStats        = 10
+       tagQueuedFinalizer = 11
+       tagData            = 12
+       tagBSS             = 13
+       tagDefer           = 14
+       tagPanic           = 15
+       tagMemProf         = 16
+       tagAllocSample     = 17
+)
+
+var dumpfd uintptr // fd to write the dump to.
+var tmpbuf []byte
+
+// buffer of pending write data
+const (
+       bufSize = 4096
+)
+
+var buf [bufSize]byte
+var nbuf uintptr
+
+func dwrite(data unsafe.Pointer, len uintptr) {
+       if len == 0 {
+               return
+       }
+       if nbuf+len <= bufSize {
+               copy(buf[nbuf:], (*[bufSize]byte)(data)[:len])
+               nbuf += len
+               return
+       }
+
+       write(dumpfd, (unsafe.Pointer)(&buf), int32(nbuf))
+       if len >= bufSize {
+               write(dumpfd, data, int32(len))
+               nbuf = 0
+       } else {
+               copy(buf[:], (*[bufSize]byte)(data)[:len])
+               nbuf = len
+       }
+}
+
+func dwritebyte(b byte) {
+       dwrite(unsafe.Pointer(&b), 1)
+}
+
+func flush() {
+       write(dumpfd, (unsafe.Pointer)(&buf), int32(nbuf))
+       nbuf = 0
+}
+
+// Cache of types that have been serialized already.
+// We use a type's hash field to pick a bucket.
+// Inside a bucket, we keep a list of types that
+// have been serialized so far, most recently used first.
+// Note: when a bucket overflows we may end up
+// serializing a type more than once.  That's ok.
+const (
+       typeCacheBuckets = 256
+       typeCacheAssoc   = 4
+)
+
+type typeCacheBucket struct {
+       t [typeCacheAssoc]*_type
+}
+
+var typecache [typeCacheBuckets]typeCacheBucket
+
+// dump a uint64 in a varint format parseable by encoding/binary
+func dumpint(v uint64) {
+       var buf [10]byte
+       var n int
+       for v >= 0x80 {
+               buf[n] = byte(v | 0x80)
+               n++
+               v >>= 7
+       }
+       buf[n] = byte(v)
+       n++
+       dwrite(unsafe.Pointer(&buf), uintptr(n))
+}
+
+func dumpbool(b bool) {
+       if b {
+               dumpint(1)
+       } else {
+               dumpint(0)
+       }
+}
+
+// dump varint uint64 length followed by memory contents
+func dumpmemrange(data unsafe.Pointer, len uintptr) {
+       dumpint(uint64(len))
+       dwrite(data, len)
+}
+
+func dumpslice(b []byte) {
+       dumpint(uint64(len(b)))
+       if len(b) > 0 {
+               dwrite(unsafe.Pointer(&b[0]), uintptr(len(b)))
+       }
+}
+
+func dumpstr(s string) {
+       sp := (*stringStruct)(unsafe.Pointer(&s))
+       dumpmemrange(sp.str, uintptr(sp.len))
+}
+
+// dump information for a type
+func dumptype(t *_type) {
+       if t == nil {
+               return
+       }
+
+       // If we've definitely serialized the type before,
+       // no need to do it again.
+       b := &typecache[t.hash&(typeCacheBuckets-1)]
+       if t == b.t[0] {
+               return
+       }
+       for i := 1; i < typeCacheAssoc; i++ {
+               if t == b.t[i] {
+                       // Move-to-front
+                       for j := i; j > 0; j-- {
+                               b.t[j] = b.t[j-1]
+                       }
+                       b.t[0] = t
+                       return
+               }
+       }
+
+       // Might not have been dumped yet.  Dump it and
+       // remember we did so.
+       for j := typeCacheAssoc - 1; j > 0; j-- {
+               b.t[j] = b.t[j-1]
+       }
+       b.t[0] = t
+
+       // dump the type
+       dumpint(tagType)
+       dumpint(uint64(uintptr(unsafe.Pointer(t))))
+       dumpint(uint64(t.size))
+       if t.x == nil || t.x.pkgpath == nil || t.x.name == nil {
+               dumpstr(*t._string)
+       } else {
+               pkgpath := (*stringStruct)(unsafe.Pointer(&t.x.pkgpath))
+               name := (*stringStruct)(unsafe.Pointer(&t.x.name))
+               dumpint(uint64(uintptr(pkgpath.len) + 1 + uintptr(name.len)))
+               dwrite(pkgpath.str, uintptr(pkgpath.len))
+               dwritebyte('.')
+               dwrite(name.str, uintptr(name.len))
+       }
+       dumpbool(t.kind&kindDirectIface == 0 || t.kind&kindNoPointers == 0)
+}
+
+// dump an object
+func dumpobj(obj unsafe.Pointer, size uintptr, bv bitvector) {
+       dumpbvtypes(&bv, obj)
+       dumpint(tagObject)
+       dumpint(uint64(uintptr(obj)))
+       dumpmemrange(obj, size)
+       dumpfields(bv)
+}
+
+func dumpotherroot(description string, to unsafe.Pointer) {
+       dumpint(tagOtherRoot)
+       dumpstr(description)
+       dumpint(uint64(uintptr(to)))
+}
+
+func dumpfinalizer(obj unsafe.Pointer, fn *funcval, fint *_type, ot *ptrtype) {
+       dumpint(tagFinalizer)
+       dumpint(uint64(uintptr(obj)))
+       dumpint(uint64(uintptr(unsafe.Pointer(fn))))
+       dumpint(uint64(uintptr(unsafe.Pointer(fn.fn))))
+       dumpint(uint64(uintptr(unsafe.Pointer(fint))))
+       dumpint(uint64(uintptr(unsafe.Pointer(ot))))
+}
+
+type childInfo struct {
+       // Information passed up from the callee frame about
+       // the layout of the outargs region.
+       argoff uintptr   // where the arguments start in the frame
+       arglen uintptr   // size of args region
+       args   bitvector // if args.n >= 0, pointer map of args region
+       sp     *uint8    // callee sp
+       depth  uintptr   // depth in call stack (0 == most recent)
+}
+
+// dump kinds & offsets of interesting fields in bv
+func dumpbv(cbv *bitvector, offset uintptr) {
+       bv := gobv(*cbv)
+       for i := uintptr(0); i < uintptr(bv.n); i += bitsPerPointer {
+               switch bv.bytedata[i/8] >> (i % 8) & 3 {
+               default:
+                       gothrow("unexpected pointer bits")
+               case _BitsDead:
+                       // BitsDead has already been processed in makeheapobjbv.
+                       // We should only see it in stack maps, in which case we should continue processing.
+               case _BitsScalar:
+                       // ok
+               case _BitsPointer:
+                       dumpint(fieldKindPtr)
+                       dumpint(uint64(offset + i/_BitsPerPointer*ptrSize))
+               }
+       }
+}
+
+func dumpframe(s *stkframe, arg unsafe.Pointer) bool {
+       child := (*childInfo)(arg)
+       f := s.fn
+
+       // Figure out what we can about our stack map
+       pc := s.pc
+       if pc != f.entry {
+               pc--
+       }
+       pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, pc)
+       if pcdata == -1 {
+               // We do not have a valid pcdata value but there might be a
+               // stackmap for this function.  It is likely that we are looking
+               // at the function prologue, assume so and hope for the best.
+               pcdata = 0
+       }
+       stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
+
+       // Dump any types we will need to resolve Efaces.
+       if child.args.n >= 0 {
+               dumpbvtypes(&child.args, unsafe.Pointer(s.sp+child.argoff))
+       }
+       var bv bitvector
+       if stkmap != nil && stkmap.n > 0 {
+               bv = stackmapdata(stkmap, pcdata)
+               dumpbvtypes(&bv, unsafe.Pointer(s.varp-uintptr(bv.n/_BitsPerPointer*ptrSize)))
+       } else {
+               bv.n = -1
+       }
+
+       // Dump main body of stack frame.
+       dumpint(tagStackFrame)
+       dumpint(uint64(s.sp))                              // lowest address in frame
+       dumpint(uint64(child.depth))                       // # of frames deep on the stack
+       dumpint(uint64(uintptr(unsafe.Pointer(child.sp)))) // sp of child, or 0 if bottom of stack
+       dumpmemrange(unsafe.Pointer(s.sp), s.fp-s.sp)      // frame contents
+       dumpint(uint64(f.entry))
+       dumpint(uint64(s.pc))
+       dumpint(uint64(s.continpc))
+       name := gofuncname(f)
+       if name == "" {
+               name = "unknown function"
+       }
+       dumpstr(name)
+
+       // Dump fields in the outargs section
+       if child.args.n >= 0 {
+               dumpbv(&child.args, child.argoff)
+       } else {
+               // conservative - everything might be a pointer
+               for off := child.argoff; off < child.argoff+child.arglen; off += ptrSize {
+                       dumpint(fieldKindPtr)
+                       dumpint(uint64(off))
+               }
+       }
+
+       // Dump fields in the local vars section
+       if stkmap == nil {
+               // No locals information, dump everything.
+               for off := child.arglen; off < s.varp-s.sp; off += ptrSize {
+                       dumpint(fieldKindPtr)
+                       dumpint(uint64(off))
+               }
+       } else if stkmap.n < 0 {
+               // Locals size information, dump just the locals.
+               size := uintptr(-stkmap.n)
+               for off := s.varp - size - s.sp; off < s.varp-s.sp; off += ptrSize {
+                       dumpint(fieldKindPtr)
+                       dumpint(uint64(off))
+               }
+       } else if stkmap.n > 0 {
+               // Locals bitmap information, scan just the pointers in
+               // locals.
+               dumpbv(&bv, s.varp-uintptr(bv.n)/_BitsPerPointer*ptrSize-s.sp)
+       }
+       dumpint(fieldKindEol)
+
+       // Record arg info for parent.
+       child.argoff = s.argp - s.fp
+       child.arglen = s.arglen
+       child.sp = (*uint8)(unsafe.Pointer(s.sp))
+       child.depth++
+       stkmap = (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
+       if stkmap != nil {
+               child.args = stackmapdata(stkmap, pcdata)
+       } else {
+               child.args.n = -1
+       }
+       return true
+}
+
+func dumpgoroutine(gp *g) {
+       var sp, pc, lr uintptr
+       if gp.syscallsp != 0 {
+               sp = gp.syscallsp
+               pc = gp.syscallpc
+               lr = 0
+       } else {
+               sp = gp.sched.sp
+               pc = gp.sched.pc
+               lr = gp.sched.lr
+       }
+
+       dumpint(tagGoroutine)
+       dumpint(uint64(uintptr(unsafe.Pointer(gp))))
+       dumpint(uint64(sp))
+       dumpint(uint64(gp.goid))
+       dumpint(uint64(gp.gopc))
+       dumpint(uint64(readgstatus(gp)))
+       dumpbool(gp.issystem)
+       dumpbool(false) // isbackground
+       dumpint(uint64(gp.waitsince))
+       dumpstr(gp.waitreason)
+       dumpint(uint64(uintptr(gp.sched.ctxt)))
+       dumpint(uint64(uintptr(unsafe.Pointer(gp.m))))
+       dumpint(uint64(uintptr(unsafe.Pointer(gp._defer))))
+       dumpint(uint64(uintptr(unsafe.Pointer(gp._panic))))
+
+       // dump stack
+       var child childInfo
+       child.args.n = -1
+       child.arglen = 0
+       child.sp = nil
+       child.depth = 0
+       gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, dumpframe, noescape(unsafe.Pointer(&child)), 0)
+
+       // dump defer & panic records
+       for d := gp._defer; d != nil; d = d.link {
+               dumpint(tagDefer)
+               dumpint(uint64(uintptr(unsafe.Pointer(d))))
+               dumpint(uint64(uintptr(unsafe.Pointer(gp))))
+               dumpint(uint64(d.argp))
+               dumpint(uint64(d.pc))
+               dumpint(uint64(uintptr(unsafe.Pointer(d.fn))))
+               dumpint(uint64(uintptr(unsafe.Pointer(d.fn.fn))))
+               dumpint(uint64(uintptr(unsafe.Pointer(d.link))))
+       }
+       for p := gp._panic; p != nil; p = p.link {
+               dumpint(tagPanic)
+               dumpint(uint64(uintptr(unsafe.Pointer(p))))
+               dumpint(uint64(uintptr(unsafe.Pointer(gp))))
+               eface := (*eface)(unsafe.Pointer(&p.arg))
+               dumpint(uint64(uintptr(unsafe.Pointer(eface._type))))
+               dumpint(uint64(uintptr(unsafe.Pointer(eface.data))))
+               dumpint(0) // was p->defer, no longer recorded
+               dumpint(uint64(uintptr(unsafe.Pointer(p.link))))
+       }
+}
+
+func dumpgs() {
+       // goroutines & stacks
+       for i := 0; uintptr(i) < allglen; i++ {
+               gp := allgs[i]
+               status := readgstatus(gp) // The world is stopped so gp will not be in a scan state.
+               switch status {
+               default:
+                       print("runtime: unexpected G.status ", hex(status), "\n")
+                       gothrow("dumpgs in STW - bad status")
+               case _Gdead:
+                       // ok
+               case _Grunnable,
+                       _Gsyscall,
+                       _Gwaiting:
+                       dumpgoroutine(gp)
+               }
+       }
+}
+
+func finq_callback(fn *funcval, obj unsafe.Pointer, nret uintptr, fint *_type, ot *ptrtype) {
+       dumpint(tagQueuedFinalizer)
+       dumpint(uint64(uintptr(obj)))
+       dumpint(uint64(uintptr(unsafe.Pointer(fn))))
+       dumpint(uint64(uintptr(unsafe.Pointer(fn.fn))))
+       dumpint(uint64(uintptr(unsafe.Pointer(fint))))
+       dumpint(uint64(uintptr(unsafe.Pointer(ot))))
+}
+
+func dumproots() {
+       // data segment
+       dumpbvtypes(&gcdatamask, unsafe.Pointer(&data))
+       dumpint(tagData)
+       dumpint(uint64(uintptr(unsafe.Pointer(&data))))
+       dumpmemrange(unsafe.Pointer(&data), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)))
+       dumpfields(gcdatamask)
+
+       // bss segment
+       dumpbvtypes(&gcbssmask, unsafe.Pointer(&bss))
+       dumpint(tagBSS)
+       dumpint(uint64(uintptr(unsafe.Pointer(&bss))))
+       dumpmemrange(unsafe.Pointer(&bss), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)))
+       dumpfields(gcbssmask)
+
+       // MSpan.types
+       allspans := h_allspans
+       for spanidx := uint32(0); spanidx < mheap_.nspan; spanidx++ {
+               s := allspans[spanidx]
+               if s.state == _MSpanInUse {
+                       // Finalizers
+                       for sp := s.specials; sp != nil; sp = sp.next {
+                               if sp.kind != _KindSpecialFinalizer {
+                                       continue
+                               }
+                               spf := (*specialfinalizer)(unsafe.Pointer(sp))
+                               p := unsafe.Pointer((uintptr(s.start) << _PageShift) + uintptr(spf.special.offset))
+                               dumpfinalizer(p, spf.fn, spf.fint, spf.ot)
+                       }
+               }
+       }
+
+       // Finalizer queue
+       iterate_finq(finq_callback)
+}
+
+// Bit vector of free marks.
+// Needs to be as big as the largest number of objects per span.
+var freemark [_PageSize / 8]bool
+
+func dumpobjs() {
+       for i := uintptr(0); i < uintptr(mheap_.nspan); i++ {
+               s := h_allspans[i]
+               if s.state != _MSpanInUse {
+                       continue
+               }
+               p := uintptr(s.start << _PageShift)
+               size := s.elemsize
+               n := (s.npages << _PageShift) / size
+               if n > uintptr(len(freemark)) {
+                       gothrow("freemark array doesn't have enough entries")
+               }
+               for l := s.freelist; l != nil; l = l.next {
+                       freemark[(uintptr(unsafe.Pointer(l))-p)/size] = true
+               }
+               for j := uintptr(0); j < n; j, p = j+1, p+size {
+                       if freemark[j] {
+                               freemark[j] = false
+                               continue
+                       }
+                       dumpobj(unsafe.Pointer(p), size, makeheapobjbv(p, size))
+               }
+       }
+}
+
+func dumpparams() {
+       dumpint(tagParams)
+       x := uintptr(1)
+       if *(*byte)(unsafe.Pointer(&x)) == 1 {
+               dumpbool(false) // little-endian ptrs
+       } else {
+               dumpbool(true) // big-endian ptrs
+       }
+       dumpint(ptrSize)
+       dumpint(uint64(mheap_.arena_start))
+       dumpint(uint64(mheap_.arena_used))
+       dumpint(thechar)
+       dumpstr(goexperiment)
+       dumpint(uint64(ncpu))
+}
+
+func itab_callback(tab *itab) {
+       t := tab._type
+       // Dump a map from itab* to the type of its data field.
+       // We want this map so we can deduce types of interface referents.
+       if t.kind&kindDirectIface == 0 {
+               // indirect - data slot is a pointer to t.
+               dumptype(t.ptrto)
+               dumpint(tagItab)
+               dumpint(uint64(uintptr(unsafe.Pointer(tab))))
+               dumpint(uint64(uintptr(unsafe.Pointer(t.ptrto))))
+       } else if t.kind&kindNoPointers == 0 {
+               // t is pointer-like - data slot is a t.
+               dumptype(t)
+               dumpint(tagItab)
+               dumpint(uint64(uintptr(unsafe.Pointer(tab))))
+               dumpint(uint64(uintptr(unsafe.Pointer(t))))
+       } else {
+               // Data slot is a scalar.  Dump type just for fun.
+               // With pointer-only interfaces, this shouldn't happen.
+               dumptype(t)
+               dumpint(tagItab)
+               dumpint(uint64(uintptr(unsafe.Pointer(tab))))
+               dumpint(uint64(uintptr(unsafe.Pointer(t))))
+       }
+}
+
+func dumpitabs() {
+       iterate_itabs(itab_callback)
+}
+
+func dumpms() {
+       for mp := allm; mp != nil; mp = mp.alllink {
+               dumpint(tagOSThread)
+               dumpint(uint64(uintptr(unsafe.Pointer(mp))))
+               dumpint(uint64(mp.id))
+               dumpint(mp.procid)
+       }
+}
+
+func dumpmemstats() {
+       dumpint(tagMemStats)
+       dumpint(memstats.alloc)
+       dumpint(memstats.total_alloc)
+       dumpint(memstats.sys)
+       dumpint(memstats.nlookup)
+       dumpint(memstats.nmalloc)
+       dumpint(memstats.nfree)
+       dumpint(memstats.heap_alloc)
+       dumpint(memstats.heap_sys)
+       dumpint(memstats.heap_idle)
+       dumpint(memstats.heap_inuse)
+       dumpint(memstats.heap_released)
+       dumpint(memstats.heap_objects)
+       dumpint(memstats.stacks_inuse)
+       dumpint(memstats.stacks_sys)
+       dumpint(memstats.mspan_inuse)
+       dumpint(memstats.mspan_sys)
+       dumpint(memstats.mcache_inuse)
+       dumpint(memstats.mcache_sys)
+       dumpint(memstats.buckhash_sys)
+       dumpint(memstats.gc_sys)
+       dumpint(memstats.other_sys)
+       dumpint(memstats.next_gc)
+       dumpint(memstats.last_gc)
+       dumpint(memstats.pause_total_ns)
+       for i := 0; i < 256; i++ {
+               dumpint(memstats.pause_ns[i])
+       }
+       dumpint(uint64(memstats.numgc))
+}
+
+func dumpmemprof_callback(b *bucket, nstk uintptr, pstk *uintptr, size, allocs, frees uintptr) {
+       stk := (*[100000]uintptr)(unsafe.Pointer(pstk))
+       dumpint(tagMemProf)
+       dumpint(uint64(uintptr(unsafe.Pointer(b))))
+       dumpint(uint64(size))
+       dumpint(uint64(nstk))
+       for i := uintptr(0); i < nstk; i++ {
+               pc := stk[i]
+               f := findfunc(pc)
+               if f == nil {
+                       var buf [64]byte
+                       n := len(buf)
+                       n--
+                       buf[n] = ')'
+                       if pc == 0 {
+                               n--
+                               buf[n] = '0'
+                       } else {
+                               for pc > 0 {
+                                       n--
+                                       buf[n] = "0123456789abcdef"[pc&15]
+                                       pc >>= 4
+                               }
+                       }
+                       n--
+                       buf[n] = 'x'
+                       n--
+                       buf[n] = '0'
+                       n--
+                       buf[n] = '('
+                       dumpslice(buf[n:])
+                       dumpstr("?")
+                       dumpint(0)
+               } else {
+                       dumpstr(gofuncname(f))
+                       if i > 0 && pc > f.entry {
+                               pc--
+                       }
+                       file, line := funcline(f, pc)
+                       dumpstr(file)
+                       dumpint(uint64(line))
+               }
+       }
+       dumpint(uint64(allocs))
+       dumpint(uint64(frees))
+}
+
+func dumpmemprof() {
+       iterate_memprof(dumpmemprof_callback)
+       allspans := h_allspans
+       for spanidx := uint32(0); spanidx < mheap_.nspan; spanidx++ {
+               s := allspans[spanidx]
+               if s.state != _MSpanInUse {
+                       continue
+               }
+               for sp := s.specials; sp != nil; sp = sp.next {
+                       if sp.kind != _KindSpecialProfile {
+                               continue
+                       }
+                       spp := (*specialprofile)(unsafe.Pointer(sp))
+                       p := uintptr(s.start<<_PageShift) + uintptr(spp.special.offset)
+                       dumpint(tagAllocSample)
+                       dumpint(uint64(p))
+                       dumpint(uint64(uintptr(unsafe.Pointer(spp.b))))
+               }
+       }
+}
+
+var dumphdr = []byte("go1.4 heap dump\n")
+
+func mdump() {
+       // make sure we're done sweeping
+       for i := uintptr(0); i < uintptr(mheap_.nspan); i++ {
+               s := h_allspans[i]
+               if s.state == _MSpanInUse {
+                       mSpan_EnsureSwept(s)
+               }
+       }
+       memclr(unsafe.Pointer(&typecache), unsafe.Sizeof(typecache))
+       dwrite(unsafe.Pointer(&dumphdr[0]), uintptr(len(dumphdr)))
+       dumpparams()
+       dumpitabs()
+       dumpobjs()
+       dumpgs()
+       dumpms()
+       dumproots()
+       dumpmemstats()
+       dumpmemprof()
+       dumpint(tagEOF)
+       flush()
+}
+
+func writeheapdump_m(fd uintptr) {
+       _g_ := getg()
+       casgstatus(_g_.m.curg, _Grunning, _Gwaiting)
+       _g_.waitreason = "dumping heap"
+
+       // Update stats so we can dump them.
+       // As a side effect, flushes all the MCaches so the MSpan.freelist
+       // lists contain all the free objects.
+       updatememstats(nil)
+
+       // Set dump file.
+       dumpfd = fd
+
+       // Call dump routine.
+       mdump()
+
+       // Reset dump file.
+       dumpfd = 0
+       if tmpbuf != nil {
+               sysFree(unsafe.Pointer(&tmpbuf[0]), uintptr(len(tmpbuf)), &memstats.other_sys)
+               tmpbuf = nil
+       }
+
+       casgstatus(_g_.m.curg, _Gwaiting, _Grunning)
+}
+
+// dumpint() the kind & offset of each field in an object.
+func dumpfields(bv bitvector) {
+       dumpbv(&bv, 0)
+       dumpint(fieldKindEol)
+}
+
+// The heap dump reader needs to be able to disambiguate
+// Eface entries.  So it needs to know every type that might
+// appear in such an entry.  The following routine accomplishes that.
+// TODO(rsc, khr): Delete - no longer possible.
+
+// Dump all the types that appear in the type field of
+// any Eface described by this bit vector.
+func dumpbvtypes(bv *bitvector, base unsafe.Pointer) {
+}
+
+func makeheapobjbv(p uintptr, size uintptr) bitvector {
+       // Extend the temp buffer if necessary.
+       nptr := size / ptrSize
+       if uintptr(len(tmpbuf)) < nptr*_BitsPerPointer/8+1 {
+               if tmpbuf != nil {
+                       sysFree(unsafe.Pointer(&tmpbuf[0]), uintptr(len(tmpbuf)), &memstats.other_sys)
+               }
+               n := nptr*_BitsPerPointer/8 + 1
+               p := sysAlloc(n, &memstats.other_sys)
+               if p == nil {
+                       gothrow("heapdump: out of memory")
+               }
+               tmpbuf = (*[1 << 30]byte)(p)[:n]
+       }
+       // Copy and compact the bitmap.
+       var i uintptr
+       for i = 0; i < nptr; i++ {
+               off := (p + i*ptrSize - mheap_.arena_start) / ptrSize
+               bitp := (*uint8)(unsafe.Pointer(mheap_.arena_start - off/wordsPerBitmapByte - 1))
+               shift := uint8((off % wordsPerBitmapByte) * gcBits)
+               bits := (*bitp >> (shift + 2)) & _BitsMask
+               if bits == _BitsDead {
+                       break // end of heap object
+               }
+               tmpbuf[i*_BitsPerPointer/8] &^= (_BitsMask << ((i * _BitsPerPointer) % 8))
+               tmpbuf[i*_BitsPerPointer/8] |= bits << ((i * _BitsPerPointer) % 8)
+       }
+       return bitvector{int32(i * _BitsPerPointer), &tmpbuf[0]}
+}
diff --git a/src/runtime/lfstack.c b/src/runtime/lfstack.c
deleted file mode 100644 (file)
index 57e0af2..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Lock-free stack.
-// The following code runs only on g0 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)
-
-#ifdef _64BIT
-#ifdef GOOS_solaris
-// SPARC64 and Solaris on AMD64 uses all 64 bits of virtual addresses.
-// Use low-order three bits as ABA counter.
-// http://docs.oracle.com/cd/E19120-01/open.solaris/816-5138/6mba6ua5p/index.html
-#undef PTR_BITS
-#undef CNT_MASK
-#undef PTR_MASK
-#define PTR_BITS 0
-#define CNT_MASK 7
-#define PTR_MASK ((0ull-1)<<3)
-#endif
-#endif
-
-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);
-       for(;;) {
-               old = runtime·atomicload64(head);
-               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;
-
-       for(;;) {
-               old = runtime·atomicload64(head);
-               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·lfstackpush_m(void)
-{
-       runtime·lfstackpush(g->m->ptrarg[0], g->m->ptrarg[1]);
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-}
-
-void
-runtime·lfstackpop_m(void)
-{
-       g->m->ptrarg[0] = runtime·lfstackpop(g->m->ptrarg[0]);
-}
diff --git a/src/runtime/lfstack.go b/src/runtime/lfstack.go
new file mode 100644 (file)
index 0000000..8a36a67
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2012 The Go 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.
+// The following code runs only on g0 stack.
+
+package runtime
+
+import "unsafe"
+
+func lfstackpush(head *uint64, node *lfnode) {
+       node.pushcnt++
+       new := lfstackPack(node, node.pushcnt)
+       if node1, _ := lfstackUnpack(new); node1 != node {
+               println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+               gothrow("lfstackpush")
+       }
+       for {
+               old := atomicload64(head)
+               node.next, _ = lfstackUnpack(old)
+               if cas64(head, old, new) {
+                       break
+               }
+       }
+}
+
+func lfstackpop(head *uint64) unsafe.Pointer {
+       for {
+               old := atomicload64(head)
+               if old == 0 {
+                       return nil
+               }
+               node, _ := lfstackUnpack(old)
+               node2 := (*lfnode)(atomicloadp(unsafe.Pointer(&node.next)))
+               new := uint64(0)
+               if node2 != nil {
+                       new = lfstackPack(node2, node2.pushcnt)
+               }
+               if cas64(head, old, new) {
+                       return unsafe.Pointer(node)
+               }
+       }
+}
diff --git a/src/runtime/lfstack_32bit.go b/src/runtime/lfstack_32bit.go
new file mode 100644 (file)
index 0000000..61d8678
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 386 arm
+
+package runtime
+
+import "unsafe"
+
+// On 32-bit systems, the stored uint64 has a 32-bit pointer and 32-bit count.
+
+func lfstackPack(node *lfnode, cnt uintptr) uint64 {
+       return uint64(uintptr(unsafe.Pointer(node)))<<32 | uint64(cnt)
+}
+
+func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
+       node = (*lfnode)(unsafe.Pointer(uintptr(val >> 32)))
+       cnt = uintptr(val)
+       return
+}
diff --git a/src/runtime/lfstack_amd64.go b/src/runtime/lfstack_amd64.go
new file mode 100644 (file)
index 0000000..84e2851
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// On AMD64, virtual addresses are 48-bit numbers sign extended to 64.
+// We shift the address left 16 to eliminate the sign extended part and make
+// room in the bottom for the count.
+// In addition to the 16 bits taken from the top, we can take 3 from the
+// bottom, because node must be pointer-aligned, giving a total of 19 bits
+// of count.
+
+func lfstackPack(node *lfnode, cnt uintptr) uint64 {
+       return uint64(uintptr(unsafe.Pointer(node)))<<16 | uint64(cnt&(1<<19-1))
+}
+
+func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
+       node = (*lfnode)(unsafe.Pointer(uintptr(int64(val) >> 19 << 3)))
+       cnt = uintptr(val & (1<<19 - 1))
+       return
+}
diff --git a/src/runtime/lfstack_linux_power64x.go b/src/runtime/lfstack_linux_power64x.go
new file mode 100644 (file)
index 0000000..89e389f
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+// +build linux
+
+package runtime
+
+import "unsafe"
+
+// On Power64, Linux limits the user address space to 46 bits (see
+// TASK_SIZE_USER64 in the Linux kernel).  This has grown over time,
+// so here we allow 48 bit addresses.
+//
+// In addition to the 16 bits taken from the top, we can take 3 from the
+// bottom, because node must be pointer-aligned, giving a total of 19 bits
+// of count.
+const (
+       addrBits = 48
+       cntBits  = 64 - addrBits + 3
+)
+
+func lfstackPack(node *lfnode, cnt uintptr) uint64 {
+       return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
+}
+
+func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
+       node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
+       cnt = uintptr(val & (1<<cntBits - 1))
+       return
+}
index 725962341d47cfde83b063afdfdbb73ed841e248..11c3a3f06e150168a6047001448eb7316f8c13dc 100644 (file)
@@ -34,9 +34,6 @@ const (
 // Note that there can be spinning threads during all states - they do not
 // affect mutex's state.
 
-func futexsleep(addr *uint32, val uint32, ns int64)
-func futexwakeup(addr *uint32, cnt uint32)
-
 // We use the uintptr mutex.key and note.key as a uint32.
 func key32(p *uintptr) *uint32 {
        return (*uint32)(unsafe.Pointer(p))
@@ -198,8 +195,8 @@ func notetsleepg(n *note, ns int64) bool {
                gothrow("notetsleepg on g0")
        }
 
-       entersyscallblock()
+       entersyscallblock(0)
        ok := notetsleep_internal(n, ns)
-       exitsyscall()
+       exitsyscall(0)
        return ok
 }
index d136b828061d8206a641864ad49b7ef38c51feda..a2a87bac4debc2943f09a9d03d13d61056e0ba31 100644 (file)
@@ -31,10 +31,6 @@ const (
        passive_spin    = 1
 )
 
-func semacreate() uintptr
-func semasleep(int64) int32
-func semawakeup(mp *m)
-
 func lock(l *mutex) {
        gp := getg()
        if gp.m.locks < 0 {
@@ -263,8 +259,8 @@ func notetsleepg(n *note, ns int64) bool {
        if gp.m.waitsema == 0 {
                gp.m.waitsema = semacreate()
        }
-       entersyscallblock()
+       entersyscallblock(0)
        ok := notetsleep_internal(n, ns, nil, 0)
-       exitsyscall()
+       exitsyscall(0)
        return ok
 }
diff --git a/src/runtime/malloc.c b/src/runtime/malloc.c
deleted file mode 100644 (file)
index b79c30b..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// See malloc.h for overview.
-//
-// TODO(rsc): double-check stats.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "type.h"
-#include "typekind.h"
-#include "race.h"
-#include "stack.h"
-#include "textflag.h"
-
-// Mark mheap as 'no pointers', it does not contain interesting pointers but occupies ~45K.
-#pragma dataflag NOPTR
-MHeap runtime·mheap;
-#pragma dataflag NOPTR
-MStats runtime·memstats;
-
-int32
-runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
-{
-       uintptr n, i;
-       byte *p;
-       MSpan *s;
-
-       g->m->mcache->local_nlookup++;
-       if (sizeof(void*) == 4 && g->m->mcache->local_nlookup >= (1<<30)) {
-               // purge cache stats to prevent overflow
-               runtime·lock(&runtime·mheap.lock);
-               runtime·purgecachedstats(g->m->mcache);
-               runtime·unlock(&runtime·mheap.lock);
-       }
-
-       s = runtime·MHeap_LookupMaybe(&runtime·mheap, v);
-       if(sp)
-               *sp = s;
-       if(s == nil) {
-               if(base)
-                       *base = nil;
-               if(size)
-                       *size = 0;
-               return 0;
-       }
-
-       p = (byte*)((uintptr)s->start<<PageShift);
-       if(s->sizeclass == 0) {
-               // Large object.
-               if(base)
-                       *base = p;
-               if(size)
-                       *size = s->npages<<PageShift;
-               return 1;
-       }
-
-       n = s->elemsize;
-       if(base) {
-               i = ((byte*)v - p)/n;
-               *base = p + i*n;
-       }
-       if(size)
-               *size = n;
-
-       return 1;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·purgecachedstats(MCache *c)
-{
-       MHeap *h;
-       int32 i;
-
-       // Protected by either heap or GC lock.
-       h = &runtime·mheap;
-       mstats.heap_alloc += c->local_cachealloc;
-       c->local_cachealloc = 0;
-       mstats.tinyallocs += c->local_tinyallocs;
-       c->local_tinyallocs = 0;
-       mstats.nlookup += c->local_nlookup;
-       c->local_nlookup = 0;
-       h->largefree += c->local_largefree;
-       c->local_largefree = 0;
-       h->nlargefree += c->local_nlargefree;
-       c->local_nlargefree = 0;
-       for(i=0; i<nelem(c->local_nsmallfree); i++) {
-               h->nsmallfree[i] += c->local_nsmallfree[i];
-               c->local_nsmallfree[i] = 0;
-       }
-}
-
-// Size of the trailing by_size array differs between Go and C,
-// and all data after by_size is local to C, not exported to Go.
-// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
-// sizeof_C_MStats is what C thinks about size of Go struct.
-uintptr runtime·sizeof_C_MStats = offsetof(MStats, by_size[61]);
-
-#define MaxArena32 (2U<<30)
-
-// For use by Go. If it were a C enum it would be made available automatically,
-// but the value of MaxMem is too large for enum.
-uintptr runtime·maxmem = MaxMem;
-
-void
-runtime·mallocinit(void)
-{
-       byte *p, *p1;
-       uintptr arena_size, bitmap_size, spans_size, p_size;
-       extern byte runtime·end[];
-       uintptr limit;
-       uint64 i;
-       bool reserved;
-
-       p = nil;
-       p_size = 0;
-       arena_size = 0;
-       bitmap_size = 0;
-       spans_size = 0;
-       reserved = false;
-
-       // for 64-bit build
-       USED(p);
-       USED(p_size);
-       USED(arena_size);
-       USED(bitmap_size);
-       USED(spans_size);
-
-       runtime·InitSizes();
-
-       if(runtime·class_to_size[TinySizeClass] != TinySize)
-               runtime·throw("bad TinySizeClass");
-
-       // limit = runtime·memlimit();
-       // See https://code.google.com/p/go/issues/detail?id=5049
-       // TODO(rsc): Fix after 1.1.
-       limit = 0;
-
-       // Set up the allocation arena, a contiguous area of memory where
-       // allocated data will be found.  The arena begins with a bitmap large
-       // enough to hold 4 bits per allocated word.
-       if(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) {
-               // On a 64-bit machine, allocate from a single contiguous reservation.
-               // 128 GB (MaxMem) should be big enough for now.
-               //
-               // The code will work with the reservation at any address, but ask
-               // SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
-               // Allocating a 128 GB region takes away 37 bits, and the amd64
-               // doesn't let us choose the top 17 bits, so that leaves the 11 bits
-               // in the middle of 0x00c0 for us to choose.  Choosing 0x00c0 means
-               // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
-               // In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
-               // UTF-8 sequences, and they are otherwise as far away from 
-               // ff (likely a common byte) as possible.  If that fails, we try other 0xXXc0
-               // addresses.  An earlier attempt to use 0x11f8 caused out of memory errors
-               // on OS X during thread allocations.  0x00c0 causes conflicts with
-               // AddressSanitizer which reserves all memory up to 0x0100.
-               // These choices are both for debuggability and to reduce the
-               // odds of the conservative garbage collector not collecting memory
-               // because some non-pointer block of memory had a bit pattern
-               // that matched a memory address.
-               //
-               // Actually we reserve 136 GB (because the bitmap ends up being 8 GB)
-               // but it hardly matters: e0 00 is not valid UTF-8 either.
-               //
-               // If this fails we fall back to the 32 bit memory mechanism
-               arena_size = MaxMem;
-               bitmap_size = arena_size / (sizeof(void*)*8/4);
-               spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
-               spans_size = ROUND(spans_size, PageSize);
-               for(i = 0; i <= 0x7f; i++) {
-                       p = (void*)(i<<40 | 0x00c0ULL<<32);
-                       p_size = bitmap_size + spans_size + arena_size + PageSize;
-                       p = runtime·SysReserve(p, p_size, &reserved);
-                       if(p != nil)
-                               break;
-               }
-       }
-       if (p == nil) {
-               // On a 32-bit machine, we can't typically get away
-               // with a giant virtual address space reservation.
-               // Instead we map the memory information bitmap
-               // immediately after the data segment, large enough
-               // to handle another 2GB of mappings (256 MB),
-               // along with a reservation for another 512 MB of memory.
-               // When that gets used up, we'll start asking the kernel
-               // for any memory anywhere and hope it's in the 2GB
-               // following the bitmap (presumably the executable begins
-               // near the bottom of memory, so we'll have to use up
-               // most of memory before the kernel resorts to giving out
-               // memory before the beginning of the text segment).
-               //
-               // Alternatively we could reserve 512 MB bitmap, enough
-               // for 4GB of mappings, and then accept any memory the
-               // kernel threw at us, but normally that's a waste of 512 MB
-               // of address space, which is probably too much in a 32-bit world.
-               bitmap_size = MaxArena32 / (sizeof(void*)*8/4);
-               arena_size = 512<<20;
-               spans_size = MaxArena32 / PageSize * sizeof(runtime·mheap.spans[0]);
-               if(limit > 0 && arena_size+bitmap_size+spans_size > limit) {
-                       bitmap_size = (limit / 9) & ~((1<<PageShift) - 1);
-                       arena_size = bitmap_size * 8;
-                       spans_size = arena_size / PageSize * sizeof(runtime·mheap.spans[0]);
-               }
-               spans_size = ROUND(spans_size, PageSize);
-
-               // SysReserve treats the address we ask for, end, as a hint,
-               // not as an absolute requirement.  If we ask for the end
-               // of the data segment but the operating system requires
-               // a little more space before we can start allocating, it will
-               // give out a slightly higher pointer.  Except QEMU, which
-               // is buggy, as usual: it won't adjust the pointer upward.
-               // So adjust it upward a little bit ourselves: 1/4 MB to get
-               // away from the running binary image and then round up
-               // to a MB boundary.
-               p = (byte*)ROUND((uintptr)runtime·end + (1<<18), 1<<20);
-               p_size = bitmap_size + spans_size + arena_size + PageSize;
-               p = runtime·SysReserve(p, p_size, &reserved);
-               if(p == nil)
-                       runtime·throw("runtime: cannot reserve arena virtual address space");
-       }
-
-       // PageSize can be larger than OS definition of page size,
-       // so SysReserve can give us a PageSize-unaligned pointer.
-       // To overcome this we ask for PageSize more and round up the pointer.
-       p1 = (byte*)ROUND((uintptr)p, PageSize);
-
-       runtime·mheap.spans = (MSpan**)p1;
-       runtime·mheap.bitmap = p1 + spans_size;
-       runtime·mheap.arena_start = p1 + spans_size + bitmap_size;
-       runtime·mheap.arena_used = runtime·mheap.arena_start;
-       runtime·mheap.arena_end = p + p_size;
-       runtime·mheap.arena_reserved = reserved;
-
-       if(((uintptr)runtime·mheap.arena_start & (PageSize-1)) != 0)
-               runtime·throw("misrounded allocation in mallocinit");
-
-       // Initialize the rest of the allocator.        
-       runtime·MHeap_Init(&runtime·mheap);
-       g->m->mcache = runtime·allocmcache();
-}
-
-void*
-runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
-{
-       byte *p, *p_end;
-       uintptr p_size;
-       bool reserved;
-
-       if(n > h->arena_end - h->arena_used) {
-               // We are in 32-bit mode, maybe we didn't use all possible address space yet.
-               // Reserve some more space.
-               byte *new_end;
-
-               p_size = ROUND(n + PageSize, 256<<20);
-               new_end = h->arena_end + p_size;
-               if(new_end <= h->arena_start + MaxArena32) {
-                       // TODO: It would be bad if part of the arena
-                       // is reserved and part is not.
-                       p = runtime·SysReserve(h->arena_end, p_size, &reserved);
-                       if(p == h->arena_end) {
-                               h->arena_end = new_end;
-                               h->arena_reserved = reserved;
-                       }
-                       else if(p+p_size <= h->arena_start + MaxArena32) {
-                               // Keep everything page-aligned.
-                               // Our pages are bigger than hardware pages.
-                               h->arena_end = p+p_size;
-                               h->arena_used = p + (-(uintptr)p&(PageSize-1));
-                               h->arena_reserved = reserved;
-                       } else {
-                               uint64 stat;
-                               stat = 0;
-                               runtime·SysFree(p, p_size, &stat);
-                       }
-               }
-       }
-       if(n <= h->arena_end - h->arena_used) {
-               // Keep taking from our reservation.
-               p = h->arena_used;
-               runtime·SysMap(p, n, h->arena_reserved, &mstats.heap_sys);
-               h->arena_used += n;
-               runtime·MHeap_MapBits(h);
-               runtime·MHeap_MapSpans(h);
-               if(raceenabled)
-                       runtime·racemapshadow(p, n);
-               
-               if(((uintptr)p & (PageSize-1)) != 0)
-                       runtime·throw("misrounded allocation in MHeap_SysAlloc");
-               return p;
-       }
-       
-       // If using 64-bit, our reservation is all we have.
-       if(h->arena_end - h->arena_start >= MaxArena32)
-               return nil;
-
-       // On 32-bit, once the reservation is gone we can
-       // try to get memory at a location chosen by the OS
-       // and hope that it is in the range we allocated bitmap for.
-       p_size = ROUND(n, PageSize) + PageSize;
-       p = runtime·sysAlloc(p_size, &mstats.heap_sys);
-       if(p == nil)
-               return nil;
-
-       if(p < h->arena_start || p+p_size - h->arena_start >= MaxArena32) {
-               runtime·printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n",
-                       p, h->arena_start, h->arena_start+MaxArena32);
-               runtime·SysFree(p, p_size, &mstats.heap_sys);
-               return nil;
-       }
-       
-       p_end = p + p_size;
-       p += -(uintptr)p & (PageSize-1);
-       if(p+n > h->arena_used) {
-               h->arena_used = p+n;
-               if(p_end > h->arena_end)
-                       h->arena_end = p_end;
-               runtime·MHeap_MapBits(h);
-               runtime·MHeap_MapSpans(h);
-               if(raceenabled)
-                       runtime·racemapshadow(p, n);
-       }
-       
-       if(((uintptr)p & (PageSize-1)) != 0)
-               runtime·throw("misrounded allocation in MHeap_SysAlloc");
-       return p;
-}
-
-void
-runtime·setFinalizer_m(void)
-{
-       FuncVal *fn;
-       void *arg;
-       uintptr nret;
-       Type *fint;
-       PtrType *ot;
-
-       fn = g->m->ptrarg[0];
-       arg = g->m->ptrarg[1];
-       nret = g->m->scalararg[0];
-       fint = g->m->ptrarg[2];
-       ot = g->m->ptrarg[3];
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-       g->m->ptrarg[2] = nil;
-       g->m->ptrarg[3] = nil;
-
-       g->m->scalararg[0] = runtime·addfinalizer(arg, fn, nret, fint, ot);
-}
-
-void
-runtime·removeFinalizer_m(void)
-{
-       void *p;
-
-       p = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       runtime·removefinalizer(p);
-}
-
-// mcallable cache refill
-void 
-runtime·mcacheRefill_m(void)
-{
-       runtime·MCache_Refill(g->m->mcache, (int32)g->m->scalararg[0]);
-}
-
-void
-runtime·largeAlloc_m(void)
-{
-       uintptr npages, size;
-       MSpan *s;
-       void *v;
-       int32 flag;
-
-       //runtime·printf("largeAlloc size=%D\n", g->m->scalararg[0]);
-       // Allocate directly from heap.
-       size = g->m->scalararg[0];
-       flag = (int32)g->m->scalararg[1];
-       if(size + PageSize < size)
-               runtime·throw("out of memory");
-       npages = size >> PageShift;
-       if((size & PageMask) != 0)
-               npages++;
-       s = runtime·MHeap_Alloc(&runtime·mheap, npages, 0, 1, !(flag & FlagNoZero));
-       if(s == nil)
-               runtime·throw("out of memory");
-       s->limit = (byte*)(s->start<<PageShift) + size;
-       v = (void*)(s->start << PageShift);
-       // setup for mark sweep
-       runtime·markspan(v, 0, 0, true);
-       g->m->ptrarg[0] = s;
-}
index 117044944041547324f195e2c6e8a63316bdf73b..d73d1ba6a613865bed394273f401071d26836bd8 100644 (file)
@@ -4,9 +4,7 @@
 
 package runtime
 
-import (
-       "unsafe"
-)
+import "unsafe"
 
 const (
        debugMalloc = false
@@ -28,10 +26,11 @@ const (
        maxGCMask       = _MaxGCMask
        bitsDead        = _BitsDead
        bitsPointer     = _BitsPointer
+       bitsScalar      = _BitsScalar
 
        mSpanInUse = _MSpanInUse
 
-       concurrentSweep = _ConcurrentSweep != 0
+       concurrentSweep = _ConcurrentSweep
 )
 
 // Page number (address>>pageShift)
@@ -56,7 +55,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
        // This function must be atomic wrt GC, but for performance reasons
        // we don't acquirem/releasem on fast path. The code below does not have
        // split stack checks, so it can't be preempted by GC.
-       // Functions like roundup/add are inlined. And onM/racemalloc are nosplit.
+       // Functions like roundup/add are inlined. And systemstack/racemalloc are nosplit.
        // If debugMalloc = true, these assumptions are checked below.
        if debugMalloc {
                mp := acquirem()
@@ -142,10 +141,9 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
                        s = c.alloc[tinySizeClass]
                        v := s.freelist
                        if v == nil {
-                               mp := acquirem()
-                               mp.scalararg[0] = tinySizeClass
-                               onM(mcacheRefill_m)
-                               releasem(mp)
+                               systemstack(func() {
+                                       mCache_Refill(c, tinySizeClass)
+                               })
                                s = c.alloc[tinySizeClass]
                                v = s.freelist
                        }
@@ -173,10 +171,9 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
                        s = c.alloc[sizeclass]
                        v := s.freelist
                        if v == nil {
-                               mp := acquirem()
-                               mp.scalararg[0] = uintptr(sizeclass)
-                               onM(mcacheRefill_m)
-                               releasem(mp)
+                               systemstack(func() {
+                                       mCache_Refill(c, int32(sizeclass))
+                               })
                                s = c.alloc[sizeclass]
                                v = s.freelist
                        }
@@ -193,13 +190,10 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
                }
                c.local_cachealloc += intptr(size)
        } else {
-               mp := acquirem()
-               mp.scalararg[0] = uintptr(size)
-               mp.scalararg[1] = uintptr(flags)
-               onM(largeAlloc_m)
-               s = (*mspan)(mp.ptrarg[0])
-               mp.ptrarg[0] = nil
-               releasem(mp)
+               var s *mspan
+               systemstack(func() {
+                       s = largeAlloc(size, uint32(flags))
+               })
                x = unsafe.Pointer(uintptr(s.start << pageShift))
                size = uintptr(s.elemsize)
        }
@@ -251,22 +245,19 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
                                // into the GC bitmap. It's 7 times slower than copying
                                // from the pre-unrolled mask, but saves 1/16 of type size
                                // memory for the mask.
-                               mp := acquirem()
-                               mp.ptrarg[0] = x
-                               mp.ptrarg[1] = unsafe.Pointer(typ)
-                               mp.scalararg[0] = uintptr(size)
-                               mp.scalararg[1] = uintptr(size0)
-                               onM(unrollgcproginplace_m)
-                               releasem(mp)
+                               systemstack(func() {
+                                       unrollgcproginplace_m(x, typ, size, size0)
+                               })
                                goto marked
                        }
                        ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0])))
-                       // Check whether the program is already unrolled.
-                       if uintptr(atomicloadp(unsafe.Pointer(ptrmask)))&0xff == 0 {
-                               mp := acquirem()
-                               mp.ptrarg[0] = unsafe.Pointer(typ)
-                               onM(unrollgcprog_m)
-                               releasem(mp)
+                       // Check whether the program is already unrolled
+                       // by checking if the unroll flag byte is set
+                       maskword := uintptr(atomicloadp(unsafe.Pointer(ptrmask)))
+                       if *(*uint8)(unsafe.Pointer(&maskword)) == 0 {
+                               systemstack(func() {
+                                       unrollgcprog_m(typ)
+                               })
                        }
                        ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
                } else {
@@ -359,7 +350,7 @@ func newarray(typ *_type, n uintptr) unsafe.Pointer {
        if typ.kind&kindNoPointers != 0 {
                flags |= flagNoScan
        }
-       if int(n) < 0 || (typ.size > 0 && n > maxmem/uintptr(typ.size)) {
+       if int(n) < 0 || (typ.size > 0 && n > _MaxMem/uintptr(typ.size)) {
                panic("runtime: allocation size out of range")
        }
        return mallocgc(uintptr(typ.size)*n, typ, flags)
@@ -438,7 +429,7 @@ func gogc(force int32) {
        mp = acquirem()
        mp.gcing = 1
        releasem(mp)
-       onM(stoptheworld)
+       systemstack(stoptheworld)
        if mp != acquirem() {
                gothrow("gogc: rescheduled")
        }
@@ -459,20 +450,16 @@ func gogc(force int32) {
                        startTime = nanotime()
                }
                // switch to g0, call gc, then switch back
-               mp.scalararg[0] = uintptr(uint32(startTime)) // low 32 bits
-               mp.scalararg[1] = uintptr(startTime >> 32)   // high 32 bits
-               if force >= 2 {
-                       mp.scalararg[2] = 1 // eagersweep
-               } else {
-                       mp.scalararg[2] = 0
-               }
-               onM(gc_m)
+               eagersweep := force >= 2
+               systemstack(func() {
+                       gc_m(startTime, eagersweep)
+               })
        }
 
        // all done
        mp.gcing = 0
        semrelease(&worldsema)
-       onM(starttheworld)
+       systemstack(starttheworld)
        releasem(mp)
        mp = nil
 
@@ -591,11 +578,10 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
        f := (*eface)(unsafe.Pointer(&finalizer))
        ftyp := f._type
        if ftyp == nil {
-               // switch to M stack and remove finalizer
-               mp := acquirem()
-               mp.ptrarg[0] = e.data
-               onM(removeFinalizer_m)
-               releasem(mp)
+               // switch to system stack and remove finalizer
+               systemstack(func() {
+                       removefinalizer(e.data)
+               })
                return
        }
 
@@ -640,18 +626,11 @@ okarg:
        // make sure we have a finalizer goroutine
        createfing()
 
-       // switch to M stack to add finalizer record
-       mp := acquirem()
-       mp.ptrarg[0] = f.data
-       mp.ptrarg[1] = e.data
-       mp.scalararg[0] = nret
-       mp.ptrarg[2] = unsafe.Pointer(fint)
-       mp.ptrarg[3] = unsafe.Pointer(ot)
-       onM(setFinalizer_m)
-       if mp.scalararg[0] != 1 {
-               gothrow("runtime.SetFinalizer: finalizer already set")
-       }
-       releasem(mp)
+       systemstack(func() {
+               if !addfinalizer(e.data, (*funcval)(f.data), nret, fint, ot) {
+                       gothrow("runtime.SetFinalizer: finalizer already set")
+               }
+       })
 }
 
 // round n up to a multiple of a.  a must be a power of 2.
diff --git a/src/runtime/malloc.h b/src/runtime/malloc.h
deleted file mode 100644 (file)
index adb8d3d..0000000
+++ /dev/null
@@ -1,621 +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.
-
-// Memory allocator, based on tcmalloc.
-// http://goog-perftools.sourceforge.net/doc/tcmalloc.html
-
-// The main allocator works in runs of pages.
-// Small allocation sizes (up to and including 32 kB) are
-// rounded to one of about 100 size classes, each of which
-// has its own free list of objects of exactly that size.
-// Any free page of memory can be split into a set of objects
-// of one size class, which are then managed using free list
-// allocators.
-//
-// The allocator's data structures are:
-//
-//     FixAlloc: a free-list allocator for fixed-size objects,
-//             used to manage storage used by the allocator.
-//     MHeap: the malloc heap, managed at page (4096-byte) granularity.
-//     MSpan: a run of pages managed by the MHeap.
-//     MCentral: a shared free list for a given size class.
-//     MCache: a per-thread (in Go, per-P) cache for small objects.
-//     MStats: allocation statistics.
-//
-// Allocating a small object proceeds up a hierarchy of caches:
-//
-//     1. Round the size up to one of the small size classes
-//        and look in the corresponding MCache free list.
-//        If the list is not empty, allocate an object from it.
-//        This can all be done without acquiring a lock.
-//
-//     2. If the MCache free list is empty, replenish it by
-//        taking a bunch of objects from the MCentral free list.
-//        Moving a bunch amortizes the cost of acquiring the MCentral lock.
-//
-//     3. If the MCentral free list is empty, replenish it by
-//        allocating a run of pages from the MHeap and then
-//        chopping that memory into a objects of the given size.
-//        Allocating many objects amortizes the cost of locking
-//        the heap.
-//
-//     4. If the MHeap is empty or has no page runs large enough,
-//        allocate a new group of pages (at least 1MB) from the
-//        operating system.  Allocating a large run of pages
-//        amortizes the cost of talking to the operating system.
-//
-// Freeing a small object proceeds up the same hierarchy:
-//
-//     1. Look up the size class for the object and add it to
-//        the MCache free list.
-//
-//     2. If the MCache free list is too long or the MCache has
-//        too much memory, return some to the MCentral free lists.
-//
-//     3. If all the objects in a given span have returned to
-//        the MCentral list, return that span to the page heap.
-//
-//     4. If the heap has too much memory, return some to the
-//        operating system.
-//
-//     TODO(rsc): Step 4 is not implemented.
-//
-// Allocating and freeing a large object uses the page heap
-// directly, bypassing the MCache and MCentral free lists.
-//
-// The small objects on the MCache and MCentral free lists
-// may or may not be zeroed.  They are zeroed if and only if
-// the second word of the object is zero.  A span in the
-// page heap is zeroed unless s->needzero is set. When a span
-// is allocated to break into small objects, it is zeroed if needed
-// and s->needzero is set. There are two main benefits to delaying the
-// zeroing this way:
-//
-//     1. stack frames allocated from the small object lists
-//        or the page heap can avoid zeroing altogether.
-//     2. the cost of zeroing when reusing a small object is
-//        charged to the mutator, not the garbage collector.
-//
-// This C code was written with an eye toward translating to Go
-// in the future.  Methods have the form Type_Method(Type *t, ...).
-
-typedef struct MCentral        MCentral;
-typedef struct MHeap   MHeap;
-typedef struct MSpan   MSpan;
-typedef struct MStats  MStats;
-typedef struct MLink   MLink;
-typedef struct GCStats GCStats;
-
-enum
-{
-       PageShift       = 13,
-       PageSize        = 1<<PageShift,
-       PageMask        = PageSize - 1,
-};
-typedef        uintptr pageID;         // address >> PageShift
-
-enum
-{
-       // Computed constant.  The definition of MaxSmallSize and the
-       // algorithm in msize.c produce some number of different allocation
-       // size classes.  NumSizeClasses is that number.  It's needed here
-       // because there are static arrays of this length; when msize runs its
-       // size choosing algorithm it double-checks that NumSizeClasses agrees.
-       NumSizeClasses = 67,
-
-       // Tunable constants.
-       MaxSmallSize = 32<<10,
-
-       // Tiny allocator parameters, see "Tiny allocator" comment in malloc.goc.
-       TinySize = 16,
-       TinySizeClass = 2,
-
-       FixAllocChunk = 16<<10,         // Chunk size for FixAlloc
-       MaxMHeapList = 1<<(20 - PageShift),     // Maximum page length for fixed-size list in MHeap.
-       HeapAllocChunk = 1<<20,         // Chunk size for heap growth
-
-       // Per-P, per order stack segment cache size.
-       StackCacheSize = 32*1024,
-       // Number of orders that get caching.  Order 0 is FixedStack
-       // and each successive order is twice as large.
-       NumStackOrders = 3,
-
-       // Number of bits in page to span calculations (4k pages).
-       // On Windows 64-bit we limit the arena to 32GB or 35 bits (see below for reason).
-       // On other 64-bit platforms, we limit the arena to 128GB, or 37 bits.
-       // On 32-bit, we don't bother limiting anything, so we use the full 32-bit address.
-#ifdef _64BIT
-#ifdef GOOS_windows
-       // Windows counts memory used by page table into committed memory
-       // of the process, so we can't reserve too much memory.
-       // See http://golang.org/issue/5402 and http://golang.org/issue/5236.
-       MHeapMap_Bits = 35 - PageShift,
-#else
-       MHeapMap_Bits = 37 - PageShift,
-#endif
-#else
-       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 32 cpus.
-       MaxGcproc = 32,
-};
-
-// 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 or 32 GB */
-#else
-#define        MaxMem  ((uintptr)-1)
-#endif
-
-// A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
-struct MLink
-{
-       MLink *next;
-};
-
-// sysAlloc obtains a large chunk of zeroed memory from the
-// operating system, typically on the order of a hundred kilobytes
-// or a megabyte.
-// NOTE: sysAlloc returns OS-aligned memory, but the heap allocator
-// may use larger alignment, so the caller must be careful to realign the
-// memory obtained by sysAlloc.
-//
-// SysUnused notifies the operating system that the contents
-// of the memory region are no longer needed and can be reused
-// for other purposes.
-// SysUsed notifies the operating system that the contents
-// of the memory region are needed again.
-//
-// SysFree returns it unconditionally; this is only used if
-// an out-of-memory error has been detected midway through
-// an allocation.  It is okay if SysFree is a no-op.
-//
-// SysReserve reserves address space without allocating memory.
-// If the pointer passed to it is non-nil, the caller wants the
-// reservation there, but SysReserve can still choose another
-// location if that one is unavailable.  On some systems and in some
-// cases SysReserve will simply check that the address space is
-// available and not actually reserve it.  If SysReserve returns
-// non-nil, it sets *reserved to true if the address space is
-// reserved, false if it has merely been checked.
-// NOTE: SysReserve returns OS-aligned memory, but the heap allocator
-// may use larger alignment, so the caller must be careful to realign the
-// memory obtained by sysAlloc.
-//
-// SysMap maps previously reserved address space for use.
-// The reserved argument is true if the address space was really
-// reserved, not merely checked.
-//
-// SysFault marks a (already sysAlloc'd) region to fault
-// if accessed.  Used only for debugging the runtime.
-
-void*  runtime·sysAlloc(uintptr nbytes, uint64 *stat);
-void   runtime·SysFree(void *v, uintptr nbytes, uint64 *stat);
-void   runtime·SysUnused(void *v, uintptr nbytes);
-void   runtime·SysUsed(void *v, uintptr nbytes);
-void   runtime·SysMap(void *v, uintptr nbytes, bool reserved, uint64 *stat);
-void*  runtime·SysReserve(void *v, uintptr nbytes, bool *reserved);
-void   runtime·SysFault(void *v, uintptr nbytes);
-
-// FixAlloc is a simple free-list allocator for fixed size objects.
-// Malloc uses a FixAlloc wrapped around sysAlloc to manages its
-// MCache and MSpan objects.
-//
-// Memory returned by FixAlloc_Alloc is not zeroed.
-// The caller is responsible for locking around FixAlloc calls.
-// Callers can keep state in the object but the first word is
-// smashed by freeing and reallocating.
-struct FixAlloc
-{
-       uintptr size;
-       void    (*first)(void *arg, byte *p);   // called first time p is returned
-       void*   arg;
-       MLink*  list;
-       byte*   chunk;
-       uint32  nchunk;
-       uintptr inuse;  // in-use bytes now
-       uint64* stat;
-};
-
-void   runtime·FixAlloc_Init(FixAlloc *f, uintptr size, void (*first)(void*, byte*), void *arg, uint64 *stat);
-void*  runtime·FixAlloc_Alloc(FixAlloc *f);
-void   runtime·FixAlloc_Free(FixAlloc *f, void *p);
-
-
-// Statistics.
-// Shared with Go: if you edit this structure, also edit type MemStats in mem.go.
-struct MStats
-{
-       // General statistics.
-       uint64  alloc;          // bytes allocated and still in use
-       uint64  total_alloc;    // bytes allocated (even if freed)
-       uint64  sys;            // bytes obtained from system (should be sum of xxx_sys below, no locking, approximate)
-       uint64  nlookup;        // number of pointer lookups
-       uint64  nmalloc;        // number of mallocs
-       uint64  nfree;  // number of frees
-
-       // Statistics about malloc heap.
-       // protected by mheap.lock
-       uint64  heap_alloc;     // bytes allocated and still in use
-       uint64  heap_sys;       // bytes obtained from system
-       uint64  heap_idle;      // bytes in idle spans
-       uint64  heap_inuse;     // bytes in non-idle spans
-       uint64  heap_released;  // bytes released to the OS
-       uint64  heap_objects;   // total number of allocated objects
-
-       // Statistics about allocation of low-level fixed-size structures.
-       // Protected by FixAlloc locks.
-       uint64  stacks_inuse;   // this number is included in heap_inuse above
-       uint64  stacks_sys;     // always 0 in mstats
-       uint64  mspan_inuse;    // MSpan structures
-       uint64  mspan_sys;
-       uint64  mcache_inuse;   // MCache structures
-       uint64  mcache_sys;
-       uint64  buckhash_sys;   // profiling bucket hash table
-       uint64  gc_sys;
-       uint64  other_sys;
-
-       // Statistics about garbage collector.
-       // 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;
-       uint64  pause_ns[256];  // circular buffer of recent GC pause lengths
-       uint64  pause_end[256]; // circular buffer of recent GC end times (nanoseconds since 1970)
-       uint32  numgc;
-       bool    enablegc;
-       bool    debuggc;
-
-       // Statistics about allocation size classes.
-       
-       struct MStatsBySize {
-               uint32 size;
-               uint64 nmalloc;
-               uint64 nfree;
-       } by_size[NumSizeClasses];
-       
-       uint64  tinyallocs;     // number of tiny allocations that didn't cause actual allocation; not exported to Go directly
-};
-
-
-#define mstats runtime·memstats
-extern MStats mstats;
-void   runtime·updatememstats(GCStats *stats);
-void   runtime·ReadMemStats(MStats *stats);
-
-// Size classes.  Computed and initialized by InitSizes.
-//
-// SizeToClass(0 <= n <= MaxSmallSize) returns the size class,
-//     1 <= sizeclass < NumSizeClasses, for n.
-//     Size class 0 is reserved to mean "not small".
-//
-// class_to_size[i] = largest size in class i
-// class_to_allocnpages[i] = number of pages to allocate when
-//     making new objects in class i
-
-int32  runtime·SizeToClass(int32);
-uintptr        runtime·roundupsize(uintptr);
-extern int32   runtime·class_to_size[NumSizeClasses];
-extern int32   runtime·class_to_allocnpages[NumSizeClasses];
-extern int8    runtime·size_to_class8[1024/8 + 1];
-extern int8    runtime·size_to_class128[(MaxSmallSize-1024)/128 + 1];
-extern void    runtime·InitSizes(void);
-
-typedef struct MCacheList MCacheList;
-struct MCacheList
-{
-       MLink *list;
-       uint32 nlist;
-};
-
-typedef struct StackFreeList StackFreeList;
-struct StackFreeList
-{
-       MLink *list;  // linked list of free stacks
-       uintptr size; // total size of stacks in list
-};
-
-typedef struct SudoG SudoG;
-
-// Per-thread (in Go, per-P) cache for small objects.
-// No locking needed because it is per-thread (per-P).
-struct MCache
-{
-       // The following members are accessed on every malloc,
-       // so they are grouped here for better caching.
-       int32 next_sample;              // trigger heap sample after allocating this many bytes
-       intptr local_cachealloc;        // bytes allocated (or freed) from cache since last lock of heap
-       // Allocator cache for tiny objects w/o pointers.
-       // See "Tiny allocator" comment in malloc.goc.
-       byte*   tiny;
-       uintptr tinysize;
-       uintptr local_tinyallocs;       // number of tiny allocs not counted in other stats
-       // The rest is not accessed on every malloc.
-       MSpan*  alloc[NumSizeClasses];  // spans to allocate from
-
-       StackFreeList stackcache[NumStackOrders];
-
-       SudoG*  sudogcache;
-
-       void*   gcworkbuf;
-
-       // Local allocator stats, flushed during GC.
-       uintptr local_nlookup;          // number of pointer lookups
-       uintptr local_largefree;        // bytes freed for large objects (>MaxSmallSize)
-       uintptr local_nlargefree;       // number of frees for large objects (>MaxSmallSize)
-       uintptr local_nsmallfree[NumSizeClasses];       // number of frees for small objects (<=MaxSmallSize)
-};
-
-MSpan* runtime·MCache_Refill(MCache *c, int32 sizeclass);
-void   runtime·MCache_ReleaseAll(MCache *c);
-void   runtime·stackcache_clear(MCache *c);
-void   runtime·gcworkbuffree(void *b);
-
-enum
-{
-       KindSpecialFinalizer = 1,
-       KindSpecialProfile = 2,
-       // Note: The finalizer special must be first because if we're freeing
-       // an object, a finalizer special will cause the freeing operation
-       // to abort, and we want to keep the other special records around
-       // if that happens.
-};
-
-typedef struct Special Special;
-struct Special
-{
-       Special*        next;   // linked list in span
-       uint16          offset; // span offset of object
-       byte            kind;   // kind of Special
-};
-
-// The described object has a finalizer set for it.
-typedef struct SpecialFinalizer SpecialFinalizer;
-struct SpecialFinalizer
-{
-       Special         special;
-       FuncVal*        fn;
-       uintptr         nret;
-       Type*           fint;
-       PtrType*        ot;
-};
-
-// The described object is being heap profiled.
-typedef struct Bucket Bucket; // from mprof.h
-typedef struct SpecialProfile SpecialProfile;
-struct SpecialProfile
-{
-       Special special;
-       Bucket* b;
-};
-
-// An MSpan is a run of pages.
-enum
-{
-       MSpanInUse = 0, // allocated for garbage collected heap
-       MSpanStack,     // allocated for use by stack allocator
-       MSpanFree,
-       MSpanListHead,
-       MSpanDead,
-};
-struct MSpan
-{
-       MSpan   *next;          // in a span linked list
-       MSpan   *prev;          // in a span linked list
-       pageID  start;          // starting page number
-       uintptr npages;         // number of pages in span
-       MLink   *freelist;      // list of free objects
-       // sweep generation:
-       // if sweepgen == h->sweepgen - 2, the span needs sweeping
-       // if sweepgen == h->sweepgen - 1, the span is currently being swept
-       // if sweepgen == h->sweepgen, the span is swept and ready to use
-       // h->sweepgen is incremented by 2 after every GC
-       uint32  sweepgen;
-       uint16  ref;            // capacity - number of objects in freelist
-       uint8   sizeclass;      // size class
-       bool    incache;        // being used by an MCache
-       uint8   state;          // MSpanInUse etc
-       uint8   needzero;       // needs to be zeroed before allocation
-       uintptr elemsize;       // computed from sizeclass or from npages
-       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
-       Mutex   specialLock;    // guards specials list
-       Special *specials;      // linked list of special records sorted by offset.
-};
-
-void   runtime·MSpan_Init(MSpan *span, pageID start, uintptr npages);
-void   runtime·MSpan_EnsureSwept(MSpan *span);
-bool   runtime·MSpan_Sweep(MSpan *span, bool preserve);
-
-// Every MSpan is in one doubly-linked list,
-// either one of the MHeap's free lists or one of the
-// MCentral's span lists.  We use empty MSpan structures as list heads.
-void   runtime·MSpanList_Init(MSpan *list);
-bool   runtime·MSpanList_IsEmpty(MSpan *list);
-void   runtime·MSpanList_Insert(MSpan *list, MSpan *span);
-void   runtime·MSpanList_InsertBack(MSpan *list, MSpan *span);
-void   runtime·MSpanList_Remove(MSpan *span); // from whatever list it is in
-
-
-// Central list of free objects of a given size.
-struct MCentral
-{
-       Mutex  lock;
-       int32 sizeclass;
-       MSpan nonempty; // list of spans with a free object
-       MSpan empty;    // list of spans with no free objects (or cached in an MCache)
-};
-
-void   runtime·MCentral_Init(MCentral *c, int32 sizeclass);
-MSpan* runtime·MCentral_CacheSpan(MCentral *c);
-void   runtime·MCentral_UncacheSpan(MCentral *c, MSpan *s);
-bool   runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end, bool preserve);
-
-// Main malloc heap.
-// The heap itself is the "free[]" and "large" arrays,
-// but all the other global data is here too.
-struct MHeap
-{
-       Mutex  lock;
-       MSpan free[MaxMHeapList];       // free lists of given length
-       MSpan freelarge;                // free lists length >= MaxMHeapList
-       MSpan busy[MaxMHeapList];       // busy lists of large objects of given length
-       MSpan busylarge;                // busy lists of large objects length >= MaxMHeapList
-       MSpan **allspans;               // all spans out there
-       MSpan **gcspans;                // copy of allspans referenced by GC marker or sweeper
-       uint32  nspan;
-       uint32  nspancap;
-       uint32  sweepgen;               // sweep generation, see comment in MSpan
-       uint32  sweepdone;              // all spans are swept
-
-       // span lookup
-       MSpan** spans;
-       uintptr spans_mapped;
-
-       // range of addresses we might see in the heap
-       byte *bitmap;
-       uintptr bitmap_mapped;
-       byte *arena_start;
-       byte *arena_used;
-       byte *arena_end;
-       bool arena_reserved;
-
-       // central free lists for small size classes.
-       // the padding makes sure that the MCentrals are
-       // spaced CacheLineSize bytes apart, so that each MCentral.lock
-       // gets its own cache line.
-       struct MHeapCentral {
-               MCentral mcentral;
-               byte pad[CacheLineSize];
-       } central[NumSizeClasses];
-
-       FixAlloc spanalloc;     // allocator for Span*
-       FixAlloc cachealloc;    // allocator for MCache*
-       FixAlloc specialfinalizeralloc; // allocator for SpecialFinalizer*
-       FixAlloc specialprofilealloc;   // allocator for SpecialProfile*
-       Mutex speciallock; // lock for sepcial record allocators.
-
-       // Malloc stats.
-       uint64 largefree;       // bytes freed for large objects (>MaxSmallSize)
-       uint64 nlargefree;      // number of frees for large objects (>MaxSmallSize)
-       uint64 nsmallfree[NumSizeClasses];      // number of frees for small objects (<=MaxSmallSize)
-};
-#define runtime·mheap runtime·mheap_
-extern MHeap runtime·mheap;
-
-void   runtime·MHeap_Init(MHeap *h);
-MSpan* runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero);
-MSpan* runtime·MHeap_AllocStack(MHeap *h, uintptr npage);
-void   runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct);
-void   runtime·MHeap_FreeStack(MHeap *h, MSpan *s);
-MSpan* runtime·MHeap_Lookup(MHeap *h, void *v);
-MSpan* runtime·MHeap_LookupMaybe(MHeap *h, void *v);
-void*  runtime·MHeap_SysAlloc(MHeap *h, uintptr n);
-void   runtime·MHeap_MapBits(MHeap *h);
-void   runtime·MHeap_MapSpans(MHeap *h);
-void   runtime·MHeap_Scavenge(int32 k, uint64 now, uint64 limit);
-
-void*  runtime·persistentalloc(uintptr size, uintptr align, uint64 *stat);
-int32  runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **s);
-uintptr        runtime·sweepone(void);
-void   runtime·markspan(void *v, uintptr size, uintptr n, bool leftover);
-void   runtime·unmarkspan(void *v, uintptr size);
-void   runtime·purgecachedstats(MCache*);
-void   runtime·tracealloc(void*, uintptr, Type*);
-void   runtime·tracefree(void*, uintptr);
-void   runtime·tracegc(void);
-
-int32  runtime·gcpercent;
-int32  runtime·readgogc(void);
-void   runtime·clearpools(void);
-
-enum
-{
-       // flags to malloc
-       FlagNoScan      = 1<<0, // GC doesn't have to scan object
-       FlagNoZero      = 1<<1, // don't zero memory
-};
-
-void   runtime·mProf_Malloc(void*, uintptr);
-void   runtime·mProf_Free(Bucket*, uintptr, bool);
-void   runtime·mProf_GC(void);
-void   runtime·iterate_memprof(void (**callback)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr));
-int32  runtime·gcprocs(void);
-void   runtime·helpgc(int32 nproc);
-void   runtime·gchelper(void);
-void   runtime·createfing(void);
-G*     runtime·wakefing(void);
-void   runtime·getgcmask(byte*, Type*, byte**, uintptr*);
-
-// NOTE: Layout known to queuefinalizer.
-typedef struct Finalizer Finalizer;
-struct Finalizer
-{
-       FuncVal *fn;    // function to call
-       void *arg;      // ptr to object
-       uintptr nret;   // bytes of return values from fn
-       Type *fint;     // type of first argument of fn
-       PtrType *ot;    // type of ptr to object
-};
-
-typedef struct FinBlock FinBlock;
-struct FinBlock
-{
-       FinBlock *alllink;
-       FinBlock *next;
-       int32 cnt;
-       int32 cap;
-       Finalizer fin[1];
-};
-extern Mutex   runtime·finlock;       // protects the following variables
-extern G*      runtime·fing;
-extern bool    runtime·fingwait;
-extern bool    runtime·fingwake;
-extern FinBlock        *runtime·finq;         // list of finalizers that are to be executed
-extern FinBlock        *runtime·finc;         // cache of free blocks
-
-void   runtime·setprofilebucket_m(void);
-
-bool   runtime·addfinalizer(void*, FuncVal *fn, uintptr, Type*, PtrType*);
-void   runtime·removefinalizer(void*);
-void   runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType *ot);
-bool   runtime·freespecial(Special *s, void *p, uintptr size, bool freed);
-
-// Information from the compiler about the layout of stack frames.
-struct BitVector
-{
-       int32 n; // # of bits
-       uint8 *bytedata;
-};
-typedef struct StackMap StackMap;
-struct StackMap
-{
-       int32 n; // number of bitmaps
-       int32 nbit; // number of bits in each bitmap
-       uint8 bytedata[]; // bitmaps, each starting on a 32-bit boundary
-};
-// Returns pointer map data for the given stackmap index
-// (the index is encoded in PCDATA_StackMapIndex).
-BitVector      runtime·stackmapdata(StackMap *stackmap, int32 n);
-
-extern BitVector       runtime·gcdatamask;
-extern BitVector       runtime·gcbssmask;
-
-// defined in mgc0.go
-void   runtime·gc_m_ptr(Eface*);
-void   runtime·gc_g_ptr(Eface*);
-void   runtime·gc_itab_ptr(Eface*);
-
-void  runtime·setgcpercent_m(void);
-
-// Value we use to mark dead pointers when GODEBUG=gcdead=1.
-#define PoisonGC ((uintptr)0xf969696969696969ULL)
-#define PoisonStack ((uintptr)0x6868686868686868ULL)
diff --git a/src/runtime/malloc1.go b/src/runtime/malloc1.go
new file mode 100644 (file)
index 0000000..db02d9c
--- /dev/null
@@ -0,0 +1,318 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// See malloc.h for overview.
+//
+// TODO(rsc): double-check stats.
+
+package runtime
+
+import "unsafe"
+
+const _MaxArena32 = 2 << 30
+
+// For use by Go. If it were a C enum it would be made available automatically,
+// but the value of MaxMem is too large for enum.
+// XXX - uintptr runtime·maxmem = MaxMem;
+
+func mlookup(v uintptr, base *uintptr, size *uintptr, sp **mspan) int32 {
+       _g_ := getg()
+
+       _g_.m.mcache.local_nlookup++
+       if ptrSize == 4 && _g_.m.mcache.local_nlookup >= 1<<30 {
+               // purge cache stats to prevent overflow
+               lock(&mheap_.lock)
+               purgecachedstats(_g_.m.mcache)
+               unlock(&mheap_.lock)
+       }
+
+       s := mHeap_LookupMaybe(&mheap_, unsafe.Pointer(v))
+       if sp != nil {
+               *sp = s
+       }
+       if s == nil {
+               if base != nil {
+                       *base = 0
+               }
+               if size != nil {
+                       *size = 0
+               }
+               return 0
+       }
+
+       p := uintptr(s.start) << _PageShift
+       if s.sizeclass == 0 {
+               // Large object.
+               if base != nil {
+                       *base = p
+               }
+               if size != nil {
+                       *size = s.npages << _PageShift
+               }
+               return 1
+       }
+
+       n := s.elemsize
+       if base != nil {
+               i := (uintptr(v) - uintptr(p)) / n
+               *base = p + i*n
+       }
+       if size != nil {
+               *size = n
+       }
+
+       return 1
+}
+
+//go:nosplit
+func purgecachedstats(c *mcache) {
+       // Protected by either heap or GC lock.
+       h := &mheap_
+       memstats.heap_alloc += uint64(c.local_cachealloc)
+       c.local_cachealloc = 0
+       memstats.tinyallocs += uint64(c.local_tinyallocs)
+       c.local_tinyallocs = 0
+       memstats.nlookup += uint64(c.local_nlookup)
+       c.local_nlookup = 0
+       h.largefree += uint64(c.local_largefree)
+       c.local_largefree = 0
+       h.nlargefree += uint64(c.local_nlargefree)
+       c.local_nlargefree = 0
+       for i := 0; i < len(c.local_nsmallfree); i++ {
+               h.nsmallfree[i] += uint64(c.local_nsmallfree[i])
+               c.local_nsmallfree[i] = 0
+       }
+}
+
+func mallocinit() {
+       initSizes()
+
+       if class_to_size[_TinySizeClass] != _TinySize {
+               gothrow("bad TinySizeClass")
+       }
+
+       var p, arena_size, bitmap_size, spans_size, p_size, limit uintptr
+       var reserved bool
+
+       // limit = runtime.memlimit();
+       // See https://code.google.com/p/go/issues/detail?id=5049
+       // TODO(rsc): Fix after 1.1.
+       limit = 0
+
+       // Set up the allocation arena, a contiguous area of memory where
+       // allocated data will be found.  The arena begins with a bitmap large
+       // enough to hold 4 bits per allocated word.
+       if ptrSize == 8 && (limit == 0 || limit > 1<<30) {
+               // On a 64-bit machine, allocate from a single contiguous reservation.
+               // 128 GB (MaxMem) should be big enough for now.
+               //
+               // The code will work with the reservation at any address, but ask
+               // SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
+               // Allocating a 128 GB region takes away 37 bits, and the amd64
+               // doesn't let us choose the top 17 bits, so that leaves the 11 bits
+               // in the middle of 0x00c0 for us to choose.  Choosing 0x00c0 means
+               // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
+               // In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
+               // UTF-8 sequences, and they are otherwise as far away from
+               // ff (likely a common byte) as possible.  If that fails, we try other 0xXXc0
+               // addresses.  An earlier attempt to use 0x11f8 caused out of memory errors
+               // on OS X during thread allocations.  0x00c0 causes conflicts with
+               // AddressSanitizer which reserves all memory up to 0x0100.
+               // These choices are both for debuggability and to reduce the
+               // odds of the conservative garbage collector not collecting memory
+               // because some non-pointer block of memory had a bit pattern
+               // that matched a memory address.
+               //
+               // Actually we reserve 136 GB (because the bitmap ends up being 8 GB)
+               // but it hardly matters: e0 00 is not valid UTF-8 either.
+               //
+               // If this fails we fall back to the 32 bit memory mechanism
+               arena_size = round(_MaxMem, _PageSize)
+               bitmap_size = arena_size / (ptrSize * 8 / 4)
+               spans_size = arena_size / _PageSize * ptrSize
+               spans_size = round(spans_size, _PageSize)
+               for i := 0; i <= 0x7f; i++ {
+                       p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32)
+                       p_size = bitmap_size + spans_size + arena_size + _PageSize
+                       p = uintptr(sysReserve(unsafe.Pointer(p), p_size, &reserved))
+                       if p != 0 {
+                               break
+                       }
+               }
+       }
+
+       if p == 0 {
+               // On a 32-bit machine, we can't typically get away
+               // with a giant virtual address space reservation.
+               // Instead we map the memory information bitmap
+               // immediately after the data segment, large enough
+               // to handle another 2GB of mappings (256 MB),
+               // along with a reservation for another 512 MB of memory.
+               // When that gets used up, we'll start asking the kernel
+               // for any memory anywhere and hope it's in the 2GB
+               // following the bitmap (presumably the executable begins
+               // near the bottom of memory, so we'll have to use up
+               // most of memory before the kernel resorts to giving out
+               // memory before the beginning of the text segment).
+               //
+               // Alternatively we could reserve 512 MB bitmap, enough
+               // for 4GB of mappings, and then accept any memory the
+               // kernel threw at us, but normally that's a waste of 512 MB
+               // of address space, which is probably too much in a 32-bit world.
+               bitmap_size = _MaxArena32 / (ptrSize * 8 / 4)
+               arena_size = 512 << 20
+               spans_size = _MaxArena32 / _PageSize * ptrSize
+               if limit > 0 && arena_size+bitmap_size+spans_size > limit {
+                       bitmap_size = (limit / 9) &^ ((1 << _PageShift) - 1)
+                       arena_size = bitmap_size * 8
+                       spans_size = arena_size / _PageSize * ptrSize
+               }
+               spans_size = round(spans_size, _PageSize)
+
+               // SysReserve treats the address we ask for, end, as a hint,
+               // not as an absolute requirement.  If we ask for the end
+               // of the data segment but the operating system requires
+               // a little more space before we can start allocating, it will
+               // give out a slightly higher pointer.  Except QEMU, which
+               // is buggy, as usual: it won't adjust the pointer upward.
+               // So adjust it upward a little bit ourselves: 1/4 MB to get
+               // away from the running binary image and then round up
+               // to a MB boundary.
+               p = round(uintptr(unsafe.Pointer(&end))+(1<<18), 1<<20)
+               p_size = bitmap_size + spans_size + arena_size + _PageSize
+               p = uintptr(sysReserve(unsafe.Pointer(p), p_size, &reserved))
+               if p == 0 {
+                       gothrow("runtime: cannot reserve arena virtual address space")
+               }
+       }
+
+       // PageSize can be larger than OS definition of page size,
+       // so SysReserve can give us a PageSize-unaligned pointer.
+       // To overcome this we ask for PageSize more and round up the pointer.
+       p1 := round(p, _PageSize)
+
+       mheap_.spans = (**mspan)(unsafe.Pointer(p1))
+       mheap_.bitmap = p1 + spans_size
+       mheap_.arena_start = p1 + (spans_size + bitmap_size)
+       mheap_.arena_used = mheap_.arena_start
+       mheap_.arena_end = p + p_size
+       mheap_.arena_reserved = reserved
+
+       if mheap_.arena_start&(_PageSize-1) != 0 {
+               println("bad pagesize", hex(p), hex(p1), hex(spans_size), hex(bitmap_size), hex(_PageSize), "start", hex(mheap_.arena_start))
+               gothrow("misrounded allocation in mallocinit")
+       }
+
+       // Initialize the rest of the allocator.
+       mHeap_Init(&mheap_, spans_size)
+       _g_ := getg()
+       _g_.m.mcache = allocmcache()
+}
+
+func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
+       if n > uintptr(h.arena_end)-uintptr(h.arena_used) {
+               // We are in 32-bit mode, maybe we didn't use all possible address space yet.
+               // Reserve some more space.
+               p_size := round(n+_PageSize, 256<<20)
+               new_end := h.arena_end + p_size
+               if new_end <= h.arena_start+_MaxArena32 {
+                       // TODO: It would be bad if part of the arena
+                       // is reserved and part is not.
+                       var reserved bool
+                       p := uintptr(sysReserve((unsafe.Pointer)(h.arena_end), p_size, &reserved))
+                       if p == h.arena_end {
+                               h.arena_end = new_end
+                               h.arena_reserved = reserved
+                       } else if p+p_size <= h.arena_start+_MaxArena32 {
+                               // Keep everything page-aligned.
+                               // Our pages are bigger than hardware pages.
+                               h.arena_end = p + p_size
+                               h.arena_used = p + (-uintptr(p) & (_PageSize - 1))
+                               h.arena_reserved = reserved
+                       } else {
+                               var stat uint64
+                               sysFree((unsafe.Pointer)(p), p_size, &stat)
+                       }
+               }
+       }
+
+       if n <= uintptr(h.arena_end)-uintptr(h.arena_used) {
+               // Keep taking from our reservation.
+               p := h.arena_used
+               sysMap((unsafe.Pointer)(p), n, h.arena_reserved, &memstats.heap_sys)
+               h.arena_used += n
+               mHeap_MapBits(h)
+               mHeap_MapSpans(h)
+               if raceenabled {
+                       racemapshadow((unsafe.Pointer)(p), n)
+               }
+
+               if uintptr(p)&(_PageSize-1) != 0 {
+                       gothrow("misrounded allocation in MHeap_SysAlloc")
+               }
+               return (unsafe.Pointer)(p)
+       }
+
+       // If using 64-bit, our reservation is all we have.
+       if uintptr(h.arena_end)-uintptr(h.arena_start) >= _MaxArena32 {
+               return nil
+       }
+
+       // On 32-bit, once the reservation is gone we can
+       // try to get memory at a location chosen by the OS
+       // and hope that it is in the range we allocated bitmap for.
+       p_size := round(n, _PageSize) + _PageSize
+       p := uintptr(sysAlloc(p_size, &memstats.heap_sys))
+       if p == 0 {
+               return nil
+       }
+
+       if p < h.arena_start || uintptr(p)+p_size-uintptr(h.arena_start) >= _MaxArena32 {
+               print("runtime: memory allocated by OS (", p, ") not in usable range [", hex(h.arena_start), ",", hex(h.arena_start+_MaxArena32), ")\n")
+               sysFree((unsafe.Pointer)(p), p_size, &memstats.heap_sys)
+               return nil
+       }
+
+       p_end := p + p_size
+       p += -p & (_PageSize - 1)
+       if uintptr(p)+n > uintptr(h.arena_used) {
+               h.arena_used = p + n
+               if p_end > h.arena_end {
+                       h.arena_end = p_end
+               }
+               mHeap_MapBits(h)
+               mHeap_MapSpans(h)
+               if raceenabled {
+                       racemapshadow((unsafe.Pointer)(p), n)
+               }
+       }
+
+       if uintptr(p)&(_PageSize-1) != 0 {
+               gothrow("misrounded allocation in MHeap_SysAlloc")
+       }
+       return (unsafe.Pointer)(p)
+}
+
+var end struct{}
+
+func largeAlloc(size uintptr, flag uint32) *mspan {
+       // print("largeAlloc size=", size, "\n")
+
+       if size+_PageSize < size {
+               gothrow("out of memory")
+       }
+       npages := size >> _PageShift
+       if size&_PageMask != 0 {
+               npages++
+       }
+       s := mHeap_Alloc(&mheap_, npages, 0, true, flag&_FlagNoZero == 0)
+       if s == nil {
+               gothrow("out of memory")
+       }
+       s.limit = uintptr(s.start)<<_PageShift + size
+       v := unsafe.Pointer(uintptr(s.start) << _PageShift)
+       // setup for mark sweep
+       markspan(v, 0, 0, true)
+       return s
+}
diff --git a/src/runtime/malloc2.go b/src/runtime/malloc2.go
new file mode 100644 (file)
index 0000000..c175c2a
--- /dev/null
@@ -0,0 +1,475 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// Memory allocator, based on tcmalloc.
+// http://goog-perftools.sourceforge.net/doc/tcmalloc.html
+
+// The main allocator works in runs of pages.
+// Small allocation sizes (up to and including 32 kB) are
+// rounded to one of about 100 size classes, each of which
+// has its own free list of objects of exactly that size.
+// Any free page of memory can be split into a set of objects
+// of one size class, which are then managed using free list
+// allocators.
+//
+// The allocator's data structures are:
+//
+//     FixAlloc: a free-list allocator for fixed-size objects,
+//             used to manage storage used by the allocator.
+//     MHeap: the malloc heap, managed at page (4096-byte) granularity.
+//     MSpan: a run of pages managed by the MHeap.
+//     MCentral: a shared free list for a given size class.
+//     MCache: a per-thread (in Go, per-P) cache for small objects.
+//     MStats: allocation statistics.
+//
+// Allocating a small object proceeds up a hierarchy of caches:
+//
+//     1. Round the size up to one of the small size classes
+//        and look in the corresponding MCache free list.
+//        If the list is not empty, allocate an object from it.
+//        This can all be done without acquiring a lock.
+//
+//     2. If the MCache free list is empty, replenish it by
+//        taking a bunch of objects from the MCentral free list.
+//        Moving a bunch amortizes the cost of acquiring the MCentral lock.
+//
+//     3. If the MCentral free list is empty, replenish it by
+//        allocating a run of pages from the MHeap and then
+//        chopping that memory into a objects of the given size.
+//        Allocating many objects amortizes the cost of locking
+//        the heap.
+//
+//     4. If the MHeap is empty or has no page runs large enough,
+//        allocate a new group of pages (at least 1MB) from the
+//        operating system.  Allocating a large run of pages
+//        amortizes the cost of talking to the operating system.
+//
+// Freeing a small object proceeds up the same hierarchy:
+//
+//     1. Look up the size class for the object and add it to
+//        the MCache free list.
+//
+//     2. If the MCache free list is too long or the MCache has
+//        too much memory, return some to the MCentral free lists.
+//
+//     3. If all the objects in a given span have returned to
+//        the MCentral list, return that span to the page heap.
+//
+//     4. If the heap has too much memory, return some to the
+//        operating system.
+//
+//     TODO(rsc): Step 4 is not implemented.
+//
+// Allocating and freeing a large object uses the page heap
+// directly, bypassing the MCache and MCentral free lists.
+//
+// The small objects on the MCache and MCentral free lists
+// may or may not be zeroed.  They are zeroed if and only if
+// the second word of the object is zero.  A span in the
+// page heap is zeroed unless s->needzero is set. When a span
+// is allocated to break into small objects, it is zeroed if needed
+// and s->needzero is set. There are two main benefits to delaying the
+// zeroing this way:
+//
+//     1. stack frames allocated from the small object lists
+//        or the page heap can avoid zeroing altogether.
+//     2. the cost of zeroing when reusing a small object is
+//        charged to the mutator, not the garbage collector.
+//
+// This C code was written with an eye toward translating to Go
+// in the future.  Methods have the form Type_Method(Type *t, ...).
+
+const (
+       _PageShift = 13
+       _PageSize  = 1 << _PageShift
+       _PageMask  = _PageSize - 1
+)
+
+const (
+       // _64bit = 1 on 64-bit systems, 0 on 32-bit systems
+       _64bit = 1 << (^uintptr(0) >> 63) / 2
+
+       // Computed constant.  The definition of MaxSmallSize and the
+       // algorithm in msize.c produce some number of different allocation
+       // size classes.  NumSizeClasses is that number.  It's needed here
+       // because there are static arrays of this length; when msize runs its
+       // size choosing algorithm it double-checks that NumSizeClasses agrees.
+       _NumSizeClasses = 67
+
+       // Tunable constants.
+       _MaxSmallSize = 32 << 10
+
+       // Tiny allocator parameters, see "Tiny allocator" comment in malloc.goc.
+       _TinySize      = 16
+       _TinySizeClass = 2
+
+       _FixAllocChunk  = 16 << 10               // Chunk size for FixAlloc
+       _MaxMHeapList   = 1 << (20 - _PageShift) // Maximum page length for fixed-size list in MHeap.
+       _HeapAllocChunk = 1 << 20                // Chunk size for heap growth
+
+       // Per-P, per order stack segment cache size.
+       _StackCacheSize = 32 * 1024
+
+       // Number of orders that get caching.  Order 0 is FixedStack
+       // and each successive order is twice as large.
+       _NumStackOrders = 3
+
+       // Number of bits in page to span calculations (4k pages).
+       // On Windows 64-bit we limit the arena to 32GB or 35 bits.
+       // Windows counts memory used by page table into committed memory
+       // of the process, so we can't reserve too much memory.
+       // See http://golang.org/issue/5402 and http://golang.org/issue/5236.
+       // On other 64-bit platforms, 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.
+       _MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows))*37 + (1-_64bit)*32
+       _MHeapMap_Bits      = _MHeapMap_TotalBits - _PageShift
+
+       _MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1)
+
+       // 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 32 cpus.
+       _MaxGcproc = 32
+)
+
+// A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
+type mlink struct {
+       next *mlink
+}
+
+// sysAlloc obtains a large chunk of zeroed memory from the
+// operating system, typically on the order of a hundred kilobytes
+// or a megabyte.
+// NOTE: sysAlloc returns OS-aligned memory, but the heap allocator
+// may use larger alignment, so the caller must be careful to realign the
+// memory obtained by sysAlloc.
+//
+// SysUnused notifies the operating system that the contents
+// of the memory region are no longer needed and can be reused
+// for other purposes.
+// SysUsed notifies the operating system that the contents
+// of the memory region are needed again.
+//
+// SysFree returns it unconditionally; this is only used if
+// an out-of-memory error has been detected midway through
+// an allocation.  It is okay if SysFree is a no-op.
+//
+// SysReserve reserves address space without allocating memory.
+// If the pointer passed to it is non-nil, the caller wants the
+// reservation there, but SysReserve can still choose another
+// location if that one is unavailable.  On some systems and in some
+// cases SysReserve will simply check that the address space is
+// available and not actually reserve it.  If SysReserve returns
+// non-nil, it sets *reserved to true if the address space is
+// reserved, false if it has merely been checked.
+// NOTE: SysReserve returns OS-aligned memory, but the heap allocator
+// may use larger alignment, so the caller must be careful to realign the
+// memory obtained by sysAlloc.
+//
+// SysMap maps previously reserved address space for use.
+// The reserved argument is true if the address space was really
+// reserved, not merely checked.
+//
+// SysFault marks a (already sysAlloc'd) region to fault
+// if accessed.  Used only for debugging the runtime.
+
+// FixAlloc is a simple free-list allocator for fixed size objects.
+// Malloc uses a FixAlloc wrapped around sysAlloc to manages its
+// MCache and MSpan objects.
+//
+// Memory returned by FixAlloc_Alloc is not zeroed.
+// The caller is responsible for locking around FixAlloc calls.
+// Callers can keep state in the object but the first word is
+// smashed by freeing and reallocating.
+type fixalloc struct {
+       size   uintptr
+       first  unsafe.Pointer // go func(unsafe.pointer, unsafe.pointer); f(arg, p) called first time p is returned
+       arg    unsafe.Pointer
+       list   *mlink
+       chunk  *byte
+       nchunk uint32
+       inuse  uintptr // in-use bytes now
+       stat   *uint64
+}
+
+// Statistics.
+// Shared with Go: if you edit this structure, also edit type MemStats in mem.go.
+type mstats struct {
+       // General statistics.
+       alloc       uint64 // bytes allocated and still in use
+       total_alloc uint64 // bytes allocated (even if freed)
+       sys         uint64 // bytes obtained from system (should be sum of xxx_sys below, no locking, approximate)
+       nlookup     uint64 // number of pointer lookups
+       nmalloc     uint64 // number of mallocs
+       nfree       uint64 // number of frees
+
+       // Statistics about malloc heap.
+       // protected by mheap.lock
+       heap_alloc    uint64 // bytes allocated and still in use
+       heap_sys      uint64 // bytes obtained from system
+       heap_idle     uint64 // bytes in idle spans
+       heap_inuse    uint64 // bytes in non-idle spans
+       heap_released uint64 // bytes released to the os
+       heap_objects  uint64 // total number of allocated objects
+
+       // Statistics about allocation of low-level fixed-size structures.
+       // Protected by FixAlloc locks.
+       stacks_inuse uint64 // this number is included in heap_inuse above
+       stacks_sys   uint64 // always 0 in mstats
+       mspan_inuse  uint64 // mspan structures
+       mspan_sys    uint64
+       mcache_inuse uint64 // mcache structures
+       mcache_sys   uint64
+       buckhash_sys uint64 // profiling bucket hash table
+       gc_sys       uint64
+       other_sys    uint64
+
+       // Statistics about garbage collector.
+       // Protected by mheap or stopping the world during GC.
+       next_gc        uint64 // next gc (in heap_alloc time)
+       last_gc        uint64 // last gc (in absolute time)
+       pause_total_ns uint64
+       pause_ns       [256]uint64 // circular buffer of recent gc pause lengths
+       pause_end      [256]uint64 // circular buffer of recent gc end times (nanoseconds since 1970)
+       numgc          uint32
+       enablegc       bool
+       debuggc        bool
+
+       // Statistics about allocation size classes.
+
+       by_size [_NumSizeClasses]struct {
+               size    uint32
+               nmalloc uint64
+               nfree   uint64
+       }
+
+       tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly
+}
+
+var memstats mstats
+
+// Size classes.  Computed and initialized by InitSizes.
+//
+// SizeToClass(0 <= n <= MaxSmallSize) returns the size class,
+//     1 <= sizeclass < NumSizeClasses, for n.
+//     Size class 0 is reserved to mean "not small".
+//
+// class_to_size[i] = largest size in class i
+// class_to_allocnpages[i] = number of pages to allocate when
+//     making new objects in class i
+
+var class_to_size [_NumSizeClasses]int32
+var class_to_allocnpages [_NumSizeClasses]int32
+var size_to_class8 [1024/8 + 1]int8
+var size_to_class128 [(_MaxSmallSize-1024)/128 + 1]int8
+
+type mcachelist struct {
+       list  *mlink
+       nlist uint32
+}
+
+type stackfreelist struct {
+       list *mlink  // linked list of free stacks
+       size uintptr // total size of stacks in list
+}
+
+// Per-thread (in Go, per-P) cache for small objects.
+// No locking needed because it is per-thread (per-P).
+type mcache struct {
+       // The following members are accessed on every malloc,
+       // so they are grouped here for better caching.
+       next_sample      int32  // trigger heap sample after allocating this many bytes
+       local_cachealloc intptr // bytes allocated (or freed) from cache since last lock of heap
+       // Allocator cache for tiny objects w/o pointers.
+       // See "Tiny allocator" comment in malloc.goc.
+       tiny             *byte
+       tinysize         uintptr
+       local_tinyallocs uintptr // number of tiny allocs not counted in other stats
+
+       // The rest is not accessed on every malloc.
+       alloc [_NumSizeClasses]*mspan // spans to allocate from
+
+       stackcache [_NumStackOrders]stackfreelist
+
+       sudogcache *sudog
+
+       gcworkbuf unsafe.Pointer
+
+       // Local allocator stats, flushed during GC.
+       local_nlookup    uintptr                  // number of pointer lookups
+       local_largefree  uintptr                  // bytes freed for large objects (>maxsmallsize)
+       local_nlargefree uintptr                  // number of frees for large objects (>maxsmallsize)
+       local_nsmallfree [_NumSizeClasses]uintptr // number of frees for small objects (<=maxsmallsize)
+}
+
+const (
+       _KindSpecialFinalizer = 1
+       _KindSpecialProfile   = 2
+       // Note: The finalizer special must be first because if we're freeing
+       // an object, a finalizer special will cause the freeing operation
+       // to abort, and we want to keep the other special records around
+       // if that happens.
+)
+
+type special struct {
+       next   *special // linked list in span
+       offset uint16   // span offset of object
+       kind   byte     // kind of special
+}
+
+// The described object has a finalizer set for it.
+type specialfinalizer struct {
+       special special
+       fn      *funcval
+       nret    uintptr
+       fint    *_type
+       ot      *ptrtype
+}
+
+// The described object is being heap profiled.
+type specialprofile struct {
+       special special
+       b       *bucket
+}
+
+// An MSpan is a run of pages.
+const (
+       _MSpanInUse = iota // allocated for garbage collected heap
+       _MSpanStack        // allocated for use by stack allocator
+       _MSpanFree
+       _MSpanListHead
+       _MSpanDead
+)
+
+type mspan struct {
+       next     *mspan  // in a span linked list
+       prev     *mspan  // in a span linked list
+       start    pageID  // starting page number
+       npages   uintptr // number of pages in span
+       freelist *mlink  // list of free objects
+       // sweep generation:
+       // if sweepgen == h->sweepgen - 2, the span needs sweeping
+       // if sweepgen == h->sweepgen - 1, the span is currently being swept
+       // if sweepgen == h->sweepgen, the span is swept and ready to use
+       // h->sweepgen is incremented by 2 after every GC
+       sweepgen    uint32
+       ref         uint16   // capacity - number of objects in freelist
+       sizeclass   uint8    // size class
+       incache     bool     // being used by an mcache
+       state       uint8    // mspaninuse etc
+       needzero    uint8    // needs to be zeroed before allocation
+       elemsize    uintptr  // computed from sizeclass or from npages
+       unusedsince int64    // first time spotted by gc in mspanfree state
+       npreleased  uintptr  // number of pages released to the os
+       limit       uintptr  // end of data in span
+       speciallock mutex    // guards specials list
+       specials    *special // linked list of special records sorted by offset.
+}
+
+// Every MSpan is in one doubly-linked list,
+// either one of the MHeap's free lists or one of the
+// MCentral's span lists.  We use empty MSpan structures as list heads.
+
+// Central list of free objects of a given size.
+type mcentral struct {
+       lock      mutex
+       sizeclass int32
+       nonempty  mspan // list of spans with a free object
+       empty     mspan // list of spans with no free objects (or cached in an mcache)
+}
+
+// Main malloc heap.
+// The heap itself is the "free[]" and "large" arrays,
+// but all the other global data is here too.
+type mheap struct {
+       lock      mutex
+       free      [_MaxMHeapList]mspan // free lists of given length
+       freelarge mspan                // free lists length >= _MaxMHeapList
+       busy      [_MaxMHeapList]mspan // busy lists of large objects of given length
+       busylarge mspan                // busy lists of large objects length >= _MaxMHeapList
+       allspans  **mspan              // all spans out there
+       gcspans   **mspan              // copy of allspans referenced by gc marker or sweeper
+       nspan     uint32
+       sweepgen  uint32 // sweep generation, see comment in mspan
+       sweepdone uint32 // all spans are swept
+
+       // span lookup
+       spans        **mspan
+       spans_mapped uintptr
+
+       // range of addresses we might see in the heap
+       bitmap         uintptr
+       bitmap_mapped  uintptr
+       arena_start    uintptr
+       arena_used     uintptr
+       arena_end      uintptr
+       arena_reserved bool
+
+       // central free lists for small size classes.
+       // the padding makes sure that the MCentrals are
+       // spaced CacheLineSize bytes apart, so that each MCentral.lock
+       // gets its own cache line.
+       central [_NumSizeClasses]struct {
+               mcentral mcentral
+               pad      [_CacheLineSize]byte
+       }
+
+       spanalloc             fixalloc // allocator for span*
+       cachealloc            fixalloc // allocator for mcache*
+       specialfinalizeralloc fixalloc // allocator for specialfinalizer*
+       specialprofilealloc   fixalloc // allocator for specialprofile*
+       speciallock           mutex    // lock for sepcial record allocators.
+
+       // Malloc stats.
+       largefree  uint64                  // bytes freed for large objects (>maxsmallsize)
+       nlargefree uint64                  // number of frees for large objects (>maxsmallsize)
+       nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize)
+}
+
+var mheap_ mheap
+
+const (
+       // flags to malloc
+       _FlagNoScan = 1 << 0 // GC doesn't have to scan object
+       _FlagNoZero = 1 << 1 // don't zero memory
+)
+
+// NOTE: Layout known to queuefinalizer.
+type finalizer struct {
+       fn   *funcval       // function to call
+       arg  unsafe.Pointer // ptr to object
+       nret uintptr        // bytes of return values from fn
+       fint *_type         // type of first argument of fn
+       ot   *ptrtype       // type of ptr to object
+}
+
+type finblock struct {
+       alllink *finblock
+       next    *finblock
+       cnt     int32
+       cap     int32
+       fin     [1]finalizer
+}
+
+// Information from the compiler about the layout of stack frames.
+type bitvector struct {
+       n        int32 // # of bits
+       bytedata *uint8
+}
+
+type stackmap struct {
+       n        int32   // number of bitmaps
+       nbit     int32   // number of bits in each bitmap
+       bytedata [0]byte // bitmaps, each starting on a 32-bit boundary
+}
+
+// Returns pointer map data for the given stackmap index
+// (the index is encoded in PCDATA_StackMapIndex).
+
+// defined in mgc0.go
diff --git a/src/runtime/mcache.c b/src/runtime/mcache.c
deleted file mode 100644 (file)
index 5fdbe32..0000000
+++ /dev/null
@@ -1,115 +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.
-
-// Per-P malloc cache for small objects.
-//
-// See malloc.h for an overview.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-extern volatile intgo runtime·MemProfileRate;
-
-// dummy MSpan that contains no free objects.
-MSpan runtime·emptymspan;
-
-MCache*
-runtime·allocmcache(void)
-{
-       intgo rate;
-       MCache *c;
-       int32 i;
-
-       runtime·lock(&runtime·mheap.lock);
-       c = runtime·FixAlloc_Alloc(&runtime·mheap.cachealloc);
-       runtime·unlock(&runtime·mheap.lock);
-       runtime·memclr((byte*)c, sizeof(*c));
-       for(i = 0; i < NumSizeClasses; i++)
-               c->alloc[i] = &runtime·emptymspan;
-
-       // Set first allocation sample size.
-       rate = runtime·MemProfileRate;
-       if(rate > 0x3fffffff)   // make 2*rate not overflow
-               rate = 0x3fffffff;
-       if(rate != 0)
-               c->next_sample = runtime·fastrand1() % (2*rate);
-
-       return c;
-}
-
-static void
-freemcache(MCache *c)
-{
-       runtime·MCache_ReleaseAll(c);
-       runtime·stackcache_clear(c);
-       runtime·gcworkbuffree(c->gcworkbuf);
-       runtime·lock(&runtime·mheap.lock);
-       runtime·purgecachedstats(c);
-       runtime·FixAlloc_Free(&runtime·mheap.cachealloc, c);
-       runtime·unlock(&runtime·mheap.lock);
-}
-
-static void
-freemcache_m(void)
-{
-       MCache *c;
-
-       c = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       freemcache(c);
-}
-
-void
-runtime·freemcache(MCache *c)
-{
-       void (*fn)(void);
-
-       g->m->ptrarg[0] = c;
-       fn = freemcache_m;
-       runtime·onM(&fn);
-}
-
-// Gets a span that has a free object in it and assigns it
-// to be the cached span for the given sizeclass.  Returns this span.
-MSpan*
-runtime·MCache_Refill(MCache *c, int32 sizeclass)
-{
-       MSpan *s;
-
-       g->m->locks++;
-       // Return the current cached span to the central lists.
-       s = c->alloc[sizeclass];
-       if(s->freelist != nil)
-               runtime·throw("refill on a nonempty span");
-       if(s != &runtime·emptymspan)
-               s->incache = false;
-
-       // Get a new cached span from the central lists.
-       s = runtime·MCentral_CacheSpan(&runtime·mheap.central[sizeclass].mcentral);
-       if(s == nil)
-               runtime·throw("out of memory");
-       if(s->freelist == nil) {
-               runtime·printf("%d %d\n", s->ref, (int32)((s->npages << PageShift) / s->elemsize));
-               runtime·throw("empty span");
-       }
-       c->alloc[sizeclass] = s;
-       g->m->locks--;
-       return s;
-}
-
-void
-runtime·MCache_ReleaseAll(MCache *c)
-{
-       int32 i;
-       MSpan *s;
-
-       for(i=0; i<NumSizeClasses; i++) {
-               s = c->alloc[i];
-               if(s != &runtime·emptymspan) {
-                       runtime·MCentral_UncacheSpan(&runtime·mheap.central[i].mcentral, s);
-                       c->alloc[i] = &runtime·emptymspan;
-               }
-       }
-}
diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go
new file mode 100644 (file)
index 0000000..d3afef6
--- /dev/null
@@ -0,0 +1,86 @@
+// 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.
+
+// Per-P malloc cache for small objects.
+//
+// See malloc.h for an overview.
+
+package runtime
+
+import "unsafe"
+
+// dummy MSpan that contains no free objects.
+var emptymspan mspan
+
+func allocmcache() *mcache {
+       lock(&mheap_.lock)
+       c := (*mcache)(fixAlloc_Alloc(&mheap_.cachealloc))
+       unlock(&mheap_.lock)
+       memclr(unsafe.Pointer(c), unsafe.Sizeof(*c))
+       for i := 0; i < _NumSizeClasses; i++ {
+               c.alloc[i] = &emptymspan
+       }
+
+       // Set first allocation sample size.
+       rate := MemProfileRate
+       if rate > 0x3fffffff { // make 2*rate not overflow
+               rate = 0x3fffffff
+       }
+       if rate != 0 {
+               c.next_sample = int32(int(fastrand1()) % (2 * rate))
+       }
+
+       return c
+}
+
+func freemcache(c *mcache) {
+       systemstack(func() {
+               mCache_ReleaseAll(c)
+               stackcache_clear(c)
+               gcworkbuffree(c.gcworkbuf)
+               lock(&mheap_.lock)
+               purgecachedstats(c)
+               fixAlloc_Free(&mheap_.cachealloc, unsafe.Pointer(c))
+               unlock(&mheap_.lock)
+       })
+}
+
+// Gets a span that has a free object in it and assigns it
+// to be the cached span for the given sizeclass.  Returns this span.
+func mCache_Refill(c *mcache, sizeclass int32) *mspan {
+       _g_ := getg()
+
+       _g_.m.locks++
+       // Return the current cached span to the central lists.
+       s := c.alloc[sizeclass]
+       if s.freelist != nil {
+               gothrow("refill on a nonempty span")
+       }
+       if s != &emptymspan {
+               s.incache = false
+       }
+
+       // Get a new cached span from the central lists.
+       s = mCentral_CacheSpan(&mheap_.central[sizeclass].mcentral)
+       if s == nil {
+               gothrow("out of memory")
+       }
+       if s.freelist == nil {
+               println(s.ref, (s.npages<<_PageShift)/s.elemsize)
+               gothrow("empty span")
+       }
+       c.alloc[sizeclass] = s
+       _g_.m.locks--
+       return s
+}
+
+func mCache_ReleaseAll(c *mcache) {
+       for i := 0; i < _NumSizeClasses; i++ {
+               s := c.alloc[i]
+               if s != &emptymspan {
+                       mCentral_UncacheSpan(&mheap_.central[i].mcentral, s)
+                       c.alloc[i] = &emptymspan
+               }
+       }
+}
diff --git a/src/runtime/mcentral.c b/src/runtime/mcentral.c
deleted file mode 100644 (file)
index fe6bcfe..0000000
+++ /dev/null
@@ -1,214 +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.
-
-// Central free lists.
-//
-// See malloc.h for an overview.
-//
-// The MCentral doesn't actually contain the list of free objects; the MSpan does.
-// Each MCentral is two lists of MSpans: those with free objects (c->nonempty)
-// and those that are completely allocated (c->empty).
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-static MSpan* MCentral_Grow(MCentral *c);
-
-// Initialize a single central free list.
-void
-runtime·MCentral_Init(MCentral *c, int32 sizeclass)
-{
-       c->sizeclass = sizeclass;
-       runtime·MSpanList_Init(&c->nonempty);
-       runtime·MSpanList_Init(&c->empty);
-}
-
-// Allocate a span to use in an MCache.
-MSpan*
-runtime·MCentral_CacheSpan(MCentral *c)
-{
-       MSpan *s;
-       int32 cap, n;
-       uint32 sg;
-
-       runtime·lock(&c->lock);
-       sg = runtime·mheap.sweepgen;
-retry:
-       for(s = c->nonempty.next; s != &c->nonempty; s = s->next) {
-               if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) {
-                       runtime·MSpanList_Remove(s);
-                       runtime·MSpanList_InsertBack(&c->empty, s);
-                       runtime·unlock(&c->lock);
-                       runtime·MSpan_Sweep(s, true);
-                       goto havespan;
-               }
-               if(s->sweepgen == sg-1) {
-                       // the span is being swept by background sweeper, skip
-                       continue;
-               }
-               // we have a nonempty span that does not require sweeping, allocate from it
-               runtime·MSpanList_Remove(s);
-               runtime·MSpanList_InsertBack(&c->empty, s);
-               runtime·unlock(&c->lock);
-               goto havespan;
-       }
-
-       for(s = c->empty.next; s != &c->empty; s = s->next) {
-               if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) {
-                       // we have an empty span that requires sweeping,
-                       // sweep it and see if we can free some space in it
-                       runtime·MSpanList_Remove(s);
-                       // swept spans are at the end of the list
-                       runtime·MSpanList_InsertBack(&c->empty, s);
-                       runtime·unlock(&c->lock);
-                       runtime·MSpan_Sweep(s, true);
-                       if(s->freelist != nil)
-                               goto havespan;
-                       runtime·lock(&c->lock);
-                       // the span is still empty after sweep
-                       // it is already in the empty list, so just retry
-                       goto retry;
-               }
-               if(s->sweepgen == sg-1) {
-                       // the span is being swept by background sweeper, skip
-                       continue;
-               }
-               // already swept empty span,
-               // all subsequent ones must also be either swept or in process of sweeping
-               break;
-       }
-       runtime·unlock(&c->lock);
-
-       // Replenish central list if empty.
-       s = MCentral_Grow(c);
-       if(s == nil)
-               return nil;
-       runtime·lock(&c->lock);
-       runtime·MSpanList_InsertBack(&c->empty, s);
-       runtime·unlock(&c->lock);
-
-havespan:
-       // At this point s is a non-empty span, queued at the end of the empty list,
-       // c is unlocked.
-       cap = (s->npages << PageShift) / s->elemsize;
-       n = cap - s->ref;
-       if(n == 0)
-               runtime·throw("empty span");
-       if(s->freelist == nil)
-               runtime·throw("freelist empty");
-       s->incache = true;
-       return s;
-}
-
-// Return span from an MCache.
-void
-runtime·MCentral_UncacheSpan(MCentral *c, MSpan *s)
-{
-       int32 cap, n;
-
-       runtime·lock(&c->lock);
-
-       s->incache = false;
-
-       if(s->ref == 0)
-               runtime·throw("uncaching full span");
-
-       cap = (s->npages << PageShift) / s->elemsize;
-       n = cap - s->ref;
-       if(n > 0) {
-               runtime·MSpanList_Remove(s);
-               runtime·MSpanList_Insert(&c->nonempty, s);
-       }
-       runtime·unlock(&c->lock);
-}
-
-// Free n objects from a span s back into the central free list c.
-// Called during sweep.
-// Returns true if the span was returned to heap.  Sets sweepgen to
-// the latest generation.
-// If preserve=true, don't return the span to heap nor relink in MCentral lists;
-// caller takes care of it.
-bool
-runtime·MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end, bool preserve)
-{
-       bool wasempty;
-
-       if(s->incache)
-               runtime·throw("freespan into cached span");
-
-       // Add the objects back to s's free list.
-       wasempty = s->freelist == nil;
-       end->next = s->freelist;
-       s->freelist = start;
-       s->ref -= n;
-
-       if(preserve) {
-               // preserve is set only when called from MCentral_CacheSpan above,
-               // the span must be in the empty list.
-               if(s->next == nil)
-                       runtime·throw("can't preserve unlinked span");
-               runtime·atomicstore(&s->sweepgen, runtime·mheap.sweepgen);
-               return false;
-       }
-
-       runtime·lock(&c->lock);
-
-       // Move to nonempty if necessary.
-       if(wasempty) {
-               runtime·MSpanList_Remove(s);
-               runtime·MSpanList_Insert(&c->nonempty, s);
-       }
-
-       // delay updating sweepgen until here.  This is the signal that
-       // the span may be used in an MCache, so it must come after the
-       // linked list operations above (actually, just after the
-       // lock of c above.)
-       runtime·atomicstore(&s->sweepgen, runtime·mheap.sweepgen);
-
-       if(s->ref != 0) {
-               runtime·unlock(&c->lock);
-               return false;
-       }
-
-       // s is completely freed, return it to the heap.
-       runtime·MSpanList_Remove(s);
-       s->needzero = 1;
-       s->freelist = nil;
-       runtime·unlock(&c->lock);
-       runtime·unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
-       runtime·MHeap_Free(&runtime·mheap, s, 0);
-       return true;
-}
-
-// Fetch a new span from the heap and carve into objects for the free list.
-static MSpan*
-MCentral_Grow(MCentral *c)
-{
-       uintptr size, npages, i, n;
-       MLink **tailp, *v;
-       byte *p;
-       MSpan *s;
-
-       npages = runtime·class_to_allocnpages[c->sizeclass];
-       size = runtime·class_to_size[c->sizeclass];
-       n = (npages << PageShift) / size;
-       s = runtime·MHeap_Alloc(&runtime·mheap, npages, c->sizeclass, 0, 1);
-       if(s == nil)
-               return nil;
-
-       // Carve span into sequence of blocks.
-       tailp = &s->freelist;
-       p = (byte*)(s->start << PageShift);
-       s->limit = p + size*n;
-       for(i=0; i<n; i++) {
-               v = (MLink*)p;
-               *tailp = v;
-               tailp = &v->next;
-               p += size;
-       }
-       *tailp = nil;
-       runtime·markspan((byte*)(s->start<<PageShift), size, n, size*n < (s->npages<<PageShift));
-       return s;
-}
diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go
new file mode 100644 (file)
index 0000000..0d172a0
--- /dev/null
@@ -0,0 +1,199 @@
+// 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.
+
+// Central free lists.
+//
+// See malloc.h for an overview.
+//
+// The MCentral doesn't actually contain the list of free objects; the MSpan does.
+// Each MCentral is two lists of MSpans: those with free objects (c->nonempty)
+// and those that are completely allocated (c->empty).
+
+package runtime
+
+import "unsafe"
+
+// Initialize a single central free list.
+func mCentral_Init(c *mcentral, sizeclass int32) {
+       c.sizeclass = sizeclass
+       mSpanList_Init(&c.nonempty)
+       mSpanList_Init(&c.empty)
+}
+
+// Allocate a span to use in an MCache.
+func mCentral_CacheSpan(c *mcentral) *mspan {
+       lock(&c.lock)
+       sg := mheap_.sweepgen
+retry:
+       var s *mspan
+       for s = c.nonempty.next; s != &c.nonempty; s = s.next {
+               if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
+                       mSpanList_Remove(s)
+                       mSpanList_InsertBack(&c.empty, s)
+                       unlock(&c.lock)
+                       mSpan_Sweep(s, true)
+                       goto havespan
+               }
+               if s.sweepgen == sg-1 {
+                       // the span is being swept by background sweeper, skip
+                       continue
+               }
+               // we have a nonempty span that does not require sweeping, allocate from it
+               mSpanList_Remove(s)
+               mSpanList_InsertBack(&c.empty, s)
+               unlock(&c.lock)
+               goto havespan
+       }
+
+       for s = c.empty.next; s != &c.empty; s = s.next {
+               if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
+                       // we have an empty span that requires sweeping,
+                       // sweep it and see if we can free some space in it
+                       mSpanList_Remove(s)
+                       // swept spans are at the end of the list
+                       mSpanList_InsertBack(&c.empty, s)
+                       unlock(&c.lock)
+                       mSpan_Sweep(s, true)
+                       if s.freelist != nil {
+                               goto havespan
+                       }
+                       lock(&c.lock)
+                       // the span is still empty after sweep
+                       // it is already in the empty list, so just retry
+                       goto retry
+               }
+               if s.sweepgen == sg-1 {
+                       // the span is being swept by background sweeper, skip
+                       continue
+               }
+               // already swept empty span,
+               // all subsequent ones must also be either swept or in process of sweeping
+               break
+       }
+       unlock(&c.lock)
+
+       // Replenish central list if empty.
+       s = mCentral_Grow(c)
+       if s == nil {
+               return nil
+       }
+       lock(&c.lock)
+       mSpanList_InsertBack(&c.empty, s)
+       unlock(&c.lock)
+
+       // At this point s is a non-empty span, queued at the end of the empty list,
+       // c is unlocked.
+havespan:
+       cap := int32((s.npages << _PageShift) / s.elemsize)
+       n := cap - int32(s.ref)
+       if n == 0 {
+               gothrow("empty span")
+       }
+       if s.freelist == nil {
+               gothrow("freelist empty")
+       }
+       s.incache = true
+       return s
+}
+
+// Return span from an MCache.
+func mCentral_UncacheSpan(c *mcentral, s *mspan) {
+       lock(&c.lock)
+
+       s.incache = false
+
+       if s.ref == 0 {
+               gothrow("uncaching full span")
+       }
+
+       cap := int32((s.npages << _PageShift) / s.elemsize)
+       n := cap - int32(s.ref)
+       if n > 0 {
+               mSpanList_Remove(s)
+               mSpanList_Insert(&c.nonempty, s)
+       }
+       unlock(&c.lock)
+}
+
+// Free n objects from a span s back into the central free list c.
+// Called during sweep.
+// Returns true if the span was returned to heap.  Sets sweepgen to
+// the latest generation.
+// If preserve=true, don't return the span to heap nor relink in MCentral lists;
+// caller takes care of it.
+func mCentral_FreeSpan(c *mcentral, s *mspan, n int32, start *mlink, end *mlink, preserve bool) bool {
+       if s.incache {
+               gothrow("freespan into cached span")
+       }
+
+       // Add the objects back to s's free list.
+       wasempty := s.freelist == nil
+       end.next = s.freelist
+       s.freelist = start
+       s.ref -= uint16(n)
+
+       if preserve {
+               // preserve is set only when called from MCentral_CacheSpan above,
+               // the span must be in the empty list.
+               if s.next == nil {
+                       gothrow("can't preserve unlinked span")
+               }
+               atomicstore(&s.sweepgen, mheap_.sweepgen)
+               return false
+       }
+
+       lock(&c.lock)
+
+       // Move to nonempty if necessary.
+       if wasempty {
+               mSpanList_Remove(s)
+               mSpanList_Insert(&c.nonempty, s)
+       }
+
+       // delay updating sweepgen until here.  This is the signal that
+       // the span may be used in an MCache, so it must come after the
+       // linked list operations above (actually, just after the
+       // lock of c above.)
+       atomicstore(&s.sweepgen, mheap_.sweepgen)
+
+       if s.ref != 0 {
+               unlock(&c.lock)
+               return false
+       }
+
+       // s is completely freed, return it to the heap.
+       mSpanList_Remove(s)
+       s.needzero = 1
+       s.freelist = nil
+       unlock(&c.lock)
+       unmarkspan(uintptr(s.start)<<_PageShift, s.npages<<_PageShift)
+       mHeap_Free(&mheap_, s, 0)
+       return true
+}
+
+// Fetch a new span from the heap and carve into objects for the free list.
+func mCentral_Grow(c *mcentral) *mspan {
+       npages := uintptr(class_to_allocnpages[c.sizeclass])
+       size := uintptr(class_to_size[c.sizeclass])
+       n := (npages << _PageShift) / size
+
+       s := mHeap_Alloc(&mheap_, npages, c.sizeclass, false, true)
+       if s == nil {
+               return nil
+       }
+
+       // Carve span into sequence of blocks.
+       tailp := &s.freelist
+       p := uintptr(s.start << _PageShift)
+       s.limit = p + size*n
+       for i := uintptr(0); i < n; i++ {
+               v := (*mlink)(unsafe.Pointer(p))
+               *tailp = v
+               tailp = &v.next
+               p += size
+       }
+       *tailp = nil
+       markspan(unsafe.Pointer(uintptr(s.start)<<_PageShift), size, n, size*n < s.npages<<_PageShift)
+       return s
+}
index e6f1eb0e64f1da9f4f141fe6813bc9cdd4570b4e..1835672512733c44e01adceb95af917c3b405a48 100644 (file)
@@ -59,7 +59,11 @@ type MemStats struct {
        }
 }
 
-var sizeof_C_MStats uintptr // filled in by malloc.goc
+// Size of the trailing by_size array differs between Go and C,
+// and all data after by_size is local to runtime, not exported.
+// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+// sizeof_C_MStats is what C thinks about size of Go struct.
+var sizeof_C_MStats = unsafe.Offsetof(memstats.by_size) + 61*unsafe.Sizeof(memstats.by_size[0])
 
 func init() {
        var memStats MemStats
@@ -78,15 +82,16 @@ func ReadMemStats(m *MemStats) {
        semacquire(&worldsema, false)
        gp := getg()
        gp.m.gcing = 1
-       onM(stoptheworld)
+       systemstack(stoptheworld)
 
-       gp.m.ptrarg[0] = noescape(unsafe.Pointer(m))
-       onM(readmemstats_m)
+       systemstack(func() {
+               readmemstats_m(m)
+       })
 
        gp.m.gcing = 0
        gp.m.locks++
        semrelease(&worldsema)
-       onM(starttheworld)
+       systemstack(starttheworld)
        gp.m.locks--
 }
 
@@ -95,14 +100,15 @@ func writeHeapDump(fd uintptr) {
        semacquire(&worldsema, false)
        gp := getg()
        gp.m.gcing = 1
-       onM(stoptheworld)
+       systemstack(stoptheworld)
 
-       gp.m.scalararg[0] = fd
-       onM(writeheapdump_m)
+       systemstack(func() {
+               writeheapdump_m(fd)
+       })
 
        gp.m.gcing = 0
        gp.m.locks++
        semrelease(&worldsema)
-       onM(starttheworld)
+       systemstack(starttheworld)
        gp.m.locks--
 }
diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go
new file mode 100644 (file)
index 0000000..4bd40a3
--- /dev/null
@@ -0,0 +1,88 @@
+// 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 dragonfly freebsd netbsd openbsd solaris
+
+package runtime
+
+import "unsafe"
+
+//go:nosplit
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+       v := unsafe.Pointer(mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
+       if uintptr(v) < 4096 {
+               return nil
+       }
+       xadd64(stat, int64(n))
+       return v
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+       madvise(v, n, _MADV_FREE)
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+       xadd64(stat, -int64(n))
+       munmap(v, n)
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+       mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE|_MAP_FIXED, -1, 0)
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+       // On 64-bit, people with ulimit -v set complain if we reserve too
+       // much address space.  Instead, assume that the reservation is okay
+       // and check the assumption in SysMap.
+       if ptrSize == 8 && uint64(n) > 1<<32 {
+               *reserved = false
+               return v
+       }
+
+       p := unsafe.Pointer(mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
+       if uintptr(p) < 4096 {
+               return nil
+       }
+       *reserved = true
+       return p
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+       const _ENOMEM = 12
+
+       xadd64(stat, int64(n))
+
+       // On 64-bit, we don't actually have v reserved, so tread carefully.
+       if !reserved {
+               flags := int32(_MAP_ANON | _MAP_PRIVATE)
+               if GOOS == "dragonfly" {
+                       // TODO(jsing): For some reason DragonFly seems to return
+                       // memory at a different address than we requested, even when
+                       // there should be no reason for it to do so. This can be
+                       // avoided by using MAP_FIXED, but I'm not sure we should need
+                       // to do this - we do not on other platforms.
+                       flags |= _MAP_FIXED
+               }
+               p := mmap(v, n, _PROT_READ|_PROT_WRITE, flags, -1, 0)
+               if uintptr(p) == _ENOMEM {
+                       gothrow("runtime: out of memory")
+               }
+               if p != v {
+                       print("runtime: address space conflict: map(", v, ") = ", p, "\n")
+                       gothrow("runtime: address space conflict")
+               }
+               return
+       }
+
+       p := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+       if uintptr(p) == _ENOMEM {
+               gothrow("runtime: out of memory")
+       }
+       if p != v {
+               gothrow("runtime: cannot map pages in arena address space")
+       }
+}
diff --git a/src/runtime/mem_darwin.c b/src/runtime/mem_darwin.c
deleted file mode 100644 (file)
index bf3ede5..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096)
-               return nil;
-       runtime·xadd64(stat, n);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       // Linux's MADV_DONTNEED is like BSD's MADV_FREE.
-       runtime·madvise(v, n, MADV_FREE);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       *reserved = true;
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       return p;
-}
-
-enum
-{
-       ENOMEM = 12,
-};
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       USED(reserved);
-
-       runtime·xadd64(stat, n);
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_darwin.go b/src/runtime/mem_darwin.go
new file mode 100644 (file)
index 0000000..1bee933
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//go:nosplit
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+       v := (unsafe.Pointer)(mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
+       if uintptr(v) < 4096 {
+               return nil
+       }
+       xadd64(stat, int64(n))
+       return v
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+       // Linux's MADV_DONTNEED is like BSD's MADV_FREE.
+       madvise(v, n, _MADV_FREE)
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+       xadd64(stat, -int64(n))
+       munmap(v, n)
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+       mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE|_MAP_FIXED, -1, 0)
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+       *reserved = true
+       p := (unsafe.Pointer)(mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
+       if uintptr(p) < 4096 {
+               return nil
+       }
+       return p
+}
+
+const (
+       _ENOMEM = 12
+)
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+       xadd64(stat, int64(n))
+       p := (unsafe.Pointer)(mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0))
+       if uintptr(p) == _ENOMEM {
+               gothrow("runtime: out of memory")
+       }
+       if p != v {
+               gothrow("runtime: cannot map pages in arena address space")
+       }
+}
diff --git a/src/runtime/mem_dragonfly.c b/src/runtime/mem_dragonfly.c
deleted file mode 100644 (file)
index 11457b2..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       ENOMEM = 12,
-};
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096)
-               return nil;
-       runtime·xadd64(stat, n);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       runtime·madvise(v, n, MADV_FREE);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // and check the assumption in SysMap.
-       if(sizeof(void*) == 8 && n > 1LL<<32) {
-               *reserved = false;
-               return v;
-       }
-
-       *reserved = true;
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               // TODO(jsing): For some reason DragonFly seems to return
-               // memory at a different address than we requested, even when
-               // there should be no reason for it to do so. This can be
-               // avoided by using MAP_FIXED, but I'm not sure we should need
-               // to do this - we do not on other platforms.
-               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) {
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               return;
-       }
-
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_freebsd.c b/src/runtime/mem_freebsd.c
deleted file mode 100644 (file)
index 18a9a2f..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       ENOMEM = 12,
-};
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096)
-               return nil;
-       runtime·xadd64(stat, n);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       runtime·madvise(v, n, MADV_FREE);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // and check the assumption in SysMap.
-       if(sizeof(void*) == 8 && n > 1LL<<32) {
-               *reserved = false;
-               return v;
-       }
-
-       *reserved = true;
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               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) {
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               return;
-       }
-
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_linux.c b/src/runtime/mem_linux.c
deleted file mode 100644 (file)
index bfb4056..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       _PAGE_SIZE = 4096,
-       EACCES = 13,
-};
-
-static int32
-addrspace_free(void *v, uintptr n)
-{
-       int32 errval;
-       uintptr chunk;
-       uintptr off;
-       
-       // NOTE: vec must be just 1 byte long here.
-       // Mincore returns ENOMEM if any of the pages are unmapped,
-       // but we want to know that all of the pages are unmapped.
-       // To make these the same, we can only ask about one page
-       // at a time. See golang.org/issue/7476.
-       static byte vec[1];
-
-       for(off = 0; off < n; off += chunk) {
-               chunk = _PAGE_SIZE * sizeof vec;
-               if(chunk > (n - off))
-                       chunk = n - off;
-               errval = runtime·mincore((int8*)v + off, chunk, vec);
-               // ENOMEM means unmapped, which is what we want.
-               // Anything else we assume means the pages are mapped.
-               if (errval != -ENOMEM)
-                       return 0;
-       }
-       return 1;
-}
-
-static void *
-mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset)
-{
-       void *p;
-
-       p = runtime·mmap(v, n, prot, flags, fd, offset);
-       if(p != v && addrspace_free(v, n)) {
-               // On some systems, mmap ignores v without
-               // MAP_FIXED, so retry if the address space is free.
-               if(p > (void*)4096)
-                       runtime·munmap(p, n);
-               p = runtime·mmap(v, n, prot, flags|MAP_FIXED, fd, offset);
-       }
-       return p;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *p;
-
-       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;
-       }
-       runtime·xadd64(stat, n);
-       return p;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       runtime·madvise(v, n, MADV_DONTNEED);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // if we can reserve at least 64K and check the assumption in SysMap.
-       // Only user-mode Linux (UML) rejects these requests.
-       if(sizeof(void*) == 8 && n > 1LL<<32) {
-               p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-               if (p != v) {
-                       if(p >= (void*)4096)
-                               runtime·munmap(p, 64<<10);
-                       return nil;
-               }
-               runtime·munmap(p, 64<<10);
-               *reserved = false;
-               return v;
-       }
-
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if((uintptr)p < 4096)
-               return nil;
-       *reserved = true;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               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) {
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               return;
-       }
-
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
new file mode 100644 (file)
index 0000000..85b55ef
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+const (
+       _PAGE_SIZE = _PhysPageSize
+       _EACCES    = 13
+)
+
+// NOTE: vec must be just 1 byte long here.
+// Mincore returns ENOMEM if any of the pages are unmapped,
+// but we want to know that all of the pages are unmapped.
+// To make these the same, we can only ask about one page
+// at a time. See golang.org/issue/7476.
+var addrspace_vec [1]byte
+
+func addrspace_free(v unsafe.Pointer, n uintptr) bool {
+       var chunk uintptr
+       for off := uintptr(0); off < n; off += chunk {
+               chunk = _PAGE_SIZE * uintptr(len(addrspace_vec))
+               if chunk > (n - off) {
+                       chunk = n - off
+               }
+               errval := mincore(unsafe.Pointer(uintptr(v)+off), chunk, &addrspace_vec[0])
+               // ENOMEM means unmapped, which is what we want.
+               // Anything else we assume means the pages are mapped.
+               if errval != -_ENOMEM {
+                       return false
+               }
+       }
+       return true
+}
+
+func mmap_fixed(v unsafe.Pointer, n uintptr, prot, flags, fd int32, offset uint32) unsafe.Pointer {
+       p := mmap(v, n, prot, flags, fd, offset)
+       // On some systems, mmap ignores v without
+       // MAP_FIXED, so retry if the address space is free.
+       if p != v && addrspace_free(v, n) {
+               if uintptr(p) > 4096 {
+                       munmap(p, n)
+               }
+               p = mmap(v, n, prot, flags|_MAP_FIXED, fd, offset)
+       }
+       return p
+}
+
+//go:nosplit
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+       p := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+       if uintptr(p) < 4096 {
+               if uintptr(p) == _EACCES {
+                       print("runtime: mmap: access denied\n")
+                       print("if you're running SELinux, enable execmem for this process.\n")
+                       exit(2)
+               }
+               if uintptr(p) == _EAGAIN {
+                       print("runtime: mmap: too much locked memory (check 'ulimit -l').\n")
+                       exit(2)
+               }
+               return nil
+       }
+       xadd64(stat, int64(n))
+       return p
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+       madvise(v, n, _MADV_DONTNEED)
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+       xadd64(stat, -int64(n))
+       munmap(v, n)
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+       mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE|_MAP_FIXED, -1, 0)
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+       // On 64-bit, people with ulimit -v set complain if we reserve too
+       // much address space.  Instead, assume that the reservation is okay
+       // if we can reserve at least 64K and check the assumption in SysMap.
+       // Only user-mode Linux (UML) rejects these requests.
+       if ptrSize == 7 && uint64(n) > 1<<32 {
+               p := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+               if p != v {
+                       if uintptr(p) >= 4096 {
+                               munmap(p, 64<<10)
+                       }
+                       return nil
+               }
+               munmap(p, 64<<10)
+               *reserved = false
+               return v
+       }
+
+       p := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+       if uintptr(p) < 4096 {
+               return nil
+       }
+       *reserved = true
+       return p
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+       xadd64(stat, int64(n))
+
+       // On 64-bit, we don't actually have v reserved, so tread carefully.
+       if !reserved {
+               p := mmap_fixed(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+               if uintptr(p) == _ENOMEM {
+                       gothrow("runtime: out of memory")
+               }
+               if p != v {
+                       print("runtime: address space conflict: map(", v, ") = ", p, "\n")
+                       gothrow("runtime: address space conflict")
+               }
+               return
+       }
+
+       p := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)
+       if uintptr(p) == _ENOMEM {
+               gothrow("runtime: out of memory")
+       }
+       if p != v {
+               gothrow("runtime: cannot map pages in arena address space")
+       }
+}
diff --git a/src/runtime/mem_netbsd.c b/src/runtime/mem_netbsd.c
deleted file mode 100644 (file)
index 31820e5..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       ENOMEM = 12,
-};
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096)
-               return nil;
-       runtime·xadd64(stat, n);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       runtime·madvise(v, n, MADV_FREE);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // and check the assumption in SysMap.
-       if(sizeof(void*) == 8 && n > 1LL<<32) {
-               *reserved = false;
-               return v;
-       }
-
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       *reserved = true;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               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) {
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               return;
-       }
-
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_openbsd.c b/src/runtime/mem_openbsd.c
deleted file mode 100644 (file)
index 31820e5..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       ENOMEM = 12,
-};
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096)
-               return nil;
-       runtime·xadd64(stat, n);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       runtime·madvise(v, n, MADV_FREE);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // and check the assumption in SysMap.
-       if(sizeof(void*) == 8 && n > 1LL<<32) {
-               *reserved = false;
-               return v;
-       }
-
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       *reserved = true;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               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) {
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               return;
-       }
-
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_solaris.c b/src/runtime/mem_solaris.c
deleted file mode 100644 (file)
index 8e90ba1..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum
-{
-       ENOMEM = 12,
-};
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       void *v;
-
-       v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(v < (void*)4096)
-               return nil;
-       runtime·xadd64(stat, n);
-       return v;
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       USED(v);
-       USED(n);
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)n);
-       runtime·munmap(v, n);
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       void *p;
-
-       // On 64-bit, people with ulimit -v set complain if we reserve too
-       // much address space.  Instead, assume that the reservation is okay
-       // and check the assumption in SysMap.
-       if(sizeof(void*) == 8 && n > 1LL<<32) {
-               *reserved = false;
-               return v;
-       }
-       
-       p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
-       if(p < (void*)4096)
-               return nil;
-       *reserved = true;
-       return p;
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-       
-       runtime·xadd64(stat, n);
-
-       // On 64-bit, we don't actually have v reserved, so tread carefully.
-       if(!reserved) {
-               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) {
-                       runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
-                       runtime·throw("runtime: address space conflict");
-               }
-               return;
-       }
-
-       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)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_windows.c b/src/runtime/mem_windows.c
deleted file mode 100644 (file)
index 6ea9920..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "os_GOOS.h"
-#include "defs_GOOS_GOARCH.h"
-#include "malloc.h"
-#include "textflag.h"
-
-enum {
-       MEM_COMMIT = 0x1000,
-       MEM_RESERVE = 0x2000,
-       MEM_DECOMMIT = 0x4000,
-       MEM_RELEASE = 0x8000,
-       
-       PAGE_READWRITE = 0x0004,
-       PAGE_NOACCESS = 0x0001,
-};
-
-#pragma dynimport runtime·VirtualAlloc VirtualAlloc "kernel32.dll"
-#pragma dynimport runtime·VirtualFree VirtualFree "kernel32.dll"
-#pragma dynimport runtime·VirtualProtect VirtualProtect "kernel32.dll"
-extern void *runtime·VirtualAlloc;
-extern void *runtime·VirtualFree;
-extern void *runtime·VirtualProtect;
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr n, uint64 *stat)
-{
-       runtime·xadd64(stat, n);
-       return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
-}
-
-void
-runtime·SysUnused(void *v, uintptr n)
-{
-       void *r;
-       uintptr small;
-
-       r = runtime·stdcall3(runtime·VirtualFree, (uintptr)v, n, MEM_DECOMMIT);
-       if(r != nil)
-               return;
-
-       // Decommit failed. Usual reason is that we've merged memory from two different
-       // VirtualAlloc calls, and Windows will only let each VirtualFree handle pages from
-       // a single VirtualAlloc. It is okay to specify a subset of the pages from a single alloc,
-       // just not pages from multiple allocs. This is a rare case, arising only when we're
-       // trying to give memory back to the operating system, which happens on a time
-       // scale of minutes. It doesn't have to be terribly fast. Instead of extra bookkeeping
-       // on all our VirtualAlloc calls, try freeing successively smaller pieces until
-       // we manage to free something, and then repeat. This ends up being O(n log n)
-       // in the worst case, but that's fast enough.
-       while(n > 0) {
-               small = n;
-               while(small >= 4096 && runtime·stdcall3(runtime·VirtualFree, (uintptr)v, small, MEM_DECOMMIT) == nil)
-                       small = (small / 2) & ~(4096-1);
-               if(small < 4096)
-                       runtime·throw("runtime: failed to decommit pages");
-               v = (byte*)v + small;
-               n -= small;
-       }
-}
-
-void
-runtime·SysUsed(void *v, uintptr n)
-{
-       void *r;
-       uintptr small;
-
-       r = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
-       if(r != v)
-               runtime·throw("runtime: failed to commit pages");
-
-       // Commit failed. See SysUnused.
-       while(n > 0) {
-               small = n;
-               while(small >= 4096 && runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, small, MEM_COMMIT, PAGE_READWRITE) == nil)
-                       small = (small / 2) & ~(4096-1);
-               if(small < 4096)
-                       runtime·throw("runtime: failed to decommit pages");
-               v = (byte*)v + small;
-               n -= small;
-       }
-}
-
-void
-runtime·SysFree(void *v, uintptr n, uint64 *stat)
-{
-       uintptr r;
-
-       runtime·xadd64(stat, -(uint64)n);
-       r = (uintptr)runtime·stdcall3(runtime·VirtualFree, (uintptr)v, 0, MEM_RELEASE);
-       if(r == 0)
-               runtime·throw("runtime: failed to release pages");
-}
-
-void
-runtime·SysFault(void *v, uintptr n)
-{
-       // SysUnused makes the memory inaccessible and prevents its reuse
-       runtime·SysUnused(v, n);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr n, bool *reserved)
-{
-       *reserved = true;
-       // v is just a hint.
-       // First try at v.
-       v = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_RESERVE, PAGE_READWRITE);
-       if(v != nil)
-               return v;
-       
-       // Next let the kernel choose the address.
-       return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_RESERVE, PAGE_READWRITE);
-}
-
-void
-runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
-{
-       void *p;
-
-       USED(reserved);
-
-       runtime·xadd64(stat, n);
-       p = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
-       if(p != v)
-               runtime·throw("runtime: cannot map pages in arena address space");
-}
diff --git a/src/runtime/mem_windows.go b/src/runtime/mem_windows.go
new file mode 100644 (file)
index 0000000..a1dcad0
--- /dev/null
@@ -0,0 +1,119 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+const (
+       _MEM_COMMIT   = 0x1000
+       _MEM_RESERVE  = 0x2000
+       _MEM_DECOMMIT = 0x4000
+       _MEM_RELEASE  = 0x8000
+
+       _PAGE_READWRITE = 0x0004
+       _PAGE_NOACCESS  = 0x0001
+)
+
+//go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc "kernel32.dll"
+//go:cgo_import_dynamic runtime._VirtualFree VirtualFree "kernel32.dll"
+//go:cgo_import_dynamic runtime._VirtualProtect VirtualProtect "kernel32.dll"
+
+var (
+       _VirtualAlloc,
+       _VirtualFree,
+       _VirtualProtect stdFunction
+)
+
+//go:nosplit
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+       xadd64(stat, int64(n))
+       return unsafe.Pointer(stdcall4(_VirtualAlloc, 0, n, _MEM_COMMIT|_MEM_RESERVE, _PAGE_READWRITE))
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+       r := stdcall3(_VirtualFree, uintptr(v), n, _MEM_DECOMMIT)
+       if r != 0 {
+               return
+       }
+
+       // Decommit failed. Usual reason is that we've merged memory from two different
+       // VirtualAlloc calls, and Windows will only let each VirtualFree handle pages from
+       // a single VirtualAlloc. It is okay to specify a subset of the pages from a single alloc,
+       // just not pages from multiple allocs. This is a rare case, arising only when we're
+       // trying to give memory back to the operating system, which happens on a time
+       // scale of minutes. It doesn't have to be terribly fast. Instead of extra bookkeeping
+       // on all our VirtualAlloc calls, try freeing successively smaller pieces until
+       // we manage to free something, and then repeat. This ends up being O(n log n)
+       // in the worst case, but that's fast enough.
+       for n > 0 {
+               small := n
+               for small >= 4096 && stdcall3(_VirtualFree, uintptr(v), small, _MEM_DECOMMIT) == 0 {
+                       small /= 2
+                       small &^= 4096 - 1
+               }
+               if small < 4096 {
+                       gothrow("runtime: failed to decommit pages")
+               }
+               v = add(v, small)
+               n -= small
+       }
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+       r := stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_COMMIT, _PAGE_READWRITE)
+       if r != uintptr(v) {
+               gothrow("runtime: failed to commit pages")
+       }
+
+       // Commit failed. See SysUnused.
+       for n > 0 {
+               small := n
+               for small >= 4096 && stdcall4(_VirtualAlloc, uintptr(v), small, _MEM_COMMIT, _PAGE_READWRITE) == 0 {
+                       small /= 2
+                       small &^= 4096 - 1
+               }
+               if small < 4096 {
+                       gothrow("runtime: failed to decommit pages")
+               }
+               v = add(v, small)
+               n -= small
+       }
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+       xadd64(stat, -int64(n))
+       r := stdcall3(_VirtualFree, uintptr(v), 0, _MEM_RELEASE)
+       if r == 0 {
+               gothrow("runtime: failed to release pages")
+       }
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+       // SysUnused makes the memory inaccessible and prevents its reuse
+       sysUnused(v, n)
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+       *reserved = true
+       // v is just a hint.
+       // First try at v.
+       v = unsafe.Pointer(stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_RESERVE, _PAGE_READWRITE))
+       if v != nil {
+               return v
+       }
+
+       // Next let the kernel choose the address.
+       return unsafe.Pointer(stdcall4(_VirtualAlloc, 0, n, _MEM_RESERVE, _PAGE_READWRITE))
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+       xadd64(stat, int64(n))
+       p := stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_COMMIT, _PAGE_READWRITE)
+       if p != uintptr(v) {
+               gothrow("runtime: cannot map pages in arena address space")
+       }
+}
index 1520aea2e0fbbb220f1b9836e5d3bdd7f95afa1b..3f20b69c8219b6dc139ded7316173a21102e8de1 100644 (file)
@@ -15,31 +15,31 @@ TEXT runtime·memclr(SB), NOSPLIT, $0-8
        XORL    AX, AX
 
        // MOVOU seems always faster than REP STOSL.
-clr_tail:
+tail:
        TESTL   BX, BX
-       JEQ     clr_0
+       JEQ     _0
        CMPL    BX, $2
-       JBE     clr_1or2
+       JBE     _1or2
        CMPL    BX, $4
-       JBE     clr_3or4
+       JBE     _3or4
        CMPL    BX, $8
-       JBE     clr_5through8
+       JBE     _5through8
        CMPL    BX, $16
-       JBE     clr_9through16
+       JBE     _9through16
        TESTL   $0x4000000, runtime·cpuid_edx(SB) // check for sse2
        JEQ     nosse2
        PXOR    X0, X0
        CMPL    BX, $32
-       JBE     clr_17through32
+       JBE     _17through32
        CMPL    BX, $64
-       JBE     clr_33through64
+       JBE     _33through64
        CMPL    BX, $128
-       JBE     clr_65through128
+       JBE     _65through128
        CMPL    BX, $256
-       JBE     clr_129through256
+       JBE     _129through256
        // TODO: use branch table and BSR to make this just a single dispatch
 
-clr_loop:
+loop:
        MOVOU   X0, 0(DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, 32(DI)
@@ -59,40 +59,40 @@ clr_loop:
        SUBL    $256, BX
        ADDL    $256, DI
        CMPL    BX, $256
-       JAE     clr_loop
-       JMP     clr_tail
+       JAE     loop
+       JMP     tail
 
-clr_1or2:
+_1or2:
        MOVB    AX, (DI)
        MOVB    AX, -1(DI)(BX*1)
        RET
-clr_0:
+_0:
        RET
-clr_3or4:
+_3or4:
        MOVW    AX, (DI)
        MOVW    AX, -2(DI)(BX*1)
        RET
-clr_5through8:
+_5through8:
        MOVL    AX, (DI)
        MOVL    AX, -4(DI)(BX*1)
        RET
-clr_9through16:
+_9through16:
        MOVL    AX, (DI)
        MOVL    AX, 4(DI)
        MOVL    AX, -8(DI)(BX*1)
        MOVL    AX, -4(DI)(BX*1)
        RET
-clr_17through32:
+_17through32:
        MOVOU   X0, (DI)
        MOVOU   X0, -16(DI)(BX*1)
        RET
-clr_33through64:
+_33through64:
        MOVOU   X0, (DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, -32(DI)(BX*1)
        MOVOU   X0, -16(DI)(BX*1)
        RET
-clr_65through128:
+_65through128:
        MOVOU   X0, (DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, 32(DI)
@@ -102,7 +102,7 @@ clr_65through128:
        MOVOU   X0, -32(DI)(BX*1)
        MOVOU   X0, -16(DI)(BX*1)
        RET
-clr_129through256:
+_129through256:
        MOVOU   X0, (DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, 32(DI)
@@ -126,5 +126,5 @@ nosse2:
        REP
        STOSL
        ANDL    $3, BX
-       JNE     clr_tail
+       JNE     tail
        RET
index 94a2c7f2360dbf6ad45daf048d907fcdc00fddf9..ec24f1db239032e1a52a9e293342f9038e8e0371 100644 (file)
@@ -15,30 +15,30 @@ TEXT runtime·memclr(SB), NOSPLIT, $0-16
        XORQ    AX, AX
 
        // MOVOU seems always faster than REP STOSQ.
-clr_tail:
+tail:
        TESTQ   BX, BX
-       JEQ     clr_0
+       JEQ     _0
        CMPQ    BX, $2
-       JBE     clr_1or2
+       JBE     _1or2
        CMPQ    BX, $4
-       JBE     clr_3or4
+       JBE     _3or4
        CMPQ    BX, $8
-       JBE     clr_5through8
+       JBE     _5through8
        CMPQ    BX, $16
-       JBE     clr_9through16
+       JBE     _9through16
        PXOR    X0, X0
        CMPQ    BX, $32
-       JBE     clr_17through32
+       JBE     _17through32
        CMPQ    BX, $64
-       JBE     clr_33through64
+       JBE     _33through64
        CMPQ    BX, $128
-       JBE     clr_65through128
+       JBE     _65through128
        CMPQ    BX, $256
-       JBE     clr_129through256
+       JBE     _129through256
        // TODO: use branch table and BSR to make this just a single dispatch
        // TODO: for really big clears, use MOVNTDQ.
 
-clr_loop:
+loop:
        MOVOU   X0, 0(DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, 32(DI)
@@ -58,38 +58,38 @@ clr_loop:
        SUBQ    $256, BX
        ADDQ    $256, DI
        CMPQ    BX, $256
-       JAE     clr_loop
-       JMP     clr_tail
+       JAE     loop
+       JMP     tail
 
-clr_1or2:
+_1or2:
        MOVB    AX, (DI)
        MOVB    AX, -1(DI)(BX*1)
        RET
-clr_0:
+_0:
        RET
-clr_3or4:
+_3or4:
        MOVW    AX, (DI)
        MOVW    AX, -2(DI)(BX*1)
        RET
-clr_5through8:
+_5through8:
        MOVL    AX, (DI)
        MOVL    AX, -4(DI)(BX*1)
        RET
-clr_9through16:
+_9through16:
        MOVQ    AX, (DI)
        MOVQ    AX, -8(DI)(BX*1)
        RET
-clr_17through32:
+_17through32:
        MOVOU   X0, (DI)
        MOVOU   X0, -16(DI)(BX*1)
        RET
-clr_33through64:
+_33through64:
        MOVOU   X0, (DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, -32(DI)(BX*1)
        MOVOU   X0, -16(DI)(BX*1)
        RET
-clr_65through128:
+_65through128:
        MOVOU   X0, (DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, 32(DI)
@@ -99,7 +99,7 @@ clr_65through128:
        MOVOU   X0, -32(DI)(BX*1)
        MOVOU   X0, -16(DI)(BX*1)
        RET
-clr_129through256:
+_129through256:
        MOVOU   X0, (DI)
        MOVOU   X0, 16(DI)
        MOVOU   X0, 32(DI)
index b4b671f773e3f07a4322c64a924a03e0c6fb9434..50f327b4ed0201f3456d38666c07483b613b1a93 100644 (file)
@@ -10,40 +10,40 @@ TEXT runtime·memclr(SB), NOSPLIT, $0-8
        MOVL    n+4(FP), BX
        XORL    AX, AX
 
-clr_tail:
+tail:
        TESTL   BX, BX
-       JEQ     clr_0
+       JEQ     _0
        CMPL    BX, $2
-       JBE     clr_1or2
+       JBE     _1or2
        CMPL    BX, $4
-       JBE     clr_3or4
+       JBE     _3or4
        CMPL    BX, $8
-       JBE     clr_5through8
+       JBE     _5through8
        CMPL    BX, $16
-       JBE     clr_9through16
+       JBE     _9through16
        MOVL    BX, CX
        SHRL    $2, CX
        REP
        STOSL
        ANDL    $3, BX
-       JNE     clr_tail
+       JNE     tail
        RET
 
-clr_1or2:
+_1or2:
        MOVB    AX, (DI)
        MOVB    AX, -1(DI)(BX*1)
        RET
-clr_0:
+_0:
        RET
-clr_3or4:
+_3or4:
        MOVW    AX, (DI)
        MOVW    AX, -2(DI)(BX*1)
        RET
-clr_5through8:
+_5through8:
        MOVL    AX, (DI)
        MOVL    AX, -4(DI)(BX*1)
        RET
-clr_9through16:
+_9through16:
        MOVL    AX, (DI)
        MOVL    AX, 4(DI)
        MOVL    AX, -8(DI)(BX*1)
diff --git a/src/runtime/memclr_power64x.s b/src/runtime/memclr_power64x.s
new file mode 100644 (file)
index 0000000..dfad64b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+// void runtime·memclr(void*, uintptr)
+TEXT runtime·memclr(SB),NOSPLIT,$0-16
+       MOVD    ptr+0(FP), R3
+       MOVD    n+8(FP), R4
+       CMP     R4, $0
+       BEQ     done
+       SUB     $1, R3
+       MOVD    R4, CTR
+       MOVBU   R0, 1(R3)
+       BC      25, 0, -1(PC) // bdnz+ $-4
+done:
+       RETURN
diff --git a/src/runtime/memmove_power64x.s b/src/runtime/memmove_power64x.s
new file mode 100644 (file)
index 0000000..2b04d83
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+// void runtime·memmove(void*, void*, uintptr)
+TEXT runtime·memmove(SB), NOSPLIT, $-8-24
+       MOVD    to+0(FP), R3
+       MOVD    from+8(FP), R4
+       MOVD    n+16(FP), R5
+       CMP     R5, $0
+       BNE     check
+       RETURN
+
+check:
+       CMP     R3, R4
+       BGT     backward
+
+       SUB     $1, R3
+       ADD     R3, R5
+       SUB     $1, R4
+loop:
+       MOVBU   1(R4), R6
+       MOVBU   R6, 1(R3)
+       CMP     R3, R5
+       BNE     loop
+       RETURN
+
+backward:
+       ADD     R5, R4
+       ADD     R3, R5
+loop1:
+       MOVBU   -1(R4), R6
+       MOVBU   R6, -1(R5)
+       CMP     R3, R5
+       BNE     loop1
+       RETURN
diff --git a/src/runtime/mfixalloc.c b/src/runtime/mfixalloc.c
deleted file mode 100644 (file)
index d670629..0000000
+++ /dev/null
@@ -1,64 +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.
-
-// Fixed-size object allocator.  Returned memory is not zeroed.
-//
-// See malloc.h for overview.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-// Initialize f to allocate objects of the given size,
-// using the allocator to obtain chunks of memory.
-void
-runtime·FixAlloc_Init(FixAlloc *f, uintptr size, void (*first)(void*, byte*), void *arg, uint64 *stat)
-{
-       f->size = size;
-       f->first = first;
-       f->arg = arg;
-       f->list = nil;
-       f->chunk = nil;
-       f->nchunk = 0;
-       f->inuse = 0;
-       f->stat = stat;
-}
-
-void*
-runtime·FixAlloc_Alloc(FixAlloc *f)
-{
-       void *v;
-       
-       if(f->size == 0) {
-               runtime·printf("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n");
-               runtime·throw("runtime: internal error");
-       }
-
-       if(f->list) {
-               v = f->list;
-               f->list = *(void**)f->list;
-               f->inuse += f->size;
-               return v;
-       }
-       if(f->nchunk < f->size) {
-               f->chunk = runtime·persistentalloc(FixAllocChunk, 0, f->stat);
-               f->nchunk = FixAllocChunk;
-       }
-       v = f->chunk;
-       if(f->first)
-               f->first(f->arg, v);
-       f->chunk += f->size;
-       f->nchunk -= f->size;
-       f->inuse += f->size;
-       return v;
-}
-
-void
-runtime·FixAlloc_Free(FixAlloc *f, void *p)
-{
-       f->inuse -= f->size;
-       *(void**)p = f->list;
-       f->list = p;
-}
-
diff --git a/src/runtime/mfixalloc.go b/src/runtime/mfixalloc.go
new file mode 100644 (file)
index 0000000..b66a17e
--- /dev/null
@@ -0,0 +1,59 @@
+// 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.
+
+// Fixed-size object allocator.  Returned memory is not zeroed.
+//
+// See malloc.h for overview.
+
+package runtime
+
+import "unsafe"
+
+// Initialize f to allocate objects of the given size,
+// using the allocator to obtain chunks of memory.
+func fixAlloc_Init(f *fixalloc, size uintptr, first func(unsafe.Pointer, unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
+       f.size = size
+       f.first = *(*unsafe.Pointer)(unsafe.Pointer(&first))
+       f.arg = arg
+       f.list = nil
+       f.chunk = nil
+       f.nchunk = 0
+       f.inuse = 0
+       f.stat = stat
+}
+
+func fixAlloc_Alloc(f *fixalloc) unsafe.Pointer {
+       if f.size == 0 {
+               print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
+               gothrow("runtime: internal error")
+       }
+
+       if f.list != nil {
+               v := unsafe.Pointer(f.list)
+               f.list = f.list.next
+               f.inuse += f.size
+               return v
+       }
+       if uintptr(f.nchunk) < f.size {
+               f.chunk = (*uint8)(persistentalloc(_FixAllocChunk, 0, f.stat))
+               f.nchunk = _FixAllocChunk
+       }
+
+       v := (unsafe.Pointer)(f.chunk)
+       if f.first != nil {
+               fn := *(*func(unsafe.Pointer, unsafe.Pointer))(unsafe.Pointer(&f.first))
+               fn(f.arg, v)
+       }
+       f.chunk = (*byte)(add(unsafe.Pointer(f.chunk), f.size))
+       f.nchunk -= uint32(f.size)
+       f.inuse += f.size
+       return v
+}
+
+func fixAlloc_Free(f *fixalloc, p unsafe.Pointer) {
+       f.inuse -= f.size
+       v := (*mlink)(p)
+       v.next = f.list
+       f.list = v
+}
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
new file mode 100644 (file)
index 0000000..f44d7dd
--- /dev/null
@@ -0,0 +1,1798 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO(rsc): The code having to do with the heap bitmap needs very serious cleanup.
+// It has gotten completely out of control.
+
+// Garbage collector (GC).
+//
+// GC is:
+// - mark&sweep
+// - mostly precise (with the exception of some C-allocated objects, assembly frames/arguments, etc)
+// - parallel (up to MaxGcproc threads)
+// - partially concurrent (mark is stop-the-world, while sweep is concurrent)
+// - non-moving/non-compacting
+// - full (non-partial)
+//
+// GC rate.
+// Next GC is after we've allocated an extra amount of memory proportional to
+// the amount already in use. The proportion is controlled by GOGC environment variable
+// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M
+// (this mark is tracked in next_gc variable). This keeps the GC cost in linear
+// proportion to the allocation cost. Adjusting GOGC just changes the linear constant
+// (and also the amount of extra memory used).
+//
+// Concurrent sweep.
+// The sweep phase proceeds concurrently with normal program execution.
+// The heap is swept span-by-span both lazily (when a goroutine needs another span)
+// and concurrently in a background goroutine (this helps programs that are not CPU bound).
+// However, at the end of the stop-the-world GC phase we don't know the size of the live heap,
+// and so next_gc calculation is tricky and happens as follows.
+// At the end of the stop-the-world phase next_gc is conservatively set based on total
+// heap size; all spans are marked as "needs sweeping".
+// Whenever a span is swept, next_gc is decremented by GOGC*newly_freed_memory.
+// The background sweeper goroutine simply sweeps spans one-by-one bringing next_gc
+// closer to the target value. However, this is not enough to avoid over-allocating memory.
+// Consider that a goroutine wants to allocate a new span for a large object and
+// there are no free swept spans, but there are small-object unswept spans.
+// If the goroutine naively allocates a new span, it can surpass the yet-unknown
+// target next_gc value. In order to prevent such cases (1) when a goroutine needs
+// to allocate a new small-object span, it sweeps small-object spans for the same
+// object size until it frees at least one object; (2) when a goroutine needs to
+// allocate large-object span from heap, it sweeps spans until it frees at least
+// that many pages into heap. Together these two measures ensure that we don't surpass
+// target next_gc value by a large margin. There is an exception: if a goroutine sweeps
+// and frees two nonadjacent one-page spans to the heap, it will allocate a new two-page span,
+// but there can still be other one-page unswept spans which could be combined into a two-page span.
+// It's critical to ensure that no operations proceed on unswept spans (that would corrupt
+// mark bits in GC bitmap). During GC all mcaches are flushed into the central cache,
+// so they are empty. When a goroutine grabs a new span into mcache, it sweeps it.
+// When a goroutine explicitly frees an object or sets a finalizer, it ensures that
+// the span is swept (either by sweeping it, or by waiting for the concurrent sweep to finish).
+// The finalizer goroutine is kicked off only when all spans are swept.
+// When the next GC starts, it sweeps all not-yet-swept spans (if any).
+
+package runtime
+
+import "unsafe"
+
+const (
+       _DebugGC         = 0
+       _DebugGCPtrs     = false // if true, print trace of every pointer load during GC
+       _ConcurrentSweep = true
+
+       _WorkbufSize     = 4 * 1024
+       _FinBlockSize    = 4 * 1024
+       _RootData        = 0
+       _RootBss         = 1
+       _RootFinalizers  = 2
+       _RootSpans       = 3
+       _RootFlushCaches = 4
+       _RootCount       = 5
+)
+
+// ptrmask for an allocation containing a single pointer.
+var oneptr = [...]uint8{bitsPointer}
+
+// Initialized from $GOGC.  GOGC=off means no gc.
+var gcpercent int32
+
+// Holding worldsema grants an M the right to try to stop the world.
+// The procedure is:
+//
+//     semacquire(&worldsema);
+//     m.gcing = 1;
+//     stoptheworld();
+//
+//     ... do stuff ...
+//
+//     m.gcing = 0;
+//     semrelease(&worldsema);
+//     starttheworld();
+//
+var worldsema uint32 = 1
+
+type workbuf struct {
+       node lfnode // must be first
+       nobj uintptr
+       obj  [(_WorkbufSize - unsafe.Sizeof(lfnode{}) - ptrSize) / ptrSize]uintptr
+}
+
+var data, edata, bss, ebss, gcdata, gcbss struct{}
+
+var finlock mutex  // protects the following variables
+var fing *g        // goroutine that runs finalizers
+var finq *finblock // list of finalizers that are to be executed
+var finc *finblock // cache of free blocks
+var finptrmask [_FinBlockSize / ptrSize / pointersPerByte]byte
+var fingwait bool
+var fingwake bool
+var allfin *finblock // list of all blocks
+
+var gcdatamask bitvector
+var gcbssmask bitvector
+
+var gclock mutex
+
+var badblock [1024]uintptr
+var nbadblock int32
+
+type workdata struct {
+       full    uint64                // lock-free list of full blocks
+       empty   uint64                // lock-free list of empty blocks
+       pad0    [_CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
+       nproc   uint32
+       tstart  int64
+       nwait   uint32
+       ndone   uint32
+       alldone note
+       markfor *parfor
+
+       // Copy of mheap.allspans for marker or sweeper.
+       spans []*mspan
+}
+
+var work workdata
+
+//go:linkname weak_cgo_allocate go.weak.runtime._cgo_allocate_internal
+var weak_cgo_allocate byte
+
+// Is _cgo_allocate linked into the binary?
+func have_cgo_allocate() bool {
+       return &weak_cgo_allocate != nil
+}
+
+// scanblock scans a block of n bytes starting at pointer b for references
+// to other objects, scanning any it finds recursively until there are no
+// unscanned objects left.  Instead of using an explicit recursion, it keeps
+// a work list in the Workbuf* structures and loops in the main function
+// body.  Keeping an explicit work list is easier on the stack allocator and
+// more efficient.
+func scanblock(b, n uintptr, ptrmask *uint8) {
+       // Cache memory arena parameters in local vars.
+       arena_start := mheap_.arena_start
+       arena_used := mheap_.arena_used
+
+       wbuf := getempty(nil)
+       nobj := wbuf.nobj
+       wp := &wbuf.obj[nobj]
+       keepworking := b == 0
+
+       var ptrbitp unsafe.Pointer
+
+       // ptrmask can have 2 possible values:
+       // 1. nil - obtain pointer mask from GC bitmap.
+       // 2. pointer to a compact mask (for stacks and data).
+       goto_scanobj := b != 0
+
+       for {
+               if goto_scanobj {
+                       goto_scanobj = false
+               } else {
+                       if nobj == 0 {
+                               // Out of work in workbuf.
+                               if !keepworking {
+                                       putempty(wbuf)
+                                       return
+                               }
+
+                               // Refill workbuf from global queue.
+                               wbuf = getfull(wbuf)
+                               if wbuf == nil {
+                                       return
+                               }
+                               nobj = wbuf.nobj
+                               if nobj < uintptr(len(wbuf.obj)) {
+                                       wp = &wbuf.obj[nobj]
+                               } else {
+                                       wp = nil
+                               }
+                       }
+
+                       // If another proc wants a pointer, give it some.
+                       if work.nwait > 0 && nobj > 4 && work.full == 0 {
+                               wbuf.nobj = nobj
+                               wbuf = handoff(wbuf)
+                               nobj = wbuf.nobj
+                               if nobj < uintptr(len(wbuf.obj)) {
+                                       wp = &wbuf.obj[nobj]
+                               } else {
+                                       wp = nil
+                               }
+                       }
+
+                       nobj--
+                       wp = &wbuf.obj[nobj]
+                       b = *wp
+                       n = arena_used - uintptr(b)
+                       ptrmask = nil // use GC bitmap for pointer info
+               }
+
+               if _DebugGCPtrs {
+                       print("scanblock ", b, " +", hex(n), " ", ptrmask, "\n")
+               }
+
+               // Find bits of the beginning of the object.
+               if ptrmask == nil {
+                       off := (uintptr(b) - arena_start) / ptrSize
+                       ptrbitp = unsafe.Pointer(arena_start - off/wordsPerBitmapByte - 1)
+               }
+
+               var i uintptr
+               for i = 0; i < n; i += ptrSize {
+                       // Find bits for this word.
+                       var bits uintptr
+                       if ptrmask == nil {
+                               // Check if we have reached end of span.
+                               if (uintptr(b)+i)%_PageSize == 0 &&
+                                       h_spans[(uintptr(b)-arena_start)>>_PageShift] != h_spans[(uintptr(b)+i-arena_start)>>_PageShift] {
+                                       break
+                               }
+
+                               // Consult GC bitmap.
+                               bits = uintptr(*(*byte)(ptrbitp))
+
+                               if wordsPerBitmapByte != 2 {
+                                       gothrow("alg doesn't work for wordsPerBitmapByte != 2")
+                               }
+                               j := (uintptr(b) + i) / ptrSize & 1
+                               ptrbitp = add(ptrbitp, -j)
+                               bits >>= gcBits * j
+
+                               if bits&bitBoundary != 0 && i != 0 {
+                                       break // reached beginning of the next object
+                               }
+                               bits = (bits >> 2) & bitsMask
+                               if bits == bitsDead {
+                                       break // reached no-scan part of the object
+                               }
+                       } else {
+                               // dense mask (stack or data)
+                               bits = (uintptr(*(*byte)(add(unsafe.Pointer(ptrmask), (i/ptrSize)/4))) >> (((i / ptrSize) % 4) * bitsPerPointer)) & bitsMask
+                       }
+
+                       if bits <= _BitsScalar { // BitsScalar || BitsDead
+                               continue
+                       }
+
+                       if bits != _BitsPointer {
+                               gothrow("unexpected garbage collection bits")
+                       }
+
+                       obj := *(*uintptr)(unsafe.Pointer(b + i))
+                       obj0 := obj
+
+               markobj:
+                       var s *mspan
+                       var off, bitp, shift, xbits uintptr
+
+                       // At this point we have extracted the next potential pointer.
+                       // Check if it points into heap.
+                       if obj == 0 {
+                               continue
+                       }
+                       if obj < arena_start || arena_used <= obj {
+                               if uintptr(obj) < _PhysPageSize && invalidptr != 0 {
+                                       s = nil
+                                       goto badobj
+                               }
+                               continue
+                       }
+
+                       // Mark the object.
+                       obj &^= ptrSize - 1
+                       off = (obj - arena_start) / ptrSize
+                       bitp = arena_start - off/wordsPerBitmapByte - 1
+                       shift = (off % wordsPerBitmapByte) * gcBits
+                       xbits = uintptr(*(*byte)(unsafe.Pointer(bitp)))
+                       bits = (xbits >> shift) & bitMask
+                       if (bits & bitBoundary) == 0 {
+                               // Not a beginning of a block, consult span table to find the block beginning.
+                               k := pageID(obj >> _PageShift)
+                               x := k
+                               x -= pageID(arena_start >> _PageShift)
+                               s = h_spans[x]
+                               if s == nil || k < s.start || s.limit <= obj || s.state != mSpanInUse {
+                                       // Stack pointers lie within the arena bounds but are not part of the GC heap.
+                                       // Ignore them.
+                                       if s != nil && s.state == _MSpanStack {
+                                               continue
+                                       }
+                                       goto badobj
+                               }
+                               p := uintptr(s.start) << _PageShift
+                               if s.sizeclass != 0 {
+                                       size := s.elemsize
+                                       idx := (obj - p) / size
+                                       p = p + idx*size
+                               }
+                               if p == obj {
+                                       print("runtime: failed to find block beginning for ", hex(p), " s=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), "\n")
+                                       gothrow("failed to find block beginning")
+                               }
+                               obj = p
+                               goto markobj
+                       }
+
+                       if _DebugGCPtrs {
+                               print("scan *", hex(b+i), " = ", hex(obj0), " => base ", hex(obj), "\n")
+                       }
+
+                       if nbadblock > 0 && obj == badblock[nbadblock-1] {
+                               // Running garbage collection again because
+                               // we want to find the path from a root to a bad pointer.
+                               // Found possible next step; extend or finish path.
+                               for j := int32(0); j < nbadblock; j++ {
+                                       if badblock[j] == b {
+                                               goto AlreadyBad
+                                       }
+                               }
+                               print("runtime: found *(", hex(b), "+", hex(i), ") = ", hex(obj0), "+", hex(obj-obj0), "\n")
+                               if ptrmask != nil {
+                                       gothrow("bad pointer")
+                               }
+                               if nbadblock >= int32(len(badblock)) {
+                                       gothrow("badblock trace too long")
+                               }
+                               badblock[nbadblock] = uintptr(b)
+                               nbadblock++
+                       AlreadyBad:
+                       }
+
+                       // Now we have bits, bitp, and shift correct for
+                       // obj pointing at the base of the object.
+                       // Only care about not marked objects.
+                       if bits&bitMarked != 0 {
+                               continue
+                       }
+
+                       // If obj size is greater than 8, then each byte of GC bitmap
+                       // contains info for at most one object. In such case we use
+                       // non-atomic byte store to mark the object. This can lead
+                       // to double enqueue of the object for scanning, but scanning
+                       // is an idempotent operation, so it is OK. This cannot lead
+                       // to bitmap corruption because the single marked bit is the
+                       // only thing that can change in the byte.
+                       // For 8-byte objects we use non-atomic store, if the other
+                       // quadruple is already marked. Otherwise we resort to CAS
+                       // loop for marking.
+                       if xbits&(bitMask|bitMask<<gcBits) != bitBoundary|bitBoundary<<gcBits || work.nproc == 1 {
+                               *(*byte)(unsafe.Pointer(bitp)) = uint8(xbits | bitMarked<<shift)
+                       } else {
+                               atomicor8((*byte)(unsafe.Pointer(bitp)), bitMarked<<shift)
+                       }
+
+                       if (xbits>>(shift+2))&bitsMask == bitsDead {
+                               continue // noscan object
+                       }
+
+                       // Queue the obj for scanning.
+                       // TODO: PREFETCH here.
+
+                       // If workbuf is full, obtain an empty one.
+                       if nobj >= uintptr(len(wbuf.obj)) {
+                               wbuf.nobj = nobj
+                               wbuf = getempty(wbuf)
+                               nobj = wbuf.nobj
+                               wp = &wbuf.obj[nobj]
+                       }
+                       *wp = obj
+                       nobj++
+                       if nobj < uintptr(len(wbuf.obj)) {
+                               wp = &wbuf.obj[nobj]
+                       } else {
+                               wp = nil
+                       }
+                       continue
+
+               badobj:
+                       // If cgo_allocate is linked into the binary, it can allocate
+                       // memory as []unsafe.Pointer that may not contain actual
+                       // pointers and must be scanned conservatively.
+                       // In this case alone, allow the bad pointer.
+                       if have_cgo_allocate() && ptrmask == nil {
+                               continue
+                       }
+
+                       // Anything else indicates a bug somewhere.
+                       // If we're in the middle of chasing down a different bad pointer,
+                       // don't confuse the trace by printing about this one.
+                       if nbadblock > 0 {
+                               continue
+                       }
+
+                       print("runtime: garbage collector found invalid heap pointer *(", hex(b), "+", hex(i), ")=", hex(obj))
+                       if s == nil {
+                               print(" s=nil\n")
+                       } else {
+                               print(" span=", uintptr(s.start)<<_PageShift, "-", s.limit, "-", (uintptr(s.start)+s.npages)<<_PageShift, " state=", s.state, "\n")
+                       }
+                       if ptrmask != nil {
+                               gothrow("invalid heap pointer")
+                       }
+                       // Add to badblock list, which will cause the garbage collection
+                       // to keep repeating until it has traced the chain of pointers
+                       // leading to obj all the way back to a root.
+                       if nbadblock == 0 {
+                               badblock[nbadblock] = uintptr(b)
+                               nbadblock++
+                       }
+               }
+               if _DebugGCPtrs {
+                       print("end scanblock ", hex(b), " +", hex(n), " ", ptrmask, "\n")
+               }
+               if _DebugGC > 0 && ptrmask == nil {
+                       // For heap objects ensure that we did not overscan.
+                       var p, n uintptr
+                       if mlookup(b, &p, &n, nil) == 0 || b != p || i > n {
+                               print("runtime: scanned (", hex(b), "+", hex(i), "), heap object (", hex(p), "+", hex(n), ")\n")
+                               gothrow("scanblock: scanned invalid object")
+                       }
+               }
+       }
+}
+
+func markroot(desc *parfor, i uint32) {
+       // Note: if you add a case here, please also update heapdump.c:dumproots.
+       switch i {
+       case _RootData:
+               scanblock(uintptr(unsafe.Pointer(&data)), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)), gcdatamask.bytedata)
+
+       case _RootBss:
+               scanblock(uintptr(unsafe.Pointer(&bss)), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)), gcbssmask.bytedata)
+
+       case _RootFinalizers:
+               for fb := allfin; fb != nil; fb = fb.alllink {
+                       scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), uintptr(fb.cnt)*unsafe.Sizeof(fb.fin[0]), &finptrmask[0])
+               }
+
+       case _RootSpans:
+               // mark MSpan.specials
+               sg := mheap_.sweepgen
+               for spanidx := uint32(0); spanidx < uint32(len(work.spans)); spanidx++ {
+                       s := work.spans[spanidx]
+                       if s.state != mSpanInUse {
+                               continue
+                       }
+                       if s.sweepgen != sg {
+                               print("sweep ", s.sweepgen, " ", sg, "\n")
+                               gothrow("gc: unswept span")
+                       }
+                       for sp := s.specials; sp != nil; sp = sp.next {
+                               if sp.kind != _KindSpecialFinalizer {
+                                       continue
+                               }
+                               // don't mark finalized object, but scan it so we
+                               // retain everything it points to.
+                               spf := (*specialfinalizer)(unsafe.Pointer(sp))
+                               // A finalizer can be set for an inner byte of an object, find object beginning.
+                               p := uintptr(s.start<<_PageShift) + uintptr(spf.special.offset)/s.elemsize*s.elemsize
+                               scanblock(p, s.elemsize, nil)
+                               scanblock(uintptr(unsafe.Pointer(&spf.fn)), ptrSize, &oneptr[0])
+                       }
+               }
+
+       case _RootFlushCaches:
+               flushallmcaches()
+
+       default:
+               // the rest is scanning goroutine stacks
+               if uintptr(i-_RootCount) >= allglen {
+                       gothrow("markroot: bad index")
+               }
+               gp := allgs[i-_RootCount]
+               // remember when we've first observed the G blocked
+               // needed only to output in traceback
+               status := readgstatus(gp)
+               if (status == _Gwaiting || status == _Gsyscall) && gp.waitsince == 0 {
+                       gp.waitsince = work.tstart
+               }
+               // Shrink a stack if not much of it is being used.
+               shrinkstack(gp)
+               if readgstatus(gp) == _Gdead {
+                       gp.gcworkdone = true
+               } else {
+                       gp.gcworkdone = false
+               }
+               restart := stopg(gp)
+               scanstack(gp)
+               if restart {
+                       restartg(gp)
+               }
+       }
+}
+
+// Get an empty work buffer off the work.empty list,
+// allocating new buffers as needed.
+func getempty(b *workbuf) *workbuf {
+       _g_ := getg()
+       if b != nil {
+               lfstackpush(&work.full, &b.node)
+       }
+       b = nil
+       c := _g_.m.mcache
+       if c.gcworkbuf != nil {
+               b = (*workbuf)(c.gcworkbuf)
+               c.gcworkbuf = nil
+       }
+       if b == nil {
+               b = (*workbuf)(lfstackpop(&work.empty))
+       }
+       if b == nil {
+               b = (*workbuf)(persistentalloc(unsafe.Sizeof(*b), _CacheLineSize, &memstats.gc_sys))
+       }
+       b.nobj = 0
+       return b
+}
+
+func putempty(b *workbuf) {
+       _g_ := getg()
+       c := _g_.m.mcache
+       if c.gcworkbuf == nil {
+               c.gcworkbuf = (unsafe.Pointer)(b)
+               return
+       }
+       lfstackpush(&work.empty, &b.node)
+}
+
+func gcworkbuffree(b unsafe.Pointer) {
+       if b != nil {
+               putempty((*workbuf)(b))
+       }
+}
+
+// Get a full work buffer off the work.full list, or return nil.
+func getfull(b *workbuf) *workbuf {
+       if b != nil {
+               lfstackpush(&work.empty, &b.node)
+       }
+       b = (*workbuf)(lfstackpop(&work.full))
+       if b != nil || work.nproc == 1 {
+               return b
+       }
+
+       xadd(&work.nwait, +1)
+       for i := 0; ; i++ {
+               if work.full != 0 {
+                       xadd(&work.nwait, -1)
+                       b = (*workbuf)(lfstackpop(&work.full))
+                       if b != nil {
+                               return b
+                       }
+                       xadd(&work.nwait, +1)
+               }
+               if work.nwait == work.nproc {
+                       return nil
+               }
+               _g_ := getg()
+               if i < 10 {
+                       _g_.m.gcstats.nprocyield++
+                       procyield(20)
+               } else if i < 20 {
+                       _g_.m.gcstats.nosyield++
+                       osyield()
+               } else {
+                       _g_.m.gcstats.nsleep++
+                       usleep(100)
+               }
+       }
+}
+
+func handoff(b *workbuf) *workbuf {
+       // Make new buffer with half of b's pointers.
+       b1 := getempty(nil)
+       n := b.nobj / 2
+       b.nobj -= n
+       b1.nobj = n
+       memmove(unsafe.Pointer(&b1.obj[0]), unsafe.Pointer(&b.obj[b.nobj]), n*unsafe.Sizeof(b1.obj[0]))
+       _g_ := getg()
+       _g_.m.gcstats.nhandoff++
+       _g_.m.gcstats.nhandoffcnt += uint64(n)
+
+       // Put b on full list - let first half of b get stolen.
+       lfstackpush(&work.full, &b.node)
+       return b1
+}
+
+func stackmapdata(stkmap *stackmap, n int32) bitvector {
+       if n < 0 || n >= stkmap.n {
+               gothrow("stackmapdata: index out of range")
+       }
+       return bitvector{stkmap.nbit, (*byte)(add(unsafe.Pointer(&stkmap.bytedata), uintptr(n*((stkmap.nbit+31)/32*4))))}
+}
+
+// Scan a stack frame: local variables and function arguments/results.
+func scanframe(frame *stkframe, unused unsafe.Pointer) bool {
+
+       f := frame.fn
+       targetpc := frame.continpc
+       if targetpc == 0 {
+               // Frame is dead.
+               return true
+       }
+       if _DebugGC > 1 {
+               print("scanframe ", gofuncname(f), "\n")
+       }
+       if targetpc != f.entry {
+               targetpc--
+       }
+       pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+       if pcdata == -1 {
+               // We do not have a valid pcdata value but there might be a
+               // stackmap for this function.  It is likely that we are looking
+               // at the function prologue, assume so and hope for the best.
+               pcdata = 0
+       }
+
+       // Scan local variables if stack frame has been allocated.
+       size := frame.varp - frame.sp
+       var minsize uintptr
+       if thechar != '6' && thechar != '8' {
+               minsize = ptrSize
+       } else {
+               minsize = 0
+       }
+       if size > minsize {
+               stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
+               if stkmap == nil || stkmap.n <= 0 {
+                       print("runtime: frame ", gofuncname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
+                       gothrow("missing stackmap")
+               }
+
+               // Locals bitmap information, scan just the pointers in locals.
+               if pcdata < 0 || pcdata >= stkmap.n {
+                       // don't know where we are
+                       print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " locals stack map entries for ", gofuncname(f), " (targetpc=", targetpc, ")\n")
+                       gothrow("scanframe: bad symbol table")
+               }
+               bv := stackmapdata(stkmap, pcdata)
+               size = (uintptr(bv.n) * ptrSize) / bitsPerPointer
+               scanblock(frame.varp-size, uintptr(bv.n)/bitsPerPointer*ptrSize, bv.bytedata)
+       }
+
+       // Scan arguments.
+       if frame.arglen > 0 {
+               var bv bitvector
+               if frame.argmap != nil {
+                       bv = *frame.argmap
+               } else {
+                       stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
+                       if stkmap == nil || stkmap.n <= 0 {
+                               print("runtime: frame ", gofuncname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n")
+                               gothrow("missing stackmap")
+                       }
+                       if pcdata < 0 || pcdata >= stkmap.n {
+                               // don't know where we are
+                               print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " args stack map entries for ", gofuncname(f), " (targetpc=", targetpc, ")\n")
+                               gothrow("scanframe: bad symbol table")
+                       }
+                       bv = stackmapdata(stkmap, pcdata)
+               }
+               scanblock(frame.argp, uintptr(bv.n)/bitsPerPointer*ptrSize, bv.bytedata)
+       }
+       return true
+}
+
+func scanstack(gp *g) {
+       // TODO(rsc): Due to a precedence error, this was never checked in the original C version.
+       // If you enable the check, the gothrow happens.
+       /*
+               if readgstatus(gp)&_Gscan == 0 {
+                       print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
+                       gothrow("mark - bad status")
+               }
+       */
+
+       switch readgstatus(gp) &^ _Gscan {
+       default:
+               print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
+               gothrow("mark - bad status")
+       case _Gdead:
+               return
+       case _Grunning:
+               print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
+               gothrow("mark - world not stopped")
+       case _Grunnable, _Gsyscall, _Gwaiting:
+               // ok
+       }
+
+       if gp == getg() {
+               gothrow("can't scan our own stack")
+       }
+       mp := gp.m
+       if mp != nil && mp.helpgc != 0 {
+               gothrow("can't scan gchelper stack")
+       }
+
+       gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, scanframe, nil, 0)
+       tracebackdefers(gp, scanframe, nil)
+}
+
+// The gp has been moved to a gc safepoint. If there is gcphase specific
+// work it is done here.
+func gcphasework(gp *g) {
+       switch gcphase {
+       default:
+               gothrow("gcphasework in bad gcphase")
+       case _GCoff, _GCquiesce, _GCstw, _GCsweep:
+               // No work for now.
+       case _GCmark:
+               // Disabled until concurrent GC is implemented
+               // but indicate the scan has been done.
+               // scanstack(gp);
+       }
+       gp.gcworkdone = true
+}
+
+var finalizer1 = [...]byte{
+       // Each Finalizer is 5 words, ptr ptr uintptr ptr ptr.
+       // Each byte describes 4 words.
+       // Need 4 Finalizers described by 5 bytes before pattern repeats:
+       //      ptr ptr uintptr ptr ptr
+       //      ptr ptr uintptr ptr ptr
+       //      ptr ptr uintptr ptr ptr
+       //      ptr ptr uintptr ptr ptr
+       // aka
+       //      ptr ptr uintptr ptr
+       //      ptr ptr ptr uintptr
+       //      ptr ptr ptr ptr
+       //      uintptr ptr ptr ptr
+       //      ptr uintptr ptr ptr
+       // Assumptions about Finalizer layout checked below.
+       bitsPointer | bitsPointer<<2 | bitsScalar<<4 | bitsPointer<<6,
+       bitsPointer | bitsPointer<<2 | bitsPointer<<4 | bitsScalar<<6,
+       bitsPointer | bitsPointer<<2 | bitsPointer<<4 | bitsPointer<<6,
+       bitsScalar | bitsPointer<<2 | bitsPointer<<4 | bitsPointer<<6,
+       bitsPointer | bitsScalar<<2 | bitsPointer<<4 | bitsPointer<<6,
+}
+
+func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot *ptrtype) {
+       lock(&finlock)
+       if finq == nil || finq.cnt == finq.cap {
+               if finc == nil {
+                       finc = (*finblock)(persistentalloc(_FinBlockSize, 0, &memstats.gc_sys))
+                       finc.cap = int32((_FinBlockSize-unsafe.Sizeof(finblock{}))/unsafe.Sizeof(finalizer{}) + 1)
+                       finc.alllink = allfin
+                       allfin = finc
+                       if finptrmask[0] == 0 {
+                               // Build pointer mask for Finalizer array in block.
+                               // Check assumptions made in finalizer1 array above.
+                               if (unsafe.Sizeof(finalizer{}) != 5*ptrSize ||
+                                       unsafe.Offsetof(finalizer{}.fn) != 0 ||
+                                       unsafe.Offsetof(finalizer{}.arg) != ptrSize ||
+                                       unsafe.Offsetof(finalizer{}.nret) != 2*ptrSize ||
+                                       unsafe.Offsetof(finalizer{}.fint) != 3*ptrSize ||
+                                       unsafe.Offsetof(finalizer{}.ot) != 4*ptrSize ||
+                                       bitsPerPointer != 2) {
+                                       gothrow("finalizer out of sync")
+                               }
+                               for i := range finptrmask {
+                                       finptrmask[i] = finalizer1[i%len(finalizer1)]
+                               }
+                       }
+               }
+               block := finc
+               finc = block.next
+               block.next = finq
+               finq = block
+       }
+       f := (*finalizer)(add(unsafe.Pointer(&finq.fin[0]), uintptr(finq.cnt)*unsafe.Sizeof(finq.fin[0])))
+       finq.cnt++
+       f.fn = fn
+       f.nret = nret
+       f.fint = fint
+       f.ot = ot
+       f.arg = p
+       fingwake = true
+       unlock(&finlock)
+}
+
+func iterate_finq(callback func(*funcval, unsafe.Pointer, uintptr, *_type, *ptrtype)) {
+       for fb := allfin; fb != nil; fb = fb.alllink {
+               for i := int32(0); i < fb.cnt; i++ {
+                       f := &fb.fin[i]
+                       callback(f.fn, f.arg, f.nret, f.fint, f.ot)
+               }
+       }
+}
+
+func mSpan_EnsureSwept(s *mspan) {
+       // Caller must disable preemption.
+       // Otherwise when this function returns the span can become unswept again
+       // (if GC is triggered on another goroutine).
+       _g_ := getg()
+       if _g_.m.locks == 0 && _g_.m.mallocing == 0 && _g_ != _g_.m.g0 {
+               gothrow("MSpan_EnsureSwept: m is not locked")
+       }
+
+       sg := mheap_.sweepgen
+       if atomicload(&s.sweepgen) == sg {
+               return
+       }
+       if cas(&s.sweepgen, sg-2, sg-1) {
+               mSpan_Sweep(s, false)
+               return
+       }
+       // unfortunate condition, and we don't have efficient means to wait
+       for atomicload(&s.sweepgen) != sg {
+               osyield()
+       }
+}
+
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
+// It clears the mark bits in preparation for the next GC round.
+// Returns true if the span was returned to heap.
+// If preserve=true, don't return it to heap nor relink in MCentral lists;
+// caller takes care of it.
+func mSpan_Sweep(s *mspan, preserve bool) bool {
+       // It's critical that we enter this function with preemption disabled,
+       // GC must not start while we are in the middle of this function.
+       _g_ := getg()
+       if _g_.m.locks == 0 && _g_.m.mallocing == 0 && _g_ != _g_.m.g0 {
+               gothrow("MSpan_Sweep: m is not locked")
+       }
+       sweepgen := mheap_.sweepgen
+       if s.state != mSpanInUse || s.sweepgen != sweepgen-1 {
+               print("MSpan_Sweep: state=", s.state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
+               gothrow("MSpan_Sweep: bad span state")
+       }
+       arena_start := mheap_.arena_start
+       cl := s.sizeclass
+       size := s.elemsize
+       var n int32
+       var npages int32
+       if cl == 0 {
+               n = 1
+       } else {
+               // Chunk full of small blocks.
+               npages = class_to_allocnpages[cl]
+               n = (npages << _PageShift) / int32(size)
+       }
+       res := false
+       nfree := 0
+       var head mlink
+       end := &head
+       c := _g_.m.mcache
+       sweepgenset := false
+
+       // Mark any free objects in this span so we don't collect them.
+       for link := s.freelist; link != nil; link = link.next {
+               off := (uintptr(unsafe.Pointer(link)) - arena_start) / ptrSize
+               bitp := arena_start - off/wordsPerBitmapByte - 1
+               shift := (off % wordsPerBitmapByte) * gcBits
+               *(*byte)(unsafe.Pointer(bitp)) |= bitMarked << shift
+       }
+
+       // Unlink & free special records for any objects we're about to free.
+       specialp := &s.specials
+       special := *specialp
+       for special != nil {
+               // A finalizer can be set for an inner byte of an object, find object beginning.
+               p := uintptr(s.start<<_PageShift) + uintptr(special.offset)/size*size
+               off := (p - arena_start) / ptrSize
+               bitp := arena_start - off/wordsPerBitmapByte - 1
+               shift := (off % wordsPerBitmapByte) * gcBits
+               bits := (*(*byte)(unsafe.Pointer(bitp)) >> shift) & bitMask
+               if bits&bitMarked == 0 {
+                       // Find the exact byte for which the special was setup
+                       // (as opposed to object beginning).
+                       p := uintptr(s.start<<_PageShift) + uintptr(special.offset)
+                       // about to free object: splice out special record
+                       y := special
+                       special = special.next
+                       *specialp = special
+                       if !freespecial(y, unsafe.Pointer(p), size, false) {
+                               // stop freeing of object if it has a finalizer
+                               *(*byte)(unsafe.Pointer(bitp)) |= bitMarked << shift
+                       }
+               } else {
+                       // object is still live: keep special record
+                       specialp = &special.next
+                       special = *specialp
+               }
+       }
+
+       // Sweep through n objects of given size starting at p.
+       // This thread owns the span now, so it can manipulate
+       // the block bitmap without atomic operations.
+       p := uintptr(s.start << _PageShift)
+       off := (p - arena_start) / ptrSize
+       bitp := arena_start - off/wordsPerBitmapByte - 1
+       shift := uint(0)
+       step := size / (ptrSize * wordsPerBitmapByte)
+       // Rewind to the previous quadruple as we move to the next
+       // in the beginning of the loop.
+       bitp += step
+       if step == 0 {
+               // 8-byte objects.
+               bitp++
+               shift = gcBits
+       }
+       for ; n > 0; n, p = n-1, p+size {
+               bitp -= step
+               if step == 0 {
+                       if shift != 0 {
+                               bitp--
+                       }
+                       shift = gcBits - shift
+               }
+
+               xbits := *(*byte)(unsafe.Pointer(bitp))
+               bits := (xbits >> shift) & bitMask
+
+               // Allocated and marked object, reset bits to allocated.
+               if bits&bitMarked != 0 {
+                       *(*byte)(unsafe.Pointer(bitp)) &^= bitMarked << shift
+                       continue
+               }
+
+               // At this point we know that we are looking at garbage object
+               // that needs to be collected.
+               if debug.allocfreetrace != 0 {
+                       tracefree(unsafe.Pointer(p), size)
+               }
+
+               // Reset to allocated+noscan.
+               *(*byte)(unsafe.Pointer(bitp)) = uint8(uintptr(xbits&^((bitMarked|bitsMask<<2)<<shift)) | uintptr(bitsDead)<<(shift+2))
+               if cl == 0 {
+                       // Free large span.
+                       if preserve {
+                               gothrow("can't preserve large span")
+                       }
+                       unmarkspan(p, s.npages<<_PageShift)
+                       s.needzero = 1
+
+                       // important to set sweepgen before returning it to heap
+                       atomicstore(&s.sweepgen, sweepgen)
+                       sweepgenset = true
+
+                       // NOTE(rsc,dvyukov): The original implementation of efence
+                       // in CL 22060046 used SysFree instead of SysFault, so that
+                       // the operating system would eventually give the memory
+                       // back to us again, so that an efence program could run
+                       // longer without running out of memory. Unfortunately,
+                       // calling SysFree here without any kind of adjustment of the
+                       // heap data structures means that when the memory does
+                       // come back to us, we have the wrong metadata for it, either in
+                       // the MSpan structures or in the garbage collection bitmap.
+                       // Using SysFault here means that the program will run out of
+                       // memory fairly quickly in efence mode, but at least it won't
+                       // have mysterious crashes due to confused memory reuse.
+                       // It should be possible to switch back to SysFree if we also
+                       // implement and then call some kind of MHeap_DeleteSpan.
+                       if debug.efence > 0 {
+                               s.limit = 0 // prevent mlookup from finding this span
+                               sysFault(unsafe.Pointer(p), size)
+                       } else {
+                               mHeap_Free(&mheap_, s, 1)
+                       }
+                       c.local_nlargefree++
+                       c.local_largefree += size
+                       xadd64(&memstats.next_gc, -int64(size)*int64(gcpercent+100)/100)
+                       res = true
+               } else {
+                       // Free small object.
+                       if size > 2*ptrSize {
+                               *(*uintptr)(unsafe.Pointer(p + ptrSize)) = uintptrMask & 0xdeaddeaddeaddead // mark as "needs to be zeroed"
+                       } else if size > ptrSize {
+                               *(*uintptr)(unsafe.Pointer(p + ptrSize)) = 0
+                       }
+                       end.next = (*mlink)(unsafe.Pointer(p))
+                       end = end.next
+                       nfree++
+               }
+       }
+
+       // We need to set s.sweepgen = h.sweepgen only when all blocks are swept,
+       // because of the potential for a concurrent free/SetFinalizer.
+       // But we need to set it before we make the span available for allocation
+       // (return it to heap or mcentral), because allocation code assumes that a
+       // span is already swept if available for allocation.
+       if !sweepgenset && nfree == 0 {
+               // The span must be in our exclusive ownership until we update sweepgen,
+               // check for potential races.
+               if s.state != mSpanInUse || s.sweepgen != sweepgen-1 {
+                       print("MSpan_Sweep: state=", s.state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
+                       gothrow("MSpan_Sweep: bad span state after sweep")
+               }
+               atomicstore(&s.sweepgen, sweepgen)
+       }
+       if nfree > 0 {
+               c.local_nsmallfree[cl] += uintptr(nfree)
+               c.local_cachealloc -= intptr(uintptr(nfree) * size)
+               xadd64(&memstats.next_gc, -int64(nfree)*int64(size)*int64(gcpercent+100)/100)
+               res = mCentral_FreeSpan(&mheap_.central[cl].mcentral, s, int32(nfree), head.next, end, preserve)
+               // MCentral_FreeSpan updates sweepgen
+       }
+       return res
+}
+
+// State of background sweep.
+// Protected by gclock.
+type sweepdata struct {
+       g       *g
+       parked  bool
+       started bool
+
+       spanidx uint32 // background sweeper position
+
+       nbgsweep    uint32
+       npausesweep uint32
+}
+
+var sweep sweepdata
+
+// sweeps one span
+// returns number of pages returned to heap, or ^uintptr(0) if there is nothing to sweep
+func sweepone() uintptr {
+       _g_ := getg()
+
+       // increment locks to ensure that the goroutine is not preempted
+       // in the middle of sweep thus leaving the span in an inconsistent state for next GC
+       _g_.m.locks++
+       sg := mheap_.sweepgen
+       for {
+               idx := xadd(&sweep.spanidx, 1) - 1
+               if idx >= uint32(len(work.spans)) {
+                       mheap_.sweepdone = 1
+                       _g_.m.locks--
+                       return ^uintptr(0)
+               }
+               s := work.spans[idx]
+               if s.state != mSpanInUse {
+                       s.sweepgen = sg
+                       continue
+               }
+               if s.sweepgen != sg-2 || !cas(&s.sweepgen, sg-2, sg-1) {
+                       continue
+               }
+               npages := s.npages
+               if !mSpan_Sweep(s, false) {
+                       npages = 0
+               }
+               _g_.m.locks--
+               return npages
+       }
+}
+
+func gosweepone() uintptr {
+       var ret uintptr
+       systemstack(func() {
+               ret = sweepone()
+       })
+       return ret
+}
+
+func gosweepdone() bool {
+       return mheap_.sweepdone != 0
+}
+
+func gchelper() {
+       _g_ := getg()
+       _g_.m.traceback = 2
+       gchelperstart()
+
+       // parallel mark for over gc roots
+       parfordo(work.markfor)
+
+       // help other threads scan secondary blocks
+       scanblock(0, 0, nil)
+
+       nproc := work.nproc // work.nproc can change right after we increment work.ndone
+       if xadd(&work.ndone, +1) == nproc-1 {
+               notewakeup(&work.alldone)
+       }
+       _g_.m.traceback = 0
+}
+
+func cachestats() {
+       for i := 0; ; i++ {
+               p := allp[i]
+               if p == nil {
+                       break
+               }
+               c := p.mcache
+               if c == nil {
+                       continue
+               }
+               purgecachedstats(c)
+       }
+}
+
+func flushallmcaches() {
+       for i := 0; ; i++ {
+               p := allp[i]
+               if p == nil {
+                       break
+               }
+               c := p.mcache
+               if c == nil {
+                       continue
+               }
+               mCache_ReleaseAll(c)
+               stackcache_clear(c)
+       }
+}
+
+func updatememstats(stats *gcstats) {
+       if stats != nil {
+               *stats = gcstats{}
+       }
+       for mp := allm; mp != nil; mp = mp.alllink {
+               if stats != nil {
+                       src := (*[unsafe.Sizeof(gcstats{}) / 8]uint64)(unsafe.Pointer(&mp.gcstats))
+                       dst := (*[unsafe.Sizeof(gcstats{}) / 8]uint64)(unsafe.Pointer(stats))
+                       for i, v := range src {
+                               dst[i] += v
+                       }
+                       mp.gcstats = gcstats{}
+               }
+       }
+
+       memstats.mcache_inuse = uint64(mheap_.cachealloc.inuse)
+       memstats.mspan_inuse = uint64(mheap_.spanalloc.inuse)
+       memstats.sys = memstats.heap_sys + memstats.stacks_sys + memstats.mspan_sys +
+               memstats.mcache_sys + memstats.buckhash_sys + memstats.gc_sys + memstats.other_sys
+
+       // Calculate memory allocator stats.
+       // During program execution we only count number of frees and amount of freed memory.
+       // Current number of alive object in the heap and amount of alive heap memory
+       // are calculated by scanning all spans.
+       // Total number of mallocs is calculated as number of frees plus number of alive objects.
+       // Similarly, total amount of allocated memory is calculated as amount of freed memory
+       // plus amount of alive heap memory.
+       memstats.alloc = 0
+       memstats.total_alloc = 0
+       memstats.nmalloc = 0
+       memstats.nfree = 0
+       for i := 0; i < len(memstats.by_size); i++ {
+               memstats.by_size[i].nmalloc = 0
+               memstats.by_size[i].nfree = 0
+       }
+
+       // Flush MCache's to MCentral.
+       systemstack(flushallmcaches)
+
+       // Aggregate local stats.
+       cachestats()
+
+       // Scan all spans and count number of alive objects.
+       lock(&mheap_.lock)
+       for i := uint32(0); i < mheap_.nspan; i++ {
+               s := h_allspans[i]
+               if s.state != mSpanInUse {
+                       continue
+               }
+               if s.sizeclass == 0 {
+                       memstats.nmalloc++
+                       memstats.alloc += uint64(s.elemsize)
+               } else {
+                       memstats.nmalloc += uint64(s.ref)
+                       memstats.by_size[s.sizeclass].nmalloc += uint64(s.ref)
+                       memstats.alloc += uint64(s.ref) * uint64(s.elemsize)
+               }
+       }
+       unlock(&mheap_.lock)
+
+       // Aggregate by size class.
+       smallfree := uint64(0)
+       memstats.nfree = mheap_.nlargefree
+       for i := 0; i < len(memstats.by_size); i++ {
+               memstats.nfree += mheap_.nsmallfree[i]
+               memstats.by_size[i].nfree = mheap_.nsmallfree[i]
+               memstats.by_size[i].nmalloc += mheap_.nsmallfree[i]
+               smallfree += uint64(mheap_.nsmallfree[i]) * uint64(class_to_size[i])
+       }
+       memstats.nfree += memstats.tinyallocs
+       memstats.nmalloc += memstats.nfree
+
+       // Calculate derived stats.
+       memstats.total_alloc = uint64(memstats.alloc) + uint64(mheap_.largefree) + smallfree
+       memstats.heap_alloc = memstats.alloc
+       memstats.heap_objects = memstats.nmalloc - memstats.nfree
+}
+
+func gcinit() {
+       if unsafe.Sizeof(workbuf{}) != _WorkbufSize {
+               gothrow("runtime: size of Workbuf is suboptimal")
+       }
+
+       work.markfor = parforalloc(_MaxGcproc)
+       gcpercent = readgogc()
+       gcdatamask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcdata)), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)))
+       gcbssmask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcbss)), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)))
+}
+
+func gc_m(start_time int64, eagersweep bool) {
+       _g_ := getg()
+       gp := _g_.m.curg
+       casgstatus(gp, _Grunning, _Gwaiting)
+       gp.waitreason = "garbage collection"
+
+       gc(start_time, eagersweep)
+
+       if nbadblock > 0 {
+               // Work out path from root to bad block.
+               for {
+                       gc(start_time, eagersweep)
+                       if nbadblock >= int32(len(badblock)) {
+                               gothrow("cannot find path to bad pointer")
+                       }
+               }
+       }
+
+       casgstatus(gp, _Gwaiting, _Grunning)
+}
+
+func gc(start_time int64, eagersweep bool) {
+       if _DebugGCPtrs {
+               print("GC start\n")
+       }
+
+       if debug.allocfreetrace > 0 {
+               tracegc()
+       }
+
+       _g_ := getg()
+       _g_.m.traceback = 2
+       t0 := start_time
+       work.tstart = start_time
+
+       var t1 int64
+       if debug.gctrace > 0 {
+               t1 = nanotime()
+       }
+
+       // Sweep what is not sweeped by bgsweep.
+       for sweepone() != ^uintptr(0) {
+               sweep.npausesweep++
+       }
+
+       // Cache runtime.mheap_.allspans in work.spans to avoid conflicts with
+       // resizing/freeing allspans.
+       // New spans can be created while GC progresses, but they are not garbage for
+       // this round:
+       //  - new stack spans can be created even while the world is stopped.
+       //  - new malloc spans can be created during the concurrent sweep
+
+       // Even if this is stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
+       lock(&mheap_.lock)
+       // Free the old cached sweep array if necessary.
+       if work.spans != nil && &work.spans[0] != &h_allspans[0] {
+               sysFree(unsafe.Pointer(&work.spans[0]), uintptr(len(work.spans))*unsafe.Sizeof(work.spans[0]), &memstats.other_sys)
+       }
+       // Cache the current array for marking.
+       mheap_.gcspans = mheap_.allspans
+       work.spans = h_allspans
+       unlock(&mheap_.lock)
+
+       work.nwait = 0
+       work.ndone = 0
+       work.nproc = uint32(gcprocs())
+       parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), nil, false, markroot)
+       if work.nproc > 1 {
+               noteclear(&work.alldone)
+               helpgc(int32(work.nproc))
+       }
+
+       var t2 int64
+       if debug.gctrace > 0 {
+               t2 = nanotime()
+       }
+
+       gchelperstart()
+       parfordo(work.markfor)
+       scanblock(0, 0, nil)
+
+       var t3 int64
+       if debug.gctrace > 0 {
+               t3 = nanotime()
+       }
+
+       if work.nproc > 1 {
+               notesleep(&work.alldone)
+       }
+
+       shrinkfinish()
+
+       cachestats()
+       // next_gc calculation is tricky with concurrent sweep since we don't know size of live heap
+       // estimate what was live heap size after previous GC (for printing only)
+       heap0 := memstats.next_gc * 100 / (uint64(gcpercent) + 100)
+       // conservatively set next_gc to high value assuming that everything is live
+       // concurrent/lazy sweep will reduce this number while discovering new garbage
+       memstats.next_gc = memstats.heap_alloc + memstats.heap_alloc*uint64(gcpercent)/100
+
+       t4 := nanotime()
+       atomicstore64(&memstats.last_gc, uint64(unixnanotime())) // must be Unix time to make sense to user
+       memstats.pause_ns[memstats.numgc%uint32(len(memstats.pause_ns))] = uint64(t4 - t0)
+       memstats.pause_end[memstats.numgc%uint32(len(memstats.pause_end))] = uint64(t4)
+       memstats.pause_total_ns += uint64(t4 - t0)
+       memstats.numgc++
+       if memstats.debuggc {
+               print("pause ", t4-t0, "\n")
+       }
+
+       if debug.gctrace > 0 {
+               heap1 := memstats.heap_alloc
+               var stats gcstats
+               updatememstats(&stats)
+               if heap1 != memstats.heap_alloc {
+                       print("runtime: mstats skew: heap=", heap1, "/", memstats.heap_alloc, "\n")
+                       gothrow("mstats skew")
+               }
+               obj := memstats.nmalloc - memstats.nfree
+
+               stats.nprocyield += work.markfor.nprocyield
+               stats.nosyield += work.markfor.nosyield
+               stats.nsleep += work.markfor.nsleep
+
+               print("gc", memstats.numgc, "(", work.nproc, "): ",
+                       (t1-t0)/1000, "+", (t2-t1)/1000, "+", (t3-t2)/1000, "+", (t4-t3)/1000, " us, ",
+                       heap0>>20, " -> ", heap1>>20, " MB, ",
+                       obj, " (", memstats.nmalloc, "-", memstats.nfree, ") objects, ",
+                       gcount(), " goroutines, ",
+                       len(work.spans), "/", sweep.nbgsweep, "/", sweep.npausesweep, " sweeps, ",
+                       stats.nhandoff, "(", stats.nhandoffcnt, ") handoff, ",
+                       work.markfor.nsteal, "(", work.markfor.nstealcnt, ") steal, ",
+                       stats.nprocyield, "/", stats.nosyield, "/", stats.nsleep, " yields\n")
+               sweep.nbgsweep = 0
+               sweep.npausesweep = 0
+       }
+
+       // See the comment in the beginning of this function as to why we need the following.
+       // Even if this is still stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
+       lock(&mheap_.lock)
+       // Free the old cached mark array if necessary.
+       if work.spans != nil && &work.spans[0] != &h_allspans[0] {
+               sysFree(unsafe.Pointer(&work.spans[0]), uintptr(len(work.spans))*unsafe.Sizeof(work.spans[0]), &memstats.other_sys)
+       }
+
+       // Cache the current array for sweeping.
+       mheap_.gcspans = mheap_.allspans
+       mheap_.sweepgen += 2
+       mheap_.sweepdone = 0
+       work.spans = h_allspans
+       sweep.spanidx = 0
+       unlock(&mheap_.lock)
+
+       if _ConcurrentSweep && !eagersweep {
+               lock(&gclock)
+               if !sweep.started {
+                       go bgsweep()
+                       sweep.started = true
+               } else if sweep.parked {
+                       sweep.parked = false
+                       ready(sweep.g)
+               }
+               unlock(&gclock)
+       } else {
+               // Sweep all spans eagerly.
+               for sweepone() != ^uintptr(0) {
+                       sweep.npausesweep++
+               }
+               // Do an additional mProf_GC, because all 'free' events are now real as well.
+               mProf_GC()
+       }
+
+       mProf_GC()
+       _g_.m.traceback = 0
+
+       if _DebugGCPtrs {
+               print("GC end\n")
+       }
+}
+
+func readmemstats_m(stats *MemStats) {
+       updatememstats(nil)
+
+       // Size of the trailing by_size array differs between Go and C,
+       // NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+       memmove(unsafe.Pointer(stats), unsafe.Pointer(&memstats), sizeof_C_MStats)
+
+       // Stack numbers are part of the heap numbers, separate those out for user consumption
+       stats.StackSys = stats.StackInuse
+       stats.HeapInuse -= stats.StackInuse
+       stats.HeapSys -= stats.StackInuse
+}
+
+//go:linkname readGCStats runtime/debug.readGCStats
+func readGCStats(pauses *[]uint64) {
+       systemstack(func() {
+               readGCStats_m(pauses)
+       })
+}
+
+func readGCStats_m(pauses *[]uint64) {
+       p := *pauses
+       // Calling code in runtime/debug should make the slice large enough.
+       if cap(p) < len(memstats.pause_ns)+3 {
+               gothrow("runtime: short slice passed to readGCStats")
+       }
+
+       // Pass back: pauses, pause ends, last gc (absolute time), number of gc, total pause ns.
+       lock(&mheap_.lock)
+
+       n := memstats.numgc
+       if n > uint32(len(memstats.pause_ns)) {
+               n = uint32(len(memstats.pause_ns))
+       }
+
+       // The pause buffer is circular. The most recent pause is at
+       // pause_ns[(numgc-1)%len(pause_ns)], and then backward
+       // from there to go back farther in time. We deliver the times
+       // most recent first (in p[0]).
+       p = p[:cap(p)]
+       for i := uint32(0); i < n; i++ {
+               j := (memstats.numgc - 1 - i) % uint32(len(memstats.pause_ns))
+               p[i] = memstats.pause_ns[j]
+               p[n+i] = memstats.pause_end[j]
+       }
+
+       p[n+n] = memstats.last_gc
+       p[n+n+1] = uint64(memstats.numgc)
+       p[n+n+2] = memstats.pause_total_ns
+       unlock(&mheap_.lock)
+       *pauses = p[:n+n+3]
+}
+
+func setGCPercent(in int32) (out int32) {
+       lock(&mheap_.lock)
+       out = gcpercent
+       if in < 0 {
+               in = -1
+       }
+       gcpercent = in
+       unlock(&mheap_.lock)
+       return out
+}
+
+func gchelperstart() {
+       _g_ := getg()
+
+       if _g_.m.helpgc < 0 || _g_.m.helpgc >= _MaxGcproc {
+               gothrow("gchelperstart: bad m->helpgc")
+       }
+       if _g_ != _g_.m.g0 {
+               gothrow("gchelper not running on g0 stack")
+       }
+}
+
+func wakefing() *g {
+       var res *g
+       lock(&finlock)
+       if fingwait && fingwake {
+               fingwait = false
+               fingwake = false
+               res = fing
+       }
+       unlock(&finlock)
+       return res
+}
+
+func addb(p *byte, n uintptr) *byte {
+       return (*byte)(add(unsafe.Pointer(p), n))
+}
+
+// Recursively unrolls GC program in prog.
+// mask is where to store the result.
+// ppos is a pointer to position in mask, in bits.
+// sparse says to generate 4-bits per word mask for heap (2-bits for data/bss otherwise).
+func unrollgcprog1(maskp *byte, prog *byte, ppos *uintptr, inplace, sparse bool) *byte {
+       arena_start := mheap_.arena_start
+       pos := *ppos
+       mask := (*[1 << 30]byte)(unsafe.Pointer(maskp))
+       for {
+               switch *prog {
+               default:
+                       gothrow("unrollgcprog: unknown instruction")
+
+               case insData:
+                       prog = addb(prog, 1)
+                       siz := int(*prog)
+                       prog = addb(prog, 1)
+                       p := (*[1 << 30]byte)(unsafe.Pointer(prog))
+                       for i := 0; i < siz; i++ {
+                               v := p[i/_PointersPerByte]
+                               v >>= (uint(i) % _PointersPerByte) * _BitsPerPointer
+                               v &= _BitsMask
+                               if inplace {
+                                       // Store directly into GC bitmap.
+                                       off := (uintptr(unsafe.Pointer(&mask[pos])) - arena_start) / ptrSize
+                                       bitp := (*byte)(unsafe.Pointer(arena_start - off/wordsPerBitmapByte - 1))
+                                       shift := (off % wordsPerBitmapByte) * gcBits
+                                       if shift == 0 {
+                                               *bitp = 0
+                                       }
+                                       *bitp |= v << (shift + 2)
+                                       pos += ptrSize
+                               } else if sparse {
+                                       // 4-bits per word
+                                       v <<= (pos % 8) + 2
+                                       mask[pos/8] |= v
+                                       pos += gcBits
+                               } else {
+                                       // 2-bits per word
+                                       v <<= pos % 8
+                                       mask[pos/8] |= v
+                                       pos += _BitsPerPointer
+                               }
+                       }
+                       prog = addb(prog, round(uintptr(siz)*_BitsPerPointer, 8)/8)
+
+               case insArray:
+                       prog = (*byte)(add(unsafe.Pointer(prog), 1))
+                       siz := uintptr(0)
+                       for i := uintptr(0); i < ptrSize; i++ {
+                               siz = (siz << 8) + uintptr(*(*byte)(add(unsafe.Pointer(prog), ptrSize-i-1)))
+                       }
+                       prog = (*byte)(add(unsafe.Pointer(prog), ptrSize))
+                       var prog1 *byte
+                       for i := uintptr(0); i < siz; i++ {
+                               prog1 = unrollgcprog1(&mask[0], prog, &pos, inplace, sparse)
+                       }
+                       if *prog1 != insArrayEnd {
+                               gothrow("unrollgcprog: array does not end with insArrayEnd")
+                       }
+                       prog = (*byte)(add(unsafe.Pointer(prog1), 1))
+
+               case insArrayEnd, insEnd:
+                       *ppos = pos
+                       return prog
+               }
+       }
+}
+
+// Unrolls GC program prog for data/bss, returns dense GC mask.
+func unrollglobgcprog(prog *byte, size uintptr) bitvector {
+       masksize := round(round(size, ptrSize)/ptrSize*bitsPerPointer, 8) / 8
+       mask := (*[1 << 30]byte)(persistentalloc(masksize+1, 0, &memstats.gc_sys))
+       mask[masksize] = 0xa1
+       pos := uintptr(0)
+       prog = unrollgcprog1(&mask[0], prog, &pos, false, false)
+       if pos != size/ptrSize*bitsPerPointer {
+               print("unrollglobgcprog: bad program size, got ", pos, ", expect ", size/ptrSize*bitsPerPointer, "\n")
+               gothrow("unrollglobgcprog: bad program size")
+       }
+       if *prog != insEnd {
+               gothrow("unrollglobgcprog: program does not end with insEnd")
+       }
+       if mask[masksize] != 0xa1 {
+               gothrow("unrollglobgcprog: overflow")
+       }
+       return bitvector{int32(masksize * 8), &mask[0]}
+}
+
+func unrollgcproginplace_m(v unsafe.Pointer, typ *_type, size, size0 uintptr) {
+       pos := uintptr(0)
+       prog := (*byte)(unsafe.Pointer(uintptr(typ.gc[1])))
+       for pos != size0 {
+               unrollgcprog1((*byte)(v), prog, &pos, true, true)
+       }
+
+       // Mark first word as bitAllocated.
+       arena_start := mheap_.arena_start
+       off := (uintptr(v) - arena_start) / ptrSize
+       bitp := (*byte)(unsafe.Pointer(arena_start - off/wordsPerBitmapByte - 1))
+       shift := (off % wordsPerBitmapByte) * gcBits
+       *bitp |= bitBoundary << shift
+
+       // Mark word after last as BitsDead.
+       if size0 < size {
+               off := (uintptr(v) + size0 - arena_start) / ptrSize
+               bitp := (*byte)(unsafe.Pointer(arena_start - off/wordsPerBitmapByte - 1))
+               shift := (off % wordsPerBitmapByte) * gcBits
+               *bitp &= uint8(^(bitPtrMask << shift) | uintptr(bitsDead)<<(shift+2))
+       }
+}
+
+var unroll mutex
+
+// Unrolls GC program in typ.gc[1] into typ.gc[0]
+func unrollgcprog_m(typ *_type) {
+       lock(&unroll)
+       mask := (*byte)(unsafe.Pointer(uintptr(typ.gc[0])))
+       if *mask == 0 {
+               pos := uintptr(8) // skip the unroll flag
+               prog := (*byte)(unsafe.Pointer(uintptr(typ.gc[1])))
+               prog = unrollgcprog1(mask, prog, &pos, false, true)
+               if *prog != insEnd {
+                       gothrow("unrollgcprog: program does not end with insEnd")
+               }
+               if typ.size/ptrSize%2 != 0 {
+                       // repeat the program
+                       prog := (*byte)(unsafe.Pointer(uintptr(typ.gc[1])))
+                       unrollgcprog1(mask, prog, &pos, false, true)
+               }
+
+               // atomic way to say mask[0] = 1
+               atomicor8(mask, 1)
+       }
+       unlock(&unroll)
+}
+
+// mark the span of memory at v as having n blocks of the given size.
+// if leftover is true, there is left over space at the end of the span.
+func markspan(v unsafe.Pointer, size uintptr, n uintptr, leftover bool) {
+       if uintptr(v)+size*n > mheap_.arena_used || uintptr(v) < mheap_.arena_start {
+               gothrow("markspan: bad pointer")
+       }
+
+       // Find bits of the beginning of the span.
+       off := (uintptr(v) - uintptr(mheap_.arena_start)) / ptrSize
+       if off%wordsPerBitmapByte != 0 {
+               gothrow("markspan: unaligned length")
+       }
+       b := mheap_.arena_start - off/wordsPerBitmapByte - 1
+
+       // Okay to use non-atomic ops here, because we control
+       // the entire span, and each bitmap byte has bits for only
+       // one span, so no other goroutines are changing these bitmap words.
+
+       if size == ptrSize {
+               // Possible only on 64-bits (minimal size class is 8 bytes).
+               // Set memory to 0x11.
+               if (bitBoundary|bitsDead)<<gcBits|bitBoundary|bitsDead != 0x11 {
+                       gothrow("markspan: bad bits")
+               }
+               if n%(wordsPerBitmapByte*ptrSize) != 0 {
+                       gothrow("markspan: unaligned length")
+               }
+               b = b - n/wordsPerBitmapByte + 1 // find first byte
+               if b%ptrSize != 0 {
+                       gothrow("markspan: unaligned pointer")
+               }
+               for i := uintptr(0); i < n; i, b = i+wordsPerBitmapByte*ptrSize, b+ptrSize {
+                       *(*uintptr)(unsafe.Pointer(b)) = uintptrMask & 0x1111111111111111 // bitBoundary | bitsDead, repeated
+               }
+               return
+       }
+
+       if leftover {
+               n++ // mark a boundary just past end of last block too
+       }
+       step := size / (ptrSize * wordsPerBitmapByte)
+       for i := uintptr(0); i < n; i, b = i+1, b-step {
+               *(*byte)(unsafe.Pointer(b)) = bitBoundary | bitsDead<<2
+       }
+}
+
+// unmark the span of memory at v of length n bytes.
+func unmarkspan(v, n uintptr) {
+       if v+n > mheap_.arena_used || v < mheap_.arena_start {
+               gothrow("markspan: bad pointer")
+       }
+
+       off := (v - mheap_.arena_start) / ptrSize // word offset
+       if off%(ptrSize*wordsPerBitmapByte) != 0 {
+               gothrow("markspan: unaligned pointer")
+       }
+
+       b := mheap_.arena_start - off/wordsPerBitmapByte - 1
+       n /= ptrSize
+       if n%(ptrSize*wordsPerBitmapByte) != 0 {
+               gothrow("unmarkspan: unaligned length")
+       }
+
+       // Okay to use non-atomic ops here, because we control
+       // the entire span, and each bitmap word has bits for only
+       // one span, so no other goroutines are changing these
+       // bitmap words.
+       n /= wordsPerBitmapByte
+       memclr(unsafe.Pointer(b-n+1), n)
+}
+
+func mHeap_MapBits(h *mheap) {
+       // Caller has added extra mappings to the arena.
+       // Add extra mappings of bitmap words as needed.
+       // We allocate extra bitmap pieces in chunks of bitmapChunk.
+       const bitmapChunk = 8192
+
+       n := (h.arena_used - h.arena_start) / (ptrSize * wordsPerBitmapByte)
+       n = round(n, bitmapChunk)
+       n = round(n, _PhysPageSize)
+       if h.bitmap_mapped >= n {
+               return
+       }
+
+       sysMap(unsafe.Pointer(h.arena_start-n), n-h.bitmap_mapped, h.arena_reserved, &memstats.gc_sys)
+       h.bitmap_mapped = n
+}
+
+func getgcmaskcb(frame *stkframe, ctxt unsafe.Pointer) bool {
+       target := (*stkframe)(ctxt)
+       if frame.sp <= target.sp && target.sp < frame.varp {
+               *target = *frame
+               return false
+       }
+       return true
+}
+
+// Returns GC type info for object p for testing.
+func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) {
+       *mask = nil
+       *len = 0
+
+       // data
+       if uintptr(unsafe.Pointer(&data)) <= uintptr(p) && uintptr(p) < uintptr(unsafe.Pointer(&edata)) {
+               n := (*ptrtype)(unsafe.Pointer(t)).elem.size
+               *len = n / ptrSize
+               *mask = &make([]byte, *len)[0]
+               for i := uintptr(0); i < n; i += ptrSize {
+                       off := (uintptr(p) + i - uintptr(unsafe.Pointer(&data))) / ptrSize
+                       bits := (*(*byte)(add(unsafe.Pointer(gcdatamask.bytedata), off/pointersPerByte)) >> ((off % pointersPerByte) * bitsPerPointer)) & bitsMask
+                       *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
+               }
+               return
+       }
+
+       // bss
+       if uintptr(unsafe.Pointer(&bss)) <= uintptr(p) && uintptr(p) < uintptr(unsafe.Pointer(&ebss)) {
+               n := (*ptrtype)(unsafe.Pointer(t)).elem.size
+               *len = n / ptrSize
+               *mask = &make([]byte, *len)[0]
+               for i := uintptr(0); i < n; i += ptrSize {
+                       off := (uintptr(p) + i - uintptr(unsafe.Pointer(&bss))) / ptrSize
+                       bits := (*(*byte)(add(unsafe.Pointer(gcbssmask.bytedata), off/pointersPerByte)) >> ((off % pointersPerByte) * bitsPerPointer)) & bitsMask
+                       *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
+               }
+               return
+       }
+
+       // heap
+       var n uintptr
+       var base uintptr
+       if mlookup(uintptr(p), &base, &n, nil) != 0 {
+               *len = n / ptrSize
+               *mask = &make([]byte, *len)[0]
+               for i := uintptr(0); i < n; i += ptrSize {
+                       off := (uintptr(base) + i - mheap_.arena_start) / ptrSize
+                       b := mheap_.arena_start - off/wordsPerBitmapByte - 1
+                       shift := (off % wordsPerBitmapByte) * gcBits
+                       bits := (*(*byte)(unsafe.Pointer(b)) >> (shift + 2)) & bitsMask
+                       *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
+               }
+               return
+       }
+
+       // stack
+       var frame stkframe
+       frame.sp = uintptr(p)
+       _g_ := getg()
+       gentraceback(_g_.m.curg.sched.pc, _g_.m.curg.sched.sp, 0, _g_.m.curg, 0, nil, 1000, getgcmaskcb, noescape(unsafe.Pointer(&frame)), 0)
+       if frame.fn != nil {
+               f := frame.fn
+               targetpc := frame.continpc
+               if targetpc == 0 {
+                       return
+               }
+               if targetpc != f.entry {
+                       targetpc--
+               }
+               pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+               if pcdata == -1 {
+                       return
+               }
+               stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
+               if stkmap == nil || stkmap.n <= 0 {
+                       return
+               }
+               bv := stackmapdata(stkmap, pcdata)
+               size := uintptr(bv.n) / bitsPerPointer * ptrSize
+               n := (*ptrtype)(unsafe.Pointer(t)).elem.size
+               *len = n / ptrSize
+               *mask = &make([]byte, *len)[0]
+               for i := uintptr(0); i < n; i += ptrSize {
+                       off := (uintptr(p) + i - frame.varp + size) / ptrSize
+                       bits := ((*(*byte)(add(unsafe.Pointer(bv.bytedata), off*bitsPerPointer/8))) >> ((off * bitsPerPointer) % 8)) & bitsMask
+                       *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
+               }
+       }
+}
+
+func unixnanotime() int64 {
+       var now int64
+       gc_unixnanotime(&now)
+       return now
+}
diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c
deleted file mode 100644 (file)
index 7754bad..0000000
+++ /dev/null
@@ -1,2010 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Garbage collector (GC).
-//
-// GC is:
-// - mark&sweep
-// - mostly precise (with the exception of some C-allocated objects, assembly frames/arguments, etc)
-// - parallel (up to MaxGcproc threads)
-// - partially concurrent (mark is stop-the-world, while sweep is concurrent)
-// - non-moving/non-compacting
-// - full (non-partial)
-//
-// GC rate.
-// Next GC is after we've allocated an extra amount of memory proportional to
-// the amount already in use. The proportion is controlled by GOGC environment variable
-// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M
-// (this mark is tracked in next_gc variable). This keeps the GC cost in linear
-// proportion to the allocation cost. Adjusting GOGC just changes the linear constant
-// (and also the amount of extra memory used).
-//
-// Concurrent sweep.
-// The sweep phase proceeds concurrently with normal program execution.
-// The heap is swept span-by-span both lazily (when a goroutine needs another span)
-// and concurrently in a background goroutine (this helps programs that are not CPU bound).
-// However, at the end of the stop-the-world GC phase we don't know the size of the live heap,
-// and so next_gc calculation is tricky and happens as follows.
-// At the end of the stop-the-world phase next_gc is conservatively set based on total
-// heap size; all spans are marked as "needs sweeping".
-// Whenever a span is swept, next_gc is decremented by GOGC*newly_freed_memory.
-// The background sweeper goroutine simply sweeps spans one-by-one bringing next_gc
-// closer to the target value. However, this is not enough to avoid over-allocating memory.
-// Consider that a goroutine wants to allocate a new span for a large object and
-// there are no free swept spans, but there are small-object unswept spans.
-// If the goroutine naively allocates a new span, it can surpass the yet-unknown
-// target next_gc value. In order to prevent such cases (1) when a goroutine needs
-// to allocate a new small-object span, it sweeps small-object spans for the same
-// object size until it frees at least one object; (2) when a goroutine needs to
-// allocate large-object span from heap, it sweeps spans until it frees at least
-// that many pages into heap. Together these two measures ensure that we don't surpass
-// target next_gc value by a large margin. There is an exception: if a goroutine sweeps
-// and frees two nonadjacent one-page spans to the heap, it will allocate a new two-page span,
-// but there can still be other one-page unswept spans which could be combined into a two-page span.
-// It's critical to ensure that no operations proceed on unswept spans (that would corrupt
-// mark bits in GC bitmap). During GC all mcaches are flushed into the central cache,
-// so they are empty. When a goroutine grabs a new span into mcache, it sweeps it.
-// When a goroutine explicitly frees an object or sets a finalizer, it ensures that
-// the span is swept (either by sweeping it, or by waiting for the concurrent sweep to finish).
-// The finalizer goroutine is kicked off only when all spans are swept.
-// When the next GC starts, it sweeps all not-yet-swept spans (if any).
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "stack.h"
-#include "mgc0.h"
-#include "chan.h"
-#include "race.h"
-#include "type.h"
-#include "typekind.h"
-#include "funcdata.h"
-#include "textflag.h"
-
-enum {
-       Debug           = 0,
-       DebugPtrs       = 0, // if 1, print trace of every pointer load during GC
-       ConcurrentSweep = 1,
-
-       WorkbufSize     = 4*1024,
-       FinBlockSize    = 4*1024,
-       RootData        = 0,
-       RootBss         = 1,
-       RootFinalizers  = 2,
-       RootSpans       = 3,
-       RootFlushCaches = 4,
-       RootCount       = 5,
-};
-
-// ptrmask for an allocation containing a single pointer.
-static byte oneptr[] = {BitsPointer};
-
-// Initialized from $GOGC.  GOGC=off means no gc.
-extern int32 runtime·gcpercent;
-
-// Holding worldsema grants an M the right to try to stop the world.
-// The procedure is:
-//
-//     runtime·semacquire(&runtime·worldsema);
-//     m->gcing = 1;
-//     runtime·stoptheworld();
-//
-//     ... do stuff ...
-//
-//     m->gcing = 0;
-//     runtime·semrelease(&runtime·worldsema);
-//     runtime·starttheworld();
-//
-uint32 runtime·worldsema = 1;
-
-typedef struct Workbuf Workbuf;
-struct Workbuf
-{
-       LFNode  node; // must be first
-       uintptr nobj;
-       byte*   obj[(WorkbufSize-sizeof(LFNode)-sizeof(uintptr))/PtrSize];
-};
-
-extern byte runtime·data[];
-extern byte runtime·edata[];
-extern byte runtime·bss[];
-extern byte runtime·ebss[];
-
-extern byte runtime·gcdata[];
-extern byte runtime·gcbss[];
-
-Mutex  runtime·finlock;       // protects the following variables
-G*     runtime·fing;          // goroutine that runs finalizers
-FinBlock*      runtime·finq;  // list of finalizers that are to be executed
-FinBlock*      runtime·finc;  // cache of free blocks
-static byte finptrmask[FinBlockSize/PtrSize/PointersPerByte];
-bool   runtime·fingwait;
-bool   runtime·fingwake;
-FinBlock       *runtime·allfin;       // list of all blocks
-
-BitVector      runtime·gcdatamask;
-BitVector      runtime·gcbssmask;
-
-Mutex  runtime·gclock;
-
-static uintptr badblock[1024];
-static int32   nbadblock;
-
-static Workbuf* getempty(Workbuf*);
-static Workbuf* getfull(Workbuf*);
-static void    putempty(Workbuf*);
-static Workbuf* handoff(Workbuf*);
-static void    gchelperstart(void);
-static void    flushallmcaches(void);
-static bool    scanframe(Stkframe *frame, void *unused);
-static void    scanstack(G *gp);
-static BitVector       unrollglobgcprog(byte *prog, uintptr size);
-
-void runtime·bgsweep(void);
-static FuncVal bgsweepv = {runtime·bgsweep};
-
-typedef struct WorkData WorkData;
-struct WorkData {
-       uint64  full;  // lock-free list of full blocks
-       uint64  empty; // lock-free list of empty blocks
-       byte    pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
-       uint32  nproc;
-       int64   tstart;
-       volatile uint32 nwait;
-       volatile uint32 ndone;
-       Note    alldone;
-       ParFor* markfor;
-
-       // Copy of mheap.allspans for marker or sweeper.
-       MSpan** spans;
-       uint32  nspan;
-};
-WorkData runtime·work;
-
-// Is _cgo_allocate linked into the binary?
-static bool
-have_cgo_allocate(void)
-{
-       extern  byte    go·weak·runtime·_cgo_allocate_internal[1];
-       return go·weak·runtime·_cgo_allocate_internal != nil;
-}
-
-// scanblock scans a block of n bytes starting at pointer b for references
-// to other objects, scanning any it finds recursively until there are no
-// unscanned objects left.  Instead of using an explicit recursion, it keeps
-// a work list in the Workbuf* structures and loops in the main function
-// body.  Keeping an explicit work list is easier on the stack allocator and
-// more efficient.
-static void
-scanblock(byte *b, uintptr n, byte *ptrmask)
-{
-       byte *obj, *obj0, *p, *arena_start, *arena_used, **wp, *scanbuf[8], *ptrbitp, *bitp;
-       uintptr i, j, nobj, size, idx, x, off, scanbufpos, bits, xbits, shift;
-       Workbuf *wbuf;
-       Iface *iface;
-       Eface *eface;
-       Type *typ;
-       MSpan *s;
-       pageID k;
-       bool keepworking;
-
-       // Cache memory arena parameters in local vars.
-       arena_start = runtime·mheap.arena_start;
-       arena_used = runtime·mheap.arena_used;
-
-       wbuf = getempty(nil);
-       nobj = wbuf->nobj;
-       wp = &wbuf->obj[nobj];
-       keepworking = b == nil;
-       scanbufpos = 0;
-       for(i = 0; i < nelem(scanbuf); i++)
-               scanbuf[i] = nil;
-
-       ptrbitp = nil;
-
-       // ptrmask can have 2 possible values:
-       // 1. nil - obtain pointer mask from GC bitmap.
-       // 2. pointer to a compact mask (for stacks and data).
-       if(b != nil)
-               goto scanobj;
-       for(;;) {
-               if(nobj == 0) {
-                       // Out of work in workbuf.
-                       // First, see is there is any work in scanbuf.
-                       for(i = 0; i < nelem(scanbuf); i++) {
-                               b = scanbuf[scanbufpos];
-                               scanbuf[scanbufpos++] = nil;
-                               scanbufpos %= nelem(scanbuf);
-                               if(b != nil) {
-                                       n = arena_used - b; // scan until bitBoundary or BitsDead
-                                       ptrmask = nil; // use GC bitmap for pointer info
-                                       goto scanobj;
-                               }
-                       }
-                       if(!keepworking) {
-                               putempty(wbuf);
-                               return;
-                       }
-                       // Refill workbuf from global queue.
-                       wbuf = getfull(wbuf);
-                       if(wbuf == nil)
-                               return;
-                       nobj = wbuf->nobj;
-                       wp = &wbuf->obj[nobj];
-               }
-
-               // If another proc wants a pointer, give it some.
-               if(runtime·work.nwait > 0 && nobj > 4 && runtime·work.full == 0) {
-                       wbuf->nobj = nobj;
-                       wbuf = handoff(wbuf);
-                       nobj = wbuf->nobj;
-                       wp = &wbuf->obj[nobj];
-               }
-
-               wp--;
-               nobj--;
-               b = *wp;
-               n = arena_used - b; // scan until next bitBoundary or BitsDead
-               ptrmask = nil; // use GC bitmap for pointer info
-
-       scanobj:
-               if(DebugPtrs)
-                       runtime·printf("scanblock %p +%p %p\n", b, n, ptrmask);
-               // Find bits of the beginning of the object.
-               if(ptrmask == nil) {
-                       off = (uintptr*)b - (uintptr*)arena_start;
-                       ptrbitp = arena_start - off/wordsPerBitmapByte - 1;
-               }
-               for(i = 0; i < n; i += PtrSize) {
-                       obj = nil;
-                       // Find bits for this word.
-                       if(ptrmask == nil) {
-                               // Check is we have reached end of span.
-                               if((((uintptr)b+i)%PageSize) == 0 &&
-                                       runtime·mheap.spans[(b-arena_start)>>PageShift] != runtime·mheap.spans[(b+i-arena_start)>>PageShift])
-                                       break;
-                               // Consult GC bitmap.
-                               bits = *ptrbitp;
-
-                               if(wordsPerBitmapByte != 2)
-                                       runtime·throw("alg doesn't work for wordsPerBitmapByte != 2");
-                               j = ((uintptr)b+i)/PtrSize & 1;
-                               ptrbitp -= j;
-                               bits >>= gcBits*j;
-
-                               if((bits&bitBoundary) != 0 && i != 0)
-                                       break; // reached beginning of the next object
-                               bits = (bits>>2)&BitsMask;
-                               if(bits == BitsDead)
-                                       break; // reached no-scan part of the object
-                       } else // dense mask (stack or data)
-                               bits = (ptrmask[(i/PtrSize)/4]>>(((i/PtrSize)%4)*BitsPerPointer))&BitsMask;
-
-                       if(bits <= BitsScalar) // BitsScalar || BitsDead
-                               continue;
-                       if(bits == BitsPointer) {
-                               obj = *(byte**)(b+i);
-                               obj0 = obj;
-                               goto markobj;
-                       }
-
-                       // With those three out of the way, must be multi-word.
-                       if(Debug && bits != BitsMultiWord)
-                               runtime·throw("unexpected garbage collection bits");
-                       // Find the next pair of bits.
-                       if(ptrmask == nil) {
-                               bits = *ptrbitp;
-                               j = ((uintptr)b+i+PtrSize)/PtrSize & 1;
-                               ptrbitp -= j;
-                               bits >>= gcBits*j;
-                               bits = (bits>>2)&BitsMask;
-                       } else
-                               bits = (ptrmask[((i+PtrSize)/PtrSize)/4]>>((((i+PtrSize)/PtrSize)%4)*BitsPerPointer))&BitsMask;
-
-                       if(Debug && bits != BitsIface && bits != BitsEface)
-                               runtime·throw("unexpected garbage collection bits");
-
-                       if(bits == BitsIface) {
-                               iface = (Iface*)(b+i);
-                               if(iface->tab != nil) {
-                                       typ = iface->tab->type;
-                                       if(!(typ->kind&KindDirectIface) || !(typ->kind&KindNoPointers))
-                                               obj = iface->data;
-                               }
-                       } else {
-                               eface = (Eface*)(b+i);
-                               typ = eface->type;
-                               if(typ != nil) {
-                                       if(!(typ->kind&KindDirectIface) || !(typ->kind&KindNoPointers))
-                                               obj = eface->data;
-                               }
-                       }
-
-                       i += PtrSize;
-
-                       obj0 = obj;
-               markobj:
-                       // At this point we have extracted the next potential pointer.
-                       // Check if it points into heap.
-                       if(obj == nil)
-                               continue;
-                       if(obj < arena_start || obj >= arena_used) {
-                               if((uintptr)obj < PhysPageSize && runtime·invalidptr) {
-                                       s = nil;
-                                       goto badobj;
-                               }
-                               continue;
-                       }
-                       // Mark the object.
-                       obj = (byte*)((uintptr)obj & ~(PtrSize-1));
-                       off = (uintptr*)obj - (uintptr*)arena_start;
-                       bitp = arena_start - off/wordsPerBitmapByte - 1;
-                       shift = (off % wordsPerBitmapByte) * gcBits;
-                       xbits = *bitp;
-                       bits = (xbits >> shift) & bitMask;
-                       if((bits&bitBoundary) == 0) {
-                               // Not a beginning of a block, consult span table to find the block beginning.
-                               k = (uintptr)obj>>PageShift;
-                               x = k;
-                               x -= (uintptr)arena_start>>PageShift;
-                               s = runtime·mheap.spans[x];
-                               if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse) {
-                                       // Stack pointers lie within the arena bounds but are not part of the GC heap.
-                                       // Ignore them.
-                                       if(s != nil && s->state == MSpanStack)
-                                               continue;
-                               
-                               badobj:
-                                       // If cgo_allocate is linked into the binary, it can allocate
-                                       // memory as []unsafe.Pointer that may not contain actual
-                                       // pointers and must be scanned conservatively.
-                                       // In this case alone, allow the bad pointer.
-                                       if(have_cgo_allocate() && ptrmask == nil)
-                                               continue;
-
-                                       // Anything else indicates a bug somewhere.
-                                       // If we're in the middle of chasing down a different bad pointer,
-                                       // don't confuse the trace by printing about this one.
-                                       if(nbadblock > 0)
-                                               continue;
-
-                                       runtime·printf("runtime: garbage collector found invalid heap pointer *(%p+%p)=%p", b, i, obj);
-                                       if(s == nil)
-                                               runtime·printf(" s=nil\n");
-                                       else
-                                               runtime·printf(" span=%p-%p-%p state=%d\n", (uintptr)s->start<<PageShift, s->limit, (uintptr)(s->start+s->npages)<<PageShift, s->state);
-                                       if(ptrmask != nil)
-                                               runtime·throw("invalid heap pointer");
-                                       // Add to badblock list, which will cause the garbage collection
-                                       // to keep repeating until it has traced the chain of pointers
-                                       // leading to obj all the way back to a root.
-                                       if(nbadblock == 0)
-                                               badblock[nbadblock++] = (uintptr)b;
-                                       continue;
-                               }
-                               p = (byte*)((uintptr)s->start<<PageShift);
-                               if(s->sizeclass != 0) {
-                                       size = s->elemsize;
-                                       idx = ((byte*)obj - p)/size;
-                                       p = p+idx*size;
-                               }
-                               if(p == obj) {
-                                       runtime·printf("runtime: failed to find block beginning for %p s=%p s->limit=%p\n",
-                                               p, s->start*PageSize, s->limit);
-                                       runtime·throw("failed to find block beginning");
-                               }
-                               obj = p;
-                               goto markobj;
-                       }
-                       if(DebugPtrs)
-                               runtime·printf("scan *%p = %p => base %p\n", b+i, obj0, obj);
-
-                       if(nbadblock > 0 && (uintptr)obj == badblock[nbadblock-1]) {
-                               // Running garbage collection again because
-                               // we want to find the path from a root to a bad pointer.
-                               // Found possible next step; extend or finish path.
-                               for(j=0; j<nbadblock; j++)
-                                       if(badblock[j] == (uintptr)b)
-                                               goto AlreadyBad;
-                               runtime·printf("runtime: found *(%p+%p) = %p+%p\n", b, i, obj0, (uintptr)(obj-obj0));
-                               if(ptrmask != nil)
-                                       runtime·throw("bad pointer");
-                               if(nbadblock >= nelem(badblock))
-                                       runtime·throw("badblock trace too long");
-                               badblock[nbadblock++] = (uintptr)b;
-                       AlreadyBad:;
-                       }
-
-                       // Now we have bits, bitp, and shift correct for
-                       // obj pointing at the base of the object.
-                       // Only care about not marked objects.
-                       if((bits&bitMarked) != 0)
-                               continue;
-                       // If obj size is greater than 8, then each byte of GC bitmap
-                       // contains info for at most one object. In such case we use
-                       // non-atomic byte store to mark the object. This can lead
-                       // to double enqueue of the object for scanning, but scanning
-                       // is an idempotent operation, so it is OK. This cannot lead
-                       // to bitmap corruption because the single marked bit is the
-                       // only thing that can change in the byte.
-                       // For 8-byte objects we use non-atomic store, if the other
-                       // quadruple is already marked. Otherwise we resort to CAS
-                       // loop for marking.
-                       if((xbits&(bitMask|(bitMask<<gcBits))) != (bitBoundary|(bitBoundary<<gcBits)) ||
-                               runtime·work.nproc == 1)
-                               *bitp = xbits | (bitMarked<<shift);
-                       else
-                               runtime·atomicor8(bitp, bitMarked<<shift);
-
-                       if(((xbits>>(shift+2))&BitsMask) == BitsDead)
-                               continue;  // noscan object
-
-                       // Queue the obj for scanning.
-                       PREFETCH(obj);
-                       p = scanbuf[scanbufpos];
-                       scanbuf[scanbufpos++] = obj;
-                       scanbufpos %= nelem(scanbuf);
-                       if(p == nil)
-                               continue;
-
-                       // If workbuf is full, obtain an empty one.
-                       if(nobj >= nelem(wbuf->obj)) {
-                               wbuf->nobj = nobj;
-                               wbuf = getempty(wbuf);
-                               nobj = wbuf->nobj;
-                               wp = &wbuf->obj[nobj];
-                       }
-                       *wp = p;
-                       wp++;
-                       nobj++;
-               }
-               if(DebugPtrs)
-                       runtime·printf("end scanblock %p +%p %p\n", b, n, ptrmask);
-
-               if(Debug && ptrmask == nil) {
-                       // For heap objects ensure that we did not overscan.
-                       n = 0;
-                       p = nil;
-                       if(!runtime·mlookup(b, &p, &n, nil) || b != p || i > n) {
-                               runtime·printf("runtime: scanned (%p,%p), heap object (%p,%p)\n", b, i, p, n);
-                               runtime·throw("scanblock: scanned invalid object");
-                       }
-               }
-       }
-}
-
-static void
-markroot(ParFor *desc, uint32 i)
-{
-       FinBlock *fb;
-       MSpan *s;
-       uint32 spanidx, sg;
-       G *gp;
-       void *p;
-       uint32 status;
-       bool restart;
-
-       USED(&desc);
-       // Note: if you add a case here, please also update heapdump.c:dumproots.
-       switch(i) {
-       case RootData:
-               scanblock(runtime·data, runtime·edata - runtime·data, runtime·gcdatamask.bytedata);
-               break;
-
-       case RootBss:
-               scanblock(runtime·bss, runtime·ebss - runtime·bss, runtime·gcbssmask.bytedata);
-               break;
-
-       case RootFinalizers:
-               for(fb=runtime·allfin; fb; fb=fb->alllink)
-                       scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]), finptrmask);
-               break;
-
-       case RootSpans:
-               // mark MSpan.specials
-               sg = runtime·mheap.sweepgen;
-               for(spanidx=0; spanidx<runtime·work.nspan; spanidx++) {
-                       Special *sp;
-                       SpecialFinalizer *spf;
-
-                       s = runtime·work.spans[spanidx];
-                       if(s->state != MSpanInUse)
-                               continue;
-                       if(s->sweepgen != sg) {
-                               runtime·printf("sweep %d %d\n", s->sweepgen, sg);
-                               runtime·throw("gc: unswept span");
-                       }
-                       for(sp = s->specials; sp != nil; sp = sp->next) {
-                               if(sp->kind != KindSpecialFinalizer)
-                                       continue;
-                               // don't mark finalized object, but scan it so we
-                               // retain everything it points to.
-                               spf = (SpecialFinalizer*)sp;
-                               // A finalizer can be set for an inner byte of an object, find object beginning.
-                               p = (void*)((s->start << PageShift) + spf->special.offset/s->elemsize*s->elemsize);
-                               scanblock(p, s->elemsize, nil);
-                               scanblock((void*)&spf->fn, PtrSize, oneptr);
-                       }
-               }
-               break;
-
-       case RootFlushCaches:
-               flushallmcaches();
-               break;
-
-       default:
-               // the rest is scanning goroutine stacks
-               if(i - RootCount >= runtime·allglen)
-                       runtime·throw("markroot: bad index");
-               gp = runtime·allg[i - RootCount];
-               // remember when we've first observed the G blocked
-               // needed only to output in traceback
-               status = runtime·readgstatus(gp);
-               if((status == Gwaiting || status == Gsyscall) && gp->waitsince == 0)
-                       gp->waitsince = runtime·work.tstart;
-               // Shrink a stack if not much of it is being used.
-               runtime·shrinkstack(gp);
-               if(runtime·readgstatus(gp) == Gdead) 
-                       gp->gcworkdone = true;
-               else 
-                       gp->gcworkdone = false; 
-               restart = runtime·stopg(gp);
-               scanstack(gp);
-               if(restart)
-                       runtime·restartg(gp);
-               break;
-       }
-}
-
-// Get an empty work buffer off the work.empty list,
-// allocating new buffers as needed.
-static Workbuf*
-getempty(Workbuf *b)
-{
-       MCache *c;
-
-       if(b != nil)
-               runtime·lfstackpush(&runtime·work.full, &b->node);
-       b = nil;
-       c = g->m->mcache;
-       if(c->gcworkbuf != nil) {
-               b = c->gcworkbuf;
-               c->gcworkbuf = nil;
-       }
-       if(b == nil)
-               b = (Workbuf*)runtime·lfstackpop(&runtime·work.empty);
-       if(b == nil)
-               b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys);
-       b->nobj = 0;
-       return b;
-}
-
-static void
-putempty(Workbuf *b)
-{
-       MCache *c;
-
-       c = g->m->mcache;
-       if(c->gcworkbuf == nil) {
-               c->gcworkbuf = b;
-               return;
-       }
-       runtime·lfstackpush(&runtime·work.empty, &b->node);
-}
-
-void
-runtime·gcworkbuffree(void *b)
-{
-       if(b != nil)
-               putempty(b);
-}
-
-// Get a full work buffer off the work.full list, or return nil.
-static Workbuf*
-getfull(Workbuf *b)
-{
-       int32 i;
-
-       if(b != nil)
-               runtime·lfstackpush(&runtime·work.empty, &b->node);
-       b = (Workbuf*)runtime·lfstackpop(&runtime·work.full);
-       if(b != nil || runtime·work.nproc == 1)
-               return b;
-
-       runtime·xadd(&runtime·work.nwait, +1);
-       for(i=0;; i++) {
-               if(runtime·work.full != 0) {
-                       runtime·xadd(&runtime·work.nwait, -1);
-                       b = (Workbuf*)runtime·lfstackpop(&runtime·work.full);
-                       if(b != nil)
-                               return b;
-                       runtime·xadd(&runtime·work.nwait, +1);
-               }
-               if(runtime·work.nwait == runtime·work.nproc)
-                       return nil;
-               if(i < 10) {
-                       g->m->gcstats.nprocyield++;
-                       runtime·procyield(20);
-               } else if(i < 20) {
-                       g->m->gcstats.nosyield++;
-                       runtime·osyield();
-               } else {
-                       g->m->gcstats.nsleep++;
-                       runtime·usleep(100);
-               }
-       }
-}
-
-static Workbuf*
-handoff(Workbuf *b)
-{
-       int32 n;
-       Workbuf *b1;
-
-       // Make new buffer with half of b's pointers.
-       b1 = getempty(nil);
-       n = b->nobj/2;
-       b->nobj -= n;
-       b1->nobj = n;
-       runtime·memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
-       g->m->gcstats.nhandoff++;
-       g->m->gcstats.nhandoffcnt += n;
-
-       // Put b on full list - let first half of b get stolen.
-       runtime·lfstackpush(&runtime·work.full, &b->node);
-       return b1;
-}
-
-BitVector
-runtime·stackmapdata(StackMap *stackmap, int32 n)
-{
-       if(n < 0 || n >= stackmap->n)
-               runtime·throw("stackmapdata: index out of range");
-       return (BitVector){stackmap->nbit, stackmap->bytedata + n*((stackmap->nbit+31)/32*4)};
-}
-
-// Scan a stack frame: local variables and function arguments/results.
-static bool
-scanframe(Stkframe *frame, void *unused)
-{
-       Func *f;
-       StackMap *stackmap;
-       BitVector bv;
-       uintptr size, minsize;
-       uintptr targetpc;
-       int32 pcdata;
-
-       USED(unused);
-       f = frame->fn;
-       targetpc = frame->continpc;
-       if(targetpc == 0) {
-               // Frame is dead.
-               return true;
-       }
-       if(Debug > 1)
-               runtime·printf("scanframe %s\n", runtime·funcname(f));
-       if(targetpc != f->entry)
-               targetpc--;
-       pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
-       if(pcdata == -1) {
-               // We do not have a valid pcdata value but there might be a
-               // stackmap for this function.  It is likely that we are looking
-               // at the function prologue, assume so and hope for the best.
-               pcdata = 0;
-       }
-
-       // Scan local variables if stack frame has been allocated.
-       size = frame->varp - frame->sp;
-       if(thechar != '6' && thechar != '8')
-               minsize = sizeof(uintptr);
-       else
-               minsize = 0;
-       if(size > minsize) {
-               stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
-               if(stackmap == nil || stackmap->n <= 0) {
-                       runtime·printf("runtime: frame %s untyped locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
-                       runtime·throw("missing stackmap");
-               }
-
-               // Locals bitmap information, scan just the pointers in locals.
-               if(pcdata < 0 || pcdata >= stackmap->n) {
-                       // don't know where we are
-                       runtime·printf("runtime: pcdata is %d and %d locals stack map entries for %s (targetpc=%p)\n",
-                               pcdata, stackmap->n, runtime·funcname(f), targetpc);
-                       runtime·throw("scanframe: bad symbol table");
-               }
-               bv = runtime·stackmapdata(stackmap, pcdata);
-               size = (bv.n * PtrSize) / BitsPerPointer;
-               scanblock((byte*)(frame->varp - size), bv.n/BitsPerPointer*PtrSize, bv.bytedata);
-       }
-
-       // Scan arguments.
-       if(frame->arglen > 0) {
-               if(frame->argmap != nil)
-                       bv = *frame->argmap;
-               else {
-                       stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
-                       if(stackmap == nil || stackmap->n <= 0) {
-                               runtime·printf("runtime: frame %s untyped args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
-                               runtime·throw("missing stackmap");
-                       }
-                       if(pcdata < 0 || pcdata >= stackmap->n) {
-                               // don't know where we are
-                               runtime·printf("runtime: pcdata is %d and %d args stack map entries for %s (targetpc=%p)\n",
-                                       pcdata, stackmap->n, runtime·funcname(f), targetpc);
-                               runtime·throw("scanframe: bad symbol table");
-                       }
-                       bv = runtime·stackmapdata(stackmap, pcdata);
-               }
-               scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
-       }
-       return true;
-}
-
-static void
-scanstack(G *gp)
-{
-       M *mp;
-       bool (*fn)(Stkframe*, void*);
-
-       if(runtime·readgstatus(gp)&Gscan == 0) {
-               runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
-               runtime·throw("mark - bad status");
-       }
-
-       switch(runtime·readgstatus(gp)&~Gscan) {
-       default:
-               runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
-               runtime·throw("mark - bad status");
-       case Gdead:
-               return;
-       case Grunning:
-               runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp));
-               runtime·throw("mark - world not stopped");
-       case Grunnable:
-       case Gsyscall:
-       case Gwaiting:
-               break;
-       }
-
-       if(gp == g)
-               runtime·throw("can't scan our own stack");
-       if((mp = gp->m) != nil && mp->helpgc)
-               runtime·throw("can't scan gchelper stack");
-
-       fn = scanframe;
-       runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, &fn, nil, 0);
-       runtime·tracebackdefers(gp, &fn, nil);
-}
-
-// The gp has been moved to a gc safepoint. If there is gcphase specific
-// work it is done here. 
-void
-runtime·gcphasework(G *gp)
-{
-       switch(runtime·gcphase) {
-       default:
-               runtime·throw("gcphasework in bad gcphase");
-       case GCoff:
-       case GCquiesce:
-       case GCstw:
-       case GCsweep:
-               // No work for now.
-               break;
-       case GCmark:
-               // Disabled until concurrent GC is implemented
-               // but indicate the scan has been done. 
-               // scanstack(gp);
-               break;
-       }
-       gp->gcworkdone = true;
-}
-
-#pragma dataflag NOPTR
-static byte finalizer1[] = {
-       // Each Finalizer is 5 words, ptr ptr uintptr ptr ptr.
-       // Each byte describes 4 words.
-       // Need 4 Finalizers described by 5 bytes before pattern repeats:
-       //      ptr ptr uintptr ptr ptr
-       //      ptr ptr uintptr ptr ptr
-       //      ptr ptr uintptr ptr ptr
-       //      ptr ptr uintptr ptr ptr
-       // aka
-       //      ptr ptr uintptr ptr
-       //      ptr ptr ptr uintptr
-       //      ptr ptr ptr ptr
-       //      uintptr ptr ptr ptr
-       //      ptr uintptr ptr ptr
-       // Assumptions about Finalizer layout checked below.
-       BitsPointer | BitsPointer<<2 | BitsScalar<<4 | BitsPointer<<6,
-       BitsPointer | BitsPointer<<2 | BitsPointer<<4 | BitsScalar<<6,
-       BitsPointer | BitsPointer<<2 | BitsPointer<<4 | BitsPointer<<6,
-       BitsScalar | BitsPointer<<2 | BitsPointer<<4 | BitsPointer<<6,
-       BitsPointer | BitsScalar<<2 | BitsPointer<<4 | BitsPointer<<6,
-};
-
-void
-runtime·queuefinalizer(byte *p, FuncVal *fn, uintptr nret, Type *fint, PtrType *ot)
-{
-       FinBlock *block;
-       Finalizer *f;
-       int32 i;
-
-       runtime·lock(&runtime·finlock);
-       if(runtime·finq == nil || runtime·finq->cnt == runtime·finq->cap) {
-               if(runtime·finc == nil) {
-                       runtime·finc = runtime·persistentalloc(FinBlockSize, 0, &mstats.gc_sys);
-                       runtime·finc->cap = (FinBlockSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
-                       runtime·finc->alllink = runtime·allfin;
-                       runtime·allfin = runtime·finc;
-                       if(finptrmask[0] == 0) {
-                               // Build pointer mask for Finalizer array in block.
-                               // Check assumptions made in finalizer1 array above.
-                               if(sizeof(Finalizer) != 5*PtrSize ||
-                                       offsetof(Finalizer, fn) != 0 ||
-                                       offsetof(Finalizer, arg) != PtrSize ||
-                                       offsetof(Finalizer, nret) != 2*PtrSize ||
-                                       offsetof(Finalizer, fint) != 3*PtrSize ||
-                                       offsetof(Finalizer, ot) != 4*PtrSize ||
-                                       BitsPerPointer != 2) {
-                                       runtime·throw("finalizer out of sync");
-                               }
-                               for(i=0; i<nelem(finptrmask); i++)
-                                       finptrmask[i] = finalizer1[i%nelem(finalizer1)];
-                       }
-               }
-               block = runtime·finc;
-               runtime·finc = block->next;
-               block->next = runtime·finq;
-               runtime·finq = block;
-       }
-       f = &runtime·finq->fin[runtime·finq->cnt];
-       runtime·finq->cnt++;
-       f->fn = fn;
-       f->nret = nret;
-       f->fint = fint;
-       f->ot = ot;
-       f->arg = p;
-       runtime·fingwake = true;
-       runtime·unlock(&runtime·finlock);
-}
-
-void
-runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*))
-{
-       FinBlock *fb;
-       Finalizer *f;
-       uintptr i;
-
-       for(fb = runtime·allfin; fb; fb = fb->alllink) {
-               for(i = 0; i < fb->cnt; i++) {
-                       f = &fb->fin[i];
-                       callback(f->fn, f->arg, f->nret, f->fint, f->ot);
-               }
-       }
-}
-
-void
-runtime·MSpan_EnsureSwept(MSpan *s)
-{
-       uint32 sg;
-
-       // Caller must disable preemption.
-       // Otherwise when this function returns the span can become unswept again
-       // (if GC is triggered on another goroutine).
-       if(g->m->locks == 0 && g->m->mallocing == 0 && g != g->m->g0)
-               runtime·throw("MSpan_EnsureSwept: m is not locked");
-
-       sg = runtime·mheap.sweepgen;
-       if(runtime·atomicload(&s->sweepgen) == sg)
-               return;
-       if(runtime·cas(&s->sweepgen, sg-2, sg-1)) {
-               runtime·MSpan_Sweep(s, false);
-               return;
-       }
-       // unfortunate condition, and we don't have efficient means to wait
-       while(runtime·atomicload(&s->sweepgen) != sg)
-               runtime·osyield();
-}
-
-// Sweep frees or collects finalizers for blocks not marked in the mark phase.
-// It clears the mark bits in preparation for the next GC round.
-// Returns true if the span was returned to heap.
-// If preserve=true, don't return it to heap nor relink in MCentral lists;
-// caller takes care of it.
-bool
-runtime·MSpan_Sweep(MSpan *s, bool preserve)
-{
-       int32 cl, n, npages, nfree;
-       uintptr size, off, step;
-       uint32 sweepgen;
-       byte *p, *bitp, shift, xbits, bits;
-       MCache *c;
-       byte *arena_start;
-       MLink head, *end, *link;
-       Special *special, **specialp, *y;
-       bool res, sweepgenset;
-
-       // It's critical that we enter this function with preemption disabled,
-       // GC must not start while we are in the middle of this function.
-       if(g->m->locks == 0 && g->m->mallocing == 0 && g != g->m->g0)
-               runtime·throw("MSpan_Sweep: m is not locked");
-       sweepgen = runtime·mheap.sweepgen;
-       if(s->state != MSpanInUse || s->sweepgen != sweepgen-1) {
-               runtime·printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
-                       s->state, s->sweepgen, sweepgen);
-               runtime·throw("MSpan_Sweep: bad span state");
-       }
-       arena_start = runtime·mheap.arena_start;
-       cl = s->sizeclass;
-       size = s->elemsize;
-       if(cl == 0) {
-               n = 1;
-       } else {
-               // Chunk full of small blocks.
-               npages = runtime·class_to_allocnpages[cl];
-               n = (npages << PageShift) / size;
-       }
-       res = false;
-       nfree = 0;
-       end = &head;
-       c = g->m->mcache;
-       sweepgenset = false;
-
-       // Mark any free objects in this span so we don't collect them.
-       for(link = s->freelist; link != nil; link = link->next) {
-               off = (uintptr*)link - (uintptr*)arena_start;
-               bitp = arena_start - off/wordsPerBitmapByte - 1;
-               shift = (off % wordsPerBitmapByte) * gcBits;
-               *bitp |= bitMarked<<shift;
-       }
-
-       // Unlink & free special records for any objects we're about to free.
-       specialp = &s->specials;
-       special = *specialp;
-       while(special != nil) {
-               // A finalizer can be set for an inner byte of an object, find object beginning.
-               p = (byte*)(s->start << PageShift) + special->offset/size*size;
-               off = (uintptr*)p - (uintptr*)arena_start;
-               bitp = arena_start - off/wordsPerBitmapByte - 1;
-               shift = (off % wordsPerBitmapByte) * gcBits;
-               bits = (*bitp>>shift) & bitMask;
-               if((bits&bitMarked) == 0) {
-                       // Find the exact byte for which the special was setup
-                       // (as opposed to object beginning).
-                       p = (byte*)(s->start << PageShift) + special->offset;
-                       // about to free object: splice out special record
-                       y = special;
-                       special = special->next;
-                       *specialp = special;
-                       if(!runtime·freespecial(y, p, size, false)) {
-                               // stop freeing of object if it has a finalizer
-                               *bitp |= bitMarked << shift;
-                       }
-               } else {
-                       // object is still live: keep special record
-                       specialp = &special->next;
-                       special = *specialp;
-               }
-       }
-
-       // Sweep through n objects of given size starting at p.
-       // This thread owns the span now, so it can manipulate
-       // the block bitmap without atomic operations.
-       p = (byte*)(s->start << PageShift);
-       // Find bits for the beginning of the span.
-       off = (uintptr*)p - (uintptr*)arena_start;
-       bitp = arena_start - off/wordsPerBitmapByte - 1;
-       shift = 0;
-       step = size/(PtrSize*wordsPerBitmapByte);
-       // Rewind to the previous quadruple as we move to the next
-       // in the beginning of the loop.
-       bitp += step;
-       if(step == 0) {
-               // 8-byte objects.
-               bitp++;
-               shift = gcBits;
-       }
-       for(; n > 0; n--, p += size) {
-               bitp -= step;
-               if(step == 0) {
-                       if(shift != 0)
-                               bitp--;
-                       shift = gcBits - shift;
-               }
-
-               xbits = *bitp;
-               bits = (xbits>>shift) & bitMask;
-
-               // Allocated and marked object, reset bits to allocated.
-               if((bits&bitMarked) != 0) {
-                       *bitp &= ~(bitMarked<<shift);
-                       continue;
-               }
-               // At this point we know that we are looking at garbage object
-               // that needs to be collected.
-               if(runtime·debug.allocfreetrace)
-                       runtime·tracefree(p, size);
-               // Reset to allocated+noscan.
-               *bitp = (xbits & ~((bitMarked|(BitsMask<<2))<<shift)) | ((uintptr)BitsDead<<(shift+2));
-               if(cl == 0) {
-                       // Free large span.
-                       if(preserve)
-                               runtime·throw("can't preserve large span");
-                       runtime·unmarkspan(p, s->npages<<PageShift);
-                       s->needzero = 1;
-                       // important to set sweepgen before returning it to heap
-                       runtime·atomicstore(&s->sweepgen, sweepgen);
-                       sweepgenset = true;
-                       // NOTE(rsc,dvyukov): The original implementation of efence
-                       // in CL 22060046 used SysFree instead of SysFault, so that
-                       // the operating system would eventually give the memory
-                       // back to us again, so that an efence program could run
-                       // longer without running out of memory. Unfortunately,
-                       // calling SysFree here without any kind of adjustment of the
-                       // heap data structures means that when the memory does
-                       // come back to us, we have the wrong metadata for it, either in
-                       // the MSpan structures or in the garbage collection bitmap.
-                       // Using SysFault here means that the program will run out of
-                       // memory fairly quickly in efence mode, but at least it won't
-                       // have mysterious crashes due to confused memory reuse.
-                       // It should be possible to switch back to SysFree if we also
-                       // implement and then call some kind of MHeap_DeleteSpan.
-                       if(runtime·debug.efence) {
-                               s->limit = nil; // prevent mlookup from finding this span
-                               runtime·SysFault(p, size);
-                       } else
-                               runtime·MHeap_Free(&runtime·mheap, s, 1);
-                       c->local_nlargefree++;
-                       c->local_largefree += size;
-                       runtime·xadd64(&mstats.next_gc, -(uint64)(size * (runtime·gcpercent + 100)/100));
-                       res = true;
-               } else {
-                       // Free small object.
-                       if(size > 2*sizeof(uintptr))
-                               ((uintptr*)p)[1] = (uintptr)0xdeaddeaddeaddeadll;       // mark as "needs to be zeroed"
-                       else if(size > sizeof(uintptr))
-                               ((uintptr*)p)[1] = 0;
-
-                       end->next = (MLink*)p;
-                       end = (MLink*)p;
-                       nfree++;
-               }
-       }
-
-       // We need to set s->sweepgen = h->sweepgen only when all blocks are swept,
-       // because of the potential for a concurrent free/SetFinalizer.
-       // But we need to set it before we make the span available for allocation
-       // (return it to heap or mcentral), because allocation code assumes that a
-       // span is already swept if available for allocation.
-
-       if(!sweepgenset && nfree == 0) {
-               // The span must be in our exclusive ownership until we update sweepgen,
-               // check for potential races.
-               if(s->state != MSpanInUse || s->sweepgen != sweepgen-1) {
-                       runtime·printf("MSpan_Sweep: state=%d sweepgen=%d mheap.sweepgen=%d\n",
-                               s->state, s->sweepgen, sweepgen);
-                       runtime·throw("MSpan_Sweep: bad span state after sweep");
-               }
-               runtime·atomicstore(&s->sweepgen, sweepgen);
-       }
-       if(nfree > 0) {
-               c->local_nsmallfree[cl] += nfree;
-               c->local_cachealloc -= nfree * size;
-               runtime·xadd64(&mstats.next_gc, -(uint64)(nfree * size * (runtime·gcpercent + 100)/100));
-               res = runtime·MCentral_FreeSpan(&runtime·mheap.central[cl].mcentral, s, nfree, head.next, end, preserve);
-               // MCentral_FreeSpan updates sweepgen
-       }
-       return res;
-}
-
-// State of background runtime·sweep.
-// Protected by runtime·gclock.
-typedef struct SweepData SweepData;
-struct SweepData
-{
-       G*      g;
-       bool    parked;
-
-       uint32  spanidx;        // background sweeper position
-
-       uint32  nbgsweep;
-       uint32  npausesweep;
-};
-SweepData runtime·sweep;
-
-// sweeps one span
-// returns number of pages returned to heap, or -1 if there is nothing to sweep
-uintptr
-runtime·sweepone(void)
-{
-       MSpan *s;
-       uint32 idx, sg;
-       uintptr npages;
-
-       // increment locks to ensure that the goroutine is not preempted
-       // in the middle of sweep thus leaving the span in an inconsistent state for next GC
-       g->m->locks++;
-       sg = runtime·mheap.sweepgen;
-       for(;;) {
-               idx = runtime·xadd(&runtime·sweep.spanidx, 1) - 1;
-               if(idx >= runtime·work.nspan) {
-                       runtime·mheap.sweepdone = true;
-                       g->m->locks--;
-                       return -1;
-               }
-               s = runtime·work.spans[idx];
-               if(s->state != MSpanInUse) {
-                       s->sweepgen = sg;
-                       continue;
-               }
-               if(s->sweepgen != sg-2 || !runtime·cas(&s->sweepgen, sg-2, sg-1))
-                       continue;
-               npages = s->npages;
-               if(!runtime·MSpan_Sweep(s, false))
-                       npages = 0;
-               g->m->locks--;
-               return npages;
-       }
-}
-
-static void
-sweepone_m(void)
-{
-       g->m->scalararg[0] = runtime·sweepone();
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·gosweepone(void)
-{
-       void (*fn)(void);
-       
-       fn = sweepone_m;
-       runtime·onM(&fn);
-       return g->m->scalararg[0];
-}
-
-#pragma textflag NOSPLIT
-bool
-runtime·gosweepdone(void)
-{
-       return runtime·mheap.sweepdone;
-}
-
-void
-runtime·gchelper(void)
-{
-       uint32 nproc;
-
-       g->m->traceback = 2;
-       gchelperstart();
-
-       // parallel mark for over gc roots
-       runtime·parfordo(runtime·work.markfor);
-
-       // help other threads scan secondary blocks
-       scanblock(nil, 0, nil);
-
-       nproc = runtime·work.nproc;  // runtime·work.nproc can change right after we increment runtime·work.ndone
-       if(runtime·xadd(&runtime·work.ndone, +1) == nproc-1)
-               runtime·notewakeup(&runtime·work.alldone);
-       g->m->traceback = 0;
-}
-
-static void
-cachestats(void)
-{
-       MCache *c;
-       P *p, **pp;
-
-       for(pp=runtime·allp; p=*pp; pp++) {
-               c = p->mcache;
-               if(c==nil)
-                       continue;
-               runtime·purgecachedstats(c);
-       }
-}
-
-static void
-flushallmcaches(void)
-{
-       P *p, **pp;
-       MCache *c;
-
-       // Flush MCache's to MCentral.
-       for(pp=runtime·allp; p=*pp; pp++) {
-               c = p->mcache;
-               if(c==nil)
-                       continue;
-               runtime·MCache_ReleaseAll(c);
-               runtime·stackcache_clear(c);
-       }
-}
-
-static void
-flushallmcaches_m(G *gp)
-{
-       flushallmcaches();
-       runtime·gogo(&gp->sched);
-}
-
-void
-runtime·updatememstats(GCStats *stats)
-{
-       M *mp;
-       MSpan *s;
-       int32 i;
-       uint64 smallfree;
-       uint64 *src, *dst;
-       void (*fn)(G*);
-
-       if(stats)
-               runtime·memclr((byte*)stats, sizeof(*stats));
-       for(mp=runtime·allm; mp; mp=mp->alllink) {
-               if(stats) {
-                       src = (uint64*)&mp->gcstats;
-                       dst = (uint64*)stats;
-                       for(i=0; i<sizeof(*stats)/sizeof(uint64); i++)
-                               dst[i] += src[i];
-                       runtime·memclr((byte*)&mp->gcstats, sizeof(mp->gcstats));
-               }
-       }
-       mstats.mcache_inuse = runtime·mheap.cachealloc.inuse;
-       mstats.mspan_inuse = runtime·mheap.spanalloc.inuse;
-       mstats.sys = mstats.heap_sys + mstats.stacks_sys + mstats.mspan_sys +
-               mstats.mcache_sys + mstats.buckhash_sys + mstats.gc_sys + mstats.other_sys;
-       
-       // Calculate memory allocator stats.
-       // During program execution we only count number of frees and amount of freed memory.
-       // Current number of alive object in the heap and amount of alive heap memory
-       // are calculated by scanning all spans.
-       // Total number of mallocs is calculated as number of frees plus number of alive objects.
-       // Similarly, total amount of allocated memory is calculated as amount of freed memory
-       // plus amount of alive heap memory.
-       mstats.alloc = 0;
-       mstats.total_alloc = 0;
-       mstats.nmalloc = 0;
-       mstats.nfree = 0;
-       for(i = 0; i < nelem(mstats.by_size); i++) {
-               mstats.by_size[i].nmalloc = 0;
-               mstats.by_size[i].nfree = 0;
-       }
-
-       // Flush MCache's to MCentral.
-       if(g == g->m->g0)
-               flushallmcaches();
-       else {
-               fn = flushallmcaches_m;
-               runtime·mcall(&fn);
-       }
-
-       // Aggregate local stats.
-       cachestats();
-
-       // Scan all spans and count number of alive objects.
-       runtime·lock(&runtime·mheap.lock);
-       for(i = 0; i < runtime·mheap.nspan; i++) {
-               s = runtime·mheap.allspans[i];
-               if(s->state != MSpanInUse)
-                       continue;
-               if(s->sizeclass == 0) {
-                       mstats.nmalloc++;
-                       mstats.alloc += s->elemsize;
-               } else {
-                       mstats.nmalloc += s->ref;
-                       mstats.by_size[s->sizeclass].nmalloc += s->ref;
-                       mstats.alloc += s->ref*s->elemsize;
-               }
-       }
-       runtime·unlock(&runtime·mheap.lock);
-
-       // Aggregate by size class.
-       smallfree = 0;
-       mstats.nfree = runtime·mheap.nlargefree;
-       for(i = 0; i < nelem(mstats.by_size); i++) {
-               mstats.nfree += runtime·mheap.nsmallfree[i];
-               mstats.by_size[i].nfree = runtime·mheap.nsmallfree[i];
-               mstats.by_size[i].nmalloc += runtime·mheap.nsmallfree[i];
-               smallfree += runtime·mheap.nsmallfree[i] * runtime·class_to_size[i];
-       }
-       mstats.nfree += mstats.tinyallocs;
-       mstats.nmalloc += mstats.nfree;
-
-       // Calculate derived stats.
-       mstats.total_alloc = mstats.alloc + runtime·mheap.largefree + smallfree;
-       mstats.heap_alloc = mstats.alloc;
-       mstats.heap_objects = mstats.nmalloc - mstats.nfree;
-}
-
-// Structure of arguments passed to function gc().
-// This allows the arguments to be passed via runtime·mcall.
-struct gc_args
-{
-       int64 start_time; // start time of GC in ns (just before stoptheworld)
-       bool  eagersweep;
-};
-
-static void gc(struct gc_args *args);
-
-int32
-runtime·readgogc(void)
-{
-       byte *p;
-
-       p = runtime·getenv("GOGC");
-       if(p == nil || p[0] == '\0')
-               return 100;
-       if(runtime·strcmp(p, (byte*)"off") == 0)
-               return -1;
-       return runtime·atoi(p);
-}
-
-void
-runtime·gcinit(void)
-{
-       if(sizeof(Workbuf) != WorkbufSize)
-               runtime·throw("runtime: size of Workbuf is suboptimal");
-
-       runtime·work.markfor = runtime·parforalloc(MaxGcproc);
-       runtime·gcpercent = runtime·readgogc();
-       runtime·gcdatamask = unrollglobgcprog(runtime·gcdata, runtime·edata - runtime·data);
-       runtime·gcbssmask = unrollglobgcprog(runtime·gcbss, runtime·ebss - runtime·bss);
-}
-
-void
-runtime·gc_m(void)
-{
-       struct gc_args a;
-       G *gp;
-
-       gp = g->m->curg;
-       runtime·casgstatus(gp, Grunning, Gwaiting);
-       gp->waitreason = runtime·gostringnocopy((byte*)"garbage collection");
-
-       a.start_time = (uint64)(g->m->scalararg[0]) | ((uint64)(g->m->scalararg[1]) << 32);
-       a.eagersweep = g->m->scalararg[2];
-       gc(&a);
-
-       if(nbadblock > 0) {
-               // Work out path from root to bad block.
-               for(;;) {
-                       gc(&a);
-                       if(nbadblock >= nelem(badblock))
-                               runtime·throw("cannot find path to bad pointer");
-               }
-       }
-
-       runtime·casgstatus(gp, Gwaiting, Grunning);
-}
-
-static void
-gc(struct gc_args *args)
-{
-       int64 t0, t1, t2, t3, t4;
-       uint64 heap0, heap1, obj;
-       GCStats stats;
-
-       if(DebugPtrs)
-               runtime·printf("GC start\n");
-
-       if(runtime·debug.allocfreetrace)
-               runtime·tracegc();
-
-       g->m->traceback = 2;
-       t0 = args->start_time;
-       runtime·work.tstart = args->start_time; 
-
-       t1 = 0;
-       if(runtime·debug.gctrace)
-               t1 = runtime·nanotime();
-
-       // Sweep what is not sweeped by bgsweep.
-       while(runtime·sweepone() != -1)
-               runtime·sweep.npausesweep++;
-
-       // Cache runtime.mheap.allspans in work.spans to avoid conflicts with
-       // resizing/freeing allspans.
-       // New spans can be created while GC progresses, but they are not garbage for
-       // this round:
-       //  - new stack spans can be created even while the world is stopped.
-       //  - new malloc spans can be created during the concurrent sweep
-
-       // Even if this is stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
-       runtime·lock(&runtime·mheap.lock);
-       // Free the old cached sweep array if necessary.
-       if(runtime·work.spans != nil && runtime·work.spans != runtime·mheap.allspans)
-               runtime·SysFree(runtime·work.spans, runtime·work.nspan*sizeof(runtime·work.spans[0]), &mstats.other_sys);
-       // Cache the current array for marking.
-       runtime·mheap.gcspans = runtime·mheap.allspans;
-       runtime·work.spans = runtime·mheap.allspans;
-       runtime·work.nspan = runtime·mheap.nspan;
-       runtime·unlock(&runtime·mheap.lock);
-
-       runtime·work.nwait = 0;
-       runtime·work.ndone = 0;
-       runtime·work.nproc = runtime·gcprocs();
-       runtime·parforsetup(runtime·work.markfor, runtime·work.nproc, RootCount + runtime·allglen, nil, false, markroot);
-       if(runtime·work.nproc > 1) {
-               runtime·noteclear(&runtime·work.alldone);
-               runtime·helpgc(runtime·work.nproc);
-       }
-
-       t2 = 0;
-       if(runtime·debug.gctrace)
-               t2 = runtime·nanotime();
-
-       gchelperstart();
-       runtime·parfordo(runtime·work.markfor);
-       scanblock(nil, 0, nil);
-
-       t3 = 0;
-       if(runtime·debug.gctrace)
-               t3 = runtime·nanotime();
-
-       if(runtime·work.nproc > 1)
-               runtime·notesleep(&runtime·work.alldone);
-
-       runtime·shrinkfinish();
-
-       cachestats();
-       // next_gc calculation is tricky with concurrent sweep since we don't know size of live heap
-       // estimate what was live heap size after previous GC (for tracing only)
-       heap0 = mstats.next_gc*100/(runtime·gcpercent+100);
-       // conservatively set next_gc to high value assuming that everything is live
-       // concurrent/lazy sweep will reduce this number while discovering new garbage
-       mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*runtime·gcpercent/100;
-
-       t4 = runtime·nanotime();
-       runtime·atomicstore64(&mstats.last_gc, runtime·unixnanotime());  // must be Unix time to make sense to user
-       mstats.pause_ns[mstats.numgc%nelem(mstats.pause_ns)] = t4 - t0;
-       mstats.pause_end[mstats.numgc%nelem(mstats.pause_end)] = t4;
-       mstats.pause_total_ns += t4 - t0;
-       mstats.numgc++;
-       if(mstats.debuggc)
-               runtime·printf("pause %D\n", t4-t0);
-
-       if(runtime·debug.gctrace) {
-               heap1 = mstats.heap_alloc;
-               runtime·updatememstats(&stats);
-               if(heap1 != mstats.heap_alloc) {
-                       runtime·printf("runtime: mstats skew: heap=%D/%D\n", heap1, mstats.heap_alloc);
-                       runtime·throw("mstats skew");
-               }
-               obj = mstats.nmalloc - mstats.nfree;
-
-               stats.nprocyield += runtime·work.markfor->nprocyield;
-               stats.nosyield += runtime·work.markfor->nosyield;
-               stats.nsleep += runtime·work.markfor->nsleep;
-
-               runtime·printf("gc%d(%d): %D+%D+%D+%D us, %D -> %D MB, %D (%D-%D) objects,"
-                               " %d goroutines,"
-                               " %d/%d/%d sweeps,"
-                               " %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
-                       mstats.numgc, runtime·work.nproc, (t1-t0)/1000, (t2-t1)/1000, (t3-t2)/1000, (t4-t3)/1000,
-                       heap0>>20, heap1>>20, obj,
-                       mstats.nmalloc, mstats.nfree,
-                       runtime·gcount(),
-                       runtime·work.nspan, runtime·sweep.nbgsweep, runtime·sweep.npausesweep,
-                       stats.nhandoff, stats.nhandoffcnt,
-                       runtime·work.markfor->nsteal, runtime·work.markfor->nstealcnt,
-                       stats.nprocyield, stats.nosyield, stats.nsleep);
-               runtime·sweep.nbgsweep = runtime·sweep.npausesweep = 0;
-       }
-
-       // See the comment in the beginning of this function as to why we need the following.
-       // Even if this is still stop-the-world, a concurrent exitsyscall can allocate a stack from heap.
-       runtime·lock(&runtime·mheap.lock);
-       // Free the old cached mark array if necessary.
-       if(runtime·work.spans != nil && runtime·work.spans != runtime·mheap.allspans)
-               runtime·SysFree(runtime·work.spans, runtime·work.nspan*sizeof(runtime·work.spans[0]), &mstats.other_sys);
-       // Cache the current array for sweeping.
-       runtime·mheap.gcspans = runtime·mheap.allspans;
-       runtime·mheap.sweepgen += 2;
-       runtime·mheap.sweepdone = false;
-       runtime·work.spans = runtime·mheap.allspans;
-       runtime·work.nspan = runtime·mheap.nspan;
-       runtime·sweep.spanidx = 0;
-       runtime·unlock(&runtime·mheap.lock);
-
-       if(ConcurrentSweep && !args->eagersweep) {
-               runtime·lock(&runtime·gclock);
-               if(runtime·sweep.g == nil)
-                       runtime·sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, gc);
-               else if(runtime·sweep.parked) {
-                       runtime·sweep.parked = false;
-                       runtime·ready(runtime·sweep.g);
-               }
-               runtime·unlock(&runtime·gclock);
-       } else {
-               // Sweep all spans eagerly.
-               while(runtime·sweepone() != -1)
-                       runtime·sweep.npausesweep++;
-               // Do an additional mProf_GC, because all 'free' events are now real as well.
-               runtime·mProf_GC();
-       }
-
-       runtime·mProf_GC();
-       g->m->traceback = 0;
-
-       if(DebugPtrs)
-               runtime·printf("GC end\n");
-}
-
-extern uintptr runtime·sizeof_C_MStats;
-
-static void readmemstats_m(void);
-
-void
-runtime·readmemstats_m(void)
-{
-       MStats *stats;
-       
-       stats = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-
-       runtime·updatememstats(nil);
-       // Size of the trailing by_size array differs between Go and C,
-       // NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
-       runtime·memmove(stats, &mstats, runtime·sizeof_C_MStats);
-
-       // Stack numbers are part of the heap numbers, separate those out for user consumption
-       stats->stacks_sys = stats->stacks_inuse;
-       stats->heap_inuse -= stats->stacks_inuse;
-       stats->heap_sys -= stats->stacks_inuse;
-}
-
-static void readgcstats_m(void);
-
-#pragma textflag NOSPLIT
-void
-runtime∕debug·readGCStats(Slice *pauses)
-{
-       void (*fn)(void);
-       
-       g->m->ptrarg[0] = pauses;
-       fn = readgcstats_m;
-       runtime·onM(&fn);
-}
-
-static void
-readgcstats_m(void)
-{
-       Slice *pauses;  
-       uint64 *p;
-       uint32 i, j, n;
-       
-       pauses = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-
-       // Calling code in runtime/debug should make the slice large enough.
-       if(pauses->cap < nelem(mstats.pause_ns)+3)
-               runtime·throw("runtime: short slice passed to readGCStats");
-
-       // Pass back: pauses, pause ends, last gc (absolute time), number of gc, total pause ns.
-       p = (uint64*)pauses->array;
-       runtime·lock(&runtime·mheap.lock);
-
-       n = mstats.numgc;
-       if(n > nelem(mstats.pause_ns))
-               n = nelem(mstats.pause_ns);
-
-       // The pause buffer is circular. The most recent pause is at
-       // pause_ns[(numgc-1)%nelem(pause_ns)], and then backward
-       // from there to go back farther in time. We deliver the times
-       // most recent first (in p[0]).
-       for(i=0; i<n; i++) {
-               j = (mstats.numgc-1-i)%nelem(mstats.pause_ns);
-               p[i] = mstats.pause_ns[j];
-               p[n+i] = mstats.pause_end[j];
-       }
-
-       p[n+n] = mstats.last_gc;
-       p[n+n+1] = mstats.numgc;
-       p[n+n+2] = mstats.pause_total_ns;       
-       runtime·unlock(&runtime·mheap.lock);
-       pauses->len = n+n+3;
-}
-
-void
-runtime·setgcpercent_m(void)
-{
-       int32 in;
-       int32 out;
-
-       in = (int32)(intptr)g->m->scalararg[0];
-
-       runtime·lock(&runtime·mheap.lock);
-       out = runtime·gcpercent;
-       if(in < 0)
-               in = -1;
-       runtime·gcpercent = in;
-       runtime·unlock(&runtime·mheap.lock);
-
-       g->m->scalararg[0] = (uintptr)(intptr)out;
-}
-
-static void
-gchelperstart(void)
-{
-       if(g->m->helpgc < 0 || g->m->helpgc >= MaxGcproc)
-               runtime·throw("gchelperstart: bad m->helpgc");
-       if(g != g->m->g0)
-               runtime·throw("gchelper not running on g0 stack");
-}
-
-G*
-runtime·wakefing(void)
-{
-       G *res;
-
-       res = nil;
-       runtime·lock(&runtime·finlock);
-       if(runtime·fingwait && runtime·fingwake) {
-               runtime·fingwait = false;
-               runtime·fingwake = false;
-               res = runtime·fing;
-       }
-       runtime·unlock(&runtime·finlock);
-       return res;
-}
-
-// Recursively unrolls GC program in prog.
-// mask is where to store the result.
-// ppos is a pointer to position in mask, in bits.
-// sparse says to generate 4-bits per word mask for heap (2-bits for data/bss otherwise).
-static byte*
-unrollgcprog1(byte *mask, byte *prog, uintptr *ppos, bool inplace, bool sparse)
-{
-       uintptr pos, siz, i, off;
-       byte *arena_start, *prog1, v, *bitp, shift;
-
-       arena_start = runtime·mheap.arena_start;
-       pos = *ppos;
-       for(;;) {
-               switch(prog[0]) {
-               case insData:
-                       prog++;
-                       siz = prog[0];
-                       prog++;
-                       for(i = 0; i < siz; i++) {
-                               v = prog[i/PointersPerByte];
-                               v >>= (i%PointersPerByte)*BitsPerPointer;
-                               v &= BitsMask;
-                               if(inplace) {
-                                       // Store directly into GC bitmap.
-                                       off = (uintptr*)(mask+pos) - (uintptr*)arena_start;
-                                       bitp = arena_start - off/wordsPerBitmapByte - 1;
-                                       shift = (off % wordsPerBitmapByte) * gcBits;
-                                       if(shift==0)
-                                               *bitp = 0;
-                                       *bitp |= v<<(shift+2);
-                                       pos += PtrSize;
-                               } else if(sparse) {
-                                       // 4-bits per word
-                                       v <<= (pos%8)+2;
-                                       mask[pos/8] |= v;
-                                       pos += gcBits;
-                               } else {
-                                       // 2-bits per word
-                                       v <<= pos%8;
-                                       mask[pos/8] |= v;
-                                       pos += BitsPerPointer;
-                               }
-                       }
-                       prog += ROUND(siz*BitsPerPointer, 8)/8;
-                       break;
-               case insArray:
-                       prog++;
-                       siz = 0;
-                       for(i = 0; i < PtrSize; i++)
-                               siz = (siz<<8) + prog[PtrSize-i-1];
-                       prog += PtrSize;
-                       prog1 = nil;
-                       for(i = 0; i < siz; i++)
-                               prog1 = unrollgcprog1(mask, prog, &pos, inplace, sparse);
-                       if(prog1[0] != insArrayEnd)
-                               runtime·throw("unrollgcprog: array does not end with insArrayEnd");
-                       prog = prog1+1;
-                       break;
-               case insArrayEnd:
-               case insEnd:
-                       *ppos = pos;
-                       return prog;
-               default:
-                       runtime·throw("unrollgcprog: unknown instruction");
-               }
-       }
-}
-
-// Unrolls GC program prog for data/bss, returns dense GC mask.
-static BitVector
-unrollglobgcprog(byte *prog, uintptr size)
-{
-       byte *mask;
-       uintptr pos, masksize;
-
-       masksize = ROUND(ROUND(size, PtrSize)/PtrSize*BitsPerPointer, 8)/8;
-       mask = runtime·persistentalloc(masksize+1, 0, &mstats.gc_sys);
-       mask[masksize] = 0xa1;
-       pos = 0;
-       prog = unrollgcprog1(mask, prog, &pos, false, false);
-       if(pos != size/PtrSize*BitsPerPointer) {
-               runtime·printf("unrollglobgcprog: bad program size, got %D, expect %D\n",
-                       (uint64)pos, (uint64)size/PtrSize*BitsPerPointer);
-               runtime·throw("unrollglobgcprog: bad program size");
-       }
-       if(prog[0] != insEnd)
-               runtime·throw("unrollglobgcprog: program does not end with insEnd");
-       if(mask[masksize] != 0xa1)
-               runtime·throw("unrollglobgcprog: overflow");
-       return (BitVector){masksize*8, mask};
-}
-
-void
-runtime·unrollgcproginplace_m(void)
-{
-       uintptr size, size0, pos, off;
-       byte *arena_start, *prog, *bitp, shift;
-       Type *typ;
-       void *v;
-
-       v = g->m->ptrarg[0];
-       typ = g->m->ptrarg[1];
-       size = g->m->scalararg[0];
-       size0 = g->m->scalararg[1];
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-
-       pos = 0;
-       prog = (byte*)typ->gc[1];
-       while(pos != size0)
-               unrollgcprog1(v, prog, &pos, true, true);
-       // Mark first word as bitAllocated.
-       arena_start = runtime·mheap.arena_start;
-       off = (uintptr*)v - (uintptr*)arena_start;
-       bitp = arena_start - off/wordsPerBitmapByte - 1;
-       shift = (off % wordsPerBitmapByte) * gcBits;
-       *bitp |= bitBoundary<<shift;
-       // Mark word after last as BitsDead.
-       if(size0 < size) {
-               off = (uintptr*)((byte*)v + size0) - (uintptr*)arena_start;
-               bitp = arena_start - off/wordsPerBitmapByte - 1;
-               shift = (off % wordsPerBitmapByte) * gcBits;
-               *bitp &= ~(bitPtrMask<<shift) | ((uintptr)BitsDead<<(shift+2));
-       }
-}
-
-// Unrolls GC program in typ->gc[1] into typ->gc[0]
-void
-runtime·unrollgcprog_m(void)
-{
-       static Mutex lock;
-       Type *typ;
-       byte *mask, *prog;
-       uintptr pos;
-       uint32 x;
-
-       typ = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-
-       runtime·lock(&lock);
-       mask = (byte*)typ->gc[0];
-       if(mask[0] == 0) {
-               pos = 8;  // skip the unroll flag
-               prog = (byte*)typ->gc[1];
-               prog = unrollgcprog1(mask, prog, &pos, false, true);
-               if(prog[0] != insEnd)
-                       runtime·throw("unrollgcprog: program does not end with insEnd");
-               if(((typ->size/PtrSize)%2) != 0) {
-                       // repeat the program twice
-                       prog = (byte*)typ->gc[1];
-                       unrollgcprog1(mask, prog, &pos, false, true);
-               }
-               // atomic way to say mask[0] = 1
-               x = ((uint32*)mask)[0];
-               runtime·atomicstore((uint32*)mask, x|1);
-       }
-       runtime·unlock(&lock);
-}
-
-// mark the span of memory at v as having n blocks of the given size.
-// if leftover is true, there is left over space at the end of the span.
-void
-runtime·markspan(void *v, uintptr size, uintptr n, bool leftover)
-{
-       uintptr i, off, step;
-       byte *b;
-
-       if((byte*)v+size*n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
-               runtime·throw("markspan: bad pointer");
-
-       // Find bits of the beginning of the span.
-       off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;  // word offset
-       b = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
-       if((off%wordsPerBitmapByte) != 0)
-               runtime·throw("markspan: unaligned length");
-
-       // Okay to use non-atomic ops here, because we control
-       // the entire span, and each bitmap byte has bits for only
-       // one span, so no other goroutines are changing these bitmap words.
-
-       if(size == PtrSize) {
-               // Possible only on 64-bits (minimal size class is 8 bytes).
-               // Poor man's memset(0x11).
-               if(0x11 != ((bitBoundary+BitsDead)<<gcBits) + (bitBoundary+BitsDead))
-                       runtime·throw("markspan: bad bits");
-               if((n%(wordsPerBitmapByte*PtrSize)) != 0)
-                       runtime·throw("markspan: unaligned length");
-               b = b - n/wordsPerBitmapByte + 1;       // find first byte
-               if(((uintptr)b%PtrSize) != 0)
-                       runtime·throw("markspan: unaligned pointer");
-               for(i = 0; i != n; i += wordsPerBitmapByte*PtrSize, b += PtrSize)
-                       *(uintptr*)b = (uintptr)0x1111111111111111ULL;  // bitBoundary+BitsDead
-               return;
-       }
-
-       if(leftover)
-               n++;    // mark a boundary just past end of last block too
-       step = size/(PtrSize*wordsPerBitmapByte);
-       for(i = 0; i != n; i++, b -= step)
-               *b = bitBoundary|(BitsDead<<2);
-}
-
-// unmark the span of memory at v of length n bytes.
-void
-runtime·unmarkspan(void *v, uintptr n)
-{
-       uintptr off;
-       byte *b;
-
-       if((byte*)v+n > (byte*)runtime·mheap.arena_used || (byte*)v < runtime·mheap.arena_start)
-               runtime·throw("markspan: bad pointer");
-
-       off = (uintptr*)v - (uintptr*)runtime·mheap.arena_start;  // word offset
-       if((off % (PtrSize*wordsPerBitmapByte)) != 0)
-               runtime·throw("markspan: unaligned pointer");
-       b = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
-       n /= PtrSize;
-       if(n%(PtrSize*wordsPerBitmapByte) != 0)
-               runtime·throw("unmarkspan: unaligned length");
-       // Okay to use non-atomic ops here, because we control
-       // the entire span, and each bitmap word has bits for only
-       // one span, so no other goroutines are changing these
-       // bitmap words.
-       n /= wordsPerBitmapByte;
-       runtime·memclr(b - n + 1, n);
-}
-
-void
-runtime·MHeap_MapBits(MHeap *h)
-{
-       // Caller has added extra mappings to the arena.
-       // Add extra mappings of bitmap words as needed.
-       // We allocate extra bitmap pieces in chunks of bitmapChunk.
-       enum {
-               bitmapChunk = 8192
-       };
-       uintptr n;
-
-       n = (h->arena_used - h->arena_start) / (PtrSize*wordsPerBitmapByte);
-       n = ROUND(n, bitmapChunk);
-       n = ROUND(n, PhysPageSize);
-       if(h->bitmap_mapped >= n)
-               return;
-
-       runtime·SysMap(h->arena_start - n, n - h->bitmap_mapped, h->arena_reserved, &mstats.gc_sys);
-       h->bitmap_mapped = n;
-}
-
-static bool
-getgcmaskcb(Stkframe *frame, void *ctxt)
-{
-       Stkframe *frame0;
-
-       frame0 = ctxt;
-       if(frame->sp <= frame0->sp && frame0->sp < frame->varp) {
-               *frame0 = *frame;
-               return false;
-       }
-       return true;
-}
-
-// Returns GC type info for object p for testing.
-void
-runtime·getgcmask(byte *p, Type *t, byte **mask, uintptr *len)
-{
-       Stkframe frame;
-       uintptr i, n, off;
-       byte *base, bits, shift, *b;
-       bool (*cb)(Stkframe*, void*);
-
-       *mask = nil;
-       *len = 0;
-
-       // data
-       if(p >= runtime·data && p < runtime·edata) {
-               n = ((PtrType*)t)->elem->size;
-               *len = n/PtrSize;
-               *mask = runtime·mallocgc(*len, nil, FlagNoScan);
-               for(i = 0; i < n; i += PtrSize) {
-                       off = (p+i-runtime·data)/PtrSize;
-                       bits = (runtime·gcdatamask.bytedata[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask;
-                       (*mask)[i/PtrSize] = bits;
-               }
-               return;
-       }
-       // bss
-       if(p >= runtime·bss && p < runtime·ebss) {
-               n = ((PtrType*)t)->elem->size;
-               *len = n/PtrSize;
-               *mask = runtime·mallocgc(*len, nil, FlagNoScan);
-               for(i = 0; i < n; i += PtrSize) {
-                       off = (p+i-runtime·bss)/PtrSize;
-                       bits = (runtime·gcbssmask.bytedata[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask;
-                       (*mask)[i/PtrSize] = bits;
-               }
-               return;
-       }
-       // heap
-       if(runtime·mlookup(p, &base, &n, nil)) {
-               *len = n/PtrSize;
-               *mask = runtime·mallocgc(*len, nil, FlagNoScan);
-               for(i = 0; i < n; i += PtrSize) {
-                       off = (uintptr*)(base+i) - (uintptr*)runtime·mheap.arena_start;
-                       b = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
-                       shift = (off % wordsPerBitmapByte) * gcBits;
-                       bits = (*b >> (shift+2))&BitsMask;
-                       (*mask)[i/PtrSize] = bits;
-               }
-               return;
-       }
-       // stack
-       frame.fn = nil;
-       frame.sp = (uintptr)p;
-       cb = getgcmaskcb;
-       runtime·gentraceback(g->m->curg->sched.pc, g->m->curg->sched.sp, 0, g->m->curg, 0, nil, 1000, &cb, &frame, 0);
-       if(frame.fn != nil) {
-               Func *f;
-               StackMap *stackmap;
-               BitVector bv;
-               uintptr size;
-               uintptr targetpc;
-               int32 pcdata;
-
-               f = frame.fn;
-               targetpc = frame.continpc;
-               if(targetpc == 0)
-                       return;
-               if(targetpc != f->entry)
-                       targetpc--;
-               pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
-               if(pcdata == -1)
-                       return;
-               stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
-               if(stackmap == nil || stackmap->n <= 0)
-                       return;
-               bv = runtime·stackmapdata(stackmap, pcdata);
-               size = bv.n/BitsPerPointer*PtrSize;
-               n = ((PtrType*)t)->elem->size;
-               *len = n/PtrSize;
-               *mask = runtime·mallocgc(*len, nil, FlagNoScan);
-               for(i = 0; i < n; i += PtrSize) {
-                       off = (p+i-(byte*)frame.varp+size)/PtrSize;
-                       bits = (bv.bytedata[off*BitsPerPointer/8] >> ((off*BitsPerPointer)%8))&BitsMask;
-                       (*mask)[i/PtrSize] = bits;
-               }
-       }
-}
-
-void runtime·gc_unixnanotime(int64 *now);
-
-int64
-runtime·unixnanotime(void)
-{
-       int64 now;
-
-       runtime·gc_unixnanotime(&now);
-       return now;
-}
index cbf5e9cfdeffb9b08316b8b59b2327bffbe4a0e1..38406f33a873839a5a03edd32bd60070fce5d7ba 100644 (file)
@@ -28,7 +28,7 @@ func gc_unixnanotime(now *int64) {
 
 func freeOSMemory() {
        gogc(2) // force GC and do eager sweep
-       onM(scavenge_m)
+       systemstack(scavenge_m)
 }
 
 var poolcleanup func()
@@ -76,10 +76,8 @@ func clearpools() {
        }
 }
 
-func gosweepone() uintptr
-func gosweepdone() bool
-
 func bgsweep() {
+       sweep.g = getg()
        getg().issystem = true
        for {
                for gosweepone() != ^uintptr(0) {
index 64f8189143b1e8bf90f11cdef4c36d14a1972c76..62726b4f0f2c1e4e15f43d27b78b260dd7a621df 100644 (file)
@@ -2,77 +2,19 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Garbage collector (GC)
+// Used by cmd/gc.
 
 enum {
-       // Four bits per word (see #defines below).
        gcBits = 4,
-       wordsPerBitmapByte = 8/gcBits,
-
-       // GC type info programs.
-       // The programs allow to store type info required for GC in a compact form.
-       // Most importantly arrays take O(1) space instead of O(n).
-       // The program grammar is:
-       //
-       // Program = {Block} "insEnd"
-       // Block = Data | Array
-       // Data = "insData" DataSize DataBlock
-       // DataSize = int // size of the DataBlock in bit pairs, 1 byte
-       // DataBlock = binary // dense GC mask (2 bits per word) of size ]DataSize/4[ bytes
-       // Array = "insArray" ArrayLen Block "insArrayEnd"
-       // ArrayLen = int // length of the array, 8 bytes (4 bytes for 32-bit arch)
-       //
-       // Each instruction (insData, insArray, etc) is 1 byte.
-       // For example, for type struct { x []byte; y [20]struct{ z int; w *byte }; }
-       // the program looks as:
-       //
-       // insData 3 (BitsMultiWord BitsSlice BitsScalar)
-       //      insArray 20 insData 2 (BitsScalar BitsPointer) insArrayEnd insEnd
-       //
-       // Total size of the program is 17 bytes (13 bytes on 32-bits).
-       // The corresponding GC mask would take 43 bytes (it would be repeated
-       // because the type has odd number of words).
+       BitsPerPointer = 2,
+       BitsDead = 0,
+       BitsScalar = 1,
+       BitsPointer = 2,
+       BitsMask = 3,
+       PointersPerByte = 8/BitsPerPointer,
+       MaxGCMask = 64,
        insData = 1,
        insArray,
        insArrayEnd,
        insEnd,
-
-       // Pointer map
-       BitsPerPointer  = 2,
-       BitsMask        = (1<<BitsPerPointer)-1,
-       PointersPerByte = 8/BitsPerPointer,
-
-       // If you change these, also change scanblock.
-       // scanblock does "if(bits == BitsScalar || bits == BitsDead)" as "if(bits <= BitsScalar)".
-       BitsDead        = 0,
-       BitsScalar      = 1,
-       BitsPointer     = 2,
-       BitsMultiWord   = 3,
-       // BitsMultiWord will be set for the first word of a multi-word item.
-       // When it is set, one of the following will be set for the second word.
-       // NOT USED ANYMORE: BitsString = 0,
-       // NOT USED ANYMORE: BitsSlice  = 1,
-       BitsIface       = 2,
-       BitsEface       = 3,
-
-       // 64 bytes cover objects of size 1024/512 on 64/32 bits, respectively.
-       MaxGCMask       = 64,
-};
-
-// Bits in per-word bitmap.
-// #defines because we shift the values beyond 32 bits.
-//
-// Each word in the bitmap describes wordsPerBitmapWord words
-// of heap memory.  There are 4 bitmap bits dedicated to each heap word,
-// so on a 64-bit system there is one bitmap word per 16 heap words.
-//
-// The bitmap starts at mheap.arena_start and extends *backward* from
-// there.  On a 64-bit system the off'th word in the arena is tracked by
-// the off/16+1'th word before mheap.arena_start.  (On a 32-bit system,
-// the only difference is that the divisor is 8.)
-enum {
-       bitBoundary = 1, // boundary of an object
-       bitMarked = 2, // marked object
-       bitMask = bitBoundary | bitMarked,
-       bitPtrMask = BitsMask<<2,
 };
diff --git a/src/runtime/mgc1.go b/src/runtime/mgc1.go
new file mode 100644 (file)
index 0000000..d1aab45
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright 2012 The Go 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)
+
+package runtime
+
+const (
+       // Four bits per word (see #defines below).
+       gcBits             = 4
+       wordsPerBitmapByte = 8 / gcBits
+)
+
+const (
+       // GC type info programs.
+       // The programs allow to store type info required for GC in a compact form.
+       // Most importantly arrays take O(1) space instead of O(n).
+       // The program grammar is:
+       //
+       // Program = {Block} "insEnd"
+       // Block = Data | Array
+       // Data = "insData" DataSize DataBlock
+       // DataSize = int // size of the DataBlock in bit pairs, 1 byte
+       // DataBlock = binary // dense GC mask (2 bits per word) of size ]DataSize/4[ bytes
+       // Array = "insArray" ArrayLen Block "insArrayEnd"
+       // ArrayLen = int // length of the array, 8 bytes (4 bytes for 32-bit arch)
+       //
+       // Each instruction (insData, insArray, etc) is 1 byte.
+       // For example, for type struct { x []byte; y [20]struct{ z int; w *byte }; }
+       // the program looks as:
+       //
+       // insData 3 (BitsPointer BitsScalar BitsScalar)
+       //      insArray 20 insData 2 (BitsScalar BitsPointer) insArrayEnd insEnd
+       //
+       // Total size of the program is 17 bytes (13 bytes on 32-bits).
+       // The corresponding GC mask would take 43 bytes (it would be repeated
+       // because the type has odd number of words).
+       insData = 1 + iota
+       insArray
+       insArrayEnd
+       insEnd
+)
+
+const (
+       // Pointer map
+       _BitsPerPointer  = 2
+       _BitsMask        = (1 << _BitsPerPointer) - 1
+       _PointersPerByte = 8 / _BitsPerPointer
+
+       // If you change these, also change scanblock.
+       // scanblock does "if(bits == BitsScalar || bits == BitsDead)" as "if(bits <= BitsScalar)".
+       _BitsDead    = 0
+       _BitsScalar  = 1
+       _BitsPointer = 2
+
+       // 64 bytes cover objects of size 1024/512 on 64/32 bits, respectively.
+       _MaxGCMask = 64
+)
+
+// Bits in per-word bitmap.
+// #defines because we shift the values beyond 32 bits.
+//
+// Each word in the bitmap describes wordsPerBitmapWord words
+// of heap memory.  There are 4 bitmap bits dedicated to each heap word,
+// so on a 64-bit system there is one bitmap word per 16 heap words.
+//
+// The bitmap starts at mheap.arena_start and extends *backward* from
+// there.  On a 64-bit system the off'th word in the arena is tracked by
+// the off/16+1'th word before mheap.arena_start.  (On a 32-bit system,
+// the only difference is that the divisor is 8.)
+const (
+       bitBoundary = 1 // boundary of an object
+       bitMarked   = 2 // marked object
+       bitMask     = bitBoundary | bitMarked
+       bitPtrMask  = _BitsMask << 2
+)
diff --git a/src/runtime/mheap.c b/src/runtime/mheap.c
deleted file mode 100644 (file)
index bb203d5..0000000
+++ /dev/null
@@ -1,889 +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.
-
-// Page heap.
-//
-// See malloc.h for overview.
-//
-// When a MSpan is in the heap free list, state == MSpanFree
-// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span.
-//
-// When a MSpan is allocated, state == MSpanInUse or MSpanStack
-// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-static MSpan *MHeap_AllocSpanLocked(MHeap*, uintptr);
-static void MHeap_FreeSpanLocked(MHeap*, MSpan*, bool, bool);
-static bool MHeap_Grow(MHeap*, uintptr);
-static MSpan *MHeap_AllocLarge(MHeap*, uintptr);
-static MSpan *BestFit(MSpan*, uintptr, MSpan*);
-
-static void
-RecordSpan(void *vh, byte *p)
-{
-       MHeap *h;
-       MSpan *s;
-       MSpan **all;
-       uint32 cap;
-
-       h = vh;
-       s = (MSpan*)p;
-       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]), &mstats.other_sys);
-               if(all == nil)
-                       runtime·throw("runtime: cannot allocate memory");
-               if(h->allspans) {
-                       runtime·memmove(all, h->allspans, h->nspancap*sizeof(all[0]));
-                       // Don't free the old array if it's referenced by sweep.
-                       // See the comment in mgc0.c.
-                       if(h->allspans != runtime·mheap.gcspans)
-                               runtime·SysFree(h->allspans, h->nspancap*sizeof(all[0]), &mstats.other_sys);
-               }
-               h->allspans = all;
-               h->nspancap = cap;
-       }
-       h->allspans[h->nspan++] = s;
-}
-
-// Initialize the heap; fetch memory using alloc.
-void
-runtime·MHeap_Init(MHeap *h)
-{
-       uint32 i;
-
-       runtime·FixAlloc_Init(&h->spanalloc, sizeof(MSpan), RecordSpan, h, &mstats.mspan_sys);
-       runtime·FixAlloc_Init(&h->cachealloc, sizeof(MCache), nil, nil, &mstats.mcache_sys);
-       runtime·FixAlloc_Init(&h->specialfinalizeralloc, sizeof(SpecialFinalizer), nil, nil, &mstats.other_sys);
-       runtime·FixAlloc_Init(&h->specialprofilealloc, sizeof(SpecialProfile), nil, nil, &mstats.other_sys);
-       // h->mapcache needs no init
-       for(i=0; i<nelem(h->free); i++) {
-               runtime·MSpanList_Init(&h->free[i]);
-               runtime·MSpanList_Init(&h->busy[i]);
-       }
-       runtime·MSpanList_Init(&h->freelarge);
-       runtime·MSpanList_Init(&h->busylarge);
-       for(i=0; i<nelem(h->central); i++)
-               runtime·MCentral_Init(&h->central[i].mcentral, i);
-}
-
-void
-runtime·MHeap_MapSpans(MHeap *h)
-{
-       uintptr n;
-
-       // Map spans array, PageSize at a time.
-       n = (uintptr)h->arena_used;
-       n -= (uintptr)h->arena_start;
-       n = n / PageSize * sizeof(h->spans[0]);
-       n = ROUND(n, PhysPageSize);
-       if(h->spans_mapped >= n)
-               return;
-       runtime·SysMap((byte*)h->spans + h->spans_mapped, n - h->spans_mapped, h->arena_reserved, &mstats.other_sys);
-       h->spans_mapped = n;
-}
-
-// Sweeps spans in list until reclaims at least npages into heap.
-// Returns the actual number of pages reclaimed.
-static uintptr
-MHeap_ReclaimList(MHeap *h, MSpan *list, uintptr npages)
-{
-       MSpan *s;
-       uintptr n;
-       uint32 sg;
-
-       n = 0;
-       sg = runtime·mheap.sweepgen;
-retry:
-       for(s = list->next; s != list; s = s->next) {
-               if(s->sweepgen == sg-2 && runtime·cas(&s->sweepgen, sg-2, sg-1)) {
-                       runtime·MSpanList_Remove(s);
-                       // swept spans are at the end of the list
-                       runtime·MSpanList_InsertBack(list, s);
-                       runtime·unlock(&h->lock);
-                       n += runtime·MSpan_Sweep(s, false);
-                       runtime·lock(&h->lock);
-                       if(n >= npages)
-                               return n;
-                       // the span could have been moved elsewhere
-                       goto retry;
-               }
-               if(s->sweepgen == sg-1) {
-                       // the span is being sweept by background sweeper, skip
-                       continue;
-               }
-               // already swept empty span,
-               // all subsequent ones must also be either swept or in process of sweeping
-               break;
-       }
-       return n;
-}
-
-// Sweeps and reclaims at least npage pages into heap.
-// Called before allocating npage pages.
-static void
-MHeap_Reclaim(MHeap *h, uintptr npage)
-{
-       uintptr reclaimed, n;
-
-       // First try to sweep busy spans with large objects of size >= npage,
-       // this has good chances of reclaiming the necessary space.
-       for(n=npage; n < nelem(h->busy); n++) {
-               if(MHeap_ReclaimList(h, &h->busy[n], npage))
-                       return;  // Bingo!
-       }
-
-       // Then -- even larger objects.
-       if(MHeap_ReclaimList(h, &h->busylarge, npage))
-               return;  // Bingo!
-
-       // Now try smaller objects.
-       // One such object is not enough, so we need to reclaim several of them.
-       reclaimed = 0;
-       for(n=0; n < npage && n < nelem(h->busy); n++) {
-               reclaimed += MHeap_ReclaimList(h, &h->busy[n], npage-reclaimed);
-               if(reclaimed >= npage)
-                       return;
-       }
-
-       // Now sweep everything that is not yet swept.
-       runtime·unlock(&h->lock);
-       for(;;) {
-               n = runtime·sweepone();
-               if(n == -1)  // all spans are swept
-                       break;
-               reclaimed += n;
-               if(reclaimed >= npage)
-                       break;
-       }
-       runtime·lock(&h->lock);
-}
-
-// Allocate a new span of npage pages from the heap for GC'd memory
-// and record its size class in the HeapMap and HeapMapCache.
-static MSpan*
-mheap_alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large)
-{
-       MSpan *s;
-
-       if(g != g->m->g0)
-               runtime·throw("mheap_alloc not on M stack");
-       runtime·lock(&h->lock);
-
-       // To prevent excessive heap growth, before allocating n pages
-       // we need to sweep and reclaim at least n pages.
-       if(!h->sweepdone)
-               MHeap_Reclaim(h, npage);
-
-       // transfer stats from cache to global
-       mstats.heap_alloc += g->m->mcache->local_cachealloc;
-       g->m->mcache->local_cachealloc = 0;
-       mstats.tinyallocs += g->m->mcache->local_tinyallocs;
-       g->m->mcache->local_tinyallocs = 0;
-
-       s = MHeap_AllocSpanLocked(h, npage);
-       if(s != nil) {
-               // Record span info, because gc needs to be
-               // able to map interior pointer to containing span.
-               runtime·atomicstore(&s->sweepgen, h->sweepgen);
-               s->state = MSpanInUse;
-               s->freelist = nil;
-               s->ref = 0;
-               s->sizeclass = sizeclass;
-               s->elemsize = (sizeclass==0 ? s->npages<<PageShift : runtime·class_to_size[sizeclass]);
-
-               // update stats, sweep lists
-               if(large) {
-                       mstats.heap_objects++;
-                       mstats.heap_alloc += npage<<PageShift;
-                       // Swept spans are at the end of lists.
-                       if(s->npages < nelem(h->free))
-                               runtime·MSpanList_InsertBack(&h->busy[s->npages], s);
-                       else
-                               runtime·MSpanList_InsertBack(&h->busylarge, s);
-               }
-       }
-       runtime·unlock(&h->lock);
-       return s;
-}
-
-static void
-mheap_alloc_m(G *gp)
-{
-       MHeap *h;
-       MSpan *s;
-
-       h = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       s = mheap_alloc(h, g->m->scalararg[0], g->m->scalararg[1], g->m->scalararg[2]);
-       g->m->ptrarg[0] = s;
-
-       runtime·gogo(&gp->sched);
-}
-
-MSpan*
-runtime·MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool needzero)
-{
-       MSpan *s;
-       void (*fn)(G*);
-
-       // Don't do any operations that lock the heap on the G stack.
-       // It might trigger stack growth, and the stack growth code needs
-       // to be able to allocate heap.
-       if(g == g->m->g0) {
-               s = mheap_alloc(h, npage, sizeclass, large);
-       } else {
-               g->m->ptrarg[0] = h;
-               g->m->scalararg[0] = npage;
-               g->m->scalararg[1] = sizeclass;
-               g->m->scalararg[2] = large;
-               fn = mheap_alloc_m;
-               runtime·mcall(&fn);
-               s = g->m->ptrarg[0];
-               g->m->ptrarg[0] = nil;
-       }
-       if(s != nil) {
-               if(needzero && s->needzero)
-                       runtime·memclr((byte*)(s->start<<PageShift), s->npages<<PageShift);
-               s->needzero = 0;
-       }
-       return s;
-}
-
-MSpan*
-runtime·MHeap_AllocStack(MHeap *h, uintptr npage)
-{
-       MSpan *s;
-
-       if(g != g->m->g0)
-               runtime·throw("mheap_allocstack not on M stack");
-       runtime·lock(&h->lock);
-       s = MHeap_AllocSpanLocked(h, npage);
-       if(s != nil) {
-               s->state = MSpanStack;
-               s->freelist = nil;
-               s->ref = 0;
-               mstats.stacks_inuse += s->npages<<PageShift;
-       }
-       runtime·unlock(&h->lock);
-       return s;
-}
-
-// Allocates a span of the given size.  h must be locked.
-// The returned span has been removed from the
-// free list, but its state is still MSpanFree.
-static MSpan*
-MHeap_AllocSpanLocked(MHeap *h, uintptr npage)
-{
-       uintptr n;
-       MSpan *s, *t;
-       pageID p;
-
-       // Try in fixed-size lists up to max.
-       for(n=npage; n < nelem(h->free); n++) {
-               if(!runtime·MSpanList_IsEmpty(&h->free[n])) {
-                       s = h->free[n].next;
-                       goto HaveSpan;
-               }
-       }
-
-       // Best fit in list of large spans.
-       if((s = MHeap_AllocLarge(h, npage)) == nil) {
-               if(!MHeap_Grow(h, npage))
-                       return nil;
-               if((s = MHeap_AllocLarge(h, npage)) == nil)
-                       return nil;
-       }
-
-HaveSpan:
-       // Mark span in use.
-       if(s->state != MSpanFree)
-               runtime·throw("MHeap_AllocLocked - MSpan not free");
-       if(s->npages < npage)
-               runtime·throw("MHeap_AllocLocked - bad npages");
-       runtime·MSpanList_Remove(s);
-       if(s->next != nil || s->prev != nil)
-               runtime·throw("still in list");
-       if(s->npreleased > 0) {
-               runtime·SysUsed((void*)(s->start<<PageShift), s->npages<<PageShift);
-               mstats.heap_released -= s->npreleased<<PageShift;
-               s->npreleased = 0;
-       }
-
-       if(s->npages > npage) {
-               // Trim extra and put it back in the heap.
-               t = runtime·FixAlloc_Alloc(&h->spanalloc);
-               runtime·MSpan_Init(t, s->start + npage, s->npages - npage);
-               s->npages = npage;
-               p = t->start;
-               p -= ((uintptr)h->arena_start>>PageShift);
-               if(p > 0)
-                       h->spans[p-1] = s;
-               h->spans[p] = t;
-               h->spans[p+t->npages-1] = t;
-               t->needzero = s->needzero;
-               s->state = MSpanStack; // prevent coalescing with s
-               t->state = MSpanStack;
-               MHeap_FreeSpanLocked(h, t, false, false);
-               t->unusedsince = s->unusedsince; // preserve age (TODO: wrong: t is possibly merged and/or deallocated at this point)
-               s->state = MSpanFree;
-       }
-       s->unusedsince = 0;
-
-       p = s->start;
-       p -= ((uintptr)h->arena_start>>PageShift);
-       for(n=0; n<npage; n++)
-               h->spans[p+n] = s;
-
-       mstats.heap_inuse += npage<<PageShift;
-       mstats.heap_idle -= npage<<PageShift;
-
-       //runtime·printf("spanalloc %p\n", s->start << PageShift);
-       if(s->next != nil || s->prev != nil)
-               runtime·throw("still in list");
-       return s;
-}
-
-// Allocate a span of exactly npage pages from the list of large spans.
-static MSpan*
-MHeap_AllocLarge(MHeap *h, uintptr npage)
-{
-       return BestFit(&h->freelarge, npage, nil);
-}
-
-// Search list for smallest span with >= npage pages.
-// If there are multiple smallest spans, take the one
-// with the earliest starting address.
-static MSpan*
-BestFit(MSpan *list, uintptr npage, MSpan *best)
-{
-       MSpan *s;
-
-       for(s=list->next; s != list; s=s->next) {
-               if(s->npages < npage)
-                       continue;
-               if(best == nil
-               || s->npages < best->npages
-               || (s->npages == best->npages && s->start < best->start))
-                       best = s;
-       }
-       return best;
-}
-
-// Try to add at least npage pages of memory to the heap,
-// returning whether it worked.
-static bool
-MHeap_Grow(MHeap *h, uintptr npage)
-{
-       uintptr ask;
-       void *v;
-       MSpan *s;
-       pageID p;
-
-       // Ask for a big chunk, to reduce the number of mappings
-       // the operating system needs to track; also amortizes
-       // the overhead of an operating system mapping.
-       // Allocate a multiple of 64kB.
-       npage = ROUND(npage, (64<<10)/PageSize);
-       ask = npage<<PageShift;
-       if(ask < HeapAllocChunk)
-               ask = HeapAllocChunk;
-
-       v = runtime·MHeap_SysAlloc(h, ask);
-       if(v == nil) {
-               if(ask > (npage<<PageShift)) {
-                       ask = npage<<PageShift;
-                       v = runtime·MHeap_SysAlloc(h, ask);
-               }
-               if(v == nil) {
-                       runtime·printf("runtime: out of memory: cannot allocate %D-byte block (%D in use)\n", (uint64)ask, mstats.heap_sys);
-                       return false;
-               }
-       }
-
-       // Create a fake "in use" span and free it, so that the
-       // right coalescing happens.
-       s = runtime·FixAlloc_Alloc(&h->spanalloc);
-       runtime·MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift);
-       p = s->start;
-       p -= ((uintptr)h->arena_start>>PageShift);
-       h->spans[p] = s;
-       h->spans[p + s->npages - 1] = s;
-       runtime·atomicstore(&s->sweepgen, h->sweepgen);
-       s->state = MSpanInUse;
-       MHeap_FreeSpanLocked(h, s, false, true);
-       return true;
-}
-
-// Look up the span at the given address.
-// Address is guaranteed to be in map
-// and is guaranteed to be start or end of span.
-MSpan*
-runtime·MHeap_Lookup(MHeap *h, void *v)
-{
-       uintptr p;
-       
-       p = (uintptr)v;
-       p -= (uintptr)h->arena_start;
-       return h->spans[p >> PageShift];
-}
-
-// Look up the span at the given address.
-// Address is *not* guaranteed to be in map
-// and may be anywhere in the span.
-// Map entries for the middle of a span are only
-// valid for allocated spans.  Free spans may have
-// other garbage in their middles, so we have to
-// check for that.
-MSpan*
-runtime·MHeap_LookupMaybe(MHeap *h, void *v)
-{
-       MSpan *s;
-       pageID p, q;
-
-       if((byte*)v < h->arena_start || (byte*)v >= h->arena_used)
-               return nil;
-       p = (uintptr)v>>PageShift;
-       q = p;
-       q -= (uintptr)h->arena_start >> PageShift;
-       s = h->spans[q];
-       if(s == nil || p < s->start || v >= s->limit || s->state != MSpanInUse)
-               return nil;
-       return s;
-}
-
-// Free the span back into the heap.
-static void
-mheap_free(MHeap *h, MSpan *s, int32 acct)
-{
-       if(g != g->m->g0)
-               runtime·throw("mheap_free not on M stack");
-       runtime·lock(&h->lock);
-       mstats.heap_alloc += g->m->mcache->local_cachealloc;
-       g->m->mcache->local_cachealloc = 0;
-       mstats.tinyallocs += g->m->mcache->local_tinyallocs;
-       g->m->mcache->local_tinyallocs = 0;
-       if(acct) {
-               mstats.heap_alloc -= s->npages<<PageShift;
-               mstats.heap_objects--;
-       }
-       MHeap_FreeSpanLocked(h, s, true, true);
-       runtime·unlock(&h->lock);
-}
-
-static void
-mheap_free_m(G *gp)
-{
-       MHeap *h;
-       MSpan *s;
-       
-       h = g->m->ptrarg[0];
-       s = g->m->ptrarg[1];
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-       mheap_free(h, s, g->m->scalararg[0]);
-       runtime·gogo(&gp->sched);
-}
-
-void
-runtime·MHeap_Free(MHeap *h, MSpan *s, int32 acct)
-{
-       void (*fn)(G*);
-
-       if(g == g->m->g0) {
-               mheap_free(h, s, acct);
-       } else {
-               g->m->ptrarg[0] = h;
-               g->m->ptrarg[1] = s;
-               g->m->scalararg[0] = acct;
-               fn = mheap_free_m;
-               runtime·mcall(&fn);
-       }
-}
-
-void
-runtime·MHeap_FreeStack(MHeap *h, MSpan *s)
-{
-       if(g != g->m->g0)
-               runtime·throw("mheap_freestack not on M stack");
-       s->needzero = 1;
-       runtime·lock(&h->lock);
-       mstats.stacks_inuse -= s->npages<<PageShift;
-       MHeap_FreeSpanLocked(h, s, true, true);
-       runtime·unlock(&h->lock);
-}
-
-static void
-MHeap_FreeSpanLocked(MHeap *h, MSpan *s, bool acctinuse, bool acctidle)
-{
-       MSpan *t;
-       pageID p;
-
-       switch(s->state) {
-       case MSpanStack:
-               if(s->ref != 0)
-                       runtime·throw("MHeap_FreeSpanLocked - invalid stack free");
-               break;
-       case MSpanInUse:
-               if(s->ref != 0 || s->sweepgen != h->sweepgen) {
-                       runtime·printf("MHeap_FreeSpanLocked - span %p ptr %p ref %d sweepgen %d/%d\n",
-                                      s, s->start<<PageShift, s->ref, s->sweepgen, h->sweepgen);
-                       runtime·throw("MHeap_FreeSpanLocked - invalid free");
-               }
-               break;
-       default:
-               runtime·throw("MHeap_FreeSpanLocked - invalid span state");
-               break;
-       }
-       if(acctinuse)
-               mstats.heap_inuse -= s->npages<<PageShift;
-       if(acctidle)
-               mstats.heap_idle += s->npages<<PageShift;
-       s->state = MSpanFree;
-       runtime·MSpanList_Remove(s);
-       // Stamp newly unused spans. The scavenger will use that
-       // 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;
-       p -= (uintptr)h->arena_start >> PageShift;
-       if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse && t->state != MSpanStack) {
-               s->start = t->start;
-               s->npages += t->npages;
-               s->npreleased = t->npreleased; // absorb released pages
-               s->needzero |= t->needzero;
-               p -= t->npages;
-               h->spans[p] = s;
-               runtime·MSpanList_Remove(t);
-               t->state = MSpanDead;
-               runtime·FixAlloc_Free(&h->spanalloc, t);
-       }
-       if((p+s->npages)*sizeof(h->spans[0]) < h->spans_mapped && (t = h->spans[p+s->npages]) != nil && t->state != MSpanInUse && t->state != MSpanStack) {
-               s->npages += t->npages;
-               s->npreleased += t->npreleased;
-               s->needzero |= t->needzero;
-               h->spans[p + s->npages - 1] = s;
-               runtime·MSpanList_Remove(t);
-               t->state = MSpanDead;
-               runtime·FixAlloc_Free(&h->spanalloc, t);
-       }
-
-       // Insert s into appropriate list.
-       if(s->npages < nelem(h->free))
-               runtime·MSpanList_Insert(&h->free[s->npages], s);
-       else
-               runtime·MSpanList_Insert(&h->freelarge, s);
-}
-
-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 && s->npreleased != s->npages) {
-                       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;
-}
-
-void
-runtime·MHeap_Scavenge(int32 k, uint64 now, uint64 limit)
-{
-       uint32 i;
-       uintptr sumreleased;
-       MHeap *h;
-       
-       h = &runtime·mheap;
-       runtime·lock(&h->lock);
-       sumreleased = 0;
-       for(i=0; i < nelem(h->free); i++)
-               sumreleased += scavengelist(&h->free[i], now, limit);
-       sumreleased += scavengelist(&h->freelarge, now, limit);
-       runtime·unlock(&h->lock);
-
-       if(runtime·debug.gctrace > 0) {
-               if(sumreleased > 0)
-                       runtime·printf("scvg%d: %D MB released\n", k, (uint64)sumreleased>>20);
-               // TODO(dvyukov): these stats are incorrect as we don't subtract stack usage from heap.
-               // But we can't call ReadMemStats on g0 holding locks.
-               runtime·printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
-                       k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
-                       mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
-       }
-}
-
-void
-runtime·scavenge_m(void)
-{
-       runtime·MHeap_Scavenge(-1, ~(uintptr)0, 0);
-}
-
-// Initialize a new span with the given start and npages.
-void
-runtime·MSpan_Init(MSpan *span, pageID start, uintptr npages)
-{
-       span->next = nil;
-       span->prev = nil;
-       span->start = start;
-       span->npages = npages;
-       span->freelist = nil;
-       span->ref = 0;
-       span->sizeclass = 0;
-       span->incache = false;
-       span->elemsize = 0;
-       span->state = MSpanDead;
-       span->unusedsince = 0;
-       span->npreleased = 0;
-       span->specialLock.key = 0;
-       span->specials = nil;
-       span->needzero = 0;
-}
-
-// Initialize an empty doubly-linked list.
-void
-runtime·MSpanList_Init(MSpan *list)
-{
-       list->state = MSpanListHead;
-       list->next = list;
-       list->prev = list;
-}
-
-void
-runtime·MSpanList_Remove(MSpan *span)
-{
-       if(span->prev == nil && span->next == nil)
-               return;
-       span->prev->next = span->next;
-       span->next->prev = span->prev;
-       span->prev = nil;
-       span->next = nil;
-}
-
-bool
-runtime·MSpanList_IsEmpty(MSpan *list)
-{
-       return list->next == list;
-}
-
-void
-runtime·MSpanList_Insert(MSpan *list, MSpan *span)
-{
-       if(span->next != nil || span->prev != nil) {
-               runtime·printf("failed MSpanList_Insert %p %p %p\n", span, span->next, span->prev);
-               runtime·throw("MSpanList_Insert");
-       }
-       span->next = list->next;
-       span->prev = list;
-       span->next->prev = span;
-       span->prev->next = span;
-}
-
-void
-runtime·MSpanList_InsertBack(MSpan *list, MSpan *span)
-{
-       if(span->next != nil || span->prev != nil) {
-               runtime·printf("failed MSpanList_Insert %p %p %p\n", span, span->next, span->prev);
-               runtime·throw("MSpanList_Insert");
-       }
-       span->next = list;
-       span->prev = list->prev;
-       span->next->prev = span;
-       span->prev->next = span;
-}
-
-// Adds the special record s to the list of special records for
-// the object p.  All fields of s should be filled in except for
-// offset & next, which this routine will fill in.
-// Returns true if the special was successfully added, false otherwise.
-// (The add will fail only if a record with the same p and s->kind
-//  already exists.)
-static bool
-addspecial(void *p, Special *s)
-{
-       MSpan *span;
-       Special **t, *x;
-       uintptr offset;
-       byte kind;
-
-       span = runtime·MHeap_LookupMaybe(&runtime·mheap, p);
-       if(span == nil)
-               runtime·throw("addspecial on invalid pointer");
-
-       // Ensure that the span is swept.
-       // GC accesses specials list w/o locks. And it's just much safer.
-       g->m->locks++;
-       runtime·MSpan_EnsureSwept(span);
-
-       offset = (uintptr)p - (span->start << PageShift);
-       kind = s->kind;
-
-       runtime·lock(&span->specialLock);
-
-       // Find splice point, check for existing record.
-       t = &span->specials;
-       while((x = *t) != nil) {
-               if(offset == x->offset && kind == x->kind) {
-                       runtime·unlock(&span->specialLock);
-                       g->m->locks--;
-                       return false; // already exists
-               }
-               if(offset < x->offset || (offset == x->offset && kind < x->kind))
-                       break;
-               t = &x->next;
-       }
-       // Splice in record, fill in offset.
-       s->offset = offset;
-       s->next = x;
-       *t = s;
-       runtime·unlock(&span->specialLock);
-       g->m->locks--;
-       return true;
-}
-
-// Removes the Special record of the given kind for the object p.
-// Returns the record if the record existed, nil otherwise.
-// The caller must FixAlloc_Free the result.
-static Special*
-removespecial(void *p, byte kind)
-{
-       MSpan *span;
-       Special *s, **t;
-       uintptr offset;
-
-       span = runtime·MHeap_LookupMaybe(&runtime·mheap, p);
-       if(span == nil)
-               runtime·throw("removespecial on invalid pointer");
-
-       // Ensure that the span is swept.
-       // GC accesses specials list w/o locks. And it's just much safer.
-       g->m->locks++;
-       runtime·MSpan_EnsureSwept(span);
-
-       offset = (uintptr)p - (span->start << PageShift);
-
-       runtime·lock(&span->specialLock);
-       t = &span->specials;
-       while((s = *t) != nil) {
-               // This function is used for finalizers only, so we don't check for
-               // "interior" specials (p must be exactly equal to s->offset).
-               if(offset == s->offset && kind == s->kind) {
-                       *t = s->next;
-                       runtime·unlock(&span->specialLock);
-                       g->m->locks--;
-                       return s;
-               }
-               t = &s->next;
-       }
-       runtime·unlock(&span->specialLock);
-       g->m->locks--;
-       return nil;
-}
-
-// Adds a finalizer to the object p.  Returns true if it succeeded.
-bool
-runtime·addfinalizer(void *p, FuncVal *f, uintptr nret, Type *fint, PtrType *ot)
-{
-       SpecialFinalizer *s;
-
-       runtime·lock(&runtime·mheap.speciallock);
-       s = runtime·FixAlloc_Alloc(&runtime·mheap.specialfinalizeralloc);
-       runtime·unlock(&runtime·mheap.speciallock);
-       s->special.kind = KindSpecialFinalizer;
-       s->fn = f;
-       s->nret = nret;
-       s->fint = fint;
-       s->ot = ot;
-       if(addspecial(p, &s->special))
-               return true;
-
-       // There was an old finalizer
-       runtime·lock(&runtime·mheap.speciallock);
-       runtime·FixAlloc_Free(&runtime·mheap.specialfinalizeralloc, s);
-       runtime·unlock(&runtime·mheap.speciallock);
-       return false;
-}
-
-// Removes the finalizer (if any) from the object p.
-void
-runtime·removefinalizer(void *p)
-{
-       SpecialFinalizer *s;
-
-       s = (SpecialFinalizer*)removespecial(p, KindSpecialFinalizer);
-       if(s == nil)
-               return; // there wasn't a finalizer to remove
-       runtime·lock(&runtime·mheap.speciallock);
-       runtime·FixAlloc_Free(&runtime·mheap.specialfinalizeralloc, s);
-       runtime·unlock(&runtime·mheap.speciallock);
-}
-
-// Set the heap profile bucket associated with addr to b.
-void
-runtime·setprofilebucket_m(void)
-{      
-       void *p;
-       Bucket *b;
-       SpecialProfile *s;
-       
-       p = g->m->ptrarg[0];
-       b = g->m->ptrarg[1];
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-
-       runtime·lock(&runtime·mheap.speciallock);
-       s = runtime·FixAlloc_Alloc(&runtime·mheap.specialprofilealloc);
-       runtime·unlock(&runtime·mheap.speciallock);
-       s->special.kind = KindSpecialProfile;
-       s->b = b;
-       if(!addspecial(p, &s->special))
-               runtime·throw("setprofilebucket: profile already set");
-}
-
-// Do whatever cleanup needs to be done to deallocate s.  It has
-// already been unlinked from the MSpan specials list.
-// Returns true if we should keep working on deallocating p.
-bool
-runtime·freespecial(Special *s, void *p, uintptr size, bool freed)
-{
-       SpecialFinalizer *sf;
-       SpecialProfile *sp;
-
-       switch(s->kind) {
-       case KindSpecialFinalizer:
-               sf = (SpecialFinalizer*)s;
-               runtime·queuefinalizer(p, sf->fn, sf->nret, sf->fint, sf->ot);
-               runtime·lock(&runtime·mheap.speciallock);
-               runtime·FixAlloc_Free(&runtime·mheap.specialfinalizeralloc, sf);
-               runtime·unlock(&runtime·mheap.speciallock);
-               return false; // don't free p until finalizer is done
-       case KindSpecialProfile:
-               sp = (SpecialProfile*)s;
-               runtime·mProf_Free(sp->b, size, freed);
-               runtime·lock(&runtime·mheap.speciallock);
-               runtime·FixAlloc_Free(&runtime·mheap.specialprofilealloc, sp);
-               runtime·unlock(&runtime·mheap.speciallock);
-               return true;
-       default:
-               runtime·throw("bad special kind");
-               return true;
-       }
-}
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
new file mode 100644 (file)
index 0000000..fedcd69
--- /dev/null
@@ -0,0 +1,785 @@
+// 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.
+
+// Page heap.
+//
+// See malloc.h for overview.
+//
+// When a MSpan is in the heap free list, state == MSpanFree
+// and heapmap(s->start) == span, heapmap(s->start+s->npages-1) == span.
+//
+// When a MSpan is allocated, state == MSpanInUse or MSpanStack
+// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
+
+package runtime
+
+import "unsafe"
+
+var h_allspans []*mspan // TODO: make this h.allspans once mheap can be defined in Go
+var h_spans []*mspan    // TODO: make this h.spans once mheap can be defined in Go
+
+func recordspan(vh unsafe.Pointer, p unsafe.Pointer) {
+       h := (*mheap)(vh)
+       s := (*mspan)(p)
+       if len(h_allspans) >= cap(h_allspans) {
+               n := 64 * 1024 / ptrSize
+               if n < cap(h_allspans)*3/2 {
+                       n = cap(h_allspans) * 3 / 2
+               }
+               var new []*mspan
+               sp := (*slice)(unsafe.Pointer(&new))
+               sp.array = (*byte)(sysAlloc(uintptr(n)*ptrSize, &memstats.other_sys))
+               if sp.array == nil {
+                       gothrow("runtime: cannot allocate memory")
+               }
+               sp.len = uint(len(h_allspans))
+               sp.cap = uint(n)
+               if len(h_allspans) > 0 {
+                       copy(new, h_allspans)
+                       // Don't free the old array if it's referenced by sweep.
+                       // See the comment in mgc0.c.
+                       if h.allspans != mheap_.gcspans {
+                               sysFree(unsafe.Pointer(h.allspans), uintptr(cap(h_allspans))*ptrSize, &memstats.other_sys)
+                       }
+               }
+               h_allspans = new
+               h.allspans = (**mspan)(unsafe.Pointer(sp.array))
+       }
+       h_allspans = append(h_allspans, s)
+       h.nspan = uint32(len(h_allspans))
+}
+
+// Initialize the heap.
+func mHeap_Init(h *mheap, spans_size uintptr) {
+       fixAlloc_Init(&h.spanalloc, unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys)
+       fixAlloc_Init(&h.cachealloc, unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
+       fixAlloc_Init(&h.specialfinalizeralloc, unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
+       fixAlloc_Init(&h.specialprofilealloc, unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
+
+       // h->mapcache needs no init
+       for i := range h.free {
+               mSpanList_Init(&h.free[i])
+               mSpanList_Init(&h.busy[i])
+       }
+
+       mSpanList_Init(&h.freelarge)
+       mSpanList_Init(&h.busylarge)
+       for i := range h.central {
+               mCentral_Init(&h.central[i].mcentral, int32(i))
+       }
+
+       sp := (*slice)(unsafe.Pointer(&h_spans))
+       sp.array = (*byte)(unsafe.Pointer(h.spans))
+       sp.len = uint(spans_size / ptrSize)
+       sp.cap = uint(spans_size / ptrSize)
+}
+
+func mHeap_MapSpans(h *mheap) {
+       // Map spans array, PageSize at a time.
+       n := uintptr(unsafe.Pointer(h.arena_used))
+       n -= uintptr(unsafe.Pointer(h.arena_start))
+       n = n / _PageSize * ptrSize
+       n = round(n, _PhysPageSize)
+       if h.spans_mapped >= n {
+               return
+       }
+       sysMap(add(unsafe.Pointer(h.spans), h.spans_mapped), n-h.spans_mapped, h.arena_reserved, &memstats.other_sys)
+       h.spans_mapped = n
+}
+
+// Sweeps spans in list until reclaims at least npages into heap.
+// Returns the actual number of pages reclaimed.
+func mHeap_ReclaimList(h *mheap, list *mspan, npages uintptr) uintptr {
+       n := uintptr(0)
+       sg := mheap_.sweepgen
+retry:
+       for s := list.next; s != list; s = s.next {
+               if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
+                       mSpanList_Remove(s)
+                       // swept spans are at the end of the list
+                       mSpanList_InsertBack(list, s)
+                       unlock(&h.lock)
+                       if mSpan_Sweep(s, false) {
+                               // TODO(rsc,dvyukov): This is probably wrong.
+                               // It is undercounting the number of pages reclaimed.
+                               // See golang.org/issue/9048.
+                               // Note that if we want to add the true count of s's pages,
+                               // we must record that before calling mSpan_Sweep,
+                               // because if mSpan_Sweep returns true the span has
+                               // been
+                               n++
+                       }
+                       lock(&h.lock)
+                       if n >= npages {
+                               return n
+                       }
+                       // the span could have been moved elsewhere
+                       goto retry
+               }
+               if s.sweepgen == sg-1 {
+                       // the span is being sweept by background sweeper, skip
+                       continue
+               }
+               // already swept empty span,
+               // all subsequent ones must also be either swept or in process of sweeping
+               break
+       }
+       return n
+}
+
+// Sweeps and reclaims at least npage pages into heap.
+// Called before allocating npage pages.
+func mHeap_Reclaim(h *mheap, npage uintptr) {
+       // First try to sweep busy spans with large objects of size >= npage,
+       // this has good chances of reclaiming the necessary space.
+       for i := int(npage); i < len(h.busy); i++ {
+               if mHeap_ReclaimList(h, &h.busy[i], npage) != 0 {
+                       return // Bingo!
+               }
+       }
+
+       // Then -- even larger objects.
+       if mHeap_ReclaimList(h, &h.busylarge, npage) != 0 {
+               return // Bingo!
+       }
+
+       // Now try smaller objects.
+       // One such object is not enough, so we need to reclaim several of them.
+       reclaimed := uintptr(0)
+       for i := 0; i < int(npage) && i < len(h.busy); i++ {
+               reclaimed += mHeap_ReclaimList(h, &h.busy[i], npage-reclaimed)
+               if reclaimed >= npage {
+                       return
+               }
+       }
+
+       // Now sweep everything that is not yet swept.
+       unlock(&h.lock)
+       for {
+               n := sweepone()
+               if n == ^uintptr(0) { // all spans are swept
+                       break
+               }
+               reclaimed += n
+               if reclaimed >= npage {
+                       break
+               }
+       }
+       lock(&h.lock)
+}
+
+// Allocate a new span of npage pages from the heap for GC'd memory
+// and record its size class in the HeapMap and HeapMapCache.
+func mHeap_Alloc_m(h *mheap, npage uintptr, sizeclass int32, large bool) *mspan {
+       _g_ := getg()
+       if _g_ != _g_.m.g0 {
+               gothrow("_mheap_alloc not on g0 stack")
+       }
+       lock(&h.lock)
+
+       // To prevent excessive heap growth, before allocating n pages
+       // we need to sweep and reclaim at least n pages.
+       if h.sweepdone == 0 {
+               mHeap_Reclaim(h, npage)
+       }
+
+       // transfer stats from cache to global
+       memstats.heap_alloc += uint64(_g_.m.mcache.local_cachealloc)
+       _g_.m.mcache.local_cachealloc = 0
+       memstats.tinyallocs += uint64(_g_.m.mcache.local_tinyallocs)
+       _g_.m.mcache.local_tinyallocs = 0
+
+       s := mHeap_AllocSpanLocked(h, npage)
+       if s != nil {
+               // Record span info, because gc needs to be
+               // able to map interior pointer to containing span.
+               atomicstore(&s.sweepgen, h.sweepgen)
+               s.state = _MSpanInUse
+               s.freelist = nil
+               s.ref = 0
+               s.sizeclass = uint8(sizeclass)
+               if sizeclass == 0 {
+                       s.elemsize = s.npages << _PageShift
+               } else {
+                       s.elemsize = uintptr(class_to_size[sizeclass])
+               }
+
+               // update stats, sweep lists
+               if large {
+                       memstats.heap_objects++
+                       memstats.heap_alloc += uint64(npage << _PageShift)
+                       // Swept spans are at the end of lists.
+                       if s.npages < uintptr(len(h.free)) {
+                               mSpanList_InsertBack(&h.busy[s.npages], s)
+                       } else {
+                               mSpanList_InsertBack(&h.busylarge, s)
+                       }
+               }
+       }
+       unlock(&h.lock)
+       return s
+}
+
+func mHeap_Alloc(h *mheap, npage uintptr, sizeclass int32, large bool, needzero bool) *mspan {
+       // Don't do any operations that lock the heap on the G stack.
+       // It might trigger stack growth, and the stack growth code needs
+       // to be able to allocate heap.
+       var s *mspan
+       systemstack(func() {
+               s = mHeap_Alloc_m(h, npage, sizeclass, large)
+       })
+
+       if s != nil {
+               if needzero && s.needzero != 0 {
+                       memclr(unsafe.Pointer(s.start<<_PageShift), s.npages<<_PageShift)
+               }
+               s.needzero = 0
+       }
+       return s
+}
+
+func mHeap_AllocStack(h *mheap, npage uintptr) *mspan {
+       _g_ := getg()
+       if _g_ != _g_.m.g0 {
+               gothrow("mheap_allocstack not on g0 stack")
+       }
+       lock(&h.lock)
+       s := mHeap_AllocSpanLocked(h, npage)
+       if s != nil {
+               s.state = _MSpanStack
+               s.freelist = nil
+               s.ref = 0
+               memstats.stacks_inuse += uint64(s.npages << _PageShift)
+       }
+       unlock(&h.lock)
+       return s
+}
+
+// Allocates a span of the given size.  h must be locked.
+// The returned span has been removed from the
+// free list, but its state is still MSpanFree.
+func mHeap_AllocSpanLocked(h *mheap, npage uintptr) *mspan {
+       var s *mspan
+
+       // Try in fixed-size lists up to max.
+       for i := int(npage); i < len(h.free); i++ {
+               if !mSpanList_IsEmpty(&h.free[i]) {
+                       s = h.free[i].next
+                       goto HaveSpan
+               }
+       }
+
+       // Best fit in list of large spans.
+       s = mHeap_AllocLarge(h, npage)
+       if s == nil {
+               if !mHeap_Grow(h, npage) {
+                       return nil
+               }
+               s = mHeap_AllocLarge(h, npage)
+               if s == nil {
+                       return nil
+               }
+       }
+
+HaveSpan:
+       // Mark span in use.
+       if s.state != _MSpanFree {
+               gothrow("MHeap_AllocLocked - MSpan not free")
+       }
+       if s.npages < npage {
+               gothrow("MHeap_AllocLocked - bad npages")
+       }
+       mSpanList_Remove(s)
+       if s.next != nil || s.prev != nil {
+               gothrow("still in list")
+       }
+       if s.npreleased > 0 {
+               sysUsed((unsafe.Pointer)(s.start<<_PageShift), s.npages<<_PageShift)
+               memstats.heap_released -= uint64(s.npreleased << _PageShift)
+               s.npreleased = 0
+       }
+
+       if s.npages > npage {
+               // Trim extra and put it back in the heap.
+               t := (*mspan)(fixAlloc_Alloc(&h.spanalloc))
+               mSpan_Init(t, s.start+pageID(npage), s.npages-npage)
+               s.npages = npage
+               p := uintptr(t.start)
+               p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+               if p > 0 {
+                       h_spans[p-1] = s
+               }
+               h_spans[p] = t
+               h_spans[p+t.npages-1] = t
+               t.needzero = s.needzero
+               s.state = _MSpanStack // prevent coalescing with s
+               t.state = _MSpanStack
+               mHeap_FreeSpanLocked(h, t, false, false)
+               t.unusedsince = s.unusedsince // preserve age (TODO: wrong: t is possibly merged and/or deallocated at this point)
+               s.state = _MSpanFree
+       }
+       s.unusedsince = 0
+
+       p := uintptr(s.start)
+       p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+       for n := uintptr(0); n < npage; n++ {
+               h_spans[p+n] = s
+       }
+
+       memstats.heap_inuse += uint64(npage << _PageShift)
+       memstats.heap_idle -= uint64(npage << _PageShift)
+
+       //println("spanalloc", hex(s.start<<_PageShift))
+       if s.next != nil || s.prev != nil {
+               gothrow("still in list")
+       }
+       return s
+}
+
+// Allocate a span of exactly npage pages from the list of large spans.
+func mHeap_AllocLarge(h *mheap, npage uintptr) *mspan {
+       return bestFit(&h.freelarge, npage, nil)
+}
+
+// Search list for smallest span with >= npage pages.
+// If there are multiple smallest spans, take the one
+// with the earliest starting address.
+func bestFit(list *mspan, npage uintptr, best *mspan) *mspan {
+       for s := list.next; s != list; s = s.next {
+               if s.npages < npage {
+                       continue
+               }
+               if best == nil || s.npages < best.npages || (s.npages == best.npages && s.start < best.start) {
+                       best = s
+               }
+       }
+       return best
+}
+
+// Try to add at least npage pages of memory to the heap,
+// returning whether it worked.
+func mHeap_Grow(h *mheap, npage uintptr) bool {
+       // Ask for a big chunk, to reduce the number of mappings
+       // the operating system needs to track; also amortizes
+       // the overhead of an operating system mapping.
+       // Allocate a multiple of 64kB.
+       npage = round(npage, (64<<10)/_PageSize)
+       ask := npage << _PageShift
+       if ask < _HeapAllocChunk {
+               ask = _HeapAllocChunk
+       }
+
+       v := mHeap_SysAlloc(h, ask)
+       if v == nil {
+               if ask > npage<<_PageShift {
+                       ask = npage << _PageShift
+                       v = mHeap_SysAlloc(h, ask)
+               }
+               if v == nil {
+                       print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n")
+                       return false
+               }
+       }
+
+       // Create a fake "in use" span and free it, so that the
+       // right coalescing happens.
+       s := (*mspan)(fixAlloc_Alloc(&h.spanalloc))
+       mSpan_Init(s, pageID(uintptr(v)>>_PageShift), ask>>_PageShift)
+       p := uintptr(s.start)
+       p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+       h_spans[p] = s
+       h_spans[p+s.npages-1] = s
+       atomicstore(&s.sweepgen, h.sweepgen)
+       s.state = _MSpanInUse
+       mHeap_FreeSpanLocked(h, s, false, true)
+       return true
+}
+
+// Look up the span at the given address.
+// Address is guaranteed to be in map
+// and is guaranteed to be start or end of span.
+func mHeap_Lookup(h *mheap, v unsafe.Pointer) *mspan {
+       p := uintptr(v)
+       p -= uintptr(unsafe.Pointer(h.arena_start))
+       return h_spans[p>>_PageShift]
+}
+
+// Look up the span at the given address.
+// Address is *not* guaranteed to be in map
+// and may be anywhere in the span.
+// Map entries for the middle of a span are only
+// valid for allocated spans.  Free spans may have
+// other garbage in their middles, so we have to
+// check for that.
+func mHeap_LookupMaybe(h *mheap, v unsafe.Pointer) *mspan {
+       if uintptr(v) < uintptr(unsafe.Pointer(h.arena_start)) || uintptr(v) >= uintptr(unsafe.Pointer(h.arena_used)) {
+               return nil
+       }
+       p := uintptr(v) >> _PageShift
+       q := p
+       q -= uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift
+       s := h_spans[q]
+       if s == nil || p < uintptr(s.start) || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != _MSpanInUse {
+               return nil
+       }
+       return s
+}
+
+// Free the span back into the heap.
+func mHeap_Free(h *mheap, s *mspan, acct int32) {
+       systemstack(func() {
+               mp := getg().m
+               lock(&h.lock)
+               memstats.heap_alloc += uint64(mp.mcache.local_cachealloc)
+               mp.mcache.local_cachealloc = 0
+               memstats.tinyallocs += uint64(mp.mcache.local_tinyallocs)
+               mp.mcache.local_tinyallocs = 0
+               if acct != 0 {
+                       memstats.heap_alloc -= uint64(s.npages << _PageShift)
+                       memstats.heap_objects--
+               }
+               mHeap_FreeSpanLocked(h, s, true, true)
+               unlock(&h.lock)
+       })
+}
+
+func mHeap_FreeStack(h *mheap, s *mspan) {
+       _g_ := getg()
+       if _g_ != _g_.m.g0 {
+               gothrow("mheap_freestack not on g0 stack")
+       }
+       s.needzero = 1
+       lock(&h.lock)
+       memstats.stacks_inuse -= uint64(s.npages << _PageShift)
+       mHeap_FreeSpanLocked(h, s, true, true)
+       unlock(&h.lock)
+}
+
+func mHeap_FreeSpanLocked(h *mheap, s *mspan, acctinuse, acctidle bool) {
+       switch s.state {
+       case _MSpanStack:
+               if s.ref != 0 {
+                       gothrow("MHeap_FreeSpanLocked - invalid stack free")
+               }
+       case _MSpanInUse:
+               if s.ref != 0 || s.sweepgen != h.sweepgen {
+                       print("MHeap_FreeSpanLocked - span ", s, " ptr ", hex(s.start<<_PageShift), " ref ", s.ref, " sweepgen ", s.sweepgen, "/", h.sweepgen, "\n")
+                       gothrow("MHeap_FreeSpanLocked - invalid free")
+               }
+       default:
+               gothrow("MHeap_FreeSpanLocked - invalid span state")
+       }
+
+       if acctinuse {
+               memstats.heap_inuse -= uint64(s.npages << _PageShift)
+       }
+       if acctidle {
+               memstats.heap_idle += uint64(s.npages << _PageShift)
+       }
+       s.state = _MSpanFree
+       mSpanList_Remove(s)
+
+       // Stamp newly unused spans. The scavenger will use that
+       // info to potentially give back some pages to the OS.
+       s.unusedsince = nanotime()
+       s.npreleased = 0
+
+       // Coalesce with earlier, later spans.
+       p := uintptr(s.start)
+       p -= uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift
+       if p > 0 {
+               t := h_spans[p-1]
+               if t != nil && t.state != _MSpanInUse && t.state != _MSpanStack {
+                       s.start = t.start
+                       s.npages += t.npages
+                       s.npreleased = t.npreleased // absorb released pages
+                       s.needzero |= t.needzero
+                       p -= t.npages
+                       h_spans[p] = s
+                       mSpanList_Remove(t)
+                       t.state = _MSpanDead
+                       fixAlloc_Free(&h.spanalloc, (unsafe.Pointer)(t))
+               }
+       }
+       if (p+s.npages)*ptrSize < h.spans_mapped {
+               t := h_spans[p+s.npages]
+               if t != nil && t.state != _MSpanInUse && t.state != _MSpanStack {
+                       s.npages += t.npages
+                       s.npreleased += t.npreleased
+                       s.needzero |= t.needzero
+                       h_spans[p+s.npages-1] = s
+                       mSpanList_Remove(t)
+                       t.state = _MSpanDead
+                       fixAlloc_Free(&h.spanalloc, (unsafe.Pointer)(t))
+               }
+       }
+
+       // Insert s into appropriate list.
+       if s.npages < uintptr(len(h.free)) {
+               mSpanList_Insert(&h.free[s.npages], s)
+       } else {
+               mSpanList_Insert(&h.freelarge, s)
+       }
+}
+
+func scavengelist(list *mspan, now, limit uint64) uintptr {
+       if mSpanList_IsEmpty(list) {
+               return 0
+       }
+
+       var sumreleased uintptr
+       for s := list.next; s != list; s = s.next {
+               if (now-uint64(s.unusedsince)) > limit && s.npreleased != s.npages {
+                       released := (s.npages - s.npreleased) << _PageShift
+                       memstats.heap_released += uint64(released)
+                       sumreleased += released
+                       s.npreleased = s.npages
+                       sysUnused((unsafe.Pointer)(s.start<<_PageShift), s.npages<<_PageShift)
+               }
+       }
+       return sumreleased
+}
+
+func mHeap_Scavenge(k int32, now, limit uint64) {
+       h := &mheap_
+       lock(&h.lock)
+       var sumreleased uintptr
+       for i := 0; i < len(h.free); i++ {
+               sumreleased += scavengelist(&h.free[i], now, limit)
+       }
+       sumreleased += scavengelist(&h.freelarge, now, limit)
+       unlock(&h.lock)
+
+       if debug.gctrace > 0 {
+               if sumreleased > 0 {
+                       print("scvg", k, ": ", sumreleased>>20, " MB released\n")
+               }
+               // TODO(dvyukov): these stats are incorrect as we don't subtract stack usage from heap.
+               // But we can't call ReadMemStats on g0 holding locks.
+               print("scvg", k, ": inuse: ", memstats.heap_inuse>>20, ", idle: ", memstats.heap_idle>>20, ", sys: ", memstats.heap_sys>>20, ", released: ", memstats.heap_released>>20, ", consumed: ", (memstats.heap_sys-memstats.heap_released)>>20, " (MB)\n")
+       }
+}
+
+func scavenge_m() {
+       mHeap_Scavenge(-1, ^uint64(0), 0)
+}
+
+// Initialize a new span with the given start and npages.
+func mSpan_Init(span *mspan, start pageID, npages uintptr) {
+       span.next = nil
+       span.prev = nil
+       span.start = start
+       span.npages = npages
+       span.freelist = nil
+       span.ref = 0
+       span.sizeclass = 0
+       span.incache = false
+       span.elemsize = 0
+       span.state = _MSpanDead
+       span.unusedsince = 0
+       span.npreleased = 0
+       span.speciallock.key = 0
+       span.specials = nil
+       span.needzero = 0
+}
+
+// Initialize an empty doubly-linked list.
+func mSpanList_Init(list *mspan) {
+       list.state = _MSpanListHead
+       list.next = list
+       list.prev = list
+}
+
+func mSpanList_Remove(span *mspan) {
+       if span.prev == nil && span.next == nil {
+               return
+       }
+       span.prev.next = span.next
+       span.next.prev = span.prev
+       span.prev = nil
+       span.next = nil
+}
+
+func mSpanList_IsEmpty(list *mspan) bool {
+       return list.next == list
+}
+
+func mSpanList_Insert(list *mspan, span *mspan) {
+       if span.next != nil || span.prev != nil {
+               println("failed MSpanList_Insert", span, span.next, span.prev)
+               gothrow("MSpanList_Insert")
+       }
+       span.next = list.next
+       span.prev = list
+       span.next.prev = span
+       span.prev.next = span
+}
+
+func mSpanList_InsertBack(list *mspan, span *mspan) {
+       if span.next != nil || span.prev != nil {
+               println("failed MSpanList_InsertBack", span, span.next, span.prev)
+               gothrow("MSpanList_InsertBack")
+       }
+       span.next = list
+       span.prev = list.prev
+       span.next.prev = span
+       span.prev.next = span
+}
+
+// Adds the special record s to the list of special records for
+// the object p.  All fields of s should be filled in except for
+// offset & next, which this routine will fill in.
+// Returns true if the special was successfully added, false otherwise.
+// (The add will fail only if a record with the same p and s->kind
+//  already exists.)
+func addspecial(p unsafe.Pointer, s *special) bool {
+       span := mHeap_LookupMaybe(&mheap_, p)
+       if span == nil {
+               gothrow("addspecial on invalid pointer")
+       }
+
+       // Ensure that the span is swept.
+       // GC accesses specials list w/o locks. And it's just much safer.
+       mp := acquirem()
+       mSpan_EnsureSwept(span)
+
+       offset := uintptr(p) - uintptr(span.start<<_PageShift)
+       kind := s.kind
+
+       lock(&span.speciallock)
+
+       // Find splice point, check for existing record.
+       t := &span.specials
+       for {
+               x := *t
+               if x == nil {
+                       break
+               }
+               if offset == uintptr(x.offset) && kind == x.kind {
+                       unlock(&span.speciallock)
+                       releasem(mp)
+                       return false // already exists
+               }
+               if offset < uintptr(x.offset) || (offset == uintptr(x.offset) && kind < x.kind) {
+                       break
+               }
+               t = &x.next
+       }
+
+       // Splice in record, fill in offset.
+       s.offset = uint16(offset)
+       s.next = *t
+       *t = s
+       unlock(&span.speciallock)
+       releasem(mp)
+
+       return true
+}
+
+// Removes the Special record of the given kind for the object p.
+// Returns the record if the record existed, nil otherwise.
+// The caller must FixAlloc_Free the result.
+func removespecial(p unsafe.Pointer, kind uint8) *special {
+       span := mHeap_LookupMaybe(&mheap_, p)
+       if span == nil {
+               gothrow("removespecial on invalid pointer")
+       }
+
+       // Ensure that the span is swept.
+       // GC accesses specials list w/o locks. And it's just much safer.
+       mp := acquirem()
+       mSpan_EnsureSwept(span)
+
+       offset := uintptr(p) - uintptr(span.start<<_PageShift)
+
+       lock(&span.speciallock)
+       t := &span.specials
+       for {
+               s := *t
+               if s == nil {
+                       break
+               }
+               // This function is used for finalizers only, so we don't check for
+               // "interior" specials (p must be exactly equal to s->offset).
+               if offset == uintptr(s.offset) && kind == s.kind {
+                       *t = s.next
+                       unlock(&span.speciallock)
+                       releasem(mp)
+                       return s
+               }
+               t = &s.next
+       }
+       unlock(&span.speciallock)
+       releasem(mp)
+       return nil
+}
+
+// Adds a finalizer to the object p.  Returns true if it succeeded.
+func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *ptrtype) bool {
+       lock(&mheap_.speciallock)
+       s := (*specialfinalizer)(fixAlloc_Alloc(&mheap_.specialfinalizeralloc))
+       unlock(&mheap_.speciallock)
+       s.special.kind = _KindSpecialFinalizer
+       s.fn = f
+       s.nret = nret
+       s.fint = fint
+       s.ot = ot
+       if addspecial(p, &s.special) {
+               return true
+       }
+
+       // There was an old finalizer
+       lock(&mheap_.speciallock)
+       fixAlloc_Free(&mheap_.specialfinalizeralloc, (unsafe.Pointer)(s))
+       unlock(&mheap_.speciallock)
+       return false
+}
+
+// Removes the finalizer (if any) from the object p.
+func removefinalizer(p unsafe.Pointer) {
+       s := (*specialfinalizer)(unsafe.Pointer(removespecial(p, _KindSpecialFinalizer)))
+       if s == nil {
+               return // there wasn't a finalizer to remove
+       }
+       lock(&mheap_.speciallock)
+       fixAlloc_Free(&mheap_.specialfinalizeralloc, (unsafe.Pointer)(s))
+       unlock(&mheap_.speciallock)
+}
+
+// Set the heap profile bucket associated with addr to b.
+func setprofilebucket(p unsafe.Pointer, b *bucket) {
+       lock(&mheap_.speciallock)
+       s := (*specialprofile)(fixAlloc_Alloc(&mheap_.specialprofilealloc))
+       unlock(&mheap_.speciallock)
+       s.special.kind = _KindSpecialProfile
+       s.b = b
+       if !addspecial(p, &s.special) {
+               gothrow("setprofilebucket: profile already set")
+       }
+}
+
+// Do whatever cleanup needs to be done to deallocate s.  It has
+// already been unlinked from the MSpan specials list.
+// Returns true if we should keep working on deallocating p.
+func freespecial(s *special, p unsafe.Pointer, size uintptr, freed bool) bool {
+       switch s.kind {
+       case _KindSpecialFinalizer:
+               sf := (*specialfinalizer)(unsafe.Pointer(s))
+               queuefinalizer(p, sf.fn, sf.nret, sf.fint, sf.ot)
+               lock(&mheap_.speciallock)
+               fixAlloc_Free(&mheap_.specialfinalizeralloc, (unsafe.Pointer)(sf))
+               unlock(&mheap_.speciallock)
+               return false // don't free p until finalizer is done
+       case _KindSpecialProfile:
+               sp := (*specialprofile)(unsafe.Pointer(s))
+               mProf_Free(sp.b, size, freed)
+               lock(&mheap_.speciallock)
+               fixAlloc_Free(&mheap_.specialprofilealloc, (unsafe.Pointer)(sp))
+               unlock(&mheap_.speciallock)
+               return true
+       default:
+               gothrow("bad special kind")
+               panic("not reached")
+       }
+}
index d409c6c306a3fe9f32ae5a43ceac739b785f0eaf..ba989b1b86981d64e3b1f8bc8615dedf619d6856 100644 (file)
@@ -190,8 +190,6 @@ func stkbucket(typ bucketType, size uintptr, stk []uintptr, alloc bool) *bucket
        return b
 }
 
-func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer
-
 func eqslice(x, y []uintptr) bool {
        if len(x) != len(y) {
                return false
@@ -246,16 +244,9 @@ func mProf_Malloc(p unsafe.Pointer, size uintptr) {
        // This reduces potential contention and chances of deadlocks.
        // Since the object must be alive during call to mProf_Malloc,
        // it's fine to do this non-atomically.
-       setprofilebucket(p, b)
-}
-
-func setprofilebucket_m() // mheap.c
-
-func setprofilebucket(p unsafe.Pointer, b *bucket) {
-       g := getg()
-       g.m.ptrarg[0] = p
-       g.m.ptrarg[1] = unsafe.Pointer(b)
-       onM(setprofilebucket_m)
+       systemstack(func() {
+               setprofilebucket(p, b)
+       })
 }
 
 // Called when freeing a profiled block.
@@ -519,8 +510,6 @@ func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
        return
 }
 
-var allgs []*g // proc.c
-
 // GoroutineProfile returns n, the number of records in the active goroutine stack profile.
 // If len(p) >= n, GoroutineProfile copies the profile into p and returns n, true.
 // If len(p) < n, GoroutineProfile does not change p and returns n, false.
@@ -534,7 +523,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
                gp := getg()
                semacquire(&worldsema, false)
                gp.m.gcing = 1
-               onM(stoptheworld)
+               systemstack(stoptheworld)
 
                n = NumGoroutine()
                if n <= len(p) {
@@ -542,7 +531,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
                        r := p
                        sp := getcallersp(unsafe.Pointer(&p))
                        pc := getcallerpc(unsafe.Pointer(&p))
-                       onM(func() {
+                       systemstack(func() {
                                saveg(pc, sp, gp, &r[0])
                        })
                        r = r[1:]
@@ -557,7 +546,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
 
                gp.m.gcing = 0
                semrelease(&worldsema)
-               onM(starttheworld)
+               systemstack(starttheworld)
        }
 
        return n, ok
@@ -581,7 +570,7 @@ func Stack(buf []byte, all bool) int {
                semacquire(&worldsema, false)
                mp.gcing = 1
                releasem(mp)
-               onM(stoptheworld)
+               systemstack(stoptheworld)
                if mp != acquirem() {
                        gothrow("Stack: rescheduled")
                }
@@ -591,7 +580,7 @@ func Stack(buf []byte, all bool) int {
        if len(buf) > 0 {
                sp := getcallersp(unsafe.Pointer(&buf))
                pc := getcallerpc(unsafe.Pointer(&buf))
-               onM(func() {
+               systemstack(func() {
                        g0 := getg()
                        g0.writebuf = buf[0:0:len(buf)]
                        goroutineheader(gp)
@@ -607,7 +596,7 @@ func Stack(buf []byte, all bool) int {
        if all {
                mp.gcing = 0
                semrelease(&worldsema)
-               onM(starttheworld)
+               systemstack(starttheworld)
        }
        releasem(mp)
        return n
@@ -630,7 +619,7 @@ func tracealloc(p unsafe.Pointer, size uintptr, typ *_type) {
                goroutineheader(gp)
                pc := getcallerpc(unsafe.Pointer(&p))
                sp := getcallersp(unsafe.Pointer(&p))
-               onM(func() {
+               systemstack(func() {
                        traceback(pc, sp, 0, gp)
                })
        } else {
@@ -650,7 +639,7 @@ func tracefree(p unsafe.Pointer, size uintptr) {
        goroutineheader(gp)
        pc := getcallerpc(unsafe.Pointer(&p))
        sp := getcallersp(unsafe.Pointer(&p))
-       onM(func() {
+       systemstack(func() {
                traceback(pc, sp, 0, gp)
        })
        print("\n")
diff --git a/src/runtime/msize.c b/src/runtime/msize.c
deleted file mode 100644 (file)
index 7cb65da..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Malloc small size classes.
-//
-// See malloc.h for overview.
-//
-// The size classes are chosen so that rounding an allocation
-// request up to the next size class wastes at most 12.5% (1.125x).
-//
-// Each size class has its own page count that gets allocated
-// and chopped up when new objects of the size class are needed.
-// That page count is chosen so that chopping up the run of
-// pages into objects of the given size wastes at most 12.5% (1.125x)
-// of the memory.  It is not necessary that the cutoff here be
-// the same as above.
-//
-// The two sources of waste multiply, so the worst possible case
-// for the above constraints would be that allocations of some
-// size might have a 26.6% (1.266x) overhead.
-// In practice, only one of the wastes comes into play for a
-// given size (sizes < 512 waste mainly on the round-up,
-// sizes > 512 waste mainly on the page chopping).
-//
-// TODO(rsc): Compute max waste for any given size.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "textflag.h"
-
-#pragma dataflag NOPTR
-int32 runtime·class_to_size[NumSizeClasses];
-#pragma dataflag NOPTR
-int32 runtime·class_to_allocnpages[NumSizeClasses];
-
-// The SizeToClass lookup is implemented using two arrays,
-// one mapping sizes <= 1024 to their class and one mapping
-// sizes >= 1024 and <= MaxSmallSize to their class.
-// All objects are 8-aligned, so the first array is indexed by
-// the size divided by 8 (rounded up).  Objects >= 1024 bytes
-// are 128-aligned, so the second array is indexed by the
-// size divided by 128 (rounded up).  The arrays are filled in
-// by InitSizes.
-
-#pragma dataflag NOPTR
-int8 runtime·size_to_class8[1024/8 + 1];
-#pragma dataflag NOPTR
-int8 runtime·size_to_class128[(MaxSmallSize-1024)/128 + 1];
-
-void runtime·testdefersizes(void);
-
-int32
-runtime·SizeToClass(int32 size)
-{
-       if(size > MaxSmallSize)
-               runtime·throw("SizeToClass - invalid size");
-       if(size > 1024-8)
-               return runtime·size_to_class128[(size-1024+127) >> 7];
-       return runtime·size_to_class8[(size+7)>>3];
-}
-
-void
-runtime·InitSizes(void)
-{
-       int32 align, sizeclass, size, nextsize, n;
-       uint32 i;
-       uintptr allocsize, npages;
-
-       // Initialize the runtime·class_to_size table (and choose class sizes in the process).
-       runtime·class_to_size[0] = 0;
-       sizeclass = 1;  // 0 means no class
-       align = 8;
-       for(size = align; size <= MaxSmallSize; size += align) {
-               if((size&(size-1)) == 0) {      // bump alignment once in a while
-                       if(size >= 2048)
-                               align = 256;
-                       else if(size >= 128)
-                               align = size / 8;
-                       else if(size >= 16)
-                               align = 16;     // required for x86 SSE instructions, if we want to use them
-               }
-               if((align&(align-1)) != 0)
-                       runtime·throw("InitSizes - bug");
-
-               // Make the allocnpages big enough that
-               // the leftover is less than 1/8 of the total,
-               // so wasted space is at most 12.5%.
-               allocsize = PageSize;
-               while(allocsize%size > allocsize/8)
-                       allocsize += PageSize;
-               npages = allocsize >> PageShift;
-
-               // If the previous sizeclass chose the same
-               // allocation size and fit the same number of
-               // objects into the page, we might as well
-               // use just this size instead of having two
-               // different sizes.
-               if(sizeclass > 1 &&
-                       npages == runtime·class_to_allocnpages[sizeclass-1] &&
-                       allocsize/size == allocsize/runtime·class_to_size[sizeclass-1]) {
-                       runtime·class_to_size[sizeclass-1] = size;
-                       continue;
-               }
-
-               runtime·class_to_allocnpages[sizeclass] = npages;
-               runtime·class_to_size[sizeclass] = size;
-               sizeclass++;
-       }
-       if(sizeclass != NumSizeClasses) {
-               runtime·printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses);
-               runtime·throw("InitSizes - bad NumSizeClasses");
-       }
-
-       // Initialize the size_to_class tables.
-       nextsize = 0;
-       for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
-               for(; nextsize < 1024 && nextsize <= runtime·class_to_size[sizeclass]; nextsize+=8)
-                       runtime·size_to_class8[nextsize/8] = sizeclass;
-               if(nextsize >= 1024)
-                       for(; nextsize <= runtime·class_to_size[sizeclass]; nextsize += 128)
-                               runtime·size_to_class128[(nextsize-1024)/128] = sizeclass;
-       }
-
-       // Double-check SizeToClass.
-       if(0) {
-               for(n=0; n < MaxSmallSize; n++) {
-                       sizeclass = runtime·SizeToClass(n);
-                       if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime·class_to_size[sizeclass] < n) {
-                               runtime·printf("size=%d sizeclass=%d runtime·class_to_size=%d\n", n, sizeclass, runtime·class_to_size[sizeclass]);
-                               runtime·printf("incorrect SizeToClass");
-                               goto dump;
-                       }
-                       if(sizeclass > 1 && runtime·class_to_size[sizeclass-1] >= n) {
-                               runtime·printf("size=%d sizeclass=%d runtime·class_to_size=%d\n", n, sizeclass, runtime·class_to_size[sizeclass]);
-                               runtime·printf("SizeToClass too big");
-                               goto dump;
-                       }
-               }
-       }
-
-       runtime·testdefersizes();
-
-       // Copy out for statistics table.
-       for(i=0; i<nelem(runtime·class_to_size); i++)
-               mstats.by_size[i].size = runtime·class_to_size[i];
-       return;
-
-dump:
-       if(1){
-               runtime·printf("NumSizeClasses=%d\n", NumSizeClasses);
-               runtime·printf("runtime·class_to_size:");
-               for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++)
-                       runtime·printf(" %d", runtime·class_to_size[sizeclass]);
-               runtime·printf("\n\n");
-               runtime·printf("size_to_class8:");
-               for(i=0; i<nelem(runtime·size_to_class8); i++)
-                       runtime·printf(" %d=>%d(%d)\n", i*8, runtime·size_to_class8[i],
-                               runtime·class_to_size[runtime·size_to_class8[i]]);
-               runtime·printf("\n");
-               runtime·printf("size_to_class128:");
-               for(i=0; i<nelem(runtime·size_to_class128); i++)
-                       runtime·printf(" %d=>%d(%d)\n", i*128, runtime·size_to_class128[i],
-                               runtime·class_to_size[runtime·size_to_class128[i]]);
-               runtime·printf("\n");
-       }
-       runtime·throw("InitSizes failed");
-}
-
-// Returns size of the memory block that mallocgc will allocate if you ask for the size.
-uintptr
-runtime·roundupsize(uintptr size)
-{
-       if(size < MaxSmallSize) {
-               if(size <= 1024-8)
-                       return runtime·class_to_size[runtime·size_to_class8[(size+7)>>3]];
-               else
-                       return runtime·class_to_size[runtime·size_to_class128[(size-1024+127) >> 7]];
-       }
-       if(size + PageSize < size)
-               return size;
-       return ROUND(size, PageSize);
-}
diff --git a/src/runtime/msize.go b/src/runtime/msize.go
new file mode 100644 (file)
index 0000000..aa2b43e
--- /dev/null
@@ -0,0 +1,174 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Malloc small size classes.
+//
+// See malloc.h for overview.
+//
+// The size classes are chosen so that rounding an allocation
+// request up to the next size class wastes at most 12.5% (1.125x).
+//
+// Each size class has its own page count that gets allocated
+// and chopped up when new objects of the size class are needed.
+// That page count is chosen so that chopping up the run of
+// pages into objects of the given size wastes at most 12.5% (1.125x)
+// of the memory.  It is not necessary that the cutoff here be
+// the same as above.
+//
+// The two sources of waste multiply, so the worst possible case
+// for the above constraints would be that allocations of some
+// size might have a 26.6% (1.266x) overhead.
+// In practice, only one of the wastes comes into play for a
+// given size (sizes < 512 waste mainly on the round-up,
+// sizes > 512 waste mainly on the page chopping).
+//
+// TODO(rsc): Compute max waste for any given size.
+
+package runtime
+
+//var class_to_size [_NumSizeClasses]int32
+//var class_to_allocnpages [_NumSizeClasses]int32
+
+// The SizeToClass lookup is implemented using two arrays,
+// one mapping sizes <= 1024 to their class and one mapping
+// sizes >= 1024 and <= MaxSmallSize to their class.
+// All objects are 8-aligned, so the first array is indexed by
+// the size divided by 8 (rounded up).  Objects >= 1024 bytes
+// are 128-aligned, so the second array is indexed by the
+// size divided by 128 (rounded up).  The arrays are filled in
+// by InitSizes.
+//var size_to_class8 [1024/8 + 1]int8
+//var size_to_class128 [(_MaxSmallSize-1024)/128 + 1]int8
+
+func sizeToClass(size int32) int32 {
+       if size > _MaxSmallSize {
+               gothrow("SizeToClass - invalid size")
+       }
+       if size > 1024-8 {
+               return int32(size_to_class128[(size-1024+127)>>7])
+       }
+       return int32(size_to_class8[(size+7)>>3])
+}
+
+func initSizes() {
+       // Initialize the runtime·class_to_size table (and choose class sizes in the process).
+       class_to_size[0] = 0
+       sizeclass := 1 // 0 means no class
+       align := 8
+       for size := align; size <= _MaxSmallSize; size += align {
+               if size&(size-1) == 0 { // bump alignment once in a while
+                       if size >= 2048 {
+                               align = 256
+                       } else if size >= 128 {
+                               align = size / 8
+                       } else if size >= 16 {
+                               align = 16 // required for x86 SSE instructions, if we want to use them
+                       }
+               }
+               if align&(align-1) != 0 {
+                       gothrow("InitSizes - bug")
+               }
+
+               // Make the allocnpages big enough that
+               // the leftover is less than 1/8 of the total,
+               // so wasted space is at most 12.5%.
+               allocsize := _PageSize
+               for allocsize%size > allocsize/8 {
+                       allocsize += _PageSize
+               }
+               npages := allocsize >> _PageShift
+
+               // If the previous sizeclass chose the same
+               // allocation size and fit the same number of
+               // objects into the page, we might as well
+               // use just this size instead of having two
+               // different sizes.
+               if sizeclass > 1 && npages == int(class_to_allocnpages[sizeclass-1]) && allocsize/size == allocsize/int(class_to_size[sizeclass-1]) {
+                       class_to_size[sizeclass-1] = int32(size)
+                       continue
+               }
+
+               class_to_allocnpages[sizeclass] = int32(npages)
+               class_to_size[sizeclass] = int32(size)
+               sizeclass++
+       }
+       if sizeclass != _NumSizeClasses {
+               print("sizeclass=", sizeclass, " NumSizeClasses=", _NumSizeClasses, "\n")
+               gothrow("InitSizes - bad NumSizeClasses")
+       }
+
+       // Initialize the size_to_class tables.
+       nextsize := 0
+       for sizeclass = 1; sizeclass < _NumSizeClasses; sizeclass++ {
+               for ; nextsize < 1024 && nextsize <= int(class_to_size[sizeclass]); nextsize += 8 {
+                       size_to_class8[nextsize/8] = int8(sizeclass)
+               }
+               if nextsize >= 1024 {
+                       for ; nextsize <= int(class_to_size[sizeclass]); nextsize += 128 {
+                               size_to_class128[(nextsize-1024)/128] = int8(sizeclass)
+                       }
+               }
+       }
+
+       // Double-check SizeToClass.
+       if false {
+               for n := int32(0); n < _MaxSmallSize; n++ {
+                       sizeclass := sizeToClass(n)
+                       if sizeclass < 1 || sizeclass >= _NumSizeClasses || class_to_size[sizeclass] < n {
+                               print("size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
+                               print("incorrect SizeToClass\n")
+                               goto dump
+                       }
+                       if sizeclass > 1 && class_to_size[sizeclass-1] >= n {
+                               print("size=", n, " sizeclass=", sizeclass, " runtime·class_to_size=", class_to_size[sizeclass], "\n")
+                               print("SizeToClass too big\n")
+                               goto dump
+                       }
+               }
+       }
+
+       testdefersizes()
+
+       // Copy out for statistics table.
+       for i := 0; i < len(class_to_size); i++ {
+               memstats.by_size[i].size = uint32(class_to_size[i])
+       }
+       return
+
+dump:
+       if true {
+               print("NumSizeClasses=", _NumSizeClasses, "\n")
+               print("runtime·class_to_size:")
+               for sizeclass = 0; sizeclass < _NumSizeClasses; sizeclass++ {
+                       print(" ", class_to_size[sizeclass], "")
+               }
+               print("\n\n")
+               print("size_to_class8:")
+               for i := 0; i < len(size_to_class8); i++ {
+                       print(" ", i*8, "=>", size_to_class8[i], "(", class_to_size[size_to_class8[i]], ")\n")
+               }
+               print("\n")
+               print("size_to_class128:")
+               for i := 0; i < len(size_to_class128); i++ {
+                       print(" ", i*128, "=>", size_to_class128[i], "(", class_to_size[size_to_class128[i]], ")\n")
+               }
+               print("\n")
+       }
+       gothrow("InitSizes failed")
+}
+
+// Returns size of the memory block that mallocgc will allocate if you ask for the size.
+func roundupsize(size uintptr) uintptr {
+       if size < _MaxSmallSize {
+               if size <= 1024-8 {
+                       return uintptr(class_to_size[size_to_class8[(size+7)>>3]])
+               } else {
+                       return uintptr(class_to_size[size_to_class128[(size-1024+127)>>7]])
+               }
+       }
+       if size+_PageSize < size {
+               return size
+       }
+       return round(size, _PageSize)
+}
index 3456e0208104a09796b267a9d2acd64c64db1440..7a99f18ad214e0a6300fb11995ff346e982805b2 100644 (file)
@@ -49,14 +49,14 @@ type pollDesc struct {
        lock    mutex // protectes the following fields
        fd      uintptr
        closing bool
-       seq     uintptr        // protects from stale timers and ready notifications
-       rg      uintptr        // pdReady, pdWait, G waiting for read or nil
-       rt      timer          // read deadline timer (set if rt.f != nil)
-       rd      int64          // read deadline
-       wg      uintptr        // pdReady, pdWait, G waiting for write or nil
-       wt      timer          // write deadline timer
-       wd      int64          // write deadline
-       user    unsafe.Pointer // user settable cookie
+       seq     uintptr // protects from stale timers and ready notifications
+       rg      uintptr // pdReady, pdWait, G waiting for read or nil
+       rt      timer   // read deadline timer (set if rt.f != nil)
+       rd      int64   // read deadline
+       wg      uintptr // pdReady, pdWait, G waiting for write or nil
+       wt      timer   // write deadline timer
+       wd      int64   // write deadline
+       user    uint32  // user settable cookie
 }
 
 type pollCache struct {
@@ -72,7 +72,7 @@ type pollCache struct {
 var pollcache pollCache
 
 func netpollServerInit() {
-       onM(netpollinit)
+       netpollinit()
 }
 
 func netpollOpen(fd uintptr) (*pollDesc, int) {
@@ -94,9 +94,7 @@ func netpollOpen(fd uintptr) (*pollDesc, int) {
        unlock(&pd.lock)
 
        var errno int32
-       onM(func() {
-               errno = netpollopen(fd, pd)
-       })
+       errno = netpollopen(fd, pd)
        return pd, int(errno)
 }
 
@@ -110,9 +108,7 @@ func netpollClose(pd *pollDesc) {
        if pd.rg != 0 && pd.rg != pdReady {
                gothrow("netpollClose: blocked read on closing descriptor")
        }
-       onM(func() {
-               netpollclose(uintptr(pd.fd))
-       })
+       netpollclose(uintptr(pd.fd))
        pollcache.free(pd)
 }
 
@@ -143,9 +139,7 @@ func netpollWait(pd *pollDesc, mode int) int {
        }
        // As for now only Solaris uses level-triggered IO.
        if GOOS == "solaris" {
-               onM(func() {
-                       netpollarm(pd, mode)
-               })
+               netpollarm(pd, mode)
        }
        for !netpollblock(pd, int32(mode), false) {
                err = netpollcheckerr(pd, int32(mode))
@@ -263,26 +257,6 @@ func netpollUnblock(pd *pollDesc) {
        }
 }
 
-func netpollfd(pd *pollDesc) uintptr {
-       return pd.fd
-}
-
-func netpolluser(pd *pollDesc) *unsafe.Pointer {
-       return &pd.user
-}
-
-func netpollclosing(pd *pollDesc) bool {
-       return pd.closing
-}
-
-func netpolllock(pd *pollDesc) {
-       lock(&pd.lock)
-}
-
-func netpollunlock(pd *pollDesc) {
-       unlock(&pd.lock)
-}
-
 // make pd ready, newly runnable goroutines (if any) are returned in rg/wg
 func netpollready(gpp **g, pd *pollDesc, mode int32) {
        var rg, wg *g
@@ -343,8 +317,7 @@ func netpollblock(pd *pollDesc, mode int32, waitio bool) bool {
        // this is necessary because runtime_pollUnblock/runtime_pollSetDeadline/deadlineimpl
        // do the opposite: store to closing/rd/wd, membarrier, load of rg/wg
        if waitio || netpollcheckerr(pd, mode) == 0 {
-               f := netpollblockcommit
-               gopark(**(**unsafe.Pointer)(unsafe.Pointer(&f)), unsafe.Pointer(gpp), "IO wait")
+               gopark(netpollblockcommit, unsafe.Pointer(gpp), "IO wait")
        }
        // be careful to not lose concurrent READY notification
        old := xchguintptr(gpp, 0)
similarity index 55%
rename from src/runtime/netpoll_solaris.c
rename to src/runtime/netpoll_solaris.go
index d422719cf1abe9b0f05acf0ce6241b46a296637b..40e8a1a6516dacddf5cc4a9cef47d39bda349dab 100644 (file)
@@ -2,13 +2,12 @@
 // 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
+package runtime
+
+import "unsafe"
 
 // Solaris runtime-integrated network poller.
-// 
+//
 // Solaris uses event ports for scalable network I/O. Event
 // ports are level-triggered, unlike epoll and kqueue which
 // can be configured in both level-triggered and edge-triggered
@@ -18,7 +17,7 @@
 // events for that descriptor. When doing this we must keep track of
 // what kind of events the goroutines are currently interested in,
 // for example a fd may be open both for reading and writing.
-// 
+//
 // A description of the high level operation of this code
 // follows. Networking code will get a file descriptor by some means
 // and will register it with the netpolling mechanism by a code path
@@ -29,7 +28,7 @@
 // readiness notification at some point in the future. If I/O becomes
 // ready when nobody is listening, when we finally care about it,
 // nobody will tell us anymore.
-// 
+//
 // Beside calling runtime·netpollopen, the networking code paths
 // will call runtime·netpollarm each time goroutines are interested
 // in doing network I/O. Because now we know what kind of I/O we
@@ -39,7 +38,7 @@
 // when we now call port_associate, we will unblock the main poller
 // loop (in runtime·netpoll) right away if the socket is actually
 // ready for I/O.
-// 
+//
 // The main poller loop runs in its own thread waiting for events
 // using port_getn. When an event happens, it will tell the scheduler
 // about it using runtime·netpollready. Besides doing this, it must
@@ -47,7 +46,7 @@
 // notification with the file descriptor. Failing to do this would
 // mean each notification will prevent concurrent code using the
 // same file descriptor in parallel.
-// 
+//
 // The logic dealing with re-associations is encapsulated in
 // runtime·netpollupdate. This function takes care to associate the
 // descriptor only with the subset of events that were previously
@@ -56,7 +55,7 @@
 // are level triggered so it would cause a busy loop. Instead, that
 // association is effected only by the runtime·netpollarm code path,
 // when Go code actually asks for I/O.
-// 
+//
 // The open and arming mechanisms are serialized using the lock
 // inside PollDesc. This is required because the netpoll loop runs
 // asynchonously in respect to other Go code and by the time we get
 // again we know for sure we are always talking about the same file
 // descriptor and can safely access the data we want (the event set).
 
-#pragma dynimport libc·fcntl fcntl "libc.so"
-#pragma dynimport libc·port_create port_create "libc.so"
-#pragma dynimport libc·port_associate port_associate "libc.so"
-#pragma dynimport libc·port_dissociate port_dissociate "libc.so"
-#pragma dynimport libc·port_getn port_getn "libc.so"
-extern uintptr libc·fcntl;
-extern uintptr libc·port_create;
-extern uintptr libc·port_associate;
-extern uintptr libc·port_dissociate;
-extern uintptr libc·port_getn;
-
-#define errno (*g->m->perrno)
+//go:cgo_import_dynamic libc_port_create port_create "libc.so"
+//go:cgo_import_dynamic libc_port_associate port_associate "libc.so"
+//go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so"
+//go:cgo_import_dynamic libc_port_getn port_getn "libc.so"
+
+//go:linkname libc_port_create libc_port_create
+//go:linkname libc_port_associate libc_port_associate
+//go:linkname libc_port_dissociate libc_port_dissociate
+//go:linkname libc_port_getn libc_port_getn
+
+var (
+       libc_port_create,
+       libc_port_associate,
+       libc_port_dissociate,
+       libc_port_getn libcFunc
+)
+
+func errno() int32 {
+       return *getg().m.perrno
+}
 
-int32
-runtime·fcntl(int32 fd, int32 cmd, uintptr arg)
-{
-       return runtime·sysvicall3(libc·fcntl, (uintptr)fd, (uintptr)cmd, (uintptr)arg);
+func fcntl(fd, cmd int32, arg uintptr) int32 {
+       return int32(sysvicall3(libc_fcntl, uintptr(fd), uintptr(cmd), arg))
 }
 
-int32
-runtime·port_create(void)
-{
-       return runtime·sysvicall0(libc·port_create);
+func port_create() int32 {
+       return int32(sysvicall0(libc_port_create))
 }
 
-int32
-runtime·port_associate(int32 port, int32 source, uintptr object, int32 events, uintptr user)
-{
-       return runtime·sysvicall5(libc·port_associate, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
+func port_associate(port, source int32, object uintptr, events uint32, user uintptr) int32 {
+       return int32(sysvicall5(libc_port_associate, uintptr(port), uintptr(source), object, uintptr(events), user))
 }
 
-int32
-runtime·port_dissociate(int32 port, int32 source, uintptr object)
-{
-       return runtime·sysvicall3(libc·port_dissociate, (uintptr)port, (uintptr)source, object);
+func port_dissociate(port, source int32, object uintptr) int32 {
+       return int32(sysvicall3(libc_port_dissociate, uintptr(port), uintptr(source), object))
 }
 
-int32
-runtime·port_getn(int32 port, PortEvent *evs, uint32 max, uint32 *nget, Timespec *timeout)
-{
-       return runtime·sysvicall5(libc·port_getn, (uintptr)port, (uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
+func port_getn(port int32, evs *portevent, max uint32, nget *uint32, timeout *timespec) int32 {
+       return int32(sysvicall5(libc_port_getn, uintptr(port), uintptr(unsafe.Pointer(evs)), uintptr(max), uintptr(unsafe.Pointer(nget)), uintptr(unsafe.Pointer(timeout))))
 }
 
-static int32 portfd = -1;
+var portfd int32 = -1
 
-void
-runtime·netpollinit(void)
-{
-       if((portfd = runtime·port_create()) >= 0) {
-               runtime·fcntl(portfd, F_SETFD, FD_CLOEXEC);
-               return;
+func netpollinit() {
+       portfd = port_create()
+       if portfd >= 0 {
+               fcntl(portfd, _F_SETFD, _FD_CLOEXEC)
+               return
        }
 
-       runtime·printf("netpollinit: failed to create port (%d)\n", errno);
-       runtime·throw("netpollinit: failed to create port");
+       print("netpollinit: failed to create port (", errno(), ")\n")
+       gothrow("netpollinit: failed to create port")
 }
 
-int32
-runtime·netpollopen(uintptr fd, PollDesc *pd)
-{
-       int32 r;
-
-       runtime·netpolllock(pd);
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+       lock(&pd.lock)
        // We don't register for any specific type of events yet, that's
        // netpollarm's job. We merely ensure we call port_associate before
        // asynchonous connect/accept completes, so when we actually want
        // to do any I/O, the call to port_associate (from netpollarm,
        // with the interested event set) will unblock port_getn right away
        // because of the I/O readiness notification.
-       *runtime·netpolluser(pd) = 0;
-       r = runtime·port_associate(portfd, PORT_SOURCE_FD, fd, 0, (uintptr)pd);
-       runtime·netpollunlock(pd);
-       return r;
+       pd.user = 0
+       r := port_associate(portfd, _PORT_SOURCE_FD, fd, 0, uintptr(unsafe.Pointer(pd)))
+       unlock(&pd.lock)
+       return r
 }
 
-int32
-runtime·netpollclose(uintptr fd)
-{
-       return runtime·port_dissociate(portfd, PORT_SOURCE_FD, fd);
+func netpollclose(fd uintptr) int32 {
+       return port_dissociate(portfd, _PORT_SOURCE_FD, fd)
 }
 
 // Updates the association with a new set of interested events. After
 // this call, port_getn will return one and only one event for that
 // particular descriptor, so this function needs to be called again.
-void
-runtime·netpollupdate(PollDesc* pd, uint32 set, uint32 clear)
-{
-       uint32 *ep, old, events;
-       uintptr fd = runtime·netpollfd(pd);
-       ep = (uint32*)runtime·netpolluser(pd);
-
-       if(runtime·netpollclosing(pd))
-               return;
+func netpollupdate(pd *pollDesc, set, clear uint32) {
+       if pd.closing {
+               return
+       }
 
-       old = *ep;
-       events = (old & ~clear) | set;
-       if(old == events)
-               return;
+       old := pd.user
+       events := (old & ^clear) | set
+       if old == events {
+               return
+       }
 
-       if(events && runtime·port_associate(portfd, PORT_SOURCE_FD, fd, events, (uintptr)pd) != 0) {
-               runtime·printf("netpollupdate: failed to associate (%d)\n", errno);
-               runtime·throw("netpollupdate: failed to associate");
-       } 
-       *ep = events;
+       if events != 0 && port_associate(portfd, _PORT_SOURCE_FD, pd.fd, events, uintptr(unsafe.Pointer(pd))) != 0 {
+               print("netpollupdate: failed to associate (", errno(), ")\n")
+               gothrow("netpollupdate: failed to associate")
+       }
+       pd.user = events
 }
 
 // subscribe the fd to the port such that port_getn will return one event.
-void
-runtime·netpollarm(PollDesc* pd, int32 mode)
-{
-       runtime·netpolllock(pd);
-       switch(mode) {
+func netpollarm(pd *pollDesc, mode int) {
+       lock(&pd.lock)
+       switch mode {
        case 'r':
-               runtime·netpollupdate(pd, POLLIN, 0);
-               break;
+               netpollupdate(pd, _POLLIN, 0)
        case 'w':
-               runtime·netpollupdate(pd, POLLOUT, 0);
-               break;
+               netpollupdate(pd, _POLLOUT, 0)
        default:
-               runtime·throw("netpollarm: bad mode");
+               gothrow("netpollarm: bad mode")
        }
-       runtime·netpollunlock(pd);
+       unlock(&pd.lock)
 }
 
+// netpolllasterr holds the last error code returned by port_getn to prevent log spamming
+var netpolllasterr int32
+
 // polls for ready network connections
 // returns list of goroutines that become runnable
-G*
-runtime·netpoll(bool block)
-{
-       static int32 lasterr;
-       PortEvent events[128], *ev;
-       PollDesc *pd;
-       int32 i, mode, clear;
-       uint32 n;
-       Timespec *wait = nil, zero;
-       G *gp;
-
-       if(portfd == -1)
-               return (nil);
+func netpoll(block bool) (gp *g) {
+       if portfd == -1 {
+               return
+       }
 
-       if(!block) {
-               zero.tv_sec = 0;
-               zero.tv_nsec = 0;
-               wait = &zero;
+       var wait *timespec
+       var zero timespec
+       if !block {
+               wait = &zero
        }
 
+       var events [128]portevent
 retry:
-       n = 1;
-       if(runtime·port_getn(portfd, events, nelem(events), &n, wait) < 0) {
-               if(errno != EINTR && errno != lasterr) {
-                       lasterr = errno;
-                       runtime·printf("runtime: port_getn on fd %d failed with %d\n", portfd, errno);
+       var n uint32 = 1
+       if port_getn(portfd, &events[0], uint32(len(events)), &n, wait) < 0 {
+               if e := errno(); e != _EINTR && e != netpolllasterr {
+                       netpolllasterr = e
+                       print("runtime: port_getn on fd ", portfd, " failed with ", e, "\n")
                }
-               goto retry;
+               goto retry
        }
 
-       gp = nil;
-       for(i = 0; i < n; i++) {
-               ev = &events[i];
+       gp = nil
+       for i := 0; i < int(n); i++ {
+               ev := &events[i]
 
-               if(ev->portev_events == 0)
-                       continue;
-               pd = (PollDesc *)ev->portev_user;
+               if ev.portev_events == 0 {
+                       continue
+               }
+               pd := (*pollDesc)(unsafe.Pointer(ev.portev_user))
 
-               mode = 0;
-               clear = 0;
-               if(ev->portev_events & (POLLIN|POLLHUP|POLLERR)) {
-                       mode += 'r';
-                       clear |= POLLIN;
+               var mode, clear int32
+               if (ev.portev_events & (_POLLIN | _POLLHUP | _POLLERR)) != 0 {
+                       mode += 'r'
+                       clear |= _POLLIN
                }
-               if(ev->portev_events & (POLLOUT|POLLHUP|POLLERR)) {
-                       mode += 'w';
-                       clear |= POLLOUT;
+               if (ev.portev_events & (_POLLOUT | _POLLHUP | _POLLERR)) != 0 {
+                       mode += 'w'
+                       clear |= _POLLOUT
                }
                // To effect edge-triggered events, we need to be sure to
                // update our association with whatever events were not
@@ -248,17 +225,19 @@ retry:
                // for POLLIN|POLLOUT, and we get POLLIN, besides waking
                // the goroutine interested in POLLIN we have to not forget
                // about the one interested in POLLOUT.
-               if(clear != 0) {
-                       runtime·netpolllock(pd);
-                       runtime·netpollupdate(pd, 0, clear);
-                       runtime·netpollunlock(pd);
+               if clear != 0 {
+                       lock(&pd.lock)
+                       netpollupdate(pd, 0, uint32(clear))
+                       unlock(&pd.lock)
                }
 
-               if(mode)
-                       runtime·netpollready(&gp, pd, mode);
+               if mode != 0 {
+                       netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
+               }
        }
 
-       if(block && gp == nil)
-               goto retry;
-       return gp;
+       if block && gp == nil {
+               goto retry
+       }
+       return gp
 }
diff --git a/src/runtime/netpoll_windows.c b/src/runtime/netpoll_windows.c
deleted file mode 100644 (file)
index 64da41a..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-#define DWORD_MAX 0xffffffff
-
-#pragma dynimport runtime·CreateIoCompletionPort CreateIoCompletionPort "kernel32.dll"
-#pragma dynimport runtime·GetQueuedCompletionStatus GetQueuedCompletionStatus "kernel32.dll"
-#pragma dynimport runtime·WSAGetOverlappedResult WSAGetOverlappedResult "ws2_32.dll"
-
-extern void *runtime·CreateIoCompletionPort;
-extern void *runtime·GetQueuedCompletionStatus;
-extern void *runtime·WSAGetOverlappedResult;
-
-#define INVALID_HANDLE_VALUE ((uintptr)-1)
-
-// net_op must be the same as beginning of net.operation. Keep these in sync.
-typedef struct net_op net_op;
-struct net_op
-{
-       // used by windows
-       Overlapped      o;
-       // used by netpoll
-       PollDesc*       pd;
-       int32   mode;
-       int32   errno;
-       uint32  qty;
-};
-
-typedef struct OverlappedEntry OverlappedEntry;
-struct OverlappedEntry
-{
-       uintptr key;
-       net_op* op;  // In reality it's Overlapped*, but we cast it to net_op* anyway.
-       uintptr internal;
-       uint32  qty;
-};
-
-static void handlecompletion(G **gpp, net_op *o, int32 errno, uint32 qty);
-
-static uintptr iocphandle = INVALID_HANDLE_VALUE;  // completion port io handle
-
-void
-runtime·netpollinit(void)
-{
-       iocphandle = (uintptr)runtime·stdcall4(runtime·CreateIoCompletionPort, INVALID_HANDLE_VALUE, 0, 0, DWORD_MAX);
-       if(iocphandle == 0) {
-               runtime·printf("netpoll: failed to create iocp handle (errno=%d)\n", runtime·getlasterror());
-               runtime·throw("netpoll: failed to create iocp handle");
-       }
-       return;
-}
-
-int32
-runtime·netpollopen(uintptr fd, PollDesc *pd)
-{
-       USED(pd);
-       if(runtime·stdcall4(runtime·CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0)
-               return -runtime·getlasterror();
-       return 0;
-}
-
-int32
-runtime·netpollclose(uintptr fd)
-{
-       // nothing to do
-       USED(fd);
-       return 0;
-}
-
-void
-runtime·netpollarm(PollDesc* pd, int32 mode)
-{
-       USED(pd, mode);
-       runtime·throw("unused");
-}
-
-// Polls for completed network IO.
-// Returns list of goroutines that become runnable.
-G*
-runtime·netpoll(bool block)
-{
-       OverlappedEntry entries[64];
-       uint32 wait, qty, key, flags, n, i;
-       int32 errno;
-       net_op *op;
-       G *gp;
-
-       if(iocphandle == INVALID_HANDLE_VALUE)
-               return nil;
-       gp = nil;
-       wait = 0;
-       if(block)
-               wait = INFINITE;
-retry:
-       if(runtime·GetQueuedCompletionStatusEx != nil) {
-               n = nelem(entries) / runtime·gomaxprocs;
-               if(n < 8)
-                       n = 8;
-               if(block)
-                       g->m->blocked = true;
-               if(runtime·stdcall6(runtime·GetQueuedCompletionStatusEx, iocphandle, (uintptr)entries, n, (uintptr)&n, wait, 0) == 0) {
-                       g->m->blocked = false;
-                       errno = runtime·getlasterror();
-                       if(!block && errno == WAIT_TIMEOUT)
-                               return nil;
-                       runtime·printf("netpoll: GetQueuedCompletionStatusEx failed (errno=%d)\n", errno);
-                       runtime·throw("netpoll: GetQueuedCompletionStatusEx failed");
-               }
-               g->m->blocked = false;
-               for(i = 0; i < n; i++) {
-                       op = entries[i].op;
-                       errno = 0;
-                       qty = 0;
-                       if(runtime·stdcall5(runtime·WSAGetOverlappedResult, runtime·netpollfd(op->pd), (uintptr)op, (uintptr)&qty, 0, (uintptr)&flags) == 0)
-                               errno = runtime·getlasterror();
-                       handlecompletion(&gp, op, errno, qty);
-               }
-       } else {
-               op = nil;
-               errno = 0;
-               qty = 0;
-               if(block)
-                       g->m->blocked = true;
-               if(runtime·stdcall5(runtime·GetQueuedCompletionStatus, iocphandle, (uintptr)&qty, (uintptr)&key, (uintptr)&op, wait) == 0) {
-                       g->m->blocked = false;
-                       errno = runtime·getlasterror();
-                       if(!block && errno == WAIT_TIMEOUT)
-                               return nil;
-                       if(op == nil) {
-                               runtime·printf("netpoll: GetQueuedCompletionStatus failed (errno=%d)\n", errno);
-                               runtime·throw("netpoll: GetQueuedCompletionStatus failed");
-                       }
-                       // dequeued failed IO packet, so report that
-               }
-               g->m->blocked = false;
-               handlecompletion(&gp, op, errno, qty);
-       }
-       if(block && gp == nil)
-               goto retry;
-       return gp;
-}
-
-static void
-handlecompletion(G **gpp, net_op *op, int32 errno, uint32 qty)
-{
-       int32 mode;
-
-       if(op == nil)
-               runtime·throw("netpoll: GetQueuedCompletionStatus returned op == nil");
-       mode = op->mode;
-       if(mode != 'r' && mode != 'w') {
-               runtime·printf("netpoll: GetQueuedCompletionStatus returned invalid mode=%d\n", mode);
-               runtime·throw("netpoll: GetQueuedCompletionStatus returned invalid mode");
-       }
-       op->errno = errno;
-       op->qty = qty;
-       runtime·netpollready(gpp, op->pd, mode);
-}
diff --git a/src/runtime/netpoll_windows.go b/src/runtime/netpoll_windows.go
new file mode 100644 (file)
index 0000000..23d5dc0
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+const _DWORD_MAX = 0xffffffff
+
+//go:cgo_import_dynamic runtime._CreateIoCompletionPort CreateIoCompletionPort "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus "kernel32.dll"
+//go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult "ws2_32.dll"
+
+var (
+       _CreateIoCompletionPort,
+       _GetQueuedCompletionStatus,
+       _WSAGetOverlappedResult stdFunction
+)
+
+const _INVALID_HANDLE_VALUE = ^uintptr(0)
+
+// net_op must be the same as beginning of net.operation. Keep these in sync.
+type net_op struct {
+       // used by windows
+       o overlapped
+       // used by netpoll
+       pd    *pollDesc
+       mode  int32
+       errno int32
+       qty   uint32
+}
+
+type overlappedEntry struct {
+       key      uintptr
+       op       *net_op // In reality it's *overlapped, but we cast it to *net_op anyway.
+       internal uintptr
+       qty      uint32
+}
+
+var iocphandle uintptr = _INVALID_HANDLE_VALUE // completion port io handle
+
+func netpollinit() {
+       iocphandle = uintptr(stdcall4(_CreateIoCompletionPort, _INVALID_HANDLE_VALUE, 0, 0, _DWORD_MAX))
+       if iocphandle == 0 {
+               println("netpoll: failed to create iocp handle (errno=", getlasterror(), ")")
+               gothrow("netpoll: failed to create iocp handle")
+       }
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+       if stdcall4(_CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0 {
+               return -int32(getlasterror())
+       }
+       return 0
+}
+
+func netpollclose(fd uintptr) int32 {
+       // nothing to do
+       return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+       gothrow("unused")
+}
+
+// Polls for completed network IO.
+// Returns list of goroutines that become runnable.
+func netpoll(block bool) *g {
+       var entries [64]overlappedEntry
+       var wait, qty, key, flags, n, i uint32
+       var errno int32
+       var op *net_op
+       var gp *g
+
+       mp := getg().m
+
+       if iocphandle == _INVALID_HANDLE_VALUE {
+               return nil
+       }
+       gp = nil
+       wait = 0
+       if block {
+               wait = _INFINITE
+       }
+retry:
+       if _GetQueuedCompletionStatusEx != nil {
+               n = uint32(len(entries) / int(gomaxprocs))
+               if n < 8 {
+                       n = 8
+               }
+               if block {
+                       mp.blocked = true
+               }
+               if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
+                       mp.blocked = false
+                       errno = int32(getlasterror())
+                       if !block && errno == _WAIT_TIMEOUT {
+                               return nil
+                       }
+                       println("netpoll: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
+                       gothrow("netpoll: GetQueuedCompletionStatusEx failed")
+               }
+               mp.blocked = false
+               for i = 0; i < n; i++ {
+                       op = entries[i].op
+                       errno = 0
+                       qty = 0
+                       if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
+                               errno = int32(getlasterror())
+                       }
+                       handlecompletion(&gp, op, errno, qty)
+               }
+       } else {
+               op = nil
+               errno = 0
+               qty = 0
+               if block {
+                       mp.blocked = true
+               }
+               if stdcall5(_GetQueuedCompletionStatus, iocphandle, uintptr(unsafe.Pointer(&qty)), uintptr(unsafe.Pointer(&key)), uintptr(unsafe.Pointer(&op)), uintptr(wait)) == 0 {
+                       mp.blocked = false
+                       errno = int32(getlasterror())
+                       if !block && errno == _WAIT_TIMEOUT {
+                               return nil
+                       }
+                       if op == nil {
+                               println("netpoll: GetQueuedCompletionStatus failed (errno=", errno, ")")
+                               gothrow("netpoll: GetQueuedCompletionStatus failed")
+                       }
+                       // dequeued failed IO packet, so report that
+               }
+               mp.blocked = false
+               handlecompletion(&gp, op, errno, qty)
+       }
+       if block && gp == nil {
+               goto retry
+       }
+       return gp
+}
+
+func handlecompletion(gpp **g, op *net_op, errno int32, qty uint32) {
+       if op == nil {
+               gothrow("netpoll: GetQueuedCompletionStatus returned op == nil")
+       }
+       mode := op.mode
+       if mode != 'r' && mode != 'w' {
+               println("netpoll: GetQueuedCompletionStatus returned invalid mode=", mode)
+               gothrow("netpoll: GetQueuedCompletionStatus returned invalid mode")
+       }
+       op.errno = errno
+       op.qty = qty
+       netpollready((**g)(noescape(unsafe.Pointer(gpp))), op.pd, mode)
+}
similarity index 96%
rename from src/runtime/noasm_arm.go
rename to src/runtime/noasm.go
index dd3ef8267662ce68e773048e0a088e8b14ef4ec5..43c16860b2b96930e26d1d775f8a00da8ece9f7d 100644 (file)
@@ -5,6 +5,8 @@
 // Routines that are implemented in assembly in asm_{amd64,386}.s
 // but are implemented in Go for arm.
 
+// +build arm power64 power64le
+
 package runtime
 
 func cmpstring(s1, s2 string) int {
index 3b171877a6f5b77396159a5936e92dae2fd32e5d..3681bf190d24367594fef0fc2bbbb4e327b8950c 100644 (file)
@@ -34,12 +34,12 @@ func benchmarkSyscall(b *testing.B, work, excess int) {
        b.RunParallel(func(pb *testing.PB) {
                foo := 42
                for pb.Next() {
-                       runtime.Entersyscall()
+                       runtime.Entersyscall(0)
                        for i := 0; i < work; i++ {
                                foo *= 2
                                foo /= 2
                        }
-                       runtime.Exitsyscall()
+                       runtime.Exitsyscall(0)
                }
                _ = foo
        })
diff --git a/src/runtime/os1_darwin.go b/src/runtime/os1_darwin.go
new file mode 100644 (file)
index 0000000..2fbf2ca
--- /dev/null
@@ -0,0 +1,423 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//extern SigTabTT runtime·sigtab[];
+
+var sigset_none = uint32(0)
+var sigset_all = ^uint32(0)
+
+func unimplemented(name string) {
+       println(name, "not implemented")
+       *(*int)(unsafe.Pointer(uintptr(1231))) = 1231
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       mach_semrelease(uint32(mp.waitsema))
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       var x uintptr
+       systemstack(func() {
+               x = uintptr(mach_semcreate())
+       })
+       return x
+}
+
+// BSD interface for threading.
+func osinit() {
+       // bsdthread_register delayed until end of goenvs so that we
+       // can look at the environment first.
+
+       // Use sysctl to fetch hw.ncpu.
+       mib := [2]uint32{6, 3}
+       out := uint32(0)
+       nout := unsafe.Sizeof(out)
+       ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+       if ret >= 0 {
+               ncpu = int32(out)
+       }
+}
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/random\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       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 library install its own thread-creation callback.
+       if !iscgo {
+               if bsdthread_register() != 0 {
+                       if gogetenv("DYLD_INSERT_LIBRARIES") != "" {
+                               gothrow("runtime: bsdthread_register error (unset DYLD_INSERT_LIBRARIES)")
+                       }
+                       gothrow("runtime: bsdthread_register error")
+               }
+       }
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
+       if false {
+               print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int(mp.tls[0]), " ostk=", &mp, "\n")
+       }
+
+       var oset uint32
+       sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
+       errno := bsdthread_create(stk, mp, mp.g0, funcPC(mstart))
+       sigprocmask(_SIG_SETMASK, &oset, nil)
+
+       if errno < 0 {
+               print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -errno, ")\n")
+               gothrow("runtime.newosproc")
+       }
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024) // OS X wants >= 8K
+       mp.gsignal.m = mp
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       // Initialize signal handling.
+       _g_ := getg()
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       sigprocmask(_SIG_SETMASK, &sigset_none, nil)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+// Mach IPC, to get at semaphores
+// Definitions are in /usr/include/mach on a Mac.
+
+func macherror(r int32, fn string) {
+       print("mach error ", fn, ": ", r, "\n")
+       gothrow("mach error")
+}
+
+const _DebugMach = false
+
+var zerondr machndr
+
+func mach_msgh_bits(a, b uint32) uint32 {
+       return a | b<<8
+}
+
+func mach_msg(h *machheader, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32 {
+       // TODO: Loop on interrupt.
+       return mach_msg_trap(unsafe.Pointer(h), op, send_size, rcv_size, rcv_name, timeout, notify)
+}
+
+// Mach RPC (MIG)
+const (
+       _MinMachMsg = 48
+       _MachReply  = 100
+)
+
+type codemsg struct {
+       h    machheader
+       ndr  machndr
+       code int32
+}
+
+func machcall(h *machheader, maxsize int32, rxsize int32) int32 {
+       _g_ := getg()
+       port := _g_.m.machport
+       if port == 0 {
+               port = mach_reply_port()
+               _g_.m.machport = port
+       }
+
+       h.msgh_bits |= mach_msgh_bits(_MACH_MSG_TYPE_COPY_SEND, _MACH_MSG_TYPE_MAKE_SEND_ONCE)
+       h.msgh_local_port = port
+       h.msgh_reserved = 0
+       id := h.msgh_id
+
+       if _DebugMach {
+               p := (*[10000]unsafe.Pointer)(unsafe.Pointer(h))
+               print("send:\t")
+               var i uint32
+               for i = 0; i < h.msgh_size/uint32(unsafe.Sizeof(p[0])); i++ {
+                       print(" ", p[i])
+                       if i%8 == 7 {
+                               print("\n\t")
+                       }
+               }
+               if i%8 != 0 {
+                       print("\n")
+               }
+       }
+       ret := mach_msg(h, _MACH_SEND_MSG|_MACH_RCV_MSG, h.msgh_size, uint32(maxsize), port, 0, 0)
+       if ret != 0 {
+               if _DebugMach {
+                       print("mach_msg error ", ret, "\n")
+               }
+               return ret
+       }
+       if _DebugMach {
+               p := (*[10000]unsafe.Pointer)(unsafe.Pointer(h))
+               var i uint32
+               for i = 0; i < h.msgh_size/uint32(unsafe.Sizeof(p[0])); i++ {
+                       print(" ", p[i])
+                       if i%8 == 7 {
+                               print("\n\t")
+                       }
+               }
+               if i%8 != 0 {
+                       print("\n")
+               }
+       }
+       if h.msgh_id != id+_MachReply {
+               if _DebugMach {
+                       print("mach_msg _MachReply id mismatch ", h.msgh_id, " != ", id+_MachReply, "\n")
+               }
+               return -303 // MIG_REPLY_MISMATCH
+       }
+       // Look for a response giving the return value.
+       // Any call can send this back with an error,
+       // and some calls only have return values so they
+       // send it back on success too.  I don't quite see how
+       // you know it's one of these and not the full response
+       // format, so just look if the message is right.
+       c := (*codemsg)(unsafe.Pointer(h))
+       if uintptr(h.msgh_size) == unsafe.Sizeof(*c) && h.msgh_bits&_MACH_MSGH_BITS_COMPLEX == 0 {
+               if _DebugMach {
+                       print("mig result ", c.code, "\n")
+               }
+               return c.code
+       }
+       if h.msgh_size != uint32(rxsize) {
+               if _DebugMach {
+                       print("mach_msg _MachReply size mismatch ", h.msgh_size, " != ", rxsize, "\n")
+               }
+               return -307 // MIG_ARRAY_TOO_LARGE
+       }
+       return 0
+}
+
+// Semaphores!
+
+const (
+       tmach_semcreate = 3418
+       rmach_semcreate = tmach_semcreate + _MachReply
+
+       tmach_semdestroy = 3419
+       rmach_semdestroy = tmach_semdestroy + _MachReply
+
+       _KERN_ABORTED             = 14
+       _KERN_OPERATION_TIMED_OUT = 49
+)
+
+type tmach_semcreatemsg struct {
+       h      machheader
+       ndr    machndr
+       policy int32
+       value  int32
+}
+
+type rmach_semcreatemsg struct {
+       h         machheader
+       body      machbody
+       semaphore machport
+}
+
+type tmach_semdestroymsg struct {
+       h         machheader
+       body      machbody
+       semaphore machport
+}
+
+func mach_semcreate() uint32 {
+       var m [256]uint8
+       tx := (*tmach_semcreatemsg)(unsafe.Pointer(&m))
+       rx := (*rmach_semcreatemsg)(unsafe.Pointer(&m))
+
+       tx.h.msgh_bits = 0
+       tx.h.msgh_size = uint32(unsafe.Sizeof(*tx))
+       tx.h.msgh_remote_port = mach_task_self()
+       tx.h.msgh_id = tmach_semcreate
+       tx.ndr = zerondr
+
+       tx.policy = 0 // 0 = SYNC_POLICY_FIFO
+       tx.value = 0
+
+       for {
+               r := machcall(&tx.h, int32(unsafe.Sizeof(m)), int32(unsafe.Sizeof(*rx)))
+               if r == 0 {
+                       break
+               }
+               if r == _KERN_ABORTED { // interrupted
+                       continue
+               }
+               macherror(r, "semaphore_create")
+       }
+       if rx.body.msgh_descriptor_count != 1 {
+               unimplemented("mach_semcreate desc count")
+       }
+       return rx.semaphore.name
+}
+
+func mach_semdestroy(sem uint32) {
+       var m [256]uint8
+       tx := (*tmach_semdestroymsg)(unsafe.Pointer(&m))
+
+       tx.h.msgh_bits = _MACH_MSGH_BITS_COMPLEX
+       tx.h.msgh_size = uint32(unsafe.Sizeof(*tx))
+       tx.h.msgh_remote_port = mach_task_self()
+       tx.h.msgh_id = tmach_semdestroy
+       tx.body.msgh_descriptor_count = 1
+       tx.semaphore.name = sem
+       tx.semaphore.disposition = _MACH_MSG_TYPE_MOVE_SEND
+       tx.semaphore._type = 0
+
+       for {
+               r := machcall(&tx.h, int32(unsafe.Sizeof(m)), 0)
+               if r == 0 {
+                       break
+               }
+               if r == _KERN_ABORTED { // interrupted
+                       continue
+               }
+               macherror(r, "semaphore_destroy")
+       }
+}
+
+// The other calls have simple system call traps in sys_darwin_{amd64,386}.s
+
+func mach_semaphore_wait(sema uint32) int32
+func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
+func mach_semaphore_signal(sema uint32) int32
+func mach_semaphore_signal_all(sema uint32) int32
+
+func semasleep1(ns int64) int32 {
+       _g_ := getg()
+
+       if ns >= 0 {
+               var nsecs int32
+               secs := timediv(ns, 1000000000, &nsecs)
+               r := mach_semaphore_timedwait(uint32(_g_.m.waitsema), uint32(secs), uint32(nsecs))
+               if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT {
+                       return -1
+               }
+               if r != 0 {
+                       macherror(r, "semaphore_wait")
+               }
+               return 0
+       }
+
+       for {
+               r := mach_semaphore_wait(uint32(_g_.m.waitsema))
+               if r == 0 {
+                       break
+               }
+               if r == _KERN_ABORTED { // interrupted
+                       continue
+               }
+               macherror(r, "semaphore_wait")
+       }
+       return 0
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       var r int32
+       systemstack(func() {
+               r = semasleep1(ns)
+       })
+       return r
+}
+
+//go:nosplit
+func mach_semrelease(sem uint32) {
+       for {
+               r := mach_semaphore_signal(sem)
+               if r == 0 {
+                       break
+               }
+               if r == _KERN_ABORTED { // interrupted
+                       continue
+               }
+
+               // mach_semrelease must be completely nosplit,
+               // because it is called from Go code.
+               // If we're going to die, start that process on the system stack
+               // to avoid a Go stack split.
+               systemstack(func() { macherror(r, "semaphore_signal") })
+       }
+}
+
+//go:nosplit
+func osyield() {
+       usleep(1)
+}
+
+func memlimit() uintptr {
+       // NOTE(rsc): Could use getrlimit here,
+       // like on FreeBSD or Linux, but Darwin doesn't enforce
+       // ulimit -v, so it's unclear why we'd try to stay within
+       // the limit.
+       return 0
+}
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+       memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = ^uint32(0)
+       sa.sa_tramp = unsafe.Pointer(funcPC(sigtramp)) // runtime·sigtramp's job is to call into real handler
+       *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn
+       sigaction(uint32(i), &sa, nil)
+}
+
+func getsig(i int32) uintptr {
+       var sa sigactiont
+       memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
+       sigaction(uint32(i), nil, &sa)
+       return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
+}
+
+func signalstack(p *byte, n int32) {
+       var st stackt
+       st.ss_sp = p
+       st.ss_size = uintptr(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       sigprocmask(_SIG_SETMASK, &sigset_none, nil)
+}
diff --git a/src/runtime/os1_dragonfly.go b/src/runtime/os1_dragonfly.go
new file mode 100644 (file)
index 0000000..82bb45b
--- /dev/null
@@ -0,0 +1,220 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// From DragonFly's <sys/sysctl.h>
+const (
+       _CTL_HW  = 6
+       _HW_NCPU = 3
+)
+
+var sigset_none = sigset{}
+var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
+
+func getncpu() int32 {
+       mib := [2]uint32{_CTL_HW, _HW_NCPU}
+       out := uint32(0)
+       nout := unsafe.Sizeof(out)
+       ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+       if ret >= 0 {
+               return int32(out)
+       }
+       return 1
+}
+
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+       systemstack(func() {
+               futexsleep1(addr, val, ns)
+       })
+}
+
+func futexsleep1(addr *uint32, val uint32, ns int64) {
+       var timeout int32
+       if ns >= 0 {
+               // The timeout is specified in microseconds - ensure that we
+               // do not end up dividing to zero, which would put us to sleep
+               // indefinitely...
+               timeout = timediv(ns, 1000, nil)
+               if timeout == 0 {
+                       timeout = 1
+               }
+       }
+
+       // sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
+       // expires or EBUSY if the mutex value does not match.
+       ret := sys_umtx_sleep(addr, int32(val), timeout)
+       if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY {
+               return
+       }
+
+       print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n")
+       *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
+}
+
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+       ret := sys_umtx_wakeup(addr, int32(cnt))
+       if ret >= 0 {
+               return
+       }
+
+       systemstack(func() {
+               print("umtx_wake_addr=", addr, " ret=", ret, "\n")
+               *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
+       })
+}
+
+func lwp_start(uintptr)
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       if false {
+               print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+       }
+
+       var oset sigset
+       sigprocmask(&sigset_all, &oset)
+
+       params := lwpparams{
+               start_func: funcPC(lwp_start),
+               arg:        unsafe.Pointer(mp),
+               stack:      uintptr(stk),
+               tid1:       unsafe.Pointer(&mp.procid),
+               tid2:       nil,
+       }
+
+       mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
+
+       lwp_create(&params)
+       sigprocmask(&oset, nil)
+}
+
+func osinit() {
+       ncpu = getncpu()
+}
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/urandom\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       _g_ := getg()
+
+       // m.procid is a uint64, but lwp_start writes an int32. Fix it up.
+       _g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
+
+       // Initialize signal handling
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       sigprocmask(&sigset_none, nil)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+func memlimit() uintptr {
+       /*
+                               TODO: Convert to Go when something actually uses the result.
+
+                               Rlimit rl;
+                               extern byte runtime·text[], runtime·end[];
+                               uintptr used;
+
+                               if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
+                                       return 0;
+                               if(rl.rlim_cur >= 0x7fffffff)
+                                       return 0;
+
+                               // Estimate our VM footprint excluding the heap.
+                               // Not an exact science: use size of binary plus
+                               // some room for thread stacks.
+                               used = runtime·end - runtime·text + (64<<20);
+                               if(used >= rl.rlim_cur)
+                                       return 0;
+
+                               // If there's not at least 16 MB left, we're probably
+                               // not going to be able to do much.  Treat as no limit.
+                               rl.rlim_cur -= used;
+                               if(rl.rlim_cur < (16<<20))
+                                       return 0;
+
+                               return rl.rlim_cur - used;
+       */
+       return 0
+}
+
+func sigtramp()
+
+type sigactiont struct {
+       sa_sigaction uintptr
+       sa_flags     int32
+       sa_mask      sigset
+}
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = sigset_all
+       if fn == funcPC(sighandler) {
+               fn = funcPC(sigtramp)
+       }
+       sa.sa_sigaction = fn
+       sigaction(i, &sa, nil)
+}
+
+func getsig(i int32) uintptr {
+       var sa sigactiont
+       sigaction(i, nil, &sa)
+       if sa.sa_sigaction == funcPC(sigtramp) {
+               return funcPC(sighandler)
+       }
+       return sa.sa_sigaction
+}
+
+func signalstack(p *byte, n int32) {
+       var st sigaltstackt
+       st.ss_sp = uintptr(unsafe.Pointer(p))
+       st.ss_size = uintptr(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       sigprocmask(&sigset_none, nil)
+}
diff --git a/src/runtime/os1_freebsd.go b/src/runtime/os1_freebsd.go
new file mode 100644 (file)
index 0000000..2cacfba
--- /dev/null
@@ -0,0 +1,221 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// From FreeBSD's <sys/sysctl.h>
+const (
+       _CTL_HW  = 6
+       _HW_NCPU = 3
+)
+
+var sigset_none = sigset{}
+var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
+
+func getncpu() int32 {
+       mib := [2]uint32{_CTL_HW, _HW_NCPU}
+       out := uint32(0)
+       nout := unsafe.Sizeof(out)
+       ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+       if ret >= 0 {
+               return int32(out)
+       }
+       return 1
+}
+
+// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
+// thus the code is largely similar. See Linux implementation
+// and lock_futex.c for comments.
+
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+       systemstack(func() {
+               futexsleep1(addr, val, ns)
+       })
+}
+
+func futexsleep1(addr *uint32, val uint32, ns int64) {
+       var tsp *timespec
+       if ns >= 0 {
+               var ts timespec
+               ts.tv_nsec = 0
+               ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
+               tsp = &ts
+       }
+       ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp)
+       if ret >= 0 || ret == -_EINTR {
+               return
+       }
+       print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n")
+       *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
+}
+
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+       ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil)
+       if ret >= 0 {
+               return
+       }
+
+       systemstack(func() {
+               print("umtx_wake_addr=", addr, " ret=", ret, "\n")
+       })
+}
+
+func thr_start()
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       if false {
+               print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+       }
+
+       // 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 := thrparam{
+               start_func: funcPC(thr_start),
+               arg:        unsafe.Pointer(mp),
+               stack_base: mp.g0.stack.hi,
+               stack_size: uintptr(stk) - mp.g0.stack.hi,
+               child_tid:  unsafe.Pointer(&mp.procid),
+               parent_tid: nil,
+               tls_base:   unsafe.Pointer(&mp.tls[0]),
+               tls_size:   unsafe.Sizeof(mp.tls),
+       }
+       mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
+
+       var oset sigset
+       sigprocmask(&sigset_all, &oset)
+       thr_new(&param, int32(unsafe.Sizeof(param)))
+       sigprocmask(&oset, nil)
+}
+
+func osinit() {
+       ncpu = getncpu()
+}
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/random\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       _g_ := getg()
+
+       // m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
+       // Fix it up. (Only matters on big-endian, but be clean anyway.)
+       if ptrSize == 4 {
+               _g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
+       }
+
+       // Initialize signal handling.
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       sigprocmask(&sigset_none, nil)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+func memlimit() uintptr {
+       /*
+               TODO: Convert to Go when something actually uses the result.
+               Rlimit rl;
+               extern byte runtime·text[], runtime·end[];
+               uintptr used;
+
+               if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
+                       return 0;
+               if(rl.rlim_cur >= 0x7fffffff)
+                       return 0;
+
+               // Estimate our VM footprint excluding the heap.
+               // Not an exact science: use size of binary plus
+               // some room for thread stacks.
+               used = runtime·end - runtime·text + (64<<20);
+               if(used >= rl.rlim_cur)
+                       return 0;
+
+               // If there's not at least 16 MB left, we're probably
+               // not going to be able to do much.  Treat as no limit.
+               rl.rlim_cur -= used;
+               if(rl.rlim_cur < (16<<20))
+                       return 0;
+
+               return rl.rlim_cur - used;
+       */
+
+       return 0
+}
+
+func sigtramp()
+
+type sigactiont struct {
+       sa_handler uintptr
+       sa_flags   int32
+       sa_mask    sigset
+}
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = sigset_all
+       if fn == funcPC(sighandler) {
+               fn = funcPC(sigtramp)
+       }
+       sa.sa_handler = fn
+       sigaction(i, &sa, nil)
+}
+func getsig(i int32) uintptr {
+       var sa sigactiont
+       sigaction(i, nil, &sa)
+       if sa.sa_handler == funcPC(sigtramp) {
+               return funcPC(sighandler)
+       }
+       return sa.sa_handler
+}
+
+func signalstack(p *byte, n int32) {
+       var st stackt
+       st.ss_sp = uintptr(unsafe.Pointer(p))
+       st.ss_size = uintptr(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       sigprocmask(&sigset_none, nil)
+}
diff --git a/src/runtime/os1_linux.go b/src/runtime/os1_linux.go
new file mode 100644 (file)
index 0000000..67fa639
--- /dev/null
@@ -0,0 +1,287 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+var sigset_none sigset
+var sigset_all sigset = sigset{^uint32(0), ^uint32(0)}
+
+// Linux futex.
+//
+//     futexsleep(uint32 *addr, uint32 val)
+//     futexwakeup(uint32 *addr)
+//
+// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
+// Futexwakeup wakes up threads sleeping on addr.
+// Futexsleep is allowed to wake up spuriously.
+
+const (
+       _FUTEX_WAIT = 0
+       _FUTEX_WAKE = 1
+)
+
+// Atomically,
+//     if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+       var ts timespec
+
+       // Some Linux kernels have a bug where futex of
+       // FUTEX_WAIT returns an internal error code
+       // as an errno.  Libpthread ignores the return value
+       // here, and so can we: as it says a few lines up,
+       // spurious wakeups are allowed.
+       if ns < 0 {
+               futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
+               return
+       }
+
+       // It's difficult to live within the no-split stack limits here.
+       // On ARM and 386, a 64-bit divide invokes a general software routine
+       // that needs more stack than we can afford. So we use timediv instead.
+       // But on real 64-bit systems, where words are larger but the stack limit
+       // is not, even timediv is too heavy, and we really need to use just an
+       // ordinary machine instruction.
+       if ptrSize == 8 {
+               ts.set_sec(ns / 1000000000)
+               ts.set_nsec(int32(ns % 1000000000))
+       } else {
+               ts.tv_nsec = 0
+               ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
+       }
+       futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
+}
+
+// If any procs are sleeping on addr, wake up at most cnt.
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+       ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
+       if ret >= 0 {
+               return
+       }
+
+       // I don't know that futex wakeup can return
+       // EAGAIN or EINTR, but if it does, it would be
+       // safe to loop and call futex again.
+       systemstack(func() {
+               print("futexwakeup addr=", addr, " returned ", ret, "\n")
+       })
+
+       *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
+}
+
+func getproccount() int32 {
+       var buf [16]uintptr
+       r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
+       n := int32(0)
+       for _, v := range buf[:r/ptrSize] {
+               for i := 0; i < 64; i++ {
+                       n += int32(v & 1)
+                       v >>= 1
+               }
+       }
+       if n == 0 {
+               n = 1
+       }
+       return n
+}
+
+// Clone, the Linux rfork.
+const (
+       _CLONE_VM             = 0x100
+       _CLONE_FS             = 0x200
+       _CLONE_FILES          = 0x400
+       _CLONE_SIGHAND        = 0x800
+       _CLONE_PTRACE         = 0x2000
+       _CLONE_VFORK          = 0x4000
+       _CLONE_PARENT         = 0x8000
+       _CLONE_THREAD         = 0x10000
+       _CLONE_NEWNS          = 0x20000
+       _CLONE_SYSVSEM        = 0x40000
+       _CLONE_SETTLS         = 0x80000
+       _CLONE_PARENT_SETTID  = 0x100000
+       _CLONE_CHILD_CLEARTID = 0x200000
+       _CLONE_UNTRACED       = 0x800000
+       _CLONE_CHILD_SETTID   = 0x1000000
+       _CLONE_STOPPED        = 0x2000000
+       _CLONE_NEWUTS         = 0x4000000
+       _CLONE_NEWIPC         = 0x8000000
+)
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       /*
+        * note: strace gets confused if we use CLONE_PTRACE here.
+        */
+       var flags int32 = _CLONE_VM | /* share memory */
+               _CLONE_FS | /* share cwd, etc */
+               _CLONE_FILES | /* share fd table */
+               _CLONE_SIGHAND | /* share sig handler table */
+               _CLONE_THREAD /* revisit - okay for now */
+
+       mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
+       if false {
+               print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+       }
+
+       // Disable signals during clone, so that the new thread starts
+       // with signals disabled.  It will enable them in minit.
+       var oset sigset
+       rtsigprocmask(_SIG_SETMASK, &sigset_all, &oset, int32(unsafe.Sizeof(oset)))
+       ret := clone(flags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
+       rtsigprocmask(_SIG_SETMASK, &oset, nil, int32(unsafe.Sizeof(oset)))
+
+       if ret < 0 {
+               print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
+               gothrow("newosproc")
+       }
+}
+
+func osinit() {
+       ncpu = getproccount()
+}
+
+// Random bytes initialized at startup.  These come
+// from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c).
+// byte*       runtime·startup_random_data;
+// uint32      runtime·startup_random_data_len;
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/random\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       if startup_random_data != nil {
+               *rnd = unsafe.Pointer(startup_random_data)
+               *rnd_len = int32(startup_random_data_len)
+               return
+       }
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024) // Linux wants >= 2K
+       mp.gsignal.m = mp
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       // Initialize signal handling.
+       _g_ := getg()
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       rtsigprocmask(_SIG_SETMASK, &sigset_none, nil, int32(unsafe.Sizeof(sigset_none)))
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+func memlimit() uintptr {
+       /*
+               TODO: Convert to Go when something actually uses the result.
+
+               Rlimit rl;
+               extern byte runtime·text[], runtime·end[];
+               uintptr used;
+
+               if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
+                       return 0;
+               if(rl.rlim_cur >= 0x7fffffff)
+                       return 0;
+
+               // Estimate our VM footprint excluding the heap.
+               // Not an exact science: use size of binary plus
+               // some room for thread stacks.
+               used = runtime·end - runtime·text + (64<<20);
+               if(used >= rl.rlim_cur)
+                       return 0;
+
+               // If there's not at least 16 MB left, we're probably
+               // not going to be able to do much.  Treat as no limit.
+               rl.rlim_cur -= used;
+               if(rl.rlim_cur < (16<<20))
+                       return 0;
+
+               return rl.rlim_cur - used;
+       */
+
+       return 0
+}
+
+//#ifdef GOARCH_386
+//#define sa_handler k_sa_handler
+//#endif
+
+func sigreturn()
+func sigtramp()
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+       memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = ^uint64(0)
+       // Although Linux manpage says "sa_restorer element is obsolete and
+       // should not be used". x86_64 kernel requires it. Only use it on
+       // x86.
+       if GOARCH == "386" || GOARCH == "amd64" {
+               sa.sa_restorer = funcPC(sigreturn)
+       }
+       if fn == funcPC(sighandler) {
+               fn = funcPC(sigtramp)
+       }
+       sa.sa_handler = fn
+       if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 {
+               gothrow("rt_sigaction failure")
+       }
+}
+
+func getsig(i int32) uintptr {
+       var sa sigactiont
+
+       memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
+       if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
+               gothrow("rt_sigaction read failure")
+       }
+       if sa.sa_handler == funcPC(sigtramp) {
+               return funcPC(sighandler)
+       }
+       return sa.sa_handler
+}
+
+func signalstack(p *byte, n int32) {
+       var st sigaltstackt
+       st.ss_sp = p
+       st.ss_size = uintptr(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       rtsigprocmask(_SIG_SETMASK, &sigset_none, nil, int32(unsafe.Sizeof(sigset_none)))
+}
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go
new file mode 100644 (file)
index 0000000..d5ffe10
--- /dev/null
@@ -0,0 +1,235 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+const (
+       ESRCH       = 3
+       EAGAIN      = 35
+       EWOULDBLOCK = EAGAIN
+       ENOTSUP     = 91
+
+       // From OpenBSD's sys/time.h
+       CLOCK_REALTIME  = 0
+       CLOCK_VIRTUAL   = 1
+       CLOCK_PROF      = 2
+       CLOCK_MONOTONIC = 3
+)
+
+var sigset_none = uint32(0)
+var sigset_all = ^sigset_none
+
+// From OpenBSD's <sys/sysctl.h>
+const (
+       CTL_HW  = 6
+       HW_NCPU = 3
+)
+
+func getncpu() int32 {
+       mib := [2]uint32{CTL_HW, HW_NCPU}
+       out := uint32(0)
+       nout := unsafe.Sizeof(out)
+
+       // Fetch hw.ncpu via sysctl.
+       ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+       if ret >= 0 {
+               return int32(out)
+       }
+       return 1
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       return 1
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       _g_ := getg()
+
+       // Compute sleep deadline.
+       var tsp *timespec
+       if ns >= 0 {
+               var ts timespec
+               var nsec int32
+               ns += nanotime()
+               ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
+               ts.set_nsec(nsec)
+               tsp = &ts
+       }
+
+       for {
+               // spin-mutex lock
+               for {
+                       if xchg(&_g_.m.waitsemalock, 1) == 0 {
+                               break
+                       }
+                       osyield()
+               }
+
+               if _g_.m.waitsemacount != 0 {
+                       // semaphore is available.
+                       _g_.m.waitsemacount--
+                       // spin-mutex unlock
+                       atomicstore(&_g_.m.waitsemalock, 0)
+                       return 0 // semaphore acquired
+               }
+
+               // sleep until semaphore != 0 or timeout.
+               // thrsleep unlocks m.waitsemalock.
+               ret := thrsleep((uintptr)(unsafe.Pointer(&_g_.m.waitsemacount)), CLOCK_MONOTONIC, tsp, (uintptr)(unsafe.Pointer(&_g_.m.waitsemalock)), (*int32)(unsafe.Pointer(&_g_.m.waitsemacount)))
+               if ret == EWOULDBLOCK {
+                       return -1
+               }
+       }
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       // spin-mutex lock
+       for {
+               if xchg(&mp.waitsemalock, 1) == 0 {
+                       break
+               }
+               osyield()
+       }
+       mp.waitsemacount++
+       ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
+       if ret != 0 && ret != ESRCH {
+               // semawakeup can be called on signal stack.
+               systemstack(func() {
+                       print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n")
+               })
+       }
+       // spin-mutex unlock
+       atomicstore(&mp.waitsemalock, 0)
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       if false {
+               print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
+       }
+
+       mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
+
+       param := tforkt{
+               tf_tcb:   unsafe.Pointer(&mp.tls[0]),
+               tf_tid:   (*int32)(unsafe.Pointer(&mp.procid)),
+               tf_stack: uintptr(stk),
+       }
+
+       oset := sigprocmask(_SIG_SETMASK, sigset_all)
+       ret := tfork(&param, unsafe.Sizeof(param), mp, mp.g0, funcPC(mstart))
+       sigprocmask(_SIG_SETMASK, oset)
+
+       if ret < 0 {
+               print("runtime: failed to create new OS thread (have ", mcount()-1, " already; errno=", -ret, ")\n")
+               if ret == -ENOTSUP {
+                       print("runtime: is kern.rthreads disabled?\n")
+               }
+               gothrow("runtime.newosproc")
+       }
+}
+
+func osinit() {
+       ncpu = getncpu()
+}
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/urandom\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       _g_ := getg()
+
+       // m.procid is a uint64, but tfork writes an int32. Fix it up.
+       _g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
+
+       // Initialize signal handling
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       sigprocmask(_SIG_SETMASK, sigset_none)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+func memlimit() uintptr {
+       return 0
+}
+
+func sigtramp()
+
+type sigactiont struct {
+       sa_sigaction uintptr
+       sa_mask      uint32
+       sa_flags     int32
+}
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = sigset_all
+       if fn == funcPC(sighandler) {
+               fn = funcPC(sigtramp)
+       }
+       sa.sa_sigaction = fn
+       sigaction(i, &sa, nil)
+}
+
+func getsig(i int32) uintptr {
+       var sa sigactiont
+       sigaction(i, nil, &sa)
+       if sa.sa_sigaction == funcPC(sigtramp) {
+               return funcPC(sighandler)
+       }
+       return sa.sa_sigaction
+}
+
+func signalstack(p *byte, n int32) {
+       var st stackt
+
+       st.ss_sp = uintptr(unsafe.Pointer(p))
+       st.ss_size = uintptr(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       sigprocmask(_SIG_SETMASK, sigset_none)
+}
diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go
new file mode 100644 (file)
index 0000000..abd2297
--- /dev/null
@@ -0,0 +1,564 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+//go:cgo_import_dynamic runtime._AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
+//go:cgo_import_dynamic runtime._CloseHandle CloseHandle "kernel32.dll"
+//go:cgo_import_dynamic runtime._CreateEventA CreateEventA "kernel32.dll"
+//go:cgo_import_dynamic runtime._CreateThread CreateThread "kernel32.dll"
+//go:cgo_import_dynamic runtime._CreateWaitableTimerA CreateWaitableTimerA "kernel32.dll"
+//go:cgo_import_dynamic runtime._CryptAcquireContextW CryptAcquireContextW "advapi32.dll"
+//go:cgo_import_dynamic runtime._CryptGenRandom CryptGenRandom "advapi32.dll"
+//go:cgo_import_dynamic runtime._CryptReleaseContext CryptReleaseContext "advapi32.dll"
+//go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle "kernel32.dll"
+//go:cgo_import_dynamic runtime._ExitProcess ExitProcess "kernel32.dll"
+//go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext "kernel32.dll"
+//go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW "kernel32.dll"
+//go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA "kernel32.dll"
+//go:cgo_import_dynamic runtime._NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll"
+//go:cgo_import_dynamic runtime._ResumeThread ResumeThread "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetEvent SetEvent "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetThreadPriority SetThreadPriority "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll"
+//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer "kernel32.dll"
+//go:cgo_import_dynamic runtime._Sleep Sleep "kernel32.dll"
+//go:cgo_import_dynamic runtime._SuspendThread SuspendThread "kernel32.dll"
+//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject "kernel32.dll"
+//go:cgo_import_dynamic runtime._WriteFile WriteFile "kernel32.dll"
+//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod "winmm.dll"
+
+var (
+       _AddVectoredExceptionHandler,
+       _CloseHandle,
+       _CreateEventA,
+       _CreateThread,
+       _CreateWaitableTimerA,
+       _CryptAcquireContextW,
+       _CryptGenRandom,
+       _CryptReleaseContext,
+       _DuplicateHandle,
+       _ExitProcess,
+       _FreeEnvironmentStringsW,
+       _GetEnvironmentStringsW,
+       _GetProcAddress,
+       _GetStdHandle,
+       _GetSystemInfo,
+       _GetThreadContext,
+       _LoadLibraryW,
+       _LoadLibraryA,
+       _NtWaitForSingleObject,
+       _ResumeThread,
+       _SetConsoleCtrlHandler,
+       _SetEvent,
+       _SetProcessPriorityBoost,
+       _SetThreadPriority,
+       _SetUnhandledExceptionFilter,
+       _SetWaitableTimer,
+       _Sleep,
+       _SuspendThread,
+       _WaitForSingleObject,
+       _WriteFile,
+       _timeBeginPeriod stdFunction
+)
+
+var _GetQueuedCompletionStatusEx stdFunction
+
+// in sys_windows_386.s and sys_windows_amd64.s
+func externalthreadhandler()
+func exceptiontramp()
+func firstcontinuetramp()
+func lastcontinuetramp()
+
+//go:nosplit
+func getLoadLibrary() uintptr {
+       return uintptr(unsafe.Pointer(_LoadLibraryW))
+}
+
+//go:nosplit
+func getGetProcAddress() uintptr {
+       return uintptr(unsafe.Pointer(_GetProcAddress))
+}
+
+func getproccount() int32 {
+       var info systeminfo
+       stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
+       return int32(info.dwnumberofprocessors)
+}
+
+const (
+       currentProcess = ^uintptr(0) // -1 = current process
+       currentThread  = ^uintptr(1) // -2 = current thread
+)
+
+var (
+       kernel32Name                    = []byte("kernel32.dll\x00")
+       addVectoredContinueHandlerName  = []byte("AddVectoredContinueHandler\x00")
+       getQueuedCompletionStatusExName = []byte("GetQueuedCompletionStatusEx\x00")
+)
+
+func osinit() {
+       setBadSignalMsg()
+
+       kernel32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32Name[0])))
+
+       externalthreadhandlerp = funcPC(externalthreadhandler)
+
+       stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
+       addVectoredContinueHandler := uintptr(0)
+       if kernel32 != 0 {
+               addVectoredContinueHandler = stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&addVectoredContinueHandlerName[0])))
+       }
+       if addVectoredContinueHandler == 0 || unsafe.Sizeof(&kernel32) == 4 {
+               // use SetUnhandledExceptionFilter for windows-386 or
+               // if VectoredContinueHandler is unavailable.
+               // note: SetUnhandledExceptionFilter handler won't be called, if debugging.
+               stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp))
+       } else {
+               stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 1, funcPC(firstcontinuetramp))
+               stdcall2(stdFunction(unsafe.Pointer(addVectoredContinueHandler)), 0, funcPC(lastcontinuetramp))
+       }
+
+       stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
+
+       stdcall1(_timeBeginPeriod, 1)
+
+       ncpu = getproccount()
+
+       // Windows dynamic priority boosting assumes that a process has different types
+       // of dedicated threads -- GUI, IO, computational, etc. Go processes use
+       // equivalent threads that all do a mix of GUI, IO, computations, etc.
+       // In such context dynamic priority boosting does nothing but harm, so we turn it off.
+       stdcall2(_SetProcessPriorityBoost, currentProcess, 1)
+
+       if kernel32 != 0 {
+               _GetQueuedCompletionStatusEx = stdFunction(unsafe.Pointer(stdcall2(_GetProcAddress, kernel32, uintptr(unsafe.Pointer(&getQueuedCompletionStatusExName[0])))))
+       }
+}
+
+var random_data [_HashRandomBytes]byte
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       const (
+               prov_rsa_full       = 1
+               crypt_verifycontext = 0xF0000000
+       )
+       var handle uintptr
+       *rnd = nil
+       *rnd_len = 0
+       if stdcall5(_CryptAcquireContextW, uintptr(unsafe.Pointer(&handle)), 0, 0, prov_rsa_full, crypt_verifycontext) != 0 {
+               if stdcall3(_CryptGenRandom, handle, _HashRandomBytes, uintptr(unsafe.Pointer(&random_data[0]))) != 0 {
+                       *rnd = unsafe.Pointer(&random_data[0])
+                       *rnd_len = _HashRandomBytes
+               }
+               stdcall2(_CryptReleaseContext, handle, 0)
+       }
+}
+
+func goenvs() {
+       var p *uint16
+
+       env := (*uint16)(unsafe.Pointer(stdcall0(_GetEnvironmentStringsW)))
+
+       n := 0
+       for p = env; *p != 0; n++ {
+               p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)))
+       }
+
+       envs = makeStringSlice(int(n))
+
+       p = env
+       for i := 0; i < n; i++ {
+               envs[i] = gostringw(p)
+               p = (*uint16)(add(unsafe.Pointer(p), uintptr(findnullw(p)+1)))
+       }
+
+       stdcall1(_FreeEnvironmentStringsW, uintptr(unsafe.Pointer(env)))
+}
+
+//go:nosplit
+func exit(code int32) {
+       stdcall1(_ExitProcess, uintptr(code))
+}
+
+//go:nosplit
+func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
+       const (
+               _STD_OUTPUT_HANDLE = ^uintptr(10) // -11
+               _STD_ERROR_HANDLE  = ^uintptr(11) // -12
+       )
+       var handle uintptr
+       switch fd {
+       case 1:
+               handle = stdcall1(_GetStdHandle, _STD_OUTPUT_HANDLE)
+       case 2:
+               handle = stdcall1(_GetStdHandle, _STD_ERROR_HANDLE)
+       default:
+               // assume fd is real windows handle.
+               handle = fd
+       }
+       var written uint32
+       stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
+       return int32(written)
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       // store ms in ns to save stack space
+       if ns < 0 {
+               ns = _INFINITE
+       } else {
+               ns = int64(timediv(ns, 1000000, nil))
+               if ns == 0 {
+                       ns = 1
+               }
+       }
+       if stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) != 0 {
+               return -1 // timeout
+       }
+       return 0
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       stdcall1(_SetEvent, mp.waitsema)
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       return stdcall4(_CreateEventA, 0, 0, 0, 0)
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       const _STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000
+       thandle := stdcall6(_CreateThread, 0, 0x20000,
+               funcPC(tstart_stdcall), uintptr(unsafe.Pointer(mp)),
+               _STACK_SIZE_PARAM_IS_A_RESERVATION, 0)
+       if thandle == 0 {
+               println("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", getlasterror(), ")")
+               gothrow("runtime.newosproc")
+       }
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       var thandle uintptr
+       stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
+       atomicstoreuintptr(&getg().m.thread, thandle)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       tp := &getg().m.thread
+       stdcall1(_CloseHandle, *tp)
+       *tp = 0
+}
+
+// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
+type _KSYSTEM_TIME struct {
+       LowPart   uint32
+       High1Time int32
+       High2Time int32
+}
+
+const (
+       _INTERRUPT_TIME = 0x7ffe0008
+       _SYSTEM_TIME    = 0x7ffe0014
+)
+
+//go:nosplit
+func systime(addr uintptr) int64 {
+       timeaddr := (*_KSYSTEM_TIME)(unsafe.Pointer(addr))
+
+       var t _KSYSTEM_TIME
+       for i := 1; i < 10000; i++ {
+               // these fields must be read in that order (see URL above)
+               t.High1Time = timeaddr.High1Time
+               t.LowPart = timeaddr.LowPart
+               t.High2Time = timeaddr.High2Time
+               if t.High1Time == t.High2Time {
+                       return int64(t.High1Time)<<32 | int64(t.LowPart)
+               }
+               if (i % 100) == 0 {
+                       osyield()
+               }
+       }
+       systemstack(func() {
+               gothrow("interrupt/system time is changing too fast")
+       })
+       return 0
+}
+
+//go:nosplit
+func unixnano() int64 {
+       return (systime(_SYSTEM_TIME) - 116444736000000000) * 100
+}
+
+//go:nosplit
+func nanotime() int64 {
+       return systime(_INTERRUPT_TIME) * 100
+}
+
+// Calling stdcall on os stack.
+//go:nosplit
+func stdcall(fn stdFunction) uintptr {
+       gp := getg()
+       mp := gp.m
+       mp.libcall.fn = uintptr(unsafe.Pointer(fn))
+
+       if mp.profilehz != 0 {
+               // leave pc/sp for cpu profiler
+               mp.libcallg = gp
+               mp.libcallpc = getcallerpc(unsafe.Pointer(&fn))
+               // sp must be the last, because once async cpu profiler finds
+               // all three values to be non-zero, it will use them
+               mp.libcallsp = getcallersp(unsafe.Pointer(&fn))
+       }
+       asmcgocall(unsafe.Pointer(funcPC(asmstdcall)), unsafe.Pointer(&mp.libcall))
+       mp.libcallsp = 0
+       return mp.libcall.r1
+}
+
+//go:nosplit
+func stdcall0(fn stdFunction) uintptr {
+       mp := getg().m
+       mp.libcall.n = 0
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall1(fn stdFunction, a0 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 1
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 2
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 3
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 4
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 5
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 6
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+//go:nosplit
+func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
+       mp := getg().m
+       mp.libcall.n = 7
+       mp.libcall.args = uintptr(noescape(unsafe.Pointer(&a0)))
+       return stdcall(fn)
+}
+
+// in sys_windows_386.s and sys_windows_amd64.s
+func usleep1(usec uint32)
+
+//go:nosplit
+func osyield() {
+       usleep1(1)
+}
+
+//go:nosplit
+func usleep(us uint32) {
+       // Have 1us units; want 100ns units.
+       usleep1(10 * us)
+}
+
+func issigpanic(code uint32) uint32 {
+       switch code {
+       default:
+               return 0
+       case _EXCEPTION_ACCESS_VIOLATION:
+       case _EXCEPTION_INT_DIVIDE_BY_ZERO:
+       case _EXCEPTION_INT_OVERFLOW:
+       case _EXCEPTION_FLT_DENORMAL_OPERAND:
+       case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
+       case _EXCEPTION_FLT_INEXACT_RESULT:
+       case _EXCEPTION_FLT_OVERFLOW:
+       case _EXCEPTION_FLT_UNDERFLOW:
+       case _EXCEPTION_BREAKPOINT:
+       }
+       return 1
+}
+
+func initsig() {
+       /*
+               // TODO(brainman): I don't think we need that bit of code
+               // following line keeps these functions alive at link stage
+               // if there's a better way please write it here
+               void *e = runtime·exceptiontramp;
+               void *f = runtime·firstcontinuetramp;
+               void *l = runtime·lastcontinuetramp;
+               USED(e);
+               USED(f);
+               USED(l);
+       */
+}
+
+func ctrlhandler1(_type uint32) uint32 {
+       var s uint32
+
+       switch _type {
+       case _CTRL_C_EVENT, _CTRL_BREAK_EVENT:
+               s = _SIGINT
+       default:
+               return 0
+       }
+
+       if sigsend(s) {
+               return 1
+       }
+       exit(2) // SIGINT, SIGTERM, etc
+       return 0
+}
+
+// in sys_windows_386.s and sys_windows_amd64.s
+func profileloop()
+
+var profiletimer uintptr
+
+func profilem(mp *m) {
+       var r *context
+       rbuf := make([]byte, unsafe.Sizeof(*r)+15)
+
+       tls := &mp.tls[0]
+       if mp == &m0 {
+               tls = &tls0[0]
+       }
+       gp := *((**g)(unsafe.Pointer(tls)))
+
+       // align Context to 16 bytes
+       r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
+       r.contextflags = _CONTEXT_CONTROL
+       stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r)))
+       dosigprof(r, gp, mp)
+}
+
+func profileloop1() {
+       stdcall2(_SetThreadPriority, currentThread, _THREAD_PRIORITY_HIGHEST)
+
+       for {
+               stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
+               first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
+               for mp := first; mp != nil; mp = mp.alllink {
+                       thread := atomicloaduintptr(&mp.thread)
+                       // Do not profile threads blocked on Notes,
+                       // this includes idle worker threads,
+                       // idle timer thread, idle heap scavenger, etc.
+                       if thread == 0 || mp.profilehz == 0 || mp.blocked {
+                               continue
+                       }
+                       stdcall1(_SuspendThread, thread)
+                       if mp.profilehz != 0 && !mp.blocked {
+                               profilem(mp)
+                       }
+                       stdcall1(_ResumeThread, thread)
+               }
+       }
+}
+
+var cpuprofilerlock mutex
+
+func resetcpuprofiler(hz int32) {
+       lock(&cpuprofilerlock)
+       if profiletimer == 0 {
+               timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
+               atomicstoreuintptr(&profiletimer, timer)
+               thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
+               stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
+               stdcall1(_CloseHandle, thread)
+       }
+       unlock(&cpuprofilerlock)
+
+       ms := int32(0)
+       due := ^int64(^uint64(1 << 63))
+       if hz > 0 {
+               ms = 1000 / hz
+               if ms == 0 {
+                       ms = 1
+               }
+               due = int64(ms) * -10000
+       }
+       stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
+       atomicstore((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
+}
+
+func memlimit() uintptr {
+       return 0
+}
+
+var (
+       badsignalmsg [100]byte
+       badsignallen int32
+)
+
+func setBadSignalMsg() {
+       const msg = "runtime: signal received on thread not created by Go.\n"
+       for i, c := range msg {
+               badsignalmsg[i] = byte(c)
+               badsignallen++
+       }
+}
+
+func crash() {
+       // TODO: This routine should do whatever is needed
+       // to make the Windows program abort/crash as it
+       // would if Go was not intercepting signals.
+       // On Unix the routine would remove the custom signal
+       // handler and then raise a signal (like SIGABRT).
+       // Something like that should happen here.
+       // It's okay to leave this empty for now: if crash returns
+       // the ordinary exit-after-panic happens.
+}
diff --git a/src/runtime/os1_windows_386.go b/src/runtime/os1_windows_386.go
new file mode 100644 (file)
index 0000000..0afef91
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+var text struct{}
+
+func dumpregs(r *context) {
+       print("eax     ", hex(r.eax), "\n")
+       print("ebx     ", hex(r.ebx), "\n")
+       print("ecx     ", hex(r.ecx), "\n")
+       print("edx     ", hex(r.edx), "\n")
+       print("edi     ", hex(r.edi), "\n")
+       print("esi     ", hex(r.esi), "\n")
+       print("ebp     ", hex(r.ebp), "\n")
+       print("esp     ", hex(r.esp), "\n")
+       print("eip     ", hex(r.eip), "\n")
+       print("eflags  ", hex(r.eflags), "\n")
+       print("cs      ", hex(r.segcs), "\n")
+       print("fs      ", hex(r.segfs), "\n")
+       print("gs      ", hex(r.seggs), "\n")
+}
+
+func isgoexception(info *exceptionrecord, r *context) bool {
+       // Only handle exception if executing instructions in Go binary
+       // (not Windows library code).
+       if r.eip < uint32(uintptr(unsafe.Pointer(&text))) || uint32(uintptr(unsafe.Pointer(&etext))) < r.eip {
+               return false
+       }
+
+       if issigpanic(info.exceptioncode) == 0 {
+               return false
+       }
+
+       return true
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
+       if !isgoexception(info, r) {
+               return _EXCEPTION_CONTINUE_SEARCH
+       }
+
+       // Make it look like a call to the signal func.
+       // Have to pass arguments out of band since
+       // augmenting the stack frame would break
+       // the unwinding code.
+       gp.sig = info.exceptioncode
+       gp.sigcode0 = uintptr(info.exceptioninformation[0])
+       gp.sigcode1 = uintptr(info.exceptioninformation[1])
+       gp.sigpc = uintptr(r.eip)
+
+       // Only push runtime·sigpanic if r->eip != 0.
+       // If r->eip == 0, probably panicked because of a
+       // call to a nil func.  Not pushing that onto sp will
+       // make the trace look like a call to runtime·sigpanic instead.
+       // (Otherwise the trace will end at runtime·sigpanic and we
+       // won't get to see who faulted.)
+       if r.eip != 0 {
+               sp := unsafe.Pointer(uintptr(r.esp))
+               sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
+               *((*uintptr)(sp)) = uintptr(r.eip)
+               r.esp = uint32(uintptr(sp))
+       }
+       r.eip = uint32(funcPC(sigpanic))
+       return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
+       _g_ := getg()
+
+       if panicking != 0 { // traceback already printed
+               exit(2)
+       }
+       panicking = 1
+
+       print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.eip), "\n")
+
+       print("PC=", hex(r.eip), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               tracebacktrap(uintptr(r.eip), uintptr(r.esp), 0, gp)
+               tracebackothers(gp)
+               dumpregs(r)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+       return 0 // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func dosigprof(r *context, gp *g, mp *m) {
+       sigprof((*byte)(unsafe.Pointer(uintptr(r.eip))), (*byte)(unsafe.Pointer(uintptr(r.esp))), nil, gp, mp)
+}
diff --git a/src/runtime/os1_windows_amd64.go b/src/runtime/os1_windows_amd64.go
new file mode 100644 (file)
index 0000000..0d21b38
--- /dev/null
@@ -0,0 +1,137 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+       "unsafe"
+)
+
+var text struct{}
+
+func dumpregs(r *context) {
+       print("rax     ", hex(r.rax), "\n")
+       print("rbx     ", hex(r.rbx), "\n")
+       print("rcx     ", hex(r.rcx), "\n")
+       print("rdi     ", hex(r.rdi), "\n")
+       print("rsi     ", hex(r.rsi), "\n")
+       print("rbp     ", hex(r.rbp), "\n")
+       print("rsp     ", hex(r.rsp), "\n")
+       print("r8      ", hex(r.r8), "\n")
+       print("r9      ", hex(r.r9), "\n")
+       print("r10     ", hex(r.r10), "\n")
+       print("r11     ", hex(r.r11), "\n")
+       print("r12     ", hex(r.r12), "\n")
+       print("r13     ", hex(r.r13), "\n")
+       print("r14     ", hex(r.r14), "\n")
+       print("r15     ", hex(r.r15), "\n")
+       print("rip     ", hex(r.rip), "\n")
+       print("rflags  ", hex(r.eflags), "\n")
+       print("cs      ", hex(r.segcs), "\n")
+       print("fs      ", hex(r.segfs), "\n")
+       print("gs      ", hex(r.seggs), "\n")
+}
+
+func isgoexception(info *exceptionrecord, r *context) bool {
+       // Only handle exception if executing instructions in Go binary
+       // (not Windows library code).
+       if r.rip < uint64(uintptr(unsafe.Pointer(&text))) || uint64(uintptr(unsafe.Pointer(&etext))) < r.rip {
+               return false
+       }
+
+       if issigpanic(info.exceptioncode) == 0 {
+               return false
+       }
+
+       return true
+}
+
+// Called by sigtramp from Windows VEH handler.
+// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
+// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
+
+func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
+       if !isgoexception(info, r) {
+               return _EXCEPTION_CONTINUE_SEARCH
+       }
+
+       // Make it look like a call to the signal func.
+       // Have to pass arguments out of band since
+       // augmenting the stack frame would break
+       // the unwinding code.
+       gp.sig = info.exceptioncode
+       gp.sigcode0 = uintptr(info.exceptioninformation[0])
+       gp.sigcode1 = uintptr(info.exceptioninformation[1])
+       gp.sigpc = uintptr(r.rip)
+
+       // Only push runtime·sigpanic if r->rip != 0.
+       // If r->rip == 0, probably panicked because of a
+       // call to a nil func.  Not pushing that onto sp will
+       // make the trace look like a call to runtime·sigpanic instead.
+       // (Otherwise the trace will end at runtime·sigpanic and we
+       // won't get to see who faulted.)
+       if r.rip != 0 {
+               sp := unsafe.Pointer(uintptr(r.rsp))
+               sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
+               *((*uintptr)(sp)) = uintptr(r.rip)
+               r.rsp = uint64(uintptr(sp))
+       }
+       r.rip = uint64(funcPC(sigpanic))
+       return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// It seems Windows searches ContinueHandler's list even
+// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
+// firstcontinuehandler will stop that search,
+// if exceptionhandler did the same earlier.
+func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
+       if !isgoexception(info, r) {
+               return _EXCEPTION_CONTINUE_SEARCH
+       }
+       return _EXCEPTION_CONTINUE_EXECUTION
+}
+
+// lastcontinuehandler is reached, because runtime cannot handle
+// current exception. lastcontinuehandler will print crash info and exit.
+func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
+       _g_ := getg()
+
+       if panicking != 0 { // traceback already printed
+               exit(2)
+       }
+       panicking = 1
+
+       print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.rip), "\n")
+
+       print("PC=", hex(r.rip), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               tracebacktrap(uintptr(r.rip), uintptr(r.rsp), 0, gp)
+               tracebackothers(gp)
+               dumpregs(r)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+       return 0 // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func dosigprof(r *context, gp *g, mp *m) {
+       sigprof((*byte)(unsafe.Pointer(uintptr(r.rip))), (*byte)(unsafe.Pointer(uintptr(r.rsp))), nil, gp, mp)
+}
diff --git a/src/runtime/os2_darwin.go b/src/runtime/os2_darwin.go
new file mode 100644 (file)
index 0000000..542bd74
--- /dev/null
@@ -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 runtime
+
+const (
+       _NSIG        = 32
+       _SI_USER     = 0 /* empirically true, but not what headers say */
+       _SIG_BLOCK   = 1
+       _SIG_UNBLOCK = 2
+       _SIG_SETMASK = 3
+       _SS_DISABLE  = 4
+)
diff --git a/src/runtime/os2_dragonfly.go b/src/runtime/os2_dragonfly.go
new file mode 100644 (file)
index 0000000..0a20ed4
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       _NSIG       = 33
+       _SI_USER    = 0x10001
+       _SS_DISABLE = 4
+       _RLIMIT_AS  = 10
+)
diff --git a/src/runtime/os2_freebsd.go b/src/runtime/os2_freebsd.go
new file mode 100644 (file)
index 0000000..f67211f
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       _SS_DISABLE = 4
+       _NSIG       = 33
+       _SI_USER    = 0x10001
+       _RLIMIT_AS  = 10
+)
diff --git a/src/runtime/os2_linux.go b/src/runtime/os2_linux.go
new file mode 100644 (file)
index 0000000..eaa9f0e
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       _SS_DISABLE  = 2
+       _NSIG        = 65
+       _SI_USER     = 0
+       _SIG_SETMASK = 2
+       _RLIMIT_AS   = 9
+)
+
+// It's hard to tease out exactly how big a Sigset is, but
+// rt_sigprocmask crashes if we get it wrong, so if binaries
+// are running, this is right.
+type sigset [2]uint32
+
+type rlimit struct {
+       rlim_cur uintptr
+       rlim_max uintptr
+}
diff --git a/src/runtime/os2_openbsd.go b/src/runtime/os2_openbsd.go
new file mode 100644 (file)
index 0000000..1e785ad
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       _SS_DISABLE  = 4
+       _SIG_BLOCK   = 1
+       _SIG_UNBLOCK = 2
+       _SIG_SETMASK = 3
+       _NSIG        = 33
+       _SI_USER     = 0
+)
diff --git a/src/runtime/os2_solaris.go b/src/runtime/os2_solaris.go
new file mode 100644 (file)
index 0000000..26ca15f
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       _SS_DISABLE  = 2
+       _SIG_SETMASK = 3
+       _NSIG        = 73 /* number of signals in sigtable array */
+       _SI_USER     = 0
+       _RLIMIT_AS   = 10
+)
diff --git a/src/runtime/os2_windows.go b/src/runtime/os2_windows.go
new file mode 100644 (file)
index 0000000..d5b1f47
--- /dev/null
@@ -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.
+
+package runtime
+
+import "unsafe"
+
+// Call a Windows function with stdcall conventions,
+// and switch to os stack during the call.
+func asmstdcall(fn unsafe.Pointer)
+
+func getlasterror() uint32
+func setlasterror(err uint32)
+
+// Function to be called by windows CreateThread
+// to start new os thread.
+func tstart_stdcall(newm *m) uint32
+
+func ctrlhandler(_type uint32) uint32
+
+// TODO(brainman): should not need those
+const (
+       _NSIG = 65
+)
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
new file mode 100644 (file)
index 0000000..1df74fa
--- /dev/null
@@ -0,0 +1,493 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//go:cgo_export_dynamic runtime.end _end
+//go:cgo_export_dynamic runtime.etext _etext
+//go:cgo_export_dynamic runtime.edata _edata
+
+//go:cgo_import_dynamic libc____errno ___errno "libc.so"
+//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so"
+//go:cgo_import_dynamic libc_close close "libc.so"
+//go:cgo_import_dynamic libc_exit exit "libc.so"
+//go:cgo_import_dynamic libc_fstat fstat "libc.so"
+//go:cgo_import_dynamic libc_getcontext getcontext "libc.so"
+//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so"
+//go:cgo_import_dynamic libc_madvise madvise "libc.so"
+//go:cgo_import_dynamic libc_malloc malloc "libc.so"
+//go:cgo_import_dynamic libc_mmap mmap "libc.so"
+//go:cgo_import_dynamic libc_munmap munmap "libc.so"
+//go:cgo_import_dynamic libc_open open "libc.so"
+//go:cgo_import_dynamic libc_pthread_attr_destroy pthread_attr_destroy "libc.so"
+//go:cgo_import_dynamic libc_pthread_attr_getstack pthread_attr_getstack "libc.so"
+//go:cgo_import_dynamic libc_pthread_attr_init pthread_attr_init "libc.so"
+//go:cgo_import_dynamic libc_pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so"
+//go:cgo_import_dynamic libc_pthread_attr_setstack pthread_attr_setstack "libc.so"
+//go:cgo_import_dynamic libc_pthread_create pthread_create "libc.so"
+//go:cgo_import_dynamic libc_raise raise "libc.so"
+//go:cgo_import_dynamic libc_read read "libc.so"
+//go:cgo_import_dynamic libc_select select "libc.so"
+//go:cgo_import_dynamic libc_sched_yield sched_yield "libc.so"
+//go:cgo_import_dynamic libc_sem_init sem_init "libc.so"
+//go:cgo_import_dynamic libc_sem_post sem_post "libc.so"
+//go:cgo_import_dynamic libc_sem_reltimedwait_np sem_reltimedwait_np "libc.so"
+//go:cgo_import_dynamic libc_sem_wait sem_wait "libc.so"
+//go:cgo_import_dynamic libc_setitimer setitimer "libc.so"
+//go:cgo_import_dynamic libc_sigaction sigaction "libc.so"
+//go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.so"
+//go:cgo_import_dynamic libc_sigprocmask sigprocmask "libc.so"
+//go:cgo_import_dynamic libc_sysconf sysconf "libc.so"
+//go:cgo_import_dynamic libc_usleep usleep "libc.so"
+//go:cgo_import_dynamic libc_write write "libc.so"
+
+//go:linkname libc____errno libc____errno
+//go:linkname libc_clock_gettime libc_clock_gettime
+//go:linkname libc_close libc_close
+//go:linkname libc_exit libc_exit
+//go:linkname libc_fstat libc_fstat
+//go:linkname libc_getcontext libc_getcontext
+//go:linkname libc_getrlimit libc_getrlimit
+//go:linkname libc_madvise libc_madvise
+//go:linkname libc_malloc libc_malloc
+//go:linkname libc_mmap libc_mmap
+//go:linkname libc_munmap libc_munmap
+//go:linkname libc_open libc_open
+//go:linkname libc_pthread_attr_destroy libc_pthread_attr_destroy
+//go:linkname libc_pthread_attr_getstack libc_pthread_attr_getstack
+//go:linkname libc_pthread_attr_init libc_pthread_attr_init
+//go:linkname libc_pthread_attr_setdetachstate libc_pthread_attr_setdetachstate
+//go:linkname libc_pthread_attr_setstack libc_pthread_attr_setstack
+//go:linkname libc_pthread_create libc_pthread_create
+//go:linkname libc_raise libc_raise
+//go:linkname libc_read libc_read
+//go:linkname libc_select libc_select
+//go:linkname libc_sched_yield libc_sched_yield
+//go:linkname libc_sem_init libc_sem_init
+//go:linkname libc_sem_post libc_sem_post
+//go:linkname libc_sem_reltimedwait_np libc_sem_reltimedwait_np
+//go:linkname libc_sem_wait libc_sem_wait
+//go:linkname libc_setitimer libc_setitimer
+//go:linkname libc_sigaction libc_sigaction
+//go:linkname libc_sigaltstack libc_sigaltstack
+//go:linkname libc_sigprocmask libc_sigprocmask
+//go:linkname libc_sysconf libc_sysconf
+//go:linkname libc_usleep libc_usleep
+//go:linkname libc_write libc_write
+
+var (
+       libc____errno,
+       libc_clock_gettime,
+       libc_close,
+       libc_exit,
+       libc_fstat,
+       libc_getcontext,
+       libc_getrlimit,
+       libc_madvise,
+       libc_malloc,
+       libc_mmap,
+       libc_munmap,
+       libc_open,
+       libc_pthread_attr_destroy,
+       libc_pthread_attr_getstack,
+       libc_pthread_attr_init,
+       libc_pthread_attr_setdetachstate,
+       libc_pthread_attr_setstack,
+       libc_pthread_create,
+       libc_raise,
+       libc_read,
+       libc_sched_yield,
+       libc_select,
+       libc_sem_init,
+       libc_sem_post,
+       libc_sem_reltimedwait_np,
+       libc_sem_wait,
+       libc_setitimer,
+       libc_sigaction,
+       libc_sigaltstack,
+       libc_sigprocmask,
+       libc_sysconf,
+       libc_usleep,
+       libc_write libcFunc
+)
+
+var sigset_none = sigset{}
+var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
+
+func getncpu() int32 {
+       n := int32(sysconf(__SC_NPROCESSORS_ONLN))
+       if n < 1 {
+               return 1
+       }
+       return n
+}
+
+func osinit() {
+       ncpu = getncpu()
+}
+
+func tstart_sysvicall()
+
+func newosproc(mp *m, _ unsafe.Pointer) {
+       var (
+               attr pthreadattr
+               oset sigset
+               tid  pthread
+               ret  int32
+               size uint64
+       )
+
+       if pthread_attr_init(&attr) != 0 {
+               gothrow("pthread_attr_init")
+       }
+       if pthread_attr_setstack(&attr, 0, 0x200000) != 0 {
+               gothrow("pthread_attr_setstack")
+       }
+       if pthread_attr_getstack(&attr, unsafe.Pointer(&mp.g0.stack.hi), &size) != 0 {
+               gothrow("pthread_attr_getstack")
+       }
+       mp.g0.stack.lo = mp.g0.stack.hi - uintptr(size)
+       if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
+               gothrow("pthread_attr_setdetachstate")
+       }
+
+       // Disable signals during create, so that the new thread starts
+       // with signals disabled.  It will enable them in minit.
+       sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
+       ret = pthread_create(&tid, &attr, funcPC(tstart_sysvicall), unsafe.Pointer(mp))
+       sigprocmask(_SIG_SETMASK, &oset, nil)
+       if ret != 0 {
+               print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n")
+               gothrow("newosproc")
+       }
+}
+
+var urandom_data [_HashRandomBytes]byte
+var urandom_dev = []byte("/dev/random\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&urandom_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+       goenvs_unix()
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+}
+
+func miniterrno()
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       _g_ := getg()
+       asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(libc____errno))
+       // Initialize signal handling
+       signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
+       sigprocmask(_SIG_SETMASK, &sigset_none, nil)
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+       signalstack(nil, 0)
+}
+
+func memlimit() uintptr {
+       /*
+               TODO: Convert to Go when something actually uses the result.
+               Rlimit rl;
+               extern byte runtime·text[], runtime·end[];
+               uintptr used;
+
+               if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
+                       return 0;
+               if(rl.rlim_cur >= 0x7fffffff)
+                       return 0;
+
+               // Estimate our VM footprint excluding the heap.
+               // Not an exact science: use size of binary plus
+               // some room for thread stacks.
+               used = runtime·end - runtime·text + (64<<20);
+               if(used >= rl.rlim_cur)
+                       return 0;
+
+               // If there's not at least 16 MB left, we're probably
+               // not going to be able to do much.  Treat as no limit.
+               rl.rlim_cur -= used;
+               if(rl.rlim_cur < (16<<20))
+                       return 0;
+
+               return rl.rlim_cur - used;
+       */
+
+       return 0
+}
+
+func sigtramp()
+
+func setsig(i int32, fn uintptr, restart bool) {
+       var sa sigactiont
+
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
+       if restart {
+               sa.sa_flags |= _SA_RESTART
+       }
+       sa.sa_mask = sigset_all
+       if fn == funcPC(sighandler) {
+               fn = funcPC(sigtramp)
+       }
+       *((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn
+       sigaction(i, &sa, nil)
+}
+
+func getsig(i int32) uintptr {
+       var sa sigactiont
+       sigaction(i, nil, &sa)
+       if *((*uintptr)(unsafe.Pointer(&sa._funcptr))) == funcPC(sigtramp) {
+               return funcPC(sighandler)
+       }
+       return *((*uintptr)(unsafe.Pointer(&sa._funcptr)))
+}
+
+func signalstack(p *byte, n int32) {
+       var st sigaltstackt
+       st.ss_sp = (*byte)(unsafe.Pointer(p))
+       st.ss_size = uint64(n)
+       st.ss_flags = 0
+       if p == nil {
+               st.ss_flags = _SS_DISABLE
+       }
+       sigaltstack(&st, nil)
+}
+
+func unblocksignals() {
+       sigprocmask(_SIG_SETMASK, &sigset_none, nil)
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       var sem *semt
+       _g_ := getg()
+
+       // Call libc's malloc rather than malloc.  This will
+       // allocate space on the C heap.  We can't call malloc
+       // here because it could cause a deadlock.
+       _g_.m.libcall.fn = uintptr(libc_malloc)
+       _g_.m.libcall.n = 1
+       memclr(unsafe.Pointer(&_g_.m.scratch), uintptr(len(_g_.m.scratch.v)))
+       _g_.m.scratch.v[0] = unsafe.Sizeof(*sem)
+       _g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch))
+       asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_g_.m.libcall))
+       sem = (*semt)(unsafe.Pointer(_g_.m.libcall.r1))
+       if sem_init(sem, 0, 0) != 0 {
+               gothrow("sem_init")
+       }
+       return uintptr(unsafe.Pointer(sem))
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+       _m_ := getg().m
+       if ns >= 0 {
+               _m_.ts.tv_sec = ns / 1000000000
+               _m_.ts.tv_nsec = ns % 1000000000
+
+               _m_.libcall.fn = uintptr(unsafe.Pointer(libc_sem_reltimedwait_np))
+               _m_.libcall.n = 2
+               memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v)))
+               _m_.scratch.v[0] = _m_.waitsema
+               _m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts))
+               _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
+               asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
+               if *_m_.perrno != 0 {
+                       if *_m_.perrno == _ETIMEDOUT || *_m_.perrno == _EAGAIN || *_m_.perrno == _EINTR {
+                               return -1
+                       }
+                       gothrow("sem_reltimedwait_np")
+               }
+               return 0
+       }
+       for {
+               _m_.libcall.fn = uintptr(unsafe.Pointer(libc_sem_wait))
+               _m_.libcall.n = 1
+               memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v)))
+               _m_.scratch.v[0] = _m_.waitsema
+               _m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
+               asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
+               if _m_.libcall.r1 == 0 {
+                       break
+               }
+               if *_m_.perrno == _EINTR {
+                       continue
+               }
+               gothrow("sem_wait")
+       }
+       return 0
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
+               gothrow("sem_post")
+       }
+}
+
+//go:nosplit
+func close(fd int32) int32 {
+       return int32(sysvicall1(libc_close, uintptr(fd)))
+}
+
+//go:nosplit
+func exit(r int32) {
+       sysvicall1(libc_exit, uintptr(r))
+}
+
+//go:nosplit
+func getcontext(context *ucontext) /* int32 */ {
+       sysvicall1(libc_getcontext, uintptr(unsafe.Pointer(context)))
+}
+
+//go:nosplit
+func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
+       sysvicall3(libc_madvise, uintptr(addr), uintptr(n), uintptr(flags))
+}
+
+//go:nosplit
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer {
+       return unsafe.Pointer(sysvicall6(libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off)))
+}
+
+//go:nosplit
+func munmap(addr unsafe.Pointer, n uintptr) {
+       sysvicall2(libc_munmap, uintptr(addr), uintptr(n))
+}
+
+func nanotime1()
+
+//go:nosplit
+func nanotime() int64 {
+       return int64(sysvicall0(libcFunc(funcPC(nanotime1))))
+}
+
+//go:nosplit
+func open(path *byte, mode, perm int32) int32 {
+       return int32(sysvicall3(libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm)))
+}
+
+func pthread_attr_destroy(attr *pthreadattr) int32 {
+       return int32(sysvicall1(libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr))))
+}
+
+func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 {
+       return int32(sysvicall3(libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size))))
+}
+
+func pthread_attr_init(attr *pthreadattr) int32 {
+       return int32(sysvicall1(libc_pthread_attr_init, uintptr(unsafe.Pointer(attr))))
+}
+
+func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 {
+       return int32(sysvicall2(libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state)))
+}
+
+func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 {
+       return int32(sysvicall3(libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size)))
+}
+
+func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 {
+       return int32(sysvicall4(libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg)))
+}
+
+func raise(sig int32) /* int32 */ {
+       sysvicall1(libc_raise, uintptr(sig))
+}
+
+//go:nosplit
+func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 {
+       return int32(sysvicall3(libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte)))
+}
+
+//go:nosplit
+func sem_init(sem *semt, pshared int32, value uint32) int32 {
+       return int32(sysvicall3(libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value)))
+}
+
+//go:nosplit
+func sem_post(sem *semt) int32 {
+       return int32(sysvicall1(libc_sem_post, uintptr(unsafe.Pointer(sem))))
+}
+
+//go:nosplit
+func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 {
+       return int32(sysvicall2(libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout))))
+}
+
+//go:nosplit
+func sem_wait(sem *semt) int32 {
+       return int32(sysvicall1(libc_sem_wait, uintptr(unsafe.Pointer(sem))))
+}
+
+func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ {
+       sysvicall3(libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue)))
+}
+
+func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ {
+       sysvicall3(libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact)))
+}
+
+func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
+       sysvicall2(libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
+}
+
+func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
+       sysvicall3(libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
+}
+
+func sysconf(name int32) int64 {
+       return int64(sysvicall1(libc_sysconf, uintptr(name)))
+}
+
+func usleep1(uint32)
+
+//go:nosplit
+func usleep(µs uint32) {
+       usleep1(µs)
+}
+
+//go:nosplit
+func write(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 {
+       return int32(sysvicall3(libc_write, uintptr(fd), uintptr(buf), uintptr(nbyte)))
+}
+
+func osyield1()
+
+//go:nosplit
+func osyield() {
+       _g_ := getg()
+
+       // Check the validity of m because we might be called in cgo callback
+       // path early enough where there isn't a m available yet.
+       if _g_ != nil && _g_.m != nil {
+               sysvicall0(libc_sched_yield)
+               return
+       }
+       osyield1()
+}
diff --git a/src/runtime/os_darwin.c b/src/runtime/os_darwin.c
deleted file mode 100644 (file)
index bbd2928..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-extern SigTab runtime·sigtab[];
-
-static Sigset sigset_none;
-static Sigset sigset_all = ~(Sigset)0;
-
-static void
-unimplemented(int8 *name)
-{
-       runtime·prints(name);
-       runtime·prints(" not implemented\n");
-       *(int32*)1231 = 1231;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       runtime·mach_semrelease(mp->waitsema);
-}
-
-static void
-semacreate(void)
-{
-       g->m->scalararg[0] = runtime·mach_semcreate();
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       uintptr x;
-       void (*fn)(void);
-       
-       fn = semacreate;
-       runtime·onM(&fn);
-       x = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       return x;
-}
-
-// BSD interface for threading.
-void
-runtime·osinit(void)
-{
-       // 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];
-       uint32 out;
-       int32 ret;
-       uintptr nout;
-
-       mib[0] = 6;
-       mib[1] = 3;
-       nout = sizeof out;
-       out = 0;
-       ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
-       if(ret >= 0)
-               runtime·ncpu = out;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       #pragma dataflag NOPTR
-       static byte urandom_data[HashRandomBytes];
-       int32 fd;
-       fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = urandom_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-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 library 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 *mp, void *stk)
-{
-       int32 errno;
-       Sigset oset;
-
-       mp->tls[0] = mp->id;    // so 386 asm can find it
-       if(0){
-               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, mp, mp->g0, runtime·mstart);
-       runtime·sigprocmask(SIG_SETMASK, &oset, nil);
-
-       if(errno < 0) {
-               runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -errno);
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-// 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
-       mp->gsignal->m = mp;
-}
-
-// 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.
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 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);
-}
-
-// Mach IPC, to get at semaphores
-// Definitions are in /usr/include/mach on a Mac.
-
-static void
-macherror(int32 r, int8 *fn)
-{
-       runtime·prints("mach error ");
-       runtime·prints(fn);
-       runtime·prints(": ");
-       runtime·printint(r);
-       runtime·prints("\n");
-       runtime·throw("mach error");
-}
-
-enum
-{
-       DebugMach = 0
-};
-
-static MachNDR zerondr;
-
-#define MACH_MSGH_BITS(a, b) ((a) | ((b)<<8))
-
-static int32
-mach_msg(MachHeader *h,
-       int32 op,
-       uint32 send_size,
-       uint32 rcv_size,
-       uint32 rcv_name,
-       uint32 timeout,
-       uint32 notify)
-{
-       // TODO: Loop on interrupt.
-       return runtime·mach_msg_trap(h, op, send_size, rcv_size, rcv_name, timeout, notify);
-}
-
-// Mach RPC (MIG)
-
-enum
-{
-       MinMachMsg = 48,
-       Reply = 100,
-};
-
-#pragma pack on
-typedef struct CodeMsg CodeMsg;
-struct CodeMsg
-{
-       MachHeader h;
-       MachNDR NDR;
-       int32 code;
-};
-#pragma pack off
-
-static int32
-machcall(MachHeader *h, int32 maxsize, int32 rxsize)
-{
-       uint32 *p;
-       int32 i, ret, id;
-       uint32 port;
-       CodeMsg *c;
-
-       if((port = g->m->machport) == 0){
-               port = runtime·mach_reply_port();
-               g->m->machport = port;
-       }
-
-       h->msgh_bits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
-       h->msgh_local_port = port;
-       h->msgh_reserved = 0;
-       id = h->msgh_id;
-
-       if(DebugMach){
-               p = (uint32*)h;
-               runtime·prints("send:\t");
-               for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
-                       runtime·prints(" ");
-                       runtime·printpointer((void*)p[i]);
-                       if(i%8 == 7)
-                               runtime·prints("\n\t");
-               }
-               if(i%8)
-                       runtime·prints("\n");
-       }
-
-       ret = mach_msg(h, MACH_SEND_MSG|MACH_RCV_MSG,
-               h->msgh_size, maxsize, port, 0, 0);
-       if(ret != 0){
-               if(DebugMach){
-                       runtime·prints("mach_msg error ");
-                       runtime·printint(ret);
-                       runtime·prints("\n");
-               }
-               return ret;
-       }
-
-       if(DebugMach){
-               p = (uint32*)h;
-               runtime·prints("recv:\t");
-               for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
-                       runtime·prints(" ");
-                       runtime·printpointer((void*)p[i]);
-                       if(i%8 == 7)
-                               runtime·prints("\n\t");
-               }
-               if(i%8)
-                       runtime·prints("\n");
-       }
-
-       if(h->msgh_id != id+Reply){
-               if(DebugMach){
-                       runtime·prints("mach_msg reply id mismatch ");
-                       runtime·printint(h->msgh_id);
-                       runtime·prints(" != ");
-                       runtime·printint(id+Reply);
-                       runtime·prints("\n");
-               }
-               return -303;    // MIG_REPLY_MISMATCH
-       }
-
-       // Look for a response giving the return value.
-       // Any call can send this back with an error,
-       // and some calls only have return values so they
-       // send it back on success too.  I don't quite see how
-       // you know it's one of these and not the full response
-       // format, so just look if the message is right.
-       c = (CodeMsg*)h;
-       if(h->msgh_size == sizeof(CodeMsg)
-       && !(h->msgh_bits & MACH_MSGH_BITS_COMPLEX)){
-               if(DebugMach){
-                       runtime·prints("mig result ");
-                       runtime·printint(c->code);
-                       runtime·prints("\n");
-               }
-               return c->code;
-       }
-
-       if(h->msgh_size != rxsize){
-               if(DebugMach){
-                       runtime·prints("mach_msg reply size mismatch ");
-                       runtime·printint(h->msgh_size);
-                       runtime·prints(" != ");
-                       runtime·printint(rxsize);
-                       runtime·prints("\n");
-               }
-               return -307;    // MIG_ARRAY_TOO_LARGE
-       }
-
-       return 0;
-}
-
-
-// Semaphores!
-
-enum
-{
-       Tmach_semcreate = 3418,
-       Rmach_semcreate = Tmach_semcreate + Reply,
-
-       Tmach_semdestroy = 3419,
-       Rmach_semdestroy = Tmach_semdestroy + Reply,
-
-       // Mach calls that get interrupted by Unix signals
-       // return this error code.  We retry them.
-       KERN_ABORTED = 14,
-       KERN_OPERATION_TIMED_OUT = 49,
-};
-
-typedef struct Tmach_semcreateMsg Tmach_semcreateMsg;
-typedef struct Rmach_semcreateMsg Rmach_semcreateMsg;
-typedef struct Tmach_semdestroyMsg Tmach_semdestroyMsg;
-// Rmach_semdestroyMsg = CodeMsg
-
-#pragma pack on
-struct Tmach_semcreateMsg
-{
-       MachHeader h;
-       MachNDR ndr;
-       int32 policy;
-       int32 value;
-};
-
-struct Rmach_semcreateMsg
-{
-       MachHeader h;
-       MachBody body;
-       MachPort semaphore;
-};
-
-struct Tmach_semdestroyMsg
-{
-       MachHeader h;
-       MachBody body;
-       MachPort semaphore;
-};
-#pragma pack off
-
-uint32
-runtime·mach_semcreate(void)
-{
-       union {
-               Tmach_semcreateMsg tx;
-               Rmach_semcreateMsg rx;
-               uint8 pad[MinMachMsg];
-       } m;
-       int32 r;
-
-       m.tx.h.msgh_bits = 0;
-       m.tx.h.msgh_size = sizeof(m.tx);
-       m.tx.h.msgh_remote_port = runtime·mach_task_self();
-       m.tx.h.msgh_id = Tmach_semcreate;
-       m.tx.ndr = zerondr;
-
-       m.tx.policy = 0;        // 0 = SYNC_POLICY_FIFO
-       m.tx.value = 0;
-
-       while((r = machcall(&m.tx.h, sizeof m, sizeof(m.rx))) != 0){
-               if(r == KERN_ABORTED)   // interrupted
-                       continue;
-               macherror(r, "semaphore_create");
-       }
-       if(m.rx.body.msgh_descriptor_count != 1)
-               unimplemented("mach_semcreate desc count");
-       return m.rx.semaphore.name;
-}
-
-void
-runtime·mach_semdestroy(uint32 sem)
-{
-       union {
-               Tmach_semdestroyMsg tx;
-               uint8 pad[MinMachMsg];
-       } m;
-       int32 r;
-
-       m.tx.h.msgh_bits = MACH_MSGH_BITS_COMPLEX;
-       m.tx.h.msgh_size = sizeof(m.tx);
-       m.tx.h.msgh_remote_port = runtime·mach_task_self();
-       m.tx.h.msgh_id = Tmach_semdestroy;
-       m.tx.body.msgh_descriptor_count = 1;
-       m.tx.semaphore.name = sem;
-       m.tx.semaphore.disposition = MACH_MSG_TYPE_MOVE_SEND;
-       m.tx.semaphore.type = 0;
-
-       while((r = machcall(&m.tx.h, sizeof m, 0)) != 0){
-               if(r == KERN_ABORTED)   // interrupted
-                       continue;
-               macherror(r, "semaphore_destroy");
-       }
-}
-
-// The other calls have simple system call traps in sys_darwin_{amd64,386}.s
-int32 runtime·mach_semaphore_wait(uint32 sema);
-int32 runtime·mach_semaphore_timedwait(uint32 sema, uint32 sec, uint32 nsec);
-int32 runtime·mach_semaphore_signal(uint32 sema);
-int32 runtime·mach_semaphore_signal_all(uint32 sema);
-
-static void
-semasleep(void)
-{
-       int32 r, secs, nsecs;
-       int64 ns;
-       
-       ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
-       g->m->scalararg[0] = 0;
-       g->m->scalararg[1] = 0;
-
-       if(ns >= 0) {
-               secs = runtime·timediv(ns, 1000000000, &nsecs);
-               r = runtime·mach_semaphore_timedwait(g->m->waitsema, secs, nsecs);
-               if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT) {
-                       g->m->scalararg[0] = -1;
-                       return;
-               }
-               if(r != 0)
-                       macherror(r, "semaphore_wait");
-               g->m->scalararg[0] = 0;
-               return;
-       }
-       while((r = runtime·mach_semaphore_wait(g->m->waitsema)) != 0) {
-               if(r == KERN_ABORTED)   // interrupted
-                       continue;
-               macherror(r, "semaphore_wait");
-       }
-       g->m->scalararg[0] = 0;
-       return;
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       int32 r;
-       void (*fn)(void);
-
-       g->m->scalararg[0] = (uint32)ns;
-       g->m->scalararg[1] = (uint32)(ns>>32);
-       fn = semasleep;
-       runtime·onM(&fn);
-       r = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       return r;
-}
-
-static int32 mach_semrelease_errno;
-
-static void
-mach_semrelease_fail(void)
-{
-       macherror(mach_semrelease_errno, "semaphore_signal");
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·mach_semrelease(uint32 sem)
-{
-       int32 r;
-       void (*fn)(void);
-
-       while((r = runtime·mach_semaphore_signal(sem)) != 0) {
-               if(r == KERN_ABORTED)   // interrupted
-                       continue;
-               
-               // mach_semrelease must be completely nosplit,
-               // because it is called from Go code.
-               // If we're going to die, start that process on the m stack
-               // to avoid a Go stack split.
-               // Only do that if we're actually running on the g stack.
-               // We might be on the gsignal stack, and if so, onM will abort.
-               // We use the global variable instead of scalararg because
-               // we might be on the gsignal stack, having interrupted a
-               // normal call to onM. It doesn't quite matter, since the
-               // program is about to die, but better to be clean.
-               mach_semrelease_errno = r;
-               fn = mach_semrelease_fail;
-               if(g == g->m->curg)
-                       runtime·onM(&fn);
-               else
-                       fn();
-       }
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·osyield(void)
-{
-       runtime·usleep(1);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       // NOTE(rsc): Could use getrlimit here,
-       // like on FreeBSD or Linux, but Darwin doesn't enforce
-       // ulimit -v, so it's unclear why we'd try to stay within
-       // the limit.
-       return 0;
-}
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-               
-       runtime·memclr((byte*)&sa, sizeof sa);
-       sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-       if(restart)
-               sa.sa_flags |= SA_RESTART;
-       sa.sa_mask = ~(uintptr)0;
-       sa.sa_tramp = (void*)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
-       *(uintptr*)sa.__sigaction_u = (uintptr)fn;
-       runtime·sigaction(i, &sa, nil);
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       runtime·sigaction(i, nil, &sa);
-       return *(void**)sa.__sigaction_u;
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       StackT st;
-
-       st.ss_sp = (void*)p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index 4327ced91482357d85b8e2c33e6262973699cfa1..d8296e0563eef6f36ba3dd13eea0a9828bdcc853 100644 (file)
@@ -6,19 +6,31 @@ package runtime
 
 import "unsafe"
 
-func bsdthread_create(stk, mm, gg, fn unsafe.Pointer) int32
+func bsdthread_create(stk unsafe.Pointer, mm *m, gg *g, fn uintptr) int32
 func bsdthread_register() int32
+
+//go:noescape
 func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
+
 func mach_reply_port() uint32
 func mach_task_self() uint32
 func mach_thread_self() uint32
+
+//go:noescape
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
-func sigprocmask(sig int32, new, old unsafe.Pointer)
-func sigaction(mode uint32, new, old unsafe.Pointer)
-func sigaltstack(new, old unsafe.Pointer)
+
+//go:noescape
+func sigprocmask(sig uint32, new, old *uint32)
+
+//go:noescape
+func sigaction(mode uint32, new, old *sigactiont)
+
+//go:noescape
+func sigaltstack(new, old *stackt)
+
 func sigtramp()
-func setitimer(mode int32, new, old unsafe.Pointer)
-func mach_semaphore_wait(sema uint32) int32
-func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
-func mach_semaphore_signal(sema uint32) int32
-func mach_semaphore_signal_all(sema uint32) int32
+
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+func raise(int32)
diff --git a/src/runtime/os_darwin.h b/src/runtime/os_darwin.h
deleted file mode 100644 (file)
index e8bb45d..0000000
+++ /dev/null
@@ -1,43 +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.
-
-typedef byte* kevent_udata;
-
-int32  runtime·bsdthread_create(void*, M*, G*, void(*)(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);
-uint32 runtime·mach_semcreate(void);
-void   runtime·mach_semdestroy(uint32);
-void   runtime·mach_semrelease(uint32);
-void   runtime·mach_semreset(uint32);
-uint32 runtime·mach_task_self(void);
-uint32 runtime·mach_task_self(void);
-uint32 runtime·mach_thread_self(void);
-uint32 runtime·mach_thread_self(void);
-int32  runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-
-typedef uint32 Sigset;
-void   runtime·sigprocmask(int32, Sigset*, Sigset*);
-void   runtime·unblocksignals(void);
-
-struct SigactionT;
-void   runtime·sigaction(uintptr, struct SigactionT*, struct SigactionT*);
-
-struct StackT;
-void   runtime·sigaltstack(struct StackT*, struct StackT*);
-void   runtime·sigtramp(void);
-void   runtime·sigpanic(void);
-void   runtime·setitimer(int32, Itimerval*, Itimerval*);
-
-
-enum {
-       NSIG = 32,
-       SI_USER = 0, /* empirically true, but not what headers say */
-       SIG_BLOCK = 1,
-       SIG_UNBLOCK = 2,
-       SIG_SETMASK = 3,
-       SS_DISABLE = 4,
-};
diff --git a/src/runtime/os_dragonfly.c b/src/runtime/os_dragonfly.c
deleted file mode 100644 (file)
index e372205..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-extern SigTab runtime·sigtab[];
-extern int32 runtime·sys_umtx_sleep(uint32*, int32, int32);
-extern int32 runtime·sys_umtx_wakeup(uint32*, int32);
-
-// From DragonFly's <sys/sysctl.h>
-#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 int32
-getncpu(void)
-{
-       uint32 mib[2];
-       uint32 out;
-       int32 ret;
-       uintptr nout;
-
-       // Fetch hw.ncpu via sysctl.
-       mib[0] = CTL_HW;
-       mib[1] = HW_NCPU;
-       nout = sizeof out;
-       out = 0;
-       ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
-       if(ret >= 0)
-               return out;
-       else
-               return 1;
-}
-
-static void futexsleep(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
-{
-       void (*fn)(void);
-
-       g->m->ptrarg[0] = addr;
-       g->m->scalararg[0] = val;
-       g->m->ptrarg[1] = &ns;
-
-       fn = futexsleep;
-       runtime·onM(&fn);
-}
-
-static void
-futexsleep(void)
-{
-       uint32 *addr;
-       uint32 val;
-       int64 ns;
-       int32 timeout = 0;
-       int32 ret;
-
-       addr = g->m->ptrarg[0];
-       val = g->m->scalararg[0];
-       ns = *(int64*)g->m->ptrarg[1];
-       g->m->ptrarg[0] = nil;
-       g->m->scalararg[0] = 0;
-       g->m->ptrarg[1] = nil;
-
-       if(ns >= 0) {
-               // The timeout is specified in microseconds - ensure that we
-               // do not end up dividing to zero, which would put us to sleep
-               // indefinitely...
-               timeout = runtime·timediv(ns, 1000, nil);
-               if(timeout == 0)
-                       timeout = 1;
-       }
-
-       // sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
-       // expires or EBUSY if the mutex value does not match. 
-       ret = runtime·sys_umtx_sleep(addr, val, timeout);
-       if(ret >= 0 || ret == -EINTR || ret == -EAGAIN || ret == -EBUSY)
-               return;
-
-       runtime·prints("umtx_wait addr=");
-       runtime·printpointer(addr);
-       runtime·prints(" val=");
-       runtime·printint(val);
-       runtime·prints(" ret=");
-       runtime·printint(ret);
-       runtime·prints("\n");
-       *(int32*)0x1005 = 0x1005;
-}
-
-static void badfutexwakeup(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·futexwakeup(uint32 *addr, uint32 cnt)
-{
-       int32 ret;
-       void (*fn)(void);
-
-       ret = runtime·sys_umtx_wakeup(addr, cnt);
-       if(ret >= 0)
-               return;
-
-       g->m->ptrarg[0] = addr;
-       g->m->scalararg[0] = ret;
-       fn = badfutexwakeup;
-       if(g == g->m->gsignal)
-               fn();
-       else
-               runtime·onM(&fn);
-       *(int32*)0x1006 = 0x1006;
-}
-
-static void
-badfutexwakeup(void)
-{
-       void *addr;
-       int32 ret;
-       
-       addr = g->m->ptrarg[0];
-       ret = g->m->scalararg[0];
-       runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
-}
-
-void runtime·lwp_start(void*);
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       Lwpparams params;
-       Sigset oset;
-
-       if(0){
-               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*)&params, sizeof params);
-
-       params.func = runtime·lwp_start;
-       params.arg = (byte*)mp;
-       params.stack = (byte*)stk;
-       params.tid1 = (int32*)&mp->procid;
-       params.tid2 = nil;
-
-       mp->tls[0] = mp->id;    // so 386 asm can find it
-
-       runtime·lwp_create(&params);
-       runtime·sigprocmask(&oset, nil);
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getncpu();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       #pragma dataflag NOPTR
-       static byte urandom_data[HashRandomBytes];
-       int32 fd;
-       fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = urandom_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-// 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);
-       mp->gsignal->m = mp;
-}
-
-// 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
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 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);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       Rlimit rl;
-       extern byte runtime·text[], runtime·end[];
-       uintptr used;
-       
-       if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
-               return 0;
-       if(rl.rlim_cur >= 0x7fffffff)
-               return 0;
-
-       // Estimate our VM footprint excluding the heap.
-       // Not an exact science: use size of binary plus
-       // some room for thread stacks.
-       used = runtime·end - runtime·text + (64<<20);
-       if(used >= rl.rlim_cur)
-               return 0;
-
-       // If there's not at least 16 MB left, we're probably
-       // not going to be able to do much.  Treat as no limit.
-       rl.rlim_cur -= used;
-       if(rl.rlim_cur < (16<<20))
-               return 0;
-
-       return rl.rlim_cur - used;
-}
-
-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 */
-} SigactionT;
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-
-       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);
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       runtime·sigaction(i, nil, &sa);
-       if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
-               return runtime·sighandler;
-       return (void*)sa.__sigaction_u.__sa_sigaction;
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       StackT st;
-
-       st.ss_sp = (void*)p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·sigprocmask(&sigset_none, nil);
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index cdaa06986ee6e85dfb4ba40abe90a3c6fe671bea..0e00f874fb272fc6d912b86e47cca58bf1232008 100644 (file)
@@ -6,15 +6,35 @@ package runtime
 
 import "unsafe"
 
-func lwp_create(param unsafe.Pointer) int32
-func sigaltstack(new, old unsafe.Pointer)
-func sigaction(sig int32, new, old unsafe.Pointer)
-func sigprocmask(new, old unsafe.Pointer)
-func setitimer(mode int32, new, old unsafe.Pointer)
+//go:noescape
+func lwp_create(param *lwpparams) int32
+
+//go:noescape
+func sigaltstack(new, old *sigaltstackt)
+
+//go:noescape
+func sigaction(sig int32, new, old *sigactiont)
+
+//go:noescape
+func sigprocmask(new, old *sigset)
+
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+//go:noescape
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+
+//go:noescape
 func getrlimit(kind int32, limit unsafe.Pointer) int32
+
 func raise(sig int32)
-func sys_umtx_sleep(addr unsafe.Pointer, val, timeout int32) int32
-func sys_umtx_wakeup(addr unsafe.Pointer, val int32) int32
+
+//go:noescape
+func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
+
+//go:noescape
+func sys_umtx_wakeup(addr *uint32, val int32) int32
+
+func osyield()
 
 const stackSystem = 0
diff --git a/src/runtime/os_dragonfly.h b/src/runtime/os_dragonfly.h
deleted file mode 100644 (file)
index 389736a..0000000
+++ /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.
-
-
-typedef byte* kevent_udata;
-
-int32  runtime·lwp_create(Lwpparams*);
-void   runtime·sigpanic(void);
-void   runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
-struct sigaction;
-void   runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void   runtime·sigprocmask(Sigset *, Sigset *);
-void   runtime·unblocksignals(void);
-void   runtime·setitimer(int32, Itimerval*, Itimerval*);
-int32  runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-
-enum {
-       NSIG = 33,
-       SI_USER = 0x10001,
-       SS_DISABLE = 4,
-       RLIMIT_AS = 10,
-};
-
-typedef struct Rlimit Rlimit;
-struct Rlimit {
-       int64   rlim_cur;
-       int64   rlim_max;
-};
-int32  runtime·getrlimit(int32, Rlimit*);
diff --git a/src/runtime/os_freebsd.c b/src/runtime/os_freebsd.c
deleted file mode 100644 (file)
index a513cb6..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-extern SigTab runtime·sigtab[];
-extern int32 runtime·sys_umtx_op(uint32*, int32, uint32, void*, void*);
-
-// From FreeBSD's <sys/sysctl.h>
-#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 int32
-getncpu(void)
-{
-       uint32 mib[2];
-       uint32 out;
-       int32 ret;
-       uintptr nout;
-
-       // Fetch hw.ncpu via sysctl.
-       mib[0] = CTL_HW;
-       mib[1] = HW_NCPU;
-       nout = sizeof out;
-       out = 0;
-       ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
-       if(ret >= 0)
-               return out;
-       else
-               return 1;
-}
-
-// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
-// thus the code is largely similar. See linux/thread.c and lock_futex.c for comments.
-
-static void futexsleep(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
-{
-       void (*fn)(void);
-
-       g->m->ptrarg[0] = addr;
-       g->m->scalararg[0] = val;
-       g->m->ptrarg[1] = &ns;
-
-       fn = futexsleep;
-       runtime·onM(&fn);
-}
-
-static void
-futexsleep(void)
-{
-       uint32 *addr;
-       uint32 val;
-       int64 ns;
-       int32 ret;
-       Timespec ts;
-       
-       addr = g->m->ptrarg[0];
-       val = g->m->scalararg[0];
-       ns = *(int64*)g->m->ptrarg[1];
-       g->m->ptrarg[0] = nil;
-       g->m->scalararg[0] = 0;
-       g->m->ptrarg[1] = nil;
-
-       if(ns < 0) {
-               ret = runtime·sys_umtx_op(addr, UMTX_OP_WAIT_UINT_PRIVATE, val, nil, nil);
-               if(ret >= 0 || ret == -EINTR)
-                       return;
-               goto fail;
-       }
-       // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
-       ts.tv_nsec = 0;
-       ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
-       ret = runtime·sys_umtx_op(addr, UMTX_OP_WAIT_UINT_PRIVATE, val, nil, &ts);
-       if(ret >= 0 || ret == -EINTR)
-               return;
-
-fail:
-       runtime·prints("umtx_wait addr=");
-       runtime·printpointer(addr);
-       runtime·prints(" val=");
-       runtime·printint(val);
-       runtime·prints(" ret=");
-       runtime·printint(ret);
-       runtime·prints("\n");
-       *(int32*)0x1005 = 0x1005;
-}
-
-static void badfutexwakeup(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·futexwakeup(uint32 *addr, uint32 cnt)
-{
-       int32 ret;
-       void (*fn)(void);
-
-       ret = runtime·sys_umtx_op(addr, UMTX_OP_WAKE_PRIVATE, cnt, nil, nil);
-       if(ret >= 0)
-               return;
-
-       g->m->ptrarg[0] = addr;
-       g->m->scalararg[0] = ret;
-       fn = badfutexwakeup;
-       if(g == g->m->gsignal)
-               fn();
-       else
-               runtime·onM(&fn);
-       *(int32*)0x1006 = 0x1006;
-}
-
-static void
-badfutexwakeup(void)
-{
-       void *addr;
-       int32 ret;
-       
-       addr = g->m->ptrarg[0];
-       ret = g->m->scalararg[0];
-       runtime·printf("umtx_wake addr=%p ret=%d\n", addr, ret);
-}
-
-void runtime·thr_start(void*);
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       ThrParam param;
-       Sigset oset;
-
-       if(0){
-               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 = (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->stack.hi;
-       param.stack_size = (byte*)stk - (byte*)mp->g0->stack.hi;
-
-       param.child_tid = (void*)&mp->procid;
-       param.parent_tid = nil;
-       param.tls_base = (void*)&mp->tls[0];
-       param.tls_size = sizeof mp->tls;
-
-       mp->tls[0] = mp->id;    // so 386 asm can find it
-
-       runtime·thr_new(&param, sizeof param);
-       runtime·sigprocmask(&oset, nil);
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getncpu();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       #pragma dataflag NOPTR
-       static byte urandom_data[HashRandomBytes];
-       int32 fd;
-       fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = urandom_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-// 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);
-       mp->gsignal->m = mp;
-}
-
-// 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
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 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);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       Rlimit rl;
-       extern byte runtime·text[], runtime·end[];
-       uintptr used;
-       
-       if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
-               return 0;
-       if(rl.rlim_cur >= 0x7fffffff)
-               return 0;
-
-       // Estimate our VM footprint excluding the heap.
-       // Not an exact science: use size of binary plus
-       // some room for thread stacks.
-       used = runtime·end - runtime·text + (64<<20);
-       if(used >= rl.rlim_cur)
-               return 0;
-
-       // If there's not at least 16 MB left, we're probably
-       // not going to be able to do much.  Treat as no limit.
-       rl.rlim_cur -= used;
-       if(rl.rlim_cur < (16<<20))
-               return 0;
-
-       return rl.rlim_cur - used;
-}
-
-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 */
-} SigactionT;
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-
-       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);
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       runtime·sigaction(i, nil, &sa);
-       if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
-               return runtime·sighandler;
-       return (void*)sa.__sigaction_u.__sa_sigaction;
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       StackT st;
-
-       st.ss_sp = (void*)p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·sigprocmask(&sigset_none, nil);
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index 59708049c8aa95031713cdaf06267260354355af..998fbca0f59380f8cf92ec81f1a32b291cfaa1ce 100644 (file)
@@ -6,12 +6,29 @@ package runtime
 
 import "unsafe"
 
-func thr_new(param unsafe.Pointer, size int32)
-func sigaltstack(new, old unsafe.Pointer)
-func sigaction(sig int32, new, old unsafe.Pointer)
-func sigprocmask(new, old unsafe.Pointer)
-func setitimer(mode int32, new, old unsafe.Pointer)
+//go:noescape
+func thr_new(param *thrparam, size int32)
+
+//go:noescape
+func sigaltstack(new, old *stackt)
+
+//go:noescape
+func sigaction(sig int32, new, old *sigactiont)
+
+//go:noescape
+func sigprocmask(new, old *sigset)
+
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+//go:noescape
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+
+//go:noescape
 func getrlimit(kind int32, limit unsafe.Pointer) int32
 func raise(sig int32)
-func sys_umtx_op(addr unsafe.Pointer, mode int32, val uint32, ptr2, ts unsafe.Pointer) int32
+
+//go:noescape
+func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32
+
+func osyield()
diff --git a/src/runtime/os_freebsd.h b/src/runtime/os_freebsd.h
deleted file mode 100644 (file)
index b86bb39..0000000
+++ /dev/null
@@ -1,29 +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.
-
-typedef byte* kevent_udata;
-
-int32  runtime·thr_new(ThrParam*, int32);
-void   runtime·sigpanic(void);
-void   runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
-struct sigaction;
-void   runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void   runtime·sigprocmask(Sigset *, Sigset *);
-void   runtime·unblocksignals(void);
-void   runtime·setitimer(int32, Itimerval*, Itimerval*);
-int32  runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-
-enum {
-       SS_DISABLE = 4,
-       NSIG = 33,
-       SI_USER = 0x10001,
-       RLIMIT_AS = 10,
-};
-
-typedef struct Rlimit Rlimit;
-struct Rlimit {
-       int64   rlim_cur;
-       int64   rlim_max;
-};
-int32  runtime·getrlimit(int32, Rlimit*);
similarity index 66%
rename from src/runtime/os_freebsd_arm.c
rename to src/runtime/os_freebsd_arm.go
index 2f2d7767f2ed0c4720c8947b06d934ca734c7458..e049cbf9a1ee5aaf8738b2e016f64fdf4582bdfb 100644 (file)
@@ -2,23 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "textflag.h"
+package runtime
 
-void
-runtime·checkgoarm(void)
-{
+func checkgoarm() {
        // TODO(minux)
 }
 
-#pragma textflag NOSPLIT
-int64
-runtime·cputicks(void)
-{
+//go:nosplit
+func cputicks() int64 {
        // 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();
+       return nanotime()
 }
diff --git a/src/runtime/os_linux.c b/src/runtime/os_linux.c
deleted file mode 100644 (file)
index 0d8ffc9..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-extern SigTab runtime·sigtab[];
-
-static Sigset sigset_none;
-static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 };
-
-// Linux futex.
-//
-//     futexsleep(uint32 *addr, uint32 val)
-//     futexwakeup(uint32 *addr)
-//
-// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
-// Futexwakeup wakes up threads sleeping on addr.
-// Futexsleep is allowed to wake up spuriously.
-
-enum
-{
-       FUTEX_WAIT = 0,
-       FUTEX_WAKE = 1,
-};
-
-// Atomically,
-//     if(*addr == val) sleep
-// Might be woken up spuriously; that's allowed.
-// Don't sleep longer than ns; ns < 0 means forever.
-#pragma textflag NOSPLIT
-void
-runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
-{
-       Timespec ts;
-
-       // Some Linux kernels have a bug where futex of
-       // FUTEX_WAIT returns an internal error code
-       // as an errno.  Libpthread ignores the return value
-       // here, and so can we: as it says a few lines up,
-       // spurious wakeups are allowed.
-
-       if(ns < 0) {
-               runtime·futex(addr, FUTEX_WAIT, val, nil, nil, 0);
-               return;
-       }
-       // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
-       ts.tv_nsec = 0;
-       ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec);
-       runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
-}
-
-static void badfutexwakeup(void);
-
-// If any procs are sleeping on addr, wake up at most cnt.
-#pragma textflag NOSPLIT
-void
-runtime·futexwakeup(uint32 *addr, uint32 cnt)
-{
-       int64 ret;
-       void (*fn)(void);
-
-       ret = runtime·futex(addr, FUTEX_WAKE, cnt, nil, nil, 0);
-       if(ret >= 0)
-               return;
-
-       // I don't know that futex wakeup can return
-       // EAGAIN or EINTR, but if it does, it would be
-       // safe to loop and call futex again.
-       g->m->ptrarg[0] = addr;
-       g->m->scalararg[0] = (int32)ret; // truncated but fine
-       fn = badfutexwakeup;
-       if(g == g->m->gsignal)
-               fn();
-       else
-               runtime·onM(&fn);
-       *(int32*)0x1006 = 0x1006;
-}
-
-static void
-badfutexwakeup(void)
-{
-       void *addr;
-       int64 ret;
-       
-       addr = g->m->ptrarg[0];
-       ret = (int32)g->m->scalararg[0];
-       runtime·printf("futexwakeup addr=%p returned %D\n", addr, ret);
-}
-
-extern runtime·sched_getaffinity(uintptr pid, uintptr len, uintptr *buf);
-static int32
-getproccount(void)
-{
-       uintptr buf[16], t;
-       int32 r, cnt, i;
-
-       cnt = 0;
-       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);
-       }
-
-       return cnt ? cnt : 1;
-}
-
-// Clone, the Linux rfork.
-enum
-{
-       CLONE_VM = 0x100,
-       CLONE_FS = 0x200,
-       CLONE_FILES = 0x400,
-       CLONE_SIGHAND = 0x800,
-       CLONE_PTRACE = 0x2000,
-       CLONE_VFORK = 0x4000,
-       CLONE_PARENT = 0x8000,
-       CLONE_THREAD = 0x10000,
-       CLONE_NEWNS = 0x20000,
-       CLONE_SYSVSEM = 0x40000,
-       CLONE_SETTLS = 0x80000,
-       CLONE_PARENT_SETTID = 0x100000,
-       CLONE_CHILD_CLEARTID = 0x200000,
-       CLONE_UNTRACED = 0x800000,
-       CLONE_CHILD_SETTID = 0x1000000,
-       CLONE_STOPPED = 0x2000000,
-       CLONE_NEWUTS = 0x4000000,
-       CLONE_NEWIPC = 0x8000000,
-};
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       int32 ret;
-       int32 flags;
-       Sigset oset;
-
-       /*
-        * note: strace gets confused if we use CLONE_PTRACE here.
-        */
-       flags = CLONE_VM        /* share memory */
-               | CLONE_FS      /* share cwd, etc */
-               | CLONE_FILES   /* share fd table */
-               | CLONE_SIGHAND /* share sig handler table */
-               | CLONE_THREAD  /* revisit - okay for now */
-               ;
-
-       mp->tls[0] = mp->id;    // so 386 asm can find it
-       if(0){
-               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, mp, mp->g0, runtime·mstart);
-       runtime·rtsigprocmask(SIG_SETMASK, &oset, nil, sizeof oset);
-
-       if(ret < 0) {
-               runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -ret);
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getproccount();
-}
-
-// Random bytes initialized at startup.  These come
-// from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c).
-byte*  runtime·startup_random_data;
-uint32 runtime·startup_random_data_len;
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       if(runtime·startup_random_data != nil) {
-               *rnd = runtime·startup_random_data;
-               *rnd_len = runtime·startup_random_data_len;
-       } else {
-               #pragma dataflag NOPTR
-               static byte urandom_data[HashRandomBytes];
-               int32 fd;
-               fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-               if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-                       *rnd = urandom_data;
-                       *rnd_len = HashRandomBytes;
-               } else {
-                       *rnd = nil;
-                       *rnd_len = 0;
-               }
-               runtime·close(fd);
-       }
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-// 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
-       mp->gsignal->m = mp;
-}
-
-// 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.
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 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);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       Rlimit rl;
-       extern byte runtime·text[], runtime·end[];
-       uintptr used;
-
-       if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
-               return 0;
-       if(rl.rlim_cur >= 0x7fffffff)
-               return 0;
-
-       // Estimate our VM footprint excluding the heap.
-       // Not an exact science: use size of binary plus
-       // some room for thread stacks.
-       used = runtime·end - runtime·text + (64<<20);
-       if(used >= rl.rlim_cur)
-               return 0;
-
-       // If there's not at least 16 MB left, we're probably
-       // not going to be able to do much.  Treat as no limit.
-       rl.rlim_cur -= used;
-       if(rl.rlim_cur < (16<<20))
-               return 0;
-
-       return rl.rlim_cur - used;
-}
-
-#ifdef GOARCH_386
-#define sa_handler k_sa_handler
-#endif
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigreturn(void);  // calls rt_sigreturn, only used with SA_RESTORER
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
-       if(restart)
-               sa.sa_flags |= SA_RESTART;
-       sa.sa_mask = ~0ULL;
-       // Although Linux manpage says "sa_restorer element is obsolete and
-       // should not be used". x86_64 kernel requires it. Only use it on
-       // x86.
-#ifdef GOARCH_386
-       sa.sa_restorer = (void*)runtime·sigreturn;
-#endif
-#ifdef GOARCH_amd64
-       sa.sa_restorer = (void*)runtime·sigreturn;
-#endif
-       if(fn == runtime·sighandler)
-               fn = (void*)runtime·sigtramp;
-       sa.sa_handler = fn;
-       if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
-               runtime·throw("rt_sigaction failure");
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       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((void*)sa.sa_handler == runtime·sigtramp)
-               return runtime·sighandler;
-       return (void*)sa.sa_handler;
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       SigaltstackT st;
-
-       st.ss_sp = p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·rtsigprocmask(SIG_SETMASK, &sigset_none, nil, sizeof sigset_none);
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index 41123ad57092c2301c30e6c3cbce19fd53acc654..113219aab043fad4e28a6e283f4d9e1b4890fc09 100644 (file)
@@ -6,12 +6,28 @@ package runtime
 
 import "unsafe"
 
+//go:noescape
 func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
+
+//go:noescape
 func clone(flags int32, stk, mm, gg, fn unsafe.Pointer) int32
-func rt_sigaction(sig uintptr, new, old unsafe.Pointer, size uintptr) int32
-func sigaltstack(new, old unsafe.Pointer)
-func setitimer(mode int32, new, old unsafe.Pointer)
-func rtsigprocmask(sig int32, new, old unsafe.Pointer, size int32)
+
+//go:noescape
+func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32
+
+//go:noescape
+func sigaltstack(new, old *sigaltstackt)
+
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+//go:noescape
+func rtsigprocmask(sig uint32, new, old *sigset, size int32)
+
+//go:noescape
 func getrlimit(kind int32, limit unsafe.Pointer) int32
-func raise(sig int32)
+func raise(sig uint32)
+
+//go:noescape
 func sched_getaffinity(pid, len uintptr, buf *uintptr) int32
+func osyield()
diff --git a/src/runtime/os_linux.h b/src/runtime/os_linux.h
deleted file mode 100644 (file)
index 75606d6..0000000
+++ /dev/null
@@ -1,41 +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.
-
-
-// Linux-specific system calls
-int32  runtime·futex(uint32*, int32, uint32, Timespec*, uint32*, uint32);
-int32  runtime·clone(int32, void*, M*, G*, void(*)(void));
-
-struct SigactionT;
-int32  runtime·rt_sigaction(uintptr, struct SigactionT*, void*, uintptr);
-
-void   runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
-void   runtime·sigpanic(void);
-void runtime·setitimer(int32, Itimerval*, Itimerval*);
-
-enum {
-       SS_DISABLE = 2,
-       NSIG = 65,
-       SI_USER = 0,
-       SIG_SETMASK = 2,
-       RLIMIT_AS = 9,
-};
-
-// It's hard to tease out exactly how big a Sigset is, but
-// rt_sigprocmask crashes if we get it wrong, so if binaries
-// are running, this is right.
-typedef struct Sigset Sigset;
-struct Sigset
-{
-       uint32 mask[2];
-};
-void   runtime·rtsigprocmask(int32, Sigset*, Sigset*, int32);
-void   runtime·unblocksignals(void);
-
-typedef struct Rlimit Rlimit;
-struct Rlimit {
-       uintptr rlim_cur;
-       uintptr rlim_max;
-};
-int32  runtime·getrlimit(int32, Rlimit*);
diff --git a/src/runtime/os_linux_386.c b/src/runtime/os_linux_386.c
deleted file mode 100644 (file)
index dc89d04..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "textflag.h"
-
-#define AT_NULL                0
-#define AT_RANDOM      25
-#define AT_SYSINFO     32
-extern uint32 runtime·_vdso;
-
-#pragma textflag NOSPLIT
-void
-runtime·linux_setup_vdso(int32 argc, byte **argv)
-{
-       byte **envp;
-       uint32 *auxv;
-
-       // 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) {
-               if(auxv[0] == AT_SYSINFO) {
-                       runtime·_vdso = auxv[1];
-                       continue;
-               }
-               if(auxv[0] == AT_RANDOM) {
-                       runtime·startup_random_data = (byte*)auxv[1];
-                       runtime·startup_random_data_len = 16;
-                       continue;
-               }
-       }
-}
diff --git a/src/runtime/os_linux_386.go b/src/runtime/os_linux_386.go
new file mode 100644 (file)
index 0000000..c4f9580
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+const (
+       _AT_NULL    = 0
+       _AT_RANDOM  = 25
+       _AT_SYSINFO = 32
+)
+
+var _vdso uint32
+
+//go:nosplit
+func linux_setup_vdso(argc int32, argv **byte) {
+       // skip over argv, envv to get to auxv
+       n := argc + 1
+       for argv_index(argv, n) != nil {
+               n++
+       }
+       n++
+       auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+
+       for i := 0; auxv[i] != _AT_NULL; i += 2 {
+               switch auxv[i] {
+               case _AT_SYSINFO:
+                       _vdso = auxv[i+1]
+
+               case _AT_RANDOM:
+                       startup_random_data = (*byte)(unsafe.Pointer(uintptr(auxv[i+1])))
+                       startup_random_data_len = 16
+               }
+       }
+}
diff --git a/src/runtime/os_linux_arm.c b/src/runtime/os_linux_arm.c
deleted file mode 100644 (file)
index e3eda7c..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "textflag.h"
-
-#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
-extern 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 NOSPLIT
-void
-runtime·setup_auxv(int32 argc, byte **argv)
-{
-       byte **envp;
-       byte *rnd;
-       uint32 *auxv;
-       uint32 t;
-
-       // 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 NOSPLIT
-int64
-runtime·cputicks(void)
-{
-       // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
-       // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
-       // runtime·randomNumber provides better seeding of fastrand1.
-       return runtime·nanotime() + runtime·randomNumber;
-}
diff --git a/src/runtime/os_linux_arm.go b/src/runtime/os_linux_arm.go
new file mode 100644 (file)
index 0000000..d5b37d6
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+const (
+       _AT_NULL     = 0
+       _AT_PLATFORM = 15 //  introduced in at least 2.6.11
+       _AT_HWCAP    = 16 // introduced in at least 2.6.11
+       _AT_RANDOM   = 25 // introduced in 2.6.29
+
+       _HWCAP_VFP   = 1 << 6  // introduced in at least 2.6.11
+       _HWCAP_VFPv3 = 1 << 13 // introduced in 2.6.30
+)
+
+var randomNumber uint32
+var armArch uint8 = 6 // we default to ARMv6
+var hwcap uint32      // set by setup_auxv
+var goarm uint8       // set by 5l
+
+func checkgoarm() {
+       if goarm > 5 && hwcap&_HWCAP_VFP == 0 {
+               print("runtime: this CPU has no floating point hardware, so it cannot run\n")
+               print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
+               exit(1)
+       }
+       if goarm > 6 && hwcap&_HWCAP_VFPv3 == 0 {
+               print("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n")
+               print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
+               exit(1)
+       }
+}
+
+//go:nosplit
+func setup_auxv(argc int32, argv **byte) {
+       // skip over argv, envv to get to auxv
+       n := argc + 1
+       for argv_index(argv, n) != nil {
+               n++
+       }
+       n++
+       auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+
+       for i := 0; auxv[i] != _AT_NULL; i += 2 {
+               switch auxv[i] {
+               case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data
+                       if auxv[i+1] != 0 {
+                               // the pointer provided may not be word alined, so we must to treat it
+                               // as a byte array.
+                               rnd := (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))
+                               randomNumber = uint32(rnd[0]) | uint32(rnd[1])<<8 | uint32(rnd[2])<<16 | uint32(rnd[3])<<24
+                       }
+
+               case _AT_PLATFORM: // v5l, v6l, v7l
+                       t := *(*uint8)(unsafe.Pointer(uintptr(auxv[i+1] + 1)))
+                       if '5' <= t && t <= '7' {
+                               armArch = t - '0'
+                       }
+
+               case _AT_HWCAP: // CPU capability bit flags
+                       hwcap = auxv[i+1]
+               }
+       }
+}
+
+func cputicks() int64 {
+       // Currently cputicks() is used in blocking profiler and to seed fastrand1().
+       // nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+       // randomNumber provides better seeding of fastrand1.
+       return nanotime() + int64(randomNumber)
+}
diff --git a/src/runtime/os_openbsd.c b/src/runtime/os_openbsd.c
deleted file mode 100644 (file)
index eebaa13..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-enum
-{
-       ESRCH = 3,
-       EAGAIN = 35,
-       EWOULDBLOCK = EAGAIN,
-       ENOTSUP = 91,
-
-       // From OpenBSD's sys/time.h
-       CLOCK_REALTIME = 0,
-       CLOCK_VIRTUAL = 1,
-       CLOCK_PROF = 2,
-       CLOCK_MONOTONIC = 3
-};
-
-extern SigTab runtime·sigtab[];
-
-static Sigset sigset_none;
-static Sigset sigset_all = ~(Sigset)0;
-
-extern int32 runtime·tfork(TforkT *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
-extern int32 runtime·thrsleep(void *ident, int32 clock_id, void *tsp, void *lock, const int32 *abort);
-extern int32 runtime·thrwakeup(void *ident, int32 n);
-
-// From OpenBSD's <sys/sysctl.h>
-#define        CTL_HW  6
-#define        HW_NCPU 3
-
-static int32
-getncpu(void)
-{
-       uint32 mib[2];
-       uint32 out;
-       int32 ret;
-       uintptr nout;
-
-       // Fetch hw.ncpu via sysctl.
-       mib[0] = CTL_HW;
-       mib[1] = HW_NCPU;
-       nout = sizeof out;
-       out = 0;
-       ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
-       if(ret >= 0)
-               return out;
-       else
-               return 1;
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       return 1;
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       Timespec ts, *tsp = nil;
-
-       // Compute sleep deadline.
-       if(ns >= 0) {
-               int32 nsec;
-               ns += runtime·nanotime();
-               ts.tv_sec = runtime·timediv(ns, 1000000000, &nsec);
-               ts.tv_nsec = nsec; // tv_nsec is int64 on amd64
-               tsp = &ts;
-       }
-
-       for(;;) {
-               int32 ret;
-
-               // spin-mutex lock
-               while(runtime·xchg(&g->m->waitsemalock, 1))
-                       runtime·osyield();
-
-               if(g->m->waitsemacount != 0) {
-                       // semaphore is available.
-                       g->m->waitsemacount--;
-                       // spin-mutex unlock
-                       runtime·atomicstore(&g->m->waitsemalock, 0);
-                       return 0;  // semaphore acquired
-               }
-
-               // sleep until semaphore != 0 or timeout.
-               // thrsleep unlocks m->waitsemalock.
-               ret = runtime·thrsleep(&g->m->waitsemacount, CLOCK_MONOTONIC, tsp, &g->m->waitsemalock, (int32 *)&g->m->waitsemacount);
-               if(ret == EWOULDBLOCK)
-                       return -1;
-       }
-}
-
-static void badsemawakeup(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       uint32 ret;
-       void *oldptr;
-       uint32 oldscalar;
-       void (*fn)(void);
-
-       // spin-mutex lock
-       while(runtime·xchg(&mp->waitsemalock, 1))
-               runtime·osyield();
-       mp->waitsemacount++;
-       ret = runtime·thrwakeup(&mp->waitsemacount, 1);
-       if(ret != 0 && ret != ESRCH) {
-               // semawakeup can be called on signal stack.
-               // Save old ptrarg/scalararg so we can restore them.
-               oldptr = g->m->ptrarg[0];
-               oldscalar = g->m->scalararg[0];
-               g->m->ptrarg[0] = mp;
-               g->m->scalararg[0] = ret;
-               fn = badsemawakeup;
-               if(g == g->m->gsignal)
-                       fn();
-               else
-                       runtime·onM(&fn);
-               g->m->ptrarg[0] = oldptr;
-               g->m->scalararg[0] = oldscalar;
-       }
-       // spin-mutex unlock
-       runtime·atomicstore(&mp->waitsemalock, 0);
-}
-
-static void
-badsemawakeup(void)
-{
-       M *mp;
-       int32 ret;
-
-       mp = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       ret = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-
-       runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
-}
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       TforkT param;
-       Sigset oset;
-       int32 ret;
-
-       if(0) {
-               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);
-       }
-
-       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;
-
-       oset = runtime·sigprocmask(SIG_SETMASK, sigset_all);
-       ret = runtime·tfork(&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");
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getncpu();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       #pragma dataflag NOPTR
-       static byte urandom_data[HashRandomBytes];
-       int32 fd;
-       fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = urandom_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-// 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);
-       mp->gsignal->m = mp;
-}
-
-// 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
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 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);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       return 0;
-}
-
-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 */
-       int32   sa_flags;               /* see signal options below */
-} SigactionT;
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-       if(restart)
-               sa.sa_flags |= SA_RESTART;
-       sa.sa_mask = ~0U;
-       if(fn == runtime·sighandler)
-               fn = (void*)runtime·sigtramp;
-       sa.__sigaction_u.__sa_sigaction = (void*)fn;
-       runtime·sigaction(i, &sa, nil);
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       runtime·sigaction(i, nil, &sa);
-       if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
-               return runtime·sighandler;
-       return (void*)sa.__sigaction_u.__sa_sigaction;
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       StackT st;
-
-       st.ss_sp = (void*)p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·sigprocmask(SIG_SETMASK, sigset_none);
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index a000f963e33ae10bdd512496997a03015f55cde0..9e5adcd3d2a34675a6254f80a221491703a9e7b3 100644 (file)
@@ -4,14 +4,30 @@
 
 package runtime
 
-import "unsafe"
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
 
-func setitimer(mode int32, new, old unsafe.Pointer)
-func sigaction(sig int32, new, old unsafe.Pointer)
-func sigaltstack(new, old unsafe.Pointer)
+//go:noescape
+func sigaction(sig int32, new, old *sigactiont)
+
+//go:noescape
+func sigaltstack(new, old *stackt)
+
+//go:noescape
 func sigprocmask(mode int32, new uint32) uint32
+
+//go:noescape
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+
 func raise(sig int32)
-func tfork(param unsafe.Pointer, psize uintptr, mm, gg, fn unsafe.Pointer) int32
-func thrsleep(ident unsafe.Pointer, clock_id int32, tsp, lock, abort unsafe.Pointer) int32
-func thrwakeup(ident unsafe.Pointer, n int32) int32
+
+//go:noescape
+func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32
+
+//go:noescape
+func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *int32) int32
+
+//go:noescape
+func thrwakeup(ident uintptr, n int32) int32
+
+func osyield()
diff --git a/src/runtime/os_openbsd.h b/src/runtime/os_openbsd.h
deleted file mode 100644 (file)
index 6ad9810..0000000
+++ /dev/null
@@ -1,26 +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.
-
-
-typedef byte* kevent_udata;
-
-struct sigaction;
-
-void   runtime·sigpanic(void);
-
-void   runtime·setitimer(int32, Itimerval*, Itimerval*);
-void   runtime·sigaction(int32, struct sigaction*, struct sigaction*);
-void   runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
-Sigset runtime·sigprocmask(int32, Sigset);
-void   runtime·unblocksignals(void);
-int32  runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-
-enum {
-       SS_DISABLE = 4,
-       SIG_BLOCK = 1,
-       SIG_UNBLOCK = 2,
-       SIG_SETMASK = 3,
-       NSIG = 33,
-       SI_USER = 0,
-};
diff --git a/src/runtime/os_solaris.c b/src/runtime/os_solaris.c
deleted file mode 100644 (file)
index e16b8e6..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-#include "stack.h"
-#include "textflag.h"
-
-#pragma dynexport runtime·end _end
-#pragma dynexport runtime·etext _etext
-#pragma dynexport runtime·edata _edata
-
-#pragma dynimport libc·___errno ___errno "libc.so"
-#pragma dynimport libc·clock_gettime clock_gettime "libc.so"
-#pragma dynimport libc·close close "libc.so"
-#pragma dynimport libc·exit exit "libc.so"
-#pragma dynimport libc·fstat fstat "libc.so"
-#pragma dynimport libc·getcontext getcontext "libc.so"
-#pragma dynimport libc·getrlimit getrlimit "libc.so"
-#pragma dynimport libc·malloc malloc "libc.so"
-#pragma dynimport libc·mmap mmap "libc.so"
-#pragma dynimport libc·munmap munmap "libc.so"
-#pragma dynimport libc·open open "libc.so"
-#pragma dynimport libc·pthread_attr_destroy pthread_attr_destroy "libc.so"
-#pragma dynimport libc·pthread_attr_getstack pthread_attr_getstack "libc.so"
-#pragma dynimport libc·pthread_attr_init pthread_attr_init "libc.so"
-#pragma dynimport libc·pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so"
-#pragma dynimport libc·pthread_attr_setstack pthread_attr_setstack "libc.so"
-#pragma dynimport libc·pthread_create pthread_create "libc.so"
-#pragma dynimport libc·raise raise "libc.so"
-#pragma dynimport libc·read read "libc.so"
-#pragma dynimport libc·select select "libc.so"
-#pragma dynimport libc·sched_yield sched_yield "libc.so"
-#pragma dynimport libc·sem_init sem_init "libc.so"
-#pragma dynimport libc·sem_post sem_post "libc.so"
-#pragma dynimport libc·sem_reltimedwait_np sem_reltimedwait_np "libc.so"
-#pragma dynimport libc·sem_wait sem_wait "libc.so"
-#pragma dynimport libc·setitimer setitimer "libc.so"
-#pragma dynimport libc·sigaction sigaction "libc.so"
-#pragma dynimport libc·sigaltstack sigaltstack "libc.so"
-#pragma dynimport libc·sigprocmask sigprocmask "libc.so"
-#pragma dynimport libc·sysconf sysconf "libc.so"
-#pragma dynimport libc·usleep usleep "libc.so"
-#pragma dynimport libc·write write "libc.so"
-
-extern uintptr libc·___errno;
-extern uintptr libc·clock_gettime;
-extern uintptr libc·close;
-extern uintptr libc·exit;
-extern uintptr libc·fstat;
-extern uintptr libc·getcontext;
-extern uintptr libc·getrlimit;
-extern uintptr libc·malloc;
-extern uintptr libc·mmap;
-extern uintptr libc·munmap;
-extern uintptr libc·open;
-extern uintptr libc·pthread_attr_destroy;
-extern uintptr libc·pthread_attr_getstack;
-extern uintptr libc·pthread_attr_init;
-extern uintptr libc·pthread_attr_setdetachstate;
-extern uintptr libc·pthread_attr_setstack;
-extern uintptr libc·pthread_create;
-extern uintptr libc·raise;
-extern uintptr libc·read;
-extern uintptr libc·sched_yield;
-extern uintptr libc·select;
-extern uintptr libc·sem_init;
-extern uintptr libc·sem_post;
-extern uintptr libc·sem_reltimedwait_np;
-extern uintptr libc·sem_wait;
-extern uintptr libc·setitimer;
-extern uintptr libc·sigaction;
-extern uintptr libc·sigaltstack;
-extern uintptr libc·sigprocmask;
-extern uintptr libc·sysconf;
-extern uintptr libc·usleep;
-extern uintptr libc·write;
-
-void   runtime·getcontext(Ucontext *context);
-int32  runtime·pthread_attr_destroy(PthreadAttr* attr);
-int32  runtime·pthread_attr_init(PthreadAttr* attr);
-int32  runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size);
-int32  runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state);
-int32  runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size);
-int32  runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg);
-uint32 runtime·tstart_sysvicall(M *newm);
-int32  runtime·sem_init(SemT* sem, int32 pshared, uint32 value);
-int32  runtime·sem_post(SemT* sem);
-int32  runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout);
-int32  runtime·sem_wait(SemT* sem);
-int64  runtime·sysconf(int32 name);
-
-extern SigTab runtime·sigtab[];
-static Sigset sigset_none;
-static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
-
-static int32
-getncpu(void) 
-{
-       int32 n;
-       
-       n = (int32)runtime·sysconf(_SC_NPROCESSORS_ONLN);
-       if(n < 1)
-               return 1;
-       return n;
-}
-
-void
-runtime·osinit(void)
-{
-       runtime·ncpu = getncpu(); 
-}
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       PthreadAttr attr;
-       Sigset oset;
-       Pthread tid;
-       int32 ret;
-       uint64 size;
-
-       USED(stk);
-       if(runtime·pthread_attr_init(&attr) != 0)
-               runtime·throw("pthread_attr_init");
-       if(runtime·pthread_attr_setstack(&attr, 0, 0x200000) != 0)
-               runtime·throw("pthread_attr_setstack");
-       size = 0;
-       if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stack.hi, &size) != 0)
-               runtime·throw("pthread_attr_getstack");        
-       mp->g0->stack.lo = mp->g0->stack.hi - size;
-       if(runtime·pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
-               runtime·throw("pthread_attr_setdetachstate");
-
-       // Disable signals during create, so that the new thread starts
-       // with signals disabled.  It will enable them in minit.
-       runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
-       ret = runtime·pthread_create(&tid, &attr, (void (*)(void))runtime·tstart_sysvicall, mp);
-       runtime·sigprocmask(SIG_SETMASK, &oset, nil);
-       if(ret != 0) {
-               runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), ret);
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       #pragma dataflag NOPTR
-       static byte urandom_data[HashRandomBytes];
-       int32 fd;
-       fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
-       if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
-               *rnd = urandom_data;
-               *rnd_len = HashRandomBytes;
-       } else {
-               *rnd = nil;
-               *rnd_len = 0;
-       }
-       runtime·close(fd);
-}
-
-void
-runtime·goenvs(void)
-{
-       runtime·goenvs_unix();
-}
-
-// 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);
-       mp->gsignal->m = 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·asmcgocall(runtime·miniterrno, (void *)libc·___errno);
-       // Initialize signal handling
-       runtime·signalstack((byte*)g->m->gsignal->stack.lo, 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);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       Rlimit rl;
-       extern byte runtime·text[], runtime·end[];
-       uintptr used;
-       
-       if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
-               return 0;
-       if(rl.rlim_cur >= 0x7fffffff)
-               return 0;
-
-       // Estimate our VM footprint excluding the heap.
-       // Not an exact science: use size of binary plus
-       // some room for thread stacks.
-       used = runtime·end - runtime·text + (64<<20);
-       if(used >= rl.rlim_cur)
-               return 0;
-
-       // If there's not at least 16 MB left, we're probably
-       // not going to be able to do much.  Treat as no limit.
-       rl.rlim_cur -= used;
-       if(rl.rlim_cur < (16<<20))
-               return 0;
-
-       return rl.rlim_cur - used;
-}
-
-void
-runtime·setprof(bool on)
-{
-       USED(on);
-}
-
-extern void runtime·sigtramp(void);
-
-void
-runtime·setsig(int32 i, GoSighandler *fn, bool restart)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
-       if(restart)
-               sa.sa_flags |= SA_RESTART;
-       sa.sa_mask.__sigbits[0] = ~(uint32)0;
-       sa.sa_mask.__sigbits[1] = ~(uint32)0;
-       sa.sa_mask.__sigbits[2] = ~(uint32)0;
-       sa.sa_mask.__sigbits[3] = ~(uint32)0;
-       if(fn == runtime·sighandler)
-               fn = (void*)runtime·sigtramp;
-       *((void**)&sa._funcptr[0]) = (void*)fn;
-       runtime·sigaction(i, &sa, nil);
-}
-
-GoSighandler*
-runtime·getsig(int32 i)
-{
-       SigactionT sa;
-
-       runtime·memclr((byte*)&sa, sizeof sa);
-       runtime·sigaction(i, nil, &sa);
-       if(*((void**)&sa._funcptr[0]) == runtime·sigtramp)
-               return runtime·sighandler;
-       return *((void**)&sa._funcptr[0]);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
-       StackT st;
-
-       st.ss_sp = (void*)p;
-       st.ss_size = n;
-       st.ss_flags = 0;
-       if(p == nil)
-               st.ss_flags = SS_DISABLE;
-       runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·unblocksignals(void)
-{
-       runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       SemT* sem;
-
-       // Call libc's malloc rather than runtime·malloc.  This will
-       // allocate space on the C heap.  We can't call runtime·malloc
-       // here because it could cause a deadlock.
-       g->m->libcall.fn = (uintptr)(void*)libc·malloc;
-       g->m->libcall.n = 1;
-       runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch));
-       g->m->scratch.v[0] = (uintptr)sizeof(*sem);
-       g->m->libcall.args = (uintptr)(uintptr*)&g->m->scratch;
-       runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall);
-       sem = (void*)g->m->libcall.r1;
-       if(runtime·sem_init(sem, 0, 0) != 0)
-               runtime·throw("sem_init");
-       return (uintptr)sem;
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       M *m;
-
-       m = g->m;
-       if(ns >= 0) {
-               m->ts.tv_sec = ns / 1000000000LL;
-               m->ts.tv_nsec = ns % 1000000000LL;
-
-               m->libcall.fn = (uintptr)(void*)libc·sem_reltimedwait_np;
-               m->libcall.n = 2;
-               runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
-               m->scratch.v[0] = m->waitsema;
-               m->scratch.v[1] = (uintptr)&m->ts;
-               m->libcall.args = (uintptr)(uintptr*)&m->scratch;
-               runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
-               if(*m->perrno != 0) {
-                       if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m->perrno == EINTR)
-                               return -1;
-                       runtime·throw("sem_reltimedwait_np");
-               }
-               return 0;
-       }
-       for(;;) {
-               m->libcall.fn = (uintptr)(void*)libc·sem_wait;
-               m->libcall.n = 1;
-               runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
-               m->scratch.v[0] = m->waitsema;
-               m->libcall.args = (uintptr)(uintptr*)&m->scratch;
-               runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
-               if(m->libcall.r1 == 0)
-                       break;
-               if(*m->perrno == EINTR) 
-                       continue;
-               runtime·throw("sem_wait");
-       }
-       return 0;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       SemT* sem = (SemT*)mp->waitsema;
-       if(runtime·sem_post(sem) != 0)
-               runtime·throw("sem_post");
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·close(int32 fd)
-{
-       return runtime·sysvicall1(libc·close, (uintptr)fd);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·exit(int32 r)
-{
-       runtime·sysvicall1(libc·exit, (uintptr)r);
-}
-
-#pragma textflag NOSPLIT
-/* int32 */ void
-runtime·getcontext(Ucontext* context)
-{
-       runtime·sysvicall1(libc·getcontext, (uintptr)context);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·getrlimit(int32 res, Rlimit* rlp)
-{
-       return runtime·sysvicall2(libc·getrlimit, (uintptr)res, (uintptr)rlp);
-}
-
-#pragma textflag NOSPLIT
-uint8*
-runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
-{
-       return (uint8*)runtime·sysvicall6(libc·mmap, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·munmap(byte* addr, uintptr len)
-{
-       runtime·sysvicall2(libc·munmap, (uintptr)addr, (uintptr)len);
-}
-
-extern int64 runtime·nanotime1(void);
-#pragma textflag NOSPLIT
-int64
-runtime·nanotime(void)
-{
-       return runtime·sysvicall0((uintptr)runtime·nanotime1);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·open(int8* path, int32 oflag, int32 mode)
-{
-       return runtime·sysvicall3(libc·open, (uintptr)path, (uintptr)oflag, (uintptr)mode);
-}
-
-int32
-runtime·pthread_attr_destroy(PthreadAttr* attr)
-{
-       return runtime·sysvicall1(libc·pthread_attr_destroy, (uintptr)attr);
-}
-
-int32
-runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size)
-{
-       return runtime·sysvicall3(libc·pthread_attr_getstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
-}
-
-int32
-runtime·pthread_attr_init(PthreadAttr* attr)
-{
-       return runtime·sysvicall1(libc·pthread_attr_init, (uintptr)attr);
-}
-
-int32
-runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state)
-{
-       return runtime·sysvicall2(libc·pthread_attr_setdetachstate, (uintptr)attr, (uintptr)state);
-}
-
-int32
-runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size)
-{
-       return runtime·sysvicall3(libc·pthread_attr_setstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
-}
-
-int32
-runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg)
-{
-       return runtime·sysvicall4(libc·pthread_create, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
-}
-
-/* int32 */ void
-runtime·raise(int32 sig)
-{
-       runtime·sysvicall1(libc·raise, (uintptr)sig);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·read(int32 fd, void* buf, int32 nbyte)
-{
-       return runtime·sysvicall3(libc·read, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·sem_init(SemT* sem, int32 pshared, uint32 value)
-{
-       return runtime·sysvicall3(libc·sem_init, (uintptr)sem, (uintptr)pshared, (uintptr)value);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·sem_post(SemT* sem)
-{
-       return runtime·sysvicall1(libc·sem_post, (uintptr)sem);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout)
-{
-       return runtime·sysvicall2(libc·sem_reltimedwait_np, (uintptr)sem, (uintptr)timeout);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·sem_wait(SemT* sem)
-{
-       return runtime·sysvicall1(libc·sem_wait, (uintptr)sem);
-}
-
-/* int32 */ void
-runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue)
-{
-       runtime·sysvicall3(libc·setitimer, (uintptr)which, (uintptr)value, (uintptr)ovalue);
-}
-
-/* int32 */ void
-runtime·sigaction(int32 sig, struct SigactionT* act, struct SigactionT* oact)
-{
-       runtime·sysvicall3(libc·sigaction, (uintptr)sig, (uintptr)act, (uintptr)oact);
-}
-
-/* int32 */ void
-runtime·sigaltstack(SigaltstackT* ss, SigaltstackT* oss)
-{
-       runtime·sysvicall2(libc·sigaltstack, (uintptr)ss, (uintptr)oss);
-}
-
-/* int32 */ void
-runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset)
-{
-       runtime·sysvicall3(libc·sigprocmask, (uintptr)how, (uintptr)set, (uintptr)oset);
-}
-
-int64
-runtime·sysconf(int32 name)
-{
-       return runtime·sysvicall1(libc·sysconf, (uintptr)name);
-}
-
-extern void runtime·usleep1(uint32);
-
-#pragma textflag NOSPLIT
-void
-runtime·usleep(uint32 Âµs)
-{
-       runtime·usleep1(µs);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·write(uintptr fd, void* buf, int32 nbyte)
-{
-       return runtime·sysvicall3(libc·write, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
-}
-
-extern void runtime·osyield1(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·osyield(void)
-{
-       // Check the validity of m because we might be called in cgo callback
-       // path early enough where there isn't a m available yet.
-       if(g && g->m != nil) {
-               runtime·sysvicall0(libc·sched_yield);
-               return;
-       }
-       runtime·osyield1();
-}
-
-#pragma textflag NOSPLIT
-int8*
-runtime·signame(int32 sig)
-{
-       return runtime·sigtab[sig].name;
-}
index ca13151204a5e213cec566103e234f17cf22f722..6864ef9383482006528551d35495dbbbc0b05e90 100644 (file)
@@ -6,53 +6,35 @@ package runtime
 
 import "unsafe"
 
-func setitimer(mode int32, new, old unsafe.Pointer)
-func sigaction(sig int32, new, old unsafe.Pointer)
-func sigaltstack(new, old unsafe.Pointer)
-func sigprocmask(mode int32, new, old unsafe.Pointer)
-func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
-func getrlimit(kind int32, limit unsafe.Pointer)
-func miniterrno(fn unsafe.Pointer)
-func raise(sig int32)
-func getcontext(ctxt unsafe.Pointer)
-func tstart_sysvicall(mm unsafe.Pointer) uint32
-func nanotime1() int64
-func usleep1(usec uint32)
-func osyield1()
-func netpollinit()
-func netpollopen(fd uintptr, pd *pollDesc) int32
-func netpollclose(fd uintptr) int32
-func netpollarm(pd *pollDesc, mode int)
-
-type libcFunc byte
+type libcFunc uintptr
 
 var asmsysvicall6 libcFunc
 
 //go:nosplit
-func sysvicall0(fn *libcFunc) uintptr {
+func sysvicall0(fn libcFunc) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 0
-       // TODO(rsc): Why is noescape necessary here and below?
-       libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
+       libcall.args = uintptr(fn) // it's unused but must be non-nil, otherwise crashes
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
        return libcall.r1
 }
 
 //go:nosplit
-func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
+func sysvicall1(fn libcFunc, a1 uintptr) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 1
+       // TODO(rsc): Why is noescape necessary here and below?
        libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
        return libcall.r1
 }
 
 //go:nosplit
-func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
+func sysvicall2(fn libcFunc, a1, a2 uintptr) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 2
        libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
@@ -60,9 +42,9 @@ func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
 }
 
 //go:nosplit
-func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
+func sysvicall3(fn libcFunc, a1, a2, a3 uintptr) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 3
        libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
@@ -70,9 +52,9 @@ func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
 }
 
 //go:nosplit
-func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
+func sysvicall4(fn libcFunc, a1, a2, a3, a4 uintptr) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 4
        libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
@@ -80,9 +62,9 @@ func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
 }
 
 //go:nosplit
-func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
+func sysvicall5(fn libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 5
        libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
@@ -90,9 +72,9 @@ func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
 }
 
 //go:nosplit
-func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
+func sysvicall6(fn libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
        libcall := &getg().m.libcall
-       libcall.fn = uintptr(unsafe.Pointer(fn))
+       libcall.fn = uintptr(fn)
        libcall.n = 6
        libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
diff --git a/src/runtime/os_solaris.h b/src/runtime/os_solaris.h
deleted file mode 100644 (file)
index 3d9e1a2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-
-typedef uintptr kevent_udata;
-
-struct sigaction;
-
-void   runtime·sigpanic(void);
-
-void   runtime·setitimer(int32, Itimerval*, Itimerval*);
-void   runtime·sigaction(int32, struct SigactionT*, struct SigactionT*);
-void   runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
-void   runtime·sigprocmask(int32, Sigset*, Sigset*);
-void   runtime·unblocksignals(void);
-int32  runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-
-
-void   runtime·raisesigpipe(void);
-void   runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
-void   runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
-void   runtime·sigpanic(void);
-
-enum {
-       SS_DISABLE = 2,
-       SIG_BLOCK = 1,
-       SIG_UNBLOCK = 2,
-       SIG_SETMASK = 3,
-       NSIG = 73, /* number of signals in runtime·SigTab array */
-       SI_USER = 0,
-       _UC_SIGMASK = 0x01,
-       _UC_CPU = 0x04,
-       RLIMIT_AS = 10,
-};
-
-typedef struct Rlimit Rlimit;
-struct Rlimit {
-       int64   rlim_cur;
-       int64   rlim_max;
-};
-int32   runtime·getrlimit(int32, Rlimit*);
-
-// Call an external library function described by {fn, a0, ..., an}, with
-// SysV conventions, switching to os stack during the call, if necessary.
-uintptr        runtime·sysvicall0(uintptr fn);
-uintptr        runtime·sysvicall1(uintptr fn, uintptr a1);
-uintptr        runtime·sysvicall2(uintptr fn, uintptr a1, uintptr a2);
-uintptr        runtime·sysvicall3(uintptr fn, uintptr a1, uintptr a2, uintptr a3);
-uintptr        runtime·sysvicall4(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
-uintptr        runtime·sysvicall5(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
-uintptr        runtime·sysvicall6(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
-void   runtime·asmsysvicall6(void *c);
-
-void   runtime·miniterrno(void *fn);
diff --git a/src/runtime/os_windows.c b/src/runtime/os_windows.c
deleted file mode 100644 (file)
index b8b8eda..0000000
+++ /dev/null
@@ -1,636 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "type.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "textflag.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-
-#pragma dynimport runtime·AddVectoredExceptionHandler AddVectoredExceptionHandler "kernel32.dll"
-#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
-#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
-#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
-#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll"
-#pragma dynimport runtime·CryptAcquireContextW CryptAcquireContextW "advapi32.dll"
-#pragma dynimport runtime·CryptGenRandom CryptGenRandom "advapi32.dll"
-#pragma dynimport runtime·CryptReleaseContext CryptReleaseContext "advapi32.dll"
-#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll"
-#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll"
-#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
-#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
-#pragma dynimport runtime·GetSystemInfo GetSystemInfo "kernel32.dll"
-#pragma dynimport runtime·GetThreadContext GetThreadContext "kernel32.dll"
-#pragma dynimport runtime·LoadLibrary LoadLibraryW "kernel32.dll"
-#pragma dynimport runtime·LoadLibraryA LoadLibraryA "kernel32.dll"
-#pragma dynimport runtime·NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll"
-#pragma dynimport runtime·ResumeThread ResumeThread "kernel32.dll"
-#pragma dynimport runtime·SetConsoleCtrlHandler SetConsoleCtrlHandler "kernel32.dll"
-#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
-#pragma dynimport runtime·SetProcessPriorityBoost SetProcessPriorityBoost "kernel32.dll"
-#pragma dynimport runtime·SetThreadPriority SetThreadPriority "kernel32.dll"
-#pragma dynimport runtime·SetUnhandledExceptionFilter SetUnhandledExceptionFilter "kernel32.dll"
-#pragma dynimport runtime·SetWaitableTimer SetWaitableTimer "kernel32.dll"
-#pragma dynimport runtime·Sleep Sleep "kernel32.dll"
-#pragma dynimport runtime·SuspendThread SuspendThread "kernel32.dll"
-#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
-#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll"
-#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll"
-
-extern void *runtime·AddVectoredExceptionHandler;
-extern void *runtime·CloseHandle;
-extern void *runtime·CreateEvent;
-extern void *runtime·CreateThread;
-extern void *runtime·CreateWaitableTimer;
-extern void *runtime·CryptAcquireContextW;
-extern void *runtime·CryptGenRandom;
-extern void *runtime·CryptReleaseContext;
-extern void *runtime·DuplicateHandle;
-extern void *runtime·ExitProcess;
-extern void *runtime·FreeEnvironmentStringsW;
-extern void *runtime·GetEnvironmentStringsW;
-extern void *runtime·GetProcAddress;
-extern void *runtime·GetStdHandle;
-extern void *runtime·GetSystemInfo;
-extern void *runtime·GetThreadContext;
-extern void *runtime·LoadLibrary;
-extern void *runtime·LoadLibraryA;
-extern void *runtime·NtWaitForSingleObject;
-extern void *runtime·ResumeThread;
-extern void *runtime·SetConsoleCtrlHandler;
-extern void *runtime·SetEvent;
-extern void *runtime·SetProcessPriorityBoost;
-extern void *runtime·SetThreadPriority;
-extern void *runtime·SetUnhandledExceptionFilter;
-extern void *runtime·SetWaitableTimer;
-extern void *runtime·Sleep;
-extern void *runtime·SuspendThread;
-extern void *runtime·WaitForSingleObject;
-extern void *runtime·WriteFile;
-extern void *runtime·timeBeginPeriod;
-
-#pragma dataflag NOPTR
-void *runtime·GetQueuedCompletionStatusEx;
-
-extern uintptr runtime·externalthreadhandlerp;
-void runtime·externalthreadhandler(void);
-void runtime·exceptiontramp(void);
-void runtime·firstcontinuetramp(void);
-void runtime·lastcontinuetramp(void);
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·getLoadLibrary(void)
-{
-       return (uintptr)runtime·LoadLibrary;
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·getGetProcAddress(void)
-{
-       return (uintptr)runtime·GetProcAddress;
-}
-
-static int32
-getproccount(void)
-{
-       SystemInfo info;
-
-       runtime·stdcall1(runtime·GetSystemInfo, (uintptr)&info);
-       return info.dwNumberOfProcessors;
-}
-
-void
-runtime·osinit(void)
-{
-       void *kernel32;
-       void *addVectoredContinueHandler;
-
-       kernel32 = runtime·stdcall1(runtime·LoadLibraryA, (uintptr)"kernel32.dll");
-
-       runtime·externalthreadhandlerp = (uintptr)runtime·externalthreadhandler;
-
-       runtime·stdcall2(runtime·AddVectoredExceptionHandler, 1, (uintptr)runtime·exceptiontramp);
-       addVectoredContinueHandler = nil;
-       if(kernel32 != nil)
-               addVectoredContinueHandler = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"AddVectoredContinueHandler");
-       if(addVectoredContinueHandler == nil || sizeof(void*) == 4) {
-               // use SetUnhandledExceptionFilter for windows-386 or
-               // if VectoredContinueHandler is unavailable.
-               // note: SetUnhandledExceptionFilter handler won't be called, if debugging.
-               runtime·stdcall1(runtime·SetUnhandledExceptionFilter, (uintptr)runtime·lastcontinuetramp);
-       } else {
-               runtime·stdcall2(addVectoredContinueHandler, 1, (uintptr)runtime·firstcontinuetramp);
-               runtime·stdcall2(addVectoredContinueHandler, 0, (uintptr)runtime·lastcontinuetramp);
-       }
-
-       runtime·stdcall2(runtime·SetConsoleCtrlHandler, (uintptr)runtime·ctrlhandler, 1);
-
-       runtime·stdcall1(runtime·timeBeginPeriod, 1);
-
-       runtime·ncpu = getproccount();
-       
-       // Windows dynamic priority boosting assumes that a process has different types
-       // of dedicated threads -- GUI, IO, computational, etc. Go processes use
-       // equivalent threads that all do a mix of GUI, IO, computations, etc.
-       // In such context dynamic priority boosting does nothing but harm, so we turn it off.
-       runtime·stdcall2(runtime·SetProcessPriorityBoost, -1, 1);
-
-       if(kernel32 != nil) {
-               runtime·GetQueuedCompletionStatusEx = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"GetQueuedCompletionStatusEx");
-       }
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·get_random_data(byte **rnd, int32 *rnd_len)
-{
-       uintptr handle;
-       *rnd = nil;
-       *rnd_len = 0;
-       if(runtime·stdcall5(runtime·CryptAcquireContextW, (uintptr)&handle, (uintptr)nil, (uintptr)nil,
-                          1 /* PROV_RSA_FULL */,
-                          0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
-               static byte random_data[HashRandomBytes];
-               if(runtime·stdcall3(runtime·CryptGenRandom, handle, HashRandomBytes, (uintptr)&random_data[0])) {
-                       *rnd = random_data;
-                       *rnd_len = HashRandomBytes;
-               }
-               runtime·stdcall2(runtime·CryptReleaseContext, handle, 0);
-       }
-}
-
-void
-runtime·goenvs(void)
-{
-       extern Slice runtime·envs;
-
-       uint16 *env;
-       String *s;
-       int32 i, n;
-       uint16 *p;
-
-       env = runtime·stdcall0(runtime·GetEnvironmentStringsW);
-
-       n = 0;
-       for(p=env; *p; n++)
-               p += runtime·findnullw(p)+1;
-
-       runtime·envs = runtime·makeStringSlice(n);
-       s = (String*)runtime·envs.array;
-
-       p = env;
-       for(i=0; i<n; i++) {
-               s[i] = runtime·gostringw(p);
-               p += runtime·findnullw(p)+1;
-       }
-
-       runtime·stdcall1(runtime·FreeEnvironmentStringsW, (uintptr)env);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·exit(int32 code)
-{
-       runtime·stdcall1(runtime·ExitProcess, code);
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·write(uintptr fd, void *buf, int32 n)
-{
-       void *handle;
-       uint32 written;
-
-       written = 0;
-       switch(fd) {
-       case 1:
-               handle = runtime·stdcall1(runtime·GetStdHandle, -11);
-               break;
-       case 2:
-               handle = runtime·stdcall1(runtime·GetStdHandle, -12);
-               break;
-       default:
-               // assume fd is real windows handle.
-               handle = (void*)fd;
-               break;
-       }
-       runtime·stdcall5(runtime·WriteFile, (uintptr)handle, (uintptr)buf, n, (uintptr)&written, 0);
-       return written;
-}
-
-#define INFINITE ((uintptr)0xFFFFFFFF)
-
-#pragma textflag NOSPLIT
-int32
-runtime·semasleep(int64 ns)
-{
-       // store ms in ns to save stack space
-       if(ns < 0)
-               ns = INFINITE;
-       else {
-               ns = runtime·timediv(ns, 1000000, nil);
-               if(ns == 0)
-                       ns = 1;
-       }
-       if(runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)g->m->waitsema, ns) != 0)
-               return -1;  // timeout
-       return 0;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·semawakeup(M *mp)
-{
-       runtime·stdcall1(runtime·SetEvent, mp->waitsema);
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·semacreate(void)
-{
-       return (uintptr)runtime·stdcall4(runtime·CreateEvent, 0, 0, 0, 0);
-}
-
-#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
-
-void
-runtime·newosproc(M *mp, void *stk)
-{
-       void *thandle;
-
-       USED(stk);
-
-       thandle = runtime·stdcall6(runtime·CreateThread,
-               (uintptr)nil, 0x20000, (uintptr)runtime·tstart_stdcall, (uintptr)mp,
-               STACK_SIZE_PARAM_IS_A_RESERVATION, (uintptr)nil);
-       if(thandle == nil) {
-               runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
-               runtime·throw("runtime.newosproc");
-       }
-}
-
-// 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)
-{
-       uintptr thandle;
-
-       // -1 = current process, -2 = current thread
-       runtime·stdcall7(runtime·DuplicateHandle, -1, -2, -1, (uintptr)&thandle, 0, 0, DUPLICATE_SAME_ACCESS);
-       runtime·atomicstoreuintptr(&g->m->thread, thandle);
-}
-
-// Called from dropm to undo the effect of an minit.
-void
-runtime·unminit(void)
-{
-       runtime·stdcall1(runtime·CloseHandle, g->m->thread);
-       g->m->thread = 0;
-}
-
-// Described in http://www.dcl.hpi.uni-potsdam.de/research/WRK/2007/08/getting-os-information-the-kuser_shared_data-structure/
-typedef struct KSYSTEM_TIME {
-       uint32  LowPart;
-       int32   High1Time;
-       int32   High2Time;
-} KSYSTEM_TIME;
-
-#pragma dataflag NOPTR
-const KSYSTEM_TIME* INTERRUPT_TIME     = (KSYSTEM_TIME*)0x7ffe0008;
-#pragma dataflag NOPTR
-const KSYSTEM_TIME* SYSTEM_TIME                = (KSYSTEM_TIME*)0x7ffe0014;
-
-static void badsystime(void);
-
-#pragma textflag NOSPLIT
-int64
-runtime·systime(KSYSTEM_TIME *timeaddr)
-{
-       KSYSTEM_TIME t;
-       int32 i;
-       void (*fn)(void);
-
-       for(i = 1; i < 10000; i++) {
-               // these fields must be read in that order (see URL above)
-               t.High1Time = timeaddr->High1Time;
-               t.LowPart = timeaddr->LowPart;
-               t.High2Time = timeaddr->High2Time;
-               if(t.High1Time == t.High2Time)
-                       return (int64)t.High1Time<<32 | t.LowPart;
-               if((i%100) == 0)
-                       runtime·osyield();
-       }
-       fn = badsystime;
-       runtime·onM(&fn);
-       return 0;
-}
-
-#pragma textflag NOSPLIT
-int64
-runtime·unixnano(void)
-{
-       return (runtime·systime(SYSTEM_TIME) - 116444736000000000LL) * 100LL;
-}
-
-static void
-badsystime(void)
-{
-       runtime·throw("interrupt/system time is changing too fast");
-}
-
-#pragma textflag NOSPLIT
-int64
-runtime·nanotime(void)
-{
-       return runtime·systime(INTERRUPT_TIME) * 100LL;
-}
-
-// Calling stdcall on os stack.
-#pragma textflag NOSPLIT
-static void*
-stdcall(void *fn)
-{
-       g->m->libcall.fn = (uintptr)fn;
-       if(g->m->profilehz != 0) {
-               // leave pc/sp for cpu profiler
-               g->m->libcallg = g;
-               g->m->libcallpc = (uintptr)runtime·getcallerpc(&fn);
-               // sp must be the last, because once async cpu profiler finds
-               // all three values to be non-zero, it will use them
-               g->m->libcallsp = (uintptr)runtime·getcallersp(&fn);
-       }
-       runtime·asmcgocall(runtime·asmstdcall, &g->m->libcall);
-       g->m->libcallsp = 0;
-       return (void*)g->m->libcall.r1;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall0(void *fn)
-{
-       g->m->libcall.n = 0;
-       g->m->libcall.args = (uintptr)&fn;  // it's unused but must be non-nil, otherwise crashes
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall1(void *fn, uintptr a0)
-{
-       USED(a0);
-       g->m->libcall.n = 1;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall2(void *fn, uintptr a0, uintptr a1)
-{
-       USED(a0, a1);
-       g->m->libcall.n = 2;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2)
-{
-       USED(a0, a1, a2);
-       g->m->libcall.n = 3;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3)
-{
-       USED(a0, a1, a2, a3);
-       g->m->libcall.n = 4;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4)
-{
-       USED(a0, a1, a2, a3, a4);
-       g->m->libcall.n = 5;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5)
-{
-       USED(a0, a1, a2, a3, a4, a5);
-       g->m->libcall.n = 6;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6)
-{
-       USED(a0, a1, a2, a3, a4, a5, a6);
-       g->m->libcall.n = 7;
-       g->m->libcall.args = (uintptr)&a0;
-       return stdcall(fn);
-}
-
-extern void runtime·usleep1(uint32);
-
-#pragma textflag NOSPLIT
-void
-runtime·osyield(void)
-{
-       runtime·usleep1(1);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·usleep(uint32 us)
-{
-       // Have 1us units; want 100ns units.
-       runtime·usleep1(10*us);
-}
-
-uint32
-runtime·issigpanic(uint32 code)
-{
-       switch(code) {
-       case EXCEPTION_ACCESS_VIOLATION:
-       case EXCEPTION_INT_DIVIDE_BY_ZERO:
-       case EXCEPTION_INT_OVERFLOW:
-       case EXCEPTION_FLT_DENORMAL_OPERAND:
-       case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-       case EXCEPTION_FLT_INEXACT_RESULT:
-       case EXCEPTION_FLT_OVERFLOW:
-       case EXCEPTION_FLT_UNDERFLOW:
-       case EXCEPTION_BREAKPOINT:
-               return 1;
-       }
-       return 0;
-}
-
-void
-runtime·initsig(void)
-{
-       // following line keeps these functions alive at link stage
-       // if there's a better way please write it here
-       void *e = runtime·exceptiontramp;
-       void *f = runtime·firstcontinuetramp;
-       void *l = runtime·lastcontinuetramp;
-       USED(e);
-       USED(f);
-       USED(l);
-}
-
-uint32
-runtime·ctrlhandler1(uint32 type)
-{
-       int32 s;
-
-       switch(type) {
-       case CTRL_C_EVENT:
-       case CTRL_BREAK_EVENT:
-               s = SIGINT;
-               break;
-       default:
-               return 0;
-       }
-
-       if(runtime·sigsend(s))
-               return 1;
-       runtime·exit(2);       // SIGINT, SIGTERM, etc
-       return 0;
-}
-
-extern void runtime·dosigprof(Context *r, G *gp, M *mp);
-extern void runtime·profileloop(void);
-#pragma dataflag NOPTR
-static void *profiletimer;
-
-static void
-profilem(M *mp)
-{
-       extern M runtime·m0;
-       extern uint32 runtime·tls0[];
-       byte rbuf[sizeof(Context)+15];
-       Context *r;
-       void *tls;
-       G *gp;
-
-       tls = mp->tls;
-       if(mp == &runtime·m0)
-               tls = runtime·tls0;
-       gp = *(G**)tls;
-
-       // align Context to 16 bytes
-       r = (Context*)((uintptr)(&rbuf[15]) & ~15);
-       r->ContextFlags = CONTEXT_CONTROL;
-       runtime·stdcall2(runtime·GetThreadContext, (uintptr)mp->thread, (uintptr)r);
-       runtime·dosigprof(r, gp, mp);
-}
-
-void
-runtime·profileloop1(void)
-{
-       M *mp, *allm;
-       uintptr thread;
-
-       runtime·stdcall2(runtime·SetThreadPriority, -2, THREAD_PRIORITY_HIGHEST);
-
-       for(;;) {
-               runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)profiletimer, -1);
-               allm = runtime·atomicloadp(&runtime·allm);
-               for(mp = allm; mp != nil; mp = mp->alllink) {
-                       thread = runtime·atomicloaduintptr(&mp->thread);
-                       // Do not profile threads blocked on Notes,
-                       // this includes idle worker threads,
-                       // idle timer thread, idle heap scavenger, etc.
-                       if(thread == 0 || mp->profilehz == 0 || mp->blocked)
-                               continue;
-                       runtime·stdcall1(runtime·SuspendThread, (uintptr)thread);
-                       if(mp->profilehz != 0 && !mp->blocked)
-                               profilem(mp);
-                       runtime·stdcall1(runtime·ResumeThread, (uintptr)thread);
-               }
-       }
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       static Mutex lock;
-       void *timer, *thread;
-       int32 ms;
-       int64 due;
-
-       runtime·lock(&lock);
-       if(profiletimer == nil) {
-               timer = runtime·stdcall3(runtime·CreateWaitableTimer, (uintptr)nil, (uintptr)nil, (uintptr)nil);
-               runtime·atomicstorep(&profiletimer, timer);
-               thread = runtime·stdcall6(runtime·CreateThread,
-                       (uintptr)nil, (uintptr)nil, (uintptr)runtime·profileloop, (uintptr)nil, (uintptr)nil, (uintptr)nil);
-               runtime·stdcall2(runtime·SetThreadPriority, (uintptr)thread, THREAD_PRIORITY_HIGHEST);
-               runtime·stdcall1(runtime·CloseHandle, (uintptr)thread);
-       }
-       runtime·unlock(&lock);
-
-       ms = 0;
-       due = 1LL<<63;
-       if(hz > 0) {
-               ms = 1000 / hz;
-               if(ms == 0)
-                       ms = 1;
-               due = ms * -10000;
-       }
-       runtime·stdcall6(runtime·SetWaitableTimer,
-               (uintptr)profiletimer, (uintptr)&due, ms, (uintptr)nil, (uintptr)nil, (uintptr)nil);
-       runtime·atomicstore((uint32*)&g->m->profilehz, hz);
-}
-
-uintptr
-runtime·memlimit(void)
-{
-       return 0;
-}
-
-#pragma dataflag NOPTR
-int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n";
-int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1;
-
-void
-runtime·crash(void)
-{
-       // TODO: This routine should do whatever is needed
-       // to make the Windows program abort/crash as it
-       // would if Go was not intercepting signals.
-       // On Unix the routine would remove the custom signal
-       // handler and then raise a signal (like SIGABRT).
-       // Something like that should happen here.
-       // It's okay to leave this empty for now: if crash returns
-       // the ordinary exit-after-panic happens.
-}
index 1528d2fd1396daaf3a1284f01a0047aa6c78a0a3..097b5d6290f2f4a5361b1dc55c5ffb48f541c2bd 100644 (file)
@@ -4,28 +4,8 @@
 
 package runtime
 
-import "unsafe"
-
 type stdFunction *byte
 
-func stdcall0(fn stdFunction) uintptr
-func stdcall1(fn stdFunction, a0 uintptr) uintptr
-func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr
-func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr
-func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr
-func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr
-func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr
-func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr
-
-func asmstdcall(fn unsafe.Pointer)
-func getlasterror() uint32
-func setlasterror(err uint32)
-func usleep1(usec uint32)
-func netpollinit()
-func netpollopen(fd uintptr, pd *pollDesc) int32
-func netpollclose(fd uintptr) int32
-func netpollarm(pd *pollDesc, mode int)
-
 func os_sigpipe() {
        gothrow("too many writes on closed pipe")
 }
diff --git a/src/runtime/os_windows.h b/src/runtime/os_windows.h
deleted file mode 100644 (file)
index d5d168d..0000000
+++ /dev/null
@@ -1,42 +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.
-
-extern void *runtime·LoadLibrary;
-extern void *runtime·GetProcAddress;
-extern void *runtime·GetQueuedCompletionStatusEx;
-
-// Call a Windows function with stdcall conventions,
-// and switch to os stack during the call.
-void runtime·asmstdcall(void *c);
-void *runtime·stdcall0(void *fn);
-void *runtime·stdcall1(void *fn, uintptr a0);
-void *runtime·stdcall2(void *fn, uintptr a0, uintptr a1);
-void *runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2);
-void *runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3);
-void *runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
-void *runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
-void *runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
-
-uint32 runtime·getlasterror(void);
-void runtime·setlasterror(uint32 err);
-
-// Function to be called by windows CreateThread
-// to start new os thread.
-uint32 runtime·tstart_stdcall(M *newm);
-
-uint32 runtime·issigpanic(uint32);
-void runtime·sigpanic(void);
-uint32 runtime·ctrlhandler(uint32 type);
-
-// Windows dll function to go callback entry.
-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
-enum {
-       NSIG = 65,
-};
diff --git a/src/runtime/os_windows_386.c b/src/runtime/os_windows_386.c
deleted file mode 100644 (file)
index 9962f0d..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Context *r)
-{
-       runtime·printf("eax     %x\n", r->Eax);
-       runtime·printf("ebx     %x\n", r->Ebx);
-       runtime·printf("ecx     %x\n", r->Ecx);
-       runtime·printf("edx     %x\n", r->Edx);
-       runtime·printf("edi     %x\n", r->Edi);
-       runtime·printf("esi     %x\n", r->Esi);
-       runtime·printf("ebp     %x\n", r->Ebp);
-       runtime·printf("esp     %x\n", r->Esp);
-       runtime·printf("eip     %x\n", r->Eip);
-       runtime·printf("eflags  %x\n", r->EFlags);
-       runtime·printf("cs      %x\n", r->SegCs);
-       runtime·printf("fs      %x\n", r->SegFs);
-       runtime·printf("gs      %x\n", r->SegGs);
-}
-
-bool
-runtime·isgoexception(ExceptionRecord *info, Context *r)
-{
-       extern byte runtime·text[], runtime·etext[];
-
-       // Only handle exception if executing instructions in Go binary
-       // (not Windows library code). 
-       if(r->Eip < (uint32)runtime·text || (uint32)runtime·etext < r->Eip)
-               return false;
-
-       if(!runtime·issigpanic(info->ExceptionCode))
-               return false;
-
-       return true;
-}
-
-// Called by sigtramp from Windows VEH handler.
-// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
-// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
-uint32
-runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       uintptr *sp;
-
-       if(!runtime·isgoexception(info, r))
-               return EXCEPTION_CONTINUE_SEARCH;
-
-       // Make it look like a call to the signal func.
-       // Have to pass arguments out of band since
-       // augmenting the stack frame would break
-       // the unwinding code.
-       gp->sig = info->ExceptionCode;
-       gp->sigcode0 = info->ExceptionInformation[0];
-       gp->sigcode1 = info->ExceptionInformation[1];
-       gp->sigpc = r->Eip;
-
-       // Only push runtime·sigpanic if r->eip != 0.
-       // If r->eip == 0, probably panicked because of a
-       // call to a nil func.  Not pushing that onto sp will
-       // make the trace look like a call to runtime·sigpanic instead.
-       // (Otherwise the trace will end at runtime·sigpanic and we
-       // won't get to see who faulted.)
-       if(r->Eip != 0) {
-               sp = (uintptr*)r->Esp;
-               *--sp = r->Eip;
-               r->Esp = (uintptr)sp;
-       }
-       r->Eip = (uintptr)runtime·sigpanic;
-       return EXCEPTION_CONTINUE_EXECUTION;
-}
-
-// lastcontinuehandler is reached, because runtime cannot handle
-// current exception. lastcontinuehandler will print crash info and exit.
-uint32
-runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       bool crash;
-
-       if(runtime·panicking)  // traceback already printed
-               runtime·exit(2);
-       runtime·panicking = 1;
-
-       runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
-               (uintptr)info->ExceptionInformation[0], (uintptr)info->ExceptionInformation[1], (uintptr)r->Eip);
-
-       runtime·printf("PC=%x\n", r->Eip);
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·tracebacktrap(r->Eip, r->Esp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·dumpregs(r);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-       return 0; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·dosigprof(Context *r, G *gp, M *mp)
-{
-       runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp, mp);
-}
diff --git a/src/runtime/os_windows_amd64.c b/src/runtime/os_windows_amd64.c
deleted file mode 100644 (file)
index e4617e4..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Context *r)
-{
-       runtime·printf("rax     %X\n", r->Rax);
-       runtime·printf("rbx     %X\n", r->Rbx);
-       runtime·printf("rcx     %X\n", r->Rcx);
-       runtime·printf("rdx     %X\n", r->Rdx);
-       runtime·printf("rdi     %X\n", r->Rdi);
-       runtime·printf("rsi     %X\n", r->Rsi);
-       runtime·printf("rbp     %X\n", r->Rbp);
-       runtime·printf("rsp     %X\n", r->Rsp);
-       runtime·printf("r8      %X\n", r->R8 );
-       runtime·printf("r9      %X\n", r->R9 );
-       runtime·printf("r10     %X\n", r->R10);
-       runtime·printf("r11     %X\n", r->R11);
-       runtime·printf("r12     %X\n", r->R12);
-       runtime·printf("r13     %X\n", r->R13);
-       runtime·printf("r14     %X\n", r->R14);
-       runtime·printf("r15     %X\n", r->R15);
-       runtime·printf("rip     %X\n", r->Rip);
-       runtime·printf("rflags  %X\n", r->EFlags);
-       runtime·printf("cs      %X\n", (uint64)r->SegCs);
-       runtime·printf("fs      %X\n", (uint64)r->SegFs);
-       runtime·printf("gs      %X\n", (uint64)r->SegGs);
-}
-
-bool
-runtime·isgoexception(ExceptionRecord *info, Context *r)
-{
-       extern byte runtime·text[], runtime·etext[];
-
-       // Only handle exception if executing instructions in Go binary
-       // (not Windows library code). 
-       if(r->Rip < (uint64)runtime·text || (uint64)runtime·etext < r->Rip)
-               return false;
-
-       if(!runtime·issigpanic(info->ExceptionCode))
-               return false;
-
-       return true;
-}
-
-// Called by sigtramp from Windows VEH handler.
-// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
-// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
-uint32
-runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       uintptr *sp;
-
-       if(!runtime·isgoexception(info, r))
-               return EXCEPTION_CONTINUE_SEARCH;
-
-       // Make it look like a call to the signal func.
-       // Have to pass arguments out of band since
-       // augmenting the stack frame would break
-       // the unwinding code.
-       gp->sig = info->ExceptionCode;
-       gp->sigcode0 = info->ExceptionInformation[0];
-       gp->sigcode1 = info->ExceptionInformation[1];
-       gp->sigpc = r->Rip;
-
-       // Only push runtime·sigpanic if r->rip != 0.
-       // If r->rip == 0, probably panicked because of a
-       // call to a nil func.  Not pushing that onto sp will
-       // make the trace look like a call to runtime·sigpanic instead.
-       // (Otherwise the trace will end at runtime·sigpanic and we
-       // won't get to see who faulted.)
-       if(r->Rip != 0) {
-               sp = (uintptr*)r->Rsp;
-               *--sp = r->Rip;
-               r->Rsp = (uintptr)sp;
-       }
-       r->Rip = (uintptr)runtime·sigpanic;
-       return EXCEPTION_CONTINUE_EXECUTION;
-}
-
-// It seems Windows searches ContinueHandler's list even
-// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
-// firstcontinuehandler will stop that search,
-// if exceptionhandler did the same earlier.
-uint32
-runtime·firstcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       USED(gp);
-       if(!runtime·isgoexception(info, r))
-               return EXCEPTION_CONTINUE_SEARCH;
-       return EXCEPTION_CONTINUE_EXECUTION;
-}
-
-// lastcontinuehandler is reached, because runtime cannot handle
-// current exception. lastcontinuehandler will print crash info and exit.
-uint32
-runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
-{
-       bool crash;
-
-       if(runtime·panicking)  // traceback already printed
-               runtime·exit(2);
-       runtime·panicking = 1;
-
-       runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
-               info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip);
-
-
-       runtime·printf("PC=%X\n", r->Rip);
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·tracebacktrap(r->Rip, r->Rsp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·dumpregs(r);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-       return 0; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·dosigprof(Context *r, G *gp, M *mp)
-{
-       runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp, mp);
-}
diff --git a/src/runtime/panic.c b/src/runtime/panic.c
deleted file mode 100644 (file)
index 24eb6db..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "stack.h"
-#include "malloc.h"
-#include "textflag.h"
-
-// Code related to defer, panic and recover.
-
-// TODO: remove once code is moved to Go
-extern Defer* runtime·newdefer(int32 siz);
-extern runtime·freedefer(Defer *d);
-
-uint32 runtime·panicking;
-static Mutex paniclk;
-
-void
-runtime·deferproc_m(void)
-{
-       int32 siz;
-       FuncVal *fn;
-       uintptr argp;
-       uintptr callerpc;
-       Defer *d;
-
-       siz = g->m->scalararg[0];
-       fn = g->m->ptrarg[0];
-       argp = g->m->scalararg[1];
-       callerpc = g->m->scalararg[2];
-       g->m->ptrarg[0] = nil;
-       g->m->scalararg[1] = 0;
-
-       d = runtime·newdefer(siz);
-       if(d->panic != nil)
-               runtime·throw("deferproc: d->panic != nil after newdefer");
-       d->fn = fn;
-       d->pc = callerpc;
-       d->argp = argp;
-       runtime·memmove(d+1, (void*)argp, siz);
-}
-
-// Unwind the stack after a deferred function calls recover
-// after a panic.  Then arrange to continue running as though
-// the caller of the deferred function returned normally.
-void
-runtime·recovery_m(G *gp)
-{
-       void *argp;
-       uintptr pc;
-       
-       // Info about defer passed in G struct.
-       argp = (void*)gp->sigcode0;
-       pc = (uintptr)gp->sigcode1;
-
-       // d's arguments need to be in the stack.
-       if(argp != nil && ((uintptr)argp < gp->stack.lo || gp->stack.hi < (uintptr)argp)) {
-               runtime·printf("recover: %p not in [%p, %p]\n", argp, gp->stack.lo, gp->stack.hi);
-               runtime·throw("bad recovery");
-       }
-
-       // Make the deferproc for this d return again,
-       // this time returning 1.  The calling function will
-       // jump to the standard return epilogue.
-       // The -2*sizeof(uintptr) makes up for the
-       // two extra words that are on the stack at
-       // each call to deferproc.
-       // (The pc we're returning to does pop pop
-       // before it tests the return value.)
-       // On the arm there are 2 saved LRs mixed in too.
-       if(thechar == '5')
-               gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr);
-       else
-               gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr);
-       gp->sched.pc = pc;
-       gp->sched.lr = 0;
-       gp->sched.ret = 1;
-       runtime·gogo(&gp->sched);
-}
-
-void
-runtime·startpanic_m(void)
-{
-       if(runtime·mheap.cachealloc.size == 0) { // very early
-               runtime·printf("runtime: panic before malloc heap initialized\n");
-               g->m->mallocing = 1; // tell rest of panic not to try to malloc
-       } else if(g->m->mcache == nil) // can happen if called from signal handler or throw
-               g->m->mcache = runtime·allocmcache();
-       switch(g->m->dying) {
-       case 0:
-               g->m->dying = 1;
-               if(g != nil) {
-                       g->writebuf.array = nil;
-                       g->writebuf.len = 0;
-                       g->writebuf.cap = 0;
-               }
-               runtime·xadd(&runtime·panicking, 1);
-               runtime·lock(&paniclk);
-               if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0)
-                       runtime·schedtrace(true);
-               runtime·freezetheworld();
-               return;
-       case 1:
-               // Something failed while panicing, probably the print of the
-               // argument to panic().  Just print a stack trace and exit.
-               g->m->dying = 2;
-               runtime·printf("panic during panic\n");
-               runtime·dopanic(0);
-               runtime·exit(3);
-       case 2:
-               // This is a genuine bug in the runtime, we couldn't even
-               // print the stack trace successfully.
-               g->m->dying = 3;
-               runtime·printf("stack trace unavailable\n");
-               runtime·exit(4);
-       default:
-               // Can't even print!  Just exit.
-               runtime·exit(5);
-       }
-}
-
-void
-runtime·dopanic_m(void)
-{
-       G *gp;
-       uintptr sp, pc;
-       static bool didothers;
-       bool crash;
-       int32 t;
-
-       gp = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       pc = g->m->scalararg[0];
-       sp = g->m->scalararg[1];
-       g->m->scalararg[1] = 0;
-       if(gp->sig != 0)
-               runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
-                       gp->sig, gp->sigcode0, gp->sigcode1, gp->sigpc);
-
-       if((t = runtime·gotraceback(&crash)) > 0){
-               if(gp != gp->m->g0) {
-                       runtime·printf("\n");
-                       runtime·goroutineheader(gp);
-                       runtime·traceback(pc, sp, 0, gp);
-               } else if(t >= 2 || g->m->throwing > 0) {
-                       runtime·printf("\nruntime stack:\n");
-                       runtime·traceback(pc, sp, 0, gp);
-               }
-               if(!didothers) {
-                       didothers = true;
-                       runtime·tracebackothers(gp);
-               }
-       }
-       runtime·unlock(&paniclk);
-       if(runtime·xadd(&runtime·panicking, -1) != 0) {
-               // Some other m is panicking too.
-               // Let it print what it needs to print.
-               // Wait forever without chewing up cpu.
-               // It will exit when it's done.
-               static Mutex deadlock;
-               runtime·lock(&deadlock);
-               runtime·lock(&deadlock);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-}
-
-#pragma textflag NOSPLIT
-bool
-runtime·canpanic(G *gp)
-{
-       M *m;
-       uint32 status;
-
-       // Note that g is m->gsignal, different from gp.
-       // Note also that g->m can change at preemption, so m can go stale
-       // if this function ever makes a function call.
-       m = g->m;
-
-       // Is it okay for gp to panic instead of crashing the program?
-       // Yes, as long as it is running Go code, not runtime code,
-       // and not stuck in a system call.
-       if(gp == nil || gp != m->curg)
-               return false;
-       if(m->locks-m->softfloat != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0)
-               return false;
-       status = runtime·readgstatus(gp);
-       if((status&~Gscan) != Grunning || gp->syscallsp != 0)
-               return false;
-#ifdef GOOS_windows
-       if(m->libcallsp != 0)
-               return false;
-#endif
-       return true;
-}
index 685ff5ca0bcc3aff9c1dd75400c216d336359fac..95e780b1d954de26a12c7df8ad0d9232caa613bd 100644 (file)
@@ -54,6 +54,11 @@ func throwinit() {
 // The compiler turns a defer statement into a call to this.
 //go:nosplit
 func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn
+       if getg().m.curg != getg() {
+               // go code on the system stack can't defer
+               gothrow("defer on system stack")
+       }
+
        // the arguments of fn are in a perilous state.  The stack map
        // for deferproc does not describe them.  So we can't let garbage
        // collection or stack copying trigger until we've copied them out
@@ -61,23 +66,21 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn
        // we can only call nosplit routines.
        argp := uintptr(unsafe.Pointer(&fn))
        argp += unsafe.Sizeof(fn)
-       if GOARCH == "arm" {
+       if GOARCH == "arm" || GOARCH == "power64" || GOARCH == "power64le" {
                argp += ptrSize // skip caller's saved link register
        }
-       mp := acquirem()
-       mp.scalararg[0] = uintptr(siz)
-       mp.ptrarg[0] = unsafe.Pointer(fn)
-       mp.scalararg[1] = argp
-       mp.scalararg[2] = getcallerpc(unsafe.Pointer(&siz))
-
-       if mp.curg != getg() {
-               // go code on the m stack can't defer
-               gothrow("defer on m")
-       }
+       callerpc := getcallerpc(unsafe.Pointer(&siz))
 
-       onM(deferproc_m)
-
-       releasem(mp)
+       systemstack(func() {
+               d := newdefer(siz)
+               if d._panic != nil {
+                       gothrow("deferproc: d.panic != nil after newdefer")
+               }
+               d.fn = fn
+               d.pc = callerpc
+               d.argp = argp
+               memmove(add(unsafe.Pointer(d), unsafe.Sizeof(*d)), unsafe.Pointer(argp), uintptr(siz))
+       })
 
        // deferproc returns 0 normally.
        // a deferred func that stops a panic
@@ -159,7 +162,7 @@ func init() {
 
 // Allocate a Defer, usually using per-P pool.
 // Each defer must be released with freedefer.
-// Note: runs on M stack
+// Note: runs on g0 stack
 func newdefer(siz int32) *_defer {
        var d *_defer
        sc := deferclass(uintptr(siz))
@@ -298,8 +301,6 @@ func Goexit() {
        goexit()
 }
 
-func canpanic(*g) bool
-
 // Print all currently active panics.  Used when crashing.
 func printpanics(p *_panic) {
        if p.link != nil {
@@ -318,7 +319,10 @@ func printpanics(p *_panic) {
 func gopanic(e interface{}) {
        gp := getg()
        if gp.m.curg != gp {
-               gothrow("panic on m stack")
+               print("panic: ")
+               printany(e)
+               print("\n")
+               gothrow("panic on system stack")
        }
 
        // m.softfloat is set during software floating point.
@@ -414,7 +418,7 @@ func gopanic(e interface{}) {
                        // Pass information about recovering frame to recovery.
                        gp.sigcode0 = uintptr(argp)
                        gp.sigcode1 = pc
-                       mcall(recovery_m)
+                       mcall(recovery)
                        gothrow("recovery failed") // mcall should not return
                }
        }
@@ -466,17 +470,17 @@ func gorecover(argp uintptr) interface{} {
 
 //go:nosplit
 func startpanic() {
-       onM_signalok(startpanic_m)
+       systemstack(startpanic_m)
 }
 
 //go:nosplit
 func dopanic(unused int) {
+       pc := getcallerpc(unsafe.Pointer(&unused))
+       sp := getcallersp(unsafe.Pointer(&unused))
        gp := getg()
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(gp)
-       mp.scalararg[0] = getcallerpc((unsafe.Pointer)(&unused))
-       mp.scalararg[1] = getcallersp((unsafe.Pointer)(&unused))
-       onM_signalok(dopanic_m) // should never return
+       systemstack(func() {
+               dopanic_m(gp, pc, sp) // should never return
+       })
        *(*int)(nil) = 0
 }
 
@@ -494,12 +498,12 @@ func throw(s *byte) {
 
 //go:nosplit
 func gothrow(s string) {
+       print("fatal error: ", s, "\n")
        gp := getg()
        if gp.m.throwing == 0 {
                gp.m.throwing = 1
        }
        startpanic()
-       print("fatal error: ", s, "\n")
        dopanic(0)
        *(*int)(nil) = 0 // not reached
 }
diff --git a/src/runtime/panic1.go b/src/runtime/panic1.go
new file mode 100644 (file)
index 0000000..17379f9
--- /dev/null
@@ -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 runtime
+
+import "unsafe"
+
+// Code related to defer, panic and recover.
+// TODO: Merge into panic.go.
+
+//uint32 runtime·panicking;
+var paniclk mutex
+
+const hasLinkRegister = GOARCH == "arm" || GOARCH == "power64" || GOARCH == "power64le"
+
+// Unwind the stack after a deferred function calls recover
+// after a panic.  Then arrange to continue running as though
+// the caller of the deferred function returned normally.
+func recovery(gp *g) {
+       // Info about defer passed in G struct.
+       argp := (unsafe.Pointer)(gp.sigcode0)
+       pc := uintptr(gp.sigcode1)
+
+       // d's arguments need to be in the stack.
+       if argp != nil && (uintptr(argp) < gp.stack.lo || gp.stack.hi < uintptr(argp)) {
+               print("recover: ", argp, " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
+               gothrow("bad recovery")
+       }
+
+       // Make the deferproc for this d return again,
+       // this time returning 1.  The calling function will
+       // jump to the standard return epilogue.
+       // The -2*sizeof(uintptr) makes up for the
+       // two extra words that are on the stack at
+       // each call to deferproc.
+       // (The pc we're returning to does pop pop
+       // before it tests the return value.)
+       // On the arm and power there are 2 saved LRs mixed in too.
+       if hasLinkRegister {
+               gp.sched.sp = uintptr(argp) - 4*ptrSize
+       } else {
+               gp.sched.sp = uintptr(argp) - 2*ptrSize
+       }
+       gp.sched.pc = pc
+       gp.sched.lr = 0
+       gp.sched.ret = 1
+       gogo(&gp.sched)
+}
+
+func startpanic_m() {
+       _g_ := getg()
+       if mheap_.cachealloc.size == 0 { // very early
+               print("runtime: panic before malloc heap initialized\n")
+               _g_.m.mallocing = 1 // tell rest of panic not to try to malloc
+       } else if _g_.m.mcache == nil { // can happen if called from signal handler or throw
+               _g_.m.mcache = allocmcache()
+       }
+
+       switch _g_.m.dying {
+       case 0:
+               _g_.m.dying = 1
+               if _g_ != nil {
+                       _g_.writebuf = nil
+               }
+               xadd(&panicking, 1)
+               lock(&paniclk)
+               if debug.schedtrace > 0 || debug.scheddetail > 0 {
+                       schedtrace(true)
+               }
+               freezetheworld()
+               return
+       case 1:
+               // Something failed while panicing, probably the print of the
+               // argument to panic().  Just print a stack trace and exit.
+               _g_.m.dying = 2
+               print("panic during panic\n")
+               dopanic(0)
+               exit(3)
+               fallthrough
+       case 2:
+               // This is a genuine bug in the runtime, we couldn't even
+               // print the stack trace successfully.
+               _g_.m.dying = 3
+               print("stack trace unavailable\n")
+               exit(4)
+               fallthrough
+       default:
+               // Can't even print!  Just exit.
+               exit(5)
+       }
+}
+
+var didothers bool
+var deadlock mutex
+
+func dopanic_m(gp *g, pc, sp uintptr) {
+       if gp.sig != 0 {
+               print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
+       }
+
+       var docrash bool
+       _g_ := getg()
+       if t := gotraceback(&docrash); t > 0 {
+               if gp != gp.m.g0 {
+                       print("\n")
+                       goroutineheader(gp)
+                       traceback(pc, sp, 0, gp)
+               } else if t >= 2 || _g_.m.throwing > 0 {
+                       print("\nruntime stack:\n")
+                       traceback(pc, sp, 0, gp)
+               }
+               if !didothers {
+                       didothers = true
+                       tracebackothers(gp)
+               }
+       }
+       unlock(&paniclk)
+
+       if xadd(&panicking, -1) != 0 {
+               // Some other m is panicking too.
+               // Let it print what it needs to print.
+               // Wait forever without chewing up cpu.
+               // It will exit when it's done.
+               lock(&deadlock)
+               lock(&deadlock)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+}
+
+//go:nosplit
+func canpanic(gp *g) bool {
+       // Note that g is m->gsignal, different from gp.
+       // Note also that g->m can change at preemption, so m can go stale
+       // if this function ever makes a function call.
+       _g_ := getg()
+       _m_ := _g_.m
+
+       // Is it okay for gp to panic instead of crashing the program?
+       // Yes, as long as it is running Go code, not runtime code,
+       // and not stuck in a system call.
+       if gp == nil || gp != _m_.curg {
+               return false
+       }
+       if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.gcing != 0 || _m_.dying != 0 {
+               return false
+       }
+       status := readgstatus(gp)
+       if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
+               return false
+       }
+       if GOOS == "windows" && _m_.libcallsp != 0 {
+               return false
+       }
+       return true
+}
diff --git a/src/runtime/parfor.c b/src/runtime/parfor.c
deleted file mode 100644 (file)
index e449568..0000000
+++ /dev/null
@@ -1,226 +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.
-
-// Parallel for algorithm.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.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];
-};
-
-void
-runtime·parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32))
-{
-       uint32 i, begin, end;
-       uint64 *pos;
-
-       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;
-               pos = &desc->thr[i].pos;
-               if(((uintptr)pos & 7) != 0)
-                       runtime·throw("parforsetup: pos is not aligned");
-               *pos = (uint64)begin | (((uint64)end)<<32);
-       }
-}
-
-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;
-                       for(;;) {
-                               // See if it has any work.
-                               pos = runtime·atomicload64(victimpos);
-                               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.
-void
-runtime·newparfor_m(void)
-{
-       g->m->ptrarg[0] = runtime·parforalloc(g->m->scalararg[0]);
-}
-
-void
-runtime·parforsetup_m(void)
-{
-       ParFor *desc;
-       void *ctx;
-       void (*body)(ParFor*, uint32);
-
-       desc = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       ctx = g->m->ptrarg[1];
-       g->m->ptrarg[1] = nil;
-       body = g->m->ptrarg[2];
-       g->m->ptrarg[2] = nil;
-
-       runtime·parforsetup(desc, g->m->scalararg[0], g->m->scalararg[1], ctx, g->m->scalararg[2], body);
-}
-
-void
-runtime·parfordo_m(void)
-{
-       ParFor *desc;
-
-       desc = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       runtime·parfordo(desc);
-}
-
-void
-runtime·parforiters_m(void)
-{
-       ParFor *desc;
-       uintptr tid;
-
-       desc = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       tid = g->m->scalararg[0];
-       g->m->scalararg[0] = desc->thr[tid].pos;
-       g->m->scalararg[1] = desc->thr[tid].pos>>32;
-}
diff --git a/src/runtime/parfor.go b/src/runtime/parfor.go
new file mode 100644 (file)
index 0000000..14870c9
--- /dev/null
@@ -0,0 +1,186 @@
+// Copyright 2012 The Go 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.
+
+package runtime
+
+import "unsafe"
+
+type parforthread struct {
+       // the thread's iteration space [32lsb, 32msb)
+       pos uint64
+       // stats
+       nsteal     uint64
+       nstealcnt  uint64
+       nprocyield uint64
+       nosyield   uint64
+       nsleep     uint64
+       pad        [_CacheLineSize]byte
+}
+
+func desc_thr_index(desc *parfor, i uint32) *parforthread {
+       return (*parforthread)(add(unsafe.Pointer(desc.thr), uintptr(i)*unsafe.Sizeof(*desc.thr)))
+}
+
+func parforsetup(desc *parfor, nthr, n uint32, ctx unsafe.Pointer, wait bool, body func(*parfor, uint32)) {
+       if desc == nil || nthr == 0 || nthr > desc.nthrmax || body == nil {
+               print("desc=", desc, " nthr=", nthr, " count=", n, " body=", body, "\n")
+               gothrow("parfor: invalid args")
+       }
+
+       desc.body = *(*unsafe.Pointer)(unsafe.Pointer(&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 := uint32(0); i < nthr; i++ {
+               begin := uint32(uint64(n) * uint64(i) / uint64(nthr))
+               end := uint32(uint64(n) * uint64(i+1) / uint64(nthr))
+               pos := &desc_thr_index(desc, i).pos
+               if uintptr(unsafe.Pointer(pos))&7 != 0 {
+                       gothrow("parforsetup: pos is not aligned")
+               }
+               *pos = uint64(begin) | uint64(end)<<32
+       }
+}
+
+func parfordo(desc *parfor) {
+       // Obtain 0-based thread index.
+       tid := xadd(&desc.thrseq, 1) - 1
+       if tid >= desc.nthr {
+               print("tid=", tid, " nthr=", desc.nthr, "\n")
+               gothrow("parfor: invalid tid")
+       }
+
+       // If single-threaded, just execute the for serially.
+       body := *(*func(*parfor, uint32))(unsafe.Pointer(&desc.body))
+       if desc.nthr == 1 {
+               for i := uint32(0); i < desc.cnt; i++ {
+                       body(desc, i)
+               }
+               return
+       }
+
+       me := desc_thr_index(desc, tid)
+       mypos := &me.pos
+       for {
+               for {
+                       // While there is local work,
+                       // bump low index and execute the iteration.
+                       pos := 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 := uint32(0); ; try++ {
+                       // If we don't see any work for long enough,
+                       // increment the done counter...
+                       if try > desc.nthr*4 && !idle {
+                               idle = true
+                               xadd(&desc.done, 1)
+                       }
+
+                       // ...if all threads have incremented the counter,
+                       // we are done.
+                       extra := uint32(0)
+                       if !idle {
+                               extra = 1
+                       }
+                       if desc.done+extra == desc.nthr {
+                               if !idle {
+                                       xadd(&desc.done, 1)
+                               }
+                               goto exit
+                       }
+
+                       // Choose a random victim for stealing.
+                       var begin, end uint32
+                       victim := fastrand1() % (desc.nthr - 1)
+                       if victim >= tid {
+                               victim++
+                       }
+                       victimpos := &desc_thr_index(desc, victim).pos
+                       for {
+                               // See if it has any work.
+                               pos := atomicload64(victimpos)
+                               begin = uint32(pos)
+                               end = uint32(pos >> 32)
+                               if begin+1 >= end {
+                                       end = 0
+                                       begin = end
+                                       break
+                               }
+                               if idle {
+                                       xadd(&desc.done, -1)
+                                       idle = false
+                               }
+                               begin2 := begin + (end-begin)/2
+                               newpos := uint64(begin) | uint64(begin2)<<32
+                               if cas64(victimpos, pos, newpos) {
+                                       begin = begin2
+                                       break
+                               }
+                       }
+                       if begin < end {
+                               // Has successfully stolen some work.
+                               if idle {
+                                       gothrow("parfor: should not be idle")
+                               }
+                               atomicstore64(mypos, uint64(begin)|uint64(end)<<32)
+                               me.nsteal++
+                               me.nstealcnt += uint64(end) - uint64(begin)
+                               break
+                       }
+
+                       // Backoff.
+                       if try < desc.nthr {
+                               // nothing
+                       } else if try < 4*desc.nthr {
+                               me.nprocyield++
+                               procyield(20)
+                       } else if !desc.wait {
+                               // If a caller asked not to wait for the others, exit now
+                               // (assume that most work is already done at this point).
+                               if !idle {
+                                       xadd(&desc.done, 1)
+                               }
+                               goto exit
+                       } else if try < 6*desc.nthr {
+                               me.nosyield++
+                               osyield()
+                       } else {
+                               me.nsleep++
+                               usleep(1)
+                       }
+               }
+       }
+
+exit:
+       xadd64(&desc.nsteal, int64(me.nsteal))
+       xadd64(&desc.nstealcnt, int64(me.nstealcnt))
+       xadd64(&desc.nprocyield, int64(me.nprocyield))
+       xadd64(&desc.nosyield, int64(me.nosyield))
+       xadd64(&desc.nsleep, int64(me.nsleep))
+       me.nsteal = 0
+       me.nstealcnt = 0
+       me.nprocyield = 0
+       me.nosyield = 0
+       me.nsleep = 0
+}
index 8677cb30c5556ef794e6b64e8358019bb66baf64..101c0598937e3468b7a82a07f78c54a2e562ebe4 100644 (file)
@@ -249,7 +249,7 @@ func TestGoroutineSwitch(t *testing.T) {
                        // exists to record a PC without a traceback. Those are okay.
                        if len(stk) == 2 {
                                f := runtime.FuncForPC(stk[1])
-                               if f != nil && (f.Name() == "System" || f.Name() == "ExternalCode" || f.Name() == "GC") {
+                               if f != nil && (f.Name() == "runtime._System" || f.Name() == "runtime._ExternalCode" || f.Name() == "runtime._GC") {
                                        return
                                }
                        }
diff --git a/src/runtime/proc.c b/src/runtime/proc.c
deleted file mode 100644 (file)
index 91e3fe1..0000000
+++ /dev/null
@@ -1,3489 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "zaexperiment.h"
-#include "malloc.h"
-#include "stack.h"
-#include "race.h"
-#include "type.h"
-#include "mgc0.h"
-#include "textflag.h"
-
-// Goroutine scheduler
-// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
-//
-// The main concepts are:
-// G - goroutine.
-// M - worker thread, or machine.
-// P - processor, a resource that is required to execute Go code.
-//     M must have an associated P to execute Go code, however it can be
-//     blocked or in a syscall w/o an associated P.
-//
-// Design doc at http://golang.org/s/go11sched.
-
-enum
-{
-       // Number of goroutine ids to grab from runtime·sched.goidgen to local per-P cache at once.
-       // 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
-       GoidCacheBatch = 16,
-};
-
-SchedT runtime·sched;
-int32  runtime·gomaxprocs;
-uint32 runtime·needextram;
-bool   runtime·iscgo;
-M      runtime·m0;
-G      runtime·g0;    // idle goroutine for m0
-G*     runtime·lastg;
-M*     runtime·allm;
-M*     runtime·extram;
-P*     runtime·allp[MaxGomaxprocs+1];
-int8*  runtime·goos;
-int32  runtime·ncpu;
-int32  runtime·newprocs;
-
-Mutex runtime·allglock;       // the following vars are protected by this lock or by stoptheworld
-G**    runtime·allg;
-Slice  runtime·allgs;
-uintptr runtime·allglen;
-ForceGCState   runtime·forcegc;
-
-void runtime·mstart(void);
-static void runqput(P*, G*);
-static G* runqget(P*);
-static bool runqputslow(P*, G*, uint32, uint32);
-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 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(int64);
-static void incidlelocked(int32);
-static void checkdead(void);
-static void exitsyscall0(G*);
-void runtime·park_m(G*);
-static void goexit0(G*);
-static void gfput(P*, G*);
-static G* gfget(P*);
-static void gfpurge(P*);
-static void globrunqput(G*);
-static void globrunqputbatch(G*, G*, int32);
-static G* globrunqget(P*, int32);
-static P* pidleget(void);
-static void pidleput(P*);
-static void injectglist(G*);
-static bool preemptall(void);
-static bool preemptone(P*);
-static bool exitsyscallfast(void);
-static bool haveexperiment(int8*);
-void runtime·allgadd(G*);
-static void dropg(void);
-
-extern String runtime·buildVersion;
-
-// For cgo-using programs with external linking,
-// export "main" (defined in assembly) so that libc can handle basic
-// C runtime startup and call the Go program as if it were
-// the C main function.
-#pragma cgo_export_static main
-
-// Filled in by dynamic linker when Cgo is available.
-void (*_cgo_init)(void);
-void (*_cgo_malloc)(void);
-void (*_cgo_free)(void);
-
-// Copy for Go code.
-void* runtime·cgoMalloc;
-void* runtime·cgoFree;
-
-// The bootstrap sequence is:
-//
-//     call osinit
-//     call schedinit
-//     make & queue new G
-//     call runtime·mstart
-//
-// The new G calls runtime·main.
-void
-runtime·schedinit(void)
-{
-       int32 n, procs;
-       byte *p;
-
-       // raceinit must be the first call to race detector.
-       // In particular, it must be done before mallocinit below calls racemapshadow.
-       if(raceenabled)
-               g->racectx = runtime·raceinit();
-
-       runtime·sched.maxmcount = 10000;
-
-       runtime·tracebackinit();
-       runtime·symtabinit();
-       runtime·stackinit();
-       runtime·mallocinit();
-       mcommoninit(g->m);
-       
-       runtime·goargs();
-       runtime·goenvs();
-       runtime·parsedebugvars();
-       runtime·gcinit();
-
-       runtime·sched.lastpoll = runtime·nanotime();
-       procs = 1;
-       p = runtime·getenv("GOMAXPROCS");
-       if(p != nil && (n = runtime·atoi(p)) > 0) {
-               if(n > MaxGomaxprocs)
-                       n = MaxGomaxprocs;
-               procs = n;
-       }
-       procresize(procs);
-
-       if(runtime·buildVersion.str == nil) {
-               // Condition should never trigger.  This code just serves
-               // to ensure runtime·buildVersion is kept in the resulting binary.
-               runtime·buildVersion.str = (uint8*)"unknown";
-               runtime·buildVersion.len = 7;
-       }
-
-       runtime·cgoMalloc = _cgo_malloc;
-       runtime·cgoFree = _cgo_free;
-}
-
-void
-runtime·newsysmon(void)
-{
-       newm(sysmon, nil);
-}
-
-static void
-dumpgstatus(G* gp)
-{
-       runtime·printf("runtime: gp: gp=%p, goid=%D, gp->atomicstatus=%x\n", gp, gp->goid, runtime·readgstatus(gp));
-       runtime·printf("runtime:  g:  g=%p, goid=%D,  g->atomicstatus=%x\n", g, g->goid, runtime·readgstatus(g));
-}
-
-static void
-checkmcount(void)
-{
-       // sched lock is held
-       if(runtime·sched.mcount > runtime·sched.maxmcount){
-               runtime·printf("runtime: program exceeds %d-thread limit\n", runtime·sched.maxmcount);
-               runtime·throw("thread exhaustion");
-       }
-}
-
-static void
-mcommoninit(M *mp)
-{
-       // g0 stack won't make sense for user (and is not necessary unwindable).
-       if(g != g->m->g0)
-               runtime·callers(1, mp->createstack, nelem(mp->createstack));
-
-       mp->fastrand = 0x49f6428aUL + mp->id + runtime·cputicks();
-
-       runtime·lock(&runtime·sched.lock);
-       mp->id = runtime·sched.mcount++;
-       checkmcount();
-       runtime·mpreinit(mp);
-       if(mp->gsignal)
-               mp->gsignal->stackguard1 = mp->gsignal->stack.lo + StackGuard;
-
-       // Add to runtime·allm so garbage collector doesn't free g->m
-       // when it is just in a register or thread-local storage.
-       mp->alllink = runtime·allm;
-       // runtime·NumCgoCall() iterates over allm w/o schedlock,
-       // so we need to publish it safely.
-       runtime·atomicstorep(&runtime·allm, mp);
-       runtime·unlock(&runtime·sched.lock);
-}
-
-// Mark gp ready to run.
-void
-runtime·ready(G *gp)
-{
-       uint32 status;
-
-       status = runtime·readgstatus(gp);
-       // Mark runnable.
-       g->m->locks++;  // disable preemption because it can be holding p in a local var
-       if((status&~Gscan) != Gwaiting){
-               dumpgstatus(gp);
-               runtime·throw("bad g->status in ready");
-       }
-       // status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
-       runtime·casgstatus(gp, Gwaiting, Grunnable);
-       runqput(g->m->p, gp);
-       if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0)  // TODO: fast atomic
-               wakep();
-       g->m->locks--;
-       if(g->m->locks == 0 && g->preempt)  // restore the preemption request in case we've cleared it in newstack
-               g->stackguard0 = StackPreempt;
-}
-
-void
-runtime·ready_m(void)
-{
-       G *gp;
-
-       gp = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       runtime·ready(gp);
-}
-
-int32
-runtime·gcprocs(void)
-{
-       int32 n;
-
-       // Figure out how many CPUs to use during GC.
-       // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
-       runtime·lock(&runtime·sched.lock);
-       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.lock);
-       return n;
-}
-
-static bool
-needaddgcproc(void)
-{
-       int32 n;
-
-       runtime·lock(&runtime·sched.lock);
-       n = runtime·gomaxprocs;
-       if(n > runtime·ncpu)
-               n = runtime·ncpu;
-       if(n > MaxGcproc)
-               n = MaxGcproc;
-       n -= runtime·sched.nmidle+1; // one M is currently running
-       runtime·unlock(&runtime·sched.lock);
-       return n > 0;
-}
-
-void
-runtime·helpgc(int32 nproc)
-{
-       M *mp;
-       int32 n, pos;
-
-       runtime·lock(&runtime·sched.lock);
-       pos = 0;
-       for(n = 1; n < nproc; n++) {  // one M is currently running
-               if(runtime·allp[pos]->mcache == g->m->mcache)
-                       pos++;
-               mp = mget();
-               if(mp == nil)
-                       runtime·throw("runtime·gcprocs inconsistency");
-               mp->helpgc = n;
-               mp->mcache = runtime·allp[pos]->mcache;
-               pos++;
-               runtime·notewakeup(&mp->park);
-       }
-       runtime·unlock(&runtime·sched.lock);
-}
-
-// Similar to stoptheworld but best-effort and can be called several times.
-// There is no reverse operation, used during crashing.
-// This function must not lock any mutexes.
-void
-runtime·freezetheworld(void)
-{
-       int32 i;
-
-       if(runtime·gomaxprocs == 1)
-               return;
-       // stopwait and preemption requests can be lost
-       // due to races with concurrently executing threads,
-       // so try several times
-       for(i = 0; i < 5; i++) {
-               // this should tell the scheduler to not start any new goroutines
-               runtime·sched.stopwait = 0x7fffffff;
-               runtime·atomicstore((uint32*)&runtime·sched.gcwaiting, 1);
-               // this should stop running goroutines
-               if(!preemptall())
-                       break;  // no running goroutines
-               runtime·usleep(1000);
-       }
-       // to be sure
-       runtime·usleep(1000);
-       preemptall();
-       runtime·usleep(1000);
-}
-
-static bool
-isscanstatus(uint32 status)
-{
-       if(status == Gscan)
-               runtime·throw("isscanstatus: Bad status Gscan");
-       return (status&Gscan) == Gscan;
-}
-
-// All reads and writes of g's status go through readgstatus, casgstatus
-// castogscanstatus, casfromgscanstatus.
-#pragma textflag NOSPLIT
-uint32
-runtime·readgstatus(G *gp)
-{
-       return runtime·atomicload(&gp->atomicstatus);
-}
-
-// The Gscanstatuses are acting like locks and this releases them.
-// If it proves to be a performance hit we should be able to make these
-// simple atomic stores but for now we are going to throw if
-// we see an inconsistent state.
-void
-runtime·casfromgscanstatus(G *gp, uint32 oldval, uint32 newval)
-{
-       bool success = false;
-
-       // Check that transition is valid.
-       switch(oldval) {
-       case Gscanrunnable:
-       case Gscanwaiting:
-       case Gscanrunning:
-       case Gscansyscall:
-               if(newval == (oldval&~Gscan))
-                       success = runtime·cas(&gp->atomicstatus, oldval, newval);
-               break;
-       case Gscanenqueue:
-               if(newval == Gwaiting)
-                       success = runtime·cas(&gp->atomicstatus, oldval, newval);
-               break;
-       }       
-       if(!success){
-               runtime·printf("runtime: casfromgscanstatus failed gp=%p, oldval=%d, newval=%d\n",  
-                       gp, oldval, newval);
-               dumpgstatus(gp);
-               runtime·throw("casfromgscanstatus: gp->status is not in scan state");
-       }
-}
-
-// This will return false if the gp is not in the expected status and the cas fails. 
-// This acts like a lock acquire while the casfromgstatus acts like a lock release.
-bool
-runtime·castogscanstatus(G *gp, uint32 oldval, uint32 newval)
-{
-       switch(oldval) {
-       case Grunnable:
-       case Gwaiting:
-       case Gsyscall:
-               if(newval == (oldval|Gscan))
-                       return runtime·cas(&gp->atomicstatus, oldval, newval);
-               break;
-       case Grunning:
-               if(newval == Gscanrunning || newval == Gscanenqueue)
-                       return runtime·cas(&gp->atomicstatus, oldval, newval);
-               break;   
-       }
-
-       runtime·printf("runtime: castogscanstatus oldval=%d newval=%d\n", oldval, newval);
-       runtime·throw("castogscanstatus");
-       return false; // not reached
-}
-
-static void badcasgstatus(void);
-static void helpcasgstatus(void);
-
-// If asked to move to or from a Gscanstatus this will throw. Use the castogscanstatus
-// and casfromgscanstatus instead.
-// casgstatus will loop if the g->atomicstatus is in a Gscan status until the routine that 
-// put it in the Gscan state is finished.
-#pragma textflag NOSPLIT
-void
-runtime·casgstatus(G *gp, uint32 oldval, uint32 newval)
-{
-       void (*fn)(void);
-
-       if((oldval&Gscan) || (newval&Gscan) || oldval == newval) {
-               g->m->scalararg[0] = oldval;
-               g->m->scalararg[1] = newval;
-               fn = badcasgstatus;
-               runtime·onM(&fn);
-       }
-
-       // loop if gp->atomicstatus is in a scan state giving
-       // GC time to finish and change the state to oldval.
-       while(!runtime·cas(&gp->atomicstatus, oldval, newval)) {
-               // Help GC if needed. 
-               if(gp->preemptscan && !gp->gcworkdone && (oldval == Grunning || oldval == Gsyscall)) {
-                       gp->preemptscan = false;
-                       g->m->ptrarg[0] = gp;
-                       fn = helpcasgstatus;
-                       runtime·onM(&fn);
-               }
-       }       
-}
-
-static void
-badcasgstatus(void)
-{
-       uint32 oldval, newval;
-       
-       oldval = g->m->scalararg[0];
-       newval = g->m->scalararg[1];
-       g->m->scalararg[0] = 0;
-       g->m->scalararg[1] = 0;
-
-       runtime·printf("casgstatus: oldval=%d, newval=%d\n", oldval, newval);
-       runtime·throw("casgstatus: bad incoming values");
-}
-
-static void
-helpcasgstatus(void)
-{
-       G *gp;
-       
-       gp = g->m->ptrarg[0];
-       g->m->ptrarg[0] = 0;
-       runtime·gcphasework(gp);
-}
-
-// stopg ensures that gp is stopped at a GC safe point where its stack can be scanned
-// or in the context of a moving collector the pointers can be flipped from pointing 
-// to old object to pointing to new objects. 
-// If stopg returns true, the caller knows gp is at a GC safe point and will remain there until
-// the caller calls restartg.
-// If stopg returns false, the caller is not responsible for calling restartg. This can happen
-// if another thread, either the gp itself or another GC thread is taking the responsibility 
-// to do the GC work related to this thread.
-bool
-runtime·stopg(G *gp)
-{
-       uint32 s;
-
-       for(;;) {
-               if(gp->gcworkdone)
-                       return false;
-
-               s = runtime·readgstatus(gp);
-               switch(s) {
-               default:
-                       dumpgstatus(gp);
-                       runtime·throw("stopg: gp->atomicstatus is not valid");
-
-               case Gdead:
-                       return false;
-
-               case Gcopystack:
-                       // Loop until a new stack is in place.
-                       break;
-
-               case Grunnable:
-               case Gsyscall:
-               case Gwaiting:
-                       // Claim goroutine by setting scan bit.
-                       if(!runtime·castogscanstatus(gp, s, s|Gscan))
-                               break;
-                       // In scan state, do work.
-                       runtime·gcphasework(gp);
-                       return true;
-
-               case Gscanrunnable:
-               case Gscanwaiting:
-               case Gscansyscall:
-                       // Goroutine already claimed by another GC helper.
-                       return false;
-
-               case Grunning:
-                       // Claim goroutine, so we aren't racing with a status
-                       // transition away from Grunning.
-                       if(!runtime·castogscanstatus(gp, Grunning, Gscanrunning))
-                               break;
-
-                       // Mark gp for preemption.
-                       if(!gp->gcworkdone) {
-                               gp->preemptscan = true;
-                               gp->preempt = true;
-                               gp->stackguard0 = StackPreempt;
-                       }
-
-                       // Unclaim.
-                       runtime·casfromgscanstatus(gp, Gscanrunning, Grunning);
-                       return false;
-               }
-       }
-       // Should not be here....
-}
-
-// The GC requests that this routine be moved from a scanmumble state to a mumble state.
-void 
-runtime·restartg (G *gp)
-{
-       uint32 s;
-
-       s = runtime·readgstatus(gp);
-       switch(s) {
-       default:
-               dumpgstatus(gp); 
-               runtime·throw("restartg: unexpected status");
-
-       case Gdead:
-               break;
-
-       case Gscanrunnable:
-       case Gscanwaiting:
-       case Gscansyscall:
-               runtime·casfromgscanstatus(gp, s, s&~Gscan);
-               break;
-
-       case Gscanenqueue:
-               // Scan is now completed.
-               // Goroutine now needs to be made runnable.
-               // We put it on the global run queue; ready blocks on the global scheduler lock.
-               runtime·casfromgscanstatus(gp, Gscanenqueue, Gwaiting);
-               if(gp != g->m->curg)
-                       runtime·throw("processing Gscanenqueue on wrong m");
-               dropg();
-               runtime·ready(gp);
-               break;
-       }
-}
-
-static void
-stopscanstart(G* gp)
-{
-       if(g == gp)
-               runtime·throw("GC not moved to G0");
-       if(runtime·stopg(gp)) {
-               if(!isscanstatus(runtime·readgstatus(gp))) {
-                       dumpgstatus(gp);
-                       runtime·throw("GC not in scan state");
-               }
-               runtime·restartg(gp);
-       }
-}
-
-// Runs on g0 and does the actual work after putting the g back on the run queue.
-static void
-mquiesce(G *gpmaster)
-{
-       G* gp;
-       uint32 i;
-       uint32 status;
-       uint32 activeglen;
-
-       activeglen = runtime·allglen;
-       // enqueue the calling goroutine.
-       runtime·restartg(gpmaster);
-       for(i = 0; i < activeglen; i++) {
-               gp = runtime·allg[i];
-               if(runtime·readgstatus(gp) == Gdead) 
-                       gp->gcworkdone = true; // noop scan.
-               else 
-                       gp->gcworkdone = false; 
-               stopscanstart(gp); 
-       }
-
-       // Check that the G's gcwork (such as scanning) has been done. If not do it now. 
-       // You can end up doing work here if the page trap on a Grunning Goroutine has
-       // not been sprung or in some race situations. For example a runnable goes dead
-       // and is started up again with a gp->gcworkdone set to false.
-       for(i = 0; i < activeglen; i++) {
-               gp = runtime·allg[i];
-               while (!gp->gcworkdone) {
-                       status = runtime·readgstatus(gp);
-                       if(status == Gdead) {
-                               gp->gcworkdone = true; // scan is a noop
-                               break;
-                               //do nothing, scan not needed. 
-                       }
-                       if(status == Grunning && gp->stackguard0 == (uintptr)StackPreempt && runtime·notetsleep(&runtime·sched.stopnote, 100*1000)) // nanosecond arg 
-                               runtime·noteclear(&runtime·sched.stopnote);
-                       else 
-                               stopscanstart(gp);
-               }
-       }
-
-       for(i = 0; i < activeglen; i++) {
-               gp = runtime·allg[i];
-               status = runtime·readgstatus(gp);
-               if(isscanstatus(status)) {
-                       runtime·printf("mstopandscang:bottom: post scan bad status gp=%p has status %x\n", gp, status);
-                       dumpgstatus(gp);
-               }
-               if(!gp->gcworkdone && status != Gdead) {
-                       runtime·printf("mstopandscang:bottom: post scan gp=%p->gcworkdone still false\n", gp);
-                       dumpgstatus(gp);
-               }
-       }
-
-       schedule(); // Never returns.
-}
-
-// quiesce moves all the goroutines to a GC safepoint which for now is a at preemption point.
-// If the global runtime·gcphase is GCmark quiesce will ensure that all of the goroutine's stacks
-// have been scanned before it returns.
-void
-runtime·quiesce(G* mastergp)
-{
-       void (*fn)(G*);
-
-       runtime·castogscanstatus(mastergp, Grunning, Gscanenqueue);
-       // Now move this to the g0 (aka m) stack.
-       // g0 will potentially scan this thread and put mastergp on the runqueue 
-       fn = mquiesce;
-       runtime·mcall(&fn);
-}
-
-// This is used by the GC as well as the routines that do stack dumps. In the case
-// of GC all the routines can be reliably stopped. This is not always the case
-// when the system is in panic or being exited.
-void
-runtime·stoptheworld(void)
-{
-       int32 i;
-       uint32 s;
-       P *p;
-       bool wait;
-
-       // If we hold a lock, then we won't be able to stop another M
-       // that is blocked trying to acquire the lock.
-       if(g->m->locks > 0)
-               runtime·throw("stoptheworld: holding locks");
-
-       runtime·lock(&runtime·sched.lock);
-       runtime·sched.stopwait = runtime·gomaxprocs;
-       runtime·atomicstore((uint32*)&runtime·sched.gcwaiting, 1);
-       preemptall();
-       // stop current P
-       g->m->p->status = Pgcstop; // Pgcstop is only diagnostic.
-       runtime·sched.stopwait--;
-       // try to retake all P's in Psyscall status
-       for(i = 0; i < runtime·gomaxprocs; i++) {
-               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.lock);
-
-       // wait for remaining P's to stop voluntarily
-       if(wait) {
-               for(;;) {
-                       // wait for 100us, then try to re-preempt in case of any races
-                       if(runtime·notetsleep(&runtime·sched.stopnote, 100*1000)) {
-                               runtime·noteclear(&runtime·sched.stopnote);
-                               break;
-                       }
-                       preemptall();
-               }
-       }
-       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");
-       }
-}
-
-static void
-mhelpgc(void)
-{
-       g->m->helpgc = -1;
-}
-
-void
-runtime·starttheworld(void)
-{
-       P *p, *p1;
-       M *mp;
-       G *gp;
-       bool add;
-
-       g->m->locks++;  // disable preemption because it can be holding p in a local var
-       gp = runtime·netpoll(false);  // non-blocking
-       injectglist(gp);
-       add = needaddgcproc();
-       runtime·lock(&runtime·sched.lock);
-       if(runtime·newprocs) {
-               procresize(runtime·newprocs);
-               runtime·newprocs = 0;
-       } else
-               procresize(runtime·gomaxprocs);
-       runtime·sched.gcwaiting = 0;
-
-       p1 = nil;
-       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;
-               }
-               p->m = mget();
-               p->link = p1;
-               p1 = p;
-       }
-       if(runtime·sched.sysmonwait) {
-               runtime·sched.sysmonwait = false;
-               runtime·notewakeup(&runtime·sched.sysmonnote);
-       }
-       runtime·unlock(&runtime·sched.lock);
-
-       while(p1) {
-               p = p1;
-               p1 = p1->link;
-               if(p->m) {
-                       mp = p->m;
-                       p->m = nil;
-                       if(mp->nextp)
-                               runtime·throw("starttheworld: inconsistent mp->nextp");
-                       mp->nextp = p;
-                       runtime·notewakeup(&mp->park);
-               } else {
-                       // Start M to run P.  Do not start another M below.
-                       newm(nil, p);
-                       add = false;
-               }
-       }
-
-       if(add) {
-               // If GC could have used another helper proc, start one now,
-               // in the hope that it will be available next time.
-               // It would have been even better to start it before the collection,
-               // but doing so requires allocating memory, so it's tricky to
-               // coordinate.  This lazy approach works out in practice:
-               // we don't mind if the first couple gc rounds don't have quite
-               // the maximum number of procs.
-               newm(mhelpgc, nil);
-       }
-       g->m->locks--;
-       if(g->m->locks == 0 && g->preempt)  // restore the preemption request in case we've cleared it in newstack
-               g->stackguard0 = StackPreempt;
-}
-
-static void mstart(void);
-
-// Called to start an M.
-#pragma textflag NOSPLIT
-void
-runtime·mstart(void)
-{
-       uintptr x, size;
-       
-       if(g->stack.lo == 0) {
-               // Initialize stack bounds from system stack.
-               // Cgo may have left stack size in stack.hi.
-               size = g->stack.hi;
-               if(size == 0)
-                       size = 8192;
-               g->stack.hi = (uintptr)&x;
-               g->stack.lo = g->stack.hi - size + 1024;
-       }
-       
-       // Initialize stack guards so that we can start calling
-       // both Go and C functions with stack growth prologues.
-       g->stackguard0 = g->stack.lo + StackGuard;
-       g->stackguard1 = g->stackguard0;
-       mstart();
-}
-
-static void
-mstart(void)
-{
-       if(g != g->m->g0)
-               runtime·throw("bad runtime·mstart");
-
-       // Record top of stack for use by mcall.
-       // Once we call schedule we're never coming back,
-       // so other calls can reuse this stack space.
-       runtime·gosave(&g->m->g0->sched);
-       g->m->g0->sched.pc = (uintptr)-1;  // make sure it is never used
-       runtime·asminit();
-       runtime·minit();
-
-       // Install signal handlers; after minit so that minit can
-       // prepare the thread to be able to handle the signals.
-       if(g->m == &runtime·m0)
-               runtime·initsig();
-       
-       if(g->m->mstartfn)
-               g->m->mstartfn();
-
-       if(g->m->helpgc) {
-               g->m->helpgc = 0;
-               stopm();
-       } else if(g->m != &runtime·m0) {
-               acquirep(g->m->nextp);
-               g->m->nextp = nil;
-       }
-       schedule();
-
-       // 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.
-}
-
-// 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*);
-
-typedef struct CgoThreadStart CgoThreadStart;
-struct CgoThreadStart
-{
-       G *g;
-       uintptr *tls;
-       void (*fn)(void);
-};
-
-M *runtime·newM(void); // in proc.go
-
-// Allocate a new m unassociated with any thread.
-// Can use p for allocation context if needed.
-M*
-runtime·allocm(P *p)
-{
-       M *mp;
-
-       g->m->locks++;  // disable GC because it can be called from sysmon
-       if(g->m->p == nil)
-               acquirep(p);  // temporarily borrow p for mallocs in this function
-       mp = runtime·newM();
-       mcommoninit(mp);
-
-       // In case of cgo or Solaris, pthread_create will make us a stack.
-       // Windows and Plan 9 will layout sched stack on OS stack.
-       if(runtime·iscgo || Solaris || Windows || Plan9)
-               mp->g0 = runtime·malg(-1);
-       else
-               mp->g0 = runtime·malg(8192);
-       mp->g0->m = mp;
-
-       if(p == g->m->p)
-               releasep();
-       g->m->locks--;
-       if(g->m->locks == 0 && g->preempt)  // restore the preemption request in case we've cleared it in newstack
-               g->stackguard0 = StackPreempt;
-
-       return mp;
-}
-
-G *runtime·newG(void); // in proc.go
-
-static G*
-allocg(void)
-{
-       return runtime·newG();
-}
-
-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 NOSPLIT
-void
-runtime·needm(byte x)
-{
-       M *mp;
-
-       if(runtime·needextram) {
-               // Can happen if C/C++ code calls Go from a global ctor.
-               // Can not throw, because scheduler is not initialized yet.
-               runtime·write(2, "fatal error: cgo callback before cgo call\n",
-                       sizeof("fatal error: cgo callback before cgo call\n")-1);
-               runtime·exit(1);
-       }
-
-       // Lock extra list, take head, unlock popped list.
-       // nilokay=false is safe here because of the invariant above,
-       // that the extra list always contains or will soon contain
-       // at least one m.
-       mp = lockextra(false);
-
-       // Set needextram when we've just emptied the list,
-       // so that the eventual call into cgocallbackg will
-       // allocate a new m for the extra list. We delay the
-       // allocation until then so that it can be done
-       // after exitsyscall makes sure it is okay to be
-       // running at all (that is, there's no garbage collection
-       // running right now).
-       mp->needextram = mp->schedlink == nil;
-       unlockextra(mp->schedlink);
-
-       // Install g (= m->g0) and set the stack bounds
-       // to match the current stack. We don't actually know
-       // how big the stack is, like we don't know how big any
-       // scheduling stack is, but we assume there's at least 32 kB,
-       // which is more than enough for us.
-       runtime·setg(mp->g0);
-       g->stack.hi = (uintptr)(&x + 1024);
-       g->stack.lo = (uintptr)(&x - 32*1024);
-       g->stackguard0 = g->stack.lo + StackGuard;
-
-       // Initialize this thread to use the m.
-       runtime·asminit();
-       runtime·minit();
-}
-
-// 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 = (uintptr)runtime·goexit + PCQuantum;
-       gp->sched.sp = gp->stack.hi;
-       gp->sched.sp -= 4*sizeof(uintreg); // extra space in case of reads slightly beyond frame
-       gp->sched.lr = 0;
-       gp->sched.g = gp;
-       gp->syscallpc = gp->sched.pc;
-       gp->syscallsp = gp->sched.sp;
-       // malg returns status as Gidle, change to Gsyscall before adding to allg
-       // where GC will see it.
-       runtime·casgstatus(gp, Gidle, Gsyscall);
-       gp->m = mp;
-       mp->curg = gp;
-       mp->locked = LockInternal;
-       mp->lockedg = gp;
-       gp->lockedm = mp;
-       gp->goid = runtime·xadd64(&runtime·sched.goidgen, 1);
-       if(raceenabled)
-               gp->racectx = runtime·racegostart(runtime·newextram);
-       // put on allg for garbage collector
-       runtime·allgadd(gp);
-
-       // 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·dropm(void)
-{
-       M *mp, *mnext;
-
-       // Undo whatever initialization minit did during needm.
-       runtime·unminit();
-
-       // Clear m and g, and return m to the extra list.
-       // After the call to setmg we can only call nosplit functions.
-       mp = g->m;
-       runtime·setg(nil);
-
-       mnext = lockextra(true);
-       mp->schedlink = mnext;
-       unlockextra(mp);
-}
-
-#define MLOCKED ((M*)1)
-
-// 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 NOSPLIT
-static M*
-lockextra(bool nilokay)
-{
-       M *mp;
-       void (*yield)(void);
-
-       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;
-       }
-       return mp;
-}
-
-#pragma textflag NOSPLIT
-static void
-unlockextra(M *mp)
-{
-       runtime·atomicstorep(&runtime·extram, mp);
-}
-
-
-// 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)
-{
-       M *mp;
-
-       mp = runtime·allocm(p);
-       mp->nextp = p;
-       mp->mstartfn = fn;
-
-       if(runtime·iscgo) {
-               CgoThreadStart ts;
-
-               if(_cgo_thread_start == nil)
-                       runtime·throw("_cgo_thread_start missing");
-               ts.g = mp->g0;
-               ts.tls = mp->tls;
-               ts.fn = runtime·mstart;
-               runtime·asmcgocall(_cgo_thread_start, &ts);
-               return;
-       }
-       runtime·newosproc(mp, (byte*)mp->g0->stack.hi);
-}
-
-// Stops execution of the current m until new work is available.
-// Returns with acquired P.
-static void
-stopm(void)
-{
-       if(g->m->locks)
-               runtime·throw("stopm holding locks");
-       if(g->m->p)
-               runtime·throw("stopm holding p");
-       if(g->m->spinning) {
-               g->m->spinning = false;
-               runtime·xadd(&runtime·sched.nmspinning, -1);
-       }
-
-retry:
-       runtime·lock(&runtime·sched.lock);
-       mput(g->m);
-       runtime·unlock(&runtime·sched.lock);
-       runtime·notesleep(&g->m->park);
-       runtime·noteclear(&g->m->park);
-       if(g->m->helpgc) {
-               runtime·gchelper();
-               g->m->helpgc = 0;
-               g->m->mcache = nil;
-               goto retry;
-       }
-       acquirep(g->m->nextp);
-       g->m->nextp = nil;
-}
-
-static void
-mspinning(void)
-{
-       g->m->spinning = true;
-}
-
-// Schedules some M to run the p (creates an M if necessary).
-// If p==nil, tries to get an idle P, if no idle P's does nothing.
-static void
-startm(P *p, bool spinning)
-{
-       M *mp;
-       void (*fn)(void);
-
-       runtime·lock(&runtime·sched.lock);
-       if(p == nil) {
-               p = pidleget();
-               if(p == nil) {
-                       runtime·unlock(&runtime·sched.lock);
-                       if(spinning)
-                               runtime·xadd(&runtime·sched.nmspinning, -1);
-                       return;
-               }
-       }
-       mp = mget();
-       runtime·unlock(&runtime·sched.lock);
-       if(mp == nil) {
-               fn = nil;
-               if(spinning)
-                       fn = mspinning;
-               newm(fn, p);
-               return;
-       }
-       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);
-}
-
-// Hands off P from syscall or locked M.
-static void
-handoffp(P *p)
-{
-       // 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.lock);
-       if(runtime·sched.gcwaiting) {
-               p->status = Pgcstop;
-               if(--runtime·sched.stopwait == 0)
-                       runtime·notewakeup(&runtime·sched.stopnote);
-               runtime·unlock(&runtime·sched.lock);
-               return;
-       }
-       if(runtime·sched.runqsize) {
-               runtime·unlock(&runtime·sched.lock);
-               startm(p, false);
-               return;
-       }
-       // If this is the last running P and nobody is polling network,
-       // need to wakeup another M to poll network.
-       if(runtime·sched.npidle == runtime·gomaxprocs-1 && runtime·atomicload64(&runtime·sched.lastpoll) != 0) {
-               runtime·unlock(&runtime·sched.lock);
-               startm(p, false);
-               return;
-       }
-       pidleput(p);
-       runtime·unlock(&runtime·sched.lock);
-}
-
-// 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);
-}
-
-// 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;
-       uint32 status;
-
-       if(g->m->lockedg == nil || g->m->lockedg->lockedm != g->m)
-               runtime·throw("stoplockedm: inconsistent locking");
-       if(g->m->p) {
-               // Schedule another M to run this p.
-               p = releasep();
-               handoffp(p);
-       }
-       incidlelocked(1);
-       // Wait until another thread schedules lockedg again.
-       runtime·notesleep(&g->m->park);
-       runtime·noteclear(&g->m->park);
-       status = runtime·readgstatus(g->m->lockedg);
-       if((status&~Gscan) != Grunnable){
-               runtime·printf("runtime:stoplockedm: g is not Grunnable or Gscanrunnable");
-               dumpgstatus(g);
-               runtime·throw("stoplockedm: not runnable");
-       }
-       acquirep(g->m->nextp);
-       g->m->nextp = nil;
-}
-
-// Schedules the locked m to run the locked gp.
-static void
-startlockedm(G *gp)
-{
-       M *mp;
-       P *p;
-
-       mp = gp->lockedm;
-       if(mp == g->m)
-               runtime·throw("startlockedm: locked to me");
-       if(mp->nextp)
-               runtime·throw("startlockedm: m has p");
-       // directly handoff current P to the locked m
-       incidlelocked(-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·sched.gcwaiting)
-               runtime·throw("gcstopm: not waiting for gc");
-       if(g->m->spinning) {
-               g->m->spinning = false;
-               runtime·xadd(&runtime·sched.nmspinning, -1);
-       }
-       p = releasep();
-       runtime·lock(&runtime·sched.lock);
-       p->status = Pgcstop;
-       if(--runtime·sched.stopwait == 0)
-               runtime·notewakeup(&runtime·sched.stopnote);
-       runtime·unlock(&runtime·sched.lock);
-       stopm();
-}
-
-// Schedules gp to run on the current M.
-// Never returns.
-static void
-execute(G *gp)
-{
-       int32 hz;
-       
-       runtime·casgstatus(gp, Grunnable, Grunning);
-       gp->waitsince = 0;
-       gp->preempt = false;
-       gp->stackguard0 = gp->stack.lo + StackGuard;
-       g->m->p->schedtick++;
-       g->m->curg = gp;
-       gp->m = g->m;
-
-       // Check whether the profiler needs to be turned on or off.
-       hz = runtime·sched.profilehz;
-       if(g->m->profilehz != hz)
-               runtime·resetcpuprofiler(hz);
-
-       runtime·gogo(&gp->sched);
-}
-
-// Finds a runnable goroutine to execute.
-// Tries to steal from other P's, get g from global queue, poll network.
-static G*
-findrunnable(void)
-{
-       G *gp;
-       P *p;
-       int32 i;
-
-top:
-       if(runtime·sched.gcwaiting) {
-               gcstopm();
-               goto top;
-       }
-       if(runtime·fingwait && runtime·fingwake && (gp = runtime·wakefing()) != nil)
-               runtime·ready(gp);
-       // local runq
-       gp = runqget(g->m->p);
-       if(gp)
-               return gp;
-       // global runq
-       if(runtime·sched.runqsize) {
-               runtime·lock(&runtime·sched.lock);
-               gp = globrunqget(g->m->p, 0);
-               runtime·unlock(&runtime·sched.lock);
-               if(gp)
-                       return gp;
-       }
-       // poll network
-       gp = runtime·netpoll(false);  // non-blocking
-       if(gp) {
-               injectglist(gp->schedlink);
-               runtime·casgstatus(gp, Gwaiting, Grunnable);
-               return gp;
-       }
-       // If number of spinning M's >= number of busy P's, block.
-       // This is necessary to prevent excessive CPU consumption
-       // when GOMAXPROCS>>1 but the program parallelism is low.
-       if(!g->m->spinning && 2 * runtime·atomicload(&runtime·sched.nmspinning) >= runtime·gomaxprocs - runtime·atomicload(&runtime·sched.npidle))  // TODO: fast atomic
-               goto stop;
-       if(!g->m->spinning) {
-               g->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·sched.gcwaiting)
-                       goto top;
-               p = runtime·allp[runtime·fastrand1()%runtime·gomaxprocs];
-               if(p == g->m->p)
-                       gp = runqget(p);
-               else
-                       gp = runqsteal(g->m->p, p);
-               if(gp)
-                       return gp;
-       }
-stop:
-       // return P and block
-       runtime·lock(&runtime·sched.lock);
-       if(runtime·sched.gcwaiting) {
-               runtime·unlock(&runtime·sched.lock);
-               goto top;
-       }
-       if(runtime·sched.runqsize) {
-               gp = globrunqget(g->m->p, 0);
-               runtime·unlock(&runtime·sched.lock);
-               return gp;
-       }
-       p = releasep();
-       pidleput(p);
-       runtime·unlock(&runtime·sched.lock);
-       if(g->m->spinning) {
-               g->m->spinning = false;
-               runtime·xadd(&runtime·sched.nmspinning, -1);
-       }
-       // check all runqueues once again
-       for(i = 0; i < runtime·gomaxprocs; i++) {
-               p = runtime·allp[i];
-               if(p && p->runqhead != p->runqtail) {
-                       runtime·lock(&runtime·sched.lock);
-                       p = pidleget();
-                       runtime·unlock(&runtime·sched.lock);
-                       if(p) {
-                               acquirep(p);
-                               goto top;
-                       }
-                       break;
-               }
-       }
-       // poll network
-       if(runtime·xchg64(&runtime·sched.lastpoll, 0) != 0) {
-               if(g->m->p)
-                       runtime·throw("findrunnable: netpoll with p");
-               if(g->m->spinning)
-                       runtime·throw("findrunnable: netpoll with spinning");
-               gp = runtime·netpoll(true);  // block until new work is available
-               runtime·atomicstore64(&runtime·sched.lastpoll, runtime·nanotime());
-               if(gp) {
-                       runtime·lock(&runtime·sched.lock);
-                       p = pidleget();
-                       runtime·unlock(&runtime·sched.lock);
-                       if(p) {
-                               acquirep(p);
-                               injectglist(gp->schedlink);
-                               runtime·casgstatus(gp, Gwaiting, Grunnable);
-                               return gp;
-                       }
-                       injectglist(gp);
-               }
-       }
-       stopm();
-       goto top;
-}
-
-static void
-resetspinning(void)
-{
-       int32 nmspinning;
-
-       if(g->m->spinning) {
-               g->m->spinning = false;
-               nmspinning = runtime·xadd(&runtime·sched.nmspinning, -1);
-               if(nmspinning < 0)
-                       runtime·throw("findrunnable: negative nmspinning");
-       } else
-               nmspinning = runtime·atomicload(&runtime·sched.nmspinning);
-
-       // M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
-       // so see if we need to wakeup another P here.
-       if (nmspinning == 0 && runtime·atomicload(&runtime·sched.npidle) > 0)
-               wakep();
-}
-
-// Injects the list of runnable G's into the scheduler.
-// Can run concurrently with GC.
-static void
-injectglist(G *glist)
-{
-       int32 n;
-       G *gp;
-
-       if(glist == nil)
-               return;
-       runtime·lock(&runtime·sched.lock);
-       for(n = 0; glist; n++) {
-               gp = glist;
-               glist = gp->schedlink;
-               runtime·casgstatus(gp, Gwaiting, Grunnable); 
-               globrunqput(gp);
-       }
-       runtime·unlock(&runtime·sched.lock);
-
-       for(; n && runtime·sched.npidle; n--)
-               startm(nil, false);
-}
-
-// One round of scheduler: find a runnable goroutine and execute it.
-// Never returns.
-static void
-schedule(void)
-{
-       G *gp;
-       uint32 tick;
-
-       if(g->m->locks)
-               runtime·throw("schedule: holding locks");
-
-       if(g->m->lockedg) {
-               stoplockedm();
-               execute(g->m->lockedg);  // Never returns.
-       }
-
-top:
-       if(runtime·sched.gcwaiting) {
-               gcstopm();
-               goto top;
-       }
-
-       gp = nil;
-       // Check the global runnable queue once in a while to ensure fairness.
-       // Otherwise two goroutines can completely occupy the local runqueue
-       // by constantly respawning each other.
-       tick = g->m->p->schedtick;
-       // This is a fancy way to say tick%61==0,
-       // it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
-       if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime·sched.runqsize > 0) {
-               runtime·lock(&runtime·sched.lock);
-               gp = globrunqget(g->m->p, 1);
-               runtime·unlock(&runtime·sched.lock);
-               if(gp)
-                       resetspinning();
-       }
-       if(gp == nil) {
-               gp = runqget(g->m->p);
-               if(gp && g->m->spinning)
-                       runtime·throw("schedule: spinning with local work");
-       }
-       if(gp == nil) {
-               gp = findrunnable();  // blocks until work is available
-               resetspinning();
-       }
-
-       if(gp->lockedm) {
-               // Hands off own p to the locked m,
-               // then blocks waiting for a new p.
-               startlockedm(gp);
-               goto top;
-       }
-
-       execute(gp);
-}
-
-// dropg removes the association between m and the current goroutine m->curg (gp for short).
-// Typically a caller sets gp's status away from Grunning and then
-// immediately calls dropg to finish the job. The caller is also responsible
-// for arranging that gp will be restarted using runtime·ready at an
-// appropriate time. After calling dropg and arranging for gp to be
-// readied later, the caller can do other work but eventually should
-// call schedule to restart the scheduling of goroutines on this m.
-static void
-dropg(void)
-{
-       if(g->m->lockedg == nil) {
-               g->m->curg->m = nil;
-               g->m->curg = nil;
-       }
-}
-
-// Puts the current goroutine into a waiting state and calls unlockf.
-// If unlockf returns false, the goroutine is resumed.
-void
-runtime·park(bool(*unlockf)(G*, void*), void *lock, String reason)
-{
-       void (*fn)(G*);
-
-       g->m->waitlock = lock;
-       g->m->waitunlockf = unlockf;
-       g->waitreason = reason;
-       fn = runtime·park_m;
-       runtime·mcall(&fn);
-}
-
-bool
-runtime·parkunlock_c(G *gp, void *lock)
-{
-       USED(gp);
-       runtime·unlock(lock);
-       return true;
-}
-
-// Puts the current goroutine into a waiting state and unlocks the lock.
-// The goroutine can be made runnable again by calling runtime·ready(gp).
-void
-runtime·parkunlock(Mutex *lock, String reason)
-{
-       runtime·park(runtime·parkunlock_c, lock, reason);
-}
-
-// runtime·park continuation on g0.
-void
-runtime·park_m(G *gp)
-{
-       bool ok;
-
-       runtime·casgstatus(gp, Grunning, Gwaiting);
-       dropg();
-
-       if(g->m->waitunlockf) {
-               ok = g->m->waitunlockf(gp, g->m->waitlock);
-               g->m->waitunlockf = nil;
-               g->m->waitlock = nil;
-               if(!ok) {
-                       runtime·casgstatus(gp, Gwaiting, Grunnable); 
-                       execute(gp);  // Schedule it back, never returns.
-               }
-       }
-
-       schedule();
-}
-
-// Gosched continuation on g0.
-void
-runtime·gosched_m(G *gp)
-{
-       uint32 status;
-
-       status = runtime·readgstatus(gp);
-       if((status&~Gscan) != Grunning){
-               dumpgstatus(gp);
-               runtime·throw("bad g status");
-       }
-       runtime·casgstatus(gp, Grunning, Grunnable);
-       dropg();
-       runtime·lock(&runtime·sched.lock);
-       globrunqput(gp);
-       runtime·unlock(&runtime·sched.lock);
-
-       schedule();
-}
-
-// Finishes execution of the current goroutine.
-// Must be NOSPLIT because it is called from Go.
-#pragma textflag NOSPLIT
-void
-runtime·goexit1(void)
-{
-       void (*fn)(G*);
-
-       if(raceenabled)
-               runtime·racegoend();
-       fn = goexit0;
-       runtime·mcall(&fn);
-}
-
-// runtime·goexit continuation on g0.
-static void
-goexit0(G *gp)
-{
-       runtime·casgstatus(gp, Grunning, Gdead);
-       gp->m = nil;
-       gp->lockedm = nil;
-       g->m->lockedg = nil;
-       gp->paniconfault = 0;
-       gp->defer = nil; // should be true already but just in case.
-       gp->panic = nil; // non-nil for Goexit during panic. points at stack-allocated data.
-       gp->writebuf.array = nil;
-       gp->writebuf.len = 0;
-       gp->writebuf.cap = 0;
-       gp->waitreason.str = nil;
-       gp->waitreason.len = 0;
-       gp->param = nil;
-
-       dropg();
-
-       if(g->m->locked & ~LockExternal) {
-               runtime·printf("invalid m->locked = %d\n", g->m->locked);
-               runtime·throw("internal lockOSThread error");
-       }       
-       g->m->locked = 0;
-       gfput(g->m->p, gp);
-       schedule();
-}
-
-#pragma textflag NOSPLIT
-static void
-save(uintptr pc, uintptr sp)
-{
-       g->sched.pc = pc;
-       g->sched.sp = sp;
-       g->sched.lr = 0;
-       g->sched.ret = 0;
-       g->sched.ctxt = 0;
-       g->sched.g = g;
-}
-
-static void entersyscall_bad(void);
-static void entersyscall_sysmon(void);
-static void entersyscall_gcwait(void);
-
-// The goroutine g is about to enter a system call.
-// Record that it's not using the cpu anymore.
-// This is called only from the go syscall library and cgocall,
-// not from the low-level system calls used by the runtime.
-//
-// Entersyscall cannot split the stack: the runtime·gosave must
-// make g->sched refer to the caller's stack segment, because
-// entersyscall is going to return immediately after.
-//
-// Nothing entersyscall calls can split the stack either.
-// We cannot safely move the stack during an active call to syscall,
-// because we do not know which of the uintptr arguments are
-// really pointers (back into the stack).
-// In practice, this means that we make the fast path run through
-// entersyscall doing no-split things, and the slow path has to use onM
-// to run bigger things on the m stack.
-//
-// reentersyscall is the entry point used by cgo callbacks, where explicitly
-// saved SP and PC are restored. This is needed when exitsyscall will be called
-// from a function further up in the call stack than the parent, as g->syscallsp
-// must always point to a valid stack frame. entersyscall below is the normal
-// entry point for syscalls, which obtains the SP and PC from the caller.
-#pragma textflag NOSPLIT
-void
-runtime·reentersyscall(uintptr pc, uintptr sp)
-{
-       void (*fn)(void);
-
-       // Disable preemption because during this function g is in Gsyscall status,
-       // but can have inconsistent g->sched, do not let GC observe it.
-       g->m->locks++;
-       
-       // Entersyscall must not call any function that might split/grow the stack.
-       // (See details in comment above.)
-       // Catch calls that might, by replacing the stack guard with something that
-       // will trip any stack check and leaving a flag to tell newstack to die.
-       g->stackguard0 = StackPreempt;
-       g->throwsplit = 1;
-
-       // Leave SP around for GC and traceback.
-       save(pc, sp);
-       g->syscallsp = sp;
-       g->syscallpc = pc;
-       runtime·casgstatus(g, Grunning, Gsyscall);
-       if(g->syscallsp < g->stack.lo || g->stack.hi < g->syscallsp) {
-               fn = entersyscall_bad;
-               runtime·onM(&fn);
-       }
-
-       if(runtime·atomicload(&runtime·sched.sysmonwait)) {  // TODO: fast atomic
-               fn = entersyscall_sysmon;
-               runtime·onM(&fn);
-               save(pc, sp);
-       }
-
-       g->m->mcache = nil;
-       g->m->p->m = nil;
-       runtime·atomicstore(&g->m->p->status, Psyscall);
-       if(runtime·sched.gcwaiting) {
-               fn = entersyscall_gcwait;
-               runtime·onM(&fn);
-               save(pc, sp);
-       }
-
-       // Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).
-       // We set stackguard to StackPreempt so that first split stack check calls morestack.
-       // Morestack detects this case and throws.
-       g->stackguard0 = StackPreempt;
-       g->m->locks--;
-}
-
-// Standard syscall entry used by the go syscall library and normal cgo calls.
-#pragma textflag NOSPLIT
-void
-·entersyscall(int32 dummy)
-{
-       runtime·reentersyscall((uintptr)runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
-}
-
-static void
-entersyscall_bad(void)
-{
-       G *gp;
-       
-       gp = g->m->curg;
-       runtime·printf("entersyscall inconsistent %p [%p,%p]\n",
-               gp->syscallsp, gp->stack.lo, gp->stack.hi);
-       runtime·throw("entersyscall");
-}
-
-static void
-entersyscall_sysmon(void)
-{
-       runtime·lock(&runtime·sched.lock);
-       if(runtime·atomicload(&runtime·sched.sysmonwait)) {
-               runtime·atomicstore(&runtime·sched.sysmonwait, 0);
-               runtime·notewakeup(&runtime·sched.sysmonnote);
-       }
-       runtime·unlock(&runtime·sched.lock);
-}
-
-static void
-entersyscall_gcwait(void)
-{
-       runtime·lock(&runtime·sched.lock);
-       if (runtime·sched.stopwait > 0 && runtime·cas(&g->m->p->status, Psyscall, Pgcstop)) {
-               if(--runtime·sched.stopwait == 0)
-                       runtime·notewakeup(&runtime·sched.stopnote);
-       }
-       runtime·unlock(&runtime·sched.lock);
-}
-
-static void entersyscallblock_handoff(void);
-
-// The same as runtime·entersyscall(), but with a hint that the syscall is blocking.
-#pragma textflag NOSPLIT
-void
-·entersyscallblock(int32 dummy)
-{
-       void (*fn)(void);
-
-       g->m->locks++;  // see comment in entersyscall
-       g->throwsplit = 1;
-       g->stackguard0 = StackPreempt;  // see comment in entersyscall
-
-       // Leave SP around for GC and traceback.
-       save((uintptr)runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
-       g->syscallsp = g->sched.sp;
-       g->syscallpc = g->sched.pc;
-       runtime·casgstatus(g, Grunning, Gsyscall);
-       if(g->syscallsp < g->stack.lo || g->stack.hi < g->syscallsp) {
-               fn = entersyscall_bad;
-               runtime·onM(&fn);
-       }
-       
-       fn = entersyscallblock_handoff;
-       runtime·onM(&fn);
-
-       // Resave for traceback during blocked call.
-       save((uintptr)runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
-
-       g->m->locks--;
-}
-
-static void
-entersyscallblock_handoff(void)
-{
-       handoffp(releasep());
-}
-
-// The goroutine g exited its system call.
-// Arrange for it to run on a cpu again.
-// This is called only from the go syscall library, not
-// from the low-level system calls used by the runtime.
-#pragma textflag NOSPLIT
-void
-·exitsyscall(int32 dummy)
-{
-       void (*fn)(G*);
-
-       g->m->locks++;  // see comment in entersyscall
-
-       if(runtime·getcallersp(&dummy) > g->syscallsp)
-               runtime·throw("exitsyscall: syscall frame is no longer valid");
-
-       g->waitsince = 0;
-       if(exitsyscallfast()) {
-               // There's a cpu for us, so we can run.
-               g->m->p->syscalltick++;
-               // We need to cas the status and scan before resuming...
-               runtime·casgstatus(g, Gsyscall, Grunning);
-
-               // Garbage collector isn't running (since we are),
-               // so okay to clear syscallsp.
-               g->syscallsp = (uintptr)nil;
-               g->m->locks--;
-               if(g->preempt) {
-                       // restore the preemption request in case we've cleared it in newstack
-                       g->stackguard0 = StackPreempt;
-               } else {
-                       // otherwise restore the real stackguard, we've spoiled it in entersyscall/entersyscallblock
-                       g->stackguard0 = g->stack.lo + StackGuard;
-               }
-               g->throwsplit = 0;
-               return;
-       }
-
-       g->m->locks--;
-
-       // Call the scheduler.
-       fn = exitsyscall0;
-       runtime·mcall(&fn);
-
-       // Scheduler returned, so we're allowed to run now.
-       // Delete the syscallsp information that we left for
-       // the garbage collector during the system call.
-       // Must wait until now because until gosched returns
-       // we don't know for sure that the garbage collector
-       // is not running.
-       g->syscallsp = (uintptr)nil;
-       g->m->p->syscalltick++;
-       g->throwsplit = 0;
-}
-
-static void exitsyscallfast_pidle(void);
-
-#pragma textflag NOSPLIT
-static bool
-exitsyscallfast(void)
-{
-       void (*fn)(void);
-
-       // Freezetheworld sets stopwait but does not retake P's.
-       if(runtime·sched.stopwait) {
-               g->m->p = nil;
-               return false;
-       }
-
-       // Try to re-acquire the last P.
-       if(g->m->p && g->m->p->status == Psyscall && runtime·cas(&g->m->p->status, Psyscall, Prunning)) {
-               // There's a cpu for us, so we can run.
-               g->m->mcache = g->m->p->mcache;
-               g->m->p->m = g->m;
-               return true;
-       }
-       // Try to get any other idle P.
-       g->m->p = nil;
-       if(runtime·sched.pidle) {
-               fn = exitsyscallfast_pidle;
-               runtime·onM(&fn);
-               if(g->m->scalararg[0]) {
-                       g->m->scalararg[0] = 0;
-                       return true;
-               }
-       }
-       return false;
-}
-
-static void
-exitsyscallfast_pidle(void)
-{
-       P *p;
-
-       runtime·lock(&runtime·sched.lock);
-       p = pidleget();
-       if(p && runtime·atomicload(&runtime·sched.sysmonwait)) {
-               runtime·atomicstore(&runtime·sched.sysmonwait, 0);
-               runtime·notewakeup(&runtime·sched.sysmonnote);
-       }
-       runtime·unlock(&runtime·sched.lock);
-       if(p) {
-               acquirep(p);
-               g->m->scalararg[0] = 1;
-       } else
-               g->m->scalararg[0] = 0;
-}
-
-// runtime·exitsyscall slow path on g0.
-// Failed to acquire P, enqueue gp as runnable.
-static void
-exitsyscall0(G *gp)
-{
-       P *p;
-
-       runtime·casgstatus(gp, Gsyscall, Grunnable);
-       dropg();
-       runtime·lock(&runtime·sched.lock);
-       p = pidleget();
-       if(p == nil)
-               globrunqput(gp);
-       else if(runtime·atomicload(&runtime·sched.sysmonwait)) {
-               runtime·atomicstore(&runtime·sched.sysmonwait, 0);
-               runtime·notewakeup(&runtime·sched.sysmonnote);
-       }
-       runtime·unlock(&runtime·sched.lock);
-       if(p) {
-               acquirep(p);
-               execute(gp);  // Never returns.
-       }
-       if(g->m->lockedg) {
-               // Wait until another thread schedules gp and so m again.
-               stoplockedm();
-               execute(gp);  // Never returns.
-       }
-       stopm();
-       schedule();  // Never returns.
-}
-
-static void
-beforefork(void)
-{
-       G *gp;
-       
-       gp = g->m->curg;
-       // Fork can hang if preempted with signals frequently enough (see issue 5517).
-       // Ensure that we stay on the same M where we disable profiling.
-       gp->m->locks++;
-       if(gp->m->profilehz != 0)
-               runtime·resetcpuprofiler(0);
-
-       // This function is called before fork in syscall package.
-       // Code between fork and exec must not allocate memory nor even try to grow stack.
-       // Here we spoil g->stackguard to reliably detect any attempts to grow stack.
-       // runtime_AfterFork will undo this in parent process, but not in child.
-       gp->stackguard0 = StackFork;
-}
-
-// Called from syscall package before fork.
-#pragma textflag NOSPLIT
-void
-syscall·runtime_BeforeFork(void)
-{
-       void (*fn)(void);
-       
-       fn = beforefork;
-       runtime·onM(&fn);
-}
-
-static void
-afterfork(void)
-{
-       int32 hz;
-       G *gp;
-       
-       gp = g->m->curg;
-       // See the comment in runtime_BeforeFork.
-       gp->stackguard0 = gp->stack.lo + StackGuard;
-
-       hz = runtime·sched.profilehz;
-       if(hz != 0)
-               runtime·resetcpuprofiler(hz);
-       gp->m->locks--;
-}
-
-// Called from syscall package after fork in parent.
-#pragma textflag NOSPLIT
-void
-syscall·runtime_AfterFork(void)
-{
-       void (*fn)(void);
-       
-       fn = afterfork;
-       runtime·onM(&fn);
-}
-
-// Hook used by runtime·malg to call runtime·stackalloc on the
-// scheduler stack.  This exists because runtime·stackalloc insists
-// on being called on the scheduler stack, to avoid trying to grow
-// the stack while allocating a new stack segment.
-static void
-mstackalloc(G *gp)
-{
-       G *newg;
-       uintptr size;
-
-       newg = g->m->ptrarg[0];
-       size = g->m->scalararg[0];
-
-       newg->stack = runtime·stackalloc(size);
-
-       runtime·gogo(&gp->sched);
-}
-
-// Allocate a new g, with a stack big enough for stacksize bytes.
-G*
-runtime·malg(int32 stacksize)
-{
-       G *newg;
-       void (*fn)(G*);
-
-       newg = allocg();
-       if(stacksize >= 0) {
-               stacksize = runtime·round2(StackSystem + stacksize);
-               if(g == g->m->g0) {
-                       // running on scheduler stack already.
-                       newg->stack = runtime·stackalloc(stacksize);
-               } else {
-                       // have to call stackalloc on scheduler stack.
-                       g->m->scalararg[0] = stacksize;
-                       g->m->ptrarg[0] = newg;
-                       fn = mstackalloc;
-                       runtime·mcall(&fn);
-                       g->m->ptrarg[0] = nil;
-               }
-               newg->stackguard0 = newg->stack.lo + StackGuard;
-               newg->stackguard1 = ~(uintptr)0;
-       }
-       return newg;
-}
-
-static void
-newproc_m(void)
-{
-       byte *argp;
-       void *callerpc;
-       FuncVal *fn;
-       int32 siz;
-
-       siz = g->m->scalararg[0];
-       callerpc = (void*)g->m->scalararg[1];   
-       argp = g->m->ptrarg[0];
-       fn = (FuncVal*)g->m->ptrarg[1];
-
-       runtime·newproc1(fn, argp, siz, 0, callerpc);
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-}
-
-// Create a new g running fn with siz bytes of arguments.
-// Put it on the queue of g's waiting to run.
-// The compiler turns a go statement into a call to this.
-// Cannot split the stack because it assumes that the arguments
-// are available sequentially after &fn; they would not be
-// copied if a stack split occurred.
-#pragma textflag NOSPLIT
-void
-runtime·newproc(int32 siz, FuncVal* fn, ...)
-{
-       byte *argp;
-       void (*mfn)(void);
-
-       if(thechar == '5')
-               argp = (byte*)(&fn+2);  // skip caller's saved LR
-       else
-               argp = (byte*)(&fn+1);
-
-       g->m->locks++;
-       g->m->scalararg[0] = siz;
-       g->m->scalararg[1] = (uintptr)runtime·getcallerpc(&siz);
-       g->m->ptrarg[0] = argp;
-       g->m->ptrarg[1] = fn;
-       mfn = newproc_m;
-       runtime·onM(&mfn);
-       g->m->locks--;
-}
-
-void runtime·main(void);
-
-// Create a new g running fn with narg bytes of arguments starting
-// at argp and returning nret bytes of results.  callerpc is the
-// address of the go statement that created this.  The new g is put
-// on the queue of g's waiting to run.
-G*
-runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerpc)
-{
-       byte *sp;
-       G *newg;
-       P *p;
-       int32 siz;
-
-       if(fn == nil) {
-               g->m->throwing = -1;  // do not dump full stacks
-               runtime·throw("go of nil func value");
-       }
-       g->m->locks++;  // disable preemption because it can be holding p in a local var
-       siz = narg + nret;
-       siz = (siz+7) & ~7;
-
-       // We could allocate a larger initial stack if necessary.
-       // Not worth it: this is almost always an error.
-       // 4*sizeof(uintreg): extra space added below
-       // sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
-       if(siz >= StackMin - 4*sizeof(uintreg) - sizeof(uintreg))
-               runtime·throw("runtime.newproc: function arguments too large for new goroutine");
-
-       p = g->m->p;
-       if((newg = gfget(p)) == nil) {
-               newg = runtime·malg(StackMin);
-               runtime·casgstatus(newg, Gidle, Gdead);
-               runtime·allgadd(newg); // publishes with a g->status of Gdead so GC scanner doesn't look at uninitialized stack.
-       }
-       if(newg->stack.hi == 0)
-               runtime·throw("newproc1: newg missing stack");
-
-       if(runtime·readgstatus(newg) != Gdead) 
-               runtime·throw("newproc1: new g is not Gdead");
-
-       sp = (byte*)newg->stack.hi;
-       sp -= 4*sizeof(uintreg); // extra space in case of reads slightly beyond frame
-       sp -= siz;
-       runtime·memmove(sp, argp, narg);
-       if(thechar == '5') {
-               // caller's LR
-               sp -= sizeof(void*);
-               *(void**)sp = nil;
-       }
-
-       runtime·memclr((byte*)&newg->sched, sizeof newg->sched);
-       newg->sched.sp = (uintptr)sp;
-       newg->sched.pc = (uintptr)runtime·goexit + PCQuantum; // +PCQuantum so that previous instruction is in same function
-       newg->sched.g = newg;
-       runtime·gostartcallfn(&newg->sched, fn);
-       newg->gopc = (uintptr)callerpc;
-       runtime·casgstatus(newg, Gdead, Grunnable);
-
-       if(p->goidcache == p->goidcacheend) {
-               // Sched.goidgen is the last allocated id,
-               // this batch must be [sched.goidgen+1, sched.goidgen+GoidCacheBatch].
-               // At startup sched.goidgen=0, so main goroutine receives goid=1.
-               p->goidcache = runtime·xadd64(&runtime·sched.goidgen, GoidCacheBatch);
-               p->goidcache -= GoidCacheBatch - 1;
-               p->goidcacheend = p->goidcache + GoidCacheBatch;
-       }
-       newg->goid = p->goidcache++;
-       if(raceenabled)
-               newg->racectx = runtime·racegostart((void*)callerpc);
-       runqput(p, newg);
-
-       if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0 && fn->fn != runtime·main)  // TODO: fast atomic
-               wakep();
-       g->m->locks--;
-       if(g->m->locks == 0 && g->preempt)  // restore the preemption request in case we've cleared it in newstack
-               g->stackguard0 = StackPreempt;
-       return newg;
-}
-
-// Put on gfree list.
-// If local list is too long, transfer a batch to the global list.
-static void
-gfput(P *p, G *gp)
-{
-       uintptr stksize;
-
-       if(runtime·readgstatus(gp) != Gdead) 
-               runtime·throw("gfput: bad status (not Gdead)");
-
-       stksize = gp->stack.hi - gp->stack.lo;
-       
-       if(stksize != FixedStack) {
-               // non-standard stack size - free it.
-               runtime·stackfree(gp->stack);
-               gp->stack.lo = 0;
-               gp->stack.hi = 0;
-               gp->stackguard0 = 0;
-       }
-       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·sched.ngfree++;
-               }
-               runtime·unlock(&runtime·sched.gflock);
-       }
-}
-
-// Get from gfree list.
-// If local list is empty, grab a batch from global list.
-static G*
-gfget(P *p)
-{
-       G *gp;
-       void (*fn)(G*);
-
-retry:
-       gp = p->gfree;
-       if(gp == nil && runtime·sched.gfree) {
-               runtime·lock(&runtime·sched.gflock);
-               while(p->gfreecnt < 32 && runtime·sched.gfree != nil) {
-                       p->gfreecnt++;
-                       gp = runtime·sched.gfree;
-                       runtime·sched.gfree = gp->schedlink;
-                       runtime·sched.ngfree--;
-                       gp->schedlink = p->gfree;
-                       p->gfree = gp;
-               }
-               runtime·unlock(&runtime·sched.gflock);
-               goto retry;
-       }
-       if(gp) {
-               p->gfree = gp->schedlink;
-               p->gfreecnt--;
-
-               if(gp->stack.lo == 0) {
-                       // Stack was deallocated in gfput.  Allocate a new one.
-                       if(g == g->m->g0) {
-                               gp->stack = runtime·stackalloc(FixedStack);
-                       } else {
-                               g->m->scalararg[0] = FixedStack;
-                               g->m->ptrarg[0] = gp;
-                               fn = mstackalloc;
-                               runtime·mcall(&fn);
-                               g->m->ptrarg[0] = nil;
-                       }
-                       gp->stackguard0 = gp->stack.lo + StackGuard;
-               } else {
-                       if(raceenabled)
-                               runtime·racemalloc((void*)gp->stack.lo, gp->stack.hi - gp->stack.lo);
-               }
-       }
-       return gp;
-}
-
-// Purge all cached G's from gfree list to the global list.
-static void
-gfpurge(P *p)
-{
-       G *gp;
-
-       runtime·lock(&runtime·sched.gflock);
-       while(p->gfreecnt != 0) {
-               p->gfreecnt--;
-               gp = p->gfree;
-               p->gfree = gp->schedlink;
-               gp->schedlink = runtime·sched.gfree;
-               runtime·sched.gfree = gp;
-               runtime·sched.ngfree++;
-       }
-       runtime·unlock(&runtime·sched.gflock);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·Breakpoint(void)
-{
-       runtime·breakpoint();
-}
-
-// lockOSThread is called by runtime.LockOSThread and runtime.lockOSThread below
-// after they modify m->locked. Do not allow preemption during this call,
-// or else the m might be different in this function than in the caller.
-#pragma textflag NOSPLIT
-static void
-lockOSThread(void)
-{
-       g->m->lockedg = g;
-       g->lockedm = g->m;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·LockOSThread(void)
-{
-       g->m->locked |= LockExternal;
-       lockOSThread();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·lockOSThread(void)
-{
-       g->m->locked += LockInternal;
-       lockOSThread();
-}
-
-
-// unlockOSThread is called by runtime.UnlockOSThread and runtime.unlockOSThread below
-// after they update m->locked. Do not allow preemption during this call,
-// or else the m might be in different in this function than in the caller.
-#pragma textflag NOSPLIT
-static void
-unlockOSThread(void)
-{
-       if(g->m->locked != 0)
-               return;
-       g->m->lockedg = nil;
-       g->lockedm = nil;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·UnlockOSThread(void)
-{
-       g->m->locked &= ~LockExternal;
-       unlockOSThread();
-}
-
-static void badunlockOSThread(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·unlockOSThread(void)
-{
-       void (*fn)(void);
-
-       if(g->m->locked < LockInternal) {
-               fn = badunlockOSThread;
-               runtime·onM(&fn);
-       }
-       g->m->locked -= LockInternal;
-       unlockOSThread();
-}
-
-static void
-badunlockOSThread(void)
-{
-       runtime·throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
-}
-
-#pragma textflag NOSPLIT
-int32
-runtime·gcount(void)
-{
-       P *p, **pp;
-       int32 n;
-
-       n = runtime·allglen - runtime·sched.ngfree;
-       for(pp=runtime·allp; p=*pp; pp++)
-               n -= p->gfreecnt;
-       // All these variables can be changed concurrently, so the result can be inconsistent.
-       // But at least the current goroutine is running.
-       if(n < 1)
-               n = 1;
-       return n;
-}
-
-int32
-runtime·mcount(void)
-{
-       return runtime·sched.mcount;
-}
-
-static struct ProfState {
-       uint32 lock;
-       int32 hz;
-} prof;
-
-static void System(void) { System(); }
-static void ExternalCode(void) { ExternalCode(); }
-static void GC(void) { GC(); }
-
-extern void runtime·cpuproftick(uintptr*, int32);
-extern byte runtime·etext[];
-
-// Called if we receive a SIGPROF signal.
-void
-runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp)
-{
-       int32 n;
-       bool traceback;
-       // Do not use global m in this function, use mp instead.
-       // On windows one m is sending reports about all the g's, so m means a wrong thing.
-       byte m;
-       uintptr stk[100];
-
-       m = 0;
-       USED(m);
-
-       if(prof.hz == 0)
-               return;
-
-       // Profiling runs concurrently with GC, so it must not allocate.
-       mp->mallocing++;
-
-       // Define that a "user g" is a user-created goroutine, and a "system g"
-       // is one that is m->g0 or m->gsignal. We've only made sure that we
-       // can unwind user g's, so exclude the system g's.
-       //
-       // It is not quite as easy as testing gp == m->curg (the current user g)
-       // because we might be interrupted for profiling halfway through a
-       // goroutine switch. The switch involves updating three (or four) values:
-       // g, PC, SP, and (on arm) LR. The PC must be the last to be updated,
-       // because once it gets updated the new g is running.
-       //
-       // When switching from a user g to a system g, LR is not considered live,
-       // so the update only affects g, SP, and PC. Since PC must be last, there
-       // the possible partial transitions in ordinary execution are (1) g alone is updated,
-       // (2) both g and SP are updated, and (3) SP alone is updated.
-       // If g is updated, we'll see a system g and not look closer.
-       // If SP alone is updated, we can detect the partial transition by checking
-       // whether the SP is within g's stack bounds. (We could also require that SP
-       // be changed only after g, but the stack bounds check is needed by other
-       // cases, so there is no need to impose an additional requirement.)
-       //
-       // There is one exceptional transition to a system g, not in ordinary execution.
-       // When a signal arrives, the operating system starts the signal handler running
-       // with an updated PC and SP. The g is updated last, at the beginning of the
-       // handler. There are two reasons this is okay. First, until g is updated the
-       // g and SP do not match, so the stack bounds check detects the partial transition.
-       // Second, signal handlers currently run with signals disabled, so a profiling
-       // signal cannot arrive during the handler.
-       //
-       // When switching from a system g to a user g, there are three possibilities.
-       //
-       // First, it may be that the g switch has no PC update, because the SP
-       // either corresponds to a user g throughout (as in runtime.asmcgocall)
-       // or because it has been arranged to look like a user g frame
-       // (as in runtime.cgocallback_gofunc). In this case, since the entire
-       // transition is a g+SP update, a partial transition updating just one of 
-       // those will be detected by the stack bounds check.
-       //
-       // Second, when returning from a signal handler, the PC and SP updates
-       // are performed by the operating system in an atomic update, so the g
-       // update must be done before them. The stack bounds check detects
-       // the partial transition here, and (again) signal handlers run with signals
-       // disabled, so a profiling signal cannot arrive then anyway.
-       //
-       // Third, the common case: it may be that the switch updates g, SP, and PC
-       // separately, as in runtime.gogo.
-       //
-       // Because runtime.gogo is the only instance, we check whether the PC lies
-       // within that function, and if so, not ask for a traceback. This approach
-       // requires knowing the size of the runtime.gogo function, which we
-       // record in arch_*.h and check in runtime_test.go.
-       //
-       // There is another apparently viable approach, recorded here in case
-       // the "PC within runtime.gogo" check turns out not to be usable.
-       // It would be possible to delay the update of either g or SP until immediately
-       // before the PC update instruction. Then, because of the stack bounds check,
-       // the only problematic interrupt point is just before that PC update instruction,
-       // and the sigprof handler can detect that instruction and simulate stepping past
-       // it in order to reach a consistent state. On ARM, the update of g must be made
-       // in two places (in R10 and also in a TLS slot), so the delayed update would
-       // need to be the SP update. The sigprof handler must read the instruction at
-       // the current PC and if it was the known instruction (for example, JMP BX or 
-       // MOV R2, PC), use that other register in place of the PC value.
-       // The biggest drawback to this solution is that it requires that we can tell
-       // whether it's safe to read from the memory pointed at by PC.
-       // In a correct program, we can test PC == nil and otherwise read,
-       // but if a profiling signal happens at the instant that a program executes
-       // a bad jump (before the program manages to handle the resulting fault)
-       // the profiling handler could fault trying to read nonexistent memory.
-       //
-       // To recap, there are no constraints on the assembly being used for the
-       // transition. We simply require that g and SP match and that the PC is not
-       // in runtime.gogo.
-       traceback = true;
-       if(gp == nil || gp != mp->curg ||
-          (uintptr)sp < gp->stack.lo || gp->stack.hi < (uintptr)sp ||
-          ((uint8*)runtime·gogo <= pc && pc < (uint8*)runtime·gogo + RuntimeGogoBytes))
-               traceback = false;
-
-       n = 0;
-       if(traceback)
-               n = runtime·gentraceback((uintptr)pc, (uintptr)sp, (uintptr)lr, gp, 0, stk, nelem(stk), nil, nil, TraceTrap);
-       if(!traceback || n <= 0) {
-               // Normal traceback is impossible or has failed.
-               // See if it falls into several common cases.
-               n = 0;
-               if(mp->ncgo > 0 && mp->curg != nil &&
-                       mp->curg->syscallpc != 0 && mp->curg->syscallsp != 0) {
-                       // Cgo, we can't unwind and symbolize arbitrary C code,
-                       // so instead collect Go stack that leads to the cgo call.
-                       // This is especially important on windows, since all syscalls are cgo calls.
-                       n = runtime·gentraceback(mp->curg->syscallpc, mp->curg->syscallsp, 0, mp->curg, 0, stk, nelem(stk), nil, nil, 0);
-               }
-#ifdef GOOS_windows
-               if(n == 0 && mp->libcallg != nil && mp->libcallpc != 0 && mp->libcallsp != 0) {
-                       // Libcall, i.e. runtime syscall on windows.
-                       // Collect Go stack that leads to the call.
-                       n = runtime·gentraceback(mp->libcallpc, mp->libcallsp, 0, mp->libcallg, 0, stk, nelem(stk), nil, nil, 0);
-               }
-#endif
-               if(n == 0) {
-                       // If all of the above has failed, account it against abstract "System" or "GC".
-                       n = 2;
-                       // "ExternalCode" is better than "etext".
-                       if((uintptr)pc > (uintptr)runtime·etext)
-                               pc = (byte*)ExternalCode + PCQuantum;
-                       stk[0] = (uintptr)pc;
-                       if(mp->gcing || mp->helpgc)
-                               stk[1] = (uintptr)GC + PCQuantum;
-                       else
-                               stk[1] = (uintptr)System + PCQuantum;
-               }
-       }
-
-       if(prof.hz != 0) {
-               // Simple cas-lock to coordinate with setcpuprofilerate.
-               while(!runtime·cas(&prof.lock, 0, 1))
-                       runtime·osyield();
-               if(prof.hz != 0)
-                       runtime·cpuproftick(stk, n);
-               runtime·atomicstore(&prof.lock, 0);
-       }
-       mp->mallocing--;
-}
-
-// Arrange to call fn with a traceback hz times a second.
-void
-runtime·setcpuprofilerate_m(void)
-{
-       int32 hz;
-       
-       hz = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-
-       // Force sane arguments.
-       if(hz < 0)
-               hz = 0;
-
-       // Disable preemption, otherwise we can be rescheduled to another thread
-       // that has profiling enabled.
-       g->m->locks++;
-
-       // Stop profiler on this thread so that it is safe to lock prof.
-       // if a profiling signal came in while we had prof locked,
-       // it would deadlock.
-       runtime·resetcpuprofiler(0);
-
-       while(!runtime·cas(&prof.lock, 0, 1))
-               runtime·osyield();
-       prof.hz = hz;
-       runtime·atomicstore(&prof.lock, 0);
-
-       runtime·lock(&runtime·sched.lock);
-       runtime·sched.profilehz = hz;
-       runtime·unlock(&runtime·sched.lock);
-
-       if(hz != 0)
-               runtime·resetcpuprofiler(hz);
-
-       g->m->locks--;
-}
-
-P *runtime·newP(void);
-
-// Change number of processors.  The world is stopped, sched is locked.
-static void
-procresize(int32 new)
-{
-       int32 i, old;
-       bool empty;
-       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 = runtime·newP();
-                       p->id = i;
-                       p->status = Pgcstop;
-                       runtime·atomicstorep(&runtime·allp[i], p);
-               }
-               if(p->mcache == nil) {
-                       if(old==0 && i==0)
-                               p->mcache = g->m->mcache;  // bootstrap
-                       else
-                               p->mcache = runtime·allocmcache();
-               }
-       }
-
-       // redistribute runnable G's evenly
-       // collect all runnable goroutines in global queue preserving FIFO order
-       // FIFO order is required to ensure fairness even during frequent GCs
-       // see http://golang.org/issue/7126
-       empty = false;
-       while(!empty) {
-               empty = true;
-               for(i = 0; i < old; i++) {
-                       p = runtime·allp[i];
-                       if(p->runqhead == p->runqtail)
-                               continue;
-                       empty = false;
-                       // pop from tail of local queue
-                       p->runqtail--;
-                       gp = p->runq[p->runqtail%nelem(p->runq)];
-                       // push onto head of global queue
-                       gp->schedlink = runtime·sched.runqhead;
-                       runtime·sched.runqhead = gp;
-                       if(runtime·sched.runqtail == nil)
-                               runtime·sched.runqtail = gp;
-                       runtime·sched.runqsize++;
-               }
-       }
-       // fill local queues with at most nelem(p->runq)/2 goroutines
-       // 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; i < new * nelem(p->runq)/2 && runtime·sched.runqsize > 0; i++) {
-               gp = runtime·sched.runqhead;
-               runtime·sched.runqhead = gp->schedlink;
-               if(runtime·sched.runqhead == nil)
-                       runtime·sched.runqtail = nil;
-               runtime·sched.runqsize--;
-               runqput(runtime·allp[i%new], gp);
-       }
-
-       // 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(g->m->p)
-               g->m->p->m = nil;
-       g->m->p = nil;
-       g->m->mcache = nil;
-       p = runtime·allp[0];
-       p->m = nil;
-       p->status = Pidle;
-       acquirep(p);
-       for(i = new-1; i > 0; i--) {
-               p = runtime·allp[i];
-               p->status = Pidle;
-               pidleput(p);
-       }
-       runtime·atomicstore((uint32*)&runtime·gomaxprocs, new);
-}
-
-// Associate p and the current m.
-static void
-acquirep(P *p)
-{
-       if(g->m->p || g->m->mcache)
-               runtime·throw("acquirep: already in go");
-       if(p->m || p->status != Pidle) {
-               runtime·printf("acquirep: p->m=%p(%d) p->status=%d\n", p->m, p->m ? p->m->id : 0, p->status);
-               runtime·throw("acquirep: invalid p state");
-       }
-       g->m->mcache = p->mcache;
-       g->m->p = p;
-       p->m = g->m;
-       p->status = Prunning;
-}
-
-// Disassociate p and the current m.
-static P*
-releasep(void)
-{
-       P *p;
-
-       if(g->m->p == nil || g->m->mcache == nil)
-               runtime·throw("releasep: invalid arg");
-       p = g->m->p;
-       if(p->m != g->m || p->mcache != g->m->mcache || p->status != Prunning) {
-               runtime·printf("releasep: m=%p m->p=%p p->m=%p m->mcache=%p p->mcache=%p p->status=%d\n",
-                       g->m, g->m->p, p->m, g->m->mcache, p->mcache, p->status);
-               runtime·throw("releasep: invalid p state");
-       }
-       g->m->p = nil;
-       g->m->mcache = nil;
-       p->m = nil;
-       p->status = Pidle;
-       return p;
-}
-
-static void
-incidlelocked(int32 v)
-{
-       runtime·lock(&runtime·sched.lock);
-       runtime·sched.nmidlelocked += v;
-       if(v > 0)
-               checkdead();
-       runtime·unlock(&runtime·sched.lock);
-}
-
-// Check for deadlock situation.
-// The check is based on number of running M's, if 0 -> deadlock.
-static void
-checkdead(void)
-{
-       G *gp;
-       P *p;
-       M *mp;
-       int32 run, grunning, s;
-       uintptr i;
-
-       // -1 for sysmon
-       run = runtime·sched.mcount - runtime·sched.nmidle - runtime·sched.nmidlelocked - 1;
-       if(run > 0)
-               return;
-       // If we are dying because of a signal caught on an already idle thread,
-       // freezetheworld will cause all running threads to block.
-       // And runtime will essentially enter into deadlock state,
-       // except that there is a thread that will call runtime·exit soon.
-       if(runtime·panicking > 0)
-               return;
-       if(run < 0) {
-               runtime·printf("runtime: checkdead: nmidle=%d nmidlelocked=%d mcount=%d\n",
-                       runtime·sched.nmidle, runtime·sched.nmidlelocked, runtime·sched.mcount);
-               runtime·throw("checkdead: inconsistent counts");
-       }
-       grunning = 0;
-       runtime·lock(&runtime·allglock);
-       for(i = 0; i < runtime·allglen; i++) {
-               gp = runtime·allg[i];
-               if(gp->issystem)
-                       continue;
-               s = runtime·readgstatus(gp);
-               switch(s&~Gscan) {
-               case Gwaiting:
-                       grunning++;
-                       break;
-               case Grunnable:
-               case Grunning:
-               case Gsyscall:
-                       runtime·unlock(&runtime·allglock);
-                       runtime·printf("runtime: checkdead: find g %D in status %d\n", gp->goid, s);
-                       runtime·throw("checkdead: runnable g");
-                       break;
-               }
-       }
-       runtime·unlock(&runtime·allglock);
-       if(grunning == 0)  // possible if main goroutine calls runtime·Goexit()
-               runtime·throw("no goroutines (main called runtime.Goexit) - deadlock!");
-
-       // Maybe jump time forward for playground.
-       if((gp = runtime·timejump()) != nil) {
-               runtime·casgstatus(gp, Gwaiting, Grunnable);
-               globrunqput(gp);
-               p = pidleget();
-               if(p == nil)
-                       runtime·throw("checkdead: no p for timer");
-               mp = mget();
-               if(mp == nil)
-                       newm(nil, p);
-               else {
-                       mp->nextp = p;
-                       runtime·notewakeup(&mp->park);
-               }
-               return;
-       }
-
-       g->m->throwing = -1;  // do not dump full stacks
-       runtime·throw("all goroutines are asleep - deadlock!");
-}
-
-static void
-sysmon(void)
-{
-       uint32 idle, delay, nscavenge;
-       int64 now, unixnow, lastpoll, lasttrace, lastgc;
-       int64 forcegcperiod, scavengelimit, lastscavenge, maxsleep;
-       G *gp;
-
-       // If we go two minutes without a garbage collection, force one to run.
-       forcegcperiod = 2*60*1e9;
-       // If a heap span goes unused for 5 minutes after a garbage collection,
-       // we hand it back to the operating system.
-       scavengelimit = 5*60*1e9;
-       if(runtime·debug.scavenge > 0) {
-               // Scavenge-a-lot for testing.
-               forcegcperiod = 10*1e6;
-               scavengelimit = 20*1e6;
-       }
-       lastscavenge = runtime·nanotime();
-       nscavenge = 0;
-       // Make wake-up period small enough for the sampling to be correct.
-       maxsleep = forcegcperiod/2;
-       if(scavengelimit < forcegcperiod)
-               maxsleep = scavengelimit/2;
-
-       lasttrace = 0;
-       idle = 0;  // how many cycles in succession we had not wokeup somebody
-       delay = 0;
-       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·debug.schedtrace <= 0 &&
-                       (runtime·sched.gcwaiting || runtime·atomicload(&runtime·sched.npidle) == runtime·gomaxprocs)) {  // TODO: fast atomic
-                       runtime·lock(&runtime·sched.lock);
-                       if(runtime·atomicload(&runtime·sched.gcwaiting) || runtime·atomicload(&runtime·sched.npidle) == runtime·gomaxprocs) {
-                               runtime·atomicstore(&runtime·sched.sysmonwait, 1);
-                               runtime·unlock(&runtime·sched.lock);
-                               runtime·notetsleep(&runtime·sched.sysmonnote, maxsleep);
-                               runtime·lock(&runtime·sched.lock);
-                               runtime·atomicstore(&runtime·sched.sysmonwait, 0);
-                               runtime·noteclear(&runtime·sched.sysmonnote);
-                               idle = 0;
-                               delay = 20;
-                       }
-                       runtime·unlock(&runtime·sched.lock);
-               }
-               // poll network if not polled for more than 10ms
-               lastpoll = runtime·atomicload64(&runtime·sched.lastpoll);
-               now = runtime·nanotime();
-               unixnow = runtime·unixnanotime();
-               if(lastpoll != 0 && lastpoll + 10*1000*1000 < now) {
-                       runtime·cas64(&runtime·sched.lastpoll, lastpoll, now);
-                       gp = runtime·netpoll(false);  // non-blocking
-                       if(gp) {
-                               // Need to decrement number of idle locked M's
-                               // (pretending that one more is running) before injectglist.
-                               // Otherwise it can lead to the following situation:
-                               // injectglist grabs all P's but before it starts M's to run the P's,
-                               // another M returns from syscall, finishes running its G,
-                               // observes that there is no work to do and no other running M's
-                               // and reports deadlock.
-                               incidlelocked(-1);
-                               injectglist(gp);
-                               incidlelocked(1);
-                       }
-               }
-               // retake P's blocked in syscalls
-               // and preempt long running G's
-               if(retake(now))
-                       idle = 0;
-               else
-                       idle++;
-
-               // check if we need to force a GC
-               lastgc = runtime·atomicload64(&mstats.last_gc);
-               if(lastgc != 0 && unixnow - lastgc > forcegcperiod && runtime·atomicload(&runtime·forcegc.idle)) {
-                       runtime·lock(&runtime·forcegc.lock);
-                       runtime·forcegc.idle = 0;
-                       runtime·forcegc.g->schedlink = nil;
-                       injectglist(runtime·forcegc.g);
-                       runtime·unlock(&runtime·forcegc.lock);
-               }
-
-               // scavenge heap once in a while
-               if(lastscavenge + scavengelimit/2 < now) {
-                       runtime·MHeap_Scavenge(nscavenge, now, scavengelimit);
-                       lastscavenge = now;
-                       nscavenge++;
-               }
-
-               if(runtime·debug.schedtrace > 0 && lasttrace + runtime·debug.schedtrace*1000000ll <= now) {
-                       lasttrace = now;
-                       runtime·schedtrace(runtime·debug.scheddetail);
-               }
-       }
-}
-
-typedef struct Pdesc Pdesc;
-struct Pdesc
-{
-       uint32  schedtick;
-       int64   schedwhen;
-       uint32  syscalltick;
-       int64   syscallwhen;
-};
-#pragma dataflag NOPTR
-static Pdesc pdesc[MaxGomaxprocs];
-
-static uint32
-retake(int64 now)
-{
-       uint32 i, s, n;
-       int64 t;
-       P *p;
-       Pdesc *pd;
-
-       n = 0;
-       for(i = 0; i < runtime·gomaxprocs; i++) {
-               p = runtime·allp[i];
-               if(p==nil)
-                       continue;
-               pd = &pdesc[i];
-               s = p->status;
-               if(s == Psyscall) {
-                       // Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
-                       t = p->syscalltick;
-                       if(pd->syscalltick != t) {
-                               pd->syscalltick = t;
-                               pd->syscallwhen = now;
-                               continue;
-                       }
-                       // On the one hand we don't want to retake Ps if there is no other work to do,
-                       // but on the other hand we want to retake them eventually
-                       // because they can prevent the sysmon thread from deep sleep.
-                       if(p->runqhead == p->runqtail &&
-                               runtime·atomicload(&runtime·sched.nmspinning) + runtime·atomicload(&runtime·sched.npidle) > 0 &&
-                               pd->syscallwhen + 10*1000*1000 > now)
-                               continue;
-                       // Need to decrement number of idle locked M's
-                       // (pretending that one more is running) before the CAS.
-                       // Otherwise the M from which we retake can exit the syscall,
-                       // increment nmidle and report deadlock.
-                       incidlelocked(-1);
-                       if(runtime·cas(&p->status, s, Pidle)) {
-                               n++;
-                               handoffp(p);
-                       }
-                       incidlelocked(1);
-               } else if(s == Prunning) {
-                       // Preempt G if it's running for more than 10ms.
-                       t = p->schedtick;
-                       if(pd->schedtick != t) {
-                               pd->schedtick = t;
-                               pd->schedwhen = now;
-                               continue;
-                       }
-                       if(pd->schedwhen + 10*1000*1000 > now)
-                               continue;
-                       preemptone(p);
-               }
-       }
-       return n;
-}
-
-// Tell all goroutines that they have been preempted and they should stop.
-// This function is purely best-effort.  It can fail to inform a goroutine if a
-// processor just started running it.
-// No locks need to be held.
-// Returns true if preemption request was issued to at least one goroutine.
-static bool
-preemptall(void)
-{
-       P *p;
-       int32 i;
-       bool res;
-
-       res = false;
-       for(i = 0; i < runtime·gomaxprocs; i++) {
-               p = runtime·allp[i];
-               if(p == nil || p->status != Prunning)
-                       continue;
-               res |= preemptone(p);
-       }
-       return res;
-}
-
-// Tell the goroutine running on processor P to stop.
-// This function is purely best-effort.  It can incorrectly fail to inform the
-// goroutine.  It can send inform the wrong goroutine.  Even if it informs the
-// correct goroutine, that goroutine might ignore the request if it is
-// simultaneously executing runtime·newstack.
-// No lock needs to be held.
-// Returns true if preemption request was issued.
-// The actual preemption will happen at some point in the future
-// and will be indicated by the gp->status no longer being
-// Grunning
-static bool
-preemptone(P *p)
-{
-       M *mp;
-       G *gp;
-
-       mp = p->m;
-       if(mp == nil || mp == g->m)
-               return false;
-       gp = mp->curg;
-       if(gp == nil || gp == mp->g0)
-               return false;
-       gp->preempt = true;
-       // Every call in a go routine checks for stack overflow by
-       // comparing the current stack pointer to gp->stackguard0.
-       // Setting gp->stackguard0 to StackPreempt folds
-       // preemption into the normal stack overflow check.
-       gp->stackguard0 = StackPreempt;
-       return true;
-}
-
-void
-runtime·schedtrace(bool detailed)
-{
-       static int64 starttime;
-       int64 now;
-       int64 id1, id2, id3;
-       int32 i, t, h;
-       uintptr gi;
-       int8 *fmt;
-       M *mp, *lockedm;
-       G *gp, *lockedg;
-       P *p;
-
-       now = runtime·nanotime();
-       if(starttime == 0)
-               starttime = now;
-
-       runtime·lock(&runtime·sched.lock);
-       runtime·printf("SCHED %Dms: gomaxprocs=%d idleprocs=%d threads=%d spinningthreads=%d idlethreads=%d runqueue=%d",
-               (now-starttime)/1000000, runtime·gomaxprocs, runtime·sched.npidle, runtime·sched.mcount,
-               runtime·sched.nmspinning, runtime·sched.nmidle, runtime·sched.runqsize);
-       if(detailed) {
-               runtime·printf(" gcwaiting=%d nmidlelocked=%d stopwait=%d sysmonwait=%d\n",
-                       runtime·sched.gcwaiting, runtime·sched.nmidlelocked,
-                       runtime·sched.stopwait, runtime·sched.sysmonwait);
-       }
-       // We must be careful while reading data from P's, M's and G's.
-       // Even if we hold schedlock, most data can be changed concurrently.
-       // E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
-       for(i = 0; i < runtime·gomaxprocs; i++) {
-               p = runtime·allp[i];
-               if(p == nil)
-                       continue;
-               mp = p->m;
-               h = runtime·atomicload(&p->runqhead);
-               t = runtime·atomicload(&p->runqtail);
-               if(detailed)
-                       runtime·printf("  P%d: status=%d schedtick=%d syscalltick=%d m=%d runqsize=%d gfreecnt=%d\n",
-                               i, p->status, p->schedtick, p->syscalltick, mp ? mp->id : -1, t-h, p->gfreecnt);
-               else {
-                       // In non-detailed mode format lengths of per-P run queues as:
-                       // [len1 len2 len3 len4]
-                       fmt = " %d";
-                       if(runtime·gomaxprocs == 1)
-                               fmt = " [%d]\n";
-                       else if(i == 0)
-                               fmt = " [%d";
-                       else if(i == runtime·gomaxprocs-1)
-                               fmt = " %d]\n";
-                       runtime·printf(fmt, t-h);
-               }
-       }
-       if(!detailed) {
-               runtime·unlock(&runtime·sched.lock);
-               return;
-       }
-       for(mp = runtime·allm; mp; mp = mp->alllink) {
-               p = mp->p;
-               gp = mp->curg;
-               lockedg = mp->lockedg;
-               id1 = -1;
-               if(p)
-                       id1 = p->id;
-               id2 = -1;
-               if(gp)
-                       id2 = gp->goid;
-               id3 = -1;
-               if(lockedg)
-                       id3 = lockedg->goid;
-               runtime·printf("  M%d: p=%D curg=%D mallocing=%d throwing=%d gcing=%d"
-                       " locks=%d dying=%d helpgc=%d spinning=%d blocked=%d lockedg=%D\n",
-                       mp->id, id1, id2,
-                       mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->dying, mp->helpgc,
-                       mp->spinning, g->m->blocked, id3);
-       }
-       runtime·lock(&runtime·allglock);
-       for(gi = 0; gi < runtime·allglen; gi++) {
-               gp = runtime·allg[gi];
-               mp = gp->m;
-               lockedm = gp->lockedm;
-               runtime·printf("  G%D: status=%d(%S) m=%d lockedm=%d\n",
-                       gp->goid, runtime·readgstatus(gp), gp->waitreason, mp ? mp->id : -1,
-                       lockedm ? lockedm->id : -1);
-       }
-       runtime·unlock(&runtime·allglock);
-       runtime·unlock(&runtime·sched.lock);
-}
-
-// 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++;
-}
-
-// Put a batch of runnable goroutines on the global runnable queue.
-// Sched must be locked.
-static void
-globrunqputbatch(G *ghead, G *gtail, int32 n)
-{
-       gtail->schedlink = nil;
-       if(runtime·sched.runqtail)
-               runtime·sched.runqtail->schedlink = ghead;
-       else
-               runtime·sched.runqhead = ghead;
-       runtime·sched.runqtail = gtail;
-       runtime·sched.runqsize += n;
-}
-
-// Try get a batch of G's from the global runnable queue.
-// Sched must be locked.
-static G*
-globrunqget(P *p, int32 max)
-{
-       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;
-       if(max > 0 && n > max)
-               n = max;
-       if(n > nelem(p->runq)/2)
-               n = nelem(p->runq)/2;
-       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;
-}
-
-// Try to put g on local runnable queue.
-// If it's full, put onto global queue.
-// Executed only by the owner P.
-static void
-runqput(P *p, G *gp)
-{
-       uint32 h, t;
-
-retry:
-       h = runtime·atomicload(&p->runqhead);  // load-acquire, synchronize with consumers
-       t = p->runqtail;
-       if(t - h < nelem(p->runq)) {
-               p->runq[t%nelem(p->runq)] = gp;
-               runtime·atomicstore(&p->runqtail, t+1);  // store-release, makes the item available for consumption
-               return;
-       }
-       if(runqputslow(p, gp, h, t))
-               return;
-       // the queue is not full, now the put above must suceed
-       goto retry;
-}
-
-// Put g and a batch of work from local runnable queue on global queue.
-// Executed only by the owner P.
-static bool
-runqputslow(P *p, G *gp, uint32 h, uint32 t)
-{
-       G *batch[nelem(p->runq)/2+1];
-       uint32 n, i;
-
-       // First, grab a batch from local queue.
-       n = t-h;
-       n = n/2;
-       if(n != nelem(p->runq)/2)
-               runtime·throw("runqputslow: queue is not full");
-       for(i=0; i<n; i++)
-               batch[i] = p->runq[(h+i)%nelem(p->runq)];
-       if(!runtime·cas(&p->runqhead, h, h+n))  // cas-release, commits consume
-               return false;
-       batch[n] = gp;
-       // Link the goroutines.
-       for(i=0; i<n; i++)
-               batch[i]->schedlink = batch[i+1];
-       // Now put the batch on global queue.
-       runtime·lock(&runtime·sched.lock);
-       globrunqputbatch(batch[0], batch[n], n+1);
-       runtime·unlock(&runtime·sched.lock);
-       return true;
-}
-
-// Get g from local runnable queue.
-// Executed only by the owner P.
-static G*
-runqget(P *p)
-{
-       G *gp;
-       uint32 t, h;
-
-       for(;;) {
-               h = runtime·atomicload(&p->runqhead);  // load-acquire, synchronize with other consumers
-               t = p->runqtail;
-               if(t == h)
-                       return nil;
-               gp = p->runq[h%nelem(p->runq)];
-               if(runtime·cas(&p->runqhead, h, h+1))  // cas-release, commits consume
-                       return gp;
-       }
-}
-
-// Grabs a batch of goroutines from local runnable queue.
-// batch array must be of size nelem(p->runq)/2. Returns number of grabbed goroutines.
-// Can be executed by any P.
-static uint32
-runqgrab(P *p, G **batch)
-{
-       uint32 t, h, n, i;
-
-       for(;;) {
-               h = runtime·atomicload(&p->runqhead);  // load-acquire, synchronize with other consumers
-               t = runtime·atomicload(&p->runqtail);  // load-acquire, synchronize with the producer
-               n = t-h;
-               n = n - n/2;
-               if(n == 0)
-                       break;
-               if(n > nelem(p->runq)/2)  // read inconsistent h and t
-                       continue;
-               for(i=0; i<n; i++)
-                       batch[i] = p->runq[(h+i)%nelem(p->runq)];
-               if(runtime·cas(&p->runqhead, h, h+n))  // cas-release, commits consume
-                       break;
-       }
-       return n;
-}
-
-// Steal half of elements from local runnable queue of p2
-// and put onto local runnable queue of p.
-// Returns one of the stolen elements (or nil if failed).
-static G*
-runqsteal(P *p, P *p2)
-{
-       G *gp;
-       G *batch[nelem(p->runq)/2];
-       uint32 t, h, n, i;
-
-       n = runqgrab(p2, batch);
-       if(n == 0)
-               return nil;
-       n--;
-       gp = batch[n];
-       if(n == 0)
-               return gp;
-       h = runtime·atomicload(&p->runqhead);  // load-acquire, synchronize with consumers
-       t = p->runqtail;
-       if(t - h + n >= nelem(p->runq))
-               runtime·throw("runqsteal: runq overflow");
-       for(i=0; i<n; i++, t++)
-               p->runq[t%nelem(p->runq)] = batch[i];
-       runtime·atomicstore(&p->runqtail, t);  // store-release, makes the item available for consumption
-       return gp;
-}
-
-void
-runtime·testSchedLocalQueue(void)
-{
-       P *p;
-       G *gs;
-       int32 i, j;
-
-       p = (P*)runtime·mallocgc(sizeof(*p), nil, FlagNoScan);
-       gs = (G*)runtime·mallocgc(nelem(p->runq)*sizeof(*gs), nil, FlagNoScan);
-
-       for(i = 0; i < nelem(p->runq); i++) {
-               if(runqget(p) != nil)
-                       runtime·throw("runq is not empty initially");
-               for(j = 0; j < i; j++)
-                       runqput(p, &gs[i]);
-               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");
-       }
-}
-
-void
-runtime·testSchedLocalQueueSteal(void)
-{
-       P *p1, *p2;
-       G *gs, *gp;
-       int32 i, j, s;
-
-       p1 = (P*)runtime·mallocgc(sizeof(*p1), nil, FlagNoScan);
-       p2 = (P*)runtime·mallocgc(sizeof(*p2), nil, FlagNoScan);
-       gs = (G*)runtime·mallocgc(nelem(p1->runq)*sizeof(*gs), nil, FlagNoScan);
-
-       for(i = 0; i < nelem(p1->runq); 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");
-               }
-       }
-}
-
-void
-runtime·setmaxthreads_m(void)
-{
-       int32 in;
-       int32 out;
-
-       in = g->m->scalararg[0];
-
-       runtime·lock(&runtime·sched.lock);
-       out = runtime·sched.maxmcount;
-       runtime·sched.maxmcount = in;
-       checkmcount();
-       runtime·unlock(&runtime·sched.lock);
-
-       g->m->scalararg[0] = out;
-}
-
-static int8 experiment[] = GOEXPERIMENT; // defined in zaexperiment.h
-
-static bool
-haveexperiment(int8 *name)
-{
-       int32 i, j;
-       
-       for(i=0; i<sizeof(experiment); i++) {
-               if((i == 0 || experiment[i-1] == ',') && experiment[i] == name[0]) {
-                       for(j=0; name[j]; j++)
-                               if(experiment[i+j] != name[j])
-                                       goto nomatch;
-                       if(experiment[i+j] != '\0' && experiment[i+j] != ',')
-                               goto nomatch;
-                       return 1;
-               }
-       nomatch:;
-       }
-       return 0;
-}
-
-#pragma textflag NOSPLIT
-void
-sync·runtime_procPin(intptr p)
-{
-       M *mp;
-
-       mp = g->m;
-       // Disable preemption.
-       mp->locks++;
-       p = mp->p->id;
-       FLUSH(&p);
-}
-
-#pragma textflag NOSPLIT
-void
-sync·runtime_procUnpin()
-{
-       g->m->locks--;
-}
index 517ca03df6497faed2bbeb6b49ef0de236edd46a..50920afe8bf68da83f5aaa67103615dc6138d5a1 100644 (file)
@@ -6,8 +6,6 @@ package runtime
 
 import "unsafe"
 
-func newsysmon()
-
 func runtime_init()
 func main_init()
 func main_main()
@@ -29,7 +27,7 @@ func main() {
                maxstacksize = 250000000
        }
 
-       onM(newsysmon)
+       systemstack(newsysmon)
 
        // Lock the main goroutine onto this, the main OS thread,
        // during initialization.  Most programs won't care, but a few
@@ -55,6 +53,24 @@ func main() {
 
        memstats.enablegc = true // now that runtime is initialized, GC is okay
 
+       if iscgo {
+               if _cgo_thread_start == nil {
+                       gothrow("_cgo_thread_start missing")
+               }
+               if _cgo_malloc == nil {
+                       gothrow("_cgo_malloc missing")
+               }
+               if _cgo_free == nil {
+                       gothrow("_cgo_free missing")
+               }
+               if _cgo_setenv == nil {
+                       gothrow("_cgo_setenv missing")
+               }
+               if _cgo_unsetenv == nil {
+                       gothrow("_cgo_unsetenv missing")
+               }
+       }
+
        main_init()
 
        needUnlock = false
@@ -80,8 +96,6 @@ func main() {
        }
 }
 
-var parkunlock_c byte
-
 // start forcegc helper goroutine
 func init() {
        go forcegchelper()
@@ -115,7 +129,7 @@ func Gosched() {
 
 // Puts the current goroutine into a waiting state and calls unlockf.
 // If unlockf returns false, the goroutine is resumed.
-func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
+func gopark(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
        mp := acquirem()
        gp := mp.curg
        status := readgstatus(gp)
@@ -123,7 +137,7 @@ func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
                gothrow("gopark: bad g status")
        }
        mp.waitlock = lock
-       mp.waitunlockf = unlockf
+       mp.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
        gp.waitreason = reason
        releasem(mp)
        // can't do anything that might move the G between Ms here.
@@ -133,14 +147,13 @@ func gopark(unlockf unsafe.Pointer, lock unsafe.Pointer, reason string) {
 // Puts the current goroutine into a waiting state and unlocks the lock.
 // The goroutine can be made runnable again by calling goready(gp).
 func goparkunlock(lock *mutex, reason string) {
-       gopark(unsafe.Pointer(&parkunlock_c), unsafe.Pointer(lock), reason)
+       gopark(parkunlock_c, unsafe.Pointer(lock), reason)
 }
 
 func goready(gp *g) {
-       mp := acquirem()
-       mp.ptrarg[0] = unsafe.Pointer(gp)
-       onM(ready_m)
-       releasem(mp)
+       systemstack(func() {
+               ready(gp)
+       })
 }
 
 //go:nosplit
@@ -233,6 +246,11 @@ func newG() *g {
        return new(g)
 }
 
+var (
+       allgs    []*g
+       allglock mutex
+)
+
 func allgadd(gp *g) {
        if readgstatus(gp) == _Gidle {
                gothrow("allgadd: bad status Gidle")
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go
new file mode 100644 (file)
index 0000000..81b211d
--- /dev/null
@@ -0,0 +1,3170 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+var (
+       m0 m
+       g0 g
+)
+
+// Goroutine scheduler
+// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
+//
+// The main concepts are:
+// G - goroutine.
+// M - worker thread, or machine.
+// P - processor, a resource that is required to execute Go code.
+//     M must have an associated P to execute Go code, however it can be
+//     blocked or in a syscall w/o an associated P.
+//
+// Design doc at http://golang.org/s/go11sched.
+
+const (
+       // Number of goroutine ids to grab from sched.goidgen to local per-P cache at once.
+       // 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
+       _GoidCacheBatch = 16
+)
+
+/*
+SchedT sched;
+int32  gomaxprocs;
+uint32 needextram;
+bool   iscgo;
+M      m0;
+G      g0;     // idle goroutine for m0
+G*     lastg;
+M*     allm;
+M*     extram;
+P*     allp[MaxGomaxprocs+1];
+int8*  goos;
+int32  ncpu;
+int32  newprocs;
+
+Mutex allglock;        // the following vars are protected by this lock or by stoptheworld
+G**    allg;
+Slice  allgs;
+uintptr allglen;
+ForceGCState   forcegc;
+
+void mstart(void);
+static void runqput(P*, G*);
+static G* runqget(P*);
+static bool runqputslow(P*, G*, uint32, uint32);
+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 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(int64);
+static void incidlelocked(int32);
+static void checkdead(void);
+static void exitsyscall0(G*);
+void park_m(G*);
+static void goexit0(G*);
+static void gfput(P*, G*);
+static G* gfget(P*);
+static void gfpurge(P*);
+static void globrunqput(G*);
+static void globrunqputbatch(G*, G*, int32);
+static G* globrunqget(P*, int32);
+static P* pidleget(void);
+static void pidleput(P*);
+static void injectglist(G*);
+static bool preemptall(void);
+static bool preemptone(P*);
+static bool exitsyscallfast(void);
+static bool haveexperiment(int8*);
+void allgadd(G*);
+static void dropg(void);
+
+extern String buildVersion;
+*/
+
+// The bootstrap sequence is:
+//
+//     call osinit
+//     call schedinit
+//     make & queue new G
+//     call runtime·mstart
+//
+// The new G calls runtime·main.
+func schedinit() {
+       // raceinit must be the first call to race detector.
+       // In particular, it must be done before mallocinit below calls racemapshadow.
+       _g_ := getg()
+       if raceenabled {
+               _g_.racectx = raceinit()
+       }
+
+       sched.maxmcount = 10000
+
+       tracebackinit()
+       symtabinit()
+       stackinit()
+       mallocinit()
+       mcommoninit(_g_.m)
+
+       goargs()
+       goenvs()
+       parsedebugvars()
+       gcinit()
+
+       sched.lastpoll = uint64(nanotime())
+       procs := 1
+       if n := goatoi(gogetenv("GOMAXPROCS")); n > 0 {
+               if n > _MaxGomaxprocs {
+                       n = _MaxGomaxprocs
+               }
+               procs = n
+       }
+       procresize(int32(procs))
+
+       if buildVersion == "" {
+               // Condition should never trigger.  This code just serves
+               // to ensure runtime·buildVersion is kept in the resulting binary.
+               buildVersion = "unknown"
+       }
+}
+
+func newsysmon() {
+       _newm(sysmon, nil)
+}
+
+func dumpgstatus(gp *g) {
+       _g_ := getg()
+       print("runtime: gp: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
+       print("runtime:  g:  g=", _g_, ", goid=", _g_.goid, ",  g->atomicstatus=", readgstatus(_g_), "\n")
+}
+
+func checkmcount() {
+       // sched lock is held
+       if sched.mcount > sched.maxmcount {
+               print("runtime: program exceeds ", sched.maxmcount, "-thread limit\n")
+               gothrow("thread exhaustion")
+       }
+}
+
+func mcommoninit(mp *m) {
+       _g_ := getg()
+
+       // g0 stack won't make sense for user (and is not necessary unwindable).
+       if _g_ != _g_.m.g0 {
+               callers(1, &mp.createstack[0], len(mp.createstack))
+       }
+
+       mp.fastrand = 0x49f6428a + uint32(mp.id) + uint32(cputicks())
+       if mp.fastrand == 0 {
+               mp.fastrand = 0x49f6428a
+       }
+
+       lock(&sched.lock)
+       mp.id = sched.mcount
+       sched.mcount++
+       checkmcount()
+       mpreinit(mp)
+       if mp.gsignal != nil {
+               mp.gsignal.stackguard1 = mp.gsignal.stack.lo + _StackGuard
+       }
+
+       // Add to allm so garbage collector doesn't free g->m
+       // when it is just in a register or thread-local storage.
+       mp.alllink = allm
+
+       // NumCgoCall() iterates over allm w/o schedlock,
+       // so we need to publish it safely.
+       atomicstorep(unsafe.Pointer(&allm), unsafe.Pointer(mp))
+       unlock(&sched.lock)
+}
+
+// Mark gp ready to run.
+func ready(gp *g) {
+       status := readgstatus(gp)
+
+       // Mark runnable.
+       _g_ := getg()
+       _g_.m.locks++ // disable preemption because it can be holding p in a local var
+       if status&^_Gscan != _Gwaiting {
+               dumpgstatus(gp)
+               gothrow("bad g->status in ready")
+       }
+
+       // status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
+       casgstatus(gp, _Gwaiting, _Grunnable)
+       runqput(_g_.m.p, gp)
+       if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 { // TODO: fast atomic
+               wakep()
+       }
+       _g_.m.locks--
+       if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+               _g_.stackguard0 = stackPreempt
+       }
+}
+
+func gcprocs() int32 {
+       // Figure out how many CPUs to use during GC.
+       // Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
+       lock(&sched.lock)
+       n := gomaxprocs
+       if n > ncpu {
+               n = ncpu
+       }
+       if n > _MaxGcproc {
+               n = _MaxGcproc
+       }
+       if n > sched.nmidle+1 { // one M is currently running
+               n = sched.nmidle + 1
+       }
+       unlock(&sched.lock)
+       return n
+}
+
+func needaddgcproc() bool {
+       lock(&sched.lock)
+       n := gomaxprocs
+       if n > ncpu {
+               n = ncpu
+       }
+       if n > _MaxGcproc {
+               n = _MaxGcproc
+       }
+       n -= sched.nmidle + 1 // one M is currently running
+       unlock(&sched.lock)
+       return n > 0
+}
+
+func helpgc(nproc int32) {
+       _g_ := getg()
+       lock(&sched.lock)
+       pos := 0
+       for n := int32(1); n < nproc; n++ { // one M is currently running
+               if allp[pos].mcache == _g_.m.mcache {
+                       pos++
+               }
+               mp := mget()
+               if mp == nil {
+                       gothrow("gcprocs inconsistency")
+               }
+               mp.helpgc = n
+               mp.mcache = allp[pos].mcache
+               pos++
+               notewakeup(&mp.park)
+       }
+       unlock(&sched.lock)
+}
+
+// Similar to stoptheworld but best-effort and can be called several times.
+// There is no reverse operation, used during crashing.
+// This function must not lock any mutexes.
+func freezetheworld() {
+       if gomaxprocs == 1 {
+               return
+       }
+       // stopwait and preemption requests can be lost
+       // due to races with concurrently executing threads,
+       // so try several times
+       for i := 0; i < 5; i++ {
+               // this should tell the scheduler to not start any new goroutines
+               sched.stopwait = 0x7fffffff
+               atomicstore(&sched.gcwaiting, 1)
+               // this should stop running goroutines
+               if !preemptall() {
+                       break // no running goroutines
+               }
+               usleep(1000)
+       }
+       // to be sure
+       usleep(1000)
+       preemptall()
+       usleep(1000)
+}
+
+func isscanstatus(status uint32) bool {
+       if status == _Gscan {
+               gothrow("isscanstatus: Bad status Gscan")
+       }
+       return status&_Gscan == _Gscan
+}
+
+// All reads and writes of g's status go through readgstatus, casgstatus
+// castogscanstatus, casfrom_Gscanstatus.
+//go:nosplit
+func readgstatus(gp *g) uint32 {
+       return atomicload(&gp.atomicstatus)
+}
+
+// The Gscanstatuses are acting like locks and this releases them.
+// If it proves to be a performance hit we should be able to make these
+// simple atomic stores but for now we are going to throw if
+// we see an inconsistent state.
+func casfrom_Gscanstatus(gp *g, oldval, newval uint32) {
+       success := false
+
+       // Check that transition is valid.
+       switch oldval {
+       case _Gscanrunnable,
+               _Gscanwaiting,
+               _Gscanrunning,
+               _Gscansyscall:
+               if newval == oldval&^_Gscan {
+                       success = cas(&gp.atomicstatus, oldval, newval)
+               }
+       case _Gscanenqueue:
+               if newval == _Gwaiting {
+                       success = cas(&gp.atomicstatus, oldval, newval)
+               }
+       }
+       if !success {
+               print("runtime: casfrom_Gscanstatus failed gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
+               dumpgstatus(gp)
+               gothrow("casfrom_Gscanstatus: gp->status is not in scan state")
+       }
+}
+
+// This will return false if the gp is not in the expected status and the cas fails.
+// This acts like a lock acquire while the casfromgstatus acts like a lock release.
+func castogscanstatus(gp *g, oldval, newval uint32) bool {
+       switch oldval {
+       case _Grunnable,
+               _Gwaiting,
+               _Gsyscall:
+               if newval == oldval|_Gscan {
+                       return cas(&gp.atomicstatus, oldval, newval)
+               }
+       case _Grunning:
+               if newval == _Gscanrunning || newval == _Gscanenqueue {
+                       return cas(&gp.atomicstatus, oldval, newval)
+               }
+       }
+       print("runtime: castogscanstatus oldval=", hex(oldval), " newval=", hex(newval), "\n")
+       gothrow("castogscanstatus")
+       panic("not reached")
+}
+
+// If asked to move to or from a Gscanstatus this will throw. Use the castogscanstatus
+// and casfrom_Gscanstatus instead.
+// casgstatus will loop if the g->atomicstatus is in a Gscan status until the routine that
+// put it in the Gscan state is finished.
+//go:nosplit
+func casgstatus(gp *g, oldval, newval uint32) {
+       if (oldval&_Gscan != 0) || (newval&_Gscan != 0) || oldval == newval {
+               systemstack(func() {
+                       print("casgstatus: oldval=", hex(oldval), " newval=", hex(newval), "\n")
+                       gothrow("casgstatus: bad incoming values")
+               })
+       }
+
+       // loop if gp->atomicstatus is in a scan state giving
+       // GC time to finish and change the state to oldval.
+       for !cas(&gp.atomicstatus, oldval, newval) {
+               // Help GC if needed.
+               if gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) {
+                       gp.preemptscan = false
+                       systemstack(func() {
+                               gcphasework(gp)
+                       })
+               }
+       }
+}
+
+// stopg ensures that gp is stopped at a GC safe point where its stack can be scanned
+// or in the context of a moving collector the pointers can be flipped from pointing
+// to old object to pointing to new objects.
+// If stopg returns true, the caller knows gp is at a GC safe point and will remain there until
+// the caller calls restartg.
+// If stopg returns false, the caller is not responsible for calling restartg. This can happen
+// if another thread, either the gp itself or another GC thread is taking the responsibility
+// to do the GC work related to this thread.
+func stopg(gp *g) bool {
+       for {
+               if gp.gcworkdone {
+                       return false
+               }
+
+               switch s := readgstatus(gp); s {
+               default:
+                       dumpgstatus(gp)
+                       gothrow("stopg: gp->atomicstatus is not valid")
+
+               case _Gdead:
+                       return false
+
+               case _Gcopystack:
+                       // Loop until a new stack is in place.
+
+               case _Grunnable,
+                       _Gsyscall,
+                       _Gwaiting:
+                       // Claim goroutine by setting scan bit.
+                       if !castogscanstatus(gp, s, s|_Gscan) {
+                               break
+                       }
+                       // In scan state, do work.
+                       gcphasework(gp)
+                       return true
+
+               case _Gscanrunnable,
+                       _Gscanwaiting,
+                       _Gscansyscall:
+                       // Goroutine already claimed by another GC helper.
+                       return false
+
+               case _Grunning:
+                       // Claim goroutine, so we aren't racing with a status
+                       // transition away from Grunning.
+                       if !castogscanstatus(gp, _Grunning, _Gscanrunning) {
+                               break
+                       }
+
+                       // Mark gp for preemption.
+                       if !gp.gcworkdone {
+                               gp.preemptscan = true
+                               gp.preempt = true
+                               gp.stackguard0 = stackPreempt
+                       }
+
+                       // Unclaim.
+                       casfrom_Gscanstatus(gp, _Gscanrunning, _Grunning)
+                       return false
+               }
+       }
+}
+
+// The GC requests that this routine be moved from a scanmumble state to a mumble state.
+func restartg(gp *g) {
+       s := readgstatus(gp)
+       switch s {
+       default:
+               dumpgstatus(gp)
+               gothrow("restartg: unexpected status")
+
+       case _Gdead:
+               // ok
+
+       case _Gscanrunnable,
+               _Gscanwaiting,
+               _Gscansyscall:
+               casfrom_Gscanstatus(gp, s, s&^_Gscan)
+
+       // Scan is now completed.
+       // Goroutine now needs to be made runnable.
+       // We put it on the global run queue; ready blocks on the global scheduler lock.
+       case _Gscanenqueue:
+               casfrom_Gscanstatus(gp, _Gscanenqueue, _Gwaiting)
+               if gp != getg().m.curg {
+                       gothrow("processing Gscanenqueue on wrong m")
+               }
+               dropg()
+               ready(gp)
+       }
+}
+
+func stopscanstart(gp *g) {
+       _g_ := getg()
+       if _g_ == gp {
+               gothrow("GC not moved to G0")
+       }
+       if stopg(gp) {
+               if !isscanstatus(readgstatus(gp)) {
+                       dumpgstatus(gp)
+                       gothrow("GC not in scan state")
+               }
+               restartg(gp)
+       }
+}
+
+// Runs on g0 and does the actual work after putting the g back on the run queue.
+func mquiesce(gpmaster *g) {
+       activeglen := len(allgs)
+       // enqueue the calling goroutine.
+       restartg(gpmaster)
+       for i := 0; i < activeglen; i++ {
+               gp := allgs[i]
+               if readgstatus(gp) == _Gdead {
+                       gp.gcworkdone = true // noop scan.
+               } else {
+                       gp.gcworkdone = false
+               }
+               stopscanstart(gp)
+       }
+
+       // Check that the G's gcwork (such as scanning) has been done. If not do it now.
+       // You can end up doing work here if the page trap on a Grunning Goroutine has
+       // not been sprung or in some race situations. For example a runnable goes dead
+       // and is started up again with a gp->gcworkdone set to false.
+       for i := 0; i < activeglen; i++ {
+               gp := allgs[i]
+               for !gp.gcworkdone {
+                       status := readgstatus(gp)
+                       if status == _Gdead {
+                               //do nothing, scan not needed.
+                               gp.gcworkdone = true // scan is a noop
+                               break
+                       }
+                       if status == _Grunning && gp.stackguard0 == uintptr(stackPreempt) && notetsleep(&sched.stopnote, 100*1000) { // nanosecond arg
+                               noteclear(&sched.stopnote)
+                       } else {
+                               stopscanstart(gp)
+                       }
+               }
+       }
+
+       for i := 0; i < activeglen; i++ {
+               gp := allgs[i]
+               status := readgstatus(gp)
+               if isscanstatus(status) {
+                       print("mstopandscang:bottom: post scan bad status gp=", gp, " has status ", hex(status), "\n")
+                       dumpgstatus(gp)
+               }
+               if !gp.gcworkdone && status != _Gdead {
+                       print("mstopandscang:bottom: post scan gp=", gp, "->gcworkdone still false\n")
+                       dumpgstatus(gp)
+               }
+       }
+
+       schedule() // Never returns.
+}
+
+// quiesce moves all the goroutines to a GC safepoint which for now is a at preemption point.
+// If the global gcphase is GCmark quiesce will ensure that all of the goroutine's stacks
+// have been scanned before it returns.
+func quiesce(mastergp *g) {
+       castogscanstatus(mastergp, _Grunning, _Gscanenqueue)
+       // Now move this to the g0 (aka m) stack.
+       // g0 will potentially scan this thread and put mastergp on the runqueue
+       mcall(mquiesce)
+}
+
+// This is used by the GC as well as the routines that do stack dumps. In the case
+// of GC all the routines can be reliably stopped. This is not always the case
+// when the system is in panic or being exited.
+func stoptheworld() {
+       _g_ := getg()
+
+       // If we hold a lock, then we won't be able to stop another M
+       // that is blocked trying to acquire the lock.
+       if _g_.m.locks > 0 {
+               gothrow("stoptheworld: holding locks")
+       }
+
+       lock(&sched.lock)
+       sched.stopwait = gomaxprocs
+       atomicstore(&sched.gcwaiting, 1)
+       preemptall()
+       // stop current P
+       _g_.m.p.status = _Pgcstop // Pgcstop is only diagnostic.
+       sched.stopwait--
+       // try to retake all P's in Psyscall status
+       for i := 0; i < int(gomaxprocs); i++ {
+               p := allp[i]
+               s := p.status
+               if s == _Psyscall && cas(&p.status, s, _Pgcstop) {
+                       sched.stopwait--
+               }
+       }
+       // stop idle P's
+       for {
+               p := pidleget()
+               if p == nil {
+                       break
+               }
+               p.status = _Pgcstop
+               sched.stopwait--
+       }
+       wait := sched.stopwait > 0
+       unlock(&sched.lock)
+
+       // wait for remaining P's to stop voluntarily
+       if wait {
+               for {
+                       // wait for 100us, then try to re-preempt in case of any races
+                       if notetsleep(&sched.stopnote, 100*1000) {
+                               noteclear(&sched.stopnote)
+                               break
+                       }
+                       preemptall()
+               }
+       }
+       if sched.stopwait != 0 {
+               gothrow("stoptheworld: not stopped")
+       }
+       for i := 0; i < int(gomaxprocs); i++ {
+               p := allp[i]
+               if p.status != _Pgcstop {
+                       gothrow("stoptheworld: not stopped")
+               }
+       }
+}
+
+func mhelpgc() {
+       _g_ := getg()
+       _g_.m.helpgc = -1
+}
+
+func starttheworld() {
+       _g_ := getg()
+
+       _g_.m.locks++        // disable preemption because it can be holding p in a local var
+       gp := netpoll(false) // non-blocking
+       injectglist(gp)
+       add := needaddgcproc()
+       lock(&sched.lock)
+       if newprocs != 0 {
+               procresize(newprocs)
+               newprocs = 0
+       } else {
+               procresize(gomaxprocs)
+       }
+       sched.gcwaiting = 0
+
+       var p1 *p
+       for {
+               p := pidleget()
+               if p == nil {
+                       break
+               }
+               // 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
+               }
+               p.m = mget()
+               p.link = p1
+               p1 = p
+       }
+       if sched.sysmonwait != 0 {
+               sched.sysmonwait = 0
+               notewakeup(&sched.sysmonnote)
+       }
+       unlock(&sched.lock)
+
+       for p1 != nil {
+               p := p1
+               p1 = p1.link
+               if p.m != nil {
+                       mp := p.m
+                       p.m = nil
+                       if mp.nextp != nil {
+                               gothrow("starttheworld: inconsistent mp->nextp")
+                       }
+                       mp.nextp = p
+                       notewakeup(&mp.park)
+               } else {
+                       // Start M to run P.  Do not start another M below.
+                       _newm(nil, p)
+                       add = false
+               }
+       }
+
+       if add {
+               // If GC could have used another helper proc, start one now,
+               // in the hope that it will be available next time.
+               // It would have been even better to start it before the collection,
+               // but doing so requires allocating memory, so it's tricky to
+               // coordinate.  This lazy approach works out in practice:
+               // we don't mind if the first couple gc rounds don't have quite
+               // the maximum number of procs.
+               _newm(mhelpgc, nil)
+       }
+       _g_.m.locks--
+       if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+               _g_.stackguard0 = stackPreempt
+       }
+}
+
+// Called to start an M.
+//go:nosplit
+func mstart() {
+       _g_ := getg()
+
+       if _g_.stack.lo == 0 {
+               // Initialize stack bounds from system stack.
+               // Cgo may have left stack size in stack.hi.
+               size := _g_.stack.hi
+               if size == 0 {
+                       size = 8192
+               }
+               _g_.stack.hi = uintptr(noescape(unsafe.Pointer(&size)))
+               _g_.stack.lo = _g_.stack.hi - size + 1024
+       }
+       // Initialize stack guards so that we can start calling
+       // both Go and C functions with stack growth prologues.
+       _g_.stackguard0 = _g_.stack.lo + _StackGuard
+       _g_.stackguard1 = _g_.stackguard0
+       mstart1()
+}
+
+func mstart1() {
+       _g_ := getg()
+
+       if _g_ != _g_.m.g0 {
+               gothrow("bad runtime·mstart")
+       }
+
+       // Record top of stack for use by mcall.
+       // Once we call schedule we're never coming back,
+       // so other calls can reuse this stack space.
+       gosave(&_g_.m.g0.sched)
+       _g_.m.g0.sched.pc = ^uintptr(0) // make sure it is never used
+       asminit()
+       minit()
+
+       // Install signal handlers; after minit so that minit can
+       // prepare the thread to be able to handle the signals.
+       if _g_.m == &m0 {
+               initsig()
+       }
+
+       if _g_.m.mstartfn != nil {
+               fn := *(*func())(unsafe.Pointer(&_g_.m.mstartfn))
+               fn()
+       }
+
+       if _g_.m.helpgc != 0 {
+               _g_.m.helpgc = 0
+               stopm()
+       } else if _g_.m != &m0 {
+               acquirep(_g_.m.nextp)
+               _g_.m.nextp = nil
+       }
+       schedule()
+
+       // 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.
+}
+
+// When running with cgo, we call _cgo_thread_start
+// to start threads for us so that we can play nicely with
+// foreign code.
+var cgoThreadStart unsafe.Pointer
+
+type cgothreadstart struct {
+       g   *g
+       tls *uint64
+       fn  unsafe.Pointer
+}
+
+// Allocate a new m unassociated with any thread.
+// Can use p for allocation context if needed.
+func allocm(_p_ *p) *m {
+       _g_ := getg()
+       _g_.m.locks++ // disable GC because it can be called from sysmon
+       if _g_.m.p == nil {
+               acquirep(_p_) // temporarily borrow p for mallocs in this function
+       }
+       mp := newM()
+       mcommoninit(mp)
+
+       // In case of cgo or Solaris, pthread_create will make us a stack.
+       // Windows and Plan 9 will layout sched stack on OS stack.
+       if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" {
+               mp.g0 = malg(-1)
+       } else {
+               mp.g0 = malg(8192)
+       }
+       mp.g0.m = mp
+
+       if _p_ == _g_.m.p {
+               releasep()
+       }
+       _g_.m.locks--
+       if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+               _g_.stackguard0 = stackPreempt
+       }
+
+       return mp
+}
+
+func allocg() *g {
+       return newG()
+}
+
+// needm is called when a cgo callback happens on a
+// thread without an m (a thread not created by Go).
+// In this case, needm is expected to find an m to use
+// and return with m, g initialized correctly.
+// Since m and g are not set now (likely nil, but see below)
+// needm is limited in what routines it can call. In particular
+// it can only call nosplit functions (textflag 7) and cannot
+// do any scheduling that requires an m.
+//
+// In order to avoid needing heavy lifting here, we adopt
+// the following strategy: there is a stack of available m's
+// that can be stolen. Using compare-and-swap
+// to pop from the stack has ABA races, so we simulate
+// a lock by doing an exchange (via casp) to steal the stack
+// head and replace the top pointer with MLOCKED (1).
+// This serves as a simple spin lock that we can use even
+// without an m. The thread that locks the stack in this way
+// unlocks the stack by storing a valid stack head pointer.
+//
+// In order to make sure that there is always an m structure
+// available to be stolen, we maintain the invariant that there
+// is always one more than needed. At the beginning of the
+// program (if cgo is in use) the list is seeded with a single m.
+// If needm finds that it has taken the last m off the list, its job
+// is - once it has installed its own m so that it can do things like
+// allocate memory - to create a spare m and put it on the list.
+//
+// Each of these extra m's also has a g0 and a curg that are
+// pressed into service as the scheduling stack and current
+// goroutine for the duration of the cgo callback.
+//
+// When the callback is done with the m, it calls dropm to
+// put the m back on the list.
+//go:nosplit
+func needm(x byte) {
+       if needextram != 0 {
+               // Can happen if C/C++ code calls Go from a global ctor.
+               // Can not throw, because scheduler is not initialized yet.
+               // XXX
+               // write(2, unsafe.Pointer("fatal error: cgo callback before cgo call\n"), sizeof("fatal error: cgo callback before cgo call\n") - 1)
+               exit(1)
+       }
+
+       // Lock extra list, take head, unlock popped list.
+       // nilokay=false is safe here because of the invariant above,
+       // that the extra list always contains or will soon contain
+       // at least one m.
+       mp := lockextra(false)
+
+       // Set needextram when we've just emptied the list,
+       // so that the eventual call into cgocallbackg will
+       // allocate a new m for the extra list. We delay the
+       // allocation until then so that it can be done
+       // after exitsyscall makes sure it is okay to be
+       // running at all (that is, there's no garbage collection
+       // running right now).
+       mp.needextram = mp.schedlink == nil
+       unlockextra(mp.schedlink)
+
+       // Install g (= m->g0) and set the stack bounds
+       // to match the current stack. We don't actually know
+       // how big the stack is, like we don't know how big any
+       // scheduling stack is, but we assume there's at least 32 kB,
+       // which is more than enough for us.
+       setg(mp.g0)
+       _g_ := getg()
+       _g_.stack.hi = uintptr(noescape(unsafe.Pointer(&x))) + 1024
+       _g_.stack.lo = uintptr(noescape(unsafe.Pointer(&x))) - 32*1024
+       _g_.stackguard0 = _g_.stack.lo + _StackGuard
+
+       // Initialize this thread to use the m.
+       asminit()
+       minit()
+}
+
+// newextram allocates an m and puts it on the extra list.
+// It is called with a working local m, so that it can do things
+// like call schedlock and allocate.
+func newextram() {
+       // Create extra goroutine locked to extra m.
+       // The goroutine is the context in which the cgo callback will run.
+       // The sched.pc will never be returned to, but setting it to
+       // goexit makes clear to the traceback routines where
+       // the goroutine stack ends.
+       mp := allocm(nil)
+       gp := malg(4096)
+       gp.sched.pc = funcPC(goexit) + _PCQuantum
+       gp.sched.sp = gp.stack.hi
+       gp.sched.sp -= 4 * regSize // extra space in case of reads slightly beyond frame
+       gp.sched.lr = 0
+       gp.sched.g = gp
+       gp.syscallpc = gp.sched.pc
+       gp.syscallsp = gp.sched.sp
+       // malg returns status as Gidle, change to Gsyscall before adding to allg
+       // where GC will see it.
+       casgstatus(gp, _Gidle, _Gsyscall)
+       gp.m = mp
+       mp.curg = gp
+       mp.locked = _LockInternal
+       mp.lockedg = gp
+       gp.lockedm = mp
+       gp.goid = int64(xadd64(&sched.goidgen, 1))
+       if raceenabled {
+               gp.racectx = racegostart(funcPC(newextram))
+       }
+       // put on allg for garbage collector
+       allgadd(gp)
+
+       // Add m to the extra list.
+       mnext := lockextra(true)
+       mp.schedlink = mnext
+       unlockextra(mp)
+}
+
+// dropm is called when a cgo callback has called needm but is now
+// done with the callback and returning back into the non-Go thread.
+// It puts the current m back onto the extra list.
+//
+// The main expense here is the call to signalstack to release the
+// m's signal stack, and then the call to needm on the next callback
+// from this thread. It is tempting to try to save the m for next time,
+// which would eliminate both these costs, but there might not be
+// a next time: the current thread (which Go does not control) might exit.
+// If we saved the m for that thread, there would be an m leak each time
+// such a thread exited. Instead, we acquire and release an m on each
+// call. These should typically not be scheduling operations, just a few
+// atomics, so the cost should be small.
+//
+// TODO(rsc): An alternative would be to allocate a dummy pthread per-thread
+// variable using pthread_key_create. Unlike the pthread keys we already use
+// on OS X, this dummy key would never be read by Go code. It would exist
+// only so that we could register at thread-exit-time destructor.
+// That destructor would put the m back onto the extra list.
+// This is purely a performance optimization. The current version,
+// in which dropm happens on each cgo call, is still correct too.
+// We may have to keep the current version on systems with cgo
+// but without pthreads, like Windows.
+func dropm() {
+       // Undo whatever initialization minit did during needm.
+       unminit()
+
+       // Clear m and g, and return m to the extra list.
+       // After the call to setmg we can only call nosplit functions.
+       mp := getg().m
+       setg(nil)
+
+       mnext := lockextra(true)
+       mp.schedlink = mnext
+       unlockextra(mp)
+}
+
+var extram uintptr
+
+// lockextra locks the extra list and returns the list head.
+// The caller must unlock the list by storing a new list head
+// to extram. If nilokay is true, then lockextra will
+// return a nil list head if that's what it finds. If nilokay is false,
+// lockextra will keep waiting until the list head is no longer nil.
+//go:nosplit
+func lockextra(nilokay bool) *m {
+       const locked = 1
+
+       for {
+               old := atomicloaduintptr(&extram)
+               if old == locked {
+                       yield := osyield
+                       yield()
+                       continue
+               }
+               if old == 0 && !nilokay {
+                       usleep(1)
+                       continue
+               }
+               if casuintptr(&extram, old, locked) {
+                       return (*m)(unsafe.Pointer(old))
+               }
+               yield := osyield
+               yield()
+               continue
+       }
+}
+
+//go:nosplit
+func unlockextra(mp *m) {
+       atomicstoreuintptr(&extram, uintptr(unsafe.Pointer(mp)))
+}
+
+// Create a new m.  It will start off with a call to fn, or else the scheduler.
+func _newm(fn func(), _p_ *p) {
+       mp := allocm(_p_)
+       mp.nextp = _p_
+       mp.mstartfn = *(*unsafe.Pointer)(unsafe.Pointer(&fn))
+
+       if iscgo {
+               var ts cgothreadstart
+               if _cgo_thread_start == nil {
+                       gothrow("_cgo_thread_start missing")
+               }
+               ts.g = mp.g0
+               ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0]))
+               ts.fn = unsafe.Pointer(funcPC(mstart))
+               asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
+               return
+       }
+       newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
+}
+
+// Stops execution of the current m until new work is available.
+// Returns with acquired P.
+func stopm() {
+       _g_ := getg()
+
+       if _g_.m.locks != 0 {
+               gothrow("stopm holding locks")
+       }
+       if _g_.m.p != nil {
+               gothrow("stopm holding p")
+       }
+       if _g_.m.spinning {
+               _g_.m.spinning = false
+               xadd(&sched.nmspinning, -1)
+       }
+
+retry:
+       lock(&sched.lock)
+       mput(_g_.m)
+       unlock(&sched.lock)
+       notesleep(&_g_.m.park)
+       noteclear(&_g_.m.park)
+       if _g_.m.helpgc != 0 {
+               gchelper()
+               _g_.m.helpgc = 0
+               _g_.m.mcache = nil
+               goto retry
+       }
+       acquirep(_g_.m.nextp)
+       _g_.m.nextp = nil
+}
+
+func mspinning() {
+       getg().m.spinning = true
+}
+
+// Schedules some M to run the p (creates an M if necessary).
+// If p==nil, tries to get an idle P, if no idle P's does nothing.
+func startm(_p_ *p, spinning bool) {
+       lock(&sched.lock)
+       if _p_ == nil {
+               _p_ = pidleget()
+               if _p_ == nil {
+                       unlock(&sched.lock)
+                       if spinning {
+                               xadd(&sched.nmspinning, -1)
+                       }
+                       return
+               }
+       }
+       mp := mget()
+       unlock(&sched.lock)
+       if mp == nil {
+               var fn func()
+               if spinning {
+                       fn = mspinning
+               }
+               _newm(fn, _p_)
+               return
+       }
+       if mp.spinning {
+               gothrow("startm: m is spinning")
+       }
+       if mp.nextp != nil {
+               gothrow("startm: m has p")
+       }
+       mp.spinning = spinning
+       mp.nextp = _p_
+       notewakeup(&mp.park)
+}
+
+// Hands off P from syscall or locked M.
+func handoffp(_p_ *p) {
+       // if it has local work, start it straight away
+       if _p_.runqhead != _p_.runqtail || sched.runqsize != 0 {
+               startm(_p_, false)
+               return
+       }
+       // no local work, check that there are no spinning/idle M's,
+       // otherwise our help is not required
+       if atomicload(&sched.nmspinning)+atomicload(&sched.npidle) == 0 && cas(&sched.nmspinning, 0, 1) { // TODO: fast atomic
+               startm(_p_, true)
+               return
+       }
+       lock(&sched.lock)
+       if sched.gcwaiting != 0 {
+               _p_.status = _Pgcstop
+               sched.stopwait--
+               if sched.stopwait == 0 {
+                       notewakeup(&sched.stopnote)
+               }
+               unlock(&sched.lock)
+               return
+       }
+       if sched.runqsize != 0 {
+               unlock(&sched.lock)
+               startm(_p_, false)
+               return
+       }
+       // If this is the last running P and nobody is polling network,
+       // need to wakeup another M to poll network.
+       if sched.npidle == uint32(gomaxprocs-1) && atomicload64(&sched.lastpoll) != 0 {
+               unlock(&sched.lock)
+               startm(_p_, false)
+               return
+       }
+       pidleput(_p_)
+       unlock(&sched.lock)
+}
+
+// Tries to add one more P to execute G's.
+// Called when a G is made runnable (newproc, ready).
+func wakep() {
+       // be conservative about spinning threads
+       if !cas(&sched.nmspinning, 0, 1) {
+               return
+       }
+       startm(nil, true)
+}
+
+// Stops execution of the current m that is locked to a g until the g is runnable again.
+// Returns with acquired P.
+func stoplockedm() {
+       _g_ := getg()
+
+       if _g_.m.lockedg == nil || _g_.m.lockedg.lockedm != _g_.m {
+               gothrow("stoplockedm: inconsistent locking")
+       }
+       if _g_.m.p != nil {
+               // Schedule another M to run this p.
+               _p_ := releasep()
+               handoffp(_p_)
+       }
+       incidlelocked(1)
+       // Wait until another thread schedules lockedg again.
+       notesleep(&_g_.m.park)
+       noteclear(&_g_.m.park)
+       status := readgstatus(_g_.m.lockedg)
+       if status&^_Gscan != _Grunnable {
+               print("runtime:stoplockedm: g is not Grunnable or Gscanrunnable\n")
+               dumpgstatus(_g_)
+               gothrow("stoplockedm: not runnable")
+       }
+       acquirep(_g_.m.nextp)
+       _g_.m.nextp = nil
+}
+
+// Schedules the locked m to run the locked gp.
+func startlockedm(gp *g) {
+       _g_ := getg()
+
+       mp := gp.lockedm
+       if mp == _g_.m {
+               gothrow("startlockedm: locked to me")
+       }
+       if mp.nextp != nil {
+               gothrow("startlockedm: m has p")
+       }
+       // directly handoff current P to the locked m
+       incidlelocked(-1)
+       _p_ := releasep()
+       mp.nextp = _p_
+       notewakeup(&mp.park)
+       stopm()
+}
+
+// Stops the current m for stoptheworld.
+// Returns when the world is restarted.
+func gcstopm() {
+       _g_ := getg()
+
+       if sched.gcwaiting == 0 {
+               gothrow("gcstopm: not waiting for gc")
+       }
+       if _g_.m.spinning {
+               _g_.m.spinning = false
+               xadd(&sched.nmspinning, -1)
+       }
+       _p_ := releasep()
+       lock(&sched.lock)
+       _p_.status = _Pgcstop
+       sched.stopwait--
+       if sched.stopwait == 0 {
+               notewakeup(&sched.stopnote)
+       }
+       unlock(&sched.lock)
+       stopm()
+}
+
+// Schedules gp to run on the current M.
+// Never returns.
+func execute(gp *g) {
+       _g_ := getg()
+
+       casgstatus(gp, _Grunnable, _Grunning)
+       gp.waitsince = 0
+       gp.preempt = false
+       gp.stackguard0 = gp.stack.lo + _StackGuard
+       _g_.m.p.schedtick++
+       _g_.m.curg = gp
+       gp.m = _g_.m
+
+       // Check whether the profiler needs to be turned on or off.
+       hz := sched.profilehz
+       if _g_.m.profilehz != hz {
+               resetcpuprofiler(hz)
+       }
+
+       gogo(&gp.sched)
+}
+
+// Finds a runnable goroutine to execute.
+// Tries to steal from other P's, get g from global queue, poll network.
+func findrunnable() *g {
+       _g_ := getg()
+
+top:
+       if sched.gcwaiting != 0 {
+               gcstopm()
+               goto top
+       }
+       if fingwait && fingwake {
+               if gp := wakefing(); gp != nil {
+                       ready(gp)
+               }
+       }
+
+       // local runq
+       if gp := runqget(_g_.m.p); gp != nil {
+               return gp
+       }
+
+       // global runq
+       if sched.runqsize != 0 {
+               lock(&sched.lock)
+               gp := globrunqget(_g_.m.p, 0)
+               unlock(&sched.lock)
+               if gp != nil {
+                       return gp
+               }
+       }
+
+       // poll network - returns list of goroutines
+       if gp := netpoll(false); gp != nil { // non-blocking
+               injectglist(gp.schedlink)
+               casgstatus(gp, _Gwaiting, _Grunnable)
+               return gp
+       }
+
+       // If number of spinning M's >= number of busy P's, block.
+       // This is necessary to prevent excessive CPU consumption
+       // when GOMAXPROCS>>1 but the program parallelism is low.
+       if !_g_.m.spinning && 2*atomicload(&sched.nmspinning) >= uint32(gomaxprocs)-atomicload(&sched.npidle) { // TODO: fast atomic
+               goto stop
+       }
+       if !_g_.m.spinning {
+               _g_.m.spinning = true
+               xadd(&sched.nmspinning, 1)
+       }
+       // random steal from other P's
+       for i := 0; i < int(2*gomaxprocs); i++ {
+               if sched.gcwaiting != 0 {
+                       goto top
+               }
+               _p_ := allp[fastrand1()%uint32(gomaxprocs)]
+               var gp *g
+               if _p_ == _g_.m.p {
+                       gp = runqget(_p_)
+               } else {
+                       gp = runqsteal(_g_.m.p, _p_)
+               }
+               if gp != nil {
+                       return gp
+               }
+       }
+stop:
+
+       // return P and block
+       lock(&sched.lock)
+       if sched.gcwaiting != 0 {
+               unlock(&sched.lock)
+               goto top
+       }
+       if sched.runqsize != 0 {
+               gp := globrunqget(_g_.m.p, 0)
+               unlock(&sched.lock)
+               return gp
+       }
+       _p_ := releasep()
+       pidleput(_p_)
+       unlock(&sched.lock)
+       if _g_.m.spinning {
+               _g_.m.spinning = false
+               xadd(&sched.nmspinning, -1)
+       }
+
+       // check all runqueues once again
+       for i := 0; i < int(gomaxprocs); i++ {
+               _p_ := allp[i]
+               if _p_ != nil && _p_.runqhead != _p_.runqtail {
+                       lock(&sched.lock)
+                       _p_ = pidleget()
+                       unlock(&sched.lock)
+                       if _p_ != nil {
+                               acquirep(_p_)
+                               goto top
+                       }
+                       break
+               }
+       }
+
+       // poll network
+       if xchg64(&sched.lastpoll, 0) != 0 {
+               if _g_.m.p != nil {
+                       gothrow("findrunnable: netpoll with p")
+               }
+               if _g_.m.spinning {
+                       gothrow("findrunnable: netpoll with spinning")
+               }
+               gp := netpoll(true) // block until new work is available
+               atomicstore64(&sched.lastpoll, uint64(nanotime()))
+               if gp != nil {
+                       lock(&sched.lock)
+                       _p_ = pidleget()
+                       unlock(&sched.lock)
+                       if _p_ != nil {
+                               acquirep(_p_)
+                               injectglist(gp.schedlink)
+                               casgstatus(gp, _Gwaiting, _Grunnable)
+                               return gp
+                       }
+                       injectglist(gp)
+               }
+       }
+       stopm()
+       goto top
+}
+
+func resetspinning() {
+       _g_ := getg()
+
+       var nmspinning uint32
+       if _g_.m.spinning {
+               _g_.m.spinning = false
+               nmspinning = xadd(&sched.nmspinning, -1)
+               if nmspinning < 0 {
+                       gothrow("findrunnable: negative nmspinning")
+               }
+       } else {
+               nmspinning = atomicload(&sched.nmspinning)
+       }
+
+       // M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
+       // so see if we need to wakeup another P here.
+       if nmspinning == 0 && atomicload(&sched.npidle) > 0 {
+               wakep()
+       }
+}
+
+// Injects the list of runnable G's into the scheduler.
+// Can run concurrently with GC.
+func injectglist(glist *g) {
+       if glist == nil {
+               return
+       }
+       lock(&sched.lock)
+       var n int
+       for n = 0; glist != nil; n++ {
+               gp := glist
+               glist = gp.schedlink
+               casgstatus(gp, _Gwaiting, _Grunnable)
+               globrunqput(gp)
+       }
+       unlock(&sched.lock)
+       for ; n != 0 && sched.npidle != 0; n-- {
+               startm(nil, false)
+       }
+}
+
+// One round of scheduler: find a runnable goroutine and execute it.
+// Never returns.
+func schedule() {
+       _g_ := getg()
+
+       if _g_.m.locks != 0 {
+               gothrow("schedule: holding locks")
+       }
+
+       if _g_.m.lockedg != nil {
+               stoplockedm()
+               execute(_g_.m.lockedg) // Never returns.
+       }
+
+top:
+       if sched.gcwaiting != 0 {
+               gcstopm()
+               goto top
+       }
+
+       var gp *g
+       // Check the global runnable queue once in a while to ensure fairness.
+       // Otherwise two goroutines can completely occupy the local runqueue
+       // by constantly respawning each other.
+       tick := _g_.m.p.schedtick
+       // This is a fancy way to say tick%61==0,
+       // it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
+       if uint64(tick)-((uint64(tick)*0x4325c53f)>>36)*61 == 0 && sched.runqsize > 0 {
+               lock(&sched.lock)
+               gp = globrunqget(_g_.m.p, 1)
+               unlock(&sched.lock)
+               if gp != nil {
+                       resetspinning()
+               }
+       }
+       if gp == nil {
+               gp = runqget(_g_.m.p)
+               if gp != nil && _g_.m.spinning {
+                       gothrow("schedule: spinning with local work")
+               }
+       }
+       if gp == nil {
+               gp = findrunnable() // blocks until work is available
+               resetspinning()
+       }
+
+       if gp.lockedm != nil {
+               // Hands off own p to the locked m,
+               // then blocks waiting for a new p.
+               startlockedm(gp)
+               goto top
+       }
+
+       execute(gp)
+}
+
+// dropg removes the association between m and the current goroutine m->curg (gp for short).
+// Typically a caller sets gp's status away from Grunning and then
+// immediately calls dropg to finish the job. The caller is also responsible
+// for arranging that gp will be restarted using ready at an
+// appropriate time. After calling dropg and arranging for gp to be
+// readied later, the caller can do other work but eventually should
+// call schedule to restart the scheduling of goroutines on this m.
+func dropg() {
+       _g_ := getg()
+
+       if _g_.m.lockedg == nil {
+               _g_.m.curg.m = nil
+               _g_.m.curg = nil
+       }
+}
+
+// Puts the current goroutine into a waiting state and calls unlockf.
+// If unlockf returns false, the goroutine is resumed.
+func park(unlockf func(*g, unsafe.Pointer) bool, lock unsafe.Pointer, reason string) {
+       _g_ := getg()
+
+       _g_.m.waitlock = lock
+       _g_.m.waitunlockf = *(*unsafe.Pointer)(unsafe.Pointer(&unlockf))
+       _g_.waitreason = reason
+       mcall(park_m)
+}
+
+func parkunlock_c(gp *g, lock unsafe.Pointer) bool {
+       unlock((*mutex)(lock))
+       return true
+}
+
+// Puts the current goroutine into a waiting state and unlocks the lock.
+// The goroutine can be made runnable again by calling ready(gp).
+func parkunlock(lock *mutex, reason string) {
+       park(parkunlock_c, unsafe.Pointer(lock), reason)
+}
+
+// park continuation on g0.
+func park_m(gp *g) {
+       _g_ := getg()
+
+       casgstatus(gp, _Grunning, _Gwaiting)
+       dropg()
+
+       if _g_.m.waitunlockf != nil {
+               fn := *(*func(*g, unsafe.Pointer) bool)(unsafe.Pointer(&_g_.m.waitunlockf))
+               ok := fn(gp, _g_.m.waitlock)
+               _g_.m.waitunlockf = nil
+               _g_.m.waitlock = nil
+               if !ok {
+                       casgstatus(gp, _Gwaiting, _Grunnable)
+                       execute(gp) // Schedule it back, never returns.
+               }
+       }
+       schedule()
+}
+
+// Gosched continuation on g0.
+func gosched_m(gp *g) {
+       status := readgstatus(gp)
+       if status&^_Gscan != _Grunning {
+               dumpgstatus(gp)
+               gothrow("bad g status")
+       }
+       casgstatus(gp, _Grunning, _Grunnable)
+       dropg()
+       lock(&sched.lock)
+       globrunqput(gp)
+       unlock(&sched.lock)
+
+       schedule()
+}
+
+// Finishes execution of the current goroutine.
+// Must be NOSPLIT because it is called from Go. (TODO - probably not anymore)
+//go:nosplit
+func goexit1() {
+       if raceenabled {
+               racegoend()
+       }
+       mcall(goexit0)
+}
+
+// goexit continuation on g0.
+func goexit0(gp *g) {
+       _g_ := getg()
+
+       casgstatus(gp, _Grunning, _Gdead)
+       gp.m = nil
+       gp.lockedm = nil
+       _g_.m.lockedg = nil
+       gp.paniconfault = false
+       gp._defer = nil // should be true already but just in case.
+       gp._panic = nil // non-nil for Goexit during panic. points at stack-allocated data.
+       gp.writebuf = nil
+       gp.waitreason = ""
+       gp.param = nil
+
+       dropg()
+
+       if _g_.m.locked&^_LockExternal != 0 {
+               print("invalid m->locked = ", _g_.m.locked, "\n")
+               gothrow("internal lockOSThread error")
+       }
+       _g_.m.locked = 0
+       gfput(_g_.m.p, gp)
+       schedule()
+}
+
+//go:nosplit
+func save(pc, sp uintptr) {
+       _g_ := getg()
+
+       _g_.sched.pc = pc
+       _g_.sched.sp = sp
+       _g_.sched.lr = 0
+       _g_.sched.ret = 0
+       _g_.sched.ctxt = nil
+       _g_.sched.g = _g_
+}
+
+// The goroutine g is about to enter a system call.
+// Record that it's not using the cpu anymore.
+// This is called only from the go syscall library and cgocall,
+// not from the low-level system calls used by the
+//
+// Entersyscall cannot split the stack: the gosave must
+// make g->sched refer to the caller's stack segment, because
+// entersyscall is going to return immediately after.
+//
+// Nothing entersyscall calls can split the stack either.
+// We cannot safely move the stack during an active call to syscall,
+// because we do not know which of the uintptr arguments are
+// really pointers (back into the stack).
+// In practice, this means that we make the fast path run through
+// entersyscall doing no-split things, and the slow path has to use systemstack
+// to run bigger things on the system stack.
+//
+// reentersyscall is the entry point used by cgo callbacks, where explicitly
+// saved SP and PC are restored. This is needed when exitsyscall will be called
+// from a function further up in the call stack than the parent, as g->syscallsp
+// must always point to a valid stack frame. entersyscall below is the normal
+// entry point for syscalls, which obtains the SP and PC from the caller.
+//go:nosplit
+func reentersyscall(pc, sp uintptr) {
+       _g_ := getg()
+
+       // Disable preemption because during this function g is in Gsyscall status,
+       // but can have inconsistent g->sched, do not let GC observe it.
+       _g_.m.locks++
+
+       // Entersyscall must not call any function that might split/grow the stack.
+       // (See details in comment above.)
+       // Catch calls that might, by replacing the stack guard with something that
+       // will trip any stack check and leaving a flag to tell newstack to die.
+       _g_.stackguard0 = stackPreempt
+       _g_.throwsplit = true
+
+       // Leave SP around for GC and traceback.
+       save(pc, sp)
+       _g_.syscallsp = sp
+       _g_.syscallpc = pc
+       casgstatus(_g_, _Grunning, _Gsyscall)
+       if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
+               systemstack(entersyscall_bad)
+       }
+
+       if atomicload(&sched.sysmonwait) != 0 { // TODO: fast atomic
+               systemstack(entersyscall_sysmon)
+               save(pc, sp)
+       }
+
+       _g_.m.mcache = nil
+       _g_.m.p.m = nil
+       atomicstore(&_g_.m.p.status, _Psyscall)
+       if sched.gcwaiting != 0 {
+               systemstack(entersyscall_gcwait)
+               save(pc, sp)
+       }
+
+       // Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).
+       // We set _StackGuard to StackPreempt so that first split stack check calls morestack.
+       // Morestack detects this case and throws.
+       _g_.stackguard0 = stackPreempt
+       _g_.m.locks--
+}
+
+// Standard syscall entry used by the go syscall library and normal cgo calls.
+//go:nosplit
+func entersyscall(dummy int32) {
+       reentersyscall(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
+}
+
+func entersyscall_bad() {
+       var gp *g
+       gp = getg().m.curg
+       print("entersyscall inconsistent ", hex(gp.syscallsp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
+       gothrow("entersyscall")
+}
+
+func entersyscall_sysmon() {
+       lock(&sched.lock)
+       if atomicload(&sched.sysmonwait) != 0 {
+               atomicstore(&sched.sysmonwait, 0)
+               notewakeup(&sched.sysmonnote)
+       }
+       unlock(&sched.lock)
+}
+
+func entersyscall_gcwait() {
+       _g_ := getg()
+
+       lock(&sched.lock)
+       if sched.stopwait > 0 && cas(&_g_.m.p.status, _Psyscall, _Pgcstop) {
+               if sched.stopwait--; sched.stopwait == 0 {
+                       notewakeup(&sched.stopnote)
+               }
+       }
+       unlock(&sched.lock)
+}
+
+// The same as entersyscall(), but with a hint that the syscall is blocking.
+//go:nosplit
+func entersyscallblock(dummy int32) {
+       _g_ := getg()
+
+       _g_.m.locks++ // see comment in entersyscall
+       _g_.throwsplit = true
+       _g_.stackguard0 = stackPreempt // see comment in entersyscall
+
+       // Leave SP around for GC and traceback.
+       save(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
+       _g_.syscallsp = _g_.sched.sp
+       _g_.syscallpc = _g_.sched.pc
+       casgstatus(_g_, _Grunning, _Gsyscall)
+       if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
+               systemstack(entersyscall_bad)
+       }
+
+       systemstack(entersyscallblock_handoff)
+
+       // Resave for traceback during blocked call.
+       save(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
+
+       _g_.m.locks--
+}
+
+func entersyscallblock_handoff() {
+       handoffp(releasep())
+}
+
+// The goroutine g exited its system call.
+// Arrange for it to run on a cpu again.
+// This is called only from the go syscall library, not
+// from the low-level system calls used by the
+//go:nosplit
+func exitsyscall(dummy int32) {
+       _g_ := getg()
+
+       _g_.m.locks++ // see comment in entersyscall
+       if getcallersp(unsafe.Pointer(&dummy)) > _g_.syscallsp {
+               gothrow("exitsyscall: syscall frame is no longer valid")
+       }
+
+       _g_.waitsince = 0
+       if exitsyscallfast() {
+               if _g_.m.mcache == nil {
+                       gothrow("lost mcache")
+               }
+               // There's a cpu for us, so we can run.
+               _g_.m.p.syscalltick++
+               // We need to cas the status and scan before resuming...
+               casgstatus(_g_, _Gsyscall, _Grunning)
+
+               // Garbage collector isn't running (since we are),
+               // so okay to clear syscallsp.
+               _g_.syscallsp = 0
+               _g_.m.locks--
+               if _g_.preempt {
+                       // restore the preemption request in case we've cleared it in newstack
+                       _g_.stackguard0 = stackPreempt
+               } else {
+                       // otherwise restore the real _StackGuard, we've spoiled it in entersyscall/entersyscallblock
+                       _g_.stackguard0 = _g_.stack.lo + _StackGuard
+               }
+               _g_.throwsplit = false
+               return
+       }
+
+       _g_.m.locks--
+
+       // Call the scheduler.
+       mcall(exitsyscall0)
+
+       if _g_.m.mcache == nil {
+               gothrow("lost mcache")
+       }
+
+       // Scheduler returned, so we're allowed to run now.
+       // Delete the syscallsp information that we left for
+       // the garbage collector during the system call.
+       // Must wait until now because until gosched returns
+       // we don't know for sure that the garbage collector
+       // is not running.
+       _g_.syscallsp = 0
+       _g_.m.p.syscalltick++
+       _g_.throwsplit = false
+}
+
+//go:nosplit
+func exitsyscallfast() bool {
+       _g_ := getg()
+
+       // Freezetheworld sets stopwait but does not retake P's.
+       if sched.stopwait != 0 {
+               _g_.m.p = nil
+               return false
+       }
+
+       // Try to re-acquire the last P.
+       if _g_.m.p != nil && _g_.m.p.status == _Psyscall && cas(&_g_.m.p.status, _Psyscall, _Prunning) {
+               // There's a cpu for us, so we can run.
+               _g_.m.mcache = _g_.m.p.mcache
+               _g_.m.p.m = _g_.m
+               return true
+       }
+
+       // Try to get any other idle P.
+       _g_.m.p = nil
+       if sched.pidle != nil {
+               var ok bool
+               systemstack(func() {
+                       ok = exitsyscallfast_pidle()
+               })
+               if ok {
+                       return true
+               }
+       }
+       return false
+}
+
+func exitsyscallfast_pidle() bool {
+       lock(&sched.lock)
+       _p_ := pidleget()
+       if _p_ != nil && atomicload(&sched.sysmonwait) != 0 {
+               atomicstore(&sched.sysmonwait, 0)
+               notewakeup(&sched.sysmonnote)
+       }
+       unlock(&sched.lock)
+       if _p_ != nil {
+               acquirep(_p_)
+               return true
+       }
+       return false
+}
+
+// exitsyscall slow path on g0.
+// Failed to acquire P, enqueue gp as runnable.
+func exitsyscall0(gp *g) {
+       _g_ := getg()
+
+       casgstatus(gp, _Gsyscall, _Grunnable)
+       dropg()
+       lock(&sched.lock)
+       _p_ := pidleget()
+       if _p_ == nil {
+               globrunqput(gp)
+       } else if atomicload(&sched.sysmonwait) != 0 {
+               atomicstore(&sched.sysmonwait, 0)
+               notewakeup(&sched.sysmonnote)
+       }
+       unlock(&sched.lock)
+       if _p_ != nil {
+               acquirep(_p_)
+               execute(gp) // Never returns.
+       }
+       if _g_.m.lockedg != nil {
+               // Wait until another thread schedules gp and so m again.
+               stoplockedm()
+               execute(gp) // Never returns.
+       }
+       stopm()
+       schedule() // Never returns.
+}
+
+func beforefork() {
+       gp := getg().m.curg
+
+       // Fork can hang if preempted with signals frequently enough (see issue 5517).
+       // Ensure that we stay on the same M where we disable profiling.
+       gp.m.locks++
+       if gp.m.profilehz != 0 {
+               resetcpuprofiler(0)
+       }
+
+       // This function is called before fork in syscall package.
+       // Code between fork and exec must not allocate memory nor even try to grow stack.
+       // Here we spoil g->_StackGuard to reliably detect any attempts to grow stack.
+       // runtime_AfterFork will undo this in parent process, but not in child.
+       gp.stackguard0 = stackFork
+}
+
+// Called from syscall package before fork.
+//go:nosplit
+func syscall_BeforeFork() {
+       systemstack(beforefork)
+}
+
+func afterfork() {
+       gp := getg().m.curg
+
+       // See the comment in beforefork.
+       gp.stackguard0 = gp.stack.lo + _StackGuard
+
+       hz := sched.profilehz
+       if hz != 0 {
+               resetcpuprofiler(hz)
+       }
+       gp.m.locks--
+}
+
+// Called from syscall package after fork in parent.
+//go:nosplit
+func syscall_AfterFork() {
+       systemstack(afterfork)
+}
+
+// Allocate a new g, with a stack big enough for stacksize bytes.
+func malg(stacksize int32) *g {
+       newg := allocg()
+       if stacksize >= 0 {
+               stacksize = round2(_StackSystem + stacksize)
+               systemstack(func() {
+                       newg.stack = stackalloc(uint32(stacksize))
+               })
+               newg.stackguard0 = newg.stack.lo + _StackGuard
+               newg.stackguard1 = ^uintptr(0)
+       }
+       return newg
+}
+
+// Create a new g running fn with siz bytes of arguments.
+// Put it on the queue of g's waiting to run.
+// The compiler turns a go statement into a call to this.
+// Cannot split the stack because it assumes that the arguments
+// are available sequentially after &fn; they would not be
+// copied if a stack split occurred.
+//go:nosplit
+func newproc(siz int32, fn *funcval) {
+       argp := add(unsafe.Pointer(&fn), ptrSize)
+       if hasLinkRegister {
+               argp = add(argp, ptrSize) // skip caller's saved LR
+       }
+
+       pc := getcallerpc(unsafe.Pointer(&siz))
+       systemstack(func() {
+               newproc1(fn, (*uint8)(argp), siz, 0, pc)
+       })
+}
+
+// Create a new g running fn with narg bytes of arguments starting
+// at argp and returning nret bytes of results.  callerpc is the
+// address of the go statement that created this.  The new g is put
+// on the queue of g's waiting to run.
+func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr) *g {
+       _g_ := getg()
+
+       if fn == nil {
+               _g_.m.throwing = -1 // do not dump full stacks
+               gothrow("go of nil func value")
+       }
+       _g_.m.locks++ // disable preemption because it can be holding p in a local var
+       siz := narg + nret
+       siz = (siz + 7) &^ 7
+
+       // We could allocate a larger initial stack if necessary.
+       // Not worth it: this is almost always an error.
+       // 4*sizeof(uintreg): extra space added below
+       // sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
+       if siz >= _StackMin-4*regSize-regSize {
+               gothrow("newproc: function arguments too large for new goroutine")
+       }
+
+       _p_ := _g_.m.p
+       newg := gfget(_p_)
+       if newg == nil {
+               newg = malg(_StackMin)
+               casgstatus(newg, _Gidle, _Gdead)
+               allgadd(newg) // publishes with a g->status of Gdead so GC scanner doesn't look at uninitialized stack.
+       }
+       if newg.stack.hi == 0 {
+               gothrow("newproc1: newg missing stack")
+       }
+
+       if readgstatus(newg) != _Gdead {
+               gothrow("newproc1: new g is not Gdead")
+       }
+
+       sp := newg.stack.hi
+       sp -= 4 * regSize // extra space in case of reads slightly beyond frame
+       sp -= uintptr(siz)
+       memmove(unsafe.Pointer(sp), unsafe.Pointer(argp), uintptr(narg))
+       if hasLinkRegister {
+               // caller's LR
+               sp -= ptrSize
+               *(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
+       }
+
+       memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
+       newg.sched.sp = sp
+       newg.sched.pc = funcPC(goexit) + _PCQuantum // +PCQuantum so that previous instruction is in same function
+       newg.sched.g = newg
+       gostartcallfn(&newg.sched, fn)
+       newg.gopc = callerpc
+       casgstatus(newg, _Gdead, _Grunnable)
+
+       if _p_.goidcache == _p_.goidcacheend {
+               // Sched.goidgen is the last allocated id,
+               // this batch must be [sched.goidgen+1, sched.goidgen+GoidCacheBatch].
+               // At startup sched.goidgen=0, so main goroutine receives goid=1.
+               _p_.goidcache = xadd64(&sched.goidgen, _GoidCacheBatch)
+               _p_.goidcache -= _GoidCacheBatch - 1
+               _p_.goidcacheend = _p_.goidcache + _GoidCacheBatch
+       }
+       newg.goid = int64(_p_.goidcache)
+       _p_.goidcache++
+       if raceenabled {
+               newg.racectx = racegostart(callerpc)
+       }
+       runqput(_p_, newg)
+
+       if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
+               wakep()
+       }
+       _g_.m.locks--
+       if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+               _g_.stackguard0 = stackPreempt
+       }
+       return newg
+}
+
+// Put on gfree list.
+// If local list is too long, transfer a batch to the global list.
+func gfput(_p_ *p, gp *g) {
+       if readgstatus(gp) != _Gdead {
+               gothrow("gfput: bad status (not Gdead)")
+       }
+
+       stksize := gp.stack.hi - gp.stack.lo
+
+       if stksize != _FixedStack {
+               // non-standard stack size - free it.
+               stackfree(gp.stack)
+               gp.stack.lo = 0
+               gp.stack.hi = 0
+               gp.stackguard0 = 0
+       }
+
+       gp.schedlink = _p_.gfree
+       _p_.gfree = gp
+       _p_.gfreecnt++
+       if _p_.gfreecnt >= 64 {
+               lock(&sched.gflock)
+               for _p_.gfreecnt >= 32 {
+                       _p_.gfreecnt--
+                       gp = _p_.gfree
+                       _p_.gfree = gp.schedlink
+                       gp.schedlink = sched.gfree
+                       sched.gfree = gp
+                       sched.ngfree++
+               }
+               unlock(&sched.gflock)
+       }
+}
+
+// Get from gfree list.
+// If local list is empty, grab a batch from global list.
+func gfget(_p_ *p) *g {
+retry:
+       gp := _p_.gfree
+       if gp == nil && sched.gfree != nil {
+               lock(&sched.gflock)
+               for _p_.gfreecnt < 32 && sched.gfree != nil {
+                       _p_.gfreecnt++
+                       gp = sched.gfree
+                       sched.gfree = gp.schedlink
+                       sched.ngfree--
+                       gp.schedlink = _p_.gfree
+                       _p_.gfree = gp
+               }
+               unlock(&sched.gflock)
+               goto retry
+       }
+       if gp != nil {
+               _p_.gfree = gp.schedlink
+               _p_.gfreecnt--
+               if gp.stack.lo == 0 {
+                       // Stack was deallocated in gfput.  Allocate a new one.
+                       systemstack(func() {
+                               gp.stack = stackalloc(_FixedStack)
+                       })
+                       gp.stackguard0 = gp.stack.lo + _StackGuard
+               } else {
+                       if raceenabled {
+                               racemalloc(unsafe.Pointer(gp.stack.lo), gp.stack.hi-gp.stack.lo)
+                       }
+               }
+       }
+       return gp
+}
+
+// Purge all cached G's from gfree list to the global list.
+func gfpurge(_p_ *p) {
+       lock(&sched.gflock)
+       for _p_.gfreecnt != 0 {
+               _p_.gfreecnt--
+               gp := _p_.gfree
+               _p_.gfree = gp.schedlink
+               gp.schedlink = sched.gfree
+               sched.gfree = gp
+               sched.ngfree++
+       }
+       unlock(&sched.gflock)
+}
+
+// Breakpoint executes a breakpoint trap.
+func Breakpoint() {
+       breakpoint()
+}
+
+// dolockOSThread is called by LockOSThread and lockOSThread below
+// after they modify m.locked. Do not allow preemption during this call,
+// or else the m might be different in this function than in the caller.
+//go:nosplit
+func dolockOSThread() {
+       _g_ := getg()
+       _g_.m.lockedg = _g_
+       _g_.lockedm = _g_.m
+}
+
+//go:nosplit
+
+// LockOSThread wires the calling goroutine to its current operating system thread.
+// Until the calling goroutine exits or calls UnlockOSThread, it will always
+// execute in that thread, and no other goroutine can.
+func LockOSThread() {
+       getg().m.locked |= _LockExternal
+       dolockOSThread()
+}
+
+//go:nosplit
+func lockOSThread() {
+       getg().m.locked += _LockInternal
+       dolockOSThread()
+}
+
+// dounlockOSThread is called by UnlockOSThread and unlockOSThread below
+// after they update m->locked. Do not allow preemption during this call,
+// or else the m might be in different in this function than in the caller.
+//go:nosplit
+func dounlockOSThread() {
+       _g_ := getg()
+       if _g_.m.locked != 0 {
+               return
+       }
+       _g_.m.lockedg = nil
+       _g_.lockedm = nil
+}
+
+//go:nosplit
+
+// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
+// If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
+func UnlockOSThread() {
+       getg().m.locked &^= _LockExternal
+       dounlockOSThread()
+}
+
+//go:nosplit
+func unlockOSThread() {
+       _g_ := getg()
+       if _g_.m.locked < _LockInternal {
+               systemstack(badunlockosthread)
+       }
+       _g_.m.locked -= _LockInternal
+       dounlockOSThread()
+}
+
+func badunlockosthread() {
+       gothrow("runtime: internal error: misuse of lockOSThread/unlockOSThread")
+}
+
+func gcount() int32 {
+       n := int32(allglen) - sched.ngfree
+       for i := 0; ; i++ {
+               _p_ := allp[i]
+               if _p_ == nil {
+                       break
+               }
+               n -= _p_.gfreecnt
+       }
+
+       // All these variables can be changed concurrently, so the result can be inconsistent.
+       // But at least the current goroutine is running.
+       if n < 1 {
+               n = 1
+       }
+       return n
+}
+
+func mcount() int32 {
+       return sched.mcount
+}
+
+var prof struct {
+       lock uint32
+       hz   int32
+}
+
+func _System()       { _System() }
+func _ExternalCode() { _ExternalCode() }
+func _GC()           { _GC() }
+
+var etext struct{}
+
+// Called if we receive a SIGPROF signal.
+func sigprof(pc *uint8, sp *uint8, lr *uint8, gp *g, mp *m) {
+       var n int32
+       var traceback bool
+       var stk [100]uintptr
+
+       if prof.hz == 0 {
+               return
+       }
+
+       // Profiling runs concurrently with GC, so it must not allocate.
+       mp.mallocing++
+
+       // Define that a "user g" is a user-created goroutine, and a "system g"
+       // is one that is m->g0 or m->gsignal. We've only made sure that we
+       // can unwind user g's, so exclude the system g's.
+       //
+       // It is not quite as easy as testing gp == m->curg (the current user g)
+       // because we might be interrupted for profiling halfway through a
+       // goroutine switch. The switch involves updating three (or four) values:
+       // g, PC, SP, and (on arm) LR. The PC must be the last to be updated,
+       // because once it gets updated the new g is running.
+       //
+       // When switching from a user g to a system g, LR is not considered live,
+       // so the update only affects g, SP, and PC. Since PC must be last, there
+       // the possible partial transitions in ordinary execution are (1) g alone is updated,
+       // (2) both g and SP are updated, and (3) SP alone is updated.
+       // If g is updated, we'll see a system g and not look closer.
+       // If SP alone is updated, we can detect the partial transition by checking
+       // whether the SP is within g's stack bounds. (We could also require that SP
+       // be changed only after g, but the stack bounds check is needed by other
+       // cases, so there is no need to impose an additional requirement.)
+       //
+       // There is one exceptional transition to a system g, not in ordinary execution.
+       // When a signal arrives, the operating system starts the signal handler running
+       // with an updated PC and SP. The g is updated last, at the beginning of the
+       // handler. There are two reasons this is okay. First, until g is updated the
+       // g and SP do not match, so the stack bounds check detects the partial transition.
+       // Second, signal handlers currently run with signals disabled, so a profiling
+       // signal cannot arrive during the handler.
+       //
+       // When switching from a system g to a user g, there are three possibilities.
+       //
+       // First, it may be that the g switch has no PC update, because the SP
+       // either corresponds to a user g throughout (as in asmcgocall)
+       // or because it has been arranged to look like a user g frame
+       // (as in cgocallback_gofunc). In this case, since the entire
+       // transition is a g+SP update, a partial transition updating just one of
+       // those will be detected by the stack bounds check.
+       //
+       // Second, when returning from a signal handler, the PC and SP updates
+       // are performed by the operating system in an atomic update, so the g
+       // update must be done before them. The stack bounds check detects
+       // the partial transition here, and (again) signal handlers run with signals
+       // disabled, so a profiling signal cannot arrive then anyway.
+       //
+       // Third, the common case: it may be that the switch updates g, SP, and PC
+       // separately, as in gogo.
+       //
+       // Because gogo is the only instance, we check whether the PC lies
+       // within that function, and if so, not ask for a traceback. This approach
+       // requires knowing the size of the gogo function, which we
+       // record in arch_*.h and check in runtime_test.go.
+       //
+       // There is another apparently viable approach, recorded here in case
+       // the "PC within gogo" check turns out not to be usable.
+       // It would be possible to delay the update of either g or SP until immediately
+       // before the PC update instruction. Then, because of the stack bounds check,
+       // the only problematic interrupt point is just before that PC update instruction,
+       // and the sigprof handler can detect that instruction and simulate stepping past
+       // it in order to reach a consistent state. On ARM, the update of g must be made
+       // in two places (in R10 and also in a TLS slot), so the delayed update would
+       // need to be the SP update. The sigprof handler must read the instruction at
+       // the current PC and if it was the known instruction (for example, JMP BX or
+       // MOV R2, PC), use that other register in place of the PC value.
+       // The biggest drawback to this solution is that it requires that we can tell
+       // whether it's safe to read from the memory pointed at by PC.
+       // In a correct program, we can test PC == nil and otherwise read,
+       // but if a profiling signal happens at the instant that a program executes
+       // a bad jump (before the program manages to handle the resulting fault)
+       // the profiling handler could fault trying to read nonexistent memory.
+       //
+       // To recap, there are no constraints on the assembly being used for the
+       // transition. We simply require that g and SP match and that the PC is not
+       // in gogo.
+       traceback = true
+       usp := uintptr(unsafe.Pointer(sp))
+       gogo := funcPC(gogo)
+       if gp == nil || gp != mp.curg ||
+               usp < gp.stack.lo || gp.stack.hi < usp ||
+               (gogo <= uintptr(unsafe.Pointer(pc)) && uintptr(unsafe.Pointer(pc)) < gogo+_RuntimeGogoBytes) {
+               traceback = false
+       }
+
+       n = 0
+       if traceback {
+               n = int32(gentraceback(uintptr(unsafe.Pointer(pc)), uintptr(unsafe.Pointer(sp)), uintptr(unsafe.Pointer(lr)), gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap))
+       }
+       if !traceback || n <= 0 {
+               // Normal traceback is impossible or has failed.
+               // See if it falls into several common cases.
+               n = 0
+               if mp.ncgo > 0 && mp.curg != nil && mp.curg.syscallpc != 0 && mp.curg.syscallsp != 0 {
+                       // Cgo, we can't unwind and symbolize arbitrary C code,
+                       // so instead collect Go stack that leads to the cgo call.
+                       // This is especially important on windows, since all syscalls are cgo calls.
+                       n = int32(gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[0], len(stk), nil, nil, 0))
+               }
+               if GOOS == "windows" && n == 0 && mp.libcallg != nil && mp.libcallpc != 0 && mp.libcallsp != 0 {
+                       // Libcall, i.e. runtime syscall on windows.
+                       // Collect Go stack that leads to the call.
+                       n = int32(gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg, 0, &stk[0], len(stk), nil, nil, 0))
+               }
+               if n == 0 {
+                       // If all of the above has failed, account it against abstract "System" or "GC".
+                       n = 2
+                       // "ExternalCode" is better than "etext".
+                       if uintptr(unsafe.Pointer(pc)) > uintptr(unsafe.Pointer(&etext)) {
+                               pc = (*uint8)(unsafe.Pointer(uintptr(funcPC(_ExternalCode) + _PCQuantum)))
+                       }
+                       stk[0] = uintptr(unsafe.Pointer(pc))
+                       if mp.gcing != 0 || mp.helpgc != 0 {
+                               stk[1] = funcPC(_GC) + _PCQuantum
+                       } else {
+                               stk[1] = funcPC(_System) + _PCQuantum
+                       }
+               }
+       }
+
+       if prof.hz != 0 {
+               // Simple cas-lock to coordinate with setcpuprofilerate.
+               for !cas(&prof.lock, 0, 1) {
+                       osyield()
+               }
+               if prof.hz != 0 {
+                       cpuproftick(&stk[0], n)
+               }
+               atomicstore(&prof.lock, 0)
+       }
+       mp.mallocing--
+}
+
+// Arrange to call fn with a traceback hz times a second.
+func setcpuprofilerate_m(hz int32) {
+       // Force sane arguments.
+       if hz < 0 {
+               hz = 0
+       }
+
+       // Disable preemption, otherwise we can be rescheduled to another thread
+       // that has profiling enabled.
+       _g_ := getg()
+       _g_.m.locks++
+
+       // Stop profiler on this thread so that it is safe to lock prof.
+       // if a profiling signal came in while we had prof locked,
+       // it would deadlock.
+       resetcpuprofiler(0)
+
+       for !cas(&prof.lock, 0, 1) {
+               osyield()
+       }
+       prof.hz = hz
+       atomicstore(&prof.lock, 0)
+
+       lock(&sched.lock)
+       sched.profilehz = hz
+       unlock(&sched.lock)
+
+       if hz != 0 {
+               resetcpuprofiler(hz)
+       }
+
+       _g_.m.locks--
+}
+
+// Change number of processors.  The world is stopped, sched is locked.
+func procresize(new int32) {
+       old := gomaxprocs
+       if old < 0 || old > _MaxGomaxprocs || new <= 0 || new > _MaxGomaxprocs {
+               gothrow("procresize: invalid arg")
+       }
+
+       // initialize new P's
+       for i := int32(0); i < new; i++ {
+               p := allp[i]
+               if p == nil {
+                       p = newP()
+                       p.id = i
+                       p.status = _Pgcstop
+                       atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(p))
+               }
+               if p.mcache == nil {
+                       if old == 0 && i == 0 {
+                               if getg().m.mcache == nil {
+                                       gothrow("missing mcache?")
+                               }
+                               p.mcache = getg().m.mcache // bootstrap
+                       } else {
+                               p.mcache = allocmcache()
+                       }
+               }
+       }
+
+       // redistribute runnable G's evenly
+       // collect all runnable goroutines in global queue preserving FIFO order
+       // FIFO order is required to ensure fairness even during frequent GCs
+       // see http://golang.org/issue/7126
+       empty := false
+       for !empty {
+               empty = true
+               for i := int32(0); i < old; i++ {
+                       p := allp[i]
+                       if p.runqhead == p.runqtail {
+                               continue
+                       }
+                       empty = false
+                       // pop from tail of local queue
+                       p.runqtail--
+                       gp := p.runq[p.runqtail%uint32(len(p.runq))]
+                       // push onto head of global queue
+                       gp.schedlink = sched.runqhead
+                       sched.runqhead = gp
+                       if sched.runqtail == nil {
+                               sched.runqtail = gp
+                       }
+                       sched.runqsize++
+               }
+       }
+
+       // fill local queues with at most len(p.runq)/2 goroutines
+       // 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].
+       var _p_ p
+       for i := int32(1); i < new*int32(len(_p_.runq))/2 && sched.runqsize > 0; i++ {
+               gp := sched.runqhead
+               sched.runqhead = gp.schedlink
+               if sched.runqhead == nil {
+                       sched.runqtail = nil
+               }
+               sched.runqsize--
+               runqput(allp[i%new], gp)
+       }
+
+       // free unused P's
+       for i := new; i < old; i++ {
+               p := allp[i]
+               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
+       }
+
+       _g_ := getg()
+       if _g_.m.p != nil {
+               _g_.m.p.m = nil
+       }
+       _g_.m.p = nil
+       _g_.m.mcache = nil
+       p := allp[0]
+       p.m = nil
+       p.status = _Pidle
+       acquirep(p)
+       for i := new - 1; i > 0; i-- {
+               p := allp[i]
+               p.status = _Pidle
+               pidleput(p)
+       }
+       var int32p *int32 = &gomaxprocs // make compiler check that gomaxprocs is an int32
+       atomicstore((*uint32)(unsafe.Pointer(int32p)), uint32(new))
+}
+
+// Associate p and the current m.
+func acquirep(_p_ *p) {
+       _g_ := getg()
+
+       if _g_.m.p != nil || _g_.m.mcache != nil {
+               gothrow("acquirep: already in go")
+       }
+       if _p_.m != nil || _p_.status != _Pidle {
+               id := int32(0)
+               if _p_.m != nil {
+                       id = _p_.m.id
+               }
+               print("acquirep: p->m=", _p_.m, "(", id, ") p->status=", _p_.status, "\n")
+               gothrow("acquirep: invalid p state")
+       }
+       _g_.m.mcache = _p_.mcache
+       _g_.m.p = _p_
+       _p_.m = _g_.m
+       _p_.status = _Prunning
+}
+
+// Disassociate p and the current m.
+func releasep() *p {
+       _g_ := getg()
+
+       if _g_.m.p == nil || _g_.m.mcache == nil {
+               gothrow("releasep: invalid arg")
+       }
+       _p_ := _g_.m.p
+       if _p_.m != _g_.m || _p_.mcache != _g_.m.mcache || _p_.status != _Prunning {
+               print("releasep: m=", _g_.m, " m->p=", _g_.m.p, " p->m=", _p_.m, " m->mcache=", _g_.m.mcache, " p->mcache=", _p_.mcache, " p->status=", _p_.status, "\n")
+               gothrow("releasep: invalid p state")
+       }
+       _g_.m.p = nil
+       _g_.m.mcache = nil
+       _p_.m = nil
+       _p_.status = _Pidle
+       return _p_
+}
+
+func incidlelocked(v int32) {
+       lock(&sched.lock)
+       sched.nmidlelocked += v
+       if v > 0 {
+               checkdead()
+       }
+       unlock(&sched.lock)
+}
+
+// Check for deadlock situation.
+// The check is based on number of running M's, if 0 -> deadlock.
+func checkdead() {
+       // If we are dying because of a signal caught on an already idle thread,
+       // freezetheworld will cause all running threads to block.
+       // And runtime will essentially enter into deadlock state,
+       // except that there is a thread that will call exit soon.
+       if panicking > 0 {
+               return
+       }
+
+       // -1 for sysmon
+       run := sched.mcount - sched.nmidle - sched.nmidlelocked - 1
+       if run > 0 {
+               return
+       }
+       if run < 0 {
+               print("runtime: checkdead: nmidle=", sched.nmidle, " nmidlelocked=", sched.nmidlelocked, " mcount=", sched.mcount, "\n")
+               gothrow("checkdead: inconsistent counts")
+       }
+
+       grunning := 0
+       lock(&allglock)
+       for i := 0; i < len(allgs); i++ {
+               gp := allgs[i]
+               if gp.issystem {
+                       continue
+               }
+               s := readgstatus(gp)
+               switch s &^ _Gscan {
+               case _Gwaiting:
+                       grunning++
+               case _Grunnable,
+                       _Grunning,
+                       _Gsyscall:
+                       unlock(&allglock)
+                       print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n")
+                       gothrow("checkdead: runnable g")
+               }
+       }
+       unlock(&allglock)
+       if grunning == 0 { // possible if main goroutine calls runtime·Goexit()
+               gothrow("no goroutines (main called runtime.Goexit) - deadlock!")
+       }
+
+       // Maybe jump time forward for playground.
+       gp := timejump()
+       if gp != nil {
+               casgstatus(gp, _Gwaiting, _Grunnable)
+               globrunqput(gp)
+               _p_ := pidleget()
+               if _p_ == nil {
+                       gothrow("checkdead: no p for timer")
+               }
+               mp := mget()
+               if mp == nil {
+                       _newm(nil, _p_)
+               } else {
+                       mp.nextp = _p_
+                       notewakeup(&mp.park)
+               }
+               return
+       }
+
+       getg().m.throwing = -1 // do not dump full stacks
+       gothrow("all goroutines are asleep - deadlock!")
+}
+
+func sysmon() {
+       // If we go two minutes without a garbage collection, force one to run.
+       forcegcperiod := int64(2 * 60 * 1e9)
+
+       // If a heap span goes unused for 5 minutes after a garbage collection,
+       // we hand it back to the operating system.
+       scavengelimit := int64(5 * 60 * 1e9)
+
+       if debug.scavenge > 0 {
+               // Scavenge-a-lot for testing.
+               forcegcperiod = 10 * 1e6
+               scavengelimit = 20 * 1e6
+       }
+
+       lastscavenge := nanotime()
+       nscavenge := 0
+
+       // Make wake-up period small enough for the sampling to be correct.
+       maxsleep := forcegcperiod / 2
+       if scavengelimit < forcegcperiod {
+               maxsleep = scavengelimit / 2
+       }
+
+       lasttrace := int64(0)
+       idle := 0 // how many cycles in succession we had not wokeup somebody
+       delay := uint32(0)
+       for {
+               if idle == 0 { // start with 20us sleep...
+                       delay = 20
+               } else if idle > 50 { // start doubling the sleep after 1ms...
+                       delay *= 2
+               }
+               if delay > 10*1000 { // up to 10ms
+                       delay = 10 * 1000
+               }
+               usleep(delay)
+               if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
+                       lock(&sched.lock)
+                       if atomicload(&sched.gcwaiting) != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs) {
+                               atomicstore(&sched.sysmonwait, 1)
+                               unlock(&sched.lock)
+                               notetsleep(&sched.sysmonnote, maxsleep)
+                               lock(&sched.lock)
+                               atomicstore(&sched.sysmonwait, 0)
+                               noteclear(&sched.sysmonnote)
+                               idle = 0
+                               delay = 20
+                       }
+                       unlock(&sched.lock)
+               }
+               // poll network if not polled for more than 10ms
+               lastpoll := int64(atomicload64(&sched.lastpoll))
+               now := nanotime()
+               unixnow := unixnanotime()
+               if lastpoll != 0 && lastpoll+10*1000*1000 < now {
+                       cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
+                       gp := netpoll(false) // non-blocking - returns list of goroutines
+                       if gp != nil {
+                               // Need to decrement number of idle locked M's
+                               // (pretending that one more is running) before injectglist.
+                               // Otherwise it can lead to the following situation:
+                               // injectglist grabs all P's but before it starts M's to run the P's,
+                               // another M returns from syscall, finishes running its G,
+                               // observes that there is no work to do and no other running M's
+                               // and reports deadlock.
+                               incidlelocked(-1)
+                               injectglist(gp)
+                               incidlelocked(1)
+                       }
+               }
+               // retake P's blocked in syscalls
+               // and preempt long running G's
+               if retake(now) != 0 {
+                       idle = 0
+               } else {
+                       idle++
+               }
+               // check if we need to force a GC
+               lastgc := int64(atomicload64(&memstats.last_gc))
+               if lastgc != 0 && unixnow-lastgc > forcegcperiod && atomicload(&forcegc.idle) != 0 {
+                       lock(&forcegc.lock)
+                       forcegc.idle = 0
+                       forcegc.g.schedlink = nil
+                       injectglist(forcegc.g)
+                       unlock(&forcegc.lock)
+               }
+               // scavenge heap once in a while
+               if lastscavenge+scavengelimit/2 < now {
+                       mHeap_Scavenge(int32(nscavenge), uint64(now), uint64(scavengelimit))
+                       lastscavenge = now
+                       nscavenge++
+               }
+               if debug.schedtrace > 0 && lasttrace+int64(debug.schedtrace*1000000) <= now {
+                       lasttrace = now
+                       schedtrace(debug.scheddetail > 0)
+               }
+       }
+}
+
+var pdesc [_MaxGomaxprocs]struct {
+       schedtick   uint32
+       schedwhen   int64
+       syscalltick uint32
+       syscallwhen int64
+}
+
+func retake(now int64) uint32 {
+       n := 0
+       for i := int32(0); i < gomaxprocs; i++ {
+               _p_ := allp[i]
+               if _p_ == nil {
+                       continue
+               }
+               pd := &pdesc[i]
+               s := _p_.status
+               if s == _Psyscall {
+                       // Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
+                       t := int64(_p_.syscalltick)
+                       if int64(pd.syscalltick) != t {
+                               pd.syscalltick = uint32(t)
+                               pd.syscallwhen = now
+                               continue
+                       }
+                       // On the one hand we don't want to retake Ps if there is no other work to do,
+                       // but on the other hand we want to retake them eventually
+                       // because they can prevent the sysmon thread from deep sleep.
+                       if _p_.runqhead == _p_.runqtail && atomicload(&sched.nmspinning)+atomicload(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
+                               continue
+                       }
+                       // Need to decrement number of idle locked M's
+                       // (pretending that one more is running) before the CAS.
+                       // Otherwise the M from which we retake can exit the syscall,
+                       // increment nmidle and report deadlock.
+                       incidlelocked(-1)
+                       if cas(&_p_.status, s, _Pidle) {
+                               n++
+                               handoffp(_p_)
+                       }
+                       incidlelocked(1)
+               } else if s == _Prunning {
+                       // Preempt G if it's running for more than 10ms.
+                       t := int64(_p_.schedtick)
+                       if int64(pd.schedtick) != t {
+                               pd.schedtick = uint32(t)
+                               pd.schedwhen = now
+                               continue
+                       }
+                       if pd.schedwhen+10*1000*1000 > now {
+                               continue
+                       }
+                       preemptone(_p_)
+               }
+       }
+       return uint32(n)
+}
+
+// Tell all goroutines that they have been preempted and they should stop.
+// This function is purely best-effort.  It can fail to inform a goroutine if a
+// processor just started running it.
+// No locks need to be held.
+// Returns true if preemption request was issued to at least one goroutine.
+func preemptall() bool {
+       res := false
+       for i := int32(0); i < gomaxprocs; i++ {
+               _p_ := allp[i]
+               if _p_ == nil || _p_.status != _Prunning {
+                       continue
+               }
+               if preemptone(_p_) {
+                       res = true
+               }
+       }
+       return res
+}
+
+// Tell the goroutine running on processor P to stop.
+// This function is purely best-effort.  It can incorrectly fail to inform the
+// goroutine.  It can send inform the wrong goroutine.  Even if it informs the
+// correct goroutine, that goroutine might ignore the request if it is
+// simultaneously executing newstack.
+// No lock needs to be held.
+// Returns true if preemption request was issued.
+// The actual preemption will happen at some point in the future
+// and will be indicated by the gp->status no longer being
+// Grunning
+func preemptone(_p_ *p) bool {
+       mp := _p_.m
+       if mp == nil || mp == getg().m {
+               return false
+       }
+       gp := mp.curg
+       if gp == nil || gp == mp.g0 {
+               return false
+       }
+
+       gp.preempt = true
+
+       // Every call in a go routine checks for stack overflow by
+       // comparing the current stack pointer to gp->stackguard0.
+       // Setting gp->stackguard0 to StackPreempt folds
+       // preemption into the normal stack overflow check.
+       gp.stackguard0 = stackPreempt
+       return true
+}
+
+var starttime int64
+
+func schedtrace(detailed bool) {
+       now := nanotime()
+       if starttime == 0 {
+               starttime = now
+       }
+
+       lock(&sched.lock)
+       print("SCHED ", (now-starttime)/1e6, "ms: gomaxprocs=", gomaxprocs, " idleprocs=", sched.npidle, " threads=", sched.mcount, " spinningthreads=", sched.nmspinning, " idlethreads=", sched.nmidle, " runqueue=", sched.runqsize)
+       if detailed {
+               print(" gcwaiting=", sched.gcwaiting, " nmidlelocked=", sched.nmidlelocked, " stopwait=", sched.stopwait, " sysmonwait=", sched.sysmonwait, "\n")
+       }
+       // We must be careful while reading data from P's, M's and G's.
+       // Even if we hold schedlock, most data can be changed concurrently.
+       // E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
+       for i := int32(0); i < gomaxprocs; i++ {
+               _p_ := allp[i]
+               if _p_ == nil {
+                       continue
+               }
+               mp := _p_.m
+               h := atomicload(&_p_.runqhead)
+               t := atomicload(&_p_.runqtail)
+               if detailed {
+                       id := int32(-1)
+                       if mp != nil {
+                               id = mp.id
+                       }
+                       print("  P", i, ": status=", _p_.status, " schedtick=", _p_.schedtick, " syscalltick=", _p_.syscalltick, " m=", id, " runqsize=", t-h, " gfreecnt=", _p_.gfreecnt, "\n")
+               } else {
+                       // In non-detailed mode format lengths of per-P run queues as:
+                       // [len1 len2 len3 len4]
+                       print(" ")
+                       if i == 0 {
+                               print("[")
+                       }
+                       print(t - h)
+                       if i == gomaxprocs-1 {
+                               print("]\n")
+                       }
+               }
+       }
+
+       if !detailed {
+               unlock(&sched.lock)
+               return
+       }
+
+       for mp := allm; mp != nil; mp = mp.alllink {
+               _p_ := mp.p
+               gp := mp.curg
+               lockedg := mp.lockedg
+               id1 := int32(-1)
+               if _p_ != nil {
+                       id1 = _p_.id
+               }
+               id2 := int64(-1)
+               if gp != nil {
+                       id2 = gp.goid
+               }
+               id3 := int64(-1)
+               if lockedg != nil {
+                       id3 = lockedg.goid
+               }
+               print("  M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " gcing=", mp.gcing, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
+       }
+
+       lock(&allglock)
+       for gi := 0; gi < len(allgs); gi++ {
+               gp := allgs[gi]
+               mp := gp.m
+               lockedm := gp.lockedm
+               id1 := int32(-1)
+               if mp != nil {
+                       id1 = mp.id
+               }
+               id2 := int32(-1)
+               if lockedm != nil {
+                       id2 = lockedm.id
+               }
+               print("  G", gp.goid, ": status=", readgstatus(gp), "(", gp.waitreason, ") m=", id1, " lockedm=", id2, "\n")
+       }
+       unlock(&allglock)
+       unlock(&sched.lock)
+}
+
+// Put mp on midle list.
+// Sched must be locked.
+func mput(mp *m) {
+       mp.schedlink = sched.midle
+       sched.midle = mp
+       sched.nmidle++
+       checkdead()
+}
+
+// Try to get an m from midle list.
+// Sched must be locked.
+func mget() *m {
+       mp := sched.midle
+       if mp != nil {
+               sched.midle = mp.schedlink
+               sched.nmidle--
+       }
+       return mp
+}
+
+// Put gp on the global runnable queue.
+// Sched must be locked.
+func globrunqput(gp *g) {
+       gp.schedlink = nil
+       if sched.runqtail != nil {
+               sched.runqtail.schedlink = gp
+       } else {
+               sched.runqhead = gp
+       }
+       sched.runqtail = gp
+       sched.runqsize++
+}
+
+// Put a batch of runnable goroutines on the global runnable queue.
+// Sched must be locked.
+func globrunqputbatch(ghead *g, gtail *g, n int32) {
+       gtail.schedlink = nil
+       if sched.runqtail != nil {
+               sched.runqtail.schedlink = ghead
+       } else {
+               sched.runqhead = ghead
+       }
+       sched.runqtail = gtail
+       sched.runqsize += n
+}
+
+// Try get a batch of G's from the global runnable queue.
+// Sched must be locked.
+func globrunqget(_p_ *p, max int32) *g {
+       if sched.runqsize == 0 {
+               return nil
+       }
+
+       n := sched.runqsize/gomaxprocs + 1
+       if n > sched.runqsize {
+               n = sched.runqsize
+       }
+       if max > 0 && n > max {
+               n = max
+       }
+       if n > int32(len(_p_.runq))/2 {
+               n = int32(len(_p_.runq)) / 2
+       }
+
+       sched.runqsize -= n
+       if sched.runqsize == 0 {
+               sched.runqtail = nil
+       }
+
+       gp := sched.runqhead
+       sched.runqhead = gp.schedlink
+       n--
+       for ; n > 0; n-- {
+               gp1 := sched.runqhead
+               sched.runqhead = gp1.schedlink
+               runqput(_p_, gp1)
+       }
+       return gp
+}
+
+// Put p to on _Pidle list.
+// Sched must be locked.
+func pidleput(_p_ *p) {
+       _p_.link = sched.pidle
+       sched.pidle = _p_
+       xadd(&sched.npidle, 1) // TODO: fast atomic
+}
+
+// Try get a p from _Pidle list.
+// Sched must be locked.
+func pidleget() *p {
+       _p_ := sched.pidle
+       if _p_ != nil {
+               sched.pidle = _p_.link
+               xadd(&sched.npidle, -1) // TODO: fast atomic
+       }
+       return _p_
+}
+
+// Try to put g on local runnable queue.
+// If it's full, put onto global queue.
+// Executed only by the owner P.
+func runqput(_p_ *p, gp *g) {
+retry:
+       h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
+       t := _p_.runqtail
+       if t-h < uint32(len(_p_.runq)) {
+               _p_.runq[t%uint32(len(_p_.runq))] = gp
+               atomicstore(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
+               return
+       }
+       if runqputslow(_p_, gp, h, t) {
+               return
+       }
+       // the queue is not full, now the put above must suceed
+       goto retry
+}
+
+// Put g and a batch of work from local runnable queue on global queue.
+// Executed only by the owner P.
+func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
+       var batch [len(_p_.runq)/2 + 1]*g
+
+       // First, grab a batch from local queue.
+       n := t - h
+       n = n / 2
+       if n != uint32(len(_p_.runq)/2) {
+               gothrow("runqputslow: queue is not full")
+       }
+       for i := uint32(0); i < n; i++ {
+               batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))]
+       }
+       if !cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
+               return false
+       }
+       batch[n] = gp
+
+       // Link the goroutines.
+       for i := uint32(0); i < n; i++ {
+               batch[i].schedlink = batch[i+1]
+       }
+
+       // Now put the batch on global queue.
+       lock(&sched.lock)
+       globrunqputbatch(batch[0], batch[n], int32(n+1))
+       unlock(&sched.lock)
+       return true
+}
+
+// Get g from local runnable queue.
+// Executed only by the owner P.
+func runqget(_p_ *p) *g {
+       for {
+               h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
+               t := _p_.runqtail
+               if t == h {
+                       return nil
+               }
+               gp := _p_.runq[h%uint32(len(_p_.runq))]
+               if cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
+                       return gp
+               }
+       }
+}
+
+// Grabs a batch of goroutines from local runnable queue.
+// batch array must be of size len(p->runq)/2. Returns number of grabbed goroutines.
+// Can be executed by any P.
+func runqgrab(_p_ *p, batch []*g) uint32 {
+       for {
+               h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
+               t := atomicload(&_p_.runqtail) // load-acquire, synchronize with the producer
+               n := t - h
+               n = n - n/2
+               if n == 0 {
+                       return 0
+               }
+               if n > uint32(len(_p_.runq)/2) { // read inconsistent h and t
+                       continue
+               }
+               for i := uint32(0); i < n; i++ {
+                       batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))]
+               }
+               if cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
+                       return n
+               }
+       }
+}
+
+// Steal half of elements from local runnable queue of p2
+// and put onto local runnable queue of p.
+// Returns one of the stolen elements (or nil if failed).
+func runqsteal(_p_, p2 *p) *g {
+       var batch [len(_p_.runq) / 2]*g
+
+       n := runqgrab(p2, batch[:])
+       if n == 0 {
+               return nil
+       }
+       n--
+       gp := batch[n]
+       if n == 0 {
+               return gp
+       }
+       h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
+       t := _p_.runqtail
+       if t-h+n >= uint32(len(_p_.runq)) {
+               gothrow("runqsteal: runq overflow")
+       }
+       for i := uint32(0); i < n; i++ {
+               _p_.runq[(t+i)%uint32(len(_p_.runq))] = batch[i]
+       }
+       atomicstore(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
+       return gp
+}
+
+func testSchedLocalQueue() {
+       _p_ := new(p)
+       gs := make([]g, len(_p_.runq))
+       for i := 0; i < len(_p_.runq); i++ {
+               if runqget(_p_) != nil {
+                       gothrow("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] {
+                               print("bad element at iter ", i, "/", j, "\n")
+                               gothrow("bad element")
+                       }
+               }
+               if runqget(_p_) != nil {
+                       gothrow("runq is not empty afterwards")
+               }
+       }
+}
+
+func testSchedLocalQueueSteal() {
+       p1 := new(p)
+       p2 := new(p)
+       gs := make([]g, len(p1.runq))
+       for i := 0; i < len(p1.runq); i++ {
+               for j := 0; j < i; j++ {
+                       gs[j].sig = 0
+                       runqput(p1, &gs[j])
+               }
+               gp := runqsteal(p2, p1)
+               s := 0
+               if gp != nil {
+                       s++
+                       gp.sig++
+               }
+               for {
+                       gp = runqget(p2)
+                       if gp == nil {
+                               break
+                       }
+                       s++
+                       gp.sig++
+               }
+               for {
+                       gp = runqget(p1)
+                       if gp == nil {
+                               break
+                       }
+                       gp.sig++
+               }
+               for j := 0; j < i; j++ {
+                       if gs[j].sig != 1 {
+                               print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n")
+                               gothrow("bad element")
+                       }
+               }
+               if s != i/2 && s != i/2+1 {
+                       print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n")
+                       gothrow("bad steal")
+               }
+       }
+}
+
+func setMaxThreads(in int) (out int) {
+       lock(&sched.lock)
+       out = int(sched.maxmcount)
+       sched.maxmcount = int32(in)
+       checkmcount()
+       unlock(&sched.lock)
+       return
+}
+
+var goexperiment string = "GOEXPERIMENT" // TODO: defined in zaexperiment.h
+
+func haveexperiment(name string) bool {
+       x := goexperiment
+       for x != "" {
+               xname := ""
+               i := index(x, ",")
+               if i < 0 {
+                       xname, x = x, ""
+               } else {
+                       xname, x = x[:i], x[i+1:]
+               }
+               if xname == name {
+                       return true
+               }
+       }
+       return false
+}
+
+//go:nosplit
+func sync_procPin() int {
+       _g_ := getg()
+       mp := _g_.m
+
+       mp.locks++
+       return int(mp.p.id)
+}
+
+//go:nosplit
+func sync_procUnpin() {
+       _g_ := getg()
+       _g_.m.locks--
+}
diff --git a/src/runtime/race.c b/src/runtime/race.c
deleted file mode 100644 (file)
index 5b0d116..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Implementation of the race detector API.
-// +build race
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "race.h"
-#include "type.h"
-#include "typekind.h"
-#include "textflag.h"
-
-// Race runtime functions called via runtime·racecall.
-void __tsan_init(void);
-void __tsan_fini(void);
-void __tsan_map_shadow(void);
-void __tsan_finalizer_goroutine(void);
-void __tsan_go_start(void);
-void __tsan_go_end(void);
-void __tsan_malloc(void);
-void __tsan_acquire(void);
-void __tsan_release(void);
-void __tsan_release_merge(void);
-void __tsan_go_ignore_sync_begin(void);
-void __tsan_go_ignore_sync_end(void);
-
-// Mimic what cmd/cgo would do.
-#pragma cgo_import_static __tsan_init
-#pragma cgo_import_static __tsan_fini
-#pragma cgo_import_static __tsan_map_shadow
-#pragma cgo_import_static __tsan_finalizer_goroutine
-#pragma cgo_import_static __tsan_go_start
-#pragma cgo_import_static __tsan_go_end
-#pragma cgo_import_static __tsan_malloc
-#pragma cgo_import_static __tsan_acquire
-#pragma cgo_import_static __tsan_release
-#pragma cgo_import_static __tsan_release_merge
-#pragma cgo_import_static __tsan_go_ignore_sync_begin
-#pragma cgo_import_static __tsan_go_ignore_sync_end
-
-// These are called from race_amd64.s.
-#pragma cgo_import_static __tsan_read
-#pragma cgo_import_static __tsan_read_pc
-#pragma cgo_import_static __tsan_read_range
-#pragma cgo_import_static __tsan_write
-#pragma cgo_import_static __tsan_write_pc
-#pragma cgo_import_static __tsan_write_range
-#pragma cgo_import_static __tsan_func_enter
-#pragma cgo_import_static __tsan_func_exit
-
-#pragma cgo_import_static __tsan_go_atomic32_load
-#pragma cgo_import_static __tsan_go_atomic64_load
-#pragma cgo_import_static __tsan_go_atomic32_store
-#pragma cgo_import_static __tsan_go_atomic64_store
-#pragma cgo_import_static __tsan_go_atomic32_exchange
-#pragma cgo_import_static __tsan_go_atomic64_exchange
-#pragma cgo_import_static __tsan_go_atomic32_fetch_add
-#pragma cgo_import_static __tsan_go_atomic64_fetch_add
-#pragma cgo_import_static __tsan_go_atomic32_compare_exchange
-#pragma cgo_import_static __tsan_go_atomic64_compare_exchange
-
-extern byte runtime·noptrdata[];
-extern byte runtime·enoptrdata[];
-extern byte runtime·data[];
-extern byte runtime·edata[];
-extern byte runtime·bss[];
-extern byte runtime·ebss[];
-extern byte runtime·noptrbss[];
-extern byte runtime·enoptrbss[];
-
-// start/end of global data (data+bss).
-uintptr runtime·racedatastart;
-uintptr runtime·racedataend;
-// start/end of heap for race_amd64.s
-uintptr runtime·racearenastart;
-uintptr runtime·racearenaend;
-
-void runtime·racefuncenter(void *callpc);
-void runtime·racefuncexit(void);
-void runtime·racereadrangepc1(void *addr, uintptr sz, void *pc);
-void runtime·racewriterangepc1(void *addr, uintptr sz, void *pc);
-void runtime·racesymbolizethunk(void*);
-
-// racecall allows calling an arbitrary function f from C race runtime
-// with up to 4 uintptr arguments.
-void runtime·racecall(void(*f)(void), ...);
-
-// checks if the address has shadow (i.e. heap or data/bss)
-#pragma textflag NOSPLIT
-static bool
-isvalidaddr(uintptr addr)
-{
-       if(addr >= runtime·racearenastart && addr < runtime·racearenaend)
-               return true;
-       if(addr >= runtime·racedatastart && addr < runtime·racedataend)
-               return true;
-       return false;
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·raceinit(void)
-{
-       uintptr racectx, start, end, size;
-
-       // cgo is required to initialize libc, which is used by race runtime
-       if(!runtime·iscgo)
-               runtime·throw("raceinit: race build must use cgo");
-       runtime·racecall(__tsan_init, &racectx, runtime·racesymbolizethunk);
-       // Round data segment to page boundaries, because it's used in mmap().
-       // The relevant sections are noptrdata, data, bss, noptrbss.
-       // In external linking mode, there may be other non-Go data mixed in,
-       // and the sections may even occur out of order.
-       // Work out a conservative range of addresses.
-       start = ~(uintptr)0;
-       end = 0;
-       if(start > (uintptr)runtime·noptrdata)
-               start = (uintptr)runtime·noptrdata;
-       if(start > (uintptr)runtime·data)
-               start = (uintptr)runtime·data;
-       if(start > (uintptr)runtime·noptrbss)
-               start = (uintptr)runtime·noptrbss;
-       if(start > (uintptr)runtime·bss)
-               start = (uintptr)runtime·bss;
-       if(end < (uintptr)runtime·enoptrdata)
-               end = (uintptr)runtime·enoptrdata;
-       if(end < (uintptr)runtime·edata)
-               end = (uintptr)runtime·edata;
-       if(end < (uintptr)runtime·enoptrbss)
-               end = (uintptr)runtime·enoptrbss;
-       if(end < (uintptr)runtime·ebss)
-               end = (uintptr)runtime·ebss;
-       start = start & ~(PageSize-1);
-       size = ROUND(end - start, PageSize);
-       runtime·racecall(__tsan_map_shadow, start, size);
-       runtime·racedatastart = start;
-       runtime·racedataend = start + size;
-       return racectx;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racefini(void)
-{
-       runtime·racecall(__tsan_fini);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racemapshadow(void *addr, uintptr size)
-{
-       if(runtime·racearenastart == 0)
-               runtime·racearenastart = (uintptr)addr;
-       if(runtime·racearenaend < (uintptr)addr+size)
-               runtime·racearenaend = (uintptr)addr+size;
-       runtime·racecall(__tsan_map_shadow, addr, size);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racemalloc(void *p, uintptr sz)
-{
-       runtime·racecall(__tsan_malloc, p, sz);
-}
-
-#pragma textflag NOSPLIT
-uintptr
-runtime·racegostart(void *pc)
-{
-       uintptr racectx;
-       G *spawng;
-
-       if(g->m->curg != nil)
-               spawng = g->m->curg;
-       else
-               spawng = g;
-
-       runtime·racecall(__tsan_go_start, spawng->racectx, &racectx, pc);
-       return racectx;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racegoend(void)
-{
-       runtime·racecall(__tsan_go_end, g->racectx);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc)
-{
-       if(g != g->m->curg) {
-               // The call is coming from manual instrumentation of Go code running on g0/gsignal.
-               // Not interesting.
-               return;
-       }
-       if(callpc != nil)
-               runtime·racefuncenter(callpc);
-       runtime·racewriterangepc1(addr, sz, pc);
-       if(callpc != nil)
-               runtime·racefuncexit();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc)
-{
-       if(g != g->m->curg) {
-               // The call is coming from manual instrumentation of Go code running on g0/gsignal.
-               // Not interesting.
-               return;
-       }
-       if(callpc != nil)
-               runtime·racefuncenter(callpc);
-       runtime·racereadrangepc1(addr, sz, pc);
-       if(callpc != nil)
-               runtime·racefuncexit();
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racewriteobjectpc(void *addr, Type *t, void *callpc, void *pc)
-{
-       uint8 kind;
-
-       kind = t->kind & KindMask;
-       if(kind == KindArray || kind == KindStruct)
-               runtime·racewriterangepc(addr, t->size, callpc, pc);
-       else
-               runtime·racewritepc(addr, callpc, pc);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racereadobjectpc(void *addr, Type *t, void *callpc, void *pc)
-{
-       uint8 kind;
-
-       kind = t->kind & KindMask;
-       if(kind == KindArray || kind == KindStruct)
-               runtime·racereadrangepc(addr, t->size, callpc, pc);
-       else
-               runtime·racereadpc(addr, callpc, pc);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·raceacquire(void *addr)
-{
-       runtime·raceacquireg(g, addr);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·raceacquireg(G *gp, void *addr)
-{
-       if(g->raceignore || !isvalidaddr((uintptr)addr))
-               return;
-       runtime·racecall(__tsan_acquire, gp->racectx, addr);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racerelease(void *addr)
-{
-       if(g->raceignore || !isvalidaddr((uintptr)addr))
-               return;
-       runtime·racereleaseg(g, addr);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racereleaseg(G *gp, void *addr)
-{
-       if(g->raceignore || !isvalidaddr((uintptr)addr))
-               return;
-       runtime·racecall(__tsan_release, gp->racectx, addr);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racereleasemerge(void *addr)
-{
-       runtime·racereleasemergeg(g, addr);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racereleasemergeg(G *gp, void *addr)
-{
-       if(g->raceignore || !isvalidaddr((uintptr)addr))
-               return;
-       runtime·racecall(__tsan_release_merge, gp->racectx, addr);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·racefingo(void)
-{
-       runtime·racecall(__tsan_finalizer_goroutine, g->racectx);
-}
-
-// func RaceAcquire(addr unsafe.Pointer)
-#pragma textflag NOSPLIT
-void
-runtime·RaceAcquire(void *addr)
-{
-       runtime·raceacquire(addr);
-}
-
-// func RaceRelease(addr unsafe.Pointer)
-#pragma textflag NOSPLIT
-void
-runtime·RaceRelease(void *addr)
-{
-       runtime·racerelease(addr);
-}
-
-// func RaceReleaseMerge(addr unsafe.Pointer)
-#pragma textflag NOSPLIT
-void
-runtime·RaceReleaseMerge(void *addr)
-{
-       runtime·racereleasemerge(addr);
-}
-
-// func RaceDisable()
-#pragma textflag NOSPLIT
-void
-runtime·RaceDisable(void)
-{
-       if(g->raceignore++ == 0)
-               runtime·racecall(__tsan_go_ignore_sync_begin, g->racectx);
-}
-
-// func RaceEnable()
-#pragma textflag NOSPLIT
-void
-runtime·RaceEnable(void)
-{
-       if(--g->raceignore == 0)
-               runtime·racecall(__tsan_go_ignore_sync_end, g->racectx);
-}
index bb0ee6df65041b3bb3f0f8d05dcbcf91b29dbc0c..649cd7295c04e1e5174c4935a82c82248ac90854 100644 (file)
@@ -12,18 +12,6 @@ import (
        "unsafe"
 )
 
-func racefini()
-
-// RaceDisable disables handling of race events in the current goroutine.
-func RaceDisable()
-
-// RaceEnable re-enables handling of race events in the current goroutine.
-func RaceEnable()
-
-func RaceAcquire(addr unsafe.Pointer)
-func RaceRelease(addr unsafe.Pointer)
-func RaceReleaseMerge(addr unsafe.Pointer)
-
 func RaceRead(addr unsafe.Pointer)
 func RaceWrite(addr unsafe.Pointer)
 func RaceReadRange(addr unsafe.Pointer, len int)
@@ -67,32 +55,6 @@ func racereadpc(addr unsafe.Pointer, callpc, pc uintptr)
 //go:noescape
 func racewritepc(addr unsafe.Pointer, callpc, pc uintptr)
 
-//go:noescape
-func racereadrangepc(addr unsafe.Pointer, len uintptr, callpc, pc uintptr)
-
-//go:noescape
-func racewriterangepc(addr unsafe.Pointer, len uintptr, callpc, pc uintptr)
-
-//go:noescape
-func raceacquire(addr unsafe.Pointer)
-
-//go:noescape
-func racerelease(addr unsafe.Pointer)
-
-//go:noescape
-func raceacquireg(gp *g, addr unsafe.Pointer)
-
-//go:noescape
-func racereleaseg(gp *g, addr unsafe.Pointer)
-
-func racefingo()
-
-//go:noescape
-func racemalloc(p unsafe.Pointer, size uintptr)
-
-//go:noescape
-func racereleasemerge(addr unsafe.Pointer)
-
 type symbolizeContext struct {
        pc   uintptr
        fn   *byte
@@ -118,8 +80,8 @@ func racesymbolize(ctx *symbolizeContext) {
        }
 
        ctx.fn = funcname(f)
-       var file string
-       ctx.line = uintptr(funcline(f, ctx.pc, &file))
+       file, line := funcline(f, ctx.pc)
+       ctx.line = uintptr(line)
        ctx.file = &bytes(file)[0] // assume NUL-terminated
        ctx.off = ctx.pc - f.entry
        ctx.res = 1
diff --git a/src/runtime/race.h b/src/runtime/race.h
deleted file mode 100644 (file)
index fee31e0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// 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);
-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, void *callpc, void *pc);
-void   runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc);
-void   runtime·racereadobjectpc(void *addr, Type *t, void *callpc, void *pc);
-void   runtime·racewriteobjectpc(void *addr, Type *t, 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);
index 5d90cc859a246f3c6ecef5db2d5a722ff974c453..dadb6083fef0f2d55d9b444a1becf4bf89650a6e 100644 (file)
@@ -18,7 +18,7 @@ const raceenabled = false
 
 func raceReadObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr)  { gothrow("race") }
 func raceWriteObjectPC(t *_type, addr unsafe.Pointer, callerpc, pc uintptr) { gothrow("race") }
-func raceinit()                                                             { gothrow("race") }
+func raceinit() uintptr                                                     { gothrow("race"); return 0 }
 func racefini()                                                             { gothrow("race") }
 func racemapshadow(addr unsafe.Pointer, size uintptr)                       { gothrow("race") }
 func racewritepc(addr unsafe.Pointer, callerpc, pc uintptr)                 { gothrow("race") }
diff --git a/src/runtime/race1.go b/src/runtime/race1.go
new file mode 100644 (file)
index 0000000..2ec2bee
--- /dev/null
@@ -0,0 +1,335 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Implementation of the race detector API.
+// +build race
+
+package runtime
+
+import "unsafe"
+
+// Race runtime functions called via runtime·racecall.
+//go:linkname __tsan_init __tsan_init
+var __tsan_init byte
+
+//go:linkname __tsan_fini __tsan_fini
+var __tsan_fini byte
+
+//go:linkname __tsan_map_shadow __tsan_map_shadow
+var __tsan_map_shadow byte
+
+//go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine
+var __tsan_finalizer_goroutine byte
+
+//go:linkname __tsan_go_start __tsan_go_start
+var __tsan_go_start byte
+
+//go:linkname __tsan_go_end __tsan_go_end
+var __tsan_go_end byte
+
+//go:linkname __tsan_malloc __tsan_malloc
+var __tsan_malloc byte
+
+//go:linkname __tsan_acquire __tsan_acquire
+var __tsan_acquire byte
+
+//go:linkname __tsan_release __tsan_release
+var __tsan_release byte
+
+//go:linkname __tsan_release_merge __tsan_release_merge
+var __tsan_release_merge byte
+
+//go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin
+var __tsan_go_ignore_sync_begin byte
+
+//go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end
+var __tsan_go_ignore_sync_end byte
+
+// Mimic what cmd/cgo would do.
+//go:cgo_import_static __tsan_init
+//go:cgo_import_static __tsan_fini
+//go:cgo_import_static __tsan_map_shadow
+//go:cgo_import_static __tsan_finalizer_goroutine
+//go:cgo_import_static __tsan_go_start
+//go:cgo_import_static __tsan_go_end
+//go:cgo_import_static __tsan_malloc
+//go:cgo_import_static __tsan_acquire
+//go:cgo_import_static __tsan_release
+//go:cgo_import_static __tsan_release_merge
+//go:cgo_import_static __tsan_go_ignore_sync_begin
+//go:cgo_import_static __tsan_go_ignore_sync_end
+
+// These are called from race_amd64.s.
+//go:cgo_import_static __tsan_read
+//go:cgo_import_static __tsan_read_pc
+//go:cgo_import_static __tsan_read_range
+//go:cgo_import_static __tsan_write
+//go:cgo_import_static __tsan_write_pc
+//go:cgo_import_static __tsan_write_range
+//go:cgo_import_static __tsan_func_enter
+//go:cgo_import_static __tsan_func_exit
+
+//go:cgo_import_static __tsan_go_atomic32_load
+//go:cgo_import_static __tsan_go_atomic64_load
+//go:cgo_import_static __tsan_go_atomic32_store
+//go:cgo_import_static __tsan_go_atomic64_store
+//go:cgo_import_static __tsan_go_atomic32_exchange
+//go:cgo_import_static __tsan_go_atomic64_exchange
+//go:cgo_import_static __tsan_go_atomic32_fetch_add
+//go:cgo_import_static __tsan_go_atomic64_fetch_add
+//go:cgo_import_static __tsan_go_atomic32_compare_exchange
+//go:cgo_import_static __tsan_go_atomic64_compare_exchange
+
+// start/end of global data (data+bss).
+var racedatastart uintptr
+var racedataend uintptr
+
+// start/end of heap for race_amd64.s
+var racearenastart uintptr
+var racearenaend uintptr
+
+func racefuncenter(uintptr)
+func racefuncexit()
+func racereadrangepc1(uintptr, uintptr, uintptr)
+func racewriterangepc1(uintptr, uintptr, uintptr)
+func racesymbolizethunk(uintptr)
+
+// racecall allows calling an arbitrary function f from C race runtime
+// with up to 4 uintptr arguments.
+func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
+
+// checks if the address has shadow (i.e. heap or data/bss)
+//go:nosplit
+func isvalidaddr(addr unsafe.Pointer) bool {
+       return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
+               racedatastart <= uintptr(addr) && uintptr(addr) < racedataend
+}
+
+//go:nosplit
+func raceinit() uintptr {
+       // cgo is required to initialize libc, which is used by race runtime
+       if !iscgo {
+               gothrow("raceinit: race build must use cgo")
+       }
+
+       var racectx uintptr
+       racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
+
+       // Round data segment to page boundaries, because it's used in mmap().
+       start := ^uintptr(0)
+       end := uintptr(0)
+       if start > uintptr(unsafe.Pointer(&noptrdata)) {
+               start = uintptr(unsafe.Pointer(&noptrdata))
+       }
+       if start > uintptr(unsafe.Pointer(&data)) {
+               start = uintptr(unsafe.Pointer(&data))
+       }
+       if start > uintptr(unsafe.Pointer(&noptrbss)) {
+               start = uintptr(unsafe.Pointer(&noptrbss))
+       }
+       if start > uintptr(unsafe.Pointer(&bss)) {
+               start = uintptr(unsafe.Pointer(&bss))
+       }
+       if end < uintptr(unsafe.Pointer(&enoptrdata)) {
+               end = uintptr(unsafe.Pointer(&enoptrdata))
+       }
+       if end < uintptr(unsafe.Pointer(&edata)) {
+               end = uintptr(unsafe.Pointer(&edata))
+       }
+       if end < uintptr(unsafe.Pointer(&enoptrbss)) {
+               end = uintptr(unsafe.Pointer(&enoptrbss))
+       }
+       if end < uintptr(unsafe.Pointer(&ebss)) {
+               end = uintptr(unsafe.Pointer(&ebss))
+       }
+       size := round(end-start, _PageSize)
+       racecall(&__tsan_map_shadow, start, size, 0, 0)
+       racedatastart = start
+       racedataend = start + size
+
+       return racectx
+}
+
+//go:nosplit
+func racefini() {
+       racecall(&__tsan_fini, 0, 0, 0, 0)
+}
+
+//go:nosplit
+func racemapshadow(addr unsafe.Pointer, size uintptr) {
+       if racearenastart == 0 {
+               racearenastart = uintptr(addr)
+       }
+       if racearenaend < uintptr(addr)+size {
+               racearenaend = uintptr(addr) + size
+       }
+       racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0)
+}
+
+//go:nosplit
+func racemalloc(p unsafe.Pointer, sz uintptr) {
+       racecall(&__tsan_malloc, uintptr(p), sz, 0, 0)
+}
+
+//go:nosplit
+func racegostart(pc uintptr) uintptr {
+       _g_ := getg()
+       var spawng *g
+       if _g_.m.curg != nil {
+               spawng = _g_.m.curg
+       } else {
+               spawng = _g_
+       }
+
+       var racectx uintptr
+       racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0)
+       return racectx
+}
+
+//go:nosplit
+func racegoend() {
+       racecall(&__tsan_go_end, getg().racectx, 0, 0, 0)
+}
+
+//go:nosplit
+func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
+       _g_ := getg()
+       if _g_ != _g_.m.curg {
+               // The call is coming from manual instrumentation of Go code running on g0/gsignal.
+               // Not interesting.
+               return
+       }
+       if callpc != 0 {
+               racefuncenter(callpc)
+       }
+       racewriterangepc1(uintptr(addr), sz, pc)
+       if callpc != 0 {
+               racefuncexit()
+       }
+}
+
+//go:nosplit
+func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
+       _g_ := getg()
+       if _g_ != _g_.m.curg {
+               // The call is coming from manual instrumentation of Go code running on g0/gsignal.
+               // Not interesting.
+               return
+       }
+       if callpc != 0 {
+               racefuncenter(callpc)
+       }
+       racereadrangepc1(uintptr(addr), sz, pc)
+       if callpc != 0 {
+               racefuncexit()
+       }
+}
+
+//go:nosplit
+func racewriteobjectpc(addr unsafe.Pointer, t *_type, callpc, pc uintptr) {
+       kind := t.kind & _KindMask
+       if kind == _KindArray || kind == _KindStruct {
+               racewriterangepc(addr, t.size, callpc, pc)
+       } else {
+               racewritepc(addr, callpc, pc)
+       }
+}
+
+//go:nosplit
+func racereadobjectpc(addr unsafe.Pointer, t *_type, callpc, pc uintptr) {
+       kind := t.kind & _KindMask
+       if kind == _KindArray || kind == _KindStruct {
+               racereadrangepc(addr, t.size, callpc, pc)
+       } else {
+               racereadpc(addr, callpc, pc)
+       }
+}
+
+//go:nosplit
+func raceacquire(addr unsafe.Pointer) {
+       raceacquireg(getg(), addr)
+}
+
+//go:nosplit
+func raceacquireg(gp *g, addr unsafe.Pointer) {
+       if getg().raceignore != 0 || !isvalidaddr(addr) {
+               return
+       }
+       racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0)
+}
+
+//go:nosplit
+func racerelease(addr unsafe.Pointer) {
+       _g_ := getg()
+       if _g_.raceignore != 0 || !isvalidaddr(addr) {
+               return
+       }
+       racereleaseg(_g_, addr)
+}
+
+//go:nosplit
+func racereleaseg(gp *g, addr unsafe.Pointer) {
+       if getg().raceignore != 0 || !isvalidaddr(addr) {
+               return
+       }
+       racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0)
+}
+
+//go:nosplit
+func racereleasemerge(addr unsafe.Pointer) {
+       racereleasemergeg(getg(), addr)
+}
+
+//go:nosplit
+func racereleasemergeg(gp *g, addr unsafe.Pointer) {
+       if getg().raceignore != 0 || !isvalidaddr(addr) {
+               return
+       }
+       racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0)
+}
+
+//go:nosplit
+func racefingo() {
+       racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0)
+}
+
+//go:nosplit
+
+func RaceAcquire(addr unsafe.Pointer) {
+       raceacquire(addr)
+}
+
+//go:nosplit
+
+func RaceRelease(addr unsafe.Pointer) {
+       racerelease(addr)
+}
+
+//go:nosplit
+
+func RaceReleaseMerge(addr unsafe.Pointer) {
+       racereleasemerge(addr)
+}
+
+//go:nosplit
+
+// RaceEnable re-enables handling of race events in the current goroutine.
+func RaceDisable() {
+       _g_ := getg()
+       if _g_.raceignore == 0 {
+               racecall(&__tsan_go_ignore_sync_begin, _g_.racectx, 0, 0, 0)
+       }
+       _g_.raceignore++
+}
+
+//go:nosplit
+
+// RaceDisable disables handling of race events in the current goroutine.
+func RaceEnable() {
+       _g_ := getg()
+       _g_.raceignore--
+       if _g_.raceignore == 0 {
+               racecall(&__tsan_go_ignore_sync_end, _g_.racectx, 0, 0, 0)
+       }
+}
index a96d9de123fab8bf9a9ffa3f30d79b29e310df53..d54d9798f032ccc6c2f8043e3ab9c6d87f008a07 100644 (file)
@@ -4,7 +4,8 @@
 
 // +build race
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
@@ -140,18 +141,18 @@ TEXT      racecalladdr<>(SB), NOSPLIT, $0-0
        MOVQ    g_racectx(R14), RARG0   // goroutine context
        // Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
        CMPQ    RARG1, runtime·racearenastart(SB)
-       JB      racecalladdr_data
+       JB      data
        CMPQ    RARG1, runtime·racearenaend(SB)
-       JB      racecalladdr_call
-racecalladdr_data:
+       JB      call
+data:
        CMPQ    RARG1, runtime·racedatastart(SB)
-       JB      racecalladdr_ret
+       JB      ret
        CMPQ    RARG1, runtime·racedataend(SB)
-       JAE     racecalladdr_ret
-racecalladdr_call:
+       JAE     ret
+call:
        MOVQ    AX, AX          // w/o this 6a miscompiles this function
        JMP     racecall<>(SB)
-racecalladdr_ret:
+ret:
        RET
 
 // func runtime·racefuncenter(pc uintptr)
@@ -366,9 +367,9 @@ TEXT        racecall<>(SB), NOSPLIT, $0-0
        MOVQ    SP, R12         // callee-saved, preserved across the CALL
        MOVQ    m_g0(R13), R10
        CMPQ    R10, R14
-       JE      racecall_cont   // already on g0
+       JE      call    // already on g0
        MOVQ    (g_sched+gobuf_sp)(R10), SP
-racecall_cont:
+call:
        ANDQ    $~15, SP        // alignment for gcc ABI
        CALL    AX
        MOVQ    R12, SP
index e5e691122c63a15a2033083da3b57611e4f66052..f2766d7937e10120d99852723ec95e0eb75d2c44 100644 (file)
@@ -10,15 +10,6 @@ func setMaxStack(in int) (out int) {
        return out
 }
 
-func setGCPercent(in int32) (out int32) {
-       mp := acquirem()
-       mp.scalararg[0] = uintptr(int(in))
-       onM(setgcpercent_m)
-       out = int32(int(mp.scalararg[0]))
-       releasem(mp)
-       return out
-}
-
 func setPanicOnFault(new bool) (old bool) {
        mp := acquirem()
        old = mp.curg.paniconfault
@@ -26,12 +17,3 @@ func setPanicOnFault(new bool) (old bool) {
        releasem(mp)
        return old
 }
-
-func setMaxThreads(in int) (out int) {
-       mp := acquirem()
-       mp.scalararg[0] = uintptr(in)
-       onM(setmaxthreads_m)
-       out = int(mp.scalararg[0])
-       releasem(mp)
-       return out
-}
diff --git a/src/runtime/rt0_linux_power64.s b/src/runtime/rt0_linux_power64.s
new file mode 100644 (file)
index 0000000..970b6a6
--- /dev/null
@@ -0,0 +1,17 @@
+#include "textflag.h"
+
+// actually a function descriptor for _main<>(SB)
+TEXT _rt0_power64_linux(SB),NOSPLIT,$0
+       DWORD $_main<>(SB)
+       DWORD $0
+       DWORD $0
+
+TEXT _main<>(SB),NOSPLIT,$-8
+       MOVD 0(R1), R3 // argc
+       ADD $8, R1, R4 // argv
+       BR main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+       MOVD    $runtime·rt0_go(SB), R31
+       MOVD    R31, CTR
+       BR      (CTR)
diff --git a/src/runtime/rt0_linux_power64le.s b/src/runtime/rt0_linux_power64le.s
new file mode 100644 (file)
index 0000000..85ce847
--- /dev/null
@@ -0,0 +1,14 @@
+#include "textflag.h"
+
+TEXT _rt0_power64le_linux(SB),NOSPLIT,$0
+       BR _main<>(SB)
+
+TEXT _main<>(SB),NOSPLIT,$-8
+       MOVD 0(R1), R3 // argc
+       ADD $8, R1, R4 // argv
+       BR main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+       MOVD    $runtime·rt0_go(SB), R31
+       MOVD    R31, CTR
+       BR      (CTR)
index 197f52e113b4312040c629432b38f95de148325c..df956ba36ee47292b2e06ffe1515f72e16577845 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 TEXT _rt0_amd64_windows(SB),NOSPLIT,$-8
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
deleted file mode 100644 (file)
index c823691..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "stack.h"
-#include "arch_GOARCH.h"
-#include "textflag.h"
-#include "malloc.h"
-
-// Keep a cached value to make gotraceback fast,
-// since we call it on every call to gentraceback.
-// The cached value is a uint32 in which the low bit
-// is the "crash" setting and the top 31 bits are the
-// gotraceback value.
-static uint32 traceback_cache = 2<<1;
-
-// The GOTRACEBACK environment variable controls the
-// behavior of a Go program that is crashing and exiting.
-//     GOTRACEBACK=0   suppress all tracebacks
-//     GOTRACEBACK=1   default behavior - show tracebacks but exclude runtime frames
-//     GOTRACEBACK=2   show tracebacks including runtime frames
-//     GOTRACEBACK=crash   show tracebacks including runtime frames, then crash (core dump etc)
-#pragma textflag NOSPLIT
-int32
-runtime·gotraceback(bool *crash)
-{
-       if(crash != nil)
-               *crash = false;
-       if(g->m->traceback != 0)
-               return g->m->traceback;
-       if(crash != nil)
-               *crash = traceback_cache&1;
-       return traceback_cache>>1;
-}
-
-int32
-runtime·mcmp(byte *s1, byte *s2, uintptr n)
-{
-       uintptr i;
-       byte c1, c2;
-
-       for(i=0; i<n; i++) {
-               c1 = s1[i];
-               c2 = s2[i];
-               if(c1 < c2)
-                       return -1;
-               if(c1 > c2)
-                       return +1;
-       }
-       return 0;
-}
-
-
-byte*
-runtime·mchr(byte *p, byte c, byte *ep)
-{
-       for(; p < ep; p++)
-               if(*p == c)
-                       return p;
-       return nil;
-}
-
-static int32   argc;
-
-#pragma dataflag NOPTR /* argv not a heap pointer */
-static uint8** argv;
-
-extern Slice runtime·argslice;
-extern Slice runtime·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;
-int32 runtime·issolaris;
-int32 runtime·iswindows;
-
-// Information about what cpu features are available.
-// Set on startup in asm_{x86/amd64}.s.
-uint32 runtime·cpuid_ecx;
-uint32 runtime·cpuid_edx;
-
-void
-runtime·goargs(void)
-{
-       String *s;
-       int32 i;
-
-       // for windows implementation see "os" package
-       if(Windows)
-               return;
-
-       runtime·argslice = runtime·makeStringSlice(argc);
-       s = (String*)runtime·argslice.array;
-       for(i=0; i<argc; i++)
-               s[i] = runtime·gostringnocopy(argv[i]);
-}
-
-void
-runtime·goenvs_unix(void)
-{
-       String *s;
-       int32 i, n;
-
-       for(n=0; argv[argc+1+n] != 0; n++)
-               ;
-
-       runtime·envs = runtime·makeStringSlice(n);
-       s = (String*)runtime·envs.array;
-       for(i=0; i<n; i++)
-               s[i] = runtime·gostringnocopy(argv[argc+1+i]);
-}
-
-#pragma textflag NOSPLIT
-Slice
-runtime·environ()
-{
-       return runtime·envs;
-}
-
-int32
-runtime·atoi(byte *p)
-{
-       int32 n;
-
-       n = 0;
-       while('0' <= *p && *p <= '9')
-               n = n*10 + *p++ - '0';
-       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 != 0)
-               runtime·throw("cas64 failed");
-       x64 = 42;
-       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");
-       if(runtime·xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2)
-               runtime·throw("xchg64 failed");
-       if(runtime·atomicload64(&z64) != (3ull<<40)+3)
-               runtime·throw("xchg64 failed");
-}
-
-void
-runtime·check(void)
-{
-       int8 a;
-       uint8 b;
-       int16 c;
-       uint16 d;
-       int32 e;
-       uint32 f;
-       int64 g;
-       uint64 h;
-       float32 i, i1;
-       float64 j, j1;
-       byte *k, *k1;
-       uint16* l;
-       struct x1 {
-               byte x;
-       };
-       struct y1 {
-               struct x1 x1;
-               byte y;
-       };
-
-       if(sizeof(a) != 1) runtime·throw("bad a");
-       if(sizeof(b) != 1) runtime·throw("bad b");
-       if(sizeof(c) != 2) runtime·throw("bad c");
-       if(sizeof(d) != 2) runtime·throw("bad d");
-       if(sizeof(e) != 4) runtime·throw("bad e");
-       if(sizeof(f) != 4) runtime·throw("bad f");
-       if(sizeof(g) != 8) runtime·throw("bad g");
-       if(sizeof(h) != 8) runtime·throw("bad h");
-       if(sizeof(i) != 4) runtime·throw("bad i");
-       if(sizeof(j) != 8) runtime·throw("bad j");
-       if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k");
-       if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l");
-       if(sizeof(struct x1) != 1) runtime·throw("bad sizeof x1");
-       if(offsetof(struct y1, y) != 1) runtime·throw("bad offsetof y1.y");
-       if(sizeof(struct y1) != 2) runtime·throw("bad sizeof y1");
-
-       if(runtime·timediv(12345LL*1000000000+54321, 1000000000, &e) != 12345 || e != 54321)
-               runtime·throw("bad timediv");
-
-       uint32 z;
-       z = 1;
-       if(!runtime·cas(&z, 1, 2))
-               runtime·throw("cas1");
-       if(z != 2)
-               runtime·throw("cas2");
-
-       z = 4;
-       if(runtime·cas(&z, 5, 6))
-               runtime·throw("cas3");
-       if(z != 4)
-               runtime·throw("cas4");
-
-       k = (byte*)0xfedcb123;
-       if(sizeof(void*) == 8)
-               k = (byte*)((uintptr)k<<10);
-       if(runtime·casp((void**)&k, nil, nil))
-               runtime·throw("casp1");
-       k1 = k+1;
-       if(!runtime·casp((void**)&k, k, k1))
-               runtime·throw("casp2");
-       if(k != k1)
-               runtime·throw("casp3");
-
-       *(uint64*)&j = ~0ULL;
-       if(j == j)
-               runtime·throw("float64nan");
-       if(!(j != j))
-               runtime·throw("float64nan1");
-
-       *(uint64*)&j1 = ~1ULL;
-       if(j == j1)
-               runtime·throw("float64nan2");
-       if(!(j != j1))
-               runtime·throw("float64nan3");
-
-       *(uint32*)&i = ~0UL;
-       if(i == i)
-               runtime·throw("float32nan");
-       if(!(i != i))
-               runtime·throw("float32nan1");
-
-       *(uint32*)&i1 = ~1UL;
-       if(i == i1)
-               runtime·throw("float32nan2");
-       if(!(i != i1))
-               runtime·throw("float32nan3");
-
-       TestAtomic64();
-
-       if(FixedStack != runtime·round2(FixedStack))
-               runtime·throw("FixedStack is not power-of-2");
-}
-
-#pragma dataflag NOPTR
-DebugVars      runtime·debug;
-
-typedef struct DbgVar DbgVar;
-struct DbgVar
-{
-       int8*   name;
-       int32*  value;
-};
-
-// Do we report invalid pointers found during stack or heap scans?
-int32 runtime·invalidptr = 1;
-
-#pragma dataflag NOPTR /* dbgvar has no heap pointers */
-static DbgVar dbgvar[] = {
-       {"allocfreetrace", &runtime·debug.allocfreetrace},
-       {"invalidptr", &runtime·invalidptr},
-       {"efence", &runtime·debug.efence},
-       {"gctrace", &runtime·debug.gctrace},
-       {"gcdead", &runtime·debug.gcdead},
-       {"scheddetail", &runtime·debug.scheddetail},
-       {"schedtrace", &runtime·debug.schedtrace},
-       {"scavenge", &runtime·debug.scavenge},
-};
-
-void
-runtime·parsedebugvars(void)
-{
-       byte *p;
-       intgo i, n;
-
-       p = runtime·getenv("GODEBUG");
-       if(p != nil){
-               for(;;) {
-                       for(i=0; i<nelem(dbgvar); i++) {
-                               n = runtime·findnull((byte*)dbgvar[i].name);
-                               if(runtime·mcmp(p, (byte*)dbgvar[i].name, n) == 0 && p[n] == '=')
-                                       *dbgvar[i].value = runtime·atoi(p+n+1);
-                       }
-                       p = runtime·strstr(p, (byte*)",");
-                       if(p == nil)
-                               break;
-                       p++;
-               }
-       }
-
-       p = runtime·getenv("GOTRACEBACK");
-       if(p == nil)
-               p = (byte*)"";
-       if(p[0] == '\0')
-               traceback_cache = 1<<1;
-       else if(runtime·strcmp(p, (byte*)"crash") == 0)
-               traceback_cache = (2<<1) | 1;
-       else
-               traceback_cache = runtime·atoi(p)<<1;  
-}
-
-// Poor mans 64-bit division.
-// This is a very special function, do not use it if you are not sure what you are doing.
-// int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
-// Handles overflow in a time-specific manner.
-#pragma textflag NOSPLIT
-int32
-runtime·timediv(int64 v, int32 div, int32 *rem)
-{
-       int32 res, bit;
-
-       res = 0;
-       for(bit = 30; bit >= 0; bit--) {
-               if(v >= ((int64)div<<bit)) {
-                       v = v - ((int64)div<<bit);
-                       res += 1<<bit;
-               }
-       }
-       if(v >= (int64)div) {
-               if(rem != nil)
-                       *rem = 0;
-               return 0x7fffffff;
-       }
-       if(rem != nil)
-               *rem = v;
-       return res;
-}
-
-// Helpers for Go. Must be NOSPLIT, must only call NOSPLIT functions, and must not block.
-
-#pragma textflag NOSPLIT
-G*
-runtime·getg(void)
-{
-       return g;
-}
-
-#pragma textflag NOSPLIT
-M*
-runtime·acquirem(void)
-{
-       g->m->locks++;
-       return g->m;
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·releasem(M *mp)
-{
-       mp->locks--;
-       if(mp->locks == 0 && g->preempt) {
-               // restore the preemption request in case we've cleared it in newstack
-               g->stackguard0 = StackPreempt;
-       }
-}
-
-#pragma textflag NOSPLIT
-MCache*
-runtime·gomcache(void)
-{
-       return g->m->mcache;
-}
-
-#pragma textflag NOSPLIT
-Slice
-reflect·typelinks(void)
-{
-       extern Type *runtime·typelink[], *runtime·etypelink[];
-       Slice ret;
-
-       ret.array = (byte*)runtime·typelink;
-       ret.len = runtime·etypelink - runtime·typelink;
-       ret.cap = ret.len;
-       return ret;
-}
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
deleted file mode 100644 (file)
index 977c454..0000000
+++ /dev/null
@@ -1,1130 +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.
-
-/*
- * basic types
- */
-typedef        signed char             int8;
-typedef        unsigned char           uint8;
-typedef        signed short            int16;
-typedef        unsigned short          uint16;
-typedef        signed int              int32;
-typedef        unsigned int            uint32;
-typedef        signed long long int    int64;
-typedef        unsigned long long int  uint64;
-typedef        float                   float32;
-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           intgo; // Go's int
-typedef        uint32          uintgo; // Go's uint
-#endif
-
-#ifdef _64BITREG
-typedef        uint64          uintreg;
-#else
-typedef        uint32          uintreg;
-#endif
-
-/*
- * get rid of C types
- * the / / / forces a syntax error immediately,
- * which will show "last name: XXunsigned".
- */
-#define        unsigned                XXunsigned / / /
-#define        signed                  XXsigned / / /
-#define        char                    XXchar / / /
-#define        short                   XXshort / / /
-#define        int                     XXint / / /
-#define        long                    XXlong / / /
-#define        float                   XXfloat / / /
-#define        double                  XXdouble / / /
-
-/*
- * defined types
- */
-typedef        uint8                   bool;
-typedef        uint8                   byte;
-typedef        struct  Func            Func;
-typedef        struct  G               G;
-typedef        struct  Gobuf           Gobuf;
-typedef        struct  SudoG           SudoG;
-typedef        struct  Mutex           Mutex;
-typedef        struct  M               M;
-typedef        struct  P               P;
-typedef        struct  SchedT  SchedT;
-typedef        struct  Note            Note;
-typedef        struct  Slice           Slice;
-typedef        struct  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  PtrType         PtrType;
-typedef        struct  ChanType        ChanType;
-typedef        struct  MapType         MapType;
-typedef        struct  Defer           Defer;
-typedef        struct  Panic           Panic;
-typedef        struct  Hmap            Hmap;
-typedef        struct  Hiter           Hiter;
-typedef        struct  Hchan           Hchan;
-typedef        struct  Complex64       Complex64;
-typedef        struct  Complex128      Complex128;
-typedef        struct  LibCall         LibCall;
-typedef        struct  WinCallbackContext      WinCallbackContext;
-typedef        struct  GCStats         GCStats;
-typedef        struct  LFNode          LFNode;
-typedef        struct  ParFor          ParFor;
-typedef        struct  ParForThread    ParForThread;
-typedef        struct  CgoMal          CgoMal;
-typedef        struct  PollDesc        PollDesc;
-typedef        struct  DebugVars       DebugVars;
-typedef        struct  ForceGCState    ForceGCState;
-typedef        struct  Stack           Stack;
-
-/*
- * Per-CPU declaration.
- *
- * "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 pseudo-register TLS. See zasmhdr in
- * src/cmd/dist/buildruntime.c for details, and be aware that the linker may
- * make further OS-specific changes to the compiler's output. For example,
- * 6l/linux rewrites 0(TLS) as -8(FS).
- *
- * Every C file linked into a Go program must include runtime.h so that the
- * C compiler (6c, 8c, etc.) knows to avoid other uses of these dedicated
- * registers. The Go compiler (6g, 8g, etc.) knows to avoid them.
- */
-extern register        G*      g;
-
-/*
- * defined constants
- */
-enum
-{
-       // G status
-       //
-       // If you add to this list, add to the list
-       // of "okay during garbage collection" status
-       // in mgc0.c too.
-       Gidle,                                 // 0
-       Grunnable,                             // 1 runnable and on a run queue
-       Grunning,                              // 2
-       Gsyscall,                              // 3
-       Gwaiting,                              // 4
-       Gmoribund_unused,                      // 5 currently unused, but hardcoded in gdb scripts
-       Gdead,                                 // 6
-       Genqueue,                              // 7 Only the Gscanenqueue is used.
-       Gcopystack,                            // 8 in this state when newstack is moving the stack
-       // the following encode that the GC is scanning the stack and what to do when it is done 
-       Gscan = 0x1000,                        // atomicstatus&~Gscan = the non-scan state,
-       // Gscanidle =     Gscan + Gidle,      // Not used. Gidle only used with newly malloced gs
-       Gscanrunnable = Gscan + Grunnable,     //  0x1001 When scanning complets make Grunnable (it is already on run queue)
-       Gscanrunning =  Gscan + Grunning,      //  0x1002 Used to tell preemption newstack routine to scan preempted stack.
-       Gscansyscall =  Gscan + Gsyscall,      //  0x1003 When scanning completes make is Gsyscall
-       Gscanwaiting =  Gscan + Gwaiting,      //  0x1004 When scanning completes make it Gwaiting
-       // Gscanmoribund_unused,               //  not possible
-       // Gscandead,                          //  not possible
-       Gscanenqueue = Gscan + Genqueue,       //  When scanning completes make it Grunnable and put on runqueue
-};
-enum
-{
-       // P status
-       Pidle,
-       Prunning,
-       Psyscall,
-       Pgcstop,
-       Pdead,
-};
-enum
-{
-       true    = 1,
-       false   = 0,
-};
-enum
-{
-       PtrSize = sizeof(void*),
-};
-/*
- * structures
- */
-struct Mutex
-{
-       // Futex-based impl treats it as uint32 key,
-       // while sema-based impl as M* waitm.
-       // Used to be a union, but unions break precise GC.
-       uintptr key;
-};
-struct Note
-{
-       // Futex-based impl treats it as uint32 key,
-       // while sema-based impl as M* waitm.
-       // Used to be a union, but unions break precise GC.
-       uintptr key;
-};
-struct String
-{
-       byte*   str;
-       intgo   len;
-};
-struct FuncVal
-{
-       void    (*fn)(void);
-       // variable-size, fn-specific data here
-};
-struct Iface
-{
-       Itab*   tab;
-       void*   data;
-};
-struct Eface
-{
-       Type*   type;
-       void*   data;
-};
-struct Complex64
-{
-       float32 real;
-       float32 imag;
-};
-struct Complex128
-{
-       float64 real;
-       float64 imag;
-};
-
-struct Slice
-{                              // must not move anything
-       byte*   array;          // actual data
-       uintgo  len;            // number of elements
-       uintgo  cap;            // allocated number of elements
-};
-struct Gobuf
-{
-       // The offsets of sp, pc, and g are known to (hard-coded in) libmach.
-       uintptr sp;
-       uintptr pc;
-       G*      g;
-       void*   ctxt; // this has to be a pointer so that GC scans it
-       uintreg ret;
-       uintptr lr;
-};
-// Known to compiler.
-// Changes here must also be made in src/cmd/gc/select.c's selecttype.
-struct SudoG
-{
-       G*      g;
-       uint32* selectdone;
-       SudoG*  next;
-       SudoG*  prev;
-       void*   elem;           // data element
-       int64   releasetime;
-       int32   nrelease;       // -1 for acquire
-       SudoG*  waitlink;       // G.waiting list
-};
-struct GCStats
-{
-       // the struct must consist of only uint64's,
-       // because it is casted to uint64[].
-       uint64  nhandoff;
-       uint64  nhandoffcnt;
-       uint64  nprocyield;
-       uint64  nosyield;
-       uint64  nsleep;
-};
-
-struct LibCall
-{
-       uintptr fn;
-       uintptr n;      // number of parameters
-       uintptr args;   // parameters
-       uintptr r1;     // return values
-       uintptr r2;
-       uintptr err;    // error number
-};
-
-// describes how to handle callback
-struct WinCallbackContext
-{
-       void*   gobody;         // Go function to call
-       uintptr argsize;        // callback arguments size (in bytes)
-       uintptr restorestack;   // adjust stack on return by (in bytes) (386 only)
-       bool    cleanstack;
-};
-
-// Stack describes a Go execution stack.
-// The bounds of the stack are exactly [lo, hi),
-// with no implicit data structures on either side.
-struct Stack
-{
-       uintptr lo;
-       uintptr hi;
-};
-
-struct G
-{
-       // Stack parameters.
-       // stack describes the actual stack memory: [stack.lo, stack.hi).
-       // stackguard0 is the stack pointer compared in the Go stack growth prologue.
-       // It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
-       // stackguard1 is the stack pointer compared in the C stack growth prologue.
-       // It is stack.lo+StackGuard on g0 and gsignal stacks.
-       // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
-       Stack   stack;  // offset known to runtime/cgo
-       uintptr stackguard0;    // offset known to liblink
-       uintptr stackguard1;    // offset known to liblink
-
-       Panic*  panic;  // innermost panic - offset known to liblink
-       Defer*  defer;  // innermost defer
-       Gobuf   sched;
-       uintptr syscallsp;      // if status==Gsyscall, syscallsp = sched.sp to use during gc
-       uintptr syscallpc;      // if status==Gsyscall, syscallpc = sched.pc to use during gc
-       void*   param;          // passed parameter on wakeup
-       uint32  atomicstatus;
-       int64   goid;
-       int64   waitsince;      // approx time when the G become blocked
-       String  waitreason;     // if status==Gwaiting
-       G*      schedlink;
-       bool    issystem;       // do not output in stack dump, ignore in deadlock detector
-       bool    preempt;        // preemption signal, duplicates stackguard0 = StackPreempt
-       bool    paniconfault;   // panic (instead of crash) on unexpected fault address
-       bool    preemptscan;    // preempted g does scan for GC
-       bool    gcworkdone;     // debug: cleared at begining of gc work phase cycle, set by gcphasework, tested at end of cycle
-       bool    throwsplit; // must not split stack
-       int8    raceignore;     // ignore race detection events
-       M*      m;              // for debuggers, but offset not hard-coded
-       M*      lockedm;
-       int32   sig;
-       Slice   writebuf;
-       uintptr sigcode0;
-       uintptr sigcode1;
-       uintptr sigpc;
-       uintptr gopc;           // pc of go statement that created this goroutine
-       uintptr racectx;
-       SudoG*  waiting;        // sudog structures this G is waiting on (that have a valid elem ptr)
-       uintptr end[];
-};
-
-struct M
-{
-       G*      g0;             // goroutine with scheduling stack
-       Gobuf   morebuf;        // gobuf arg to morestack
-
-       // Fields not known to debuggers.
-       uint64  procid;         // for debuggers, but offset not hard-coded
-       G*      gsignal;        // signal-handling G
-       uintptr tls[4];         // thread-local storage (for x86 extern register)
-       void    (*mstartfn)(void);
-       G*      curg;           // current running goroutine
-       G*      caughtsig;      // goroutine running during fatal signal
-       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   softfloat;
-       int32   dying;
-       int32   profilehz;
-       int32   helpgc;
-       bool    spinning;       // M is out of work and is actively looking for work
-       bool    blocked;        // M is blocked on a Note
-       uint32  fastrand;
-       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;
-       G*      lockedg;
-       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    needextram;
-       uint8   traceback;
-       bool    (*waitunlockf)(G*, void*);
-       void*   waitlock;
-       uintptr scalararg[4];   // scalar argument/return for mcall
-       void*   ptrarg[4];      // pointer argument/return for mcall
-#ifdef GOOS_windows
-       uintptr thread;         // thread handle
-       // these are here because they are too large to be on the stack
-       // of low-level NOSPLIT functions.
-       LibCall libcall;
-       uintptr libcallpc;      // for cpu profiler
-       uintptr libcallsp;
-       G*      libcallg;
-#endif
-#ifdef GOOS_solaris
-       int32*  perrno;         // pointer to TLS errno
-       // these are here because they are too large to be on the stack
-       // of low-level NOSPLIT functions.
-       LibCall libcall;
-       struct MTs {
-               int64   tv_sec;
-               int64   tv_nsec;
-       } ts;
-       struct MScratch {
-               uintptr v[6];
-       } scratch;
-#endif
-#ifdef GOOS_plan9
-       int8*   notesig;
-       byte*   errstr;
-#endif
-       uintptr end[];
-};
-
-struct P
-{
-       Mutex   lock;
-
-       int32   id;
-       uint32  status;         // one of Pidle/Prunning/...
-       P*      link;
-       uint32  schedtick;      // incremented on every scheduler call
-       uint32  syscalltick;    // incremented on every system call
-       M*      m;              // back-link to associated M (nil if idle)
-       MCache* mcache;
-       Defer*  deferpool[5];   // pool of available Defer structs of different sizes (see panic.c)
-
-       // Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen.
-       uint64  goidcache;
-       uint64  goidcacheend;
-
-       // Queue of runnable goroutines.
-       uint32  runqhead;
-       uint32  runqtail;
-       G*      runq[256];
-
-       // Available G's (status == Gdead)
-       G*      gfree;
-       int32   gfreecnt;
-
-       byte    pad[64];
-};
-
-enum {
-       // The max value of GOMAXPROCS.
-       // There are no fundamental restrictions on the value.
-       MaxGomaxprocs = 1<<8,
-};
-
-struct SchedT
-{
-       Mutex   lock;
-
-       uint64  goidgen;
-
-       M*      midle;   // idle m's waiting for work
-       int32   nmidle;  // number of idle m's waiting for work
-       int32   nmidlelocked; // number of locked m's waiting for work
-       int32   mcount;  // number of m's that have been created
-       int32   maxmcount;      // maximum number of m's allowed (or die)
-
-       P*      pidle;  // idle P's
-       uint32  npidle;
-       uint32  nmspinning;
-
-       // Global runnable queue.
-       G*      runqhead;
-       G*      runqtail;
-       int32   runqsize;
-
-       // Global cache of dead G's.
-       Mutex   gflock;
-       G*      gfree;
-       int32   ngfree;
-
-       uint32  gcwaiting;      // gc is waiting to run
-       int32   stopwait;
-       Note    stopnote;
-       uint32  sysmonwait;
-       Note    sysmonnote;
-       uint64  lastpoll;
-
-       int32   profilehz;      // cpu profiling rate
-};
-
-// The m->locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
-// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
-// External locks are not recursive; a second lock is silently ignored.
-// The upper bits of m->lockedcount record the nesting depth of calls to lockOSThread
-// (counting up by LockInternal), popped by unlockOSThread (counting down by LockInternal).
-// Internal locks can be recursive. For instance, a lock for cgo can occur while the main
-// goroutine is holding the lock during the initialization phase.
-enum
-{
-       LockExternal = 1,
-       LockInternal = 2,
-};
-
-struct SigTab
-{
-       int32   flags;
-       int8    *name;
-};
-enum
-{
-       SigNotify = 1<<0,       // let signal.Notify have signal, even if from kernel
-       SigKill = 1<<1,         // if signal.Notify doesn't take it, exit quietly
-       SigThrow = 1<<2,        // if signal.Notify doesn't take it, exit loudly
-       SigPanic = 1<<3,        // if the signal is from the kernel, panic
-       SigDefault = 1<<4,      // if the signal isn't explicitly requested, don't monitor it
-       SigHandling = 1<<5,     // our signal handler is registered
-       SigIgnored = 1<<6,      // the signal was ignored before we registered for it
-       SigGoExit = 1<<7,       // cause all runtime procs to exit (only used on Plan 9).
-};
-
-// Layout of in-memory per-function information prepared by linker
-// See http://golang.org/s/go12symtab.
-// Keep in sync with linker and with ../../libmach/sym.c
-// and with package debug/gosym and with symtab.go in package runtime.
-struct Func
-{
-       uintptr entry;  // start pc
-       int32   nameoff;// function name
-       
-       int32   args;   // in/out args size
-       int32   frame;  // legacy frame size; use pcsp if possible
-
-       int32   pcsp;
-       int32   pcfile;
-       int32   pcln;
-       int32   npcdata;
-       int32   nfuncdata;
-};
-
-// layout of Itab known to compilers
-// allocated in non-garbage-collected memory
-struct Itab
-{
-       InterfaceType*  inter;
-       Type*   type;
-       Itab*   link;
-       int32   bad;
-       int32   unused;
-       void    (*fun[])(void);
-};
-
-#ifdef GOOS_nacl
-enum {
-   NaCl = 1,
-};
-#else
-enum {
-   NaCl = 0,
-};
-#endif
-
-#ifdef GOOS_windows
-enum {
-   Windows = 1
-};
-#else
-enum {
-   Windows = 0
-};
-#endif
-#ifdef GOOS_solaris
-enum {
-   Solaris = 1
-};
-#else
-enum {
-   Solaris = 0
-};
-#endif
-#ifdef GOOS_plan9
-enum {
-   Plan9 = 1
-};
-#else
-enum {
-   Plan9 = 0
-};
-#endif
-
-// 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
-       uint32 pad;                     // to align ParForThread.pos for 64-bit atomic operations
-       // 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;
-       void    *alloc;
-};
-
-// Holds variables parsed from GODEBUG env var.
-struct DebugVars
-{
-       int32   allocfreetrace;
-       int32   efence;
-       int32   gctrace;
-       int32   gcdead;
-       int32   scheddetail;
-       int32   schedtrace;
-       int32   scavenge;
-};
-
-// Indicates to write barrier and sychronization task to preform.
-enum
-{                   // Synchronization            Write barrier
-       GCoff,      // stop and start             nop
-       GCquiesce,  // stop and start             nop
-       GCstw,      // stop the ps                nop
-       GCmark,     // scan the stacks and start  no white to black
-       GCsweep,    // stop and start             nop
-};
-
-struct ForceGCState
-{
-       Mutex   lock;
-       G*      g;
-       uint32  idle;
-};
-
-extern uint32 runtime·gcphase;
-
-/*
- * defined macros
- *    you need super-gopher-guru privilege
- *    to add this list.
- */
-#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)&~(uintptr)((n)-1)) /* all-caps to mark as macro: it evaluates n twice */
-
-/*
- * known to compiler
- */
-enum {
-       Structrnd = sizeof(uintreg),
-};
-
-byte*  runtime·startup_random_data;
-uint32 runtime·startup_random_data_len;
-
-int32  runtime·invalidptr;
-
-enum {
-       // hashinit wants this many random bytes
-       HashRandomBytes = 32
-};
-
-uint32  runtime·readgstatus(G*);
-void    runtime·casgstatus(G*, uint32, uint32);
-void    runtime·quiesce(G*);
-bool    runtime·stopg(G*);
-void    runtime·restartg(G*);
-void    runtime·gcphasework(G*);
-
-/*
- * deferred subroutine calls
- */
-struct Defer
-{
-       int32   siz;
-       bool    started;
-       uintptr argp;           // where args were copied from
-       uintptr pc;
-       FuncVal*        fn;
-       Panic*  panic;  // panic that is running defer
-       Defer*  link;
-};
-
-// argp used in Defer structs when there is no argp.
-#define NoArgs ((uintptr)-1)
-
-/*
- * panics
- */
-struct Panic
-{
-       void*   argp;   // pointer to arguments of deferred call run during panic; cannot move - known to liblink
-       Eface   arg;            // argument to panic
-       Panic*  link;           // link to earlier panic
-       bool    recovered;      // whether this panic is over
-       bool    aborted;        // the panic was aborted
-};
-
-/*
- * stack traces
- */
-typedef struct Stkframe Stkframe;
-typedef struct BitVector BitVector;
-struct Stkframe
-{
-       Func*   fn;     // function being run
-       uintptr pc;     // program counter within fn
-       uintptr continpc;       // program counter where execution can continue, or 0 if not
-       uintptr lr;     // program counter at caller aka link register
-       uintptr sp;     // stack pointer at pc
-       uintptr fp;     // stack pointer at caller aka frame pointer
-       uintptr varp;   // top of local variables
-       uintptr argp;   // pointer to function arguments
-       uintptr arglen; // number of bytes at argp
-       BitVector*      argmap; // force use of this argmap
-};
-
-enum
-{
-       TraceRuntimeFrames = 1<<0, // include frames for internal runtime functions.
-       TraceTrap = 1<<1, // the initial PC, SP are from a trap, not a return PC from a call
-};
-intgo  runtime·gentraceback(uintptr, uintptr, uintptr, G*, intgo, uintptr*, intgo, bool(**)(Stkframe*, void*), void*, uintgo);
-void   runtime·tracebackdefers(G*, bool(**)(Stkframe*, void*), void*);
-void   runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G* gp);
-void   runtime·tracebacktrap(uintptr pc, uintptr sp, uintptr lr, G* gp);
-void   runtime·tracebackothers(G*);
-bool   runtime·haszeroargs(uintptr pc);
-bool   runtime·topofstack(Func*);
-enum
-{
-       // The maximum number of frames we print for a traceback
-       TracebackMaxFrames = 100,
-};
-
-/*
- * external data
- */
-extern String  runtime·emptystring;
-extern G**     runtime·allg;
-extern Slice   runtime·allgs; // []*G
-extern uintptr runtime·allglen;
-extern G*      runtime·lastg;
-extern M*      runtime·allm;
-extern P*      runtime·allp[MaxGomaxprocs+1];
-extern int32   runtime·gomaxprocs;
-extern uint32  runtime·needextram;
-extern uint32  runtime·panicking;
-extern int8*   runtime·goos;
-extern int32   runtime·ncpu;
-extern bool    runtime·iscgo;
-extern         void    (*runtime·sysargs)(int32, uint8**);
-extern uintptr runtime·maxstring;
-extern uint32  runtime·cpuid_ecx;
-extern uint32  runtime·cpuid_edx;
-extern DebugVars       runtime·debug;
-extern uintptr runtime·maxstacksize;
-extern Note    runtime·signote;
-extern ForceGCState    runtime·forcegc;
-extern SchedT  runtime·sched;
-extern int32           runtime·newprocs;
-
-/*
- * common functions and data
- */
-int32  runtime·strcmp(byte*, byte*);
-int32  runtime·strncmp(byte*, byte*, uintptr);
-byte*  runtime·strstr(byte*, byte*);
-intgo  runtime·findnull(byte*);
-intgo  runtime·findnullw(uint16*);
-void   runtime·dump(byte*, int32);
-int32  runtime·runetochar(byte*, int32);
-int32  runtime·charntorune(int32*, uint8*, int32);
-
-
-/*
- * This macro is used when writing C functions
- * called as if they were Go functions.
- * Passed the address of a result before a return statement,
- * it makes sure the result has been flushed to memory
- * before the return.
- *
- * It is difficult to write such functions portably, because
- * of the varying requirements on the alignment of the
- * first output value. Almost all code should write such
- * functions in .goc files, where goc2c (part of cmd/dist)
- * can arrange the correct alignment for the target system.
- * Goc2c also takes care of conveying to the garbage collector
- * which parts of the argument list are inputs vs outputs.
- *
- * Therefore, do NOT use this macro if at all possible.
- */ 
-#define FLUSH(x)       USED(x)
-
-/*
- * GoOutput is a type with the same alignment requirements as the
- * initial output argument from a Go function. Only for use in cases
- * where using goc2c is not possible. See comment on FLUSH above.
- */
-typedef uint64 GoOutput;
-
-void   runtime·gogo(Gobuf*);
-void   runtime·gostartcall(Gobuf*, void(*)(void), void*);
-void   runtime·gostartcallfn(Gobuf*, FuncVal*);
-void   runtime·gosave(Gobuf*);
-void   runtime·goargs(void);
-void   runtime·goenvs(void);
-void   runtime·goenvs_unix(void);
-void*  runtime·getu(void);
-void   runtime·throw(int8*);
-bool   runtime·canpanic(G*);
-void   runtime·prints(int8*);
-void   runtime·printf(int8*, ...);
-void   runtime·snprintf(byte*, int32, int8*, ...);
-byte*  runtime·mchr(byte*, byte, byte*);
-int32  runtime·mcmp(byte*, byte*, uintptr);
-void   runtime·memmove(void*, void*, uintptr);
-String runtime·catstring(String, String);
-String runtime·gostring(byte*);
-Slice  runtime·makeStringSlice(intgo);
-String  runtime·gostringn(byte*, intgo);
-Slice  runtime·gobytes(byte*, intgo);
-String runtime·gostringnocopy(byte*);
-String runtime·gostringw(uint16*);
-void   runtime·initsig(void);
-void   runtime·sigenable(uint32 sig);
-void   runtime·sigdisable(uint32 sig);
-int32  runtime·gotraceback(bool *crash);
-void   runtime·goroutineheader(G*);
-int32  runtime·open(int8*, int32, int32);
-int32  runtime·read(int32, void*, int32);
-int32  runtime·write(uintptr, void*, int32); // use uintptr to accommodate windows.
-int32  runtime·close(int32);
-int32  runtime·mincore(void*, uintptr, byte*);
-void   runtime·jmpdefer(FuncVal*, uintptr);
-void   runtime·exit1(int32);
-void   runtime·ready(G*);
-byte*  runtime·getenv(int8*);
-int32  runtime·atoi(byte*);
-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);
-void   runtime·tracebackinit(void);
-void   runtime·symtabinit(void);
-Func*  runtime·findfunc(uintptr);
-int32  runtime·funcline(Func*, uintptr, String*);
-int32  runtime·funcspdelta(Func*, uintptr);
-int8*  runtime·funcname(Func*);
-int32  runtime·pcdatavalue(Func*, int32, uintptr);
-void   runtime·stackinit(void);
-Stack  runtime·stackalloc(uint32);
-void   runtime·stackfree(Stack);
-void   runtime·shrinkstack(G*);
-void   runtime·shrinkfinish(void);
-MCache*        runtime·allocmcache(void);
-void   runtime·freemcache(MCache*);
-void   runtime·mallocinit(void);
-void   runtime·gcinit(void);
-void*  runtime·mallocgc(uintptr size, Type* typ, uint32 flag);
-void   runtime·runpanic(Panic*);
-uintptr        runtime·getcallersp(void*);
-int32  runtime·mcount(void);
-int32  runtime·gcount(void);
-void   runtime·mcall(void(**)(G*));
-void   runtime·onM(void(**)(void));
-void   runtime·onMsignal(void(**)(void));
-uint32 runtime·fastrand1(void);
-void   runtime·rewindmorestack(Gobuf*);
-int32  runtime·timediv(int64, int32, int32*);
-int32  runtime·round2(int32 x); // round x up to a power of 2.
-
-// atomic operations
-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);
-uint64 runtime·xchg64(uint64 volatile*, uint64);
-void*  runtime·xchgp(void* volatile*, void*);
-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*);
-uintptr        runtime·atomicloaduintptr(uintptr volatile*);
-void   runtime·atomicstorep(void* volatile*, void*);
-void   runtime·atomicstoreuintptr(uintptr volatile*, uintptr);
-void   runtime·atomicor8(byte volatile*, byte);
-
-void   runtime·setg(G*);
-void   runtime·newextram(void);
-void   runtime·exit(int32);
-void   runtime·breakpoint(void);
-void   runtime·gosched_m(G*);
-void   runtime·schedtrace(bool);
-void   runtime·park(bool(*)(G*, void*), void*, String);
-void   runtime·parkunlock(Mutex*, String);
-void   runtime·tsleep(int64, String);
-M*     runtime·newm(void);
-void   runtime·goexit(void);
-void   runtime·asmcgocall(void (*fn)(void*), void*);
-int32  runtime·asmcgocall_errno(void (*fn)(void*), void*);
-void   runtime·entersyscall(void);
-void   runtime·reentersyscall(uintptr, uintptr);
-void   runtime·entersyscallblock(void);
-void   runtime·exitsyscall(void);
-G*     runtime·newproc1(FuncVal*, byte*, int32, int32, void*);
-bool   runtime·sigsend(int32 sig);
-intgo  runtime·callers(intgo, uintptr*, intgo);
-intgo  runtime·gcallers(G*, intgo, uintptr*, intgo);
-int64  runtime·nanotime(void);        // monotonic time
-int64  runtime·unixnanotime(void); // real time, can skip
-void   runtime·dopanic(int32);
-void   runtime·startpanic(void);
-void   runtime·freezetheworld(void);
-void   runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp);
-void   runtime·resetcpuprofiler(int32);
-void   runtime·setcpuprofilerate(int32);
-void   runtime·usleep(uint32);
-int64  runtime·cputicks(void);
-int64  runtime·tickspersecond(void);
-void   runtime·blockevent(int64, intgo);
-G*     runtime·netpoll(bool);
-void   runtime·netpollready(G**, PollDesc*, int32);
-uintptr        runtime·netpollfd(PollDesc*);
-void** runtime·netpolluser(PollDesc*);
-bool   runtime·netpollclosing(PollDesc*);
-void   runtime·netpolllock(PollDesc*);
-void   runtime·netpollunlock(PollDesc*);
-void   runtime·crash(void);
-void   runtime·parsedebugvars(void);
-void*  runtime·funcdata(Func*, int32);
-void   runtime·setmaxthreads_m(void);
-G*     runtime·timejump(void);
-void   runtime·iterate_itabs(void (**callback)(Itab*));
-void   runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*));
-
-#pragma        varargck        argpos  runtime·printf 1
-#pragma        varargck        type    "c"     int32
-#pragma        varargck        type    "d"     int32
-#pragma        varargck        type    "d"     uint32
-#pragma        varargck        type    "D"     int64
-#pragma        varargck        type    "D"     uint64
-#pragma        varargck        type    "x"     int32
-#pragma        varargck        type    "x"     uint32
-#pragma        varargck        type    "X"     int64
-#pragma        varargck        type    "X"     uint64
-#pragma        varargck        type    "p"     void*
-#pragma        varargck        type    "p"     uintptr
-#pragma        varargck        type    "s"     int8*
-#pragma        varargck        type    "s"     uint8*
-#pragma        varargck        type    "S"     String
-
-void   runtime·stoptheworld(void);
-void   runtime·starttheworld(void);
-extern uint32 runtime·worldsema;
-
-/*
- * mutual exclusion locks.  in the uncontended case,
- * as fast as spin locks (just a few user-level instructions),
- * but on the contention path they sleep in the kernel.
- * a zeroed Mutex is unlocked (no need to initialize each lock).
- */
-void   runtime·lock(Mutex*);
-void   runtime·unlock(Mutex*);
-
-/*
- * sleep and wakeup on one-time events.
- * before any calls to notesleep or notewakeup,
- * must call noteclear to initialize the Note.
- * then, exactly one thread can call notesleep
- * and exactly one thread can call notewakeup (once).
- * once notewakeup has been called, the notesleep
- * will return.  future notesleep will return immediately.
- * subsequent noteclear must be called only after
- * previous notesleep has returned, e.g. it's disallowed
- * to call noteclear straight after notewakeup.
- *
- * notetsleep is like notesleep but wakes up after
- * a given number of nanoseconds even if the event
- * has not yet happened.  if a goroutine uses notetsleep to
- * wake up early, it must wait to call noteclear until it
- * can be sure that no other goroutine is calling
- * notewakeup.
- *
- * notesleep/notetsleep are generally called on g0,
- * notetsleepg is similar to notetsleep but is called on user g.
- */
-void   runtime·noteclear(Note*);
-void   runtime·notesleep(Note*);
-void   runtime·notewakeup(Note*);
-bool   runtime·notetsleep(Note*, int64);  // false - timeout
-bool   runtime·notetsleepg(Note*, int64);  // false - timeout
-
-/*
- * low-level synchronization for implementing the above
- */
-uintptr        runtime·semacreate(void);
-int32  runtime·semasleep(int64);
-void   runtime·semawakeup(M*);
-// or
-void   runtime·futexsleep(uint32*, uint32, int64);
-void   runtime·futexwakeup(uint32*, uint32);
-
-/*
- * Mutex-free stack.
- * Initialize uint64 head to 0, compare with 0 to test for emptiness.
- * The stack does not keep pointers to nodes,
- * so they can be garbage collected if there are no other pointers to nodes.
- */
-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);
-void   runtime·parforiters(ParFor*, uintptr, uintptr*, uintptr*);
-
-/*
- * 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);
-void   runtime·memclr(byte*, uintptr);
-void   runtime·setcallerpc(void*, void*);
-void*  runtime·getcallerpc(void*);
-void   runtime·printbool(bool);
-void   runtime·printbyte(int8);
-void   runtime·printfloat(float64);
-void   runtime·printint(int64);
-void   runtime·printiface(Iface);
-void   runtime·printeface(Eface);
-void   runtime·printstring(String);
-void   runtime·printpc(void*);
-void   runtime·printpointer(void*);
-void   runtime·printuint(uint64);
-void   runtime·printhex(uint64);
-void   runtime·printslice(Slice);
-void   runtime·printcomplex(Complex128);
-
-/*
- * runtime go-called
- */
-void   runtime·gopanic(Eface);
-void   runtime·panicindex(void);
-void   runtime·panicslice(void);
-void   runtime·panicdivide(void);
-
-/*
- * runtime c-called (but written in Go)
- */
-void   runtime·printany(Eface);
-void   runtime·newTypeAssertionError(String*, String*, String*, String*, Eface*);
-void   runtime·fadd64c(uint64, uint64, uint64*);
-void   runtime·fsub64c(uint64, uint64, uint64*);
-void   runtime·fmul64c(uint64, uint64, uint64*);
-void   runtime·fdiv64c(uint64, uint64, uint64*);
-void   runtime·fneg64c(uint64, uint64*);
-void   runtime·f32to64c(uint32, uint64*);
-void   runtime·f64to32c(uint64, uint32*);
-void   runtime·fcmp64c(uint64, uint64, int32*, bool*);
-void   runtime·fintto64c(int64, uint64*);
-void   runtime·f64tointc(uint64, int64*, bool*);
-
-/*
- * wrapped for go users
- */
-float64        runtime·Inf(int32 sign);
-float64        runtime·NaN(void);
-float32        runtime·float32frombits(uint32 i);
-uint32 runtime·float32tobits(float32 f);
-float64        runtime·float64frombits(uint64 i);
-uint64 runtime·float64tobits(float64 f);
-float64        runtime·frexp(float64 d, int32 *ep);
-bool   runtime·isInf(float64 f, int32 sign);
-bool   runtime·isNaN(float64 f);
-float64        runtime·ldexp(float64 d, int32 e);
-float64        runtime·modf(float64 d, float64 *ip);
-void   runtime·semacquire(uint32*, bool);
-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);
-
-bool   runtime·showframe(Func*, G*);
-void   runtime·printcreatedby(G*);
-
-void   runtime·ifaceE2I(InterfaceType*, Eface, Iface*);
-bool   runtime·ifaceE2I2(InterfaceType*, Eface, Iface*);
-uintptr        runtime·memlimit(void);
-
-// 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/runtime/runtime1.go b/src/runtime/runtime1.go
new file mode 100644 (file)
index 0000000..15dea01
--- /dev/null
@@ -0,0 +1,417 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// Keep a cached value to make gotraceback fast,
+// since we call it on every call to gentraceback.
+// The cached value is a uint32 in which the low bit
+// is the "crash" setting and the top 31 bits are the
+// gotraceback value.
+var traceback_cache uint32 = 2 << 1
+
+// The GOTRACEBACK environment variable controls the
+// behavior of a Go program that is crashing and exiting.
+//     GOTRACEBACK=0   suppress all tracebacks
+//     GOTRACEBACK=1   default behavior - show tracebacks but exclude runtime frames
+//     GOTRACEBACK=2   show tracebacks including runtime frames
+//     GOTRACEBACK=crash   show tracebacks including runtime frames, then crash (core dump etc)
+//go:nosplit
+func gotraceback(crash *bool) int32 {
+       _g_ := getg()
+       if crash != nil {
+               *crash = false
+       }
+       if _g_.m.traceback != 0 {
+               return int32(_g_.m.traceback)
+       }
+       if crash != nil {
+               *crash = traceback_cache&1 != 0
+       }
+       return int32(traceback_cache >> 1)
+}
+
+var (
+       argc int32
+       argv **byte
+)
+
+// nosplit for use in linux/386 startup linux_setup_vdso
+//go:nosplit
+func argv_index(argv **byte, i int32) *byte {
+       return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*ptrSize))
+}
+
+func args(c int32, v **byte) {
+       argc = c
+       argv = v
+       sysargs(c, v)
+}
+
+var (
+       // TODO: Retire in favor of GOOS== checks.
+       isplan9   int32
+       issolaris int32
+       iswindows int32
+)
+
+// Information about what cpu features are available.
+// Set on startup in asm_{x86/amd64}.s.
+var (
+//cpuid_ecx uint32
+//cpuid_edx uint32
+)
+
+func goargs() {
+       if GOOS == "windows" {
+               return
+       }
+
+       argslice = make([]string, argc)
+       for i := int32(0); i < argc; i++ {
+               argslice[i] = gostringnocopy(argv_index(argv, i))
+       }
+}
+
+func goenvs_unix() {
+       n := int32(0)
+       for argv_index(argv, argc+1+n) != nil {
+               n++
+       }
+
+       envs = make([]string, n)
+       for i := int32(0); i < n; i++ {
+               envs[i] = gostringnocopy(argv_index(argv, argc+1+i))
+       }
+}
+
+func environ() []string {
+       return envs
+}
+
+func testAtomic64() {
+       var z64, x64 uint64
+
+       z64 = 42
+       x64 = 0
+       // TODO: PREFETCH((unsafe.Pointer)(&z64))
+       if cas64(&z64, x64, 1) {
+               gothrow("cas64 failed")
+       }
+       if x64 != 0 {
+               gothrow("cas64 failed")
+       }
+       x64 = 42
+       if !cas64(&z64, x64, 1) {
+               gothrow("cas64 failed")
+       }
+       if x64 != 42 || z64 != 1 {
+               gothrow("cas64 failed")
+       }
+       if atomicload64(&z64) != 1 {
+               gothrow("load64 failed")
+       }
+       atomicstore64(&z64, (1<<40)+1)
+       if atomicload64(&z64) != (1<<40)+1 {
+               gothrow("store64 failed")
+       }
+       if xadd64(&z64, (1<<40)+1) != (2<<40)+2 {
+               gothrow("xadd64 failed")
+       }
+       if atomicload64(&z64) != (2<<40)+2 {
+               gothrow("xadd64 failed")
+       }
+       if xchg64(&z64, (3<<40)+3) != (2<<40)+2 {
+               gothrow("xchg64 failed")
+       }
+       if atomicload64(&z64) != (3<<40)+3 {
+               gothrow("xchg64 failed")
+       }
+}
+
+func check() {
+       var (
+               a     int8
+               b     uint8
+               c     int16
+               d     uint16
+               e     int32
+               f     uint32
+               g     int64
+               h     uint64
+               i, i1 float32
+               j, j1 float64
+               k, k1 unsafe.Pointer
+               l     *uint16
+               m     [4]byte
+       )
+       type x1t struct {
+               x uint8
+       }
+       type y1t struct {
+               x1 x1t
+               y  uint8
+       }
+       var x1 x1t
+       var y1 y1t
+
+       if unsafe.Sizeof(a) != 1 {
+               gothrow("bad a")
+       }
+       if unsafe.Sizeof(b) != 1 {
+               gothrow("bad b")
+       }
+       if unsafe.Sizeof(c) != 2 {
+               gothrow("bad c")
+       }
+       if unsafe.Sizeof(d) != 2 {
+               gothrow("bad d")
+       }
+       if unsafe.Sizeof(e) != 4 {
+               gothrow("bad e")
+       }
+       if unsafe.Sizeof(f) != 4 {
+               gothrow("bad f")
+       }
+       if unsafe.Sizeof(g) != 8 {
+               gothrow("bad g")
+       }
+       if unsafe.Sizeof(h) != 8 {
+               gothrow("bad h")
+       }
+       if unsafe.Sizeof(i) != 4 {
+               gothrow("bad i")
+       }
+       if unsafe.Sizeof(j) != 8 {
+               gothrow("bad j")
+       }
+       if unsafe.Sizeof(k) != ptrSize {
+               gothrow("bad k")
+       }
+       if unsafe.Sizeof(l) != ptrSize {
+               gothrow("bad l")
+       }
+       if unsafe.Sizeof(x1) != 1 {
+               gothrow("bad unsafe.Sizeof x1")
+       }
+       if unsafe.Offsetof(y1.y) != 1 {
+               gothrow("bad offsetof y1.y")
+       }
+       if unsafe.Sizeof(y1) != 2 {
+               gothrow("bad unsafe.Sizeof y1")
+       }
+
+       if timediv(12345*1000000000+54321, 1000000000, &e) != 12345 || e != 54321 {
+               gothrow("bad timediv")
+       }
+
+       var z uint32
+       z = 1
+       if !cas(&z, 1, 2) {
+               gothrow("cas1")
+       }
+       if z != 2 {
+               gothrow("cas2")
+       }
+
+       z = 4
+       if cas(&z, 5, 6) {
+               gothrow("cas3")
+       }
+       if z != 4 {
+               gothrow("cas4")
+       }
+
+       z = 0xffffffff
+       if !cas(&z, 0xffffffff, 0xfffffffe) {
+               gothrow("cas5")
+       }
+       if z != 0xfffffffe {
+               gothrow("cas6")
+       }
+
+       k = unsafe.Pointer(uintptr(0xfedcb123))
+       if ptrSize == 8 {
+               k = unsafe.Pointer(uintptr(unsafe.Pointer(k)) << 10)
+       }
+       if casp(&k, nil, nil) {
+               gothrow("casp1")
+       }
+       k1 = add(k, 1)
+       if !casp(&k, k, k1) {
+               gothrow("casp2")
+       }
+       if k != k1 {
+               gothrow("casp3")
+       }
+
+       m = [4]byte{1, 1, 1, 1}
+       atomicor8(&m[1], 0xf0)
+       if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 {
+               gothrow("atomicor8")
+       }
+
+       *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0)
+       if j == j {
+               gothrow("float64nan")
+       }
+       if !(j != j) {
+               gothrow("float64nan1")
+       }
+
+       *(*uint64)(unsafe.Pointer(&j1)) = ^uint64(1)
+       if j == j1 {
+               gothrow("float64nan2")
+       }
+       if !(j != j1) {
+               gothrow("float64nan3")
+       }
+
+       *(*uint32)(unsafe.Pointer(&i)) = ^uint32(0)
+       if i == i {
+               gothrow("float32nan")
+       }
+       if i == i {
+               gothrow("float32nan1")
+       }
+
+       *(*uint32)(unsafe.Pointer(&i1)) = ^uint32(1)
+       if i == i1 {
+               gothrow("float32nan2")
+       }
+       if i == i1 {
+               gothrow("float32nan3")
+       }
+
+       testAtomic64()
+
+       if _FixedStack != round2(_FixedStack) {
+               gothrow("FixedStack is not power-of-2")
+       }
+}
+
+type dbgVar struct {
+       name  string
+       value *int32
+}
+
+// Do we report invalid pointers found during stack or heap scans?
+//var invalidptr int32 = 1
+
+var dbgvars = []dbgVar{
+       {"allocfreetrace", &debug.allocfreetrace},
+       {"invalidptr", &invalidptr},
+       {"efence", &debug.efence},
+       {"gctrace", &debug.gctrace},
+       {"gcdead", &debug.gcdead},
+       {"scheddetail", &debug.scheddetail},
+       {"schedtrace", &debug.schedtrace},
+       {"scavenge", &debug.scavenge},
+}
+
+func parsedebugvars() {
+       for p := gogetenv("GODEBUG"); p != ""; {
+               field := ""
+               i := index(p, ",")
+               if i < 0 {
+                       field, p = p, ""
+               } else {
+                       field, p = p[:i], p[i+1:]
+               }
+               i = index(field, "=")
+               if i < 0 {
+                       continue
+               }
+               key, value := field[:i], field[i+1:]
+               for _, v := range dbgvars {
+                       if v.name == key {
+                               *v.value = int32(goatoi(value))
+                       }
+               }
+       }
+
+       switch p := gogetenv("GOTRACEBACK"); p {
+       case "":
+               traceback_cache = 1 << 1
+       case "crash":
+               traceback_cache = 2<<1 | 1
+       default:
+               traceback_cache = uint32(goatoi(p)) << 1
+       }
+}
+
+// Poor mans 64-bit division.
+// This is a very special function, do not use it if you are not sure what you are doing.
+// int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
+// Handles overflow in a time-specific manner.
+//go:nosplit
+func timediv(v int64, div int32, rem *int32) int32 {
+       res := int32(0)
+       for bit := 30; bit >= 0; bit-- {
+               if v >= int64(div)<<uint(bit) {
+                       v = v - (int64(div) << uint(bit))
+                       res += 1 << uint(bit)
+               }
+       }
+       if v >= int64(div) {
+               if rem != nil {
+                       *rem = 0
+               }
+               return 0x7fffffff
+       }
+       if rem != nil {
+               *rem = int32(v)
+       }
+       return res
+}
+
+// Helpers for Go. Must be NOSPLIT, must only call NOSPLIT functions, and must not block.
+
+//go:nosplit
+func acquirem() *m {
+       _g_ := getg()
+       _g_.m.locks++
+       return _g_.m
+}
+
+//go:nosplit
+func releasem(mp *m) {
+       _g_ := getg()
+       mp.locks--
+       if mp.locks == 0 && _g_.preempt {
+               // restore the preemption request in case we've cleared it in newstack
+               _g_.stackguard0 = stackPreempt
+       }
+}
+
+//go:nosplit
+func gomcache() *mcache {
+       return getg().m.mcache
+}
+
+var typelink, etypelink [0]byte
+
+//go:nosplit
+func typelinks() []*_type {
+       var ret []*_type
+       sp := (*slice)(unsafe.Pointer(&ret))
+       sp.array = (*byte)(unsafe.Pointer(&typelink))
+       sp.len = uint((uintptr(unsafe.Pointer(&etypelink)) - uintptr(unsafe.Pointer(&typelink))) / unsafe.Sizeof(ret[0]))
+       sp.cap = sp.len
+       return ret
+}
+
+// TODO: move back into mgc0.c when converted to Go
+func readgogc() int32 {
+       p := gogetenv("GOGC")
+       if p == "" {
+               return 100
+       }
+       if p == "off" {
+               return -1
+       }
+       return int32(goatoi(p))
+}
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
new file mode 100644 (file)
index 0000000..7987a73
--- /dev/null
@@ -0,0 +1,606 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+/*
+ * defined constants
+ */
+const (
+       // G status
+       //
+       // If you add to this list, add to the list
+       // of "okay during garbage collection" status
+       // in mgc0.c too.
+       _Gidle            = iota // 0
+       _Grunnable               // 1 runnable and on a run queue
+       _Grunning                // 2
+       _Gsyscall                // 3
+       _Gwaiting                // 4
+       _Gmoribund_unused        // 5 currently unused, but hardcoded in gdb scripts
+       _Gdead                   // 6
+       _Genqueue                // 7 Only the Gscanenqueue is used.
+       _Gcopystack              // 8 in this state when newstack is moving the stack
+       // the following encode that the GC is scanning the stack and what to do when it is done
+       _Gscan = 0x1000 // atomicstatus&~Gscan = the non-scan state,
+       // _Gscanidle =     _Gscan + _Gidle,      // Not used. Gidle only used with newly malloced gs
+       _Gscanrunnable = _Gscan + _Grunnable //  0x1001 When scanning complets make Grunnable (it is already on run queue)
+       _Gscanrunning  = _Gscan + _Grunning  //  0x1002 Used to tell preemption newstack routine to scan preempted stack.
+       _Gscansyscall  = _Gscan + _Gsyscall  //  0x1003 When scanning completes make is Gsyscall
+       _Gscanwaiting  = _Gscan + _Gwaiting  //  0x1004 When scanning completes make it Gwaiting
+       // _Gscanmoribund_unused,               //  not possible
+       // _Gscandead,                          //  not possible
+       _Gscanenqueue = _Gscan + _Genqueue //  When scanning completes make it Grunnable and put on runqueue
+)
+
+const (
+       // P status
+       _Pidle = iota
+       _Prunning
+       _Psyscall
+       _Pgcstop
+       _Pdead
+)
+
+// The next line makes 'go generate' write the zgen_*.go files with
+// per-OS and per-arch information, including constants
+// named goos_$GOOS and goarch_$GOARCH for every
+// known GOOS and GOARCH. The constant is 1 on the
+// current system, 0 otherwise; multiplying by them is
+// useful for defining GOOS- or GOARCH-specific constants.
+//go:generate go run gengoos.go
+
+type mutex struct {
+       // Futex-based impl treats it as uint32 key,
+       // while sema-based impl as M* waitm.
+       // Used to be a union, but unions break precise GC.
+       key uintptr
+}
+
+type note struct {
+       // Futex-based impl treats it as uint32 key,
+       // while sema-based impl as M* waitm.
+       // Used to be a union, but unions break precise GC.
+       key uintptr
+}
+
+type _string struct {
+       str *byte
+       len int
+}
+
+type funcval struct {
+       fn uintptr
+       // variable-size, fn-specific data here
+}
+
+type iface struct {
+       tab  *itab
+       data unsafe.Pointer
+}
+
+type eface struct {
+       _type *_type
+       data  unsafe.Pointer
+}
+
+type slice struct {
+       array *byte // actual data
+       len   uint  // number of elements
+       cap   uint  // allocated number of elements
+}
+
+type gobuf struct {
+       // The offsets of sp, pc, and g are known to (hard-coded in) libmach.
+       sp   uintptr
+       pc   uintptr
+       g    *g
+       ctxt unsafe.Pointer // this has to be a pointer so that gc scans it
+       ret  uintreg
+       lr   uintptr
+}
+
+// Known to compiler.
+// Changes here must also be made in src/cmd/gc/select.c's selecttype.
+type sudog struct {
+       g           *g
+       selectdone  *uint32
+       next        *sudog
+       prev        *sudog
+       elem        unsafe.Pointer // data element
+       releasetime int64
+       nrelease    int32  // -1 for acquire
+       waitlink    *sudog // g.waiting list
+}
+
+type gcstats struct {
+       // the struct must consist of only uint64's,
+       // because it is casted to uint64[].
+       nhandoff    uint64
+       nhandoffcnt uint64
+       nprocyield  uint64
+       nosyield    uint64
+       nsleep      uint64
+}
+
+type libcall struct {
+       fn   uintptr
+       n    uintptr // number of parameters
+       args uintptr // parameters
+       r1   uintptr // return values
+       r2   uintptr
+       err  uintptr // error number
+}
+
+// describes how to handle callback
+type wincallbackcontext struct {
+       gobody       unsafe.Pointer // go function to call
+       argsize      uintptr        // callback arguments size (in bytes)
+       restorestack uintptr        // adjust stack on return by (in bytes) (386 only)
+       cleanstack   bool
+}
+
+// Stack describes a Go execution stack.
+// The bounds of the stack are exactly [lo, hi),
+// with no implicit data structures on either side.
+type stack struct {
+       lo uintptr
+       hi uintptr
+}
+
+type g struct {
+       // Stack parameters.
+       // stack describes the actual stack memory: [stack.lo, stack.hi).
+       // stackguard0 is the stack pointer compared in the Go stack growth prologue.
+       // It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
+       // stackguard1 is the stack pointer compared in the C stack growth prologue.
+       // It is stack.lo+StackGuard on g0 and gsignal stacks.
+       // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
+       stack       stack   // offset known to runtime/cgo
+       stackguard0 uintptr // offset known to liblink
+       stackguard1 uintptr // offset known to liblink
+
+       _panic       *_panic // innermost panic - offset known to liblink
+       _defer       *_defer // innermost defer
+       sched        gobuf
+       syscallsp    uintptr        // if status==gsyscall, syscallsp = sched.sp to use during gc
+       syscallpc    uintptr        // if status==gsyscall, syscallpc = sched.pc to use during gc
+       param        unsafe.Pointer // passed parameter on wakeup
+       atomicstatus uint32
+       goid         int64
+       waitsince    int64  // approx time when the g become blocked
+       waitreason   string // if status==gwaiting
+       schedlink    *g
+       issystem     bool // do not output in stack dump, ignore in deadlock detector
+       preempt      bool // preemption signal, duplicates stackguard0 = stackpreempt
+       paniconfault bool // panic (instead of crash) on unexpected fault address
+       preemptscan  bool // preempted g does scan for gc
+       gcworkdone   bool // debug: cleared at begining of gc work phase cycle, set by gcphasework, tested at end of cycle
+       throwsplit   bool // must not split stack
+       raceignore   int8 // ignore race detection events
+       m            *m   // for debuggers, but offset not hard-coded
+       lockedm      *m
+       sig          uint32
+       writebuf     []byte
+       sigcode0     uintptr
+       sigcode1     uintptr
+       sigpc        uintptr
+       gopc         uintptr // pc of go statement that created this goroutine
+       racectx      uintptr
+       waiting      *sudog // sudog structures this g is waiting on (that have a valid elem ptr)
+       end          [0]byte
+}
+
+type mts struct {
+       tv_sec  int64
+       tv_nsec int64
+}
+
+type mscratch struct {
+       v [6]uintptr
+}
+
+type m struct {
+       g0      *g    // goroutine with scheduling stack
+       morebuf gobuf // gobuf arg to morestack
+
+       // Fields not known to debuggers.
+       procid        uint64         // for debuggers, but offset not hard-coded
+       gsignal       *g             // signal-handling g
+       tls           [4]uintptr     // thread-local storage (for x86 extern register)
+       mstartfn      unsafe.Pointer // todo go func()
+       curg          *g             // current running goroutine
+       caughtsig     *g             // goroutine running during fatal signal
+       p             *p             // attached p for executing go code (nil if not executing go code)
+       nextp         *p
+       id            int32
+       mallocing     int32
+       throwing      int32
+       gcing         int32
+       locks         int32
+       softfloat     int32
+       dying         int32
+       profilehz     int32
+       helpgc        int32
+       spinning      bool // m is out of work and is actively looking for work
+       blocked       bool // m is blocked on a note
+       fastrand      uint32
+       ncgocall      uint64 // number of cgo calls in total
+       ncgo          int32  // number of cgo calls currently in progress
+       cgomal        *cgomal
+       park          note
+       alllink       *m // on allm
+       schedlink     *m
+       machport      uint32 // return address for mach ipc (os x)
+       mcache        *mcache
+       lockedg       *g
+       createstack   [32]uintptr // stack that created this thread.
+       freglo        [16]uint32  // d[i] lsb and f[i]
+       freghi        [16]uint32  // d[i] msb and f[i+16]
+       fflag         uint32      // floating point compare flags
+       locked        uint32      // tracking for lockosthread
+       nextwaitm     *m          // next m waiting for lock
+       waitsema      uintptr     // semaphore for parking on locks
+       waitsemacount uint32
+       waitsemalock  uint32
+       gcstats       gcstats
+       needextram    bool
+       traceback     uint8
+       waitunlockf   unsafe.Pointer // todo go func(*g, unsafe.pointer) bool
+       waitlock      unsafe.Pointer
+       //#ifdef GOOS_windows
+       thread uintptr // thread handle
+       // these are here because they are too large to be on the stack
+       // of low-level NOSPLIT functions.
+       libcall   libcall
+       libcallpc uintptr // for cpu profiler
+       libcallsp uintptr
+       libcallg  *g
+       //#endif
+       //#ifdef GOOS_solaris
+       perrno *int32 // pointer to tls errno
+       // these are here because they are too large to be on the stack
+       // of low-level NOSPLIT functions.
+       //LibCall       libcall;
+       ts      mts
+       scratch mscratch
+       //#endif
+       //#ifdef GOOS_plan9
+       notesig *int8
+       errstr  *byte
+       //#endif
+       end [0]byte
+}
+
+type p struct {
+       lock mutex
+
+       id          int32
+       status      uint32 // one of pidle/prunning/...
+       link        *p
+       schedtick   uint32 // incremented on every scheduler call
+       syscalltick uint32 // incremented on every system call
+       m           *m     // back-link to associated m (nil if idle)
+       mcache      *mcache
+       deferpool   [5]*_defer // pool of available defer structs of different sizes (see panic.c)
+
+       // Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen.
+       goidcache    uint64
+       goidcacheend uint64
+
+       // Queue of runnable goroutines.
+       runqhead uint32
+       runqtail uint32
+       runq     [256]*g
+
+       // Available G's (status == Gdead)
+       gfree    *g
+       gfreecnt int32
+
+       pad [64]byte
+}
+
+const (
+       // The max value of GOMAXPROCS.
+       // There are no fundamental restrictions on the value.
+       _MaxGomaxprocs = 1 << 8
+)
+
+type schedt struct {
+       lock mutex
+
+       goidgen uint64
+
+       midle        *m    // idle m's waiting for work
+       nmidle       int32 // number of idle m's waiting for work
+       nmidlelocked int32 // number of locked m's waiting for work
+       mcount       int32 // number of m's that have been created
+       maxmcount    int32 // maximum number of m's allowed (or die)
+
+       pidle      *p // idle p's
+       npidle     uint32
+       nmspinning uint32
+
+       // Global runnable queue.
+       runqhead *g
+       runqtail *g
+       runqsize int32
+
+       // Global cache of dead G's.
+       gflock mutex
+       gfree  *g
+       ngfree int32
+
+       gcwaiting  uint32 // gc is waiting to run
+       stopwait   int32
+       stopnote   note
+       sysmonwait uint32
+       sysmonnote note
+       lastpoll   uint64
+
+       profilehz int32 // cpu profiling rate
+}
+
+// The m->locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
+// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
+// External locks are not recursive; a second lock is silently ignored.
+// The upper bits of m->lockedcount record the nesting depth of calls to lockOSThread
+// (counting up by LockInternal), popped by unlockOSThread (counting down by LockInternal).
+// Internal locks can be recursive. For instance, a lock for cgo can occur while the main
+// goroutine is holding the lock during the initialization phase.
+const (
+       _LockExternal = 1
+       _LockInternal = 2
+)
+
+type sigtabtt struct {
+       flags int32
+       name  *int8
+}
+
+const (
+       _SigNotify   = 1 << 0 // let signal.Notify have signal, even if from kernel
+       _SigKill     = 1 << 1 // if signal.Notify doesn't take it, exit quietly
+       _SigThrow    = 1 << 2 // if signal.Notify doesn't take it, exit loudly
+       _SigPanic    = 1 << 3 // if the signal is from the kernel, panic
+       _SigDefault  = 1 << 4 // if the signal isn't explicitly requested, don't monitor it
+       _SigHandling = 1 << 5 // our signal handler is registered
+       _SigIgnored  = 1 << 6 // the signal was ignored before we registered for it
+       _SigGoExit   = 1 << 7 // cause all runtime procs to exit (only used on Plan 9).
+)
+
+// Layout of in-memory per-function information prepared by linker
+// See http://golang.org/s/go12symtab.
+// Keep in sync with linker and with ../../libmach/sym.c
+// and with package debug/gosym and with symtab.go in package runtime.
+type _func struct {
+       entry   uintptr // start pc
+       nameoff int32   // function name
+
+       args  int32 // in/out args size
+       frame int32 // legacy frame size; use pcsp if possible
+
+       pcsp      int32
+       pcfile    int32
+       pcln      int32
+       npcdata   int32
+       nfuncdata int32
+}
+
+// layout of Itab known to compilers
+// allocated in non-garbage-collected memory
+type itab struct {
+       inter  *interfacetype
+       _type  *_type
+       link   *itab
+       bad    int32
+       unused int32
+       fun    [0]uintptr
+}
+
+// Lock-free stack node.
+type lfnode struct {
+       next    *lfnode
+       pushcnt uintptr
+}
+
+// Parallel for descriptor.
+type parfor struct {
+       body    unsafe.Pointer // go func(*parfor, uint32), executed for each element
+       done    uint32         // number of idle threads
+       nthr    uint32         // total number of threads
+       nthrmax uint32         // maximum number of threads
+       thrseq  uint32         // thread id sequencer
+       cnt     uint32         // iteration space [0, cnt)
+       ctx     unsafe.Pointer // arbitrary user context
+       wait    bool           // if true, wait while all threads finish processing,
+       // otherwise parfor may return while other threads are still working
+       thr *parforthread // array of thread descriptors
+       pad uint32        // to align parforthread.pos for 64-bit atomic operations
+       // stats
+       nsteal     uint64
+       nstealcnt  uint64
+       nprocyield uint64
+       nosyield   uint64
+       nsleep     uint64
+}
+
+// Track memory allocated by code not written in Go during a cgo call,
+// so that the garbage collector can see them.
+type cgomal struct {
+       next  *cgomal
+       alloc unsafe.Pointer
+}
+
+// Holds variables parsed from GODEBUG env var.
+type debugvars struct {
+       allocfreetrace int32
+       efence         int32
+       gctrace        int32
+       gcdead         int32
+       scheddetail    int32
+       schedtrace     int32
+       scavenge       int32
+}
+
+// Indicates to write barrier and sychronization task to preform.
+const (
+       _GCoff     = iota // stop and start             nop
+       _GCquiesce        // stop and start             nop
+       _GCstw            // stop the ps                nop
+       _GCmark           // scan the stacks and start  no white to black
+       _GCsweep          // stop and start             nop
+)
+
+type forcegcstate struct {
+       lock mutex
+       g    *g
+       idle uint32
+}
+
+var gcphase uint32
+
+/*
+ * known to compiler
+ */
+const (
+       _Structrnd = regSize
+)
+
+var startup_random_data *byte
+var startup_random_data_len uint32
+
+var invalidptr int32
+
+const (
+       // hashinit wants this many random bytes
+       _HashRandomBytes = 32
+)
+
+/*
+ * deferred subroutine calls
+ */
+type _defer struct {
+       siz     int32
+       started bool
+       argp    uintptr // where args were copied from
+       pc      uintptr
+       fn      *funcval
+       _panic  *_panic // panic that is running defer
+       link    *_defer
+}
+
+/*
+ * panics
+ */
+type _panic struct {
+       argp      unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
+       arg       interface{}    // argument to panic
+       link      *_panic        // link to earlier panic
+       recovered bool           // whether this panic is over
+       aborted   bool           // the panic was aborted
+}
+
+/*
+ * stack traces
+ */
+
+type stkframe struct {
+       fn       *_func     // function being run
+       pc       uintptr    // program counter within fn
+       continpc uintptr    // program counter where execution can continue, or 0 if not
+       lr       uintptr    // program counter at caller aka link register
+       sp       uintptr    // stack pointer at pc
+       fp       uintptr    // stack pointer at caller aka frame pointer
+       varp     uintptr    // top of local variables
+       argp     uintptr    // pointer to function arguments
+       arglen   uintptr    // number of bytes at argp
+       argmap   *bitvector // force use of this argmap
+}
+
+const (
+       _TraceRuntimeFrames = 1 << 0 // include frames for internal runtime functions.
+       _TraceTrap          = 1 << 1 // the initial PC, SP are from a trap, not a return PC from a call
+)
+
+const (
+       // The maximum number of frames we print for a traceback
+       _TracebackMaxFrames = 100
+)
+
+var (
+       emptystring string
+       allg        **g
+       allglen     uintptr
+       lastg       *g
+       allm        *m
+       allp        [_MaxGomaxprocs + 1]*p
+       gomaxprocs  int32
+       needextram  uint32
+       panicking   uint32
+       goos        *int8
+       ncpu        int32
+       iscgo       bool
+       cpuid_ecx   uint32
+       cpuid_edx   uint32
+       debug       debugvars
+       signote     note
+       forcegc     forcegcstate
+       sched       schedt
+       newprocs    int32
+)
+
+/*
+ * mutual exclusion locks.  in the uncontended case,
+ * as fast as spin locks (just a few user-level instructions),
+ * but on the contention path they sleep in the kernel.
+ * a zeroed Mutex is unlocked (no need to initialize each lock).
+ */
+
+/*
+ * sleep and wakeup on one-time events.
+ * before any calls to notesleep or notewakeup,
+ * must call noteclear to initialize the Note.
+ * then, exactly one thread can call notesleep
+ * and exactly one thread can call notewakeup (once).
+ * once notewakeup has been called, the notesleep
+ * will return.  future notesleep will return immediately.
+ * subsequent noteclear must be called only after
+ * previous notesleep has returned, e.g. it's disallowed
+ * to call noteclear straight after notewakeup.
+ *
+ * notetsleep is like notesleep but wakes up after
+ * a given number of nanoseconds even if the event
+ * has not yet happened.  if a goroutine uses notetsleep to
+ * wake up early, it must wait to call noteclear until it
+ * can be sure that no other goroutine is calling
+ * notewakeup.
+ *
+ * notesleep/notetsleep are generally called on g0,
+ * notetsleepg is similar to notetsleep but is called on user g.
+ */
+// bool        runtime·notetsleep(Note*, int64);  // false - timeout
+// bool        runtime·notetsleepg(Note*, int64);  // false - timeout
+
+/*
+ * 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.
+ */
+
+/*
+ * 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.
+ */
+
+// 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.
diff --git a/src/runtime/runtime2_windows.go b/src/runtime/runtime2_windows.go
new file mode 100644 (file)
index 0000000..80fc386
--- /dev/null
@@ -0,0 +1,8 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+// TODO(brainman): move generation of zsys_windows_*.s out from cmd/dist/buildruntime.c and into here
+const cb_max = 2000 // maximum number of windows callbacks allowed (must be in sync with MAXWINCB from cmd/dist/buildruntime.c)
index f735a71e2f5ae0b9f704565e4ed2f121edd23d56..6717b93956b33a58a87485ac9b9ae058427a71b8 100644 (file)
@@ -167,8 +167,8 @@ func selunlock(sel *_select) {
        }
 }
 
-func selparkcommit(gp *g, sel *_select) bool {
-       selunlock(sel)
+func selparkcommit(gp *g, sel unsafe.Pointer) bool {
+       selunlock((*_select)(sel))
        return true
 }
 
@@ -363,7 +363,7 @@ loop:
 
        // wait for someone to wake us up
        gp.param = nil
-       gopark(unsafe.Pointer(funcPC(selparkcommit)), unsafe.Pointer(sel), "select")
+       gopark(selparkcommit, unsafe.Pointer(sel), "select")
 
        // someone woke us up
        sellock(sel)
diff --git a/src/runtime/signal.c b/src/runtime/signal.c
deleted file mode 100644 (file)
index 0674bfb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-
-void
-runtime·sigenable_m(void)
-{
-       uint32 s;
-       
-       s = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       runtime·sigenable(s);
-}
-
-void
-runtime·sigdisable_m(void)
-{
-       uint32 s;
-       
-       s = g->m->scalararg[0];
-       g->m->scalararg[0] = 0;
-       runtime·sigdisable(s);
-}
diff --git a/src/runtime/signal1_unix.go b/src/runtime/signal1_unix.go
new file mode 100644 (file)
index 0000000..25f01e0
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package runtime
+
+const (
+       _SIG_DFL uintptr = 0
+       _SIG_IGN uintptr = 1
+)
+
+func initsig() {
+       // _NSIG is the number of signals on this operating system.
+       // sigtable should describe what to do for all the possible signals.
+       if len(sigtable) != _NSIG {
+               print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
+               gothrow("initsig")
+       }
+
+       // First call: basic setup.
+       for i := int32(0); i < _NSIG; i++ {
+               t := &sigtable[i]
+               if t.flags == 0 || t.flags&_SigDefault != 0 {
+                       continue
+               }
+
+               // For some signals, we respect an inherited SIG_IGN handler
+               // rather than insist on installing our own default handler.
+               // Even these signals can be fetched using the os/signal package.
+               switch i {
+               case _SIGHUP, _SIGINT:
+                       if getsig(i) == _SIG_IGN {
+                               t.flags = _SigNotify | _SigIgnored
+                               continue
+                       }
+               }
+
+               t.flags |= _SigHandling
+               setsig(i, funcPC(sighandler), true)
+       }
+}
+
+func sigenable(sig uint32) {
+       if sig >= uint32(len(sigtable)) {
+               return
+       }
+
+       t := &sigtable[sig]
+       if t.flags&_SigNotify != 0 && t.flags&_SigHandling == 0 {
+               t.flags |= _SigHandling
+               if getsig(int32(sig)) == _SIG_IGN {
+                       t.flags |= _SigIgnored
+               }
+               setsig(int32(sig), funcPC(sighandler), true)
+       }
+}
+
+func sigdisable(sig uint32) {
+       if sig >= uint32(len(sigtable)) {
+               return
+       }
+
+       t := &sigtable[sig]
+       if t.flags&_SigNotify != 0 && t.flags&_SigHandling != 0 {
+               t.flags &^= _SigHandling
+               if t.flags&_SigIgnored != 0 {
+                       setsig(int32(sig), _SIG_IGN, true)
+               } else {
+                       setsig(int32(sig), _SIG_DFL, true)
+               }
+       }
+}
+
+func resetcpuprofiler(hz int32) {
+       var it itimerval
+       if hz == 0 {
+               setitimer(_ITIMER_PROF, &it, nil)
+       } else {
+               it.it_interval.tv_sec = 0
+               it.it_interval.set_usec(1000000 / hz)
+               it.it_value = it.it_interval
+               setitimer(_ITIMER_PROF, &it, nil)
+       }
+       _g_ := getg()
+       _g_.m.profilehz = hz
+}
+
+func sigpipe() {
+       setsig(_SIGPIPE, _SIG_DFL, false)
+       raise(_SIGPIPE)
+}
+
+func crash() {
+       if GOOS == "darwin" {
+               // OS X core dumps are linear dumps of the mapped memory,
+               // from the first virtual byte to the last, with zeros in the gaps.
+               // Because of the way we arrange the address space on 64-bit systems,
+               // this means the OS X core file will be >128 GB and even on a zippy
+               // workstation can take OS X well over an hour to write (uninterruptible).
+               // Save users from making that mistake.
+               if ptrSize == 8 {
+                       return
+               }
+       }
+
+       unblocksignals()
+       setsig(_SIGABRT, _SIG_DFL, false)
+       raise(_SIGABRT)
+}
diff --git a/src/runtime/signal_386.c b/src/runtime/signal_386.c
deleted file mode 100644 (file)
index 30a7488..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Siginfo *info, void *ctxt)
-{
-       USED(info);
-       USED(ctxt);
-       
-       runtime·printf("eax     %x\n", SIG_EAX(info, ctxt));
-       runtime·printf("ebx     %x\n", SIG_EBX(info, ctxt));
-       runtime·printf("ecx     %x\n", SIG_ECX(info, ctxt));
-       runtime·printf("edx     %x\n", SIG_EDX(info, ctxt));
-       runtime·printf("edi     %x\n", SIG_EDI(info, ctxt));
-       runtime·printf("esi     %x\n", SIG_ESI(info, ctxt));
-       runtime·printf("ebp     %x\n", SIG_EBP(info, ctxt));
-       runtime·printf("esp     %x\n", SIG_ESP(info, ctxt));
-       runtime·printf("eip     %x\n", SIG_EIP(info, ctxt));
-       runtime·printf("eflags  %x\n", SIG_EFLAGS(info, ctxt));
-       runtime·printf("cs      %x\n", SIG_CS(info, ctxt));
-       runtime·printf("fs      %x\n", SIG_FS(info, ctxt));
-       runtime·printf("gs      %x\n", SIG_GS(info, ctxt));
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
-{
-       uintptr *sp;
-       SigTab *t;
-       bool crash;
-
-       if(sig == SIGPROF) {
-               runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp, g->m);
-               return;
-       }
-
-       t = &runtime·sigtab[sig];
-       if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               // 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 = SIG_CODE0(info, ctxt);
-               gp->sigcode1 = SIG_CODE1(info, ctxt);
-               gp->sigpc = SIG_EIP(info, ctxt);
-
-#ifdef GOOS_darwin
-               // Work around Leopard bug that doesn't set FPE_INTDIV.
-               // Look at instruction to see if it is a divide.
-               // Not necessary in Snow Leopard (si_code will be != 0).
-               if(sig == SIGFPE && gp->sigcode0 == 0) {
-                       byte *pc;
-                       pc = (byte*)gp->sigpc;
-                       if(pc[0] == 0x66)       // 16-bit instruction prefix
-                               pc++;
-                       if(pc[0] == 0xF6 || pc[0] == 0xF7)
-                               gp->sigcode0 = FPE_INTDIV;
-               }
-#endif
-
-               // Only push runtime·sigpanic if eip != 0.
-               // If 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(SIG_EIP(info, ctxt) != 0) {
-                       sp = (uintptr*)SIG_ESP(info, ctxt);
-                       *--sp = SIG_EIP(info, ctxt);
-                       SIG_ESP(info, ctxt) = (uintptr)sp;
-               }
-               SIG_EIP(info, ctxt) = (uintptr)runtime·sigpanic;
-               return;
-       }
-
-       if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
-               if(runtime·sigsend(sig))
-                       return;
-       if(t->flags & SigKill)
-               runtime·exit(2);
-       if(!(t->flags & SigThrow))
-               return;
-
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       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", SIG_EIP(info, ctxt));
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(SIG_EIP(info, ctxt), SIG_ESP(info, ctxt), 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(info, ctxt);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-}
diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go
new file mode 100644 (file)
index 0000000..5336a43
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(c *sigctxt) {
+       print("eax    ", hex(c.eax()), "\n")
+       print("ebx    ", hex(c.ebx()), "\n")
+       print("ecx    ", hex(c.ecx()), "\n")
+       print("edx    ", hex(c.edx()), "\n")
+       print("edi    ", hex(c.edi()), "\n")
+       print("esi    ", hex(c.esi()), "\n")
+       print("ebp    ", hex(c.ebp()), "\n")
+       print("esp    ", hex(c.esp()), "\n")
+       print("eip    ", hex(c.eip()), "\n")
+       print("eflags ", hex(c.eflags()), "\n")
+       print("cs     ", hex(c.cs()), "\n")
+       print("fs     ", hex(c.fs()), "\n")
+       print("gs     ", hex(c.gs()), "\n")
+}
+
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+       _g_ := getg()
+       c := &sigctxt{info, ctxt}
+
+       if sig == _SIGPROF {
+               sigprof((*byte)(unsafe.Pointer(uintptr(c.eip()))), (*byte)(unsafe.Pointer(uintptr(c.esp()))), nil, gp, _g_.m)
+               return
+       }
+
+       flags := int32(_SigThrow)
+       if sig < uint32(len(sigtable)) {
+               flags = sigtable[sig].flags
+       }
+       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+               // Make it look like a call to the signal func.
+               // Have to pass arguments out of band since
+               // augmenting the stack frame would break
+               // the unwinding code.
+               gp.sig = sig
+               gp.sigcode0 = uintptr(c.sigcode())
+               gp.sigcode1 = uintptr(c.sigaddr())
+               gp.sigpc = uintptr(c.eip())
+
+               if GOOS == "darwin" {
+                       // Work around Leopard bug that doesn't set FPE_INTDIV.
+                       // Look at instruction to see if it is a divide.
+                       // Not necessary in Snow Leopard (si_code will be != 0).
+                       if sig == _SIGFPE && gp.sigcode0 == 0 {
+                               pc := (*[4]byte)(unsafe.Pointer(gp.sigpc))
+                               i := 0
+                               if pc[i] == 0x66 { // 16-bit instruction prefix
+                                       i++
+                               }
+                               if pc[i] == 0xF6 || pc[i] == 0xF7 {
+                                       gp.sigcode0 = _FPE_INTDIV
+                               }
+                       }
+               }
+
+               // Only push runtime.sigpanic if rip != 0.
+               // If 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 c.eip() != 0 {
+                       sp := c.esp()
+                       if regSize > ptrSize {
+                               sp -= ptrSize
+                               *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
+                       }
+                       sp -= ptrSize
+                       *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(c.eip())
+                       c.set_esp(sp)
+               }
+               c.set_eip(uint32(funcPC(sigpanic)))
+               return
+       }
+
+       if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+               if sigsend(sig) {
+                       return
+               }
+       }
+
+       if flags&_SigKill != 0 {
+               exit(2)
+       }
+
+       if flags&_SigThrow == 0 {
+               return
+       }
+
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+
+       if sig < uint32(len(sigtable)) {
+               print(sigtable[sig].name, "\n")
+       } else {
+               print("Signal ", sig, "\n")
+       }
+
+       print("PC=", hex(c.eip()), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(c.eip()), uintptr(c.esp()), 0, gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(c)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+}
diff --git a/src/runtime/signal_amd64x.c b/src/runtime/signal_amd64x.c
deleted file mode 100644 (file)
index feb4afc..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build amd64 amd64p32
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Siginfo *info, void *ctxt)
-{
-       USED(info);
-       USED(ctxt);
-       
-       runtime·printf("rax     %X\n", SIG_RAX(info, ctxt));
-       runtime·printf("rbx     %X\n", SIG_RBX(info, ctxt));
-       runtime·printf("rcx     %X\n", SIG_RCX(info, ctxt));
-       runtime·printf("rdx     %X\n", SIG_RDX(info, ctxt));
-       runtime·printf("rdi     %X\n", SIG_RDI(info, ctxt));
-       runtime·printf("rsi     %X\n", SIG_RSI(info, ctxt));
-       runtime·printf("rbp     %X\n", SIG_RBP(info, ctxt));
-       runtime·printf("rsp     %X\n", SIG_RSP(info, ctxt));
-       runtime·printf("r8      %X\n", SIG_R8(info, ctxt) );
-       runtime·printf("r9      %X\n", SIG_R9(info, ctxt) );
-       runtime·printf("r10     %X\n", SIG_R10(info, ctxt));
-       runtime·printf("r11     %X\n", SIG_R11(info, ctxt));
-       runtime·printf("r12     %X\n", SIG_R12(info, ctxt));
-       runtime·printf("r13     %X\n", SIG_R13(info, ctxt));
-       runtime·printf("r14     %X\n", SIG_R14(info, ctxt));
-       runtime·printf("r15     %X\n", SIG_R15(info, ctxt));
-       runtime·printf("rip     %X\n", SIG_RIP(info, ctxt));
-       runtime·printf("rflags  %X\n", SIG_RFLAGS(info, ctxt));
-       runtime·printf("cs      %X\n", SIG_CS(info, ctxt));
-       runtime·printf("fs      %X\n", SIG_FS(info, ctxt));
-       runtime·printf("gs      %X\n", SIG_GS(info, ctxt));
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
-{
-       uintptr *sp;
-       SigTab *t;
-       bool crash;
-
-       if(sig == SIGPROF) {
-               runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp, g->m);
-               return;
-       }
-
-#ifdef GOOS_darwin
-       // x86-64 has 48-bit virtual addresses. The top 16 bits must echo bit 47.
-       // The hardware delivers a different kind of fault for a malformed address
-       // than it does for an attempt to access a valid but unmapped address.
-       // OS X 10.9.2 mishandles the malformed address case, making it look like
-       // a user-generated signal (like someone ran kill -SEGV ourpid).
-       // We pass user-generated signals to os/signal, or else ignore them.
-       // Doing that here - and returning to the faulting code - results in an
-       // infinite loop. It appears the best we can do is rewrite what the kernel
-       // delivers into something more like the truth. The address used below
-       // has very little chance of being the one that caused the fault, but it is
-       // malformed, it is clearly not a real pointer, and if it does get printed
-       // in real life, people will probably search for it and find this code.
-       // There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
-       // as I type this comment.
-       if(sig == SIGSEGV && SIG_CODE0(info, ctxt) == SI_USER) {
-               SIG_CODE0(info, ctxt) = SI_USER+1;
-               info->si_addr = (void*)(uintptr)0xb01dfacedebac1eULL;
-       }
-#endif
-
-       t = &runtime·sigtab[sig];
-       if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               // 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 = SIG_CODE0(info, ctxt);
-               gp->sigcode1 = SIG_CODE1(info, ctxt);
-               gp->sigpc = SIG_RIP(info, ctxt);
-
-#ifdef GOOS_darwin
-               // Work around Leopard bug that doesn't set FPE_INTDIV.
-               // Look at instruction to see if it is a divide.
-               // Not necessary in Snow Leopard (si_code will be != 0).
-               if(sig == SIGFPE && gp->sigcode0 == 0) {
-                       byte *pc;
-                       pc = (byte*)gp->sigpc;
-                       if((pc[0]&0xF0) == 0x40)        // 64-bit REX prefix
-                               pc++;
-                       else if(pc[0] == 0x66)  // 16-bit instruction prefix
-                               pc++;
-                       if(pc[0] == 0xF6 || pc[0] == 0xF7)
-                               gp->sigcode0 = FPE_INTDIV;
-               }
-#endif
-
-               // Only push runtime·sigpanic if rip != 0.
-               // If 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(SIG_RIP(info, ctxt) != 0) {
-                       sp = (uintptr*)SIG_RSP(info, ctxt);
-                       if(sizeof(uintreg) > sizeof(uintptr))
-                               *--sp = 0;
-                       *--sp = SIG_RIP(info, ctxt);
-                       SIG_RSP(info, ctxt) = (uintptr)sp;
-               }
-               SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic;
-               return;
-       }
-
-       if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
-               if(runtime·sigsend(sig))
-                       return;
-       if(t->flags & SigKill)
-               runtime·exit(2);
-       if(!(t->flags & SigThrow))
-               return;
-
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       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", SIG_RIP(info, ctxt));
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(SIG_RIP(info, ctxt), SIG_RSP(info, ctxt), 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(info, ctxt);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-}
diff --git a/src/runtime/signal_amd64x.go b/src/runtime/signal_amd64x.go
new file mode 100644 (file)
index 0000000..de88d93
--- /dev/null
@@ -0,0 +1,163 @@
+// 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 amd64p32
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(c *sigctxt) {
+       print("rax    ", hex(c.rax()), "\n")
+       print("rbx    ", hex(c.rbx()), "\n")
+       print("rcx    ", hex(c.rcx()), "\n")
+       print("rdx    ", hex(c.rdx()), "\n")
+       print("rdi    ", hex(c.rdi()), "\n")
+       print("rsi    ", hex(c.rsi()), "\n")
+       print("rbp    ", hex(c.rbp()), "\n")
+       print("rsp    ", hex(c.rsp()), "\n")
+       print("r8     ", hex(c.r8()), "\n")
+       print("r9     ", hex(c.r9()), "\n")
+       print("r10    ", hex(c.r10()), "\n")
+       print("r11    ", hex(c.r11()), "\n")
+       print("r12    ", hex(c.r12()), "\n")
+       print("r13    ", hex(c.r13()), "\n")
+       print("r14    ", hex(c.r14()), "\n")
+       print("r15    ", hex(c.r15()), "\n")
+       print("rip    ", hex(c.rip()), "\n")
+       print("rflags ", hex(c.rflags()), "\n")
+       print("cs     ", hex(c.cs()), "\n")
+       print("fs     ", hex(c.fs()), "\n")
+       print("gs     ", hex(c.gs()), "\n")
+}
+
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+       _g_ := getg()
+       c := &sigctxt{info, ctxt}
+
+       if sig == _SIGPROF {
+               sigprof((*byte)(unsafe.Pointer(uintptr(c.rip()))), (*byte)(unsafe.Pointer(uintptr(c.rsp()))), nil, gp, _g_.m)
+               return
+       }
+
+       if GOOS == "darwin" {
+               // x86-64 has 48-bit virtual addresses. The top 16 bits must echo bit 47.
+               // The hardware delivers a different kind of fault for a malformed address
+               // than it does for an attempt to access a valid but unmapped address.
+               // OS X 10.9.2 mishandles the malformed address case, making it look like
+               // a user-generated signal (like someone ran kill -SEGV ourpid).
+               // We pass user-generated signals to os/signal, or else ignore them.
+               // Doing that here - and returning to the faulting code - results in an
+               // infinite loop. It appears the best we can do is rewrite what the kernel
+               // delivers into something more like the truth. The address used below
+               // has very little chance of being the one that caused the fault, but it is
+               // malformed, it is clearly not a real pointer, and if it does get printed
+               // in real life, people will probably search for it and find this code.
+               // There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
+               // as I type this comment.
+               if sig == _SIGSEGV && c.sigcode() == _SI_USER {
+                       c.set_sigcode(_SI_USER + 1)
+                       c.set_sigaddr(0xb01dfacedebac1e)
+               }
+       }
+
+       flags := int32(_SigThrow)
+       if sig < uint32(len(sigtable)) {
+               flags = sigtable[sig].flags
+       }
+       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+               // Make it look like a call to the signal func.
+               // Have to pass arguments out of band since
+               // augmenting the stack frame would break
+               // the unwinding code.
+               gp.sig = sig
+               gp.sigcode0 = uintptr(c.sigcode())
+               gp.sigcode1 = uintptr(c.sigaddr())
+               gp.sigpc = uintptr(c.rip())
+
+               if GOOS == "darwin" {
+                       // Work around Leopard bug that doesn't set FPE_INTDIV.
+                       // Look at instruction to see if it is a divide.
+                       // Not necessary in Snow Leopard (si_code will be != 0).
+                       if sig == _SIGFPE && gp.sigcode0 == 0 {
+                               pc := (*[4]byte)(unsafe.Pointer(gp.sigpc))
+                               i := 0
+                               if pc[i]&0xF0 == 0x40 { // 64-bit REX prefix
+                                       i++
+                               } else if pc[i] == 0x66 { // 16-bit instruction prefix
+                                       i++
+                               }
+                               if pc[i] == 0xF6 || pc[i] == 0xF7 {
+                                       gp.sigcode0 = _FPE_INTDIV
+                               }
+                       }
+               }
+
+               // Only push runtime.sigpanic if rip != 0.
+               // If 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 c.rip() != 0 {
+                       sp := c.rsp()
+                       if regSize > ptrSize {
+                               sp -= ptrSize
+                               *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
+                       }
+                       sp -= ptrSize
+                       *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(c.rip())
+                       c.set_rsp(sp)
+               }
+               c.set_rip(uint64(funcPC(sigpanic)))
+               return
+       }
+
+       if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+               if sigsend(sig) {
+                       return
+               }
+       }
+
+       if flags&_SigKill != 0 {
+               exit(2)
+       }
+
+       if flags&_SigThrow == 0 {
+               return
+       }
+
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+
+       if sig < uint32(len(sigtable)) {
+               print(sigtable[sig].name, "\n")
+       } else {
+               print("Signal ", sig, "\n")
+       }
+
+       print("PC=", hex(c.rip()), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(c.rip()), uintptr(c.rsp()), 0, gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(c)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+}
diff --git a/src/runtime/signal_arm.c b/src/runtime/signal_arm.c
deleted file mode 100644 (file)
index afad5e7..0000000
+++ /dev/null
@@ -1,121 +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 dragonfly freebsd linux nacl netbsd openbsd
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Siginfo *info, void *ctxt)
-{
-       USED(info);
-       USED(ctxt);
-
-       runtime·printf("trap    %x\n", SIG_TRAP(info, ctxt));
-       runtime·printf("error   %x\n", SIG_ERROR(info, ctxt));
-       runtime·printf("oldmask %x\n", SIG_OLDMASK(info, ctxt));
-       runtime·printf("r0      %x\n", SIG_R0(info, ctxt));
-       runtime·printf("r1      %x\n", SIG_R1(info, ctxt));
-       runtime·printf("r2      %x\n", SIG_R2(info, ctxt));
-       runtime·printf("r3      %x\n", SIG_R3(info, ctxt));
-       runtime·printf("r4      %x\n", SIG_R4(info, ctxt));
-       runtime·printf("r5      %x\n", SIG_R5(info, ctxt));
-       runtime·printf("r6      %x\n", SIG_R6(info, ctxt));
-       runtime·printf("r7      %x\n", SIG_R7(info, ctxt));
-       runtime·printf("r8      %x\n", SIG_R8(info, ctxt));
-       runtime·printf("r9      %x\n", SIG_R9(info, ctxt));
-       runtime·printf("r10     %x\n", SIG_R10(info, ctxt));
-       runtime·printf("fp      %x\n", SIG_FP(info, ctxt));
-       runtime·printf("ip      %x\n", SIG_IP(info, ctxt));
-       runtime·printf("sp      %x\n", SIG_SP(info, ctxt));
-       runtime·printf("lr      %x\n", SIG_LR(info, ctxt));
-       runtime·printf("pc      %x\n", SIG_PC(info, ctxt));
-       runtime·printf("cpsr    %x\n", SIG_CPSR(info, ctxt));
-       runtime·printf("fault   %x\n", SIG_FAULT(info, ctxt));
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
-{
-       SigTab *t;
-       bool crash;
-
-       if(sig == SIGPROF) {
-               runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp, g->m);
-               return;
-       }
-
-       t = &runtime·sigtab[sig];
-       if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               // 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 = SIG_CODE0(info, ctxt);
-               gp->sigcode1 = SIG_FAULT(info, ctxt);
-               gp->sigpc = SIG_PC(info, ctxt);
-
-               // 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.
-               SIG_SP(info, ctxt) -= 4;
-               *(uint32*)SIG_SP(info, ctxt) = SIG_LR(info, ctxt);
-               // 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(gp->sigpc != 0)
-                       SIG_LR(info, ctxt) = gp->sigpc;
-               // In case we are panicking from external C code
-               SIG_R10(info, ctxt) = (uintptr)gp;
-               SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
-               return;
-       }
-
-       if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
-               if(runtime·sigsend(sig))
-                       return;
-       if(t->flags & SigKill)
-               runtime·exit(2);
-       if(!(t->flags & SigThrow))
-               return;
-
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       if(runtime·panicking)  // traceback already printed
-               runtime·exit(2);
-       runtime·panicking = 1;
-
-       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", SIG_PC(info, ctxt));
-       if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
-               runtime·printf("signal arrived during cgo execution\n");
-               gp = g->m->lockedg;
-       }
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)){
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LR(info, ctxt), gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(info, ctxt);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-       runtime·exit(2);
-}
diff --git a/src/runtime/signal_arm.go b/src/runtime/signal_arm.go
new file mode 100644 (file)
index 0000000..d224ce6
--- /dev/null
@@ -0,0 +1,126 @@
+// 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 dragonfly freebsd linux nacl netbsd openbsd
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(c *sigctxt) {
+       print("trap    ", hex(c.trap()), "\n")
+       print("error   ", hex(c.error()), "\n")
+       print("oldmask ", hex(c.oldmask()), "\n")
+       print("r0      ", hex(c.r0()), "\n")
+       print("r1      ", hex(c.r1()), "\n")
+       print("r2      ", hex(c.r2()), "\n")
+       print("r3      ", hex(c.r3()), "\n")
+       print("r4      ", hex(c.r4()), "\n")
+       print("r5      ", hex(c.r5()), "\n")
+       print("r6      ", hex(c.r6()), "\n")
+       print("r7      ", hex(c.r7()), "\n")
+       print("r8      ", hex(c.r8()), "\n")
+       print("r9      ", hex(c.r9()), "\n")
+       print("r10     ", hex(c.r10()), "\n")
+       print("fp      ", hex(c.fp()), "\n")
+       print("ip      ", hex(c.ip()), "\n")
+       print("sp      ", hex(c.sp()), "\n")
+       print("lr      ", hex(c.lr()), "\n")
+       print("pc      ", hex(c.pc()), "\n")
+       print("cpsr    ", hex(c.cpsr()), "\n")
+       print("fault   ", hex(c.fault()), "\n")
+}
+
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+       _g_ := getg()
+       c := &sigctxt{info, ctxt}
+
+       if sig == _SIGPROF {
+               sigprof((*byte)(unsafe.Pointer(uintptr(c.pc()))), (*byte)(unsafe.Pointer(uintptr(c.sp()))), (*byte)(unsafe.Pointer(uintptr(c.lr()))), gp, _g_.m)
+               return
+       }
+
+       flags := int32(_SigThrow)
+       if sig < uint32(len(sigtable)) {
+               flags = sigtable[sig].flags
+       }
+       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+               // Make it look like a call to the signal func.
+               // Have to pass arguments out of band since
+               // augmenting the stack frame would break
+               // the unwinding code.
+               gp.sig = sig
+               gp.sigcode0 = uintptr(c.sigcode())
+               gp.sigcode1 = uintptr(c.fault())
+               gp.sigpc = uintptr(c.pc())
+
+               // 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.
+               sp := c.sp() - 4
+               c.set_sp(sp)
+               *(*uint32)(unsafe.Pointer(uintptr(sp))) = c.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 gp.sigpc != 0 {
+                       c.set_lr(uint32(gp.sigpc))
+               }
+
+               // In case we are panicking from external C code
+               c.set_r10(uint32(uintptr(unsafe.Pointer(gp))))
+               c.set_pc(uint32(funcPC(sigpanic)))
+               return
+       }
+
+       if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+               if sigsend(sig) {
+                       return
+               }
+       }
+
+       if flags&_SigKill != 0 {
+               exit(2)
+       }
+
+       if flags&_SigThrow == 0 {
+               return
+       }
+
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+
+       if sig < uint32(len(sigtable)) {
+               print(sigtable[sig].name, "\n")
+       } else {
+               print("Signal ", sig, "\n")
+       }
+
+       print("PC=", hex(c.pc()), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(c)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+}
diff --git a/src/runtime/signal_darwin.go b/src/runtime/signal_darwin.go
new file mode 100644 (file)
index 0000000..122648b
--- /dev/null
@@ -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.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /* 0 */ {0, "SIGNONE: no trap"},
+       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /* 4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /* 5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
+       /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /* 9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigThrow, "SIGSYS: bad system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 17 */ {0, "SIGSTOP: stop"},
+       /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 19 */ {0, "SIGCONT: continue after stop"},
+       /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
+       /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+}
diff --git a/src/runtime/signal_darwin_386.go b/src/runtime/signal_darwin_386.go
new file mode 100644 (file)
index 0000000..ccf30ef
--- /dev/null
@@ -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.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *regs32   { return &(*ucontext)(c.ctxt).uc_mcontext.ss }
+func (c *sigctxt) eax() uint32     { return c.regs().eax }
+func (c *sigctxt) ebx() uint32     { return c.regs().ebx }
+func (c *sigctxt) ecx() uint32     { return c.regs().ecx }
+func (c *sigctxt) edx() uint32     { return c.regs().edx }
+func (c *sigctxt) edi() uint32     { return c.regs().edi }
+func (c *sigctxt) esi() uint32     { return c.regs().esi }
+func (c *sigctxt) ebp() uint32     { return c.regs().ebp }
+func (c *sigctxt) esp() uint32     { return c.regs().esp }
+func (c *sigctxt) eip() uint32     { return c.regs().eip }
+func (c *sigctxt) eflags() uint32  { return c.regs().eflags }
+func (c *sigctxt) cs() uint32      { return c.regs().cs }
+func (c *sigctxt) fs() uint32      { return c.regs().fs }
+func (c *sigctxt) gs() uint32      { return c.regs().gs }
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32 { return uint32(uintptr(unsafe.Pointer(c.info.si_addr))) }
+
+func (c *sigctxt) set_eip(x uint32)     { c.regs().eip = x }
+func (c *sigctxt) set_esp(x uint32)     { c.regs().esp = x }
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) { c.info.si_addr = (*byte)(unsafe.Pointer(uintptr(x))) }
diff --git a/src/runtime/signal_darwin_386.h b/src/runtime/signal_darwin_386.h
deleted file mode 100644 (file)
index 5459e10..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext->ss)
-
-#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
-#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
-#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
-#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
-#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
-#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
-#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
-#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
-#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
-#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/runtime/signal_darwin_amd64.go b/src/runtime/signal_darwin_amd64.go
new file mode 100644 (file)
index 0000000..409bc6d
--- /dev/null
@@ -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 runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *regs64   { return &(*ucontext)(c.ctxt).uc_mcontext.ss }
+func (c *sigctxt) rax() uint64     { return c.regs().rax }
+func (c *sigctxt) rbx() uint64     { return c.regs().rbx }
+func (c *sigctxt) rcx() uint64     { return c.regs().rcx }
+func (c *sigctxt) rdx() uint64     { return c.regs().rdx }
+func (c *sigctxt) rdi() uint64     { return c.regs().rdi }
+func (c *sigctxt) rsi() uint64     { return c.regs().rsi }
+func (c *sigctxt) rbp() uint64     { return c.regs().rbp }
+func (c *sigctxt) rsp() uint64     { return c.regs().rsp }
+func (c *sigctxt) r8() uint64      { return c.regs().r8 }
+func (c *sigctxt) r9() uint64      { return c.regs().r9 }
+func (c *sigctxt) r10() uint64     { return c.regs().r10 }
+func (c *sigctxt) r11() uint64     { return c.regs().r11 }
+func (c *sigctxt) r12() uint64     { return c.regs().r12 }
+func (c *sigctxt) r13() uint64     { return c.regs().r13 }
+func (c *sigctxt) r14() uint64     { return c.regs().r14 }
+func (c *sigctxt) r15() uint64     { return c.regs().r15 }
+func (c *sigctxt) rip() uint64     { return c.regs().rip }
+func (c *sigctxt) rflags() uint64  { return c.regs().rflags }
+func (c *sigctxt) cs() uint64      { return c.regs().cs }
+func (c *sigctxt) fs() uint64      { return c.regs().fs }
+func (c *sigctxt) gs() uint64      { return c.regs().gs }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return uint64(uintptr(unsafe.Pointer(c.info.si_addr))) }
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) { c.info.si_addr = (*byte)(unsafe.Pointer(uintptr(x))) }
diff --git a/src/runtime/signal_darwin_amd64.h b/src/runtime/signal_darwin_amd64.h
deleted file mode 100644 (file)
index e3da6de..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext->ss)
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).rflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/runtime/signal_dragonfly.go b/src/runtime/signal_dragonfly.go
new file mode 100644 (file)
index 0000000..d37e11a
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /* 0 */ {0, "SIGNONE: no trap"},
+       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /* 4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /* 5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
+       /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /* 9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigThrow, "SIGSYS: bad system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 17 */ {0, "SIGSTOP: stop"},
+       /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 19 */ {0, "SIGCONT: continue after stop"},
+       /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
+       /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+       /* 32 */ {_SigNotify, "SIGTHR: reserved"},
+}
diff --git a/src/runtime/signal_dragonfly_amd64.go b/src/runtime/signal_dragonfly_amd64.go
new file mode 100644 (file)
index 0000000..740959c
--- /dev/null
@@ -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 runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontext {
+       return (*mcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
+}
+func (c *sigctxt) rax() uint64     { return c.regs().mc_rax }
+func (c *sigctxt) rbx() uint64     { return c.regs().mc_rbx }
+func (c *sigctxt) rcx() uint64     { return c.regs().mc_rcx }
+func (c *sigctxt) rdx() uint64     { return c.regs().mc_rdx }
+func (c *sigctxt) rdi() uint64     { return c.regs().mc_rdi }
+func (c *sigctxt) rsi() uint64     { return c.regs().mc_rsi }
+func (c *sigctxt) rbp() uint64     { return c.regs().mc_rbp }
+func (c *sigctxt) rsp() uint64     { return c.regs().mc_rsp }
+func (c *sigctxt) r8() uint64      { return c.regs().mc_r8 }
+func (c *sigctxt) r9() uint64      { return c.regs().mc_r9 }
+func (c *sigctxt) r10() uint64     { return c.regs().mc_r10 }
+func (c *sigctxt) r11() uint64     { return c.regs().mc_r11 }
+func (c *sigctxt) r12() uint64     { return c.regs().mc_r12 }
+func (c *sigctxt) r13() uint64     { return c.regs().mc_r13 }
+func (c *sigctxt) r14() uint64     { return c.regs().mc_r14 }
+func (c *sigctxt) r15() uint64     { return c.regs().mc_r15 }
+func (c *sigctxt) rip() uint64     { return c.regs().mc_rip }
+func (c *sigctxt) rflags() uint64  { return c.regs().mc_rflags }
+func (c *sigctxt) cs() uint64      { return uint64(c.regs().mc_cs) }
+func (c *sigctxt) fs() uint64      { return uint64(c.regs().mc_ss) }
+func (c *sigctxt) gs() uint64      { return uint64(c.regs().mc_ss) }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return uint64(c.info.si_addr) }
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().mc_rip = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().mc_rsp = x }
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) { c.info.si_addr = x }
diff --git a/src/runtime/signal_dragonfly_amd64.h b/src/runtime/signal_dragonfly_amd64.h
deleted file mode 100644 (file)
index 5b4f977..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).mc_rax)
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).mc_rbx)
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).mc_rcx)
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).mc_rdx)
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).mc_rdi)
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).mc_rsi)
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).mc_rbp)
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).mc_rsp)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).mc_r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).mc_r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).mc_r10)
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).mc_r11)
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).mc_r12)
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).mc_r13)
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).mc_r14)
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).mc_r15)
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).mc_rip)
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_rflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_ss)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_ss)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/runtime/signal_freebsd.go b/src/runtime/signal_freebsd.go
new file mode 100644 (file)
index 0000000..1dbdb1b
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /* 0 */ {0, "SIGNONE: no trap"},
+       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /* 4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /* 5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
+       /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /* 9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigNotify, "SIGSYS: bad system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 17 */ {0, "SIGSTOP: stop"},
+       /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 19 */ {0, "SIGCONT: continue after stop"},
+       /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
+       /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+       /* 32 */ {_SigNotify, "SIGTHR: reserved"},
+}
diff --git a/src/runtime/signal_freebsd_386.go b/src/runtime/signal_freebsd_386.go
new file mode 100644 (file)
index 0000000..a0fec13
--- /dev/null
@@ -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.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) eax() uint32     { return c.regs().mc_eax }
+func (c *sigctxt) ebx() uint32     { return c.regs().mc_ebx }
+func (c *sigctxt) ecx() uint32     { return c.regs().mc_ecx }
+func (c *sigctxt) edx() uint32     { return c.regs().mc_edx }
+func (c *sigctxt) edi() uint32     { return c.regs().mc_edi }
+func (c *sigctxt) esi() uint32     { return c.regs().mc_esi }
+func (c *sigctxt) ebp() uint32     { return c.regs().mc_ebp }
+func (c *sigctxt) esp() uint32     { return c.regs().mc_esp }
+func (c *sigctxt) eip() uint32     { return c.regs().mc_eip }
+func (c *sigctxt) eflags() uint32  { return c.regs().mc_eflags }
+func (c *sigctxt) cs() uint32      { return uint32(c.regs().mc_cs) }
+func (c *sigctxt) fs() uint32      { return uint32(c.regs().mc_fs) }
+func (c *sigctxt) gs() uint32      { return uint32(c.regs().mc_gs) }
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32 { return uint32(c.info.si_addr) }
+
+func (c *sigctxt) set_eip(x uint32)     { c.regs().mc_eip = x }
+func (c *sigctxt) set_esp(x uint32)     { c.regs().mc_esp = x }
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) { c.info.si_addr = uintptr(x) }
diff --git a/src/runtime/signal_freebsd_386.h b/src/runtime/signal_freebsd_386.h
deleted file mode 100644 (file)
index a24f1ee..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
-
-#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).mc_eax)
-#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).mc_ebx)
-#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).mc_ecx)
-#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).mc_edx)
-#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).mc_edi)
-#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).mc_esi)
-#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).mc_ebp)
-#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).mc_esp)
-#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).mc_eip)
-#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_eflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/runtime/signal_freebsd_amd64.go b/src/runtime/signal_freebsd_amd64.go
new file mode 100644 (file)
index 0000000..d10c883
--- /dev/null
@@ -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 runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontext {
+       return (*mcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
+}
+func (c *sigctxt) rax() uint64     { return c.regs().mc_rax }
+func (c *sigctxt) rbx() uint64     { return c.regs().mc_rbx }
+func (c *sigctxt) rcx() uint64     { return c.regs().mc_rcx }
+func (c *sigctxt) rdx() uint64     { return c.regs().mc_rdx }
+func (c *sigctxt) rdi() uint64     { return c.regs().mc_rdi }
+func (c *sigctxt) rsi() uint64     { return c.regs().mc_rsi }
+func (c *sigctxt) rbp() uint64     { return c.regs().mc_rbp }
+func (c *sigctxt) rsp() uint64     { return c.regs().mc_rsp }
+func (c *sigctxt) r8() uint64      { return c.regs().mc_r8 }
+func (c *sigctxt) r9() uint64      { return c.regs().mc_r9 }
+func (c *sigctxt) r10() uint64     { return c.regs().mc_r10 }
+func (c *sigctxt) r11() uint64     { return c.regs().mc_r11 }
+func (c *sigctxt) r12() uint64     { return c.regs().mc_r12 }
+func (c *sigctxt) r13() uint64     { return c.regs().mc_r13 }
+func (c *sigctxt) r14() uint64     { return c.regs().mc_r14 }
+func (c *sigctxt) r15() uint64     { return c.regs().mc_r15 }
+func (c *sigctxt) rip() uint64     { return c.regs().mc_rip }
+func (c *sigctxt) rflags() uint64  { return c.regs().mc_rflags }
+func (c *sigctxt) cs() uint64      { return uint64(c.regs().mc_cs) }
+func (c *sigctxt) fs() uint64      { return uint64(c.regs().mc_fs) }
+func (c *sigctxt) gs() uint64      { return uint64(c.regs().mc_gs) }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return uint64(c.info.si_addr) }
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().mc_rip = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().mc_rsp = x }
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) { c.info.si_addr = x }
diff --git a/src/runtime/signal_freebsd_amd64.h b/src/runtime/signal_freebsd_amd64.h
deleted file mode 100644 (file)
index 7d35b7f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).mc_rax)
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).mc_rbx)
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).mc_rcx)
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).mc_rdx)
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).mc_rdi)
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).mc_rsi)
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).mc_rbp)
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).mc_rsp)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).mc_r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).mc_r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).mc_r10)
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).mc_r11)
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).mc_r12)
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).mc_r13)
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).mc_r14)
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).mc_r15)
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).mc_rip)
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_rflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/runtime/signal_freebsd_arm.go b/src/runtime/signal_freebsd_arm.go
new file mode 100644 (file)
index 0000000..12de23d
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) r0() uint32      { return c.regs().__gregs[0] }
+func (c *sigctxt) r1() uint32      { return c.regs().__gregs[1] }
+func (c *sigctxt) r2() uint32      { return c.regs().__gregs[2] }
+func (c *sigctxt) r3() uint32      { return c.regs().__gregs[3] }
+func (c *sigctxt) r4() uint32      { return c.regs().__gregs[4] }
+func (c *sigctxt) r5() uint32      { return c.regs().__gregs[5] }
+func (c *sigctxt) r6() uint32      { return c.regs().__gregs[6] }
+func (c *sigctxt) r7() uint32      { return c.regs().__gregs[7] }
+func (c *sigctxt) r8() uint32      { return c.regs().__gregs[8] }
+func (c *sigctxt) r9() uint32      { return c.regs().__gregs[9] }
+func (c *sigctxt) r10() uint32     { return c.regs().__gregs[10] }
+func (c *sigctxt) fp() uint32      { return c.regs().__gregs[11] }
+func (c *sigctxt) ip() uint32      { return c.regs().__gregs[12] }
+func (c *sigctxt) sp() uint32      { return c.regs().__gregs[13] }
+func (c *sigctxt) lr() uint32      { return c.regs().__gregs[14] }
+func (c *sigctxt) pc() uint32      { return c.regs().__gregs[15] }
+func (c *sigctxt) cpsr() uint32    { return c.regs().__gregs[16] }
+func (c *sigctxt) fault() uint32   { return uint32(c.info.si_addr) }
+func (c *sigctxt) trap() uint32    { return 0 }
+func (c *sigctxt) error() uint32   { return 0 }
+func (c *sigctxt) oldmask() uint32 { return 0 }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32 { return uint32(c.info.si_addr) }
+
+func (c *sigctxt) set_pc(x uint32)  { c.regs().__gregs[15] = x }
+func (c *sigctxt) set_sp(x uint32)  { c.regs().__gregs[13] = x }
+func (c *sigctxt) set_lr(x uint32)  { c.regs().__gregs[14] = x }
+func (c *sigctxt) set_r10(x uint32) { c.regs().__gregs[10] = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) {
+       c.info.si_addr = uintptr(x)
+}
diff --git a/src/runtime/signal_freebsd_arm.h b/src/runtime/signal_freebsd_arm.h
deleted file mode 100644 (file)
index 87a45aa..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
-
-#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).__gregs[0])
-#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).__gregs[1])
-#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).__gregs[2])
-#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).__gregs[3])
-#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).__gregs[4])
-#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).__gregs[5])
-#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).__gregs[6])
-#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).__gregs[7])
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[8])
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[9])
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[10])
-#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).__gregs[11])
-#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).__gregs[12])
-#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).__gregs[13])
-#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).__gregs[14])
-#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).__gregs[15])
-#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).__gregs[16])
-#define SIG_FAULT(info, ctxt) ((uintptr)(info)->si_addr)
-#define SIG_TRAP(info, ctxt) (0)
-#define SIG_ERROR(info, ctxt) (0)
-#define SIG_OLDMASK(info, ctxt) (0)
-#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
diff --git a/src/runtime/signal_linux.go b/src/runtime/signal_linux.go
new file mode 100644 (file)
index 0000000..1c3d687
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /* 0 */ {0, "SIGNONE: no trap"},
+       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /* 4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /* 5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /* 7 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /* 9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigThrow, "SIGSTKFLT: stack fault"},
+       /* 17 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 18 */ {0, "SIGCONT: continue"},
+       /* 19 */ {0, "SIGSTOP: stop, unblockable"},
+       /* 20 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
+       /* 31 */ {_SigNotify, "SIGSYS: bad system call"},
+       /* 32 */ {0, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+       /* 33 */ {0, "signal 33"}, /* SIGSETXID; see issue 3871 */
+       /* 34 */ {_SigNotify, "signal 34"},
+       /* 35 */ {_SigNotify, "signal 35"},
+       /* 36 */ {_SigNotify, "signal 36"},
+       /* 37 */ {_SigNotify, "signal 37"},
+       /* 38 */ {_SigNotify, "signal 38"},
+       /* 39 */ {_SigNotify, "signal 39"},
+       /* 40 */ {_SigNotify, "signal 40"},
+       /* 41 */ {_SigNotify, "signal 41"},
+       /* 42 */ {_SigNotify, "signal 42"},
+       /* 43 */ {_SigNotify, "signal 43"},
+       /* 44 */ {_SigNotify, "signal 44"},
+       /* 45 */ {_SigNotify, "signal 45"},
+       /* 46 */ {_SigNotify, "signal 46"},
+       /* 47 */ {_SigNotify, "signal 47"},
+       /* 48 */ {_SigNotify, "signal 48"},
+       /* 49 */ {_SigNotify, "signal 49"},
+       /* 50 */ {_SigNotify, "signal 50"},
+       /* 51 */ {_SigNotify, "signal 51"},
+       /* 52 */ {_SigNotify, "signal 52"},
+       /* 53 */ {_SigNotify, "signal 53"},
+       /* 54 */ {_SigNotify, "signal 54"},
+       /* 55 */ {_SigNotify, "signal 55"},
+       /* 56 */ {_SigNotify, "signal 56"},
+       /* 57 */ {_SigNotify, "signal 57"},
+       /* 58 */ {_SigNotify, "signal 58"},
+       /* 59 */ {_SigNotify, "signal 59"},
+       /* 60 */ {_SigNotify, "signal 60"},
+       /* 61 */ {_SigNotify, "signal 61"},
+       /* 62 */ {_SigNotify, "signal 62"},
+       /* 63 */ {_SigNotify, "signal 63"},
+       /* 64 */ {_SigNotify, "signal 64"},
+}
diff --git a/src/runtime/signal_linux_386.go b/src/runtime/signal_linux_386.go
new file mode 100644 (file)
index 0000000..085f66e
--- /dev/null
@@ -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 runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) eax() uint32       { return c.regs().eax }
+func (c *sigctxt) ebx() uint32       { return c.regs().ebx }
+func (c *sigctxt) ecx() uint32       { return c.regs().ecx }
+func (c *sigctxt) edx() uint32       { return c.regs().edx }
+func (c *sigctxt) edi() uint32       { return c.regs().edi }
+func (c *sigctxt) esi() uint32       { return c.regs().esi }
+func (c *sigctxt) ebp() uint32       { return c.regs().ebp }
+func (c *sigctxt) esp() uint32       { return c.regs().esp }
+func (c *sigctxt) eip() uint32       { return c.regs().eip }
+func (c *sigctxt) eflags() uint32    { return c.regs().eflags }
+func (c *sigctxt) cs() uint32        { return uint32(c.regs().cs) }
+func (c *sigctxt) fs() uint32        { return uint32(c.regs().fs) }
+func (c *sigctxt) gs() uint32        { return uint32(c.regs().gs) }
+func (c *sigctxt) sigcode() uint32   { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32   { return c.info.si_addr }
+
+func (c *sigctxt) set_eip(x uint32)     { c.regs().eip = x }
+func (c *sigctxt) set_esp(x uint32)     { c.regs().esp = x }
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) {
+       *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_linux_386.h b/src/runtime/signal_linux_386.h
deleted file mode 100644 (file)
index f77f1c9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
-
-#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
-#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
-#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
-#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
-#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
-#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
-#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
-#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
-#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
-#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
-
diff --git a/src/runtime/signal_linux_amd64.go b/src/runtime/signal_linux_amd64.go
new file mode 100644 (file)
index 0000000..5e339b8
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext {
+       return (*sigcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
+}
+func (c *sigctxt) rax() uint64     { return c.regs().rax }
+func (c *sigctxt) rbx() uint64     { return c.regs().rbx }
+func (c *sigctxt) rcx() uint64     { return c.regs().rcx }
+func (c *sigctxt) rdx() uint64     { return c.regs().rdx }
+func (c *sigctxt) rdi() uint64     { return c.regs().rdi }
+func (c *sigctxt) rsi() uint64     { return c.regs().rsi }
+func (c *sigctxt) rbp() uint64     { return c.regs().rbp }
+func (c *sigctxt) rsp() uint64     { return c.regs().rsp }
+func (c *sigctxt) r8() uint64      { return c.regs().r8 }
+func (c *sigctxt) r9() uint64      { return c.regs().r9 }
+func (c *sigctxt) r10() uint64     { return c.regs().r10 }
+func (c *sigctxt) r11() uint64     { return c.regs().r11 }
+func (c *sigctxt) r12() uint64     { return c.regs().r12 }
+func (c *sigctxt) r13() uint64     { return c.regs().r13 }
+func (c *sigctxt) r14() uint64     { return c.regs().r14 }
+func (c *sigctxt) r15() uint64     { return c.regs().r15 }
+func (c *sigctxt) rip() uint64     { return c.regs().rip }
+func (c *sigctxt) rflags() uint64  { return c.regs().eflags }
+func (c *sigctxt) cs() uint64      { return uint64(c.regs().cs) }
+func (c *sigctxt) fs() uint64      { return uint64(c.regs().fs) }
+func (c *sigctxt) gs() uint64      { return uint64(c.regs().gs) }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_linux_amd64.h b/src/runtime/signal_linux_amd64.h
deleted file mode 100644 (file)
index 5a9a3e5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
-#define SIG_RFLAGS(info, ctxt) ((uint64)SIG_REGS(ctxt).eflags)
-
-#define SIG_CS(info, ctxt) ((uint64)SIG_REGS(ctxt).cs)
-#define SIG_FS(info, ctxt) ((uint64)SIG_REGS(ctxt).fs)
-#define SIG_GS(info, ctxt) ((uint64)SIG_REGS(ctxt).gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
-
diff --git a/src/runtime/signal_linux_arm.go b/src/runtime/signal_linux_arm.go
new file mode 100644 (file)
index 0000000..bdb4314
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) r0() uint32        { return c.regs().r0 }
+func (c *sigctxt) r1() uint32        { return c.regs().r1 }
+func (c *sigctxt) r2() uint32        { return c.regs().r2 }
+func (c *sigctxt) r3() uint32        { return c.regs().r3 }
+func (c *sigctxt) r4() uint32        { return c.regs().r4 }
+func (c *sigctxt) r5() uint32        { return c.regs().r5 }
+func (c *sigctxt) r6() uint32        { return c.regs().r6 }
+func (c *sigctxt) r7() uint32        { return c.regs().r7 }
+func (c *sigctxt) r8() uint32        { return c.regs().r8 }
+func (c *sigctxt) r9() uint32        { return c.regs().r9 }
+func (c *sigctxt) r10() uint32       { return c.regs().r10 }
+func (c *sigctxt) fp() uint32        { return c.regs().fp }
+func (c *sigctxt) ip() uint32        { return c.regs().ip }
+func (c *sigctxt) sp() uint32        { return c.regs().sp }
+func (c *sigctxt) lr() uint32        { return c.regs().lr }
+func (c *sigctxt) pc() uint32        { return c.regs().pc }
+func (c *sigctxt) cpsr() uint32      { return c.regs().cpsr }
+func (c *sigctxt) fault() uint32     { return c.regs().fault_address }
+func (c *sigctxt) trap() uint32      { return c.regs().trap_no }
+func (c *sigctxt) error() uint32     { return c.regs().error_code }
+func (c *sigctxt) oldmask() uint32   { return c.regs().oldmask }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32 { return c.info.si_addr }
+
+func (c *sigctxt) set_pc(x uint32)  { c.regs().pc = x }
+func (c *sigctxt) set_sp(x uint32)  { c.regs().sp = x }
+func (c *sigctxt) set_lr(x uint32)  { c.regs().lr = x }
+func (c *sigctxt) set_r10(x uint32) { c.regs().r10 = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) {
+       *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_linux_arm.h b/src/runtime/signal_linux_arm.h
deleted file mode 100644 (file)
index a674c0d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
-
-#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).arm_r0)
-#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).arm_r1)
-#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).arm_r2)
-#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).arm_r3)
-#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).arm_r4)
-#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).arm_r5)
-#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).arm_r6)
-#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).arm_r7)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).arm_r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).arm_r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).arm_r10)
-#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).arm_fp)
-#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).arm_ip)
-#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).arm_sp)
-#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).arm_lr)
-#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).arm_pc)
-#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).arm_cpsr)
-#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).fault_address)
-#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap_no)
-#define SIG_ERROR(info, ctxt) (SIG_REGS(ctxt).error_code)
-#define SIG_OLDMASK(info, ctxt) (SIG_REGS(ctxt).oldmask)
-#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
diff --git a/src/runtime/signal_linux_power64x.go b/src/runtime/signal_linux_power64x.go
new file mode 100644 (file)
index 0000000..0a406b3
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *ptregs { return (*ucontext)(c.ctxt).uc_mcontext.regs }
+func (c *sigctxt) r0() uint64    { return c.regs().gpr[0] }
+func (c *sigctxt) r1() uint64    { return c.regs().gpr[1] }
+func (c *sigctxt) r2() uint64    { return c.regs().gpr[2] }
+func (c *sigctxt) r3() uint64    { return c.regs().gpr[3] }
+func (c *sigctxt) r4() uint64    { return c.regs().gpr[4] }
+func (c *sigctxt) r5() uint64    { return c.regs().gpr[5] }
+func (c *sigctxt) r6() uint64    { return c.regs().gpr[6] }
+func (c *sigctxt) r7() uint64    { return c.regs().gpr[7] }
+func (c *sigctxt) r8() uint64    { return c.regs().gpr[8] }
+func (c *sigctxt) r9() uint64    { return c.regs().gpr[9] }
+func (c *sigctxt) r10() uint64   { return c.regs().gpr[10] }
+func (c *sigctxt) r11() uint64   { return c.regs().gpr[11] }
+func (c *sigctxt) r12() uint64   { return c.regs().gpr[12] }
+func (c *sigctxt) r13() uint64   { return c.regs().gpr[13] }
+func (c *sigctxt) r14() uint64   { return c.regs().gpr[14] }
+func (c *sigctxt) r15() uint64   { return c.regs().gpr[15] }
+func (c *sigctxt) r16() uint64   { return c.regs().gpr[16] }
+func (c *sigctxt) r17() uint64   { return c.regs().gpr[17] }
+func (c *sigctxt) r18() uint64   { return c.regs().gpr[18] }
+func (c *sigctxt) r19() uint64   { return c.regs().gpr[19] }
+func (c *sigctxt) r20() uint64   { return c.regs().gpr[20] }
+func (c *sigctxt) r21() uint64   { return c.regs().gpr[21] }
+func (c *sigctxt) r22() uint64   { return c.regs().gpr[22] }
+func (c *sigctxt) r23() uint64   { return c.regs().gpr[23] }
+func (c *sigctxt) r24() uint64   { return c.regs().gpr[24] }
+func (c *sigctxt) r25() uint64   { return c.regs().gpr[25] }
+func (c *sigctxt) r26() uint64   { return c.regs().gpr[26] }
+func (c *sigctxt) r27() uint64   { return c.regs().gpr[27] }
+func (c *sigctxt) r28() uint64   { return c.regs().gpr[28] }
+func (c *sigctxt) r29() uint64   { return c.regs().gpr[29] }
+func (c *sigctxt) r30() uint64   { return c.regs().gpr[30] }
+func (c *sigctxt) r31() uint64   { return c.regs().gpr[31] }
+func (c *sigctxt) sp() uint64    { return c.regs().gpr[1] }
+func (c *sigctxt) pc() uint64    { return c.regs().nip }
+func (c *sigctxt) trap() uint64  { return c.regs().trap }
+func (c *sigctxt) ctr() uint64   { return c.regs().ctr }
+func (c *sigctxt) link() uint64  { return c.regs().link }
+func (c *sigctxt) xer() uint64   { return c.regs().xer }
+func (c *sigctxt) ccr() uint64   { return c.regs().ccr }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
+func (c *sigctxt) fault() uint64   { return c.regs().dar }
+
+func (c *sigctxt) set_r0(x uint64)   { c.regs().gpr[0] = x }
+func (c *sigctxt) set_r30(x uint64)  { c.regs().gpr[30] = x }
+func (c *sigctxt) set_pc(x uint64)   { c.regs().nip = x }
+func (c *sigctxt) set_sp(x uint64)   { c.regs().gpr[1] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().link = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_openbsd.go b/src/runtime/signal_openbsd.go
new file mode 100644 (file)
index 0000000..78afc59
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /*  0 */ {0, "SIGNONE: no trap"},
+       /*  1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /*  2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /*  3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /*  4 */ {_SigThrow, "SIGILL: illegal instruction"},
+       /*  5 */ {_SigThrow, "SIGTRAP: trace trap"},
+       /*  6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /*  7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
+       /*  8 */ {_SigPanic, "SIGFPE: floating-point exception"},
+       /*  9 */ {0, "SIGKILL: kill"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigThrow, "SIGSYS: bad system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /* 17 */ {0, "SIGSTOP: stop"},
+       /* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /* 19 */ {0, "SIGCONT: continue after stop"},
+       /* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
+       /* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /* 27 */ {_SigNotify, "SIGPROF: profiling alarm clock"},
+       /* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
+       /* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+       /* 32 */ {_SigNotify, "SIGTHR: reserved"},
+}
diff --git a/src/runtime/signal_openbsd_386.go b/src/runtime/signal_openbsd_386.go
new file mode 100644 (file)
index 0000000..c582a44
--- /dev/null
@@ -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 runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext {
+       return (*sigcontext)(c.ctxt)
+}
+
+func (c *sigctxt) eax() uint32     { return c.regs().sc_eax }
+func (c *sigctxt) ebx() uint32     { return c.regs().sc_ebx }
+func (c *sigctxt) ecx() uint32     { return c.regs().sc_ecx }
+func (c *sigctxt) edx() uint32     { return c.regs().sc_edx }
+func (c *sigctxt) edi() uint32     { return c.regs().sc_edi }
+func (c *sigctxt) esi() uint32     { return c.regs().sc_esi }
+func (c *sigctxt) ebp() uint32     { return c.regs().sc_ebp }
+func (c *sigctxt) esp() uint32     { return c.regs().sc_esp }
+func (c *sigctxt) eip() uint32     { return c.regs().sc_eip }
+func (c *sigctxt) eflags() uint32  { return c.regs().sc_eflags }
+func (c *sigctxt) cs() uint32      { return c.regs().sc_cs }
+func (c *sigctxt) fs() uint32      { return c.regs().sc_fs }
+func (c *sigctxt) gs() uint32      { return c.regs().sc_gs }
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32 {
+       return *(*uint32)(add(unsafe.Pointer(c.info), 12))
+}
+
+func (c *sigctxt) set_eip(x uint32)     { c.regs().sc_eip = x }
+func (c *sigctxt) set_esp(x uint32)     { c.regs().sc_esp = x }
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) {
+       *(*uint32)(add(unsafe.Pointer(c.info), 12)) = x
+}
diff --git a/src/runtime/signal_openbsd_386.h b/src/runtime/signal_openbsd_386.h
deleted file mode 100644 (file)
index 6742db8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (*(Sigcontext*)(ctxt))
-
-#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).sc_eax)
-#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).sc_ebx)
-#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).sc_ecx)
-#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).sc_edx)
-#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).sc_edi)
-#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).sc_esi)
-#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).sc_ebp)
-#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).sc_esp)
-#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).sc_eip)
-#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).sc_eflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).sc_cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).sc_fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).sc_gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) (*(uintptr*)((byte*)info + 12))
diff --git a/src/runtime/signal_openbsd_amd64.go b/src/runtime/signal_openbsd_amd64.go
new file mode 100644 (file)
index 0000000..4f0d19d
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext {
+       return (*sigcontext)(c.ctxt)
+}
+
+func (c *sigctxt) rax() uint64     { return c.regs().sc_rax }
+func (c *sigctxt) rbx() uint64     { return c.regs().sc_rbx }
+func (c *sigctxt) rcx() uint64     { return c.regs().sc_rcx }
+func (c *sigctxt) rdx() uint64     { return c.regs().sc_rdx }
+func (c *sigctxt) rdi() uint64     { return c.regs().sc_rdi }
+func (c *sigctxt) rsi() uint64     { return c.regs().sc_rsi }
+func (c *sigctxt) rbp() uint64     { return c.regs().sc_rbp }
+func (c *sigctxt) rsp() uint64     { return c.regs().sc_rsp }
+func (c *sigctxt) r8() uint64      { return c.regs().sc_r8 }
+func (c *sigctxt) r9() uint64      { return c.regs().sc_r9 }
+func (c *sigctxt) r10() uint64     { return c.regs().sc_r10 }
+func (c *sigctxt) r11() uint64     { return c.regs().sc_r11 }
+func (c *sigctxt) r12() uint64     { return c.regs().sc_r12 }
+func (c *sigctxt) r13() uint64     { return c.regs().sc_r13 }
+func (c *sigctxt) r14() uint64     { return c.regs().sc_r14 }
+func (c *sigctxt) r15() uint64     { return c.regs().sc_r15 }
+func (c *sigctxt) rip() uint64     { return c.regs().sc_rip }
+func (c *sigctxt) rflags() uint64  { return c.regs().sc_rflags }
+func (c *sigctxt) cs() uint64      { return c.regs().sc_cs }
+func (c *sigctxt) fs() uint64      { return c.regs().sc_fs }
+func (c *sigctxt) gs() uint64      { return c.regs().sc_gs }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 {
+       return *(*uint64)(add(unsafe.Pointer(c.info), 16))
+}
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().sc_rip = x }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().sc_rsp = x }
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uint64)(add(unsafe.Pointer(c.info), 16)) = x
+}
diff --git a/src/runtime/signal_openbsd_amd64.h b/src/runtime/signal_openbsd_amd64.h
deleted file mode 100644 (file)
index b46a5df..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (*(Sigcontext*)(ctxt))
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).sc_rax)
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).sc_rbx)
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).sc_rcx)
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).sc_rdx)
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).sc_rdi)
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).sc_rsi)
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).sc_rbp)
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).sc_rsp)
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).sc_r8)
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).sc_r9)
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).sc_r10)
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).sc_r11)
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).sc_r12)
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).sc_r13)
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).sc_r14)
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).sc_r15)
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).sc_rip)
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).sc_rflags)
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).sc_cs)
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).sc_fs)
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).sc_gs)
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) (*(uintptr*)((byte*)(info) + 16))
diff --git a/src/runtime/signal_power64x.go b/src/runtime/signal_power64x.go
new file mode 100644 (file)
index 0000000..fc83beb
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(c *sigctxt) {
+       print("r0   ", hex(c.r0()), "\t")
+       print("r1   ", hex(c.r1()), "\n")
+       print("r2   ", hex(c.r2()), "\t")
+       print("r3   ", hex(c.r3()), "\n")
+       print("r4   ", hex(c.r4()), "\t")
+       print("r5   ", hex(c.r5()), "\n")
+       print("r6   ", hex(c.r6()), "\t")
+       print("r7   ", hex(c.r7()), "\n")
+       print("r8   ", hex(c.r8()), "\t")
+       print("r9   ", hex(c.r9()), "\n")
+       print("r10  ", hex(c.r10()), "\t")
+       print("r11  ", hex(c.r11()), "\n")
+       print("r12  ", hex(c.r12()), "\t")
+       print("r13  ", hex(c.r13()), "\n")
+       print("r14  ", hex(c.r14()), "\t")
+       print("r15  ", hex(c.r15()), "\n")
+       print("r16  ", hex(c.r16()), "\t")
+       print("r17  ", hex(c.r17()), "\n")
+       print("r18  ", hex(c.r18()), "\t")
+       print("r19  ", hex(c.r19()), "\n")
+       print("r20  ", hex(c.r20()), "\t")
+       print("r21  ", hex(c.r21()), "\n")
+       print("r22  ", hex(c.r22()), "\t")
+       print("r23  ", hex(c.r23()), "\n")
+       print("r24  ", hex(c.r24()), "\t")
+       print("r25  ", hex(c.r25()), "\n")
+       print("r26  ", hex(c.r26()), "\t")
+       print("r27  ", hex(c.r27()), "\n")
+       print("r28  ", hex(c.r28()), "\t")
+       print("r29  ", hex(c.r29()), "\n")
+       print("r30  ", hex(c.r30()), "\t")
+       print("r31  ", hex(c.r31()), "\n")
+       print("pc   ", hex(c.pc()), "\t")
+       print("ctr  ", hex(c.ctr()), "\n")
+       print("link ", hex(c.link()), "\t")
+       print("xer  ", hex(c.xer()), "\n")
+       print("ccr  ", hex(c.ccr()), "\t")
+       print("trap ", hex(c.trap()), "\n")
+}
+
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+       _g_ := getg()
+       c := &sigctxt{info, ctxt}
+
+       if sig == _SIGPROF {
+               sigprof((*byte)(unsafe.Pointer(uintptr(c.pc()))), (*byte)(unsafe.Pointer(uintptr(c.sp()))), (*byte)(unsafe.Pointer(uintptr(c.link()))), gp, _g_.m)
+               return
+       }
+       flags := int32(_SigThrow)
+       if sig < uint32(len(sigtable)) {
+               flags = sigtable[sig].flags
+       }
+       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+               // Make it look like a call to the signal func.
+               // Have to pass arguments out of band since
+               // augmenting the stack frame would break
+               // the unwinding code.
+               gp.sig = sig
+               gp.sigcode0 = uintptr(c.sigcode())
+               gp.sigcode1 = uintptr(c.fault())
+               gp.sigpc = uintptr(c.pc())
+
+               // We arrange link, and pc to pretend the panicking
+               // function calls sigpanic directly.
+               // Always save LINK to stack so that panics in leaf
+               // functions are correctly handled. This smashes
+               // the stack frame but we're not going back there
+               // anyway.
+               sp := c.sp() - ptrSize
+               c.set_sp(sp)
+               *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
+
+               // 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 gp.sigpc != 0 {
+                       c.set_link(uint64(gp.sigpc))
+               }
+
+               // In case we are panicking from external C code
+               c.set_r0(0)
+               c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
+               c.set_pc(uint64(funcPC(sigpanic)))
+               return
+       }
+
+       if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+               if sigsend(sig) {
+                       return
+               }
+       }
+
+       if flags&_SigKill != 0 {
+               exit(2)
+       }
+
+       if flags&_SigThrow == 0 {
+               return
+       }
+
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+
+       if sig < uint32(len(sigtable)) {
+               print(sigtable[sig].name, "\n")
+       } else {
+               print("Signal ", sig, "\n")
+       }
+
+       print("PC=", hex(c.pc()), "\n")
+       if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg
+       }
+       print("\n")
+
+       var docrash bool
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(c)
+       }
+
+       if docrash {
+               crash()
+       }
+
+       exit(2)
+}
diff --git a/src/runtime/signal_solaris.go b/src/runtime/signal_solaris.go
new file mode 100644 (file)
index 0000000..2986c5a
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /* 0 */ {0, "SIGNONE: no trap"},
+       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: hangup"},
+       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt (rubout)"},
+       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit (ASCII FS)"},
+       /* 4 */ {_SigThrow, "SIGILL: illegal instruction (not reset when caught)"},
+       /* 5 */ {_SigThrow, "SIGTRAP: trace trap (not reset when caught)"},
+       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: used by abort, replace SIGIOT in the future"},
+       /* 7 */ {_SigThrow, "SIGEMT: EMT instruction"},
+       /* 8 */ {_SigPanic, "SIGFPE: floating point exception"},
+       /* 9 */ {0, "SIGKILL: kill (cannot be caught or ignored)"},
+       /* 10 */ {_SigPanic, "SIGBUS: bus error"},
+       /* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
+       /* 12 */ {_SigThrow, "SIGSYS: bad argument to system call"},
+       /* 13 */ {_SigNotify, "SIGPIPE: write on a pipe with no one to read it"},
+       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: software termination signal from kill"},
+       /* 16 */ {_SigNotify, "SIGUSR1: user defined signal 1"},
+       /* 17 */ {_SigNotify, "SIGUSR2: user defined signal 2"},
+       /* 18 */ {_SigNotify, "SIGCHLD: child status change alias (POSIX)"},
+       /* 19 */ {_SigNotify, "SIGPWR: power-fail restart"},
+       /* 20 */ {_SigNotify, "SIGWINCH: window size change"},
+       /* 21 */ {_SigNotify, "SIGURG: urgent socket condition"},
+       /* 22 */ {_SigNotify, "SIGPOLL: pollable event occured"},
+       /* 23 */ {_SigNotify + _SigDefault, "SIGSTOP: stop (cannot be caught or ignored)"},
+       /* 24 */ {0, "SIGTSTP: user stop requested from tty"},
+       /* 25 */ {0, "SIGCONT: stopped process has been continued"},
+       /* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background tty read attempted"},
+       /* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background tty write attempted"},
+       /* 28 */ {_SigNotify, "SIGVTALRM: virtual timer expired"},
+       /* 29 */ {_SigNotify, "SIGPROF: profiling timer expired"},
+       /* 30 */ {_SigNotify, "SIGXCPU: exceeded cpu limit"},
+       /* 31 */ {_SigNotify, "SIGXFSZ: exceeded file size limit"},
+       /* 32 */ {_SigNotify, "SIGWAITING: reserved signal no longer used by"},
+       /* 33 */ {_SigNotify, "SIGLWP: reserved signal no longer used by"},
+       /* 34 */ {_SigNotify, "SIGFREEZE: special signal used by CPR"},
+       /* 35 */ {_SigNotify, "SIGTHAW: special signal used by CPR"},
+       /* 36 */ {0, "SIGCANCEL: reserved signal for thread cancellation"},
+       /* 37 */ {_SigNotify, "SIGLOST: resource lost (eg, record-lock lost)"},
+       /* 38 */ {_SigNotify, "SIGXRES: resource control exceeded"},
+       /* 39 */ {_SigNotify, "SIGJVM1: reserved signal for Java Virtual Machine"},
+       /* 40 */ {_SigNotify, "SIGJVM2: reserved signal for Java Virtual Machine"},
+
+       /* TODO(aram): what should be do about these signals? _SigDefault or _SigNotify? is this set static? */
+       /* 41 */ {_SigNotify, "real time signal"},
+       /* 42 */ {_SigNotify, "real time signal"},
+       /* 43 */ {_SigNotify, "real time signal"},
+       /* 44 */ {_SigNotify, "real time signal"},
+       /* 45 */ {_SigNotify, "real time signal"},
+       /* 46 */ {_SigNotify, "real time signal"},
+       /* 47 */ {_SigNotify, "real time signal"},
+       /* 48 */ {_SigNotify, "real time signal"},
+       /* 49 */ {_SigNotify, "real time signal"},
+       /* 50 */ {_SigNotify, "real time signal"},
+       /* 51 */ {_SigNotify, "real time signal"},
+       /* 52 */ {_SigNotify, "real time signal"},
+       /* 53 */ {_SigNotify, "real time signal"},
+       /* 54 */ {_SigNotify, "real time signal"},
+       /* 55 */ {_SigNotify, "real time signal"},
+       /* 56 */ {_SigNotify, "real time signal"},
+       /* 57 */ {_SigNotify, "real time signal"},
+       /* 58 */ {_SigNotify, "real time signal"},
+       /* 59 */ {_SigNotify, "real time signal"},
+       /* 60 */ {_SigNotify, "real time signal"},
+       /* 61 */ {_SigNotify, "real time signal"},
+       /* 62 */ {_SigNotify, "real time signal"},
+       /* 63 */ {_SigNotify, "real time signal"},
+       /* 64 */ {_SigNotify, "real time signal"},
+       /* 65 */ {_SigNotify, "real time signal"},
+       /* 66 */ {_SigNotify, "real time signal"},
+       /* 67 */ {_SigNotify, "real time signal"},
+       /* 68 */ {_SigNotify, "real time signal"},
+       /* 69 */ {_SigNotify, "real time signal"},
+       /* 70 */ {_SigNotify, "real time signal"},
+       /* 71 */ {_SigNotify, "real time signal"},
+       /* 72 */ {_SigNotify, "real time signal"},
+}
diff --git a/src/runtime/signal_solaris_amd64.go b/src/runtime/signal_solaris_amd64.go
new file mode 100644 (file)
index 0000000..a577c8c
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *mcontext {
+       return (*mcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
+}
+func (c *sigctxt) rax() uint64     { return uint64(c.regs().gregs[_REG_RAX]) }
+func (c *sigctxt) rbx() uint64     { return uint64(c.regs().gregs[_REG_RBX]) }
+func (c *sigctxt) rcx() uint64     { return uint64(c.regs().gregs[_REG_RCX]) }
+func (c *sigctxt) rdx() uint64     { return uint64(c.regs().gregs[_REG_RDX]) }
+func (c *sigctxt) rdi() uint64     { return uint64(c.regs().gregs[_REG_RDI]) }
+func (c *sigctxt) rsi() uint64     { return uint64(c.regs().gregs[_REG_RSI]) }
+func (c *sigctxt) rbp() uint64     { return uint64(c.regs().gregs[_REG_RBP]) }
+func (c *sigctxt) rsp() uint64     { return uint64(c.regs().gregs[_REG_RSP]) }
+func (c *sigctxt) r8() uint64      { return uint64(c.regs().gregs[_REG_R8]) }
+func (c *sigctxt) r9() uint64      { return uint64(c.regs().gregs[_REG_R9]) }
+func (c *sigctxt) r10() uint64     { return uint64(c.regs().gregs[_REG_R10]) }
+func (c *sigctxt) r11() uint64     { return uint64(c.regs().gregs[_REG_R11]) }
+func (c *sigctxt) r12() uint64     { return uint64(c.regs().gregs[_REG_R12]) }
+func (c *sigctxt) r13() uint64     { return uint64(c.regs().gregs[_REG_R13]) }
+func (c *sigctxt) r14() uint64     { return uint64(c.regs().gregs[_REG_R14]) }
+func (c *sigctxt) r15() uint64     { return uint64(c.regs().gregs[_REG_R15]) }
+func (c *sigctxt) rip() uint64     { return uint64(c.regs().gregs[_REG_RIP]) }
+func (c *sigctxt) rflags() uint64  { return uint64(c.regs().gregs[_REG_RFLAGS]) }
+func (c *sigctxt) cs() uint64      { return uint64(c.regs().gregs[_REG_CS]) }
+func (c *sigctxt) fs() uint64      { return uint64(c.regs().gregs[_REG_FS]) }
+func (c *sigctxt) gs() uint64      { return uint64(c.regs().gregs[_REG_GS]) }
+func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return *(*uint64)(unsafe.Pointer(&c.info.__data[0])) }
+
+func (c *sigctxt) set_rip(x uint64)     { c.regs().gregs[_REG_RIP] = int64(x) }
+func (c *sigctxt) set_rsp(x uint64)     { c.regs().gregs[_REG_RSP] = int64(x) }
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+       *(*uintptr)(unsafe.Pointer(&c.info.__data[0])) = uintptr(x)
+}
diff --git a/src/runtime/signal_solaris_amd64.h b/src/runtime/signal_solaris_amd64.h
deleted file mode 100644 (file)
index c2e0a15..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
-
-#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RAX])
-#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RBX])
-#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RCX])
-#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RDX])
-#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RDI])
-#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RSI])
-#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RBP])
-#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RSP])
-#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R8])
-#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R9])
-#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R10])
-#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R11])
-#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R12])
-#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R13])
-#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R14])
-#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R15])
-#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RIP])
-#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RFLAGS])
-
-#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_CS])
-#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_FS])
-#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_GS])
-
-#define SIG_CODE0(info, ctxt) ((info)->si_code)
-#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->__data[0])
diff --git a/src/runtime/signal_unix.c b/src/runtime/signal_unix.c
deleted file mode 100644 (file)
index 0e33ece..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signal_unix.h"
-
-extern SigTab runtime·sigtab[];
-
-void
-runtime·initsig(void)
-{
-       int32 i;
-       SigTab *t;
-
-       // First call: basic setup.
-       for(i = 0; i<NSIG; i++) {
-               t = &runtime·sigtab[i];
-               if((t->flags == 0) || (t->flags & SigDefault))
-                       continue;
-
-               // For some signals, we respect an inherited SIG_IGN handler
-               // rather than insist on installing our own default handler.
-               // Even these signals can be fetched using the os/signal package.
-               switch(i) {
-               case SIGHUP:
-               case SIGINT:
-                       if(runtime·getsig(i) == SIG_IGN) {
-                               t->flags = SigNotify | SigIgnored;
-                               continue;
-                       }
-               }
-
-               t->flags |= SigHandling;
-               runtime·setsig(i, runtime·sighandler, true);
-       }
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       SigTab *t;
-
-       if(sig >= NSIG)
-               return;
-
-       t = &runtime·sigtab[sig];
-       if((t->flags & SigNotify) && !(t->flags & SigHandling)) {
-               t->flags |= SigHandling;
-               if(runtime·getsig(sig) == SIG_IGN)
-                       t->flags |= SigIgnored;
-               runtime·setsig(sig, runtime·sighandler, true);
-       }
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       SigTab *t;
-
-       if(sig >= NSIG)
-               return;
-
-       t = &runtime·sigtab[sig];
-       if((t->flags & SigNotify) && (t->flags & SigHandling)) {
-               t->flags &= ~SigHandling;
-               if(t->flags & SigIgnored)
-                       runtime·setsig(sig, SIG_IGN, true);
-               else
-                       runtime·setsig(sig, SIG_DFL, true);
-       }
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       Itimerval it;
-
-       runtime·memclr((byte*)&it, sizeof it);
-       if(hz == 0) {
-               runtime·setitimer(ITIMER_PROF, &it, nil);
-       } else {
-               it.it_interval.tv_sec = 0;
-               it.it_interval.tv_usec = 1000000 / hz;
-               it.it_value = it.it_interval;
-               runtime·setitimer(ITIMER_PROF, &it, nil);
-       }
-       g->m->profilehz = hz;
-}
-
-void
-runtime·sigpipe(void)
-{
-       runtime·setsig(SIGPIPE, SIG_DFL, false);
-       runtime·raise(SIGPIPE);
-}
-
-void
-runtime·crash(void)
-{
-#ifdef GOOS_darwin
-       // OS X core dumps are linear dumps of the mapped memory,
-       // from the first virtual byte to the last, with zeros in the gaps.
-       // Because of the way we arrange the address space on 64-bit systems,
-       // this means the OS X core file will be >128 GB and even on a zippy
-       // workstation can take OS X well over an hour to write (uninterruptible).
-       // Save users from making that mistake.
-       if(sizeof(void*) == 8)
-               return;
-#endif
-
-       runtime·unblocksignals();
-       runtime·setsig(SIGABRT, SIG_DFL, false);
-       runtime·raise(SIGABRT);
-}
index ba77b6e7be12f87ea0b99bb99b83220a9eb125aa..c457083dcfe73c33fc3ba114968af7b6bb8e71f6 100644 (file)
@@ -6,8 +6,6 @@
 
 package runtime
 
-func sigpipe()
-
 func os_sigpipe() {
-       onM(sigpipe)
+       systemstack(sigpipe)
 }
diff --git a/src/runtime/signals_darwin.h b/src/runtime/signals_darwin.h
deleted file mode 100644 (file)
index 8761e1b..0000000
+++ /dev/null
@@ -1,53 +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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /* 0 */ 0, "SIGNONE: no trap",
-       /* 1 */ N+K, "SIGHUP: terminal line hangup",
-       /* 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",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        N, "SIGURG: urgent condition on socket",
-       /* 17 */        0, "SIGSTOP: stop",
-       /* 18 */        N+D, "SIGTSTP: keyboard stop",
-       /* 19 */        0, "SIGCONT: continue after stop",
-       /* 20 */        N, "SIGCHLD: child status has changed",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGIO: i/o now possible",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGINFO: status request from keyboard",
-       /* 30 */        N, "SIGUSR1: user-defined signal 1",
-       /* 31 */        N, "SIGUSR2: user-defined signal 2",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
diff --git a/src/runtime/signals_dragonfly.h b/src/runtime/signals_dragonfly.h
deleted file mode 100644 (file)
index 07343a7..0000000
+++ /dev/null
@@ -1,54 +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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /* 0 */ 0, "SIGNONE: no trap",
-       /* 1 */ N+K, "SIGHUP: terminal line hangup",
-       /* 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",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        N, "SIGURG: urgent condition on socket",
-       /* 17 */        0, "SIGSTOP: stop",
-       /* 18 */        N+D, "SIGTSTP: keyboard stop",
-       /* 19 */        0, "SIGCONT: continue after stop",
-       /* 20 */        N, "SIGCHLD: child status has changed",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGIO: i/o now possible",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGINFO: status request from keyboard",
-       /* 30 */        N, "SIGUSR1: user-defined signal 1",
-       /* 31 */        N, "SIGUSR2: user-defined signal 2",
-       /* 32 */        N, "SIGTHR: reserved",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
diff --git a/src/runtime/signals_freebsd.h b/src/runtime/signals_freebsd.h
deleted file mode 100644 (file)
index 39e0a94..0000000
+++ /dev/null
@@ -1,54 +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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /* 0 */ 0, "SIGNONE: no trap",
-       /* 1 */ N+K, "SIGHUP: terminal line hangup",
-       /* 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 */        N, "SIGSYS: bad system call",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        N, "SIGURG: urgent condition on socket",
-       /* 17 */        0, "SIGSTOP: stop",
-       /* 18 */        N+D, "SIGTSTP: keyboard stop",
-       /* 19 */        0, "SIGCONT: continue after stop",
-       /* 20 */        N, "SIGCHLD: child status has changed",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGIO: i/o now possible",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGINFO: status request from keyboard",
-       /* 30 */        N, "SIGUSR1: user-defined signal 1",
-       /* 31 */        N, "SIGUSR2: user-defined signal 2",
-       /* 32 */        N, "SIGTHR: reserved",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
diff --git a/src/runtime/signals_linux.h b/src/runtime/signals_linux.h
deleted file mode 100644 (file)
index 3741076..0000000
+++ /dev/null
@@ -1,86 +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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /* 0 */ 0, "SIGNONE: no trap",
-       /* 1 */ N+K, "SIGHUP: terminal line hangup",
-       /* 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 */ P, "SIGBUS: bus error",
-       /* 8 */ P, "SIGFPE: floating-point exception",
-       /* 9 */ 0, "SIGKILL: kill",
-       /* 10 */        N, "SIGUSR1: user-defined signal 1",
-       /* 11 */        P, "SIGSEGV: segmentation violation",
-       /* 12 */        N, "SIGUSR2: user-defined signal 2",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        T, "SIGSTKFLT: stack fault",
-       /* 17 */        N, "SIGCHLD: child status has changed",
-       /* 18 */        0, "SIGCONT: continue",
-       /* 19 */        0, "SIGSTOP: stop, unblockable",
-       /* 20 */        N+D, "SIGTSTP: keyboard stop",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGURG: urgent condition on socket",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGIO: i/o now possible",
-       /* 30 */        N, "SIGPWR: power failure restart",
-       /* 31 */        N, "SIGSYS: bad system call",
-       /* 32 */        0, "signal 32", /* SIGCANCEL; see issue 6997 */
-       /* 33 */        0, "signal 33", /* SIGSETXID; see issue 3871 */
-       /* 34 */        N, "signal 34",
-       /* 35 */        N, "signal 35",
-       /* 36 */        N, "signal 36",
-       /* 37 */        N, "signal 37",
-       /* 38 */        N, "signal 38",
-       /* 39 */        N, "signal 39",
-       /* 40 */        N, "signal 40",
-       /* 41 */        N, "signal 41",
-       /* 42 */        N, "signal 42",
-       /* 43 */        N, "signal 43",
-       /* 44 */        N, "signal 44",
-       /* 45 */        N, "signal 45",
-       /* 46 */        N, "signal 46",
-       /* 47 */        N, "signal 47",
-       /* 48 */        N, "signal 48",
-       /* 49 */        N, "signal 49",
-       /* 50 */        N, "signal 50",
-       /* 51 */        N, "signal 51",
-       /* 52 */        N, "signal 52",
-       /* 53 */        N, "signal 53",
-       /* 54 */        N, "signal 54",
-       /* 55 */        N, "signal 55",
-       /* 56 */        N, "signal 56",
-       /* 57 */        N, "signal 57",
-       /* 58 */        N, "signal 58",
-       /* 59 */        N, "signal 59",
-       /* 60 */        N, "signal 60",
-       /* 61 */        N, "signal 61",
-       /* 62 */        N, "signal 62",
-       /* 63 */        N, "signal 63",
-       /* 64 */        N, "signal 64",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
diff --git a/src/runtime/signals_openbsd.h b/src/runtime/signals_openbsd.h
deleted file mode 100644 (file)
index 950a2fe..0000000
+++ /dev/null
@@ -1,54 +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 "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /*  0 */        0, "SIGNONE: no trap",
-       /*  1 */        N+K, "SIGHUP: terminal line hangup",
-       /*  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",
-       /* 13 */        N, "SIGPIPE: write to broken pipe",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: termination",
-       /* 16 */        N, "SIGURG: urgent condition on socket",
-       /* 17 */        0, "SIGSTOP: stop",
-       /* 18 */        N+D, "SIGTSTP: keyboard stop",
-       /* 19 */        0, "SIGCONT: continue after stop",
-       /* 20 */        N, "SIGCHLD: child status has changed",
-       /* 21 */        N+D, "SIGTTIN: background read from tty",
-       /* 22 */        N+D, "SIGTTOU: background write to tty",
-       /* 23 */        N, "SIGIO: i/o now possible",
-       /* 24 */        N, "SIGXCPU: cpu limit exceeded",
-       /* 25 */        N, "SIGXFSZ: file size limit exceeded",
-       /* 26 */        N, "SIGVTALRM: virtual alarm clock",
-       /* 27 */        N, "SIGPROF: profiling alarm clock",
-       /* 28 */        N, "SIGWINCH: window size change",
-       /* 29 */        N, "SIGINFO: status request from keyboard",
-       /* 30 */        N, "SIGUSR1: user-defined signal 1",
-       /* 31 */        N, "SIGUSR2: user-defined signal 2",
-       /* 32 */        N, "SIGTHR: reserved",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
diff --git a/src/runtime/signals_solaris.h b/src/runtime/signals_solaris.h
deleted file mode 100644 (file)
index 1f0a65e..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "textflag.h"
-
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
-       /* 0 */         0, "SIGNONE: no trap",
-       /* 1 */         N+K, "SIGHUP: hangup",
-       /* 2 */         N+K, "SIGINT: interrupt (rubout)",
-       /* 3 */         N+T, "SIGQUIT: quit (ASCII FS)",
-       /* 4 */         T, "SIGILL: illegal instruction (not reset when caught)",
-       /* 5 */         T, "SIGTRAP: trace trap (not reset when caught)",
-       /* 6 */         N+T, "SIGABRT: used by abort, replace SIGIOT in the future",
-       /* 7 */         T, "SIGEMT: EMT instruction",
-       /* 8 */         P, "SIGFPE: floating point exception",
-       /* 9 */         0, "SIGKILL: kill (cannot be caught or ignored)",
-       /* 10 */        P, "SIGBUS: bus error",
-       /* 11 */        P, "SIGSEGV: segmentation violation",
-       /* 12 */        T, "SIGSYS: bad argument to system call",
-       /* 13 */        N, "SIGPIPE: write on a pipe with no one to read it",
-       /* 14 */        N, "SIGALRM: alarm clock",
-       /* 15 */        N+K, "SIGTERM: software termination signal from kill",
-       /* 16 */        N, "SIGUSR1: user defined signal 1",
-       /* 17 */        N, "SIGUSR2: user defined signal 2",
-       /* 18 */        N, "SIGCLD: child status change",
-       /* 18 */        N, "SIGCHLD: child status change alias (POSIX)",
-       /* 19 */        N, "SIGPWR: power-fail restart",
-       /* 20 */        N, "SIGWINCH: window size change",
-       /* 21 */        N, "SIGURG: urgent socket condition",
-       /* 22 */        N, "SIGPOLL: pollable event occured",
-       /* 23 */        N+D, "SIGSTOP: stop (cannot be caught or ignored)",
-       /* 24 */        0, "SIGTSTP: user stop requested from tty",
-       /* 25 */        0, "SIGCONT: stopped process has been continued",
-       /* 26 */        N+D, "SIGTTIN: background tty read attempted",
-       /* 27 */        N+D, "SIGTTOU: background tty write attempted",
-       /* 28 */        N, "SIGVTALRM: virtual timer expired",
-       /* 29 */        N, "SIGPROF: profiling timer expired",
-       /* 30 */        N, "SIGXCPU: exceeded cpu limit",
-       /* 31 */        N, "SIGXFSZ: exceeded file size limit",
-       /* 32 */        N, "SIGWAITING: reserved signal no longer used by",
-       /* 33 */        N, "SIGLWP: reserved signal no longer used by",
-       /* 34 */        N, "SIGFREEZE: special signal used by CPR",
-       /* 35 */        N, "SIGTHAW: special signal used by CPR",
-       /* 36 */        0, "SIGCANCEL: reserved signal for thread cancellation",
-       /* 37 */        N, "SIGLOST: resource lost (eg, record-lock lost)",
-       /* 38 */        N, "SIGXRES: resource control exceeded",
-       /* 39 */        N, "SIGJVM1: reserved signal for Java Virtual Machine",
-       /* 40 */        N, "SIGJVM2: reserved signal for Java Virtual Machine",
-
-       /* TODO(aram): what should be do about these signals? D or N? is this set static? */
-       /* 41 */        N, "real time signal",
-       /* 42 */        N, "real time signal",
-       /* 43 */        N, "real time signal",
-       /* 44 */        N, "real time signal",
-       /* 45 */        N, "real time signal",
-       /* 46 */        N, "real time signal",
-       /* 47 */        N, "real time signal",
-       /* 48 */        N, "real time signal",
-       /* 49 */        N, "real time signal",
-       /* 50 */        N, "real time signal",
-       /* 51 */        N, "real time signal",
-       /* 52 */        N, "real time signal",
-       /* 53 */        N, "real time signal",
-       /* 54 */        N, "real time signal",
-       /* 55 */        N, "real time signal",
-       /* 56 */        N, "real time signal",
-       /* 57 */        N, "real time signal",
-       /* 58 */        N, "real time signal",
-       /* 59 */        N, "real time signal",
-       /* 60 */        N, "real time signal",
-       /* 61 */        N, "real time signal",
-       /* 62 */        N, "real time signal",
-       /* 63 */        N, "real time signal",
-       /* 64 */        N, "real time signal",
-       /* 65 */        N, "real time signal",
-       /* 66 */        N, "real time signal",
-       /* 67 */        N, "real time signal",
-       /* 68 */        N, "real time signal",
-       /* 69 */        N, "real time signal",
-       /* 70 */        N, "real time signal",
-       /* 71 */        N, "real time signal",
-       /* 72 */        N, "real time signal",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
index 68079859b06704ee1f6d3e411dcf63a9ebb89701..7bf2c15409170ac27f014684078494e2ed8ee3e6 100644 (file)
@@ -6,8 +6,6 @@
 
 package runtime
 
-func signame(int32) *byte
-
 func sigpanic() {
        g := getg()
        if !canpanic(g) {
@@ -36,5 +34,10 @@ func sigpanic() {
                }
                panicfloat()
        }
-       panic(errorString(gostringnocopy(signame(g.sig))))
+
+       if g.sig >= uint32(len(sigtable)) {
+               // can't happen: we looked up g.sig in sigtable to decide to call sigpanic
+               gothrow("unexpected signal value")
+       }
+       panic(errorString(sigtable[g.sig].name))
 }
index 2d9c24d2d24909a206d7efddeb980ed9718b8f75..82ead228fa873694348770cac126600628f752cb 100644 (file)
@@ -45,7 +45,7 @@ const (
 
 // Called from sighandler to send a signal back out of the signal handling thread.
 // Reports whether the signal was sent. If not, the caller typically crashes the program.
-func sigsend(s int32) bool {
+func sigsend(s uint32) bool {
        bit := uint32(1) << uint(s&31)
        if !sig.inuse || s < 0 || int(s) >= 32*len(sig.wanted) || sig.wanted[s/32]&bit == 0 {
                return false
@@ -139,7 +139,7 @@ func signal_enable(s uint32) {
                return
        }
        sig.wanted[s/32] |= 1 << (s & 31)
-       sigenable_go(s)
+       sigenable(s)
 }
 
 // Must only be called from a single goroutine at a time.
@@ -148,7 +148,7 @@ func signal_disable(s uint32) {
                return
        }
        sig.wanted[s/32] &^= 1 << (s & 31)
-       sigdisable_go(s)
+       sigdisable(s)
 }
 
 // This runs on a foreign stack, without an m or a g.  No stack split.
@@ -156,18 +156,3 @@ func signal_disable(s uint32) {
 func badsignal(sig uintptr) {
        cgocallback(unsafe.Pointer(funcPC(sigsend)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
 }
-
-func sigenable_m()
-func sigdisable_m()
-
-func sigenable_go(s uint32) {
-       g := getg()
-       g.m.scalararg[0] = uintptr(s)
-       onM(sigenable_m)
-}
-
-func sigdisable_go(s uint32) {
-       g := getg()
-       g.m.scalararg[0] = uintptr(s)
-       onM(sigdisable_m)
-}
index 171087d7f6fe51c0c243e77d6338c04b4eff7282..93cea5cc38bd812a44b1535c73ae15215d5e7918 100644 (file)
@@ -22,11 +22,11 @@ func makeslice(t *slicetype, len64 int64, cap64 int64) sliceStruct {
        // but since the cap is only being supplied implicitly, saying len is clearer.
        // See issue 4085.
        len := int(len64)
-       if len64 < 0 || int64(len) != len64 || t.elem.size > 0 && uintptr(len) > maxmem/uintptr(t.elem.size) {
+       if len64 < 0 || int64(len) != len64 || t.elem.size > 0 && uintptr(len) > _MaxMem/uintptr(t.elem.size) {
                panic(errorString("makeslice: len out of range"))
        }
        cap := int(cap64)
-       if cap < len || int64(cap) != cap64 || t.elem.size > 0 && uintptr(cap) > maxmem/uintptr(t.elem.size) {
+       if cap < len || int64(cap) != cap64 || t.elem.size > 0 && uintptr(cap) > _MaxMem/uintptr(t.elem.size) {
                panic(errorString("makeslice: cap out of range"))
        }
        p := newarray(t.elem, uintptr(cap))
@@ -42,7 +42,7 @@ func growslice(t *slicetype, old sliceStruct, n int64) sliceStruct {
        cap64 := int64(old.cap) + n
        cap := int(cap64)
 
-       if int64(cap) != cap64 || cap < old.cap || t.elem.size > 0 && uintptr(cap) > maxmem/uintptr(t.elem.size) {
+       if int64(cap) != cap64 || cap < old.cap || t.elem.size > 0 && uintptr(cap) > _MaxMem/uintptr(t.elem.size) {
                panic(errorString("growslice: cap out of range"))
        }
 
@@ -72,7 +72,7 @@ func growslice(t *slicetype, old sliceStruct, n int64) sliceStruct {
                }
        }
 
-       if uintptr(newcap) >= maxmem/uintptr(et.size) {
+       if uintptr(newcap) >= _MaxMem/uintptr(et.size) {
                panic(errorString("growslice: cap out of range"))
        }
        lenmem := uintptr(old.len) * uintptr(et.size)
index 4fcf8f269018e90440157f2f7a1dd72dff00e24d..c157a14e268d3984e8a415cce008bd3822d09c5a 100644 (file)
@@ -340,7 +340,7 @@ func f32to64(f uint32) uint64 {
        return fpack64(fs64, uint64(fm)<<d, fe, 0)
 }
 
-func fcmp64(f, g uint64) (cmp int, isnan bool) {
+func fcmp64(f, g uint64) (cmp int32, isnan bool) {
        fs, fm, _, fi, fn := funpack64(f)
        gs, gm, _, gi, gn := funpack64(g)
 
@@ -486,13 +486,13 @@ again2:
 
 // callable from C
 
-func fadd64c(f, g uint64, ret *uint64)            { *ret = fadd64(f, g) }
-func fsub64c(f, g uint64, ret *uint64)            { *ret = fsub64(f, g) }
-func fmul64c(f, g uint64, ret *uint64)            { *ret = fmul64(f, g) }
-func fdiv64c(f, g uint64, ret *uint64)            { *ret = fdiv64(f, g) }
-func fneg64c(f uint64, ret *uint64)               { *ret = fneg64(f) }
-func f32to64c(f uint32, ret *uint64)              { *ret = f32to64(f) }
-func f64to32c(f uint64, ret *uint32)              { *ret = f64to32(f) }
-func fcmp64c(f, g uint64, ret *int, retnan *bool) { *ret, *retnan = fcmp64(f, g) }
-func fintto64c(val int64, ret *uint64)            { *ret = fintto64(val) }
-func f64tointc(f uint64, ret *int64, retok *bool) { *ret, *retok = f64toint(f) }
+func fadd64c(f, g uint64, ret *uint64)              { *ret = fadd64(f, g) }
+func fsub64c(f, g uint64, ret *uint64)              { *ret = fsub64(f, g) }
+func fmul64c(f, g uint64, ret *uint64)              { *ret = fmul64(f, g) }
+func fdiv64c(f, g uint64, ret *uint64)              { *ret = fdiv64(f, g) }
+func fneg64c(f uint64, ret *uint64)                 { *ret = fneg64(f) }
+func f32to64c(f uint32, ret *uint64)                { *ret = f32to64(f) }
+func f64to32c(f uint64, ret *uint32)                { *ret = f64to32(f) }
+func fcmp64c(f, g uint64, ret *int32, retnan *bool) { *ret, *retnan = fcmp64(f, g) }
+func fintto64c(val int64, ret *uint64)              { *ret = fintto64(val) }
+func f64tointc(f uint64, ret *int64, retok *bool)   { *ret, *retok = f64toint(f) }
index df63010fbd5e9b0b55cedee8b9af302c10f0b424..e1088728358fad1d7b605a44b51d97a450b6d627 100644 (file)
@@ -182,7 +182,7 @@ func hwcmp(f, g float64) (cmp int, isnan bool) {
 func testcmp(t *testing.T, f, g float64) {
        hcmp, hisnan := hwcmp(f, g)
        scmp, sisnan := Fcmp64(math.Float64bits(f), math.Float64bits(g))
-       if hcmp != scmp || hisnan != sisnan {
+       if int32(hcmp) != scmp || hisnan != sisnan {
                err(t, "cmp(%g, %g) = sw %v, %v, hw %v, %v\n", f, g, scmp, sisnan, hcmp, hisnan)
        }
 }
diff --git a/src/runtime/softfloat_arm.c b/src/runtime/softfloat_arm.c
deleted file mode 100644 (file)
index 3f3f33a..0000000
+++ /dev/null
@@ -1,687 +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.
-
-// Software floating point interpretaton of ARM 7500 FP instructions.
-// The interpretation is not bit compatible with the 7500.
-// It uses true little-endian doubles, while the 7500 used mixed-endian.
-
-#include "runtime.h"
-#include "textflag.h"
-
-#define CPSR 14
-#define FLAGS_N (1U << 31)
-#define FLAGS_Z (1U << 30)
-#define FLAGS_C (1U << 29)
-#define FLAGS_V (1U << 28)
-
-void   runtime·abort(void);
-void   runtime·sqrtC(uint64, uint64*);
-
-static uint32  trace = 0;
-
-static void
-fabort(void)
-{
-       if (1) {
-               runtime·printf("Unsupported floating point instruction\n");
-               runtime·abort();
-       }
-}
-
-static void
-putf(uint32 reg, uint32 val)
-{
-       g->m->freglo[reg] = val;
-}
-
-static void
-putd(uint32 reg, uint64 val)
-{
-       g->m->freglo[reg] = (uint32)val;
-       g->m->freghi[reg] = (uint32)(val>>32);
-}
-
-static uint64
-getd(uint32 reg)
-{
-       return (uint64)g->m->freglo[reg] | ((uint64)g->m->freghi[reg]<<32);
-}
-
-static void
-fprint(void)
-{
-       uint32 i;
-       for (i = 0; i < 16; i++) {
-               runtime·printf("\tf%d:\t%X %X\n", i, g->m->freghi[i], g->m->freglo[i]);
-       }
-}
-
-static uint32
-d2f(uint64 d)
-{
-       uint32 x;
-
-       runtime·f64to32c(d, &x);
-       return x;
-}
-
-static uint64
-f2d(uint32 f)
-{
-       uint64 x;
-
-       runtime·f32to64c(f, &x);
-       return x;
-}
-
-static uint32
-fstatus(bool nan, int32 cmp)
-{
-       if(nan)
-               return FLAGS_C | FLAGS_V;
-       if(cmp == 0)
-               return FLAGS_Z | FLAGS_C;
-       if(cmp < 0)
-               return FLAGS_N;
-       return FLAGS_C;
-}
-
-// conditions array record the required CPSR cond field for the
-// first 5 pairs of conditional execution opcodes
-// higher 4 bits are must set, lower 4 bits are must clear
-#pragma dataflag NOPTR
-static const uint8 conditions[10/2] = {
-       [0/2] = (FLAGS_Z >> 24) | 0, // 0: EQ (Z set), 1: NE (Z clear)
-       [2/2] = (FLAGS_C >> 24) | 0, // 2: CS/HS (C set), 3: CC/LO (C clear)
-       [4/2] = (FLAGS_N >> 24) | 0, // 4: MI (N set), 5: PL (N clear)
-       [6/2] = (FLAGS_V >> 24) | 0, // 6: VS (V set), 7: VC (V clear)
-       [8/2] = (FLAGS_C >> 24) | 
-               (FLAGS_Z >> 28),     // 8: HI (C set and Z clear), 9: LS (C clear and Z set)
-};
-
-#define FAULT (0x80000000U) // impossible PC offset
-
-// returns number of words that the fp instruction
-// is occupying, 0 if next instruction isn't float.
-static uint32
-stepflt(uint32 *pc, uint32 *regs)
-{
-       uint32 i, opc, regd, regm, regn, cpsr;
-       int32 delta;
-       uint32 *addr;
-       uint64 uval;
-       int64 sval;
-       bool nan, ok;
-       int32 cmp;
-       M *m;
-
-       // m is locked in vlop_arm.s, so g->m cannot change during this function call,
-       // so caching it in a local variable is safe.
-       m = g->m;
-       i = *pc;
-
-       if(trace)
-               runtime·printf("stepflt %p %x (cpsr %x)\n", pc, i, regs[CPSR] >> 28);
-
-       opc = i >> 28;
-       if(opc == 14) // common case first
-               goto execute;
-       cpsr = regs[CPSR] >> 28;
-       switch(opc) {
-       case 0: case 1: case 2: case 3: case 4: 
-       case 5: case 6: case 7: case 8: case 9:
-               if(((cpsr & (conditions[opc/2] >> 4)) == (conditions[opc/2] >> 4)) &&
-                  ((cpsr & (conditions[opc/2] & 0xf)) == 0)) {
-                       if(opc & 1) return 1;
-               } else {
-                       if(!(opc & 1)) return 1;
-               }
-               break;
-       case 10: // GE (N == V)
-       case 11: // LT (N != V)
-               if((cpsr & (FLAGS_N >> 28)) == (cpsr & (FLAGS_V >> 28))) {
-                       if(opc & 1) return 1;
-               } else {
-                       if(!(opc & 1)) return 1;
-               }
-               break;
-       case 12: // GT (N == V and Z == 0)
-       case 13: // LE (N != V or Z == 1)
-               if((cpsr & (FLAGS_N >> 28)) == (cpsr & (FLAGS_V >> 28)) &&
-                  (cpsr & (FLAGS_Z >> 28)) == 0) {
-                       if(opc & 1) return 1;
-               } else {
-                       if(!(opc & 1)) return 1;
-               }
-               break;
-       case 14: // AL
-               break;
-       case 15: // shouldn't happen
-               return 0;
-       }
-       if(trace)
-               runtime·printf("conditional %x (cpsr %x) pass\n", opc, cpsr);
-       i = (0xeU << 28) | (i & 0xfffffff);
-
-execute:
-       // special cases
-       if((i&0xfffff000) == 0xe59fb000) {
-               // load r11 from pc-relative address.
-               // might be part of a floating point move
-               // (or might not, but no harm in simulating
-               // one instruction too many).
-               addr = (uint32*)((uint8*)pc + (i&0xfff) + 8);
-               regs[11] = addr[0];
-
-               if(trace)
-                       runtime·printf("*** cpu R[%d] = *(%p) %x\n",
-                               11, addr, regs[11]);
-               return 1;
-       }
-       if(i == 0xe08bb00d) {
-               // add sp to r11.
-               // might be part of a large stack offset address
-               // (or might not, but again no harm done).
-               regs[11] += regs[13];
-
-               if(trace)
-                       runtime·printf("*** cpu R[%d] += R[%d] %x\n",
-                               11, 13, regs[11]);
-               return 1;
-       }
-       if(i == 0xeef1fa10) {
-               regs[CPSR] = (regs[CPSR]&0x0fffffff) | m->fflag;
-
-               if(trace)
-                       runtime·printf("*** fpsr R[CPSR] = F[CPSR] %x\n", regs[CPSR]);
-               return 1;
-       }
-       if((i&0xff000000) == 0xea000000) {
-               // unconditional branch
-               // can happen in the middle of floating point
-               // if the linker decides it is time to lay down
-               // a sequence of instruction stream constants.
-               delta = i&0xffffff;
-               delta = (delta<<8) >> 8;        // sign extend
-
-               if(trace)
-                       runtime·printf("*** cpu PC += %x\n", (delta+2)*4);
-               return delta+2;
-       }
-
-       goto stage1;
-
-stage1:        // load/store regn is cpureg, regm is 8bit offset
-       regd = i>>12 & 0xf;
-       regn = i>>16 & 0xf;
-       regm = (i & 0xff) << 2; // PLUS or MINUS ??
-
-       switch(i & 0xfff00f00) {
-       default:
-               goto stage2;
-
-       case 0xed900a00:        // single load
-               addr = (uint32*)(regs[regn] + regm);
-               if((uintptr)addr < 4096) {
-                       if(trace)
-                               runtime·printf("*** load @%p => fault\n", addr);
-                       return FAULT;
-               }
-               m->freglo[regd] = addr[0];
-
-               if(trace)
-                       runtime·printf("*** load F[%d] = %x\n",
-                               regd, m->freglo[regd]);
-               break;
-
-       case 0xed900b00:        // double load
-               addr = (uint32*)(regs[regn] + regm);
-               if((uintptr)addr < 4096) {
-                       if(trace)
-                               runtime·printf("*** double load @%p => fault\n", addr);
-                       return FAULT;
-               }
-               m->freglo[regd] = addr[0];
-               m->freghi[regd] = addr[1];
-
-               if(trace)
-                       runtime·printf("*** load D[%d] = %x-%x\n",
-                               regd, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xed800a00:        // single store
-               addr = (uint32*)(regs[regn] + regm);
-               if((uintptr)addr < 4096) {
-                       if(trace)
-                               runtime·printf("*** store @%p => fault\n", addr);
-                       return FAULT;
-               }
-               addr[0] = m->freglo[regd];
-
-               if(trace)
-                       runtime·printf("*** *(%p) = %x\n",
-                               addr, addr[0]);
-               break;
-
-       case 0xed800b00:        // double store
-               addr = (uint32*)(regs[regn] + regm);
-               if((uintptr)addr < 4096) {
-                       if(trace)
-                               runtime·printf("*** double store @%p => fault\n", addr);
-                       return FAULT;
-               }
-               addr[0] = m->freglo[regd];
-               addr[1] = m->freghi[regd];
-
-               if(trace)
-                       runtime·printf("*** *(%p) = %x-%x\n",
-                               addr, addr[1], addr[0]);
-               break;
-       }
-       return 1;
-
-stage2:        // regd, regm, regn are 4bit variables
-       regm = i>>0 & 0xf;
-       switch(i & 0xfff00ff0) {
-       default:
-               goto stage3;
-
-       case 0xf3000110:        // veor
-               m->freglo[regd] = m->freglo[regm]^m->freglo[regn];
-               m->freghi[regd] = m->freghi[regm]^m->freghi[regn];
-
-               if(trace)
-                       runtime·printf("*** veor D[%d] = %x-%x\n",
-                               regd, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb00b00:        // D[regd] = const(regn,regm)
-               regn = (regn<<4) | regm;
-               regm = 0x40000000UL;
-               if(regn & 0x80)
-                       regm |= 0x80000000UL;
-               if(regn & 0x40)
-                       regm ^= 0x7fc00000UL;
-               regm |= (regn & 0x3f) << 16;
-               m->freglo[regd] = 0;
-               m->freghi[regd] = regm;
-
-               if(trace)
-                       runtime·printf("*** immed D[%d] = %x-%x\n",
-                               regd, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb00a00:        // F[regd] = const(regn,regm)
-               regn = (regn<<4) | regm;
-               regm = 0x40000000UL;
-               if(regn & 0x80)
-                       regm |= 0x80000000UL;
-               if(regn & 0x40)
-                       regm ^= 0x7e000000UL;
-               regm |= (regn & 0x3f) << 19;
-               m->freglo[regd] = regm;
-
-               if(trace)
-                       runtime·printf("*** immed D[%d] = %x\n",
-                               regd, m->freglo[regd]);
-               break;
-
-       case 0xee300b00:        // D[regd] = D[regn]+D[regm]
-               runtime·fadd64c(getd(regn), getd(regm), &uval);
-               putd(regd, uval);
-
-               if(trace)
-                       runtime·printf("*** add D[%d] = D[%d]+D[%d] %x-%x\n",
-                               regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xee300a00:        // F[regd] = F[regn]+F[regm]
-               runtime·fadd64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-               m->freglo[regd] = d2f(uval);
-
-               if(trace)
-                       runtime·printf("*** add F[%d] = F[%d]+F[%d] %x\n",
-                               regd, regn, regm, m->freglo[regd]);
-               break;
-
-       case 0xee300b40:        // D[regd] = D[regn]-D[regm]
-               runtime·fsub64c(getd(regn), getd(regm), &uval);
-               putd(regd, uval);
-
-               if(trace)
-                       runtime·printf("*** sub D[%d] = D[%d]-D[%d] %x-%x\n",
-                               regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xee300a40:        // F[regd] = F[regn]-F[regm]
-               runtime·fsub64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-               m->freglo[regd] = d2f(uval);
-
-               if(trace)
-                       runtime·printf("*** sub F[%d] = F[%d]-F[%d] %x\n",
-                               regd, regn, regm, m->freglo[regd]);
-               break;
-
-       case 0xee200b00:        // D[regd] = D[regn]*D[regm]
-               runtime·fmul64c(getd(regn), getd(regm), &uval);
-               putd(regd, uval);
-
-               if(trace)
-                       runtime·printf("*** mul D[%d] = D[%d]*D[%d] %x-%x\n",
-                               regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xee200a00:        // F[regd] = F[regn]*F[regm]
-               runtime·fmul64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-               m->freglo[regd] = d2f(uval);
-
-               if(trace)
-                       runtime·printf("*** mul F[%d] = F[%d]*F[%d] %x\n",
-                               regd, regn, regm, m->freglo[regd]);
-               break;
-
-       case 0xee800b00:        // D[regd] = D[regn]/D[regm]
-               runtime·fdiv64c(getd(regn), getd(regm), &uval);
-               putd(regd, uval);
-
-               if(trace)
-                       runtime·printf("*** div D[%d] = D[%d]/D[%d] %x-%x\n",
-                               regd, regn, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xee800a00:        // F[regd] = F[regn]/F[regm]
-               runtime·fdiv64c(f2d(m->freglo[regn]), f2d(m->freglo[regm]), &uval);
-               m->freglo[regd] = d2f(uval);
-
-               if(trace)
-                       runtime·printf("*** div F[%d] = F[%d]/F[%d] %x\n",
-                               regd, regn, regm, m->freglo[regd]);
-               break;
-
-       case 0xee000b10:        // S[regn] = R[regd] (MOVW) (regm ignored)
-               m->freglo[regn] = regs[regd];
-
-               if(trace)
-                       runtime·printf("*** cpy S[%d] = R[%d] %x\n",
-                               regn, regd, m->freglo[regn]);
-               break;
-
-       case 0xee100b10:        // R[regd] = S[regn] (MOVW) (regm ignored)
-               regs[regd] = m->freglo[regn];
-
-               if(trace)
-                       runtime·printf("*** cpy R[%d] = S[%d] %x\n",
-                               regd, regn, regs[regd]);
-               break;
-       }
-       return 1;
-
-stage3:        // regd, regm are 4bit variables
-       switch(i & 0xffff0ff0) {
-       default:
-               goto done;
-
-       case 0xeeb00a40:        // F[regd] = F[regm] (MOVF)
-               m->freglo[regd] = m->freglo[regm];
-
-               if(trace)
-                       runtime·printf("*** F[%d] = F[%d] %x\n",
-                               regd, regm, m->freglo[regd]);
-               break;
-
-       case 0xeeb00b40:        // D[regd] = D[regm] (MOVD)
-               m->freglo[regd] = m->freglo[regm];
-               m->freghi[regd] = m->freghi[regm];
-
-               if(trace)
-                       runtime·printf("*** D[%d] = D[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb10bc0:        // D[regd] = sqrt D[regm]
-               runtime·sqrtC(getd(regm), &uval);
-               putd(regd, uval);
-
-               if(trace)
-                       runtime·printf("*** D[%d] = sqrt D[%d] %x-%x\n",
-                               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);
-
-               if(trace)
-                       runtime·printf("*** cmp D[%d]::D[%d] %x\n",
-                               regd, regm, m->fflag);
-               break;
-
-       case 0xeeb40ac0:        // F[regd] :: F[regm] (CMPF)
-               runtime·fcmp64c(f2d(m->freglo[regd]), f2d(m->freglo[regm]), &cmp, &nan);
-               m->fflag = fstatus(nan, cmp);
-
-               if(trace)
-                       runtime·printf("*** cmp F[%d]::F[%d] %x\n",
-                               regd, regm, m->fflag);
-               break;
-
-       case 0xeeb70ac0:        // D[regd] = F[regm] (MOVFD)
-               putd(regd, f2d(m->freglo[regm]));
-
-               if(trace)
-                       runtime·printf("*** f2d D[%d]=F[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb70bc0:        // F[regd] = D[regm] (MOVDF)
-               m->freglo[regd] = d2f(getd(regm));
-
-               if(trace)
-                       runtime·printf("*** d2f F[%d]=D[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeebd0ac0:        // S[regd] = F[regm] (MOVFW)
-               runtime·f64tointc(f2d(m->freglo[regm]), &sval, &ok);
-               if(!ok || (int32)sval != sval)
-                       sval = 0;
-               m->freglo[regd] = sval;
-
-               if(trace)
-                       runtime·printf("*** fix S[%d]=F[%d] %x\n",
-                               regd, regm, m->freglo[regd]);
-               break;
-
-       case 0xeebc0ac0:        // S[regd] = F[regm] (MOVFW.U)
-               runtime·f64tointc(f2d(m->freglo[regm]), &sval, &ok);
-               if(!ok || (uint32)sval != sval)
-                       sval = 0;
-               m->freglo[regd] = sval;
-
-               if(trace)
-                       runtime·printf("*** fix unsigned S[%d]=F[%d] %x\n",
-                               regd, regm, m->freglo[regd]);
-               break;
-
-       case 0xeebd0bc0:        // S[regd] = D[regm] (MOVDW)
-               runtime·f64tointc(getd(regm), &sval, &ok);
-               if(!ok || (int32)sval != sval)
-                       sval = 0;
-               m->freglo[regd] = sval;
-
-               if(trace)
-                       runtime·printf("*** fix S[%d]=D[%d] %x\n",
-                               regd, regm, m->freglo[regd]);
-               break;
-
-       case 0xeebc0bc0:        // S[regd] = D[regm] (MOVDW.U)
-               runtime·f64tointc(getd(regm), &sval, &ok);
-               if(!ok || (uint32)sval != sval)
-                       sval = 0;
-               m->freglo[regd] = sval;
-
-               if(trace)
-                       runtime·printf("*** fix unsigned S[%d]=D[%d] %x\n",
-                               regd, regm, m->freglo[regd]);
-               break;
-
-       case 0xeeb80ac0:        // D[regd] = S[regm] (MOVWF)
-               cmp = m->freglo[regm];
-               if(cmp < 0) {
-                       runtime·fintto64c(-cmp, &uval);
-                       putf(regd, d2f(uval));
-                       m->freglo[regd] ^= 0x80000000;
-               } else {
-                       runtime·fintto64c(cmp, &uval);
-                       putf(regd, d2f(uval));
-               }
-
-               if(trace)
-                       runtime·printf("*** float D[%d]=S[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb80a40:        // D[regd] = S[regm] (MOVWF.U)
-               runtime·fintto64c(m->freglo[regm], &uval);
-               putf(regd, d2f(uval));
-
-               if(trace)
-                       runtime·printf("*** float unsigned D[%d]=S[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb80bc0:        // D[regd] = S[regm] (MOVWD)
-               cmp = m->freglo[regm];
-               if(cmp < 0) {
-                       runtime·fintto64c(-cmp, &uval);
-                       putd(regd, uval);
-                       m->freghi[regd] ^= 0x80000000;
-               } else {
-                       runtime·fintto64c(cmp, &uval);
-                       putd(regd, uval);
-               }
-
-               if(trace)
-                       runtime·printf("*** float D[%d]=S[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-
-       case 0xeeb80b40:        // D[regd] = S[regm] (MOVWD.U)
-               runtime·fintto64c(m->freglo[regm], &uval);
-               putd(regd, uval);
-
-               if(trace)
-                       runtime·printf("*** float unsigned D[%d]=S[%d] %x-%x\n",
-                               regd, regm, m->freghi[regd], m->freglo[regd]);
-               break;
-       }
-       return 1;
-
-done:
-       if((i&0xff000000) == 0xee000000 ||
-          (i&0xff000000) == 0xed000000) {
-               runtime·printf("stepflt %p %x\n", pc, i);
-               fabort();
-       }
-       return 0;
-}
-
-typedef struct Sfregs Sfregs;
-
-// NOTE: These are all recorded as pointers because they are possibly live registers,
-// and we don't know what they contain. Recording them as pointers should be
-// safer than not.
-struct Sfregs
-{
-       uint32 *r0;
-       uint32 *r1;
-       uint32 *r2;
-       uint32 *r3;
-       uint32 *r4;
-       uint32 *r5;
-       uint32 *r6;
-       uint32 *r7;
-       uint32 *r8;
-       uint32 *r9;
-       uint32 *r10;
-       uint32 *r11;
-       uint32 *r12;
-       uint32 *r13;
-       uint32 cspr;
-};
-
-static void sfloat2(void);
-void _sfloatpanic(void);
-
-#pragma textflag NOSPLIT
-uint32*
-runtime·_sfloat2(uint32 *pc, Sfregs regs)
-{
-       void (*fn)(void);
-       
-       g->m->ptrarg[0] = pc;
-       g->m->ptrarg[1] = &regs;
-       fn = sfloat2;
-       runtime·onM(&fn);
-       pc = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       return pc;
-}
-
-static void
-sfloat2(void)
-{
-       uint32 *pc;
-       G *curg;
-       Sfregs *regs;
-       int32 skip;
-       bool first;
-       
-       pc = g->m->ptrarg[0];
-       regs = g->m->ptrarg[1];
-       g->m->ptrarg[0] = nil;
-       g->m->ptrarg[1] = nil;
-
-       first = true;
-       while(skip = stepflt(pc, (uint32*)&regs->r0)) {
-               first = false;
-               if(skip == FAULT) {
-                       // Encountered bad address in store/load.
-                       // Record signal information and return to assembly
-                       // trampoline that fakes the call.
-                       enum { SIGSEGV = 11 };
-                       curg = g->m->curg;
-                       curg->sig = SIGSEGV;
-                       curg->sigcode0 = 0;
-                       curg->sigcode1 = 0;
-                       curg->sigpc = (uint32)pc;
-                       pc = (uint32*)_sfloatpanic;
-                       break;
-               }
-               pc += skip;
-       }
-       if(first) {
-               runtime·printf("sfloat2 %p %x\n", pc, *pc);
-               fabort(); // not ok to fail first instruction
-       }
-               
-       g->m->ptrarg[0] = pc;
-}
diff --git a/src/runtime/softfloat_arm.go b/src/runtime/softfloat_arm.go
new file mode 100644 (file)
index 0000000..efee31c
--- /dev/null
@@ -0,0 +1,645 @@
+// 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.
+
+// Software floating point interpretaton of ARM 7500 FP instructions.
+// The interpretation is not bit compatible with the 7500.
+// It uses true little-endian doubles, while the 7500 used mixed-endian.
+
+package runtime
+
+import "unsafe"
+
+const (
+       _CPSR    = 14
+       _FLAGS_N = 1 << 31
+       _FLAGS_Z = 1 << 30
+       _FLAGS_C = 1 << 29
+       _FLAGS_V = 1 << 28
+)
+
+var fptrace = 0
+
+func fabort() {
+       gothrow("unsupported floating point instruction")
+}
+
+func fputf(reg uint32, val uint32) {
+       _g_ := getg()
+       _g_.m.freglo[reg] = val
+}
+
+func fputd(reg uint32, val uint64) {
+       _g_ := getg()
+       _g_.m.freglo[reg] = uint32(val)
+       _g_.m.freghi[reg] = uint32(val >> 32)
+}
+
+func fgetd(reg uint32) uint64 {
+       _g_ := getg()
+       return uint64(_g_.m.freglo[reg]) | uint64(_g_.m.freghi[reg])<<32
+}
+
+func fprintregs() {
+       _g_ := getg()
+       for i := range _g_.m.freglo {
+               print("\tf", i, ":\t", hex(_g_.m.freghi[i]), " ", hex(_g_.m.freglo[i]), "\n")
+       }
+}
+
+func fstatus(nan bool, cmp int32) uint32 {
+       if nan {
+               return _FLAGS_C | _FLAGS_V
+       }
+       if cmp == 0 {
+               return _FLAGS_Z | _FLAGS_C
+       }
+       if cmp < 0 {
+               return _FLAGS_N
+       }
+       return _FLAGS_C
+}
+
+// conditions array record the required CPSR cond field for the
+// first 5 pairs of conditional execution opcodes
+// higher 4 bits are must set, lower 4 bits are must clear
+var conditions = [10 / 2]uint32{
+       0 / 2: _FLAGS_Z>>24 | 0, // 0: EQ (Z set), 1: NE (Z clear)
+       2 / 2: _FLAGS_C>>24 | 0, // 2: CS/HS (C set), 3: CC/LO (C clear)
+       4 / 2: _FLAGS_N>>24 | 0, // 4: MI (N set), 5: PL (N clear)
+       6 / 2: _FLAGS_V>>24 | 0, // 6: VS (V set), 7: VC (V clear)
+       8 / 2: _FLAGS_C>>24 |
+               _FLAGS_Z>>28,
+}
+
+const _FAULT = 0x80000000 // impossible PC offset
+
+// returns number of words that the fp instruction
+// is occupying, 0 if next instruction isn't float.
+func stepflt(pc *uint32, regs *[15]uint32) uint32 {
+       var (
+               i, opc, regd, regm, regn, cpsr uint32
+               cmp, delta                     int32
+               uval                           uint64
+               sval                           int64
+               nan, ok                        bool
+       )
+
+       // m is locked in vlop_arm.s, so g.m cannot change during this function call,
+       // so caching it in a local variable is safe.
+       m := getg().m
+       i = *pc
+
+       if fptrace > 0 {
+               print("stepflt ", pc, " ", hex(i), " (cpsr ", hex(regs[_CPSR]>>28), ")\n")
+       }
+
+       opc = i >> 28
+       if opc == 14 { // common case first
+               goto execute
+       }
+
+       cpsr = regs[_CPSR] >> 28
+       switch opc {
+       case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
+               if cpsr&(conditions[opc/2]>>4) == conditions[opc/2]>>4 &&
+                       cpsr&(conditions[opc/2]&0xf) == 0 {
+                       if opc&1 != 0 {
+                               return 1
+                       }
+               } else {
+                       if opc&1 == 0 {
+                               return 1
+                       }
+               }
+
+       case 10, 11: // GE (N == V), LT (N != V)
+               if cpsr&(_FLAGS_N>>28) == cpsr&(_FLAGS_V>>28) {
+                       if opc&1 != 0 {
+                               return 1
+                       }
+               } else {
+                       if opc&1 == 0 {
+                               return 1
+                       }
+               }
+
+       case 12, 13: // GT (N == V and Z == 0), LE (N != V or Z == 1)
+               if cpsr&(_FLAGS_N>>28) == cpsr&(_FLAGS_V>>28) &&
+                       cpsr&(_FLAGS_Z>>28) == 0 {
+                       if opc&1 != 0 {
+                               return 1
+                       }
+               } else {
+                       if opc&1 == 0 {
+                               return 1
+                       }
+               }
+
+       case 14: // AL
+               // ok
+
+       case 15: // shouldn't happen
+               return 0
+       }
+
+       if fptrace > 0 {
+               print("conditional ", hex(opc), " (cpsr ", hex(cpsr), ") pass\n")
+       }
+       i = 0xe<<28 | i&(1<<28-1)
+
+execute:
+       // special cases
+       if i&0xfffff000 == 0xe59fb000 {
+               // load r11 from pc-relative address.
+               // might be part of a floating point move
+               // (or might not, but no harm in simulating
+               // one instruction too many).
+               addr := (*[1]uint32)(add(unsafe.Pointer(pc), uintptr(i&0xfff+8)))
+               regs[11] = addr[0]
+
+               if fptrace > 0 {
+                       print("*** cpu R[11] = *(", addr, ") ", hex(regs[11]), "\n")
+               }
+               return 1
+       }
+       if i == 0xe08bb00d {
+               // add sp to r11.
+               // might be part of a large stack offset address
+               // (or might not, but again no harm done).
+               regs[11] += regs[13]
+
+               if fptrace > 0 {
+                       print("*** cpu R[11] += R[13] ", hex(regs[11]), "\n")
+               }
+               return 1
+       }
+       if i == 0xeef1fa10 {
+               regs[_CPSR] = regs[_CPSR]&0x0fffffff | m.fflag
+
+               if fptrace > 0 {
+                       print("*** fpsr R[CPSR] = F[CPSR] ", hex(regs[_CPSR]), "\n")
+               }
+               return 1
+       }
+       if i&0xff000000 == 0xea000000 {
+               // unconditional branch
+               // can happen in the middle of floating point
+               // if the linker decides it is time to lay down
+               // a sequence of instruction stream constants.
+               delta = int32(i&0xffffff) << 8 >> 8 // sign extend
+
+               if fptrace > 0 {
+                       print("*** cpu PC += ", hex((delta+2)*4), "\n")
+               }
+               return uint32(delta + 2)
+       }
+
+       goto stage1
+
+stage1: // load/store regn is cpureg, regm is 8bit offset
+       regd = i >> 12 & 0xf
+       regn = i >> 16 & 0xf
+       regm = i & 0xff << 2 // PLUS or MINUS ??
+
+       switch i & 0xfff00f00 {
+       default:
+               goto stage2
+
+       case 0xed900a00: // single load
+               uaddr := uintptr(regs[regn] + regm)
+               if uaddr < 4096 {
+                       if fptrace > 0 {
+                               print("*** load @", hex(uaddr), " => fault\n")
+                       }
+                       return _FAULT
+               }
+               addr := (*[1]uint32)(unsafe.Pointer(uaddr))
+               m.freglo[regd] = addr[0]
+
+               if fptrace > 0 {
+                       print("*** load F[", regd, "] = ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xed900b00: // double load
+               uaddr := uintptr(regs[regn] + regm)
+               if uaddr < 4096 {
+                       if fptrace > 0 {
+                               print("*** double load @", hex(uaddr), " => fault\n")
+                       }
+                       return _FAULT
+               }
+               addr := (*[2]uint32)(unsafe.Pointer(uaddr))
+               m.freglo[regd] = addr[0]
+               m.freghi[regd] = addr[1]
+
+               if fptrace > 0 {
+                       print("*** load D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xed800a00: // single store
+               uaddr := uintptr(regs[regn] + regm)
+               if uaddr < 4096 {
+                       if fptrace > 0 {
+                               print("*** store @", hex(uaddr), " => fault\n")
+                       }
+                       return _FAULT
+               }
+               addr := (*[1]uint32)(unsafe.Pointer(uaddr))
+               addr[0] = m.freglo[regd]
+
+               if fptrace > 0 {
+                       print("*** *(", addr, ") = ", hex(addr[0]), "\n")
+               }
+               break
+
+       case 0xed800b00: // double store
+               uaddr := uintptr(regs[regn] + regm)
+               if uaddr < 4096 {
+                       if fptrace > 0 {
+                               print("*** double store @", hex(uaddr), " => fault\n")
+                       }
+                       return _FAULT
+               }
+               addr := (*[2]uint32)(unsafe.Pointer(uaddr))
+               addr[0] = m.freglo[regd]
+               addr[1] = m.freghi[regd]
+
+               if fptrace > 0 {
+                       print("*** *(", addr, ") = ", hex(addr[1]), "-", hex(addr[0]), "\n")
+               }
+               break
+       }
+       return 1
+
+stage2: // regd, regm, regn are 4bit variables
+       regm = i >> 0 & 0xf
+       switch i & 0xfff00ff0 {
+       default:
+               goto stage3
+
+       case 0xf3000110: // veor
+               m.freglo[regd] = m.freglo[regm] ^ m.freglo[regn]
+               m.freghi[regd] = m.freghi[regm] ^ m.freghi[regn]
+
+               if fptrace > 0 {
+                       print("*** veor D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb00b00: // D[regd] = const(regn,regm)
+               regn = regn<<4 | regm
+               regm = 0x40000000
+               if regn&0x80 != 0 {
+                       regm |= 0x80000000
+               }
+               if regn&0x40 != 0 {
+                       regm ^= 0x7fc00000
+               }
+               regm |= regn & 0x3f << 16
+               m.freglo[regd] = 0
+               m.freghi[regd] = regm
+
+               if fptrace > 0 {
+                       print("*** immed D[", regd, "] = ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb00a00: // F[regd] = const(regn,regm)
+               regn = regn<<4 | regm
+               regm = 0x40000000
+               if regn&0x80 != 0 {
+                       regm |= 0x80000000
+               }
+               if regn&0x40 != 0 {
+                       regm ^= 0x7e000000
+               }
+               regm |= regn & 0x3f << 19
+               m.freglo[regd] = regm
+
+               if fptrace > 0 {
+                       print("*** immed D[", regd, "] = ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee300b00: // D[regd] = D[regn]+D[regm]
+               fadd64c(fgetd(regn), fgetd(regm), &uval)
+               fputd(regd, uval)
+
+               if fptrace > 0 {
+                       print("*** add D[", regd, "] = D[", regn, "]+D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee300a00: // F[regd] = F[regn]+F[regm]
+               fadd64c(f32to64(m.freglo[regn]), f32to64(m.freglo[regm]), &uval)
+               m.freglo[regd] = f64to32(uval)
+
+               if fptrace > 0 {
+                       print("*** add F[", regd, "] = F[", regn, "]+F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee300b40: // D[regd] = D[regn]-D[regm]
+               fsub64c(fgetd(regn), fgetd(regm), &uval)
+               fputd(regd, uval)
+
+               if fptrace > 0 {
+                       print("*** sub D[", regd, "] = D[", regn, "]-D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee300a40: // F[regd] = F[regn]-F[regm]
+               fsub64c(f32to64(m.freglo[regn]), f32to64(m.freglo[regm]), &uval)
+               m.freglo[regd] = f64to32(uval)
+
+               if fptrace > 0 {
+                       print("*** sub F[", regd, "] = F[", regn, "]-F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee200b00: // D[regd] = D[regn]*D[regm]
+               fmul64c(fgetd(regn), fgetd(regm), &uval)
+               fputd(regd, uval)
+
+               if fptrace > 0 {
+                       print("*** mul D[", regd, "] = D[", regn, "]*D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee200a00: // F[regd] = F[regn]*F[regm]
+               fmul64c(f32to64(m.freglo[regn]), f32to64(m.freglo[regm]), &uval)
+               m.freglo[regd] = f64to32(uval)
+
+               if fptrace > 0 {
+                       print("*** mul F[", regd, "] = F[", regn, "]*F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee800b00: // D[regd] = D[regn]/D[regm]
+               fdiv64c(fgetd(regn), fgetd(regm), &uval)
+               fputd(regd, uval)
+
+               if fptrace > 0 {
+                       print("*** div D[", regd, "] = D[", regn, "]/D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee800a00: // F[regd] = F[regn]/F[regm]
+               fdiv64c(f32to64(m.freglo[regn]), f32to64(m.freglo[regm]), &uval)
+               m.freglo[regd] = f64to32(uval)
+
+               if fptrace > 0 {
+                       print("*** div F[", regd, "] = F[", regn, "]/F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xee000b10: // S[regn] = R[regd] (MOVW) (regm ignored)
+               m.freglo[regn] = regs[regd]
+
+               if fptrace > 0 {
+                       print("*** cpy S[", regn, "] = R[", regd, "] ", hex(m.freglo[regn]), "\n")
+               }
+               break
+
+       case 0xee100b10: // R[regd] = S[regn] (MOVW) (regm ignored)
+               regs[regd] = m.freglo[regn]
+
+               if fptrace > 0 {
+                       print("*** cpy R[", regd, "] = S[", regn, "] ", hex(regs[regd]), "\n")
+               }
+               break
+       }
+       return 1
+
+stage3: // regd, regm are 4bit variables
+       switch i & 0xffff0ff0 {
+       default:
+               goto done
+
+       case 0xeeb00a40: // F[regd] = F[regm] (MOVF)
+               m.freglo[regd] = m.freglo[regm]
+
+               if fptrace > 0 {
+                       print("*** F[", regd, "] = F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb00b40: // D[regd] = D[regm] (MOVD)
+               m.freglo[regd] = m.freglo[regm]
+               m.freghi[regd] = m.freghi[regm]
+
+               if fptrace > 0 {
+                       print("*** D[", regd, "] = D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb10bc0: // D[regd] = sqrt D[regm]
+               uval = float64bits(sqrt(float64frombits(fgetd(regm))))
+               fputd(regd, uval)
+
+               if fptrace > 0 {
+                       print("*** D[", regd, "] = sqrt D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb00bc0: // D[regd] = abs D[regm]
+               m.freglo[regd] = m.freglo[regm]
+               m.freghi[regd] = m.freghi[regm] & (1<<31 - 1)
+
+               if fptrace > 0 {
+                       print("*** D[", regd, "] = abs D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb00ac0: // F[regd] = abs F[regm]
+               m.freglo[regd] = m.freglo[regm] & (1<<31 - 1)
+
+               if fptrace > 0 {
+                       print("*** F[", regd, "] = abs F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb40bc0: // D[regd] :: D[regm] (CMPD)
+               fcmp64c(fgetd(regd), fgetd(regm), &cmp, &nan)
+               m.fflag = fstatus(nan, cmp)
+
+               if fptrace > 0 {
+                       print("*** cmp D[", regd, "]::D[", regm, "] ", hex(m.fflag), "\n")
+               }
+               break
+
+       case 0xeeb40ac0: // F[regd] :: F[regm] (CMPF)
+               fcmp64c(f32to64(m.freglo[regd]), f32to64(m.freglo[regm]), &cmp, &nan)
+               m.fflag = fstatus(nan, cmp)
+
+               if fptrace > 0 {
+                       print("*** cmp F[", regd, "]::F[", regm, "] ", hex(m.fflag), "\n")
+               }
+               break
+
+       case 0xeeb70ac0: // D[regd] = F[regm] (MOVFD)
+               fputd(regd, f32to64(m.freglo[regm]))
+
+               if fptrace > 0 {
+                       print("*** f2d D[", regd, "]=F[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb70bc0: // F[regd] = D[regm] (MOVDF)
+               m.freglo[regd] = f64to32(fgetd(regm))
+
+               if fptrace > 0 {
+                       print("*** d2f F[", regd, "]=D[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeebd0ac0: // S[regd] = F[regm] (MOVFW)
+               f64tointc(f32to64(m.freglo[regm]), &sval, &ok)
+               if !ok || int64(int32(sval)) != sval {
+                       sval = 0
+               }
+               m.freglo[regd] = uint32(sval)
+               if fptrace > 0 {
+                       print("*** fix S[", regd, "]=F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeebc0ac0: // S[regd] = F[regm] (MOVFW.U)
+               f64tointc(f32to64(m.freglo[regm]), &sval, &ok)
+               if !ok || int64(uint32(sval)) != sval {
+                       sval = 0
+               }
+               m.freglo[regd] = uint32(sval)
+
+               if fptrace > 0 {
+                       print("*** fix unsigned S[", regd, "]=F[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeebd0bc0: // S[regd] = D[regm] (MOVDW)
+               f64tointc(fgetd(regm), &sval, &ok)
+               if !ok || int64(int32(sval)) != sval {
+                       sval = 0
+               }
+               m.freglo[regd] = uint32(sval)
+
+               if fptrace > 0 {
+                       print("*** fix S[", regd, "]=D[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeebc0bc0: // S[regd] = D[regm] (MOVDW.U)
+               f64tointc(fgetd(regm), &sval, &ok)
+               if !ok || int64(uint32(sval)) != sval {
+                       sval = 0
+               }
+               m.freglo[regd] = uint32(sval)
+
+               if fptrace > 0 {
+                       print("*** fix unsigned S[", regd, "]=D[", regm, "] ", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb80ac0: // D[regd] = S[regm] (MOVWF)
+               cmp = int32(m.freglo[regm])
+               if cmp < 0 {
+                       fintto64c(int64(-cmp), &uval)
+                       fputf(regd, f64to32(uval))
+                       m.freglo[regd] ^= 0x80000000
+               } else {
+                       fintto64c(int64(cmp), &uval)
+                       fputf(regd, f64to32(uval))
+               }
+
+               if fptrace > 0 {
+                       print("*** float D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb80a40: // D[regd] = S[regm] (MOVWF.U)
+               fintto64c(int64(m.freglo[regm]), &uval)
+               fputf(regd, f64to32(uval))
+
+               if fptrace > 0 {
+                       print("*** float unsigned D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb80bc0: // D[regd] = S[regm] (MOVWD)
+               cmp = int32(m.freglo[regm])
+               if cmp < 0 {
+                       fintto64c(int64(-cmp), &uval)
+                       fputd(regd, uval)
+                       m.freghi[regd] ^= 0x80000000
+               } else {
+                       fintto64c(int64(cmp), &uval)
+                       fputd(regd, uval)
+               }
+
+               if fptrace > 0 {
+                       print("*** float D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+
+       case 0xeeb80b40: // D[regd] = S[regm] (MOVWD.U)
+               fintto64c(int64(m.freglo[regm]), &uval)
+               fputd(regd, uval)
+
+               if fptrace > 0 {
+                       print("*** float unsigned D[", regd, "]=S[", regm, "] ", hex(m.freghi[regd]), "-", hex(m.freglo[regd]), "\n")
+               }
+               break
+       }
+       return 1
+
+done:
+       if i&0xff000000 == 0xee000000 ||
+               i&0xff000000 == 0xed000000 {
+               print("stepflt ", pc, " ", hex(i), "\n")
+               fabort()
+       }
+       return 0
+}
+
+//go:nosplit
+func _sfloat2(pc uint32, regs [15]uint32) (newpc uint32) {
+       systemstack(func() {
+               newpc = sfloat2(pc, &regs)
+       })
+       return
+}
+
+func _sfloatpanic()
+
+func sfloat2(pc uint32, regs *[15]uint32) uint32 {
+       first := true
+       for {
+               skip := stepflt((*uint32)(unsafe.Pointer(uintptr(pc))), regs)
+               if skip == 0 {
+                       break
+               }
+               first = false
+               if skip == _FAULT {
+                       // Encountered bad address in store/load.
+                       // Record signal information and return to assembly
+                       // trampoline that fakes the call.
+                       const SIGSEGV = 11
+                       curg := getg().m.curg
+                       curg.sig = SIGSEGV
+                       curg.sigcode0 = 0
+                       curg.sigcode1 = 0
+                       curg.sigpc = uintptr(pc)
+                       pc = uint32(funcPC(_sfloatpanic))
+                       break
+               }
+               pc += 4 * uint32(skip)
+       }
+       if first {
+               print("sfloat2 ", pc, " ", hex(*(*uint32)(unsafe.Pointer(uintptr(pc)))), "\n")
+               fabort() // not ok to fail first instruction
+       }
+       return pc
+}
index 34a8c3806b91294c8a707311b17d8b42b09ff7ea..e3a27014b5cf3fd224e11020cda8efd9a4395f13 100644 (file)
@@ -86,9 +86,6 @@ import "unsafe"
 // Notes:  Rounding mode detection omitted.
 
 const (
-       uvnan      = 0x7FF8000000000001
-       uvinf      = 0x7FF0000000000000
-       uvneginf   = 0xFFF0000000000000
        mask       = 0x7FF
        shift      = 64 - 11 - 1
        bias       = 1023
@@ -104,7 +101,7 @@ func sqrt(x float64) float64 {
        case x == 0 || x != x || x > maxFloat64:
                return x
        case x < 0:
-               return nan
+               return nan()
        }
        ix := float64bits(x)
        // normalize x
@@ -144,7 +141,3 @@ func sqrt(x float64) float64 {
        ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent
        return float64frombits(ix)
 }
-
-func sqrtC(f float64, r *float64) {
-       *r = sqrt(f)
-}
diff --git a/src/runtime/stack.c b/src/runtime/stack.c
deleted file mode 100644 (file)
index 072bc24..0000000
+++ /dev/null
@@ -1,897 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "stack.h"
-#include "funcdata.h"
-#include "typekind.h"
-#include "type.h"
-#include "race.h"
-#include "mgc0.h"
-#include "textflag.h"
-
-enum
-{
-       // StackDebug == 0: no logging
-       //            == 1: logging of per-stack operations
-       //            == 2: logging of per-frame operations
-       //            == 3: logging of per-word updates
-       //            == 4: logging of per-word reads
-       StackDebug = 0,
-       StackFromSystem = 0,    // allocate stacks from system memory instead of the heap
-       StackFaultOnFree = 0,   // old stacks are mapped noaccess to detect use after free
-       StackPoisonCopy = 0,    // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
-
-       StackCache = 1,
-};
-
-// Global pool of spans that have free stacks.
-// Stacks are assigned an order according to size.
-//     order = log_2(size/FixedStack)
-// There is a free list for each order.
-MSpan runtime·stackpool[NumStackOrders];
-Mutex runtime·stackpoolmu;
-// TODO: one lock per order?
-
-static Stack stackfreequeue;
-
-void
-runtime·stackinit(void)
-{
-       int32 i;
-
-       if((StackCacheSize & PageMask) != 0)
-               runtime·throw("cache size must be a multiple of page size");
-
-       for(i = 0; i < NumStackOrders; i++)
-               runtime·MSpanList_Init(&runtime·stackpool[i]);
-}
-
-// Allocates a stack from the free pool.  Must be called with
-// stackpoolmu held.
-static MLink*
-poolalloc(uint8 order)
-{
-       MSpan *list;
-       MSpan *s;
-       MLink *x;
-       uintptr i;
-
-       list = &runtime·stackpool[order];
-       s = list->next;
-       if(s == list) {
-               // no free stacks.  Allocate another span worth.
-               s = runtime·MHeap_AllocStack(&runtime·mheap, StackCacheSize >> PageShift);
-               if(s == nil)
-                       runtime·throw("out of memory");
-               if(s->ref != 0)
-                       runtime·throw("bad ref");
-               if(s->freelist != nil)
-                       runtime·throw("bad freelist");
-               for(i = 0; i < StackCacheSize; i += FixedStack << order) {
-                       x = (MLink*)((s->start << PageShift) + i);
-                       x->next = s->freelist;
-                       s->freelist = x;
-               }
-               runtime·MSpanList_Insert(list, s);
-       }
-       x = s->freelist;
-       if(x == nil)
-               runtime·throw("span has no free stacks");
-       s->freelist = x->next;
-       s->ref++;
-       if(s->freelist == nil) {
-               // all stacks in s are allocated.
-               runtime·MSpanList_Remove(s);
-       }
-       return x;
-}
-
-// Adds stack x to the free pool.  Must be called with stackpoolmu held.
-static void
-poolfree(MLink *x, uint8 order)
-{
-       MSpan *s;
-
-       s = runtime·MHeap_Lookup(&runtime·mheap, x);
-       if(s->state != MSpanStack)
-               runtime·throw("freeing stack not in a stack span");
-       if(s->freelist == nil) {
-               // s will now have a free stack
-               runtime·MSpanList_Insert(&runtime·stackpool[order], s);
-       }
-       x->next = s->freelist;
-       s->freelist = x;
-       s->ref--;
-       if(s->ref == 0) {
-               // span is completely free - return to heap
-               runtime·MSpanList_Remove(s);
-               s->freelist = nil;
-               runtime·MHeap_FreeStack(&runtime·mheap, s);
-       }
-}
-
-// stackcacherefill/stackcacherelease implement a global pool of stack segments.
-// The pool is required to prevent unlimited growth of per-thread caches.
-static void
-stackcacherefill(MCache *c, uint8 order)
-{
-       MLink *x, *list;
-       uintptr size;
-
-       if(StackDebug >= 1)
-               runtime·printf("stackcacherefill order=%d\n", order);
-
-       // Grab some stacks from the global cache.
-       // Grab half of the allowed capacity (to prevent thrashing).
-       list = nil;
-       size = 0;
-       runtime·lock(&runtime·stackpoolmu);
-       while(size < StackCacheSize/2) {
-               x = poolalloc(order);
-               x->next = list;
-               list = x;
-               size += FixedStack << order;
-       }
-       runtime·unlock(&runtime·stackpoolmu);
-
-       c->stackcache[order].list = list;
-       c->stackcache[order].size = size;
-}
-
-static void
-stackcacherelease(MCache *c, uint8 order)
-{
-       MLink *x, *y;
-       uintptr size;
-
-       if(StackDebug >= 1)
-               runtime·printf("stackcacherelease order=%d\n", order);
-       x = c->stackcache[order].list;
-       size = c->stackcache[order].size;
-       runtime·lock(&runtime·stackpoolmu);
-       while(size > StackCacheSize/2) {
-               y = x->next;
-               poolfree(x, order);
-               x = y;
-               size -= FixedStack << order;
-       }
-       runtime·unlock(&runtime·stackpoolmu);
-       c->stackcache[order].list = x;
-       c->stackcache[order].size = size;
-}
-
-void
-runtime·stackcache_clear(MCache *c)
-{
-       uint8 order;
-       MLink *x, *y;
-
-       if(StackDebug >= 1)
-               runtime·printf("stackcache clear\n");
-       runtime·lock(&runtime·stackpoolmu);
-       for(order = 0; order < NumStackOrders; order++) {
-               x = c->stackcache[order].list;
-               while(x != nil) {
-                       y = x->next;
-                       poolfree(x, order);
-                       x = y;
-               }
-               c->stackcache[order].list = nil;
-               c->stackcache[order].size = 0;
-       }
-       runtime·unlock(&runtime·stackpoolmu);
-}
-
-Stack
-runtime·stackalloc(uint32 n)
-{
-       uint8 order;
-       uint32 n2;
-       void *v;
-       MLink *x;
-       MSpan *s;
-       MCache *c;
-
-       // Stackalloc must be called on scheduler stack, so that we
-       // never try to grow the stack during the code that stackalloc runs.
-       // Doing so would cause a deadlock (issue 1547).
-       if(g != g->m->g0)
-               runtime·throw("stackalloc not on scheduler stack");
-       if((n & (n-1)) != 0)
-               runtime·throw("stack size not a power of 2");
-       if(StackDebug >= 1)
-               runtime·printf("stackalloc %d\n", n);
-
-       if(runtime·debug.efence || StackFromSystem) {
-               v = runtime·sysAlloc(ROUND(n, PageSize), &mstats.stacks_sys);
-               if(v == nil)
-                       runtime·throw("out of memory (stackalloc)");
-               return (Stack){(uintptr)v, (uintptr)v+n};
-       }
-
-       // Small stacks are allocated with a fixed-size free-list allocator.
-       // If we need a stack of a bigger size, we fall back on allocating
-       // a dedicated span.
-       if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
-               order = 0;
-               n2 = n;
-               while(n2 > FixedStack) {
-                       order++;
-                       n2 >>= 1;
-               }
-               c = g->m->mcache;
-               if(c == nil || g->m->gcing || g->m->helpgc) {
-                       // c == nil can happen in the guts of exitsyscall or
-                       // procresize. Just get a stack from the global pool.
-                       // Also don't touch stackcache during gc
-                       // as it's flushed concurrently.
-                       runtime·lock(&runtime·stackpoolmu);
-                       x = poolalloc(order);
-                       runtime·unlock(&runtime·stackpoolmu);
-               } else {
-                       x = c->stackcache[order].list;
-                       if(x == nil) {
-                               stackcacherefill(c, order);
-                               x = c->stackcache[order].list;
-                       }
-                       c->stackcache[order].list = x->next;
-                       c->stackcache[order].size -= n;
-               }
-               v = (byte*)x;
-       } else {
-               s = runtime·MHeap_AllocStack(&runtime·mheap, ROUND(n, PageSize) >> PageShift);
-               if(s == nil)
-                       runtime·throw("out of memory");
-               v = (byte*)(s->start<<PageShift);
-       }
-       
-       if(raceenabled)
-               runtime·racemalloc(v, n);
-       if(StackDebug >= 1)
-               runtime·printf("  allocated %p\n", v);
-       return (Stack){(uintptr)v, (uintptr)v+n};
-}
-
-void
-runtime·stackfree(Stack stk)
-{
-       uint8 order;
-       uintptr n, n2;
-       MSpan *s;
-       MLink *x;
-       MCache *c;
-       void *v;
-       
-       n = stk.hi - stk.lo;
-       v = (void*)stk.lo;
-       if(n & (n-1))
-               runtime·throw("stack not a power of 2");
-       if(StackDebug >= 1) {
-               runtime·printf("stackfree %p %d\n", v, (int32)n);
-               runtime·memclr(v, n); // for testing, clobber stack data
-       }
-       if(runtime·debug.efence || StackFromSystem) {
-               if(runtime·debug.efence || StackFaultOnFree)
-                       runtime·SysFault(v, n);
-               else
-                       runtime·SysFree(v, n, &mstats.stacks_sys);
-               return;
-       }
-       if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
-               order = 0;
-               n2 = n;
-               while(n2 > FixedStack) {
-                       order++;
-                       n2 >>= 1;
-               }
-               x = (MLink*)v;
-               c = g->m->mcache;
-               if(c == nil || g->m->gcing || g->m->helpgc) {
-                       runtime·lock(&runtime·stackpoolmu);
-                       poolfree(x, order);
-                       runtime·unlock(&runtime·stackpoolmu);
-               } else {
-                       if(c->stackcache[order].size >= StackCacheSize)
-                               stackcacherelease(c, order);
-                       x->next = c->stackcache[order].list;
-                       c->stackcache[order].list = x;
-                       c->stackcache[order].size += n;
-               }
-       } else {
-               s = runtime·MHeap_Lookup(&runtime·mheap, v);
-               if(s->state != MSpanStack) {
-                       runtime·printf("%p %p\n", s->start<<PageShift, v);
-                       runtime·throw("bad span state");
-               }
-               runtime·MHeap_FreeStack(&runtime·mheap, s);
-       }
-}
-
-uintptr runtime·maxstacksize = 1<<20; // enough until runtime.main sets it for real
-
-static uint8*
-mapnames[] = {
-       (uint8*)"---",
-       (uint8*)"scalar",
-       (uint8*)"ptr",
-       (uint8*)"multi",
-};
-
-// Stack frame layout
-//
-// (x86)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// |  return address  |
-// +------------------+ <- frame->varp
-// |     locals       |
-// +------------------+
-// |  args to callee  |
-// +------------------+ <- frame->sp
-//
-// (arm)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// | caller's retaddr |
-// +------------------+ <- frame->varp
-// |     locals       |
-// +------------------+
-// |  args to callee  |
-// +------------------+
-// |  return address  |
-// +------------------+ <- frame->sp
-
-void runtime·main(void);
-void runtime·switchtoM(void(*)(void));
-
-typedef struct AdjustInfo AdjustInfo;
-struct AdjustInfo {
-       Stack old;
-       uintptr delta;  // ptr distance from old to new stack (newbase - oldbase)
-};
-
-// Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
-// If so, it rewrites *vpp to point into the new stack.
-static void
-adjustpointer(AdjustInfo *adjinfo, void *vpp)
-{
-       byte **pp, *p;
-       
-       pp = vpp;
-       p = *pp;
-       if(StackDebug >= 4)
-               runtime·printf("        %p:%p\n", pp, p);
-       if(adjinfo->old.lo <= (uintptr)p && (uintptr)p < adjinfo->old.hi) {
-               *pp = p + adjinfo->delta;
-               if(StackDebug >= 3)
-                       runtime·printf("        adjust ptr %p: %p -> %p\n", pp, p, *pp);
-       }
-}
-
-// bv describes the memory starting at address scanp.
-// Adjust any pointers contained therein.
-static void
-adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
-{
-       uintptr delta;
-       int32 num, i;
-       byte *p, *minp, *maxp;
-       Type *t;
-       Itab *tab;
-       
-       minp = (byte*)adjinfo->old.lo;
-       maxp = (byte*)adjinfo->old.hi;
-       delta = adjinfo->delta;
-       num = bv->n / BitsPerPointer;
-       for(i = 0; i < num; i++) {
-               if(StackDebug >= 4)
-                       runtime·printf("        %p:%s:%p\n", &scanp[i], mapnames[bv->bytedata[i / (8 / BitsPerPointer)] >> (i * BitsPerPointer & 7) & 3], scanp[i]);
-               switch(bv->bytedata[i / (8 / BitsPerPointer)] >> (i * BitsPerPointer & 7) & 3) {
-               case BitsDead:
-                       if(runtime·debug.gcdead)
-                               scanp[i] = (byte*)PoisonStack;
-                       break;
-               case BitsScalar:
-                       break;
-               case BitsPointer:
-                       p = scanp[i];
-                       if(f != nil && (byte*)0 < p && (p < (byte*)PageSize && runtime·invalidptr || (uintptr)p == PoisonGC || (uintptr)p == PoisonStack)) {
-                               // Looks like a junk value in a pointer slot.
-                               // Live analysis wrong?
-                               g->m->traceback = 2;
-                               runtime·printf("runtime: bad pointer in frame %s at %p: %p\n", runtime·funcname(f), &scanp[i], p);
-                               runtime·throw("invalid stack pointer");
-                       }
-                       if(minp <= p && p < maxp) {
-                               if(StackDebug >= 3)
-                                       runtime·printf("adjust ptr %p %s\n", p, runtime·funcname(f));
-                               scanp[i] = p + delta;
-                       }
-                       break;
-               case BitsMultiWord:
-                       switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 7) & 3) {
-                       default:
-                               runtime·throw("unexpected garbage collection bits");
-                       case BitsEface:
-                               t = (Type*)scanp[i];
-                               if(t != nil && ((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0)) {
-                                       p = scanp[i+1];
-                                       if(minp <= p && p < maxp) {
-                                               if(StackDebug >= 3)
-                                                       runtime·printf("adjust eface %p\n", p);
-                                               if(t->size > PtrSize) // currently we always allocate such objects on the heap
-                                                       runtime·throw("large interface value found on stack");
-                                               scanp[i+1] = p + delta;
-                                       }
-                               }
-                               i++;
-                               break;
-                       case BitsIface:
-                               tab = (Itab*)scanp[i];
-                               if(tab != nil) {
-                                       t = tab->type;
-                                       //runtime·printf("          type=%p\n", t);
-                                       if((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0) {
-                                               p = scanp[i+1];
-                                               if(minp <= p && p < maxp) {
-                                                       if(StackDebug >= 3)
-                                                               runtime·printf("adjust iface %p\n", p);
-                                                       if(t->size > PtrSize) // currently we always allocate such objects on the heap
-                                                               runtime·throw("large interface value found on stack");
-                                                       scanp[i+1] = p + delta;
-                                               }
-                                       }
-                               }
-                               i++;
-                               break;
-                       }
-                       break;
-               }
-       }
-}
-
-// Note: the argument/return area is adjusted by the callee.
-static bool
-adjustframe(Stkframe *frame, void *arg)
-{
-       AdjustInfo *adjinfo;
-       Func *f;
-       StackMap *stackmap;
-       int32 pcdata;
-       BitVector bv;
-       uintptr targetpc, size, minsize;
-
-       adjinfo = arg;
-       targetpc = frame->continpc;
-       if(targetpc == 0) {
-               // Frame is dead.
-               return true;
-       }
-       f = frame->fn;
-       if(StackDebug >= 2)
-               runtime·printf("    adjusting %s frame=[%p,%p] pc=%p continpc=%p\n", runtime·funcname(f), frame->sp, frame->fp, frame->pc, frame->continpc);
-       if(f->entry == (uintptr)runtime·switchtoM) {
-               // A special routine at the bottom of stack of a goroutine that does an onM call.
-               // We will allow it to be copied even though we don't
-               // have full GC info for it (because it is written in asm).
-               return true;
-       }
-       if(targetpc != f->entry)
-               targetpc--;
-       pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
-       if(pcdata == -1)
-               pcdata = 0; // in prologue
-
-       // Adjust local variables if stack frame has been allocated.
-       size = frame->varp - frame->sp;
-       if(thechar != '6' && thechar != '8')
-               minsize = sizeof(uintptr);
-       else
-               minsize = 0;
-       if(size > minsize) {
-               stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
-               if(stackmap == nil || stackmap->n <= 0) {
-                       runtime·printf("runtime: frame %s untyped locals %p+%p\n", runtime·funcname(f), (byte*)(frame->varp-size), size);
-                       runtime·throw("missing stackmap");
-               }
-               // Locals bitmap information, scan just the pointers in locals.
-               if(pcdata < 0 || pcdata >= stackmap->n) {
-                       // don't know where we are
-                       runtime·printf("runtime: pcdata is %d and %d locals stack map entries for %s (targetpc=%p)\n",
-                               pcdata, stackmap->n, runtime·funcname(f), targetpc);
-                       runtime·throw("bad symbol table");
-               }
-               bv = runtime·stackmapdata(stackmap, pcdata);
-               size = (bv.n * PtrSize) / BitsPerPointer;
-               if(StackDebug >= 3)
-                       runtime·printf("      locals\n");
-               adjustpointers((byte**)(frame->varp - size), &bv, adjinfo, f);
-       }
-       
-       // Adjust arguments.
-       if(frame->arglen > 0) {
-               if(frame->argmap != nil) {
-                       bv = *frame->argmap;
-               } else {
-                       stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
-                       if(stackmap == nil || stackmap->n <= 0) {
-                               runtime·printf("runtime: frame %s untyped args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen);
-                               runtime·throw("missing stackmap");
-                       }
-                       if(pcdata < 0 || pcdata >= stackmap->n) {
-                               // don't know where we are
-                               runtime·printf("runtime: pcdata is %d and %d args stack map entries for %s (targetpc=%p)\n",
-                                       pcdata, stackmap->n, runtime·funcname(f), targetpc);
-                               runtime·throw("bad symbol table");
-                       }
-                       bv = runtime·stackmapdata(stackmap, pcdata);
-               }
-               if(StackDebug >= 3)
-                       runtime·printf("      args\n");
-               adjustpointers((byte**)frame->argp, &bv, adjinfo, nil);
-       }
-       
-       return true;
-}
-
-static void
-adjustctxt(G *gp, AdjustInfo *adjinfo)
-{
-       adjustpointer(adjinfo, &gp->sched.ctxt);
-}
-
-static void
-adjustdefers(G *gp, AdjustInfo *adjinfo)
-{
-       Defer *d;
-       bool (*cb)(Stkframe*, void*);
-
-       // Adjust defer argument blocks the same way we adjust active stack frames.
-       cb = adjustframe;
-       runtime·tracebackdefers(gp, &cb, adjinfo);
-
-       // Adjust pointers in the Defer structs.
-       // Defer structs themselves are never on the stack.
-       for(d = gp->defer; d != nil; d = d->link) {
-               adjustpointer(adjinfo, &d->fn);
-               adjustpointer(adjinfo, &d->argp);
-               adjustpointer(adjinfo, &d->panic);
-       }
-}
-
-static void
-adjustpanics(G *gp, AdjustInfo *adjinfo)
-{
-       // Panics are on stack and already adjusted.
-       // Update pointer to head of list in G.
-       adjustpointer(adjinfo, &gp->panic);
-}
-
-static void
-adjustsudogs(G *gp, AdjustInfo *adjinfo)
-{
-       SudoG *s;
-
-       // the data elements pointed to by a SudoG structure
-       // might be in the stack.
-       for(s = gp->waiting; s != nil; s = s->waitlink) {
-               adjustpointer(adjinfo, &s->elem);
-               adjustpointer(adjinfo, &s->selectdone);
-       }
-}
-
-// Copies gp's stack to a new stack of a different size.
-static void
-copystack(G *gp, uintptr newsize)
-{
-       Stack old, new;
-       uintptr used;
-       AdjustInfo adjinfo;
-       uint32 oldstatus;
-       bool (*cb)(Stkframe*, void*);
-       byte *p, *ep;
-
-       if(gp->syscallsp != 0)
-               runtime·throw("stack growth not allowed in system call");
-       old = gp->stack;
-       if(old.lo == 0)
-               runtime·throw("nil stackbase");
-       used = old.hi - gp->sched.sp;
-
-       // allocate new stack
-       new = runtime·stackalloc(newsize);
-       if(StackPoisonCopy) {
-               p = (byte*)new.lo;
-               ep = (byte*)new.hi;
-               while(p < ep)
-                       *p++ = 0xfd;
-       }
-
-       if(StackDebug >= 1)
-               runtime·printf("copystack gp=%p [%p %p %p]/%d -> [%p %p %p]/%d\n", gp, old.lo, old.hi-used, old.hi, (int32)(old.hi-old.lo), new.lo, new.hi-used, new.hi, (int32)newsize);
-       
-       // adjust pointers in the to-be-copied frames
-       adjinfo.old = old;
-       adjinfo.delta = new.hi - old.hi;
-       cb = adjustframe;
-       runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff, &cb, &adjinfo, 0);
-       
-       // adjust other miscellaneous things that have pointers into stacks.
-       adjustctxt(gp, &adjinfo);
-       adjustdefers(gp, &adjinfo);
-       adjustpanics(gp, &adjinfo);
-       adjustsudogs(gp, &adjinfo);
-       
-       // copy the stack to the new location
-       if(StackPoisonCopy) {
-               p = (byte*)new.lo;
-               ep = (byte*)new.hi;
-               while(p < ep)
-                       *p++ = 0xfb;
-       }
-       runtime·memmove((byte*)new.hi - used, (byte*)old.hi - used, used);
-
-       oldstatus = runtime·readgstatus(gp);
-       oldstatus &= ~Gscan;
-       if(oldstatus == Gwaiting || oldstatus == Grunnable)
-               runtime·casgstatus(gp, oldstatus, Gcopystack); // oldstatus is Gwaiting or Grunnable
-       else
-               runtime·throw("copystack: bad status, not Gwaiting or Grunnable");
-
-       // Swap out old stack for new one
-       gp->stack = new;
-       gp->stackguard0 = new.lo + StackGuard; // NOTE: might clobber a preempt request
-       gp->sched.sp = new.hi - used;
-
-       runtime·casgstatus(gp, Gcopystack, oldstatus); // oldstatus is Gwaiting or Grunnable
-
-       // free old stack
-       if(StackPoisonCopy) {
-               p = (byte*)old.lo;
-               ep = (byte*)old.hi;
-               while(p < ep)
-                       *p++ = 0xfc;
-       }
-       if(newsize > old.hi-old.lo) {
-               // growing, free stack immediately
-               runtime·stackfree(old);
-       } else {
-               // shrinking, queue up free operation.  We can't actually free the stack
-               // just yet because we might run into the following situation:
-               // 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
-               // 2) The stack that pointer points to is shrunk
-               // 3) The old stack is freed
-               // 4) The containing span is marked free
-               // 5) GC attempts to mark the SudoG.elem pointer.  The marking fails because
-               //    the pointer looks like a pointer into a free span.
-               // By not freeing, we prevent step #4 until GC is done.
-               runtime·lock(&runtime·stackpoolmu);
-               *(Stack*)old.lo = stackfreequeue;
-               stackfreequeue = old;
-               runtime·unlock(&runtime·stackpoolmu);
-       }
-}
-
-// round x up to a power of 2.
-int32
-runtime·round2(int32 x)
-{
-       int32 s;
-
-       s = 0;
-       while((1 << s) < x)
-               s++;
-       return 1 << s;
-}
-
-// Called from runtime·morestack when more stack is needed.
-// Allocate larger stack and relocate to new stack.
-// Stack growth is multiplicative, for constant amortized cost.
-//
-// g->atomicstatus will be Grunning or Gscanrunning upon entry. 
-// If the GC is trying to stop this g then it will set preemptscan to true.
-void
-runtime·newstack(void)
-{
-       int32 oldsize, newsize;
-       uintptr sp;
-       G *gp;
-       Gobuf morebuf;
-
-       if(g->m->morebuf.g->stackguard0 == (uintptr)StackFork)
-               runtime·throw("stack growth after fork");
-       if(g->m->morebuf.g != g->m->curg) {
-               runtime·printf("runtime: newstack called from g=%p\n"
-                       "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
-                       g->m->morebuf.g, g->m, g->m->curg, g->m->g0, g->m->gsignal);
-               morebuf = g->m->morebuf;
-               runtime·traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g);
-               runtime·throw("runtime: wrong goroutine in newstack");
-       }
-       if(g->m->curg->throwsplit)
-               runtime·throw("runtime: stack split at bad time");
-
-       // The goroutine must be executing in order to call newstack,
-       // so it must be Grunning or Gscanrunning.
-
-       gp = g->m->curg;
-       morebuf = g->m->morebuf;
-       g->m->morebuf.pc = (uintptr)nil;
-       g->m->morebuf.lr = (uintptr)nil;
-       g->m->morebuf.sp = (uintptr)nil;
-       g->m->morebuf.g = (G*)nil;
-
-       runtime·casgstatus(gp, Grunning, Gwaiting);
-       gp->waitreason = runtime·gostringnocopy((byte*)"stack growth");
-
-       runtime·rewindmorestack(&gp->sched);
-
-       if(gp->stack.lo == 0)
-               runtime·throw("missing stack in newstack");
-       sp = gp->sched.sp;
-       if(thechar == '6' || thechar == '8') {
-               // The call to morestack cost a word.
-               sp -= sizeof(uintreg);
-       }
-       if(StackDebug >= 1 || sp < gp->stack.lo) {
-               runtime·printf("runtime: newstack sp=%p stack=[%p, %p]\n"
-                       "\tmorebuf={pc:%p sp:%p lr:%p}\n"
-                       "\tsched={pc:%p sp:%p lr:%p ctxt:%p}\n",
-                       sp, gp->stack.lo, gp->stack.hi,
-                       g->m->morebuf.pc, g->m->morebuf.sp, g->m->morebuf.lr,
-                       gp->sched.pc, gp->sched.sp, gp->sched.lr, gp->sched.ctxt);
-       }
-       if(sp < gp->stack.lo) {
-               runtime·printf("runtime: gp=%p, gp->status=%d\n ", (void*)gp, runtime·readgstatus(gp));
-               runtime·printf("runtime: split stack overflow: %p < %p\n", sp, gp->stack.lo);
-               runtime·throw("runtime: split stack overflow");
-       }
-
-       if(gp->stackguard0 == (uintptr)StackPreempt) {
-               if(gp == g->m->g0)
-                       runtime·throw("runtime: preempt g0");
-               if(g->m->p == nil && g->m->locks == 0)
-                       runtime·throw("runtime: g is running but p is not");
-               if(gp->preemptscan) {
-                       runtime·gcphasework(gp);
-                       runtime·casgstatus(gp, Gwaiting, Grunning);
-                       gp->stackguard0 = gp->stack.lo + StackGuard;
-                       gp->preempt = false; 
-                       gp->preemptscan = false;        // Tells the GC premption was successful.
-                       runtime·gogo(&gp->sched);      // never return 
-               }
-
-               // Be conservative about where we preempt.
-               // We are interested in preempting user Go code, not runtime code.
-               if(g->m->locks || g->m->mallocing || g->m->gcing || g->m->p->status != Prunning) {
-                       // Let the goroutine keep running for now.
-                       // gp->preempt is set, so it will be preempted next time.
-                       gp->stackguard0 = gp->stack.lo + StackGuard;
-                       runtime·casgstatus(gp, Gwaiting, Grunning);
-                       runtime·gogo(&gp->sched);      // never return
-               }
-               // Act like goroutine called runtime.Gosched.
-               runtime·casgstatus(gp, Gwaiting, Grunning);
-               runtime·gosched_m(gp); // never return
-       }
-
-       // Allocate a bigger segment and move the stack.
-       oldsize = gp->stack.hi - gp->stack.lo;
-       newsize = oldsize * 2;
-       if(newsize > runtime·maxstacksize) {
-               runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n", (uint64)runtime·maxstacksize);
-               runtime·throw("stack overflow");
-       }
-
-       // Note that the concurrent GC might be scanning the stack as we try to replace it.
-       // copystack takes care of the appropriate coordination with the stack scanner.
-       copystack(gp, newsize);
-       if(StackDebug >= 1)
-               runtime·printf("stack grow done\n");
-       runtime·casgstatus(gp, Gwaiting, Grunning);
-       runtime·gogo(&gp->sched);
-}
-
-#pragma textflag NOSPLIT
-void
-runtime·nilfunc(void)
-{
-       *(byte*)0 = 0;
-}
-
-// adjust Gobuf as if it executed a call to fn
-// and then did an immediate gosave.
-void
-runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv)
-{
-       void *fn;
-
-       if(fv != nil)
-               fn = fv->fn;
-       else
-               fn = runtime·nilfunc;
-       runtime·gostartcall(gobuf, fn, fv);
-}
-
-// Maybe shrink the stack being used by gp.
-// Called at garbage collection time.
-void
-runtime·shrinkstack(G *gp)
-{
-       uintptr used, oldsize, newsize;
-
-       if(runtime·readgstatus(gp) == Gdead) {
-               if(gp->stack.lo != 0) {
-                       // Free whole stack - it will get reallocated
-                       // if G is used again.
-                       runtime·stackfree(gp->stack);
-                       gp->stack.lo = 0;
-                       gp->stack.hi = 0;
-               }
-               return;
-       }
-       if(gp->stack.lo == 0)
-               runtime·throw("missing stack in shrinkstack");
-
-       oldsize = gp->stack.hi - gp->stack.lo;
-       newsize = oldsize / 2;
-       if(newsize < FixedStack)
-               return; // don't shrink below the minimum-sized stack
-       used = gp->stack.hi - gp->sched.sp;
-       if(used >= oldsize / 4)
-               return; // still using at least 1/4 of the segment.
-
-       // We can't copy the stack if we're in a syscall.
-       // The syscall might have pointers into the stack.
-       if(gp->syscallsp != 0)
-               return;
-
-#ifdef GOOS_windows
-       if(gp->m != nil && gp->m->libcallsp != 0)
-               return;
-#endif
-       if(StackDebug > 0)
-               runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uint64)newsize);
-       copystack(gp, newsize);
-}
-
-// Do any delayed stack freeing that was queued up during GC.
-void
-runtime·shrinkfinish(void)
-{
-       Stack s, t;
-
-       runtime·lock(&runtime·stackpoolmu);
-       s = stackfreequeue;
-       stackfreequeue = (Stack){0,0};
-       runtime·unlock(&runtime·stackpoolmu);
-       while(s.lo != 0) {
-               t = *(Stack*)s.lo;
-               runtime·stackfree(s);
-               s = t;
-       }
-}
-
-static void badc(void);
-
-#pragma textflag NOSPLIT
-void
-runtime·morestackc(void)
-{
-       void (*fn)(void);
-       
-       fn = badc;
-       runtime·onM(&fn);
-}
-
-static void
-badc(void)
-{
-       runtime·throw("attempt to execute C code on Go stack");
-}
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
deleted file mode 100644 (file)
index f1b7d32..0000000
+++ /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.
-
-package runtime
-
-const (
-       // Goroutine preemption request.
-       // Stored into g->stackguard0 to cause split stack check failure.
-       // Must be greater than any real sp.
-       // 0xfffffade in hex.
-       stackPreempt = ^uintptr(1313)
-)
index f97dc4ed8db097dd8350256352eb9a7aaec51ba9..0099d05c23a19a5359b71f389472f7af4aeab33a 100644 (file)
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-/*
-Stack layout parameters.
-Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
-
-The per-goroutine g->stackguard is set to point StackGuard bytes
-above the bottom of the stack.  Each function compares its stack
-pointer against g->stackguard to check for overflow.  To cut one
-instruction from the check sequence for functions with tiny frames,
-the stack is allowed to protrude StackSmall bytes below the stack
-guard.  Functions with large frames don't bother with the check and
-always call morestack.  The sequences are (for amd64, others are
-similar):
-       guard = g->stackguard
-       frame = function's stack frame size
-       argsize = size of function arguments (call + return)
-
-       stack frame size <= StackSmall:
-               CMPQ guard, SP
-               JHI 3(PC)
-               MOVQ m->morearg, $(argsize << 32)
-               CALL morestack(SB)
-
-       stack frame size > StackSmall but < StackBig
-               LEAQ (frame-StackSmall)(SP), R0
-               CMPQ guard, R0
-               JHI 3(PC)
-               MOVQ m->morearg, $(argsize << 32)
-               CALL morestack(SB)
-
-       stack frame size >= StackBig:
-               MOVQ m->morearg, $((argsize << 32) | frame)
-               CALL morestack(SB)
-
-The bottom StackGuard - StackSmall bytes are important: there has
-to be enough room to execute functions that refuse to check for
-stack overflow, either because they need to be adjacent to the
-actual caller's frame (deferproc) or because they handle the imminent
-stack overflow (morestack).
-
-For example, deferproc might call malloc, which does one of the
-above checks (without allocating a full frame), which might trigger
-a call to morestack.  This sequence needs to fit in the bottom
-section of the stack.  On amd64, morestack's frame is 40 bytes, and
-deferproc's frame is 56 bytes.  That fits well within the
-StackGuard - StackSmall bytes at the bottom.  
-The linkers explore all possible call traces involving non-splitting
-functions to make sure that this limit cannot be violated.
- */
+// For the linkers. Must match Go definitions.
+// TODO(rsc): Share Go definitions with linkers directly.
 
 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 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 // Plan 9
 #endif // Windows
 
-       // The minimum size of stack used by Go code
-       StackMin = 2048,
-
-       // The minimum stack size to allocate.
-       // The hackery here rounds FixedStack0 up to a power of 2.
-       FixedStack0 = StackMin + StackSystem,
-       FixedStack1 = FixedStack0 - 1,
-       FixedStack2 = FixedStack1 | (FixedStack1 >> 1),
-       FixedStack3 = FixedStack2 | (FixedStack2 >> 2),
-       FixedStack4 = FixedStack3 | (FixedStack3 >> 4),
-       FixedStack5 = FixedStack4 | (FixedStack4 >> 8),
-       FixedStack6 = FixedStack5 | (FixedStack5 >> 16),
-       FixedStack = FixedStack6 + 1,
-
-       // Functions that need frames bigger than this use an extra
-       // instruction to do the stack split check, to avoid overflow
-       // in case SP - framesize wraps below zero.
-       // This value can be no bigger than the size of the unmapped
-       // space at zero.
        StackBig = 4096,
-
-       // The stack guard is a pointer this many bytes above the
-       // bottom of the stack.
        StackGuard = 512 + StackSystem,
-
-       // After a stack split check the SP is allowed to be this
-       // many bytes below the stack guard.  This saves an instruction
-       // in the checking sequence for tiny frames.
        StackSmall = 128,
-
-       // The maximum number of bytes that a chain of NOSPLIT
-       // functions can use.
        StackLimit = StackGuard - StackSystem - StackSmall,
 };
 
-// Goroutine preemption request.
-// Stored into g->stackguard0 to cause split stack check failure.
-// Must be greater than any real sp.
-// 0xfffffade in hex.
 #define StackPreempt ((uint64)-1314)
-/*c2go
-enum
-{
-       StackPreempt = -1314,
-};
-*/
-#define StackFork ((uint64)-1234)
diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go
new file mode 100644 (file)
index 0000000..ad83e58
--- /dev/null
@@ -0,0 +1,807 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+const (
+       // StackDebug == 0: no logging
+       //            == 1: logging of per-stack operations
+       //            == 2: logging of per-frame operations
+       //            == 3: logging of per-word updates
+       //            == 4: logging of per-word reads
+       stackDebug       = 0
+       stackFromSystem  = 0 // allocate stacks from system memory instead of the heap
+       stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free
+       stackPoisonCopy  = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
+
+       stackCache = 1
+)
+
+const (
+       uintptrMask = 1<<(8*ptrSize) - 1
+       poisonGC    = uintptrMask & 0xf969696969696969
+       poisonStack = uintptrMask & 0x6868686868686868
+
+       // Goroutine preemption request.
+       // Stored into g->stackguard0 to cause split stack check failure.
+       // Must be greater than any real sp.
+       // 0xfffffade in hex.
+       stackPreempt = uintptrMask & -1314
+
+       // Thread is forking.
+       // Stored into g->stackguard0 to cause split stack check failure.
+       // Must be greater than any real sp.
+       stackFork = uintptrMask & -1234
+)
+
+// Global pool of spans that have free stacks.
+// Stacks are assigned an order according to size.
+//     order = log_2(size/FixedStack)
+// There is a free list for each order.
+// TODO: one lock per order?
+var stackpool [_NumStackOrders]mspan
+var stackpoolmu mutex
+
+var stackfreequeue stack
+
+func stackinit() {
+       if _StackCacheSize&_PageMask != 0 {
+               gothrow("cache size must be a multiple of page size")
+       }
+       for i := range stackpool {
+               mSpanList_Init(&stackpool[i])
+       }
+}
+
+// Allocates a stack from the free pool.  Must be called with
+// stackpoolmu held.
+func stackpoolalloc(order uint8) *mlink {
+       list := &stackpool[order]
+       s := list.next
+       if s == list {
+               // no free stacks.  Allocate another span worth.
+               s = mHeap_AllocStack(&mheap_, _StackCacheSize>>_PageShift)
+               if s == nil {
+                       gothrow("out of memory")
+               }
+               if s.ref != 0 {
+                       gothrow("bad ref")
+               }
+               if s.freelist != nil {
+                       gothrow("bad freelist")
+               }
+               for i := uintptr(0); i < _StackCacheSize; i += _FixedStack << order {
+                       x := (*mlink)(unsafe.Pointer(uintptr(s.start)<<_PageShift + i))
+                       x.next = s.freelist
+                       s.freelist = x
+               }
+               mSpanList_Insert(list, s)
+       }
+       x := s.freelist
+       if x == nil {
+               gothrow("span has no free stacks")
+       }
+       s.freelist = x.next
+       s.ref++
+       if s.freelist == nil {
+               // all stacks in s are allocated.
+               mSpanList_Remove(s)
+       }
+       return x
+}
+
+// Adds stack x to the free pool.  Must be called with stackpoolmu held.
+func stackpoolfree(x *mlink, order uint8) {
+       s := mHeap_Lookup(&mheap_, (unsafe.Pointer)(x))
+       if s.state != _MSpanStack {
+               gothrow("freeing stack not in a stack span")
+       }
+       if s.freelist == nil {
+               // s will now have a free stack
+               mSpanList_Insert(&stackpool[order], s)
+       }
+       x.next = s.freelist
+       s.freelist = x
+       s.ref--
+       if s.ref == 0 {
+               // span is completely free - return to heap
+               mSpanList_Remove(s)
+               s.freelist = nil
+               mHeap_FreeStack(&mheap_, s)
+       }
+}
+
+// stackcacherefill/stackcacherelease implement a global pool of stack segments.
+// The pool is required to prevent unlimited growth of per-thread caches.
+func stackcacherefill(c *mcache, order uint8) {
+       if stackDebug >= 1 {
+               print("stackcacherefill order=", order, "\n")
+       }
+
+       // Grab some stacks from the global cache.
+       // Grab half of the allowed capacity (to prevent thrashing).
+       var list *mlink
+       var size uintptr
+       lock(&stackpoolmu)
+       for size < _StackCacheSize/2 {
+               x := stackpoolalloc(order)
+               x.next = list
+               list = x
+               size += _FixedStack << order
+       }
+       unlock(&stackpoolmu)
+       c.stackcache[order].list = list
+       c.stackcache[order].size = size
+}
+
+func stackcacherelease(c *mcache, order uint8) {
+       if stackDebug >= 1 {
+               print("stackcacherelease order=", order, "\n")
+       }
+       x := c.stackcache[order].list
+       size := c.stackcache[order].size
+       lock(&stackpoolmu)
+       for size > _StackCacheSize/2 {
+               y := x.next
+               stackpoolfree(x, order)
+               x = y
+               size -= _FixedStack << order
+       }
+       unlock(&stackpoolmu)
+       c.stackcache[order].list = x
+       c.stackcache[order].size = size
+}
+
+func stackcache_clear(c *mcache) {
+       if stackDebug >= 1 {
+               print("stackcache clear\n")
+       }
+       lock(&stackpoolmu)
+       for order := uint8(0); order < _NumStackOrders; order++ {
+               x := c.stackcache[order].list
+               for x != nil {
+                       y := x.next
+                       stackpoolfree(x, order)
+                       x = y
+               }
+               c.stackcache[order].list = nil
+               c.stackcache[order].size = 0
+       }
+       unlock(&stackpoolmu)
+}
+
+func stackalloc(n uint32) stack {
+       // Stackalloc must be called on scheduler stack, so that we
+       // never try to grow the stack during the code that stackalloc runs.
+       // Doing so would cause a deadlock (issue 1547).
+       thisg := getg()
+       if thisg != thisg.m.g0 {
+               gothrow("stackalloc not on scheduler stack")
+       }
+       if n&(n-1) != 0 {
+               gothrow("stack size not a power of 2")
+       }
+       if stackDebug >= 1 {
+               print("stackalloc ", n, "\n")
+       }
+
+       if debug.efence != 0 || stackFromSystem != 0 {
+               v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
+               if v == nil {
+                       gothrow("out of memory (stackalloc)")
+               }
+               return stack{uintptr(v), uintptr(v) + uintptr(n)}
+       }
+
+       // Small stacks are allocated with a fixed-size free-list allocator.
+       // If we need a stack of a bigger size, we fall back on allocating
+       // a dedicated span.
+       var v unsafe.Pointer
+       if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
+               order := uint8(0)
+               n2 := n
+               for n2 > _FixedStack {
+                       order++
+                       n2 >>= 1
+               }
+               var x *mlink
+               c := thisg.m.mcache
+               if c == nil || thisg.m.gcing != 0 || thisg.m.helpgc != 0 {
+                       // c == nil can happen in the guts of exitsyscall or
+                       // procresize. Just get a stack from the global pool.
+                       // Also don't touch stackcache during gc
+                       // as it's flushed concurrently.
+                       lock(&stackpoolmu)
+                       x = stackpoolalloc(order)
+                       unlock(&stackpoolmu)
+               } else {
+                       x = c.stackcache[order].list
+                       if x == nil {
+                               stackcacherefill(c, order)
+                               x = c.stackcache[order].list
+                       }
+                       c.stackcache[order].list = x.next
+                       c.stackcache[order].size -= uintptr(n)
+               }
+               v = (unsafe.Pointer)(x)
+       } else {
+               s := mHeap_AllocStack(&mheap_, round(uintptr(n), _PageSize)>>_PageShift)
+               if s == nil {
+                       gothrow("out of memory")
+               }
+               v = (unsafe.Pointer)(s.start << _PageShift)
+       }
+
+       if raceenabled {
+               racemalloc(v, uintptr(n))
+       }
+       if stackDebug >= 1 {
+               print("  allocated ", v, "\n")
+       }
+       return stack{uintptr(v), uintptr(v) + uintptr(n)}
+}
+
+func stackfree(stk stack) {
+       gp := getg()
+       n := stk.hi - stk.lo
+       v := (unsafe.Pointer)(stk.lo)
+       if n&(n-1) != 0 {
+               gothrow("stack not a power of 2")
+       }
+       if stackDebug >= 1 {
+               println("stackfree", v, n)
+               memclr(v, n) // for testing, clobber stack data
+       }
+       if debug.efence != 0 || stackFromSystem != 0 {
+               if debug.efence != 0 || stackFaultOnFree != 0 {
+                       sysFault(v, n)
+               } else {
+                       sysFree(v, n, &memstats.stacks_sys)
+               }
+               return
+       }
+       if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
+               order := uint8(0)
+               n2 := n
+               for n2 > _FixedStack {
+                       order++
+                       n2 >>= 1
+               }
+               x := (*mlink)(v)
+               c := gp.m.mcache
+               if c == nil || gp.m.gcing != 0 || gp.m.helpgc != 0 {
+                       lock(&stackpoolmu)
+                       stackpoolfree(x, order)
+                       unlock(&stackpoolmu)
+               } else {
+                       if c.stackcache[order].size >= _StackCacheSize {
+                               stackcacherelease(c, order)
+                       }
+                       x.next = c.stackcache[order].list
+                       c.stackcache[order].list = x
+                       c.stackcache[order].size += n
+               }
+       } else {
+               s := mHeap_Lookup(&mheap_, v)
+               if s.state != _MSpanStack {
+                       println(hex(s.start<<_PageShift), v)
+                       gothrow("bad span state")
+               }
+               mHeap_FreeStack(&mheap_, s)
+       }
+}
+
+var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
+
+var mapnames = []string{
+       _BitsDead:    "---",
+       _BitsScalar:  "scalar",
+       _BitsPointer: "ptr",
+}
+
+// Stack frame layout
+//
+// (x86)
+// +------------------+
+// | args from caller |
+// +------------------+ <- frame->argp
+// |  return address  |
+// +------------------+ <- frame->varp
+// |     locals       |
+// +------------------+
+// |  args to callee  |
+// +------------------+ <- frame->sp
+//
+// (arm)
+// +------------------+
+// | args from caller |
+// +------------------+ <- frame->argp
+// | caller's retaddr |
+// +------------------+ <- frame->varp
+// |     locals       |
+// +------------------+
+// |  args to callee  |
+// +------------------+
+// |  return address  |
+// +------------------+ <- frame->sp
+
+type adjustinfo struct {
+       old   stack
+       delta uintptr // ptr distance from old to new stack (newbase - oldbase)
+}
+
+// Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
+// If so, it rewrites *vpp to point into the new stack.
+func adjustpointer(adjinfo *adjustinfo, vpp unsafe.Pointer) {
+       pp := (*unsafe.Pointer)(vpp)
+       p := *pp
+       if stackDebug >= 4 {
+               print("        ", pp, ":", p, "\n")
+       }
+       if adjinfo.old.lo <= uintptr(p) && uintptr(p) < adjinfo.old.hi {
+               *pp = add(p, adjinfo.delta)
+               if stackDebug >= 3 {
+                       print("        adjust ptr ", pp, ":", p, " -> ", *pp, "\n")
+               }
+       }
+}
+
+type gobitvector struct {
+       n        uintptr
+       bytedata []uint8
+}
+
+func gobv(bv bitvector) gobitvector {
+       return gobitvector{
+               uintptr(bv.n),
+               (*[1 << 30]byte)(unsafe.Pointer(bv.bytedata))[:(bv.n+7)/8],
+       }
+}
+
+func ptrbits(bv *gobitvector, i uintptr) uint8 {
+       return (bv.bytedata[i/4] >> ((i & 3) * 2)) & 3
+}
+
+// bv describes the memory starting at address scanp.
+// Adjust any pointers contained therein.
+func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f *_func) {
+       bv := gobv(*cbv)
+       minp := adjinfo.old.lo
+       maxp := adjinfo.old.hi
+       delta := adjinfo.delta
+       num := uintptr(bv.n / _BitsPerPointer)
+       for i := uintptr(0); i < num; i++ {
+               if stackDebug >= 4 {
+                       print("        ", add(scanp, i*ptrSize), ":", mapnames[ptrbits(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*ptrSize))), " # ", i, " ", bv.bytedata[i/4], "\n")
+               }
+               switch ptrbits(&bv, i) {
+               default:
+                       gothrow("unexpected pointer bits")
+               case _BitsDead:
+                       if debug.gcdead != 0 {
+                               *(*unsafe.Pointer)(add(scanp, i*ptrSize)) = unsafe.Pointer(uintptr(poisonStack))
+                       }
+               case _BitsScalar:
+                       // ok
+               case _BitsPointer:
+                       p := *(*unsafe.Pointer)(add(scanp, i*ptrSize))
+                       up := uintptr(p)
+                       if f != nil && 0 < up && up < _PageSize && invalidptr != 0 || up == poisonGC || up == poisonStack {
+                               // Looks like a junk value in a pointer slot.
+                               // Live analysis wrong?
+                               getg().m.traceback = 2
+                               print("runtime: bad pointer in frame ", gofuncname(f), " at ", add(scanp, i*ptrSize), ": ", p, "\n")
+                               gothrow("invalid stack pointer")
+                       }
+                       if minp <= up && up < maxp {
+                               if stackDebug >= 3 {
+                                       print("adjust ptr ", p, " ", gofuncname(f), "\n")
+                               }
+                               *(*unsafe.Pointer)(add(scanp, i*ptrSize)) = unsafe.Pointer(up + delta)
+                       }
+               }
+       }
+}
+
+// Note: the argument/return area is adjusted by the callee.
+func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
+       adjinfo := (*adjustinfo)(arg)
+       targetpc := frame.continpc
+       if targetpc == 0 {
+               // Frame is dead.
+               return true
+       }
+       f := frame.fn
+       if stackDebug >= 2 {
+               print("    adjusting ", funcname(f), " frame=[", hex(frame.sp), ",", hex(frame.fp), "] pc=", hex(frame.pc), " continpc=", hex(frame.continpc), "\n")
+       }
+       if f.entry == systemstack_switchPC {
+               // A special routine at the bottom of stack of a goroutine that does an systemstack call.
+               // We will allow it to be copied even though we don't
+               // have full GC info for it (because it is written in asm).
+               return true
+       }
+       if targetpc != f.entry {
+               targetpc--
+       }
+       pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+       if pcdata == -1 {
+               pcdata = 0 // in prologue
+       }
+
+       // Adjust local variables if stack frame has been allocated.
+       size := frame.varp - frame.sp
+       var minsize uintptr
+       if thechar != '6' && thechar != '8' {
+               minsize = ptrSize
+       } else {
+               minsize = 0
+       }
+       if size > minsize {
+               var bv bitvector
+               stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
+               if stackmap == nil || stackmap.n <= 0 {
+                       print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
+                       gothrow("missing stackmap")
+               }
+               // Locals bitmap information, scan just the pointers in locals.
+               if pcdata < 0 || pcdata >= stackmap.n {
+                       // don't know where we are
+                       print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
+                       gothrow("bad symbol table")
+               }
+               bv = stackmapdata(stackmap, pcdata)
+               size = (uintptr(bv.n) * ptrSize) / _BitsPerPointer
+               if stackDebug >= 3 {
+                       print("      locals ", pcdata, "/", stackmap.n, " ", size/ptrSize, " words ", bv.bytedata, "\n")
+               }
+               adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
+       }
+
+       // Adjust arguments.
+       if frame.arglen > 0 {
+               var bv bitvector
+               if frame.argmap != nil {
+                       bv = *frame.argmap
+               } else {
+                       stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
+                       if stackmap == nil || stackmap.n <= 0 {
+                               print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", uintptr(frame.arglen), "\n")
+                               gothrow("missing stackmap")
+                       }
+                       if pcdata < 0 || pcdata >= stackmap.n {
+                               // don't know where we are
+                               print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
+                               gothrow("bad symbol table")
+                       }
+                       bv = stackmapdata(stackmap, pcdata)
+               }
+               if stackDebug >= 3 {
+                       print("      args\n")
+               }
+               adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, nil)
+       }
+       return true
+}
+
+func adjustctxt(gp *g, adjinfo *adjustinfo) {
+       adjustpointer(adjinfo, (unsafe.Pointer)(&gp.sched.ctxt))
+}
+
+func adjustdefers(gp *g, adjinfo *adjustinfo) {
+       // Adjust defer argument blocks the same way we adjust active stack frames.
+       tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo)))
+
+       // Adjust pointers in the Defer structs.
+       // Defer structs themselves are never on the stack.
+       for d := gp._defer; d != nil; d = d.link {
+               adjustpointer(adjinfo, (unsafe.Pointer)(&d.fn))
+               adjustpointer(adjinfo, (unsafe.Pointer)(&d.argp))
+               adjustpointer(adjinfo, (unsafe.Pointer)(&d._panic))
+       }
+}
+
+func adjustpanics(gp *g, adjinfo *adjustinfo) {
+       // Panics are on stack and already adjusted.
+       // Update pointer to head of list in G.
+       adjustpointer(adjinfo, (unsafe.Pointer)(&gp._panic))
+}
+
+func adjustsudogs(gp *g, adjinfo *adjustinfo) {
+       // the data elements pointed to by a SudoG structure
+       // might be in the stack.
+       for s := gp.waiting; s != nil; s = s.waitlink {
+               adjustpointer(adjinfo, (unsafe.Pointer)(&s.elem))
+               adjustpointer(adjinfo, (unsafe.Pointer)(&s.selectdone))
+       }
+}
+
+func fillstack(stk stack, b byte) {
+       for p := stk.lo; p < stk.hi; p++ {
+               *(*byte)(unsafe.Pointer(p)) = b
+       }
+}
+
+// Copies gp's stack to a new stack of a different size.
+func copystack(gp *g, newsize uintptr) {
+       if gp.syscallsp != 0 {
+               gothrow("stack growth not allowed in system call")
+       }
+       old := gp.stack
+       if old.lo == 0 {
+               gothrow("nil stackbase")
+       }
+       used := old.hi - gp.sched.sp
+
+       // allocate new stack
+       new := stackalloc(uint32(newsize))
+       if stackPoisonCopy != 0 {
+               fillstack(new, 0xfd)
+       }
+       if stackDebug >= 1 {
+               print("copystack gp=", gp, " [", hex(old.lo), " ", hex(old.hi-used), " ", hex(old.hi), "]/", old.hi-old.lo, " -> [", hex(new.lo), " ", hex(new.hi-used), " ", hex(new.hi), "]/", newsize, "\n")
+       }
+
+       // adjust pointers in the to-be-copied frames
+       var adjinfo adjustinfo
+       adjinfo.old = old
+       adjinfo.delta = new.hi - old.hi
+       gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, adjustframe, noescape(unsafe.Pointer(&adjinfo)), 0)
+
+       // adjust other miscellaneous things that have pointers into stacks.
+       adjustctxt(gp, &adjinfo)
+       adjustdefers(gp, &adjinfo)
+       adjustpanics(gp, &adjinfo)
+       adjustsudogs(gp, &adjinfo)
+
+       // copy the stack to the new location
+       if stackPoisonCopy != 0 {
+               fillstack(new, 0xfb)
+       }
+       memmove(unsafe.Pointer(new.hi-used), unsafe.Pointer(old.hi-used), used)
+
+       oldstatus := readgstatus(gp)
+       oldstatus &^= _Gscan
+       if oldstatus == _Gwaiting || oldstatus == _Grunnable {
+               casgstatus(gp, oldstatus, _Gcopystack) // oldstatus is Gwaiting or Grunnable
+       } else {
+               gothrow("copystack: bad status, not Gwaiting or Grunnable")
+       }
+
+       // Swap out old stack for new one
+       gp.stack = new
+       gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request
+       gp.sched.sp = new.hi - used
+
+       casgstatus(gp, _Gcopystack, oldstatus) // oldstatus is Gwaiting or Grunnable
+
+       // free old stack
+       if stackPoisonCopy != 0 {
+               fillstack(old, 0xfc)
+       }
+       if newsize > old.hi-old.lo {
+               // growing, free stack immediately
+               stackfree(old)
+       } else {
+               // shrinking, queue up free operation.  We can't actually free the stack
+               // just yet because we might run into the following situation:
+               // 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
+               // 2) The stack that pointer points to is shrunk
+               // 3) The old stack is freed
+               // 4) The containing span is marked free
+               // 5) GC attempts to mark the SudoG.elem pointer.  The marking fails because
+               //    the pointer looks like a pointer into a free span.
+               // By not freeing, we prevent step #4 until GC is done.
+               lock(&stackpoolmu)
+               *(*stack)(unsafe.Pointer(old.lo)) = stackfreequeue
+               stackfreequeue = old
+               unlock(&stackpoolmu)
+       }
+}
+
+// round x up to a power of 2.
+func round2(x int32) int32 {
+       s := uint(0)
+       for 1<<s < x {
+               s++
+       }
+       return 1 << s
+}
+
+// Called from runtime·morestack when more stack is needed.
+// Allocate larger stack and relocate to new stack.
+// Stack growth is multiplicative, for constant amortized cost.
+//
+// g->atomicstatus will be Grunning or Gscanrunning upon entry.
+// If the GC is trying to stop this g then it will set preemptscan to true.
+func newstack() {
+       thisg := getg()
+       // TODO: double check all gp. shouldn't be getg().
+       if thisg.m.morebuf.g.stackguard0 == stackFork {
+               gothrow("stack growth after fork")
+       }
+       if thisg.m.morebuf.g != thisg.m.curg {
+               print("runtime: newstack called from g=", thisg.m.morebuf.g, "\n"+"\tm=", thisg.m, " m->curg=", thisg.m.curg, " m->g0=", thisg.m.g0, " m->gsignal=", thisg.m.gsignal, "\n")
+               morebuf := thisg.m.morebuf
+               traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g)
+               gothrow("runtime: wrong goroutine in newstack")
+       }
+       if thisg.m.curg.throwsplit {
+               gp := thisg.m.curg
+               // Update syscallsp, syscallpc in case traceback uses them.
+               morebuf := thisg.m.morebuf
+               gp.syscallsp = morebuf.sp
+               gp.syscallpc = morebuf.pc
+               print("runtime: newstack sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
+                       "\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
+                       "\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
+               gothrow("runtime: stack split at bad time")
+       }
+
+       // The goroutine must be executing in order to call newstack,
+       // so it must be Grunning or Gscanrunning.
+
+       gp := thisg.m.curg
+       morebuf := thisg.m.morebuf
+       thisg.m.morebuf.pc = 0
+       thisg.m.morebuf.lr = 0
+       thisg.m.morebuf.sp = 0
+       thisg.m.morebuf.g = nil
+
+       casgstatus(gp, _Grunning, _Gwaiting)
+       gp.waitreason = "stack growth"
+
+       rewindmorestack(&gp.sched)
+
+       if gp.stack.lo == 0 {
+               gothrow("missing stack in newstack")
+       }
+       sp := gp.sched.sp
+       if thechar == '6' || thechar == '8' {
+               // The call to morestack cost a word.
+               sp -= ptrSize
+       }
+       if stackDebug >= 1 || sp < gp.stack.lo {
+               print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
+                       "\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
+                       "\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
+       }
+       if sp < gp.stack.lo {
+               print("runtime: gp=", gp, ", gp->status=", hex(readgstatus(gp)), "\n ")
+               print("runtime: split stack overflow: ", hex(sp), " < ", hex(gp.stack.lo), "\n")
+               gothrow("runtime: split stack overflow")
+       }
+
+       if gp.stackguard0 == stackPreempt {
+               if gp == thisg.m.g0 {
+                       gothrow("runtime: preempt g0")
+               }
+               if thisg.m.p == nil && thisg.m.locks == 0 {
+                       gothrow("runtime: g is running but p is not")
+               }
+               if gp.preemptscan {
+                       gcphasework(gp)
+                       casgstatus(gp, _Gwaiting, _Grunning)
+                       gp.stackguard0 = gp.stack.lo + _StackGuard
+                       gp.preempt = false
+                       gp.preemptscan = false // Tells the GC premption was successful.
+                       gogo(&gp.sched)        // never return
+               }
+
+               // Be conservative about where we preempt.
+               // We are interested in preempting user Go code, not runtime code.
+               if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.gcing != 0 || thisg.m.p.status != _Prunning {
+                       // Let the goroutine keep running for now.
+                       // gp->preempt is set, so it will be preempted next time.
+                       gp.stackguard0 = gp.stack.lo + _StackGuard
+                       casgstatus(gp, _Gwaiting, _Grunning)
+                       gogo(&gp.sched) // never return
+               }
+
+               // Act like goroutine called runtime.Gosched.
+               casgstatus(gp, _Gwaiting, _Grunning)
+               gosched_m(gp) // never return
+       }
+
+       // Allocate a bigger segment and move the stack.
+       oldsize := int(gp.stack.hi - gp.stack.lo)
+       newsize := oldsize * 2
+       if uintptr(newsize) > maxstacksize {
+               print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
+               gothrow("stack overflow")
+       }
+
+       // Note that the concurrent GC might be scanning the stack as we try to replace it.
+       // copystack takes care of the appropriate coordination with the stack scanner.
+       copystack(gp, uintptr(newsize))
+       if stackDebug >= 1 {
+               print("stack grow done\n")
+       }
+       casgstatus(gp, _Gwaiting, _Grunning)
+       gogo(&gp.sched)
+}
+
+//go:nosplit
+func nilfunc() {
+       *(*uint8)(nil) = 0
+}
+
+// adjust Gobuf as if it executed a call to fn
+// and then did an immediate gosave.
+func gostartcallfn(gobuf *gobuf, fv *funcval) {
+       var fn unsafe.Pointer
+       if fv != nil {
+               fn = (unsafe.Pointer)(fv.fn)
+       } else {
+               fn = unsafe.Pointer(funcPC(nilfunc))
+       }
+       gostartcall(gobuf, fn, (unsafe.Pointer)(fv))
+}
+
+// Maybe shrink the stack being used by gp.
+// Called at garbage collection time.
+func shrinkstack(gp *g) {
+       if readgstatus(gp) == _Gdead {
+               if gp.stack.lo != 0 {
+                       // Free whole stack - it will get reallocated
+                       // if G is used again.
+                       stackfree(gp.stack)
+                       gp.stack.lo = 0
+                       gp.stack.hi = 0
+               }
+               return
+       }
+       if gp.stack.lo == 0 {
+               gothrow("missing stack in shrinkstack")
+       }
+
+       oldsize := gp.stack.hi - gp.stack.lo
+       newsize := oldsize / 2
+       if newsize < _FixedStack {
+               return // don't shrink below the minimum-sized stack
+       }
+       used := gp.stack.hi - gp.sched.sp
+       if used >= oldsize/4 {
+               return // still using at least 1/4 of the segment.
+       }
+
+       // We can't copy the stack if we're in a syscall.
+       // The syscall might have pointers into the stack.
+       if gp.syscallsp != 0 {
+               return
+       }
+
+       /* TODO
+       if goos_windows && gp.m != nil && gp.m.libcallsp != 0 {
+               return
+       }
+       */
+
+       if stackDebug > 0 {
+               print("shrinking stack ", oldsize, "->", newsize, "\n")
+       }
+       copystack(gp, newsize)
+}
+
+// Do any delayed stack freeing that was queued up during GC.
+func shrinkfinish() {
+       lock(&stackpoolmu)
+       s := stackfreequeue
+       stackfreequeue = stack{}
+       unlock(&stackpoolmu)
+       for s.lo != 0 {
+               t := *(*stack)(unsafe.Pointer(s.lo))
+               stackfree(s)
+               s = t
+       }
+}
+
+//go:nosplit
+func morestackc() {
+       systemstack(func() {
+               gothrow("attempt to execute C code on Go stack")
+       })
+}
diff --git a/src/runtime/stack2.go b/src/runtime/stack2.go
new file mode 100644 (file)
index 0000000..e50b32c
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+/*
+Stack layout parameters.
+Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
+
+The per-goroutine g->stackguard is set to point StackGuard bytes
+above the bottom of the stack.  Each function compares its stack
+pointer against g->stackguard to check for overflow.  To cut one
+instruction from the check sequence for functions with tiny frames,
+the stack is allowed to protrude StackSmall bytes below the stack
+guard.  Functions with large frames don't bother with the check and
+always call morestack.  The sequences are (for amd64, others are
+similar):
+
+       guard = g->stackguard
+       frame = function's stack frame size
+       argsize = size of function arguments (call + return)
+
+       stack frame size <= StackSmall:
+               CMPQ guard, SP
+               JHI 3(PC)
+               MOVQ m->morearg, $(argsize << 32)
+               CALL morestack(SB)
+
+       stack frame size > StackSmall but < StackBig
+               LEAQ (frame-StackSmall)(SP), R0
+               CMPQ guard, R0
+               JHI 3(PC)
+               MOVQ m->morearg, $(argsize << 32)
+               CALL morestack(SB)
+
+       stack frame size >= StackBig:
+               MOVQ m->morearg, $((argsize << 32) | frame)
+               CALL morestack(SB)
+
+The bottom StackGuard - StackSmall bytes are important: there has
+to be enough room to execute functions that refuse to check for
+stack overflow, either because they need to be adjacent to the
+actual caller's frame (deferproc) or because they handle the imminent
+stack overflow (morestack).
+
+For example, deferproc might call malloc, which does one of the
+above checks (without allocating a full frame), which might trigger
+a call to morestack.  This sequence needs to fit in the bottom
+section of the stack.  On amd64, morestack's frame is 40 bytes, and
+deferproc's frame is 56 bytes.  That fits well within the
+StackGuard - StackSmall bytes at the bottom.
+The linkers explore all possible call traces involving non-splitting
+functions to make sure that this limit cannot be violated.
+*/
+
+const (
+       // StackSystem is a number of additional bytes to add
+       // to each stack below the usual guard area for OS-specific
+       // purposes like signal handling. Used on Windows and on
+       // Plan 9 because they do not use a separate stack.
+       _StackSystem = goos_windows*512*ptrSize + goos_plan9*512
+
+       // The minimum size of stack used by Go code
+       _StackMin = 2048
+
+       // The minimum stack size to allocate.
+       // The hackery here rounds FixedStack0 up to a power of 2.
+       _FixedStack0 = _StackMin + _StackSystem
+       _FixedStack1 = _FixedStack0 - 1
+       _FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1)
+       _FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2)
+       _FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4)
+       _FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8)
+       _FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16)
+       _FixedStack  = _FixedStack6 + 1
+
+       // Functions that need frames bigger than this use an extra
+       // instruction to do the stack split check, to avoid overflow
+       // in case SP - framesize wraps below zero.
+       // This value can be no bigger than the size of the unmapped
+       // space at zero.
+       _StackBig = 4096
+
+       // The stack guard is a pointer this many bytes above the
+       // bottom of the stack.
+       _StackGuard = 512 + _StackSystem
+
+       // After a stack split check the SP is allowed to be this
+       // many bytes below the stack guard.  This saves an instruction
+       // in the checking sequence for tiny frames.
+       _StackSmall = 128
+
+       // The maximum number of bytes that a chain of NOSPLIT
+       // functions can use.
+       _StackLimit = _StackGuard - _StackSystem - _StackSmall
+)
+
+// Goroutine preemption request.
+// Stored into g->stackguard0 to cause split stack check failure.
+// Must be greater than any real sp.
+// 0xfffffade in hex.
+const (
+       _StackPreempt = uintptrMask & -1314
+       _StackFork    = uintptrMask & -1234
+)
diff --git a/src/runtime/string.c b/src/runtime/string.c
deleted file mode 100644 (file)
index ed5debc..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "race.h"
-#include "textflag.h"
-
-String runtime·emptystring;
-
-#pragma textflag NOSPLIT
-intgo
-runtime·findnull(byte *s)
-{
-       intgo l;
-
-       if(s == nil)
-               return 0;
-       for(l=0; s[l]!=0; l++)
-               ;
-       return l;
-}
-
-intgo
-runtime·findnullw(uint16 *s)
-{
-       intgo l;
-
-       if(s == nil)
-               return 0;
-       for(l=0; s[l]!=0; l++)
-               ;
-       return l;
-}
-
-uintptr runtime·maxstring = 256; // a hint for print
-
-#pragma textflag NOSPLIT
-String
-runtime·gostringnocopy(byte *str)
-{
-       String s;
-       uintptr ms;
-       
-       s.str = str;
-       s.len = runtime·findnull(str);
-       while(true) {
-               ms = runtime·maxstring;
-               if(s.len <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)s.len))
-                       return s;
-       }
-}
-
-// TODO: move this elsewhere
-enum
-{
-       Bit1    = 7,
-       Bitx    = 6,
-       Bit2    = 5,
-       Bit3    = 4,
-       Bit4    = 3,
-       Bit5    = 2,
-
-       Tx      = ((1<<(Bitx+1))-1) ^ 0xFF,     /* 1000 0000 */
-       T2      = ((1<<(Bit2+1))-1) ^ 0xFF,     /* 1100 0000 */
-       T3      = ((1<<(Bit3+1))-1) ^ 0xFF,     /* 1110 0000 */
-       T4      = ((1<<(Bit4+1))-1) ^ 0xFF,     /* 1111 0000 */
-
-       Rune1   = (1<<(Bit1+0*Bitx))-1,         /* 0000 0000 0111 1111 */
-       Rune2   = (1<<(Bit2+1*Bitx))-1,         /* 0000 0111 1111 1111 */
-       Rune3   = (1<<(Bit3+2*Bitx))-1,         /* 1111 1111 1111 1111 */
-
-       Maskx   = (1<<Bitx)-1,                  /* 0011 1111 */
-
-       Runeerror       = 0xFFFD,
-
-       SurrogateMin = 0xD800,
-       SurrogateMax = 0xDFFF,
-
-       Runemax = 0x10FFFF,     /* maximum rune value */
-};
-
-static int32
-runetochar(byte *str, int32 rune)  /* note: in original, arg2 was pointer */
-{
-       /* Runes are signed, so convert to unsigned for range check. */
-       uint32 c;
-
-       /*
-        * one character sequence
-        *      00000-0007F => 00-7F
-        */
-       c = rune;
-       if(c <= Rune1) {
-               str[0] = c;
-               return 1;
-       }
-
-       /*
-        * two character sequence
-        *      0080-07FF => T2 Tx
-        */
-       if(c <= Rune2) {
-               str[0] = T2 | (c >> 1*Bitx);
-               str[1] = Tx | (c & Maskx);
-               return 2;
-       }
-
-       /*
-        * If the Rune is out of range or a surrogate half, convert it to the error rune.
-        * Do this test here because the error rune encodes to three bytes.
-        * Doing it earlier would duplicate work, since an out of range
-        * Rune wouldn't have fit in one or two bytes.
-        */
-       if (c > Runemax)
-               c = Runeerror;
-       if (SurrogateMin <= c && c <= SurrogateMax)
-               c = Runeerror;
-
-       /*
-        * three character sequence
-        *      0800-FFFF => T3 Tx Tx
-        */
-       if (c <= Rune3) {
-               str[0] = T3 |  (c >> 2*Bitx);
-               str[1] = Tx | ((c >> 1*Bitx) & Maskx);
-               str[2] = Tx |  (c & Maskx);
-               return 3;
-       }
-
-       /*
-        * four character sequence (21-bit value)
-        *     10000-1FFFFF => T4 Tx Tx Tx
-        */
-       str[0] = T4 | (c >> 3*Bitx);
-       str[1] = Tx | ((c >> 2*Bitx) & Maskx);
-       str[2] = Tx | ((c >> 1*Bitx) & Maskx);
-       str[3] = Tx | (c & Maskx);
-       return 4;
-}
-
-String runtime·gostringsize(intgo);
-
-String
-runtime·gostringw(uint16 *str)
-{
-       intgo n1, n2, i;
-       byte buf[8];
-       String s;
-
-       n1 = 0;
-       for(i=0; str[i]; i++)
-               n1 += runetochar(buf, str[i]);
-       s = runtime·gostringsize(n1+4);
-       n2 = 0;
-       for(i=0; str[i]; i++) {
-               // check for race
-               if(n2 >= n1)
-                       break;
-               n2 += runetochar(s.str+n2, str[i]);
-       }
-       s.len = n2;
-       s.str[s.len] = 0;
-       return s;
-}
-
-int32
-runtime·strcmp(byte *s1, byte *s2)
-{
-       uintptr i;
-       byte c1, c2;
-
-       for(i=0;; i++) {
-               c1 = s1[i];
-               c2 = s2[i];
-               if(c1 < c2)
-                       return -1;
-               if(c1 > c2)
-                       return +1;
-               if(c1 == 0)
-                       return 0;
-       }
-}
-
-int32
-runtime·strncmp(byte *s1, byte *s2, uintptr n)
-{
-       uintptr i;
-       byte c1, c2;
-
-       for(i=0; i<n; i++) {
-               c1 = s1[i];
-               c2 = s2[i];
-               if(c1 < c2)
-                       return -1;
-               if(c1 > c2)
-                       return +1;
-               if(c1 == 0)
-                       break;
-       }
-       return 0;
-}
-
-byte*
-runtime·strstr(byte *s1, byte *s2)
-{
-       byte *sp1, *sp2;
-
-       if(*s2 == 0)
-               return s1;
-       for(; *s1; s1++) {
-               if(*s1 != *s2)
-                       continue;
-               sp1 = s1;
-               sp2 = s2;
-               for(;;) {
-                       if(*sp2 == 0)
-                               return s1;
-                       if(*sp1++ != *sp2++)
-                               break;
-               }
-       }
-       return nil;
-}
index 0809f89bc1fe1796b3fcb54885185cb270522814..e01bc3b846ad3c673dbd34c803098e8fe8e404eb 100644 (file)
@@ -39,22 +39,18 @@ func concatstrings(a []string) string {
        return s
 }
 
-//go:nosplit
 func concatstring2(a [2]string) string {
        return concatstrings(a[:])
 }
 
-//go:nosplit
 func concatstring3(a [3]string) string {
        return concatstrings(a[:])
 }
 
-//go:nosplit
 func concatstring4(a [4]string) string {
        return concatstrings(a[:])
 }
 
-//go:nosplit
 func concatstring5(a [5]string) string {
        return concatstrings(a[:])
 }
@@ -225,7 +221,7 @@ func rawbyteslice(size int) (b []byte) {
 
 // rawruneslice allocates a new rune slice. The rune slice is not zeroed.
 func rawruneslice(size int) (b []rune) {
-       if uintptr(size) > maxmem/4 {
+       if uintptr(size) > _MaxMem/4 {
                gothrow("out of memory")
        }
        mem := goroundupsize(uintptr(size) * 4)
@@ -255,9 +251,6 @@ func gostringsize(n int) string {
        return s
 }
 
-//go:noescape
-func findnull(*byte) int
-
 func gostring(p *byte) string {
        l := findnull(p)
        if l == 0 {
@@ -296,3 +289,12 @@ func contains(s, t string) bool {
 func hasprefix(s, t string) bool {
        return len(s) >= len(t) && s[:len(t)] == t
 }
+
+func goatoi(s string) int {
+       n := 0
+       for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+               n = n*10 + int(s[0]) - '0'
+               s = s[1:]
+       }
+       return n
+}
diff --git a/src/runtime/string1.go b/src/runtime/string1.go
new file mode 100644 (file)
index 0000000..35cde43
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+//go:nosplit
+func findnull(s *byte) int {
+       if s == nil {
+               return 0
+       }
+       p := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s))
+       l := 0
+       for p[l] != 0 {
+               l++
+       }
+       return l
+}
+
+func findnullw(s *uint16) int {
+       if s == nil {
+               return 0
+       }
+       p := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(s))
+       l := 0
+       for p[l] != 0 {
+               l++
+       }
+       return l
+}
+
+var maxstring uintptr = 256 // a hint for print
+
+//go:nosplit
+func gostringnocopy(str *byte) string {
+       var s string
+       sp := (*stringStruct)(unsafe.Pointer(&s))
+       sp.str = unsafe.Pointer(str)
+       sp.len = findnull(str)
+       for {
+               ms := maxstring
+               if uintptr(len(s)) <= ms || casuintptr(&maxstring, ms, uintptr(len(s))) {
+                       break
+               }
+       }
+       return s
+}
+
+func gostringw(strw *uint16) string {
+       var buf [8]byte
+       str := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw))
+       n1 := 0
+       for i := 0; str[i] != 0; i++ {
+               n1 += runetochar(buf[:], rune(str[i]))
+       }
+       s, b := rawstring(n1 + 4)
+       n2 := 0
+       for i := 0; str[i] != 0; i++ {
+               // check for race
+               if n2 >= n1 {
+                       break
+               }
+               n2 += runetochar(b[n2:], rune(str[i]))
+       }
+       b[n2] = 0 // for luck
+       return s[:n2]
+}
+
+func strcmp(s1, s2 *byte) int32 {
+       p1 := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s1))
+       p2 := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s2))
+
+       for i := uintptr(0); ; i++ {
+               c1 := p1[i]
+               c2 := p2[i]
+               if c1 < c2 {
+                       return -1
+               }
+               if c1 > c2 {
+                       return +1
+               }
+               if c1 == 0 {
+                       return 0
+               }
+       }
+}
+
+func strncmp(s1, s2 *byte, n uintptr) int32 {
+       p1 := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s1))
+       p2 := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s2))
+
+       for i := uintptr(0); i < n; i++ {
+               c1 := p1[i]
+               c2 := p2[i]
+               if c1 < c2 {
+                       return -1
+               }
+               if c1 > c2 {
+                       return +1
+               }
+               if c1 == 0 {
+                       break
+               }
+       }
+       return 0
+}
index 1282397adb4e587ab82c7f388d605917235279cb..aa7577cf9438f27abcb0403516230f63c8140baf 100644 (file)
@@ -23,12 +23,7 @@ func roundup(p unsafe.Pointer, n uintptr) unsafe.Pointer {
        return unsafe.Pointer(uintptr(p) + delta)
 }
 
-// in runtime.c
 func getg() *g
-func acquirem() *m
-func releasem(mp *m)
-func gomcache() *mcache
-func readgstatus(*g) uint32 // proc.c
 
 // mcall switches from the g to the g0 stack and invokes fn(g),
 // where g is the goroutine that made the call.
@@ -43,85 +38,30 @@ func readgstatus(*g) uint32 // proc.c
 //go:noescape
 func mcall(fn func(*g))
 
-// onM switches from the g to the g0 stack and invokes fn().
-// When fn returns, onM switches back to the g and returns,
-// continuing execution on the g stack.
-// If arguments must be passed to fn, they can be written to
-// g->m->ptrarg (pointers) and g->m->scalararg (non-pointers)
-// before the call and then consulted during fn.
-// Similarly, fn can pass return values back in those locations.
-// If fn is written in Go, it can be a closure, which avoids the need for
-// ptrarg and scalararg entirely.
-// After reading values out of ptrarg and scalararg it is conventional
-// to zero them to avoid (memory or information) leaks.
+// systemstack runs fn on a system stack.
+// If systemstack is called from the per-OS-thread (g0) stack, or
+// if systemstack is called from the signal handling (gsignal) stack,
+// systemstack calls fn directly and returns.
+// Otherwise, systemstack is being called from the limited stack
+// of an ordinary goroutine. In this case, systemstack switches
+// to the per-OS-thread stack, calls fn, and switches back.
+// It is common to use a func literal as the argument, in order
+// to share inputs and outputs with the code around the call
+// to system stack:
 //
-// If onM is called from a g0 stack, it invokes fn and returns,
-// without any stack switches.
-//
-// If onM is called from a gsignal stack, it crashes the program.
-// The implication is that functions used in signal handlers must
-// not use onM.
-//
-// NOTE(rsc): We could introduce a separate onMsignal that is
-// like onM but if called from a gsignal stack would just run fn on
-// that stack. The caller of onMsignal would be required to save the
-// old values of ptrarg/scalararg and restore them when the call
-// was finished, in case the signal interrupted an onM sequence
-// in progress on the g or g0 stacks. Until there is a clear need for this,
-// we just reject onM in signal handling contexts entirely.
-//
-//go:noescape
-func onM(fn func())
-
-// onMsignal is like onM but is allowed to be used in code that
-// might run on the gsignal stack. Code running on a signal stack
-// may be interrupting an onM sequence on the main stack, so
-// if the onMsignal calling sequence writes to ptrarg/scalararg,
-// it must first save the old values and then restore them when
-// finished. As an exception to the rule, it is fine not to save and
-// restore the values if the program is trying to crash rather than
-// return from the signal handler.
-// Once all the runtime is written in Go, there will be no ptrarg/scalararg
-// and the distinction between onM and onMsignal (and perhaps mcall)
-// can go away.
-//
-// If onMsignal is called from a gsignal stack, it invokes fn directly,
-// without a stack switch. Otherwise onMsignal behaves like onM.
+//     ... set up y ...
+//     systemstack(func() {
+//             x = bigcall(y)
+//     })
+//     ... use x ...
 //
 //go:noescape
-func onM_signalok(fn func())
+func systemstack(fn func())
 
-func badonm() {
-       gothrow("onM called from signal goroutine")
+func badsystemstack() {
+       gothrow("systemstack called from unexpected goroutine")
 }
 
-// C functions that run on the M stack.
-// Call using mcall.
-func gosched_m(*g)
-func park_m(*g)
-func recovery_m(*g)
-
-// More C functions that run on the M stack.
-// Call using onM.
-func mcacheRefill_m()
-func largeAlloc_m()
-func gc_m()
-func scavenge_m()
-func setFinalizer_m()
-func removeFinalizer_m()
-func markallocated_m()
-func unrollgcprog_m()
-func unrollgcproginplace_m()
-func setgcpercent_m()
-func setmaxthreads_m()
-func ready_m()
-func deferproc_m()
-func goexit_m()
-func startpanic_m()
-func dopanic_m()
-func readmemstats_m()
-func writeheapdump_m()
-
 // memclr clears n bytes starting at ptr.
 // in memclr_*.s
 //go:noescape
@@ -132,12 +72,6 @@ func memclr(ptr unsafe.Pointer, n uintptr)
 //go:noescape
 func memmove(to unsafe.Pointer, from unsafe.Pointer, n uintptr)
 
-func starttheworld()
-func stoptheworld()
-func newextram()
-func lockOSThread()
-func unlockOSThread()
-
 // exported value for testing
 var hashLoad = loadFactor
 
@@ -159,16 +93,9 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
        return unsafe.Pointer(x ^ 0)
 }
 
-func entersyscall()
-func reentersyscall(pc uintptr, sp unsafe.Pointer)
-func entersyscallblock()
-func exitsyscall()
-
 func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
 func gogo(buf *gobuf)
 func gosave(buf *gobuf)
-func read(fd int32, p unsafe.Pointer, n int32) int32
-func close(fd int32) int32
 func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
 
 //go:noescape
@@ -176,35 +103,31 @@ func jmpdefer(fv *funcval, argp uintptr)
 func exit1(code int32)
 func asminit()
 func setg(gg *g)
-func exit(code int32)
 func breakpoint()
-func nanotime() int64
-func usleep(usec uint32)
-
-// careful: cputicks is not guaranteed to be monotonic!  In particular, we have
-// noticed drift between cpus on certain os/arch combinations.  See issue 8976.
-func cputicks() int64
 
-func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
-func munmap(addr unsafe.Pointer, n uintptr)
-func madvise(addr unsafe.Pointer, n uintptr, flags int32)
 func reflectcall(fn, arg unsafe.Pointer, n uint32, retoffset uint32)
-func osyield()
 func procyield(cycles uint32)
 func cgocallback_gofunc(fv *funcval, frame unsafe.Pointer, framesize uintptr)
-func readgogc() int32
-func purgecachedstats(c *mcache)
-func gostringnocopy(b *byte) string
 func goexit()
 
-//go:noescape
-func write(fd uintptr, p unsafe.Pointer, n int32) int32
-
 //go:noescape
 func cas(ptr *uint32, old, new uint32) bool
 
-//go:noescape
-func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
+// casp cannot have a go:noescape annotation, because
+// while ptr and old do not escape, new does. If new is marked as
+// not escaping, the compiler will make incorrect escape analysis
+// decisions about the value being xchg'ed.
+// Instead, make casp a wrapper around the actual atomic.
+// When calling the wrapper we mark ptr as noescape explicitly.
+
+//go:nosplit
+func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
+       return casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new)
+}
+
+func casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
+
+func nop() // call to prevent inlining of function body
 
 //go:noescape
 func casuintptr(ptr *uintptr, old, new uintptr) bool
@@ -261,18 +184,10 @@ func asmcgocall(fn, arg unsafe.Pointer)
 //go:noescape
 func asmcgocall_errno(fn, arg unsafe.Pointer) int32
 
-//go:noescape
-func open(name *byte, mode, perm int32) int32
-
-//go:noescape
-func gotraceback(*bool) int32
-
+// argp used in Defer structs when there is no argp.
 const _NoArgs = ^uintptr(0)
 
-func newstack()
-func newproc()
 func morestack()
-func mstart()
 func rt0_go()
 
 // return0 is a stub used to return 0 from deferproc.
@@ -314,3 +229,5 @@ func call134217728(fn, arg unsafe.Pointer, n, retoffset uint32)
 func call268435456(fn, arg unsafe.Pointer, n, retoffset uint32)
 func call536870912(fn, arg unsafe.Pointer, n, retoffset uint32)
 func call1073741824(fn, arg unsafe.Pointer, n, retoffset uint32)
+
+func systemstack_switch()
diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go
new file mode 100644 (file)
index 0000000..cb0b0f0
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !solaris
+// +build !windows
+
+package runtime
+
+import "unsafe"
+
+func read(fd int32, p unsafe.Pointer, n int32) int32
+func close(fd int32) int32
+
+func exit(code int32)
+func nanotime() int64
+func usleep(usec uint32)
+
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
+func munmap(addr unsafe.Pointer, n uintptr)
+
+//go:noescape
+func write(fd uintptr, p unsafe.Pointer, n int32) int32
+
+//go:noescape
+func open(name *byte, mode, perm int32) int32
+
+func madvise(addr unsafe.Pointer, n uintptr, flags int32)
index 45d107b777869e1a0cd7e4bcd7c38922e85eeba4..749a289cd10bbb53747c0cc0d89d78f188750221 100644 (file)
@@ -22,8 +22,7 @@ func (f *Func) raw() *_func {
 
 // funcdata.h
 const (
-       _PCDATA_ArgSize             = 0
-       _PCDATA_StackMapIndex       = 1
+       _PCDATA_StackMapIndex       = 0
        _FUNCDATA_ArgsPointerMaps   = 0
        _FUNCDATA_LocalsPointerMaps = 1
        _FUNCDATA_DeadValueMaps     = 2
@@ -122,8 +121,8 @@ func (f *Func) Entry() uintptr {
 func (f *Func) FileLine(pc uintptr) (file string, line int) {
        // Pass strict=false here, because anyone can call this function,
        // and they might just be wrong about targetpc belonging to f.
-       line = int(funcline1(f.raw(), pc, &file, false))
-       return file, line
+       file, line32 := funcline1(f.raw(), pc, false)
+       return file, int(line32)
 }
 
 func findfunc(pc uintptr) *_func {
@@ -208,20 +207,19 @@ func gofuncname(f *_func) string {
        return gostringnocopy(funcname(f))
 }
 
-func funcline1(f *_func, targetpc uintptr, file *string, strict bool) int32 {
-       *file = "?"
+func funcline1(f *_func, targetpc uintptr, strict bool) (file string, line int32) {
        fileno := int(pcvalue(f, f.pcfile, targetpc, strict))
-       line := pcvalue(f, f.pcln, targetpc, strict)
+       line = pcvalue(f, f.pcln, targetpc, strict)
        if fileno == -1 || line == -1 || fileno >= len(filetab) {
                // print("looking for ", hex(targetpc), " in ", gofuncname(f), " got file=", fileno, " line=", lineno, "\n")
-               return 0
+               return "?", 0
        }
-       *file = gostringnocopy(&pclntable[filetab[fileno]])
-       return line
+       file = gostringnocopy(&pclntable[filetab[fileno]])
+       return
 }
 
-func funcline(f *_func, targetpc uintptr, file *string) int32 {
-       return funcline1(f, targetpc, file, true)
+func funcline(f *_func, targetpc uintptr) (file string, line int32) {
+       return funcline1(f, targetpc, true)
 }
 
 func funcspdelta(f *_func, targetpc uintptr) int32 {
diff --git a/src/runtime/sys_arm.c b/src/runtime/sys_arm.c
deleted file mode 100644 (file)
index a65560e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-
-// adjust Gobuf as if it executed a call to fn with context ctxt
-// and then did an immediate Gosave.
-void
-runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt)
-{
-       if(gobuf->lr != 0)
-               runtime·throw("invalid use of gostartcall");
-       gobuf->lr = gobuf->pc;
-       gobuf->pc = (uintptr)fn;
-       gobuf->ctxt = ctxt;
-}
-
-// Called to rewind context saved during morestack back to beginning of function.
-// To help us, the linker emits a jmp back to the beginning right after the
-// call to morestack. We just have to decode and apply that jump.
-void
-runtime·rewindmorestack(Gobuf *gobuf)
-{
-       uint32 inst;
-
-       inst = *(uint32*)gobuf->pc;
-       if((gobuf->pc&3) == 0 && (inst>>24) == 0x9a) {
-               //runtime·printf("runtime: rewind pc=%p to pc=%p\n", gobuf->pc, gobuf->pc + ((int32)(inst<<8)>>6) + 8);
-               gobuf->pc += ((int32)(inst<<8)>>6) + 8;
-               return;
-       }
-       runtime·printf("runtime: pc=%p %x\n", gobuf->pc, inst);
-       runtime·throw("runtime: misuse of rewindmorestack");
-}
diff --git a/src/runtime/sys_arm.go b/src/runtime/sys_arm.go
new file mode 100644 (file)
index 0000000..81777c7
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// adjust Gobuf as if it executed a call to fn with context ctxt
+// and then did an immediate Gosave.
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+       if buf.lr != 0 {
+               gothrow("invalid use of gostartcall")
+       }
+       buf.lr = buf.pc
+       buf.pc = uintptr(fn)
+       buf.ctxt = ctxt
+}
+
+// Called to rewind context saved during morestack back to beginning of function.
+// To help us, the linker emits a jmp back to the beginning right after the
+// call to morestack. We just have to decode and apply that jump.
+func rewindmorestack(buf *gobuf) {
+       var inst uint32
+       if buf.pc&3 == 0 && buf.pc != 0 {
+               inst = *(*uint32)(unsafe.Pointer(buf.pc))
+               if inst>>24 == 0x9a {
+                       buf.pc += uintptr(int32(inst<<8)>>6) + 8
+                       return
+               }
+       }
+
+       print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
+       gothrow("runtime: misuse of rewindmorestack")
+}
index a961c71a83abe602527da067fd78d51edadd113a..7cb5695e7c05d263572e9143cc5c0cb77466e663 100644 (file)
@@ -6,7 +6,8 @@
 // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // Exit the entire program (like C exit)
@@ -248,7 +249,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$40
        MOVL    BX, 0(SP)
        MOVL    $runtime·badsignal(SB), AX
        CALL    AX
-       JMP     sigtramp_ret
+       JMP     ret
 
        // save g
        MOVL    DI, 20(SP)
@@ -275,7 +276,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$40
        MOVL    20(SP), DI
        MOVL    DI, g(CX)
 
-sigtramp_ret:
+ret:
        // call sigreturn
        MOVL    context+16(FP), CX
        MOVL    style+4(FP), BX
index bd397d72a76ae538f81b938499a6b8574fa83c68..0a955f98280f9fb82d7bb08522a9521d53b03360 100644 (file)
@@ -11,7 +11,8 @@
 // The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // Exit the entire program (like C exit)
@@ -211,7 +212,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
        MOVL    DX, 0(SP)
        MOVQ    $runtime·badsignal(SB), AX
        CALL    AX
-       JMP     sigtramp_ret
+       JMP     ret
 
        // save g
        MOVQ    R10, 48(SP)
@@ -233,7 +234,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
        MOVQ    48(SP), R10
        MOVQ    R10, g(BX)
 
-sigtramp_ret:
+ret:
        // call sigreturn
        MOVL    $(0x2000000+184), AX    // sigreturn(ucontext, infostyle)
        MOVQ    32(SP), DI      // saved ucontext
index 161eaec19d3688b3064a5ddc80b5654e3bff0180..bb4903ef6795eeaefc34ad2b77c6252be70e2d80 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
        
 TEXT runtime·sys_umtx_sleep(SB),NOSPLIT,$-4
@@ -217,7 +218,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
        MOVL    BX, 0(SP)
        MOVL    $runtime·badsignal(SB), AX
        CALL    AX
-       JMP     sigtramp_ret
+       JMP     ret
 
        // save g
        MOVL    DI, 20(SP)
@@ -243,7 +244,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
        MOVL    20(SP), BX
        MOVL    BX, g(CX)
 
-sigtramp_ret:
+ret:
        // call sigreturn
        MOVL    context+8(FP), AX
        MOVL    $0, 0(SP)       // syscall gap
index 2c756018c2566595a9437f0d6515dc7e6515f364..db07ed70325d52aed48af49de49546ed902da073 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
        
 TEXT runtime·sys_umtx_sleep(SB),NOSPLIT,$0
index 2c40fc433bb0addda7d10833e9948f7f8d16660b..d1f67c3fcc07af8823980f5c5bc71d18554262a7 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
        
 TEXT runtime·sys_umtx_op(SB),NOSPLIT,$-4
@@ -197,7 +198,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
        MOVL    BX, 0(SP)
        MOVL    $runtime·badsignal(SB), AX
        CALL    AX
-       JMP     sigtramp_ret
+       JMP     ret
 
        // save g
        MOVL    DI, 20(SP)
@@ -223,7 +224,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
        MOVL    20(SP), BX
        MOVL    BX, g(CX)
 
-sigtramp_ret:
+ret:
        // call sigreturn
        MOVL    context+8(FP), AX
        MOVL    $0, 0(SP)       // syscall gap
index 65f8c1a6eeef3a8a6a0bb1a5cab1affa365f8595..84cee51d8c1c2982c171c199d73461f47ba42e61 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // FreeBSD 8, FreeBSD 9, and older versions that I have checked
index d875138b6282c5ab045edc5a2668d44f3d8585b5..198b427bf7ac0960bac33b48dbd366ddb11daa82 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // for EABI, as we don't support OABI
@@ -362,7 +363,7 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
        SWI $0
        RET
 
-TEXT runtime·casp(SB),NOSPLIT,$0
+TEXT runtime·casp1(SB),NOSPLIT,$0
        B       runtime·cas(SB)
 
 // TODO(minux): this is only valid for ARMv6+
index 0f6d4bbb5e58e84dc96163cc6be79d4e073ce0e2..1861f237f5bb57aa8156eeb310be3b77ec45107e 100644 (file)
@@ -6,7 +6,8 @@
 // System calls and other sys.stuff for 386, Linux
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 TEXT runtime·exit(SB),NOSPLIT,$0
index 33b91e872f9a00a99221c08588394eec5d4c4ff2..6d4dfdbd2c73fa499f2fdac2b3fe517527458a2f 100644 (file)
@@ -6,7 +6,8 @@
 // System calls and other sys.stuff for AMD64, Linux
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 TEXT runtime·exit(SB),NOSPLIT,$0-4
@@ -115,7 +116,7 @@ TEXT time·now(SB),NOSPLIT,$16
        // 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
+       JEQ     fallback
        MOVL    $0, DI // CLOCK_REALTIME
        LEAQ    0(SP), SI
        CALL    AX
@@ -124,7 +125,7 @@ TEXT time·now(SB),NOSPLIT,$16
        MOVQ    AX, sec+0(FP)
        MOVL    DX, nsec+8(FP)
        RET
-fallback_gtod:
+fallback:
        LEAQ    0(SP), DI
        MOVQ    $0, SI
        MOVQ    runtime·__vdso_gettimeofday_sym(SB), AX
@@ -141,7 +142,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
        // See comment above in time.now.
        MOVQ    runtime·__vdso_clock_gettime_sym(SB), AX
        CMPQ    AX, $0
-       JEQ     fallback_gtod_nt
+       JEQ     fallback
        MOVL    $1, DI // CLOCK_MONOTONIC
        LEAQ    0(SP), SI
        CALL    AX
@@ -153,7 +154,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
        ADDQ    DX, AX
        MOVQ    AX, ret+0(FP)
        RET
-fallback_gtod_nt:
+fallback:
        LEAQ    0(SP), DI
        MOVQ    $0, SI
        MOVQ    runtime·__vdso_gettimeofday_sym(SB), AX
index bd285f399820395c7a96e1b26107741516e876a4..21d97fda9b30b338fe89600f9457968364cfb565 100644 (file)
@@ -6,7 +6,8 @@
 // System calls and other sys.stuff for arm, Linux
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // for EABI, as we don't support OABI
@@ -373,25 +374,25 @@ TEXT cas<>(SB),NOSPLIT,$0
 TEXT runtime·cas(SB),NOSPLIT,$0
        MOVW    ptr+0(FP), R2
        MOVW    old+4(FP), R0
-casagain:
+loop:
        MOVW    new+8(FP), R1
        BL      cas<>(SB)
-       BCC     cascheck
+       BCC     check
        MOVW    $1, R0
        MOVB    R0, ret+12(FP)
        RET
-cascheck:
+check:
        // Kernel lies; double-check.
        MOVW    ptr+0(FP), R2
        MOVW    old+4(FP), R0
        MOVW    0(R2), R3
        CMP     R0, R3
-       BEQ     casagain
+       BEQ     loop
        MOVW    $0, R0
        MOVB    R0, ret+12(FP)
        RET
 
-TEXT runtime·casp(SB),NOSPLIT,$0
+TEXT runtime·casp1(SB),NOSPLIT,$0
        B       runtime·cas(SB)
 
 TEXT runtime·osyield(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_linux_power64x.s b/src/runtime/sys_linux_power64x.s
new file mode 100644 (file)
index 0000000..395f657
--- /dev/null
@@ -0,0 +1,384 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build power64 power64le
+
+//
+// System calls and other sys.stuff for Power64, Linux
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define SYS_exit                 1
+#define SYS_read                 3
+#define SYS_write                4
+#define SYS_open                 5
+#define SYS_close                6
+#define SYS_fcntl               55
+#define SYS_gettimeofday        78
+#define SYS_select              82     // always return -ENOSYS
+#define SYS_mmap                90
+#define SYS_munmap              91
+#define SYS_setitimer          104
+#define SYS_clone              120
+#define SYS_newselect          142
+#define SYS_sched_yield                158
+#define SYS_rt_sigreturn       172
+#define SYS_rt_sigaction       173
+#define SYS_rt_sigprocmask     174
+#define SYS_sigaltstack                185
+#define SYS_ugetrlimit         190
+#define SYS_madvise            205
+#define SYS_mincore            206
+#define SYS_gettid             207
+#define SYS_tkill              208
+#define SYS_futex              221
+#define SYS_sched_getaffinity  223
+#define SYS_exit_group         234
+#define SYS_epoll_create       236
+#define SYS_epoll_ctl          237
+#define SYS_epoll_wait         238
+#define SYS_clock_gettime      246
+#define SYS_epoll_create1      315
+
+TEXT runtime·exit(SB),NOSPLIT,$-8-4
+       MOVW    code+0(FP), R3
+       SYSCALL $SYS_exit_group
+       RETURN
+
+TEXT runtime·exit1(SB),NOSPLIT,$-8-4
+       MOVW    code+0(FP), R3
+       SYSCALL $SYS_exit
+       RETURN
+
+TEXT runtime·open(SB),NOSPLIT,$-8-20
+       MOVD    name+0(FP), R3
+       MOVW    mode+8(FP), R4
+       MOVW    perm+12(FP), R5
+       SYSCALL $SYS_open
+       MOVW    R3, ret+16(FP)
+       RETURN
+
+TEXT runtime·close(SB),NOSPLIT,$-8-12
+       MOVW    fd+0(FP), R3
+       SYSCALL $SYS_close
+       MOVW    R3, ret+8(FP)
+       RETURN
+
+TEXT runtime·write(SB),NOSPLIT,$-8-28
+       MOVD    fd+0(FP), R3
+       MOVD    p+8(FP), R4
+       MOVW    n+16(FP), R5
+       SYSCALL $SYS_write
+       MOVW    R3, ret+24(FP)
+       RETURN
+
+TEXT runtime·read(SB),NOSPLIT,$-8-28
+       MOVW    fd+0(FP), R3
+       MOVD    p+8(FP), R4
+       MOVW    n+16(FP), R5
+       SYSCALL $SYS_read
+       MOVW    R3, ret+24(FP)
+       RETURN
+
+TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20
+       MOVW    kind+0(FP), R3
+       MOVD    limit+8(FP), R4
+       SYSCALL $SYS_ugetrlimit
+       MOVW    R3, ret+16(FP)
+       RETURN
+
+TEXT runtime·usleep(SB),NOSPLIT,$16-4
+       MOVW    usec+0(FP), R3
+       MOVD    R3, R5
+       MOVW    $1000000, R4
+       DIVD    R4, R3
+       MOVD    R3, 8(R1)
+       MULLD   R3, R4
+       SUB     R4, R5
+       MOVD    R5, 16(R1)
+
+       // select(0, 0, 0, 0, &tv)
+       MOVW    $0, R3
+       MOVW    $0, R4
+       MOVW    $0, R5
+       MOVW    $0, R6
+       ADD     $8, R1, R7
+       SYSCALL $SYS_newselect
+       RETURN
+
+TEXT runtime·raise(SB),NOSPLIT,$-8
+       SYSCALL $SYS_gettid
+       MOVW    R3, R3  // arg 1 tid
+       MOVW    sig+0(FP), R4   // arg 2
+       SYSCALL $SYS_tkill
+       RETURN
+
+TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
+       MOVW    mode+0(FP), R3
+       MOVD    new+8(FP), R4
+       MOVD    old+16(FP), R5
+       SYSCALL $SYS_setitimer
+       RETURN
+
+TEXT runtime·mincore(SB),NOSPLIT,$-8-28
+       MOVD    addr+0(FP), R3
+       MOVD    n+8(FP), R4
+       MOVD    dst+16(FP), R5
+       SYSCALL $SYS_mincore
+       MOVW    R3, ret+24(FP)
+       RETURN
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$16
+       MOVD    $0(R1), R3
+       MOVD    $0, R4
+       SYSCALL $SYS_gettimeofday
+       MOVD    0(R1), R3       // sec
+       MOVD    8(R1), R5       // usec
+       MOVD    $1000, R4
+       MULLD   R4, R5
+       MOVD    R3, sec+0(FP)
+       MOVW    R5, nsec+8(FP)
+       RETURN
+
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+       MOVW    $1, R3 // CLOCK_MONOTONIC
+       MOVD    $0(R1), R4
+       SYSCALL $SYS_clock_gettime
+       MOVD    0(R1), R3       // sec
+       MOVD    8(R1), R5       // nsec
+       // sec is in R3, nsec in R5
+       // return nsec in R3
+       MOVD    $1000000000, R4
+       MULLD   R4, R3
+       ADD     R5, R3
+       MOVD    R3, ret+0(FP)
+       RETURN
+
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
+       MOVW    sig+0(FP), R3
+       MOVD    new+8(FP), R4
+       MOVD    old+16(FP), R5
+       MOVW    size+24(FP), R6
+       SYSCALL $SYS_rt_sigprocmask
+       BVC     2(PC)
+       MOVD    R0, 0xf1(R0)    // crash
+       RETURN
+
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36
+       MOVD    sig+0(FP), R3
+       MOVD    new+8(FP), R4
+       MOVD    old+16(FP), R5
+       MOVD    size+24(FP), R6
+       SYSCALL $SYS_rt_sigaction
+       MOVW    R3, ret+32(FP)
+       RETURN
+
+#ifdef GOARCH_power64le
+// power64le doesn't need function descriptors
+TEXT runtime·sigtramp(SB),NOSPLIT,$64
+#else
+// function descriptor for the real sigtramp
+TEXT runtime·sigtramp(SB),NOSPLIT,$-8
+       DWORD   $runtime·_sigtramp(SB)
+       DWORD   $0
+       DWORD   $0
+TEXT runtime·_sigtramp(SB),NOSPLIT,$64
+#endif
+       // initialize essential registers (just in case)
+       BL      runtime·reginit(SB)
+
+       // check that g exists
+       CMP     g, $0
+       BNE     6(PC)
+       MOVD    R3, 8(R1)
+       MOVD    $runtime·badsignal(SB), R31
+       MOVD    R31, CTR
+       BL      (CTR)
+       RETURN
+
+       // save g
+       MOVD    g, 40(R1)
+       MOVD    g, R6
+
+       // g = m->gsignal
+       MOVD    g_m(g), R7
+       MOVD    m_gsignal(R7), g
+
+       MOVW    R3, 8(R1)
+       MOVD    R4, 16(R1)
+       MOVD    R5, 24(R1)
+       MOVD    R6, 32(R1)
+
+       BL      runtime·sighandler(SB)
+
+       // restore g
+       MOVD    40(R1), g
+
+       RETURN
+
+TEXT runtime·mmap(SB),NOSPLIT,$-8
+       MOVD    addr+0(FP), R3
+       MOVD    n+8(FP), R4
+       MOVW    prot+16(FP), R5
+       MOVW    flags+20(FP), R6
+       MOVW    fd+24(FP), R7
+       MOVW    off+28(FP), R8
+
+       SYSCALL $SYS_mmap
+       MOVD    R3, ret+32(FP)
+       RETURN
+
+TEXT runtime·munmap(SB),NOSPLIT,$-8
+       MOVD    addr+0(FP), R3
+       MOVD    n+8(FP), R4
+       SYSCALL $SYS_munmap
+       BVC     2(PC)
+       MOVD    R0, 0xf3(R0)
+       RETURN
+
+TEXT runtime·madvise(SB),NOSPLIT,$-8
+       MOVD    addr+0(FP), R3
+       MOVD    n+8(FP), R4
+       MOVW    flags+16(FP), R5
+       SYSCALL $SYS_madvise
+       // ignore failure - maybe pages are locked
+       RETURN
+
+// int64 futex(int32 *uaddr, int32 op, int32 val,
+//     struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),NOSPLIT,$-8
+       MOVD    addr+0(FP), R3
+       MOVW    op+8(FP), R4
+       MOVW    val+12(FP), R5
+       MOVD    ts+16(FP), R6
+       MOVD    addr2+24(FP), R7
+       MOVW    val3+32(FP), R8
+       SYSCALL $SYS_futex
+       MOVW    R3, ret+40(FP)
+       RETURN
+
+// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·clone(SB),NOSPLIT,$-8
+       MOVW    flags+0(FP), R3
+       MOVD    stk+8(FP), R4
+
+       // Copy mp, gp, fn off parent stack for use by child.
+       // Careful: Linux system call clobbers ???.
+       MOVD    mm+16(FP), R7
+       MOVD    gg+24(FP), R8
+       MOVD    fn+32(FP), R12
+
+       MOVD    R7, -8(R4)
+       MOVD    R8, -16(R4)
+       MOVD    R12, -24(R4)
+       MOVD    $1234, R7
+       MOVD    R7, -32(R4)
+
+       SYSCALL $SYS_clone
+
+       // In parent, return.
+       CMP     R3, $0
+       BEQ     3(PC)
+       MOVW    R3, ret+40(FP)
+       RETURN
+
+       // In child, on new stack.
+       // initialize essential registers
+       BL      runtime·reginit(SB)
+       MOVD    -32(R1), R7
+       CMP     R7, $1234
+       BEQ     2(PC)
+       MOVD    R0, 0(R0)
+
+       // Initialize m->procid to Linux tid
+       SYSCALL $SYS_gettid
+
+       MOVD    -24(R1), R12
+       MOVD    -16(R1), R8
+       MOVD    -8(R1), R7
+
+       MOVD    R3, m_procid(R7)
+
+       // TODO: setup TLS.
+
+       // In child, set up new stack
+       MOVD    R7, g_m(R8)
+       MOVD    R8, g
+       //CALL  runtime·stackcheck(SB)
+
+       // Call fn
+       MOVD    R12, CTR
+       BL      (CTR)
+
+       // It shouldn't return.  If it does, exit
+       MOVW    $111, R3
+       SYSCALL $SYS_exit_group
+       BR      -2(PC)  // keep exiting
+
+TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
+       MOVD    new+0(FP), R3
+       MOVD    old+8(FP), R4
+       SYSCALL $SYS_sigaltstack
+       BVC     2(PC)
+       MOVD    R0, 0xf1(R0)  // crash
+       RETURN
+
+TEXT runtime·osyield(SB),NOSPLIT,$-8
+       SYSCALL $SYS_sched_yield
+       RETURN
+
+TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
+       MOVD    pid+0(FP), R3
+       MOVD    len+8(FP), R4
+       MOVD    buf+16(FP), R5
+       SYSCALL $SYS_sched_getaffinity
+       MOVW    R3, ret+24(FP)
+       RETURN
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),NOSPLIT,$-8
+       MOVW    size+0(FP), R3
+       SYSCALL $SYS_epoll_create
+       MOVW    R3, ret+8(FP)
+       RETURN
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
+       MOVW    flags+0(FP), R3
+       SYSCALL $SYS_epoll_create1
+       MOVW    R3, ret+8(FP)
+       RETURN
+
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
+TEXT runtime·epollctl(SB),NOSPLIT,$-8
+       MOVW    epfd+0(FP), R3
+       MOVW    op+4(FP), R4
+       MOVW    fd+8(FP), R5
+       MOVD    ev+16(FP), R6
+       SYSCALL $SYS_epoll_ctl
+       MOVW    R3, ret+24(FP)
+       RETURN
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),NOSPLIT,$-8
+       MOVW    epfd+0(FP), R3
+       MOVD    ev+8(FP), R4
+       MOVW    nev+16(FP), R5
+       MOVW    timeout+20(FP), R6
+       SYSCALL $SYS_epoll_wait
+       MOVW    R3, ret+24(FP)
+       RETURN
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),NOSPLIT,$-8
+       MOVW    fd+0(FP), R3  // fd
+       MOVD    $2, R4  // F_SETFD
+       MOVD    $1, R5  // FD_CLOEXEC
+       SYSCALL $SYS_fcntl
+       RETURN
index 47985f31f5607b2a40e8abc5083186f0d91cc79d..85c8175b1a680e0a1e4ceb4d90bae3c274b73423 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 #include "syscall_nacl.h"
 
@@ -293,7 +294,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
        MOVL    $0, 0(SP)
        MOVL    $runtime·badsignal(SB), AX
        CALL    AX
-       JMP     sigtramp_ret
+       JMP     ret
 
        // save g
        MOVL    DI, 20(SP)
@@ -317,7 +318,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
        MOVL    20(SP), BX
        MOVL    BX, g(CX)
 
-sigtramp_ret:
+ret:
        // Enable exceptions again.
        NACL_SYSCALL(SYS_exception_clear_flag)
 
index 4eb4aacdd58cad0dd2d3b02b6b60d75292ee0b35..f5624ca8dfd0837630deb80a0bfc54ad650c8b3e 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 #include "syscall_nacl.h"
 
@@ -338,7 +339,6 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
        MOVL    20(SP), BX
        MOVL    BX, g(CX)
 
-sigtramp_ret:
        // Enable exceptions again.
        NACL_SYSCALL(SYS_exception_clear_flag)
 
index d354ab48373157731bb272512316c7a0cec9c50a..ded95a86b5431381313e15e8b402fd31018db63a 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 #include "syscall_nacl.h"
 
@@ -269,7 +270,6 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
        // restore g
        MOVW    20(R13), g
 
-sigtramp_ret:
        // Enable exceptions again.
        NACL_SYSCALL(SYS_exception_clear_flag)
 
@@ -301,7 +301,7 @@ nog:
 TEXT runtime·nacl_sysinfo(SB),NOSPLIT,$16
        RET
 
-TEXT runtime·casp(SB),NOSPLIT,$0
+TEXT runtime·casp1(SB),NOSPLIT,$0
        B       runtime·cas(SB)
 
 // This is only valid for ARMv6+, however, NaCl/ARM is only defined
index 23f2f6bd1474a10f1807bb82333fb46ed315ad8b..509d6d4a85706ae3620a657f453f3ef0db14e5d0 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // Exit the entire program (like C exit)
index eb9766d3f53de2c3d79c5a6c757f27e7092979f9..e26d6066719beb3133c69480ab8de289a3ca8dd5 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // int32 lwp_create(void *context, uintptr flags, void *lwpid)
index 039a0832e067d6b329a4dc5451beee720ca7074e..fa9bc577acbd105d9b638b67461bc3b72d95e285 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // Exit the entire program (like C exit)
@@ -330,7 +331,7 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
        SWI $0xa0005c   // sys_fcntl
        RET
 
-TEXT runtime·casp(SB),NOSPLIT,$0
+TEXT runtime·casp1(SB),NOSPLIT,$0
        B       runtime·cas(SB)
 
 // TODO(minux): this is only valid for ARMv6+
index 5cda7768ae97bd0201514615ea9c113384ac76f6..93907577ea87bdbebb2760ef993f79d797d5f656 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 #define        CLOCK_MONOTONIC $3
@@ -186,7 +187,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
        MOVL    BX, 0(SP)
        MOVL    $runtime·badsignal(SB), AX
        CALL    AX
-       JMP     sigtramp_ret
+       JMP     ret
 
        // save g
        MOVL    DI, 20(SP)
@@ -212,7 +213,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44
        MOVL    20(SP), BX
        MOVL    BX, g(CX)
 
-sigtramp_ret:
+ret:
        // call sigreturn
        MOVL    context+8(FP), AX
        MOVL    $0, 0(SP)               // syscall gap
index 4e9db23908251029a356368efef16fbcc08cab03..9dc0fb6857f15fa566dd0fd7dc5565907bfaa082 100644 (file)
@@ -6,7 +6,8 @@
 // /usr/src/sys/kern/syscalls.master for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 #define CLOCK_MONOTONIC        $3
index a41b56258aa9107aa1d055e41e040674ba89f393..b9db8cbf1a5bf821e8c84fea78fc64ad924d1a68 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // setldt(int entry, int address, int limit)
index 3a96c2bf915b73be9da49b9cd84e8053f0dbbfa3..02c7c8743eb8c54c70f2c1fa1983eee7e0ba1f4b 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // setldt(int entry, int address, int limit)
diff --git a/src/runtime/sys_power64x.go b/src/runtime/sys_power64x.go
new file mode 100644 (file)
index 0000000..90ebde7
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+package runtime
+
+import "unsafe"
+
+// adjust Gobuf as if it executed a call to fn with context ctxt
+// and then did an immediate Gosave.
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+       if buf.lr != 0 {
+               gothrow("invalid use of gostartcall")
+       }
+       buf.lr = buf.pc
+       buf.pc = uintptr(fn)
+       buf.ctxt = ctxt
+}
+
+// Called to rewind context saved during morestack back to beginning of function.
+// To help us, the linker emits a jmp back to the beginning right after the
+// call to morestack. We just have to decode and apply that jump.
+func rewindmorestack(buf *gobuf) {
+       var inst uint32
+       if buf.pc&3 == 0 && buf.pc != 0 {
+               inst = *(*uint32)(unsafe.Pointer(buf.pc))
+               if inst>>26 == 18 && inst&3 == 0 {
+                       //print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(uintptr(buf.pc + int32(inst<<6)>>6)), "\n");
+                       buf.pc += uintptr(int32(inst<<6) >> 6)
+                       return
+               }
+       }
+       print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
+       gothrow("runtime: misuse of rewindmorestack")
+}
index 0ebdab6ee2e5bdfd2243e6ea925eb2286fb957ba..54aeaeaf548fd184fdc475cb820ffabaca6710ff 100644 (file)
@@ -6,14 +6,15 @@
 // /usr/include/sys/syscall.h for syscall numbers.
 //
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // This is needed by asm_amd64.s
 TEXT runtime·settls(SB),NOSPLIT,$8
        RET
 
-// void libc·miniterrno(void *(*___errno)(void));
+// void libc_miniterrno(void *(*___errno)(void));
 //
 // Set the TLS errno pointer in M.
 //
@@ -40,7 +41,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
        SUBQ    $64, SP // 16 bytes will do, but who knows in the future?
        MOVQ    $3, DI  // CLOCK_REALTIME from <sys/time_impl.h>
        MOVQ    SP, SI
-       MOVQ    libc·clock_gettime(SB), AX
+       MOVQ    libc_clock_gettime(SB), AX
        CALL    AX
        MOVQ    (SP), AX        // tv_sec from struct timespec
        IMULQ   $1000000000, AX // multiply into nanoseconds
@@ -53,7 +54,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
 TEXT runtime·pipe1(SB),NOSPLIT,$0
        SUBQ    $16, SP // 8 bytes will do, but stack has to be 16-byte alligned
        MOVQ    SP, DI
-       MOVQ    libc·pipe(SB), AX
+       MOVQ    libc_pipe(SB), AX
        CALL    AX
        MOVL    0(SP), AX
        MOVL    4(SP), DX
@@ -132,7 +133,7 @@ TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
        MOVQ    AX, (g_stack+stack_hi)(DX)
        SUBQ    $(0x100000), AX         // stack size
        MOVQ    AX, (g_stack+stack_lo)(DX)
-       ADDQ    $const_StackGuard, AX
+       ADDQ    $const__StackGuard, AX
        MOVQ    AX, g_stackguard0(DX)
        MOVQ    AX, g_stackguard1(DX)
 
@@ -287,24 +288,24 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
        // Execute call on m->g0.
        get_tls(R15)
        CMPQ    R15, $0
-       JE      usleep1_noswitch
+       JE      noswitch
 
        MOVQ    g(R15), R13
        CMPQ    R13, $0
-       JE      usleep1_noswitch
+       JE      noswitch
        MOVQ    g_m(R13), R13
        CMPQ    R13, $0
-       JE      usleep1_noswitch
+       JE      noswitch
        // TODO(aram): do something about the cpu profiler here.
 
        MOVQ    m_g0(R13), R14
        CMPQ    g(R15), R14
-       JNE     usleep1_switch
+       JNE     switch
        // executing on m->g0 already
        CALL    AX
        RET
 
-usleep1_switch:
+switch:
        // Switch to m->g0 stack and back.
        MOVQ    (g_sched+gobuf_sp)(R14), R14
        MOVQ    SP, -8(R14)
@@ -313,20 +314,20 @@ usleep1_switch:
        MOVQ    0(SP), SP
        RET
 
-usleep1_noswitch:
+noswitch:
        // Not a Go-managed thread. Do not switch stack.
        CALL    AX
        RET
 
 // Runs on OS stack. duration (in Âµs units) is in DI.
 TEXT runtime·usleep2(SB),NOSPLIT,$0
-       MOVQ    libc·usleep(SB), AX
+       MOVQ    libc_usleep(SB), AX
        CALL    AX
        RET
 
 // Runs on OS stack, called from runtime·osyield.
 TEXT runtime·osyield1(SB),NOSPLIT,$0
-       MOVQ    libc·sched_yield(SB), AX
+       MOVQ    libc_sched_yield(SB), AX
        CALL    AX
        RET
 
index 932fe9dd2450c0eee0082d2b109d63080af3965e..c8a830cdf8e36fb6f649acc8e31a335cea5d3fd3 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // void runtime·asmstdcall(void *c);
@@ -43,7 +44,7 @@ TEXT  runtime·badsignal2(SB),NOSPLIT,$24
        // stderr
        MOVL    $-12, 0(SP)
        MOVL    SP, BP
-       CALL    *runtime·GetStdHandle(SB)
+       CALL    *runtime·_GetStdHandle(SB)
        MOVL    BP, SP
 
        MOVL    AX, 0(SP)       // handle
@@ -55,7 +56,7 @@ TEXT  runtime·badsignal2(SB),NOSPLIT,$24
        MOVL    $0, 0(DX)
        MOVL    DX, 12(SP)
        MOVL    $0, 16(SP) // overlapped
-       CALL    *runtime·WriteFile(SB)
+       CALL    *runtime·_WriteFile(SB)
        MOVL    BP, SI
        RET
 
@@ -106,7 +107,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVL    g_m(DX), BX
        MOVL    m_g0(BX), BX
        CMPL    DX, BX
-       JEQ     sigtramp_g0
+       JEQ     g0
 
        // switch to the g0 stack
        get_tls(BP)
@@ -123,7 +124,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVL    SP, 36(DI)
        MOVL    DI, SP
 
-sigtramp_g0:
+g0:
        MOVL    0(CX), BX // ExceptionRecord*
        MOVL    4(CX), CX // Context*
        MOVL    BX, 0(SP)
@@ -207,7 +208,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
        MOVL    BX, g_m(SP)
        LEAL    -8192(SP), CX
        MOVL    CX, (g_stack+stack_lo)(SP)
-       ADDL    $const_StackGuard, CX
+       ADDL    $const__StackGuard, CX
        MOVL    CX, g_stackguard0(SP)
        MOVL    CX, g_stackguard1(SP)
        MOVL    DX, (g_stack+stack_hi)(SP)
@@ -254,8 +255,8 @@ TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0
        MOVL    -4(BX)(AX*4), BX
 
        // extract callback context
-       MOVL    cbctxt_gobody(BX), AX
-       MOVL    cbctxt_argsize(BX), DX
+       MOVL    wincallbackcontext_gobody(BX), AX
+       MOVL    wincallbackcontext_argsize(BX), DX
 
        // preserve whatever's at the memory location that
        // the callback will use to store the return value
@@ -265,7 +266,7 @@ TEXT runtime·callbackasm1+0(SB),NOSPLIT,$0
        ADDL    $4, DX
 
        // remember how to restore stack on return
-       MOVL    cbctxt_restorestack(BX), BX
+       MOVL    wincallbackcontext_restorestack(BX), BX
        PUSHL   BX
 
        // call target Go function
@@ -313,7 +314,7 @@ TEXT runtime·tstart(SB),NOSPLIT,$0
        MOVL    AX, (g_stack+stack_hi)(DX)
        SUBL    $(64*1024), AX          // stack size
        MOVL    AX, (g_stack+stack_lo)(DX)
-       ADDL    $const_StackGuard, AX
+       ADDL    $const__StackGuard, AX
        MOVL    AX, g_stackguard0(DX)
        MOVL    AX, g_stackguard1(DX)
 
@@ -383,12 +384,12 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
 
        MOVL    m_g0(BP), SI
        CMPL    g(CX), SI
-       JNE     usleep1_switch
+       JNE     switch
        // executing on m->g0 already
        CALL    AX
-       JMP     usleep1_ret
+       JMP     ret
 
-usleep1_switch:
+switch:
        // Switch to m->g0 stack and back.
        MOVL    (g_sched+gobuf_sp)(SI), SI
        MOVL    SP, -4(SI)
@@ -396,7 +397,7 @@ usleep1_switch:
        CALL    AX
        MOVL    0(SP), SP
 
-usleep1_ret:
+ret:
        get_tls(CX)
        MOVL    g(CX), BP
        MOVL    g_m(BP), BP
@@ -414,7 +415,7 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20
        MOVL    $0, alertable-16(SP)
        MOVL    $-1, handle-20(SP)
        MOVL    SP, BP
-       MOVL    runtime·NtWaitForSingleObject(SB), AX
+       MOVL    runtime·_NtWaitForSingleObject(SB), AX
        CALL    AX
        MOVL    BP, SP
        RET
index e6190ce684d70e7b4a7bea86e09bc8194178568f..68f7cd3924d62d58441ff507d1fa35e5f20f7fc7 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 // maxargs should be divisible by 2, as Windows stack
@@ -65,7 +66,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48
        // stderr
        MOVQ    $-12, CX // stderr
        MOVQ    CX, 0(SP)
-       MOVQ    runtime·GetStdHandle(SB), AX
+       MOVQ    runtime·_GetStdHandle(SB), AX
        CALL    AX
 
        MOVQ    AX, CX  // handle
@@ -78,7 +79,7 @@ TEXT runtime·badsignal2(SB),NOSPLIT,$48
        MOVQ    $0, 0(R9)
        MOVQ    R9, 24(SP)
        MOVQ    $0, 32(SP)      // overlapped
-       MOVQ    runtime·WriteFile(SB), AX
+       MOVQ    runtime·_WriteFile(SB), AX
        CALL    AX
        
        RET
@@ -138,7 +139,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVQ    g_m(DX), BX
        MOVQ    m_g0(BX), BX
        CMPQ    DX, BX
-       JEQ     sigtramp_g0
+       JEQ     g0
 
        // switch to g0 stack
        get_tls(BP)
@@ -157,7 +158,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0
        MOVQ    SP, 104(DI)
        MOVQ    DI, SP
 
-sigtramp_g0:
+g0:
        MOVQ    0(CX), BX // ExceptionRecord*
        MOVQ    8(CX), CX // Context*
        MOVQ    BX, 0(SP)
@@ -244,7 +245,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
 
        LEAQ    -8192(SP), CX
        MOVQ    CX, (g_stack+stack_lo)(SP)
-       ADDQ    $const_StackGuard, CX
+       ADDQ    $const__StackGuard, CX
        MOVQ    CX, g_stackguard0(SP)
        MOVQ    CX, g_stackguard1(SP)
        MOVQ    DX, (g_stack+stack_hi)(SP)
@@ -293,8 +294,8 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0
        MOVQ    -8(CX)(AX*8), AX
 
        // extract callback context
-       MOVQ    cbctxt_argsize(AX), DX
-       MOVQ    cbctxt_gobody(AX), AX
+       MOVQ    wincallbackcontext_argsize(AX), DX
+       MOVQ    wincallbackcontext_gobody(AX), AX
 
        // preserve whatever's at the memory location that
        // the callback will use to store the return value
@@ -354,7 +355,7 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0
        MOVQ    AX, (g_stack+stack_hi)(DX)
        SUBQ    $(64*1024), AX          // stack size
        MOVQ    AX, (g_stack+stack_lo)(DX)
-       ADDQ    $const_StackGuard, AX
+       ADDQ    $const__StackGuard, AX
        MOVQ    AX, g_stackguard0(DX)
        MOVQ    AX, g_stackguard1(DX)
 
@@ -407,12 +408,12 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0
 
        MOVQ    m_g0(R13), R14
        CMPQ    g(R15), R14
-       JNE     usleep1_switch
+       JNE     switch
        // executing on m->g0 already
        CALL    AX
-       JMP     usleep1_ret
+       JMP     ret
 
-usleep1_switch:
+switch:
        // Switch to m->g0 stack and back.
        MOVQ    (g_sched+gobuf_sp)(R14), R14
        MOVQ    SP, -8(R14)
@@ -420,7 +421,7 @@ usleep1_switch:
        CALL    AX
        MOVQ    0(SP), SP
 
-usleep1_ret:
+ret:
        MOVQ    $0, m_libcallsp(R13)
        RET
 
@@ -435,7 +436,7 @@ TEXT runtime·usleep2(SB),NOSPLIT,$16
        MOVQ    BX, (R8)
        MOVQ    $-1, CX // handle
        MOVQ    $0, DX // alertable
-       MOVQ    runtime·NtWaitForSingleObject(SB), AX
+       MOVQ    runtime·_NtWaitForSingleObject(SB), AX
        CALL    AX
        MOVQ    8(SP), SP
        RET
similarity index 53%
rename from src/runtime/sys_x86.c
rename to src/runtime/sys_x86.go
index a450b3e58443363280950ffcbda63cc537520d5d..086af8ff10f737b472219e3020ed71ce1383f487 100644 (file)
@@ -4,54 +4,51 @@
 
 // +build amd64 amd64p32 386
 
-#include "runtime.h"
+package runtime
+
+import "unsafe"
 
 // adjust Gobuf as it if executed a call to fn with context ctxt
 // and then did an immediate gosave.
-void
-runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt)
-{
-       uintptr *sp;
-       
-       sp = (uintptr*)gobuf->sp;
-       if(sizeof(uintreg) > sizeof(uintptr))
-               *--sp = 0;
-       *--sp = (uintptr)gobuf->pc;
-       gobuf->sp = (uintptr)sp;
-       gobuf->pc = (uintptr)fn;
-       gobuf->ctxt = ctxt;
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+       sp := buf.sp
+       if regSize > ptrSize {
+               sp -= ptrSize
+               *(*uintptr)(unsafe.Pointer(sp)) = 0
+       }
+       sp -= ptrSize
+       *(*uintptr)(unsafe.Pointer(sp)) = buf.pc
+       buf.sp = sp
+       buf.pc = uintptr(fn)
+       buf.ctxt = ctxt
 }
 
 // Called to rewind context saved during morestack back to beginning of function.
 // To help us, the linker emits a jmp back to the beginning right after the
 // call to morestack. We just have to decode and apply that jump.
-void
-runtime·rewindmorestack(Gobuf *gobuf)
-{
-       byte *pc;
-
-       pc = (byte*)gobuf->pc;
-       if(pc[0] == 0xe9) { // jmp 4-byte offset
-               gobuf->pc = gobuf->pc + 5 + *(int32*)(pc+1);
-               return;
+func rewindmorestack(buf *gobuf) {
+       pc := (*[8]byte)(unsafe.Pointer(buf.pc))
+       if pc[0] == 0xe9 { // jmp 4-byte offset
+               buf.pc = buf.pc + 5 + uintptr(int64(*(*int32)(unsafe.Pointer(&pc[1]))))
+               return
        }
-       if(pc[0] == 0xeb) { // jmp 1-byte offset
-               gobuf->pc = gobuf->pc + 2 + *(int8*)(pc+1);
-               return;
+       if pc[0] == 0xeb { // jmp 1-byte offset
+               buf.pc = buf.pc + 2 + uintptr(int64(*(*int8)(unsafe.Pointer(&pc[1]))))
+               return
        }
-       if(pc[0] == 0xcc) {
+       if pc[0] == 0xcc {
                // This is a breakpoint inserted by gdb.  We could use
                // runtime·findfunc to find the function.  But if we
                // do that, then we will continue execution at the
                // function entry point, and we will not hit the gdb
                // breakpoint.  So for this case we don't change
-               // gobuf->pc, so that when we return we will execute
+               // buf.pc, so that when we return we will execute
                // the jump instruction and carry on.  This means that
                // stack unwinding may not work entirely correctly
                // (http://golang.org/issue/5723) but the user is
                // running under gdb anyhow.
-               return;
+               return
        }
-       runtime·printf("runtime: pc=%p %x %x %x %x %x\n", pc, pc[0], pc[1], pc[2], pc[3], pc[4]);
-       runtime·throw("runtime: misuse of rewindmorestack");
+       print("runtime: pc=", pc, " ", hex(pc[0]), " ", hex(pc[1]), " ", hex(pc[2]), " ", hex(pc[3]), " ", hex(pc[4]), "\n")
+       gothrow("runtime: misuse of rewindmorestack")
 }
diff --git a/src/runtime/syscall2_solaris.go b/src/runtime/syscall2_solaris.go
new file mode 100644 (file)
index 0000000..f4ffa74
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import _ "unsafe"
+
+//go:cgo_import_dynamic libc_chdir chdir "libc.so"
+//go:cgo_import_dynamic libc_chroot chroot "libc.so"
+//go:cgo_import_dynamic libc_close close "libc.so"
+//go:cgo_import_dynamic libc_dlclose dlclose "libc.so"
+//go:cgo_import_dynamic libc_dlopen dlopen "libc.so"
+//go:cgo_import_dynamic libc_dlsym dlsym "libc.so"
+//go:cgo_import_dynamic libc_execve execve "libc.so"
+//go:cgo_import_dynamic libc_fcntl fcntl "libc.so"
+//go:cgo_import_dynamic libc_gethostname gethostname "libc.so"
+//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
+//go:cgo_import_dynamic libc_pipe pipe "libc.so"
+//go:cgo_import_dynamic libc_setgid setgid "libc.so"
+//go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
+//go:cgo_import_dynamic libc_setsid setsid "libc.so"
+//go:cgo_import_dynamic libc_setuid setuid "libc.so"
+//go:cgo_import_dynamic libc_setpgid setsid "libc.so"
+//go:cgo_import_dynamic libc_syscall syscall "libc.so"
+//go:cgo_import_dynamic libc_forkx forkx "libc.so"
+//go:cgo_import_dynamic libc_wait4 wait4 "libc.so"
+
+//go:linkname libc_chdir libc_chdir
+//go:linkname libc_chroot libc_chroot
+//go:linkname libc_close libc_close
+//go:linkname libc_dlclose libc_dlclose
+//go:linkname libc_dlopen libc_dlopen
+//go:linkname libc_dlsym libc_dlsym
+//go:linkname libc_execve libc_execve
+//go:linkname libc_fcntl libc_fcntl
+//go:linkname libc_gethostname libc_gethostname
+//go:linkname libc_ioctl libc_ioctl
+//go:linkname libc_pipe libc_pipe
+//go:linkname libc_setgid libc_setgid
+//go:linkname libc_setgroups libc_setgroups
+//go:linkname libc_setsid libc_setsid
+//go:linkname libc_setuid libc_setuid
+//go:linkname libc_setpgid libc_setpgid
+//go:linkname libc_syscall libc_syscall
+//go:linkname libc_forkx libc_forkx
+//go:linkname libc_wait4 libc_wait4
diff --git a/src/runtime/syscall_solaris.c b/src/runtime/syscall_solaris.c
deleted file mode 100644 (file)
index 13ac31b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#pragma dynimport libc·chdir chdir "libc.so"
-#pragma dynimport libc·chroot chroot "libc.so"
-#pragma dynimport libc·close close "libc.so"
-#pragma dynimport libc·dlclose dlclose "libc.so"
-#pragma dynimport libc·dlopen dlopen "libc.so"
-#pragma dynimport libc·dlsym dlsym "libc.so"
-#pragma dynimport libc·execve execve "libc.so"
-#pragma dynimport libc·fcntl fcntl "libc.so"
-#pragma dynimport libc·gethostname gethostname "libc.so"
-#pragma dynimport libc·ioctl ioctl "libc.so"
-#pragma dynimport libc·pipe pipe "libc.so"
-#pragma dynimport libc·setgid setgid "libc.so"
-#pragma dynimport libc·setgroups setgroups "libc.so"
-#pragma dynimport libc·setsid setsid "libc.so"
-#pragma dynimport libc·setuid setuid "libc.so"
-#pragma dynimport libc·setpgid setsid "libc.so"
-#pragma dynimport libc·syscall syscall "libc.so"
-#pragma dynimport libc·forkx forkx "libc.so"
-#pragma dynimport libc·wait4 wait4 "libc.so"
index 50d3a1d36dc0c41ac2d861ce2785d496c78c4cdd..9b9971674797b12a8ac6699350eb68c9849f3520 100644 (file)
@@ -9,12 +9,10 @@ import "unsafe"
 var (
        libc_chdir,
        libc_chroot,
-       libc_close,
        libc_dlopen,
        libc_dlclose,
        libc_dlsym,
        libc_execve,
-       libc_exit,
        libc_fcntl,
        libc_forkx,
        libc_gethostname,
@@ -27,7 +25,6 @@ var (
        libc_setpgid,
        libc_syscall,
        libc_wait4,
-       libc_write,
        pipe1 libcFunc
 )
 
@@ -38,9 +35,9 @@ func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err
                n:    nargs,
                args: uintptr(unsafe.Pointer(&a1)),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        return call.r1, call.r2, call.err
 }
 
@@ -62,7 +59,7 @@ func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, e
 //go:nosplit
 func syscall_chdir(path uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_chdir)),
+               fn:   uintptr(unsafe.Pointer(libc_chdir)),
                n:    1,
                args: uintptr(unsafe.Pointer(&path)),
        }
@@ -73,7 +70,7 @@ func syscall_chdir(path uintptr) (err uintptr) {
 //go:nosplit
 func syscall_chroot(path uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_chroot)),
+               fn:   uintptr(unsafe.Pointer(libc_chroot)),
                n:    1,
                args: uintptr(unsafe.Pointer(&path)),
        }
@@ -84,18 +81,18 @@ func syscall_chroot(path uintptr) (err uintptr) {
 // like close, but must not split stack, for forkx.
 //go:nosplit
 func syscall_close(fd int32) int32 {
-       return int32(sysvicall1(&libc_close, uintptr(fd)))
+       return int32(sysvicall1(libc_close, uintptr(fd)))
 }
 
 func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_dlopen)),
+               fn:   uintptr(unsafe.Pointer(libc_dlopen)),
                n:    2,
                args: uintptr(unsafe.Pointer(&name)),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        if call.r1 == 0 {
                return call.r1, call.err
        }
@@ -104,25 +101,25 @@ func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
 
 func syscall_dlclose(handle uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_dlclose)),
+               fn:   uintptr(unsafe.Pointer(libc_dlclose)),
                n:    1,
                args: uintptr(unsafe.Pointer(&handle)),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        return call.r1
 }
 
 func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_dlsym)),
+               fn:   uintptr(unsafe.Pointer(libc_dlsym)),
                n:    2,
                args: uintptr(unsafe.Pointer(&handle)),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        if call.r1 == 0 {
                return call.r1, call.err
        }
@@ -132,7 +129,7 @@ func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
 //go:nosplit
 func syscall_execve(path, argv, envp uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_execve)),
+               fn:   uintptr(unsafe.Pointer(libc_execve)),
                n:    3,
                args: uintptr(unsafe.Pointer(&path)),
        }
@@ -143,13 +140,13 @@ func syscall_execve(path, argv, envp uintptr) (err uintptr) {
 // like exit, but must not split stack, for forkx.
 //go:nosplit
 func syscall_exit(code uintptr) {
-       sysvicall1(&libc_exit, code)
+       sysvicall1(libc_exit, code)
 }
 
 //go:nosplit
 func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_fcntl)),
+               fn:   uintptr(unsafe.Pointer(libc_fcntl)),
                n:    3,
                args: uintptr(unsafe.Pointer(&fd)),
        }
@@ -160,7 +157,7 @@ func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
 //go:nosplit
 func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_forkx)),
+               fn:   uintptr(unsafe.Pointer(libc_forkx)),
                n:    1,
                args: uintptr(unsafe.Pointer(&flags)),
        }
@@ -172,13 +169,13 @@ func syscall_gethostname() (name string, err uintptr) {
        cname := new([_MAXHOSTNAMELEN]byte)
        var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_gethostname)),
+               fn:   uintptr(unsafe.Pointer(libc_gethostname)),
                n:    2,
                args: uintptr(unsafe.Pointer(&args[0])),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        if call.r1 != 0 {
                return "", call.err
        }
@@ -189,7 +186,7 @@ func syscall_gethostname() (name string, err uintptr) {
 //go:nosplit
 func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_ioctl)),
+               fn:   uintptr(unsafe.Pointer(libc_ioctl)),
                n:    3,
                args: uintptr(unsafe.Pointer(&fd)),
        }
@@ -203,9 +200,9 @@ func syscall_pipe() (r, w, err uintptr) {
                n:    0,
                args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        return call.r1, call.r2, call.err
 }
 
@@ -217,7 +214,7 @@ func syscall_pipe() (r, w, err uintptr) {
 // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
 func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_syscall)),
+               fn:   uintptr(unsafe.Pointer(libc_syscall)),
                n:    4,
                args: uintptr(unsafe.Pointer(&trap)),
        }
@@ -228,7 +225,7 @@ func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
 //go:nosplit
 func syscall_setgid(gid uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_setgid)),
+               fn:   uintptr(unsafe.Pointer(libc_setgid)),
                n:    1,
                args: uintptr(unsafe.Pointer(&gid)),
        }
@@ -239,7 +236,7 @@ func syscall_setgid(gid uintptr) (err uintptr) {
 //go:nosplit
 func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_setgroups)),
+               fn:   uintptr(unsafe.Pointer(libc_setgroups)),
                n:    2,
                args: uintptr(unsafe.Pointer(&ngid)),
        }
@@ -250,9 +247,9 @@ func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
 //go:nosplit
 func syscall_setsid() (pid, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_setsid)),
+               fn:   uintptr(unsafe.Pointer(libc_setsid)),
                n:    0,
-               args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes
+               args: uintptr(unsafe.Pointer(libc_setsid)), // it's unused but must be non-nil, otherwise crashes
        }
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
        return call.r1, call.err
@@ -261,7 +258,7 @@ func syscall_setsid() (pid, err uintptr) {
 //go:nosplit
 func syscall_setuid(uid uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_setuid)),
+               fn:   uintptr(unsafe.Pointer(libc_setuid)),
                n:    1,
                args: uintptr(unsafe.Pointer(&uid)),
        }
@@ -272,7 +269,7 @@ func syscall_setuid(uid uintptr) (err uintptr) {
 //go:nosplit
 func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_setpgid)),
+               fn:   uintptr(unsafe.Pointer(libc_setpgid)),
                n:    2,
                args: uintptr(unsafe.Pointer(&pid)),
        }
@@ -288,32 +285,32 @@ func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
 // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
 func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_syscall)),
+               fn:   uintptr(unsafe.Pointer(libc_syscall)),
                n:    4,
                args: uintptr(unsafe.Pointer(&trap)),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        return call.r1, call.r2, call.err
 }
 
 func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_wait4)),
+               fn:   uintptr(unsafe.Pointer(libc_wait4)),
                n:    4,
                args: uintptr(unsafe.Pointer(&pid)),
        }
-       entersyscallblock()
+       entersyscallblock(0)
        asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-       exitsyscall()
+       exitsyscall(0)
        return int(call.r1), call.err
 }
 
 //go:nosplit
 func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
        call := libcall{
-               fn:   uintptr(unsafe.Pointer(&libc_write)),
+               fn:   uintptr(unsafe.Pointer(libc_write)),
                n:    3,
                args: uintptr(unsafe.Pointer(&fd)),
        }
index efbcab510dad875dc2ee8decd33b96304a5ff43f..661ee59d7b5f419c63fc2a5aa75406def6a2a499 100644 (file)
@@ -41,20 +41,20 @@ func callbackasmAddr(i int) uintptr {
 
 func compileCallback(fn eface, cleanstack bool) (code uintptr) {
        if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
-               panic("compilecallback: not a function")
+               panic("compileCallback: not a function")
        }
        ft := (*functype)(unsafe.Pointer(fn._type))
-       if len(ft.out) != 1 {
-               panic("compilecallback: function must have one output parameter")
+       if ft.out.len != 1 {
+               panic("compileCallback: function must have one output parameter")
        }
        uintptrSize := unsafe.Sizeof(uintptr(0))
-       if t := (**_type)(unsafe.Pointer(&ft.out[0])); (*t).size != uintptrSize {
-               panic("compilecallback: output parameter size is wrong")
+       if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
+               panic("compileCallback: output parameter size is wrong")
        }
        argsize := uintptr(0)
-       for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
+       for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
                if (*t).size > uintptrSize {
-                       panic("compilecallback: input parameter size is wrong")
+                       panic("compileCallback: input parameter size is wrong")
                }
                argsize += uintptrSize
        }
@@ -87,8 +87,6 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
        return callbackasmAddr(n)
 }
 
-func getLoadLibrary() uintptr
-
 //go:nosplit
 func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
        var c libcall
@@ -103,8 +101,6 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
        return
 }
 
-func getGetProcAddress() uintptr
-
 //go:nosplit
 func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
        var c libcall
index 0a0f147c4b45aee91cf3f32bc54d797a61b6c9ce..241dd90afefbc9b18b8ead7b14dee40586e9d455 100644 (file)
@@ -4,12 +4,17 @@
 
 // This file exposes various internal runtime functions to other packages in std lib.
 
-#include "zasm_GOOS_GOARCH.h"
 #include "textflag.h"
 
 #ifdef GOARCH_arm
 #define JMP B
 #endif
+#ifdef GOARCH_power64
+#define JMP BR
+#endif
+#ifdef GOARCH_power64le
+#define JMP BR
+#endif
 
 TEXT net·runtimeNano(SB),NOSPLIT,$0-0
        JMP     runtime·nanotime(SB)
@@ -181,3 +186,18 @@ TEXT syscall·runtime_envs(SB),NOSPLIT,$0-0
 
 TEXT os·runtime_args(SB),NOSPLIT,$0-0
        JMP     runtime·runtime_args(SB)
+
+TEXT sync·runtime_procUnpin(SB),NOSPLIT,$0-0
+       JMP     runtime·sync_procUnpin(SB)
+
+TEXT sync·runtime_procPin(SB),NOSPLIT,$0-0
+       JMP     runtime·sync_procPin(SB)
+
+TEXT syscall·runtime_BeforeFork(SB),NOSPLIT,$0-0
+       JMP     runtime·syscall_BeforeFork(SB)
+
+TEXT syscall·runtime_AfterFork(SB),NOSPLIT,$0-0
+       JMP     runtime·syscall_AfterFork(SB)
+
+TEXT reflect·typelinks(SB),NOSPLIT,$0-0
+       JMP     runtime·typelinks(SB)
diff --git a/src/runtime/thunk_solaris_amd64.s b/src/runtime/thunk_solaris_amd64.s
deleted file mode 100644 (file)
index f61188c..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file exposes various external library functions to Go code in the runtime.
-
-#include "zasm_GOOS_GOARCH.h"
-#include "textflag.h"
-
-TEXT runtime·libc_chdir(SB),NOSPLIT,$0
-       MOVQ    libc·chdir(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_chroot(SB),NOSPLIT,$0
-       MOVQ    libc·chroot(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_close(SB),NOSPLIT,$0
-       MOVQ    libc·close(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_dlopen(SB),NOSPLIT,$0
-       MOVQ    libc·dlopen(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_dlclose(SB),NOSPLIT,$0
-       MOVQ    libc·dlclose(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_dlsym(SB),NOSPLIT,$0
-       MOVQ    libc·dlsym(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_execve(SB),NOSPLIT,$0
-       MOVQ    libc·execve(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_exit(SB),NOSPLIT,$0
-       MOVQ    libc·exit(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_fcntl(SB),NOSPLIT,$0
-       MOVQ    libc·fcntl(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_forkx(SB),NOSPLIT,$0
-       MOVQ    libc·forkx(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_gethostname(SB),NOSPLIT,$0
-       MOVQ    libc·gethostname(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_ioctl(SB),NOSPLIT,$0
-       MOVQ    libc·ioctl(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_setgid(SB),NOSPLIT,$0
-       MOVQ    libc·setgid(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_setgroups(SB),NOSPLIT,$0
-       MOVQ    libc·setgroups(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_setsid(SB),NOSPLIT,$0
-       MOVQ    libc·setsid(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_setuid(SB),NOSPLIT,$0
-       MOVQ    libc·setuid(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_setpgid(SB),NOSPLIT,$0
-       MOVQ    libc·setpgid(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_syscall(SB),NOSPLIT,$0
-       MOVQ    libc·syscall(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_wait4(SB),NOSPLIT,$0
-       MOVQ    libc·wait4(SB), AX
-       JMP     AX
-
-TEXT runtime·libc_write(SB),NOSPLIT,$0
-       MOVQ    libc·write(SB), AX
-       JMP     AX
index 7ccb98fd4dc29396b96164fbd439f141cd8175c8..b1d5d5753b7f6cae6e005406a48c10cec07c158b 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 TEXT syscall·Syscall(SB),NOSPLIT,$0-0
index 85c3940bf2543cfa5f63549269e85690ad8e7ee4..7c5c0e215e2c4ab1c6dff0cf5a3171ee8acc5ff9 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
 
index 1c6ce6e6447947a03c1e0da080465b5f26e3f7ea..e1cc9123f2c6d9b576908f223f36db1ef028b2d5 100644 (file)
@@ -32,15 +32,16 @@ const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386"
 
 var (
        // initialized in tracebackinit
-       deferprocPC uintptr
-       goexitPC    uintptr
-       jmpdeferPC  uintptr
-       mcallPC     uintptr
-       morestackPC uintptr
-       mstartPC    uintptr
-       newprocPC   uintptr
-       rt0_goPC    uintptr
-       sigpanicPC  uintptr
+       deferprocPC          uintptr
+       goexitPC             uintptr
+       jmpdeferPC           uintptr
+       mcallPC              uintptr
+       morestackPC          uintptr
+       mstartPC             uintptr
+       newprocPC            uintptr
+       rt0_goPC             uintptr
+       sigpanicPC           uintptr
+       systemstack_switchPC uintptr
 
        externalthreadhandlerp uintptr // initialized elsewhere
 )
@@ -59,6 +60,7 @@ func tracebackinit() {
        newprocPC = funcPC(newproc)
        rt0_goPC = funcPC(rt0_go)
        sigpanicPC = funcPC(sigpanic)
+       systemstack_switchPC = funcPC(systemstack_switch)
 }
 
 // Traceback over the deferred function calls.
@@ -335,8 +337,7 @@ func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf
                                        print(hex(argp[i]))
                                }
                                print(")\n")
-                               var file string
-                               line := funcline(f, tracepc, &file)
+                               file, line := funcline(f, tracepc)
                                print("\t", file, ":", line)
                                if frame.pc > f.entry {
                                        print(" +", hex(frame.pc-f.entry))
@@ -480,8 +481,7 @@ func printcreatedby(gp *g) {
                if pc > f.entry {
                        tracepc -= _PCQuantum
                }
-               var file string
-               line := funcline(f, tracepc, &file)
+               file, line := funcline(f, tracepc)
                print("\t", file, ":", line)
                if pc > f.entry {
                        print(" +", hex(pc-f.entry))
@@ -528,7 +528,7 @@ func callers(skip int, pcbuf *uintptr, m int) int {
        sp := getcallersp(unsafe.Pointer(&skip))
        pc := uintptr(getcallerpc(unsafe.Pointer(&skip)))
        var n int
-       onM(func() {
+       systemstack(func() {
                n = gentraceback(pc, sp, 0, getg(), skip, pcbuf, m, nil, nil, 0)
        })
        return n
diff --git a/src/runtime/type.go b/src/runtime/type.go
new file mode 100644 (file)
index 0000000..cbd5c9e
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Runtime _type representation.
+
+package runtime
+
+import "unsafe"
+
+// Needs to be in sync with ../../cmd/ld/decodesym.c:/^commonsize and pkg/reflect/type.go:/type.
+type _type struct {
+       size       uintptr
+       hash       uint32
+       _unused    uint8
+       align      uint8
+       fieldalign uint8
+       kind       uint8
+       alg        unsafe.Pointer
+       // gc stores _type info required for garbage collector.
+       // If (kind&KindGCProg)==0, then gc[0] points at sparse GC bitmap
+       // (no indirection), 4 bits per word.
+       // If (kind&KindGCProg)!=0, then gc[1] points to a compiler-generated
+       // read-only GC program; and gc[0] points to BSS space for sparse GC bitmap.
+       // For huge _types (>MaxGCMask), runtime unrolls the program directly into
+       // GC bitmap and gc[0] is not used. For moderately-sized _types, runtime
+       // unrolls the program into gc[0] space on first use. The first byte of gc[0]
+       // (gc[0][0]) contains 'unroll' flag saying whether the program is already
+       // unrolled into gc[0] or not.
+       gc      [2]uintptr
+       _string *string
+       x       *uncommontype
+       ptrto   *_type
+       zero    *byte // ptr to the zero value for this _type
+}
+
+type method struct {
+       name    *string
+       pkgpath *string
+       mtyp    *_type
+       typ     *_type
+       ifn     unsafe.Pointer
+       tfn     unsafe.Pointer
+}
+
+type uncommontype struct {
+       name    *string
+       pkgpath *string
+       mhdr    []method
+       m       [0]method
+}
+
+type imethod struct {
+       name    *string
+       pkgpath *string
+       _type   *_type
+}
+
+type interfacetype struct {
+       typ  _type
+       mhdr []imethod
+       m    [0]imethod
+}
+
+type maptype struct {
+       typ           _type
+       key           *_type
+       elem          *_type
+       bucket        *_type // internal _type representing a hash bucket
+       hmap          *_type // internal _type representing a hmap
+       keysize       uint8  // size of key slot
+       indirectkey   bool   // store ptr to key instead of key itself
+       valuesize     uint8  // size of value slot
+       indirectvalue bool   // store ptr to value instead of value itself
+       bucketsize    uint16 // size of bucket
+}
+
+type chantype struct {
+       typ  _type
+       elem *_type
+       dir  uintptr
+}
+
+type slicetype struct {
+       typ  _type
+       elem *_type
+}
+
+type functype struct {
+       typ       _type
+       dotdotdot bool
+       in        slice
+       out       slice
+}
+
+type ptrtype struct {
+       typ  _type
+       elem *_type
+}
diff --git a/src/runtime/type.h b/src/runtime/type.h
deleted file mode 100644 (file)
index f5b4f9d..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Runtime type representation.
-
-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;
-
-// Needs to be in sync with ../../cmd/ld/decodesym.c:/^commonsize and pkg/reflect/type.go:/type.
-struct Type
-{
-       uintptr size;
-       uint32 hash;
-       uint8 _unused;
-       uint8 align;
-       uint8 fieldAlign;
-       uint8 kind;
-       void* alg;
-       // gc stores type info required for garbage collector.
-       // If (kind&KindGCProg)==0, then gc[0] points at sparse GC bitmap
-       // (no indirection), 4 bits per word.
-       // If (kind&KindGCProg)!=0, then gc[1] points to a compiler-generated
-       // read-only GC program; and gc[0] points to BSS space for sparse GC bitmap.
-       // For huge types (>MaxGCMask), runtime unrolls the program directly into
-       // GC bitmap and gc[0] is not used. For moderately-sized types, runtime
-       // unrolls the program into gc[0] space on first use. The first byte of gc[0]
-       // (gc[0][0]) contains 'unroll' flag saying whether the program is already
-       // unrolled into gc[0] or not.
-       uintptr gc[2];
-       String *string;
-       UncommonType *x;
-       Type *ptrto;
-       byte *zero;  // ptr to the zero value for this type
-};
-
-struct Method
-{
-       String *name;
-       String *pkgPath;
-       Type    *mtyp;
-       Type *typ;
-       void (*ifn)(void);
-       void (*tfn)(void);
-};
-
-struct UncommonType
-{
-       String *name;
-       String *pkgPath;
-       Slice mhdr;
-       Method m[];
-};
-
-struct IMethod
-{
-       String *name;
-       String *pkgPath;
-       Type *type;
-};
-
-struct InterfaceType
-{
-       Type  typ;
-       Slice mhdr;
-       IMethod m[];
-};
-
-struct MapType
-{
-       Type typ;
-       Type *key;
-       Type *elem;
-       Type *bucket;           // internal type representing a hash bucket
-       Type *hmap;             // internal type representing a Hmap
-       uint8 keysize;          // size of key slot
-       bool indirectkey;       // store ptr to key instead of key itself
-       uint8 valuesize;        // size of value slot
-       bool indirectvalue;     // store ptr to value instead of value itself
-       uint16 bucketsize;      // size of bucket
-};
-
-struct ChanType
-{
-       Type typ;
-       Type *elem;
-       uintptr dir;
-};
-
-struct SliceType
-{
-       Type typ;
-       Type *elem;
-};
-
-struct FuncType
-{
-       Type typ;
-       bool dotdotdot;
-       Slice in;
-       Slice out;
-};
-
-struct PtrType
-{
-       Type typ;
-       Type *elem;
-};
index e0fe177bb75a7a7f24806c84f96edced452d3643..39cd45c2e9f8be60488d04fa2e1c4d8ab1ae5c3a 100644 (file)
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Must match runtime and reflect.
+// Included by cmd/gc.
+
 enum {
        KindBool = 1,
        KindInt,
@@ -30,9 +33,8 @@ enum {
        KindStruct,
        KindUnsafePointer,
 
-       KindDirectIface = 1<<5,
-       KindGCProg = 1<<6,      // Type.gc points to GC program
-       KindNoPointers = 1<<7,
-       KindMask = (1<<5)-1,
+       KindDirectIface = 1 << 5,
+       KindGCProg      = 1 << 6, // Type.gc points to GC program
+       KindNoPointers  = 1 << 7,
+       KindMask        = (1 << 5) - 1,
 };
-
diff --git a/src/runtime/typekind1.go b/src/runtime/typekind1.go
new file mode 100644 (file)
index 0000000..73028d6
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+const (
+       _KindBool = 1 + iota
+       _KindInt
+       _KindInt8
+       _KindInt16
+       _KindInt32
+       _KindInt64
+       _KindUint
+       _KindUint8
+       _KindUint16
+       _KindUint32
+       _KindUint64
+       _KindUintptr
+       _KindFloat32
+       _KindFloat64
+       _KindComplex64
+       _KindComplex128
+       _KindArray
+       _KindChan
+       _KindFunc
+       _KindInterface
+       _KindMap
+       _KindPtr
+       _KindSlice
+       _KindString
+       _KindStruct
+       _KindUnsafePointer
+
+       _KindDirectIface = 1 << 5
+       _KindGCProg      = 1 << 6 // Type.gc points to GC program
+       _KindNoPointers  = 1 << 7
+       _KindMask        = (1 << 5) - 1
+)
diff --git a/src/runtime/vdso_linux_amd64.c b/src/runtime/vdso_linux_amd64.c
deleted file mode 100644 (file)
index 681340c..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "textflag.h"
-
-// Look up symbols in the Linux vDSO.
-
-// This code was originally based on the sample Linux vDSO parser at
-// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/vDSO/parse_vdso.c
-
-// This implements the ELF dynamic linking spec at
-// http://sco.com/developers/gabi/latest/ch5.dynamic.html
-
-// The version section is documented at
-// http://refspecs.linuxfoundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/symversion.html
-
-#define AT_RANDOM 25
-#define AT_SYSINFO_EHDR 33
-#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_HASH 4    /* Dynamic symbol hash table */
-#define DT_STRTAB 5  /* Address of string table */
-#define DT_SYMTAB 6  /* Address of symbol table */
-#define DT_VERSYM 0x6ffffff0
-#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_Sym
-{
-       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_Verdef
-{
-       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 Elf64_Ehdr
-{
-       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_Phdr
-{
-       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_Shdr
-{
-       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_Dyn
-{
-       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_Verdaux
-{
-       Elf64_Word vda_name; /* Version or dependency names */
-       Elf64_Word vda_next; /* Offset in bytes to next verdaux entry */
-} Elf64_Verdaux;
-
-typedef struct Elf64_auxv_t
-{
-       uint64 a_type;        /* Entry type */
-       union
-       {
-               uint64 a_val; /* Integer value */
-       } a_un;
-} Elf64_auxv_t;
-
-
-typedef struct symbol_key {
-       byte* name;
-       int32 sym_hash;
-       void** var_ptr;
-} symbol_key;
-
-typedef struct version_key {
-       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 */
-       Elf64_Sym *symtab;
-       const byte *symstrings;
-       Elf64_Word *bucket, *chain;
-       Elf64_Word nbucket, nchain;
-
-       /* Version table */
-       Elf64_Versym *versym;
-       Elf64_Verdef *verdef;
-};
-
-#pragma dataflag NOPTR
-static version_key linux26 = { (byte*)"LINUX_2.6", 0x3ae75f6 };
-
-// initialize with vsyscall fallbacks
-#pragma dataflag NOPTR
-void* runtime·__vdso_time_sym = (void*)0xffffffffff600400ULL;
-#pragma dataflag NOPTR
-void* runtime·__vdso_gettimeofday_sym = (void*)0xffffffffff600000ULL;
-#pragma dataflag NOPTR
-void* runtime·__vdso_clock_gettime_sym = (void*)0;
-
-#pragma dataflag NOPTR
-static symbol_key sym_keys[] = {
-       { (byte*)"__vdso_time", 0xa33c485, &runtime·__vdso_time_sym },
-       { (byte*)"__vdso_gettimeofday", 0x315ca59, &runtime·__vdso_gettimeofday_sym },
-       { (byte*)"__vdso_clock_gettime", 0xd35ec75, &runtime·__vdso_clock_gettime_sym },
-};
-
-static void
-vdso_init_from_sysinfo_ehdr(struct vdso_info *vdso_info, Elf64_Ehdr* hdr)
-{
-       uint64 i;
-       bool found_vaddr = false;
-       Elf64_Phdr *pt;
-       Elf64_Dyn *dyn;
-       Elf64_Word *hash;
-
-       vdso_info->valid = false;
-       vdso_info->load_addr = (uintptr) hdr;
-
-       pt = (Elf64_Phdr*)(vdso_info->load_addr + hdr->e_phoff);
-       dyn = nil;
-
-       // We need two things from the segment table: the load offset
-       // and the dynamic table.
-       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.
-       hash = nil;
-       vdso_info->symstrings = nil;
-       vdso_info->symtab = nil;
-       vdso_info->versym = nil;
-       vdso_info->verdef = nil;
-       for(i=0; dyn[i].d_tag!=DT_NULL; i++) {
-               switch(dyn[i].d_tag) {
-               case DT_STRTAB:
-                       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_HASH:
-                       hash = (Elf64_Word *)
-                         ((uintptr)dyn[i].d_un.d_ptr
-                          + vdso_info->load_offset);
-                       break;
-               case DT_VERSYM:
-                       vdso_info->versym = (Elf64_Versym *)
-                               ((uintptr)dyn[i].d_un.d_ptr
-                                + 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 || hash == nil)
-               return;  // Failed
-
-       if(vdso_info->verdef == nil)
-               vdso_info->versym = 0;
-
-       // Parse the hash table header.
-       vdso_info->nbucket = hash[0];
-       vdso_info->nchain = hash[1];
-       vdso_info->bucket = &hash[2];
-       vdso_info->chain = &hash[vdso_info->nbucket + 2];
-
-       // That's all we need.
-       vdso_info->valid = true;
-}
-
-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 -1; // can not match any version
-}
-
-static void
-vdso_parse_symbols(struct vdso_info *vdso_info, int32 version)
-{
-       int32 i;
-       Elf64_Word chain;
-       Elf64_Sym *sym;
-
-       if(vdso_info->valid == false)
-               return;
-
-       for(i=0; i<nelem(sym_keys); i++) {
-               for(chain = vdso_info->bucket[sym_keys[i].sym_hash % vdso_info->nbucket];
-                       chain != 0; chain = vdso_info->chain[chain]) {
-
-                       sym = &vdso_info->symtab[chain];
-                       if(ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
-                               continue;
-                       if(ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
-                                ELF64_ST_BIND(sym->st_info) != STB_WEAK)
-                               continue;
-                       if(sym->st_shndx == SHN_UNDEF)
-                               continue;
-                       if(runtime·strcmp(sym_keys[i].name, vdso_info->symstrings + sym->st_name) != 0)
-                               continue;
-
-                       // Check symbol version.
-                       if(vdso_info->versym != nil && version != 0
-                               && vdso_info->versym[chain] & 0x7fff != version)
-                               continue;
-
-                       *sym_keys[i].var_ptr = (void *)(vdso_info->load_offset + sym->st_value);
-                       break;
-               }
-       }
-}
-
-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
-                               continue;
-                       }
-                       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));
-                       continue;
-               }
-               if(elf_auxv[i].a_type == AT_RANDOM) {
-                       runtime·startup_random_data = (byte*)elf_auxv[i].a_un.a_val;
-                       runtime·startup_random_data_len = 16;
-                       continue;
-               }
-       }
-}
-
-void (*runtime·sysargs)(int32, uint8**) = runtime·linux_setup_vdso;
diff --git a/src/runtime/vdso_linux_amd64.go b/src/runtime/vdso_linux_amd64.go
new file mode 100644 (file)
index 0000000..7eb6988
--- /dev/null
@@ -0,0 +1,328 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// Look up symbols in the Linux vDSO.
+
+// This code was originally based on the sample Linux vDSO parser at
+// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/vDSO/parse_vdso.c
+
+// This implements the ELF dynamic linking spec at
+// http://sco.com/developers/gabi/latest/ch5.dynamic.html
+
+// The version section is documented at
+// http://refspecs.linuxfoundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/symversion.html
+
+const (
+       _AT_RANDOM       = 25
+       _AT_SYSINFO_EHDR = 33
+       _AT_NULL         = 0 /* End of vector */
+
+       _PT_LOAD    = 1 /* Loadable program segment */
+       _PT_DYNAMIC = 2 /* Dynamic linking information */
+
+       _DT_NULL   = 0 /* Marks end of dynamic section */
+       _DT_HASH   = 4 /* Dynamic symbol hash table */
+       _DT_STRTAB = 5 /* Address of string table */
+       _DT_SYMTAB = 6 /* Address of symbol table */
+       _DT_VERSYM = 0x6ffffff0
+       _DT_VERDEF = 0x6ffffffc
+
+       _VER_FLG_BASE = 0x1 /* Version definition of file itself */
+
+       _SHN_UNDEF = 0 /* Undefined section */
+
+       _SHT_DYNSYM = 11 /* Dynamic linker symbol table */
+
+       _STT_FUNC = 2 /* Symbol is a code object */
+
+       _STB_GLOBAL = 1 /* Global symbol */
+       _STB_WEAK   = 2 /* Weak symbol */
+
+       _EI_NIDENT = 16
+)
+
+/* How to extract and insert information held in the st_info field.  */
+func _ELF64_ST_BIND(val byte) byte { return val >> 4 }
+func _ELF64_ST_TYPE(val byte) byte { return val & 0xf }
+
+type elf64Sym struct {
+       st_name  uint32
+       st_info  byte
+       st_other byte
+       st_shndx uint16
+       st_value uint64
+       st_size  uint64
+}
+
+type elf64Verdef struct {
+       vd_version uint16 /* Version revision */
+       vd_flags   uint16 /* Version information */
+       vd_ndx     uint16 /* Version Index */
+       vd_cnt     uint16 /* Number of associated aux entries */
+       vd_hash    uint32 /* Version name hash value */
+       vd_aux     uint32 /* Offset in bytes to verdaux array */
+       vd_next    uint32 /* Offset in bytes to next verdef entry */
+}
+
+type elf64Ehdr struct {
+       e_ident     [_EI_NIDENT]byte /* Magic number and other info */
+       e_type      uint16           /* Object file type */
+       e_machine   uint16           /* Architecture */
+       e_version   uint32           /* Object file version */
+       e_entry     uint64           /* Entry point virtual address */
+       e_phoff     uint64           /* Program header table file offset */
+       e_shoff     uint64           /* Section header table file offset */
+       e_flags     uint32           /* Processor-specific flags */
+       e_ehsize    uint16           /* ELF header size in bytes */
+       e_phentsize uint16           /* Program header table entry size */
+       e_phnum     uint16           /* Program header table entry count */
+       e_shentsize uint16           /* Section header table entry size */
+       e_shnum     uint16           /* Section header table entry count */
+       e_shstrndx  uint16           /* Section header string table index */
+}
+
+type elf64Phdr struct {
+       p_type   uint32 /* Segment type */
+       p_flags  uint32 /* Segment flags */
+       p_offset uint64 /* Segment file offset */
+       p_vaddr  uint64 /* Segment virtual address */
+       p_paddr  uint64 /* Segment physical address */
+       p_filesz uint64 /* Segment size in file */
+       p_memsz  uint64 /* Segment size in memory */
+       p_align  uint64 /* Segment alignment */
+}
+
+type elf64Shdr struct {
+       sh_name      uint32 /* Section name (string tbl index) */
+       sh_type      uint32 /* Section type */
+       sh_flags     uint64 /* Section flags */
+       sh_addr      uint64 /* Section virtual addr at execution */
+       sh_offset    uint64 /* Section file offset */
+       sh_size      uint64 /* Section size in bytes */
+       sh_link      uint32 /* Link to another section */
+       sh_info      uint32 /* Additional section information */
+       sh_addralign uint64 /* Section alignment */
+       sh_entsize   uint64 /* Entry size if section holds table */
+}
+
+type elf64Dyn struct {
+       d_tag int64  /* Dynamic entry type */
+       d_val uint64 /* Integer value */
+}
+
+type elf64Verdaux struct {
+       vda_name uint32 /* Version or dependency names */
+       vda_next uint32 /* Offset in bytes to next verdaux entry */
+}
+
+type elf64Auxv struct {
+       a_type uint64 /* Entry type */
+       a_val  uint64 /* Integer value */
+}
+
+type symbol_key struct {
+       name     string
+       sym_hash uint32
+       ptr      *uintptr
+}
+
+type version_key struct {
+       version  string
+       ver_hash uint32
+}
+
+type vdso_info struct {
+       valid bool
+
+       /* Load information */
+       load_addr   uintptr
+       load_offset uintptr /* load_addr - recorded vaddr */
+
+       /* Symbol table */
+       symtab     *[1 << 32]elf64Sym
+       symstrings *[1 << 32]byte
+       chain      []uint32
+       bucket     []uint32
+
+       /* Version table */
+       versym *[1 << 32]uint16
+       verdef *elf64Verdef
+}
+
+var linux26 = version_key{"LINUX_2.6", 0x3ae75f6}
+
+var sym_keys = []symbol_key{
+       {"__vdso_time", 0xa33c485, &__vdso_time_sym},
+       {"__vdso_gettimeofday", 0x315ca59, &__vdso_gettimeofday_sym},
+       {"__vdso_clock_gettime", 0xd35ec75, &__vdso_clock_gettime_sym},
+}
+
+// initialize with vsyscall fallbacks
+var (
+       __vdso_time_sym          uintptr = 0xffffffffff600400
+       __vdso_gettimeofday_sym  uintptr = 0xffffffffff600000
+       __vdso_clock_gettime_sym uintptr = 0
+)
+
+func vdso_init_from_sysinfo_ehdr(info *vdso_info, hdr *elf64Ehdr) {
+       info.valid = false
+       info.load_addr = uintptr(unsafe.Pointer(hdr))
+
+       pt := unsafe.Pointer(info.load_addr + uintptr(hdr.e_phoff))
+
+       // We need two things from the segment table: the load offset
+       // and the dynamic table.
+       var found_vaddr bool
+       var dyn *[1 << 20]elf64Dyn
+       for i := uint16(0); i < hdr.e_phnum; i++ {
+               pt := (*elf64Phdr)(add(pt, uintptr(i)*unsafe.Sizeof(elf64Phdr{})))
+               switch pt.p_type {
+               case _PT_LOAD:
+                       if !found_vaddr {
+                               found_vaddr = true
+                               info.load_offset = info.load_addr + uintptr(pt.p_offset-pt.p_vaddr)
+                       }
+
+               case _PT_DYNAMIC:
+                       dyn = (*[1 << 20]elf64Dyn)(unsafe.Pointer(info.load_addr + uintptr(pt.p_offset)))
+               }
+       }
+
+       if !found_vaddr || dyn == nil {
+               return // Failed
+       }
+
+       // Fish out the useful bits of the dynamic table.
+
+       var hash *[1 << 30]uint32
+       hash = nil
+       info.symstrings = nil
+       info.symtab = nil
+       info.versym = nil
+       info.verdef = nil
+       for i := 0; dyn[i].d_tag != _DT_NULL; i++ {
+               dt := &dyn[i]
+               p := info.load_offset + uintptr(dt.d_val)
+               switch dt.d_tag {
+               case _DT_STRTAB:
+                       info.symstrings = (*[1 << 32]byte)(unsafe.Pointer(p))
+               case _DT_SYMTAB:
+                       info.symtab = (*[1 << 32]elf64Sym)(unsafe.Pointer(p))
+               case _DT_HASH:
+                       hash = (*[1 << 30]uint32)(unsafe.Pointer(p))
+               case _DT_VERSYM:
+                       info.versym = (*[1 << 32]uint16)(unsafe.Pointer(p))
+               case _DT_VERDEF:
+                       info.verdef = (*elf64Verdef)(unsafe.Pointer(p))
+               }
+       }
+
+       if info.symstrings == nil || info.symtab == nil || hash == nil {
+               return // Failed
+       }
+
+       if info.verdef == nil {
+               info.versym = nil
+       }
+
+       // Parse the hash table header.
+       nbucket := hash[0]
+       nchain := hash[1]
+       info.bucket = hash[2 : 2+nbucket]
+       info.chain = hash[2+nbucket : 2+nbucket+nchain]
+
+       // That's all we need.
+       info.valid = true
+}
+
+func vdso_find_version(info *vdso_info, ver *version_key) int32 {
+       if !info.valid {
+               return 0
+       }
+
+       def := info.verdef
+       for {
+               if def.vd_flags&_VER_FLG_BASE == 0 {
+                       aux := (*elf64Verdaux)(add(unsafe.Pointer(def), uintptr(def.vd_aux)))
+                       if def.vd_hash == ver.ver_hash && ver.version == gostringnocopy(&info.symstrings[aux.vda_name]) {
+                               return int32(def.vd_ndx & 0x7fff)
+                       }
+               }
+
+               if def.vd_next == 0 {
+                       break
+               }
+               def = (*elf64Verdef)(add(unsafe.Pointer(def), uintptr(def.vd_next)))
+       }
+
+       return -1 // can not match any version
+}
+
+func vdso_parse_symbols(info *vdso_info, version int32) {
+       if !info.valid {
+               return
+       }
+
+       for _, k := range sym_keys {
+               for chain := info.bucket[k.sym_hash%uint32(len(info.bucket))]; chain != 0; chain = info.chain[chain] {
+                       sym := &info.symtab[chain]
+                       typ := _ELF64_ST_TYPE(sym.st_info)
+                       bind := _ELF64_ST_BIND(sym.st_info)
+                       if typ != _STT_FUNC || bind != _STB_GLOBAL && bind != _STB_WEAK || sym.st_shndx == _SHN_UNDEF {
+                               continue
+                       }
+                       if k.name != gostringnocopy(&info.symstrings[sym.st_name]) {
+                               continue
+                       }
+
+                       // Check symbol version.
+                       if info.versym != nil && version != 0 && int32(info.versym[chain]&0x7fff) != version {
+                               continue
+                       }
+
+                       *k.ptr = info.load_offset + uintptr(sym.st_value)
+                       break
+               }
+       }
+}
+
+func sysargs(argc int32, argv **byte) {
+       n := argc + 1
+
+       // skip envp to get to ELF auxiliary vector.
+       for argv_index(argv, n) != nil {
+               n++
+       }
+
+       // skip NULL separator
+       n++
+
+       // now argv+n is auxv
+       auxv := (*[1 << 32]elf64Auxv)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+
+       for i := 0; auxv[i].a_type != _AT_NULL; i++ {
+               av := &auxv[i]
+               switch av.a_type {
+               case _AT_SYSINFO_EHDR:
+                       if av.a_val == 0 {
+                               // Something went wrong
+                               continue
+                       }
+                       var info vdso_info
+                       // TODO(rsc): I don't understand why the compiler thinks info escapes
+                       // when passed to the three functions below.
+                       info1 := (*vdso_info)(noescape(unsafe.Pointer(&info)))
+                       vdso_init_from_sysinfo_ehdr(info1, (*elf64Ehdr)(unsafe.Pointer(uintptr(av.a_val))))
+                       vdso_parse_symbols(info1, vdso_find_version(info1, &linux26))
+
+               case _AT_RANDOM:
+                       startup_random_data = (*byte)(unsafe.Pointer(uintptr(av.a_val)))
+                       startup_random_data_len = 16
+               }
+       }
+}
diff --git a/src/runtime/vdso_none.go b/src/runtime/vdso_none.go
new file mode 100644 (file)
index 0000000..ac6f8cb
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !linux !amd64
+
+package runtime
+
+func sysargs(argc int32, argv **byte) {
+}
index b4b905bb7a483bf8b84b312a87e61adf5460eb54..5354bf911592ff2c250b4ece84216ff7598ce6a5 100644 (file)
@@ -23,7 +23,8 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#include "zasm_GOOS_GOARCH.h"
+#include "go_asm.h"
+#include "go_tls.h"
 #include "textflag.h"
 
 arg=0
@@ -100,7 +101,7 @@ TEXT _sfloat(SB), NOSPLIT, $68-0 // 4 arg + 14*4 saved regs + cpsr + return valu
 // load the signal fault address into LR, and jump
 // to the real sigpanic.
 // This simulates what sighandler does for a memory fault.
-TEXT _sfloatpanic(SB),NOSPLIT,$-4
+TEXT runtime·_sfloatpanic(SB),NOSPLIT,$-4
        MOVW    $0, R0
        MOVW.W  R0, -4(R13)
        MOVW    g_sigpc(g), LR
diff --git a/src/runtime/vlrt.c b/src/runtime/vlrt.c
deleted file mode 100644 (file)
index cb0d147..0000000
+++ /dev/null
@@ -1,914 +0,0 @@
-// Inferno's libkern/vlrt-386.c
-// http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-386.c
-//
-//         Copyright Â© 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//         Revisions Copyright Â© 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved.
-//         Portions Copyright 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// +build arm 386
-
-#include "textflag.h"
-
-/*
- * C runtime for 64-bit divide, others.
- *
- * TODO(rsc): The simple functions are dregs--8c knows how
- * to generate the code directly now.  Find and remove.
- */
-
-void   runtime·panicdivide(void);
-
-typedef        unsigned long   ulong;
-typedef        unsigned int    uint;
-typedef        unsigned short  ushort;
-typedef        unsigned char   uchar;
-typedef        signed char     schar;
-
-#define        SIGN(n) (1UL<<(n-1))
-
-typedef        struct  Vlong   Vlong;
-struct Vlong
-{
-       ulong   lo;
-       ulong   hi;
-};
-
-typedef        union   Vlong64 Vlong64;
-union  Vlong64
-{
-       long long       v;
-       Vlong   v2;
-};
-
-void   runtime·abort(void);
-
-#pragma textflag NOSPLIT
-Vlong
-_addv(Vlong a, Vlong b)
-{
-       Vlong r;
-
-       r.lo = a.lo + b.lo;
-       r.hi = a.hi + b.hi;
-       if(r.lo < a.lo)
-               r.hi++;
-       return r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_subv(Vlong a, Vlong b)
-{
-       Vlong r;
-
-       r.lo = a.lo - b.lo;
-       r.hi = a.hi - b.hi;
-       if(r.lo > a.lo)
-               r.hi--;
-       return r;
-}
-
-Vlong
-_d2v(double d)
-{
-       union { double d; Vlong vl; } x;
-       ulong xhi, xlo, ylo, yhi;
-       int sh;
-       Vlong y;
-
-       x.d = d;
-
-       xhi = (x.vl.hi & 0xfffff) | 0x100000;
-       xlo = x.vl.lo;
-       sh = 1075 - ((x.vl.hi >> 20) & 0x7ff);
-
-       ylo = 0;
-       yhi = 0;
-       if(sh >= 0) {
-               /* v = (hi||lo) >> sh */
-               if(sh < 32) {
-                       if(sh == 0) {
-                               ylo = xlo;
-                               yhi = xhi;
-                       } else {
-                               ylo = (xlo >> sh) | (xhi << (32-sh));
-                               yhi = xhi >> sh;
-                       }
-               } else {
-                       if(sh == 32) {
-                               ylo = xhi;
-                       } else
-                       if(sh < 64) {
-                               ylo = xhi >> (sh-32);
-                       }
-               }
-       } else {
-               /* v = (hi||lo) << -sh */
-               sh = -sh;
-               if(sh <= 10) { /* NOTE: sh <= 11 on ARM??? */
-                       ylo = xlo << sh;
-                       yhi = (xhi << sh) | (xlo >> (32-sh));
-               } else {
-                       /* overflow */
-                       yhi = d;        /* causes something awful */
-               }
-       }
-       if(x.vl.hi & SIGN(32)) {
-               if(ylo != 0) {
-                       ylo = -ylo;
-                       yhi = ~yhi;
-               } else
-                       yhi = -yhi;
-       }
-
-       y.hi = yhi;
-       y.lo = ylo;
-       return y;
-}
-
-Vlong
-_f2v(float f)
-{
-       return _d2v(f);
-}
-
-double
-_ul2d(ulong u)
-{
-       // compensate for bug in c
-       if(u & SIGN(32)) {
-               u ^= SIGN(32);
-               return 2147483648. + u;
-       }
-       return u;
-}
-
-double
-_v2d(Vlong x)
-{
-       if(x.hi & SIGN(32)) {
-               if(x.lo) {
-                       x.lo = -x.lo;
-                       x.hi = ~x.hi;
-               } else
-                       x.hi = -x.hi;
-               return -(_ul2d(x.hi)*4294967296. + _ul2d(x.lo));
-       }
-       return (long)x.hi*4294967296. + x.lo;
-}
-
-float
-_v2f(Vlong x)
-{
-       return _v2d(x);
-}
-
-ulong  runtime·_div64by32(Vlong, ulong, ulong*);
-int    runtime·_mul64by32(Vlong*, Vlong, ulong);
-
-static void
-slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
-{
-       ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
-       int i;
-
-       numhi = num.hi;
-       numlo = num.lo;
-       denhi = den.hi;
-       denlo = den.lo;
-
-       /*
-        * get a divide by zero
-        */
-       if(denlo==0 && denhi==0) {
-               runtime·panicdivide();
-       }
-
-       /*
-        * set up the divisor and find the number of iterations needed
-        */
-       if(numhi >= SIGN(32)) {
-               quohi = SIGN(32);
-               quolo = 0;
-       } else {
-               quohi = numhi;
-               quolo = numlo;
-       }
-       i = 0;
-       while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
-               denhi = (denhi<<1) | (denlo>>31);
-               denlo <<= 1;
-               i++;
-       }
-
-       quohi = 0;
-       quolo = 0;
-       for(; i >= 0; i--) {
-               quohi = (quohi<<1) | (quolo>>31);
-               quolo <<= 1;
-               if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
-                       t = numlo;
-                       numlo -= denlo;
-                       if(numlo > t)
-                               numhi--;
-                       numhi -= denhi;
-                       quolo |= 1;
-               }
-               denlo = (denlo>>1) | (denhi<<31);
-               denhi >>= 1;
-       }
-
-       if(q) {
-               q->lo = quolo;
-               q->hi = quohi;
-       }
-       if(r) {
-               r->lo = numlo;
-               r->hi = numhi;
-       }
-}
-
-#ifdef GOARCH_arm
-static void
-dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
-{
-       slowdodiv(num, den, qp, rp);
-}
-#endif
-
-#ifdef GOARCH_386
-static void
-dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
-{
-       ulong n;
-       Vlong x, q, r;
-       
-       if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){
-               if(qp) {
-                       qp->hi = 0;
-                       qp->lo = 0;
-               }
-               if(rp) {
-                       rp->hi = num.hi;
-                       rp->lo = num.lo;
-               }
-               return;
-       }
-
-       if(den.hi != 0){
-               q.hi = 0;
-               n = num.hi/den.hi;
-               if(runtime·_mul64by32(&x, den, n) || x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
-                       slowdodiv(num, den, &q, &r);
-               else {
-                       q.lo = n;
-                       *(long long*)&r = *(long long*)&num - *(long long*)&x;
-               }
-       } else {
-               if(num.hi >= den.lo){
-                       if(den.lo == 0)
-                               runtime·panicdivide();
-                       q.hi = n = num.hi/den.lo;
-                       num.hi -= den.lo*n;
-               } else {
-                       q.hi = 0;
-               }
-               q.lo = runtime·_div64by32(num, den.lo, &r.lo);
-               r.hi = 0;
-       }
-       if(qp) {
-               qp->lo = q.lo;
-               qp->hi = q.hi;
-       }
-       if(rp) {
-               rp->lo = r.lo;
-               rp->hi = r.hi;
-       }
-}
-#endif
-
-Vlong
-_divvu(Vlong n, Vlong d)
-{
-       Vlong q;
-
-       if(n.hi == 0 && d.hi == 0) {
-               if(d.lo == 0)
-                       runtime·panicdivide();
-               q.hi = 0;
-               q.lo = n.lo / d.lo;
-               return q;
-       }
-       dodiv(n, d, &q, 0);
-       return q;
-}
-
-Vlong
-_modvu(Vlong n, Vlong d)
-{
-       Vlong r;
-
-       if(n.hi == 0 && d.hi == 0) {
-               if(d.lo == 0)
-                       runtime·panicdivide();
-               r.hi = 0;
-               r.lo = n.lo % d.lo;
-               return r;
-       }
-       dodiv(n, d, 0, &r);
-       return r;
-}
-
-static void
-vneg(Vlong *v)
-{
-
-       if(v->lo == 0) {
-               v->hi = -v->hi;
-               return;
-       }
-       v->lo = -v->lo;
-       v->hi = ~v->hi;
-}
-
-Vlong
-_divv(Vlong n, Vlong d)
-{
-       long nneg, dneg;
-       Vlong q;
-
-       if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
-               if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
-                       // special case: 32-bit -0x80000000 / -1 causes divide error,
-                       // but it's okay in this 64-bit context.
-                       q.lo = 0x80000000;
-                       q.hi = 0;
-                       return q;
-               }
-               if(d.lo == 0)
-                       runtime·panicdivide();
-               q.lo = (long)n.lo / (long)d.lo;
-               q.hi = ((long)q.lo) >> 31;
-               return q;
-       }
-       nneg = n.hi >> 31;
-       if(nneg)
-               vneg(&n);
-       dneg = d.hi >> 31;
-       if(dneg)
-               vneg(&d);
-       dodiv(n, d, &q, 0);
-       if(nneg != dneg)
-               vneg(&q);
-       return q;
-}
-
-Vlong
-_modv(Vlong n, Vlong d)
-{
-       long nneg, dneg;
-       Vlong r;
-
-       if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
-               if((long)n.lo == -0x80000000 && (long)d.lo == -1) {
-                       // special case: 32-bit -0x80000000 % -1 causes divide error,
-                       // but it's okay in this 64-bit context.
-                       r.lo = 0;
-                       r.hi = 0;
-                       return r;
-               }
-               if(d.lo == 0)
-                       runtime·panicdivide();
-               r.lo = (long)n.lo % (long)d.lo;
-               r.hi = ((long)r.lo) >> 31;
-               return r;
-       }
-       nneg = n.hi >> 31;
-       if(nneg)
-               vneg(&n);
-       dneg = d.hi >> 31;
-       if(dneg)
-               vneg(&d);
-       dodiv(n, d, 0, &r);
-       if(nneg)
-               vneg(&r);
-       return r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_rshav(Vlong a, int b)
-{
-       long t;
-       Vlong r;
-
-       t = a.hi;
-       if(b >= 32) {
-               r.hi = t>>31;
-               if(b >= 64) {
-                       /* this is illegal re C standard */
-                       r.lo = t>>31;
-                       return r;
-               }
-               r.lo = t >> (b-32);
-               return r;
-       }
-       if(b <= 0) {
-               r.hi = t;
-               r.lo = a.lo;
-               return r;
-       }
-       r.hi = t >> b;
-       r.lo = (t << (32-b)) | (a.lo >> b);
-       return r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_rshlv(Vlong a, int b)
-{
-       ulong t;
-       Vlong r;
-
-       t = a.hi;
-       if(b >= 32) {
-               r.hi = 0;
-               if(b >= 64) {
-                       /* this is illegal re C standard */
-                       r.lo = 0;
-                       return r;
-               }
-               r.lo = t >> (b-32);
-               return r;
-       }
-       if(b <= 0) {
-               r.hi = t;
-               r.lo = a.lo;
-               return r;
-       }
-       r.hi = t >> b;
-       r.lo = (t << (32-b)) | (a.lo >> b);
-       return r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_lshv(Vlong a, int b)
-{
-       ulong t;
-
-       t = a.lo;
-       if(b >= 32) {
-               if(b >= 64) {
-                       /* this is illegal re C standard */
-                       return (Vlong){0, 0};
-               }
-               return (Vlong){0, t<<(b-32)};
-       }
-       if(b <= 0) {
-               return (Vlong){t, a.hi};
-       }
-       return (Vlong){t<<b, (t >> (32-b)) | (a.hi << b)};
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_andv(Vlong a, Vlong b)
-{
-       Vlong r;
-
-       r.hi = a.hi & b.hi;
-       r.lo = a.lo & b.lo;
-       return r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_orv(Vlong a, Vlong b)
-{
-       Vlong r;
-
-       r.hi = a.hi | b.hi;
-       r.lo = a.lo | b.lo;
-       return r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_xorv(Vlong a, Vlong b)
-{
-       Vlong r;
-
-       r.hi = a.hi ^ b.hi;
-       r.lo = a.lo ^ b.lo;
-       return r;
-}
-
-Vlong
-_vpp(Vlong *r)
-{
-       Vlong l;
-
-       l = *r;
-       r->lo++;
-       if(r->lo == 0)
-               r->hi++;
-       return l;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_vmm(Vlong *r)
-{
-       Vlong l;
-
-       l = *r;
-       if(r->lo == 0)
-               r->hi--;
-       r->lo--;
-       return l;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_ppv(Vlong *r)
-{
-
-       r->lo++;
-       if(r->lo == 0)
-               r->hi++;
-       return *r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_mmv(Vlong *r)
-{
-
-       if(r->lo == 0)
-               r->hi--;
-       r->lo--;
-       return *r;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_vasop(void *lv, Vlong fn(Vlong, Vlong), int type, Vlong rv)
-{
-       Vlong t, u;
-
-       u.lo = 0;
-       u.hi = 0;
-       switch(type) {
-       default:
-               runtime·abort();
-               break;
-
-       case 1: /* schar */
-               t.lo = *(schar*)lv;
-               t.hi = t.lo >> 31;
-               u = fn(t, rv);
-               *(schar*)lv = u.lo;
-               break;
-
-       case 2: /* uchar */
-               t.lo = *(uchar*)lv;
-               t.hi = 0;
-               u = fn(t, rv);
-               *(uchar*)lv = u.lo;
-               break;
-
-       case 3: /* short */
-               t.lo = *(short*)lv;
-               t.hi = t.lo >> 31;
-               u = fn(t, rv);
-               *(short*)lv = u.lo;
-               break;
-
-       case 4: /* ushort */
-               t.lo = *(ushort*)lv;
-               t.hi = 0;
-               u = fn(t, rv);
-               *(ushort*)lv = u.lo;
-               break;
-
-       case 9: /* int */
-               t.lo = *(int*)lv;
-               t.hi = t.lo >> 31;
-               u = fn(t, rv);
-               *(int*)lv = u.lo;
-               break;
-
-       case 10:        /* uint */
-               t.lo = *(uint*)lv;
-               t.hi = 0;
-               u = fn(t, rv);
-               *(uint*)lv = u.lo;
-               break;
-
-       case 5: /* long */
-               t.lo = *(long*)lv;
-               t.hi = t.lo >> 31;
-               u = fn(t, rv);
-               *(long*)lv = u.lo;
-               break;
-
-       case 6: /* ulong */
-               t.lo = *(ulong*)lv;
-               t.hi = 0;
-               u = fn(t, rv);
-               *(ulong*)lv = u.lo;
-               break;
-
-       case 7: /* vlong */
-       case 8: /* uvlong */
-               if((void*)fn == _lshv || (void*)fn == _rshav || (void*)fn == _rshlv)
-                       u = ((Vlong(*)(Vlong,int))fn)(*(Vlong*)lv, *(int*)&rv);
-               else
-                       u = fn(*(Vlong*)lv, rv);
-               *(Vlong*)lv = u;
-               break;
-       }
-       return u;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_p2v(void *p)
-{
-       long t;
-       Vlong ret;
-
-       t = (ulong)p;
-       ret.lo = t;
-       ret.hi = 0;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_sl2v(long sl)
-{
-       long t;
-       Vlong ret;
-
-       t = sl;
-       ret.lo = t;
-       ret.hi = t >> 31;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_ul2v(ulong ul)
-{
-       long t;
-       Vlong ret;
-
-       t = ul;
-       ret.lo = t;
-       ret.hi = 0;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_si2v(int si)
-{
-       return (Vlong){si, si>>31};
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_ui2v(uint ui)
-{
-       long t;
-       Vlong ret;
-
-       t = ui;
-       ret.lo = t;
-       ret.hi = 0;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_sh2v(long sh)
-{
-       long t;
-       Vlong ret;
-
-       t = (sh << 16) >> 16;
-       ret.lo = t;
-       ret.hi = t >> 31;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_uh2v(ulong ul)
-{
-       long t;
-       Vlong ret;
-
-       t = ul & 0xffff;
-       ret.lo = t;
-       ret.hi = 0;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_sc2v(long uc)
-{
-       long t;
-       Vlong ret;
-
-       t = (uc << 24) >> 24;
-       ret.lo = t;
-       ret.hi = t >> 31;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-Vlong
-_uc2v(ulong ul)
-{
-       long t;
-       Vlong ret;
-
-       t = ul & 0xff;
-       ret.lo = t;
-       ret.hi = 0;
-       return ret;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2sc(Vlong rv)
-{
-       long t;
-
-       t = rv.lo & 0xff;
-       return (t << 24) >> 24;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2uc(Vlong rv)
-{
-
-       return rv.lo & 0xff;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2sh(Vlong rv)
-{
-       long t;
-
-       t = rv.lo & 0xffff;
-       return (t << 16) >> 16;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2uh(Vlong rv)
-{
-
-       return rv.lo & 0xffff;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2sl(Vlong rv)
-{
-
-       return rv.lo;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2ul(Vlong rv)
-{
-
-       return rv.lo;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2si(Vlong rv)
-{
-       return rv.lo;
-}
-
-#pragma textflag NOSPLIT
-long
-_v2ui(Vlong rv)
-{
-
-       return rv.lo;
-}
-
-#pragma textflag NOSPLIT
-int
-_testv(Vlong rv)
-{
-       return rv.lo || rv.hi;
-}
-
-#pragma textflag NOSPLIT
-int
-_eqv(Vlong lv, Vlong rv)
-{
-       return lv.lo == rv.lo && lv.hi == rv.hi;
-}
-
-#pragma textflag NOSPLIT
-int
-_nev(Vlong lv, Vlong rv)
-{
-       return lv.lo != rv.lo || lv.hi != rv.hi;
-}
-
-#pragma textflag NOSPLIT
-int
-_ltv(Vlong lv, Vlong rv)
-{
-       return (long)lv.hi < (long)rv.hi ||
-               (lv.hi == rv.hi && lv.lo < rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_lev(Vlong lv, Vlong rv)
-{
-       return (long)lv.hi < (long)rv.hi ||
-               (lv.hi == rv.hi && lv.lo <= rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_gtv(Vlong lv, Vlong rv)
-{
-       return (long)lv.hi > (long)rv.hi ||
-               (lv.hi == rv.hi && lv.lo > rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_gev(Vlong lv, Vlong rv)
-{
-       return (long)lv.hi > (long)rv.hi ||
-               (lv.hi == rv.hi && lv.lo >= rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_lov(Vlong lv, Vlong rv)
-{
-       return lv.hi < rv.hi ||
-               (lv.hi == rv.hi && lv.lo < rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_lsv(Vlong lv, Vlong rv)
-{
-       return lv.hi < rv.hi ||
-               (lv.hi == rv.hi && lv.lo <= rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_hiv(Vlong lv, Vlong rv)
-{
-       return lv.hi > rv.hi ||
-               (lv.hi == rv.hi && lv.lo > rv.lo);
-}
-
-#pragma textflag NOSPLIT
-int
-_hsv(Vlong lv, Vlong rv)
-{
-       return lv.hi > rv.hi ||
-               (lv.hi == rv.hi && lv.lo >= rv.lo);
-}
diff --git a/src/runtime/zgoarch_386.go b/src/runtime/zgoarch_386.go
new file mode 100644 (file)
index 0000000..057a746
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `386`
+
+const goarch_386 = 1
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_amd64.go b/src/runtime/zgoarch_amd64.go
new file mode 100644 (file)
index 0000000..a712407
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `amd64`
+
+const goarch_386 = 0
+const goarch_amd64 = 1
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_amd64p32.go b/src/runtime/zgoarch_amd64p32.go
new file mode 100644 (file)
index 0000000..2b6a142
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `amd64p32`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 1
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_arm.go b/src/runtime/zgoarch_arm.go
new file mode 100644 (file)
index 0000000..4030210
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `arm`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 1
+const goarch_power64 = 0
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_power64.go b/src/runtime/zgoarch_power64.go
new file mode 100644 (file)
index 0000000..cc361f0
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `power64`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 1
+const goarch_power64le = 0
diff --git a/src/runtime/zgoarch_power64le.go b/src/runtime/zgoarch_power64le.go
new file mode 100644 (file)
index 0000000..41294e6
--- /dev/null
@@ -0,0 +1,12 @@
+// generated by gengoos.go using 'go generate'
+
+package runtime
+
+const theGoarch = `power64le`
+
+const goarch_386 = 0
+const goarch_amd64 = 0
+const goarch_amd64p32 = 0
+const goarch_arm = 0
+const goarch_power64 = 0
+const goarch_power64le = 1
diff --git a/src/runtime/zgoos_android.go b/src/runtime/zgoos_android.go
new file mode 100644 (file)
index 0000000..abfba80
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build android
+
+package runtime
+
+const theGoos = `android`
+
+const goos_android = 1
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_darwin.go b/src/runtime/zgoos_darwin.go
new file mode 100644 (file)
index 0000000..eb39b53
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build darwin
+
+package runtime
+
+const theGoos = `darwin`
+
+const goos_android = 0
+const goos_darwin = 1
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_dragonfly.go b/src/runtime/zgoos_dragonfly.go
new file mode 100644 (file)
index 0000000..f6e839d
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build dragonfly
+
+package runtime
+
+const theGoos = `dragonfly`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 1
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_freebsd.go b/src/runtime/zgoos_freebsd.go
new file mode 100644 (file)
index 0000000..3c47aef
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build freebsd
+
+package runtime
+
+const theGoos = `freebsd`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 1
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_linux.go b/src/runtime/zgoos_linux.go
new file mode 100644 (file)
index 0000000..5d899e3
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build linux
+
+package runtime
+
+const theGoos = `linux`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 1
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_nacl.go b/src/runtime/zgoos_nacl.go
new file mode 100644 (file)
index 0000000..b5c4281
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build nacl
+
+package runtime
+
+const theGoos = `nacl`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 1
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_netbsd.go b/src/runtime/zgoos_netbsd.go
new file mode 100644 (file)
index 0000000..b2e4522
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build netbsd
+
+package runtime
+
+const theGoos = `netbsd`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 1
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_openbsd.go b/src/runtime/zgoos_openbsd.go
new file mode 100644 (file)
index 0000000..331c96d
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build openbsd
+
+package runtime
+
+const theGoos = `openbsd`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 1
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_plan9.go b/src/runtime/zgoos_plan9.go
new file mode 100644 (file)
index 0000000..f29eb45
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build plan9
+
+package runtime
+
+const theGoos = `plan9`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 1
+const goos_solaris = 0
+const goos_windows = 0
diff --git a/src/runtime/zgoos_solaris.go b/src/runtime/zgoos_solaris.go
new file mode 100644 (file)
index 0000000..ac613db
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build solaris
+
+package runtime
+
+const theGoos = `solaris`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 1
+const goos_windows = 0
diff --git a/src/runtime/zgoos_windows.go b/src/runtime/zgoos_windows.go
new file mode 100644 (file)
index 0000000..43710d8
--- /dev/null
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build windows
+
+package runtime
+
+const theGoos = `windows`
+
+const goos_android = 0
+const goos_darwin = 0
+const goos_dragonfly = 0
+const goos_freebsd = 0
+const goos_linux = 0
+const goos_nacl = 0
+const goos_netbsd = 0
+const goos_openbsd = 0
+const goos_plan9 = 0
+const goos_solaris = 0
+const goos_windows = 1
diff --git a/src/sync/atomic/asm_power64x.s b/src/sync/atomic/asm_power64x.s
new file mode 100644 (file)
index 0000000..1130d3c
--- /dev/null
@@ -0,0 +1,184 @@
+// Copyright 2014 The Go 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 power64 power64le
+
+#include "textflag.h"
+
+TEXT Â·SwapInt32(SB),NOSPLIT,$0-20
+       BR      Â·SwapUint32(SB)
+
+TEXT Â·SwapUint32(SB),NOSPLIT,$0-20
+       MOVD    addr+0(FP), R3
+       MOVW    new+8(FP), R4
+       SYNC
+       LWAR    (R3), R5
+       STWCCC  R4, (R3)
+       BNE     -3(PC)
+       SYNC
+       ISYNC
+       MOVW    R5, old+16(FP)
+       RETURN
+
+TEXT Â·SwapInt64(SB),NOSPLIT,$0-24
+       BR      Â·SwapUint64(SB)
+
+TEXT Â·SwapUint64(SB),NOSPLIT,$0-24
+       MOVD    addr+0(FP), R3
+       MOVD    new+8(FP), R4
+       SYNC
+       LDAR    (R3), R5
+       STDCCC  R4, (R3)
+       BNE     -3(PC)
+       SYNC
+       ISYNC
+       MOVD    R5, old+16(FP)
+       RETURN
+
+TEXT Â·SwapUintptr(SB),NOSPLIT,$0-24
+       BR      Â·SwapUint64(SB)
+
+TEXT Â·SwapPointer(SB),NOSPLIT,$0-24
+       BR      Â·SwapUint64(SB)
+
+TEXT Â·CompareAndSwapInt32(SB),NOSPLIT,$0-17
+       BR      Â·CompareAndSwapUint32(SB)
+
+TEXT Â·CompareAndSwapUint32(SB),NOSPLIT,$0-17
+       MOVD    addr+0(FP), R3
+       MOVW    old+8(FP), R4
+       MOVW    new+12(FP), R5
+       SYNC
+       LWAR    (R3), R6
+       CMPW    R6, R4
+       BNE     8(PC)
+       STWCCC  R5, (R3)
+       BNE     -5(PC)
+       SYNC
+       ISYNC
+       MOVD    $1, R3
+       MOVB    R3, swapped+16(FP)
+       RETURN
+       MOVB    R0, swapped+16(FP)
+       RETURN
+
+TEXT Â·CompareAndSwapUintptr(SB),NOSPLIT,$0-25
+       BR      Â·CompareAndSwapUint64(SB)
+
+TEXT Â·CompareAndSwapPointer(SB),NOSPLIT,$0-25
+       BR      Â·CompareAndSwapUint64(SB)
+
+TEXT Â·CompareAndSwapInt64(SB),NOSPLIT,$0-25
+       BR      Â·CompareAndSwapUint64(SB)
+
+TEXT Â·CompareAndSwapUint64(SB),NOSPLIT,$0-25
+       MOVD    addr+0(FP), R3
+       MOVD    old+8(FP), R4
+       MOVD    new+16(FP), R5
+       SYNC
+       LDAR    (R3), R6
+       CMP     R6, R4
+       BNE     8(PC)
+       STDCCC  R5, (R3)
+       BNE     -5(PC)
+       SYNC
+       ISYNC
+       MOVD    $1, R3
+       MOVB    R3, swapped+24(FP)
+       RETURN
+       MOVB    R0, swapped+24(FP)
+       RETURN
+
+TEXT Â·AddInt32(SB),NOSPLIT,$0-20
+       BR      Â·AddUint32(SB)
+
+TEXT Â·AddUint32(SB),NOSPLIT,$0-20
+       MOVD    addr+0(FP), R3
+       MOVW    delta+8(FP), R4
+       SYNC
+       LWAR    (R3), R5
+       ADD     R4, R5
+       STWCCC  R5, (R3)
+       BNE     -4(PC)
+       SYNC
+       ISYNC
+       MOVW    R5, ret+16(FP)
+       RETURN
+
+TEXT Â·AddUintptr(SB),NOSPLIT,$0-24
+       BR      Â·AddUint64(SB)
+
+TEXT Â·AddInt64(SB),NOSPLIT,$0-24
+       BR      Â·AddUint64(SB)
+
+TEXT Â·AddUint64(SB),NOSPLIT,$0-24
+       MOVD    addr+0(FP), R3
+       MOVD    delta+8(FP), R4
+       SYNC
+       LDAR    (R3), R5
+       ADD     R4, R5
+       STDCCC  R5, (R3)
+       BNE     -4(PC)
+       SYNC
+       ISYNC
+       MOVD    R5, ret+16(FP)
+       RETURN
+
+TEXT Â·LoadInt32(SB),NOSPLIT,$0-12
+       BR      Â·LoadUint32(SB)
+
+TEXT Â·LoadUint32(SB),NOSPLIT,$0-12
+       MOVD    addr+0(FP), R3
+       SYNC
+       MOVW    0(R3), R3
+       CMPW    R3, R3, CR7
+       BC      4, 30, 1(PC)    // bne- cr7,0x4
+       ISYNC
+       MOVW    R3, val+8(FP)
+       RETURN
+
+TEXT Â·LoadInt64(SB),NOSPLIT,$0-16
+       BR      Â·LoadUint64(SB)
+
+TEXT Â·LoadUint64(SB),NOSPLIT,$0-16
+       MOVD    addr+0(FP), R3
+       SYNC
+       MOVD    0(R3), R3
+       CMP     R3, R3, CR7
+       BC      4, 30, 1(PC)    // bne- cr7,0x4
+       ISYNC
+       MOVD    R3, val+8(FP)
+       RETURN
+
+TEXT Â·LoadUintptr(SB),NOSPLIT,$0-16
+       BR      Â·LoadPointer(SB)
+
+TEXT Â·LoadPointer(SB),NOSPLIT,$0-16
+       BR      Â·LoadUint64(SB)
+
+TEXT Â·StoreInt32(SB),NOSPLIT,$0-12
+       BR      Â·StoreUint32(SB)
+
+TEXT Â·StoreUint32(SB),NOSPLIT,$0-12
+       MOVD    addr+0(FP), R3
+       MOVW    val+8(FP), R4
+       SYNC
+       MOVW    R4, 0(R3)
+       RETURN
+
+TEXT Â·StoreInt64(SB),NOSPLIT,$0-16
+       BR      Â·StoreUint64(SB)
+
+TEXT Â·StoreUint64(SB),NOSPLIT,$0-16
+       MOVD    addr+0(FP), R3
+       MOVD    val+8(FP), R4
+       SYNC
+       MOVD    R4, 0(R3)
+       RETURN
+
+TEXT Â·StoreUintptr(SB),NOSPLIT,$0-16
+       BR      Â·StorePointer(SB)
+
+TEXT Â·StorePointer(SB),NOSPLIT,$0-16
+       BR      Â·StoreUint64(SB)
index d4ca868f17f98e7500163b292a1a139961448ca5..43561e20195dd578a388bf074bcbdf866f85bc10 100644 (file)
@@ -4,5 +4,12 @@
 
 #include "textflag.h"
 
+#ifdef GOARCH_power64
+#define RET RETURN
+#endif
+#ifdef GOARCH_power64le
+#define RET RETURN
+#endif
+
 TEXT Â·use(SB),NOSPLIT,$0
        RET
diff --git a/src/syscall/asm_linux_power64x.s b/src/syscall/asm_linux_power64x.s
new file mode 100644 (file)
index 0000000..be8518a
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build power64 power64le
+
+#include "textflag.h"
+
+//
+// System calls for Power64, Linux
+//
+
+// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
+
+TEXT   Â·Syscall(SB),NOSPLIT,$0-56
+       BL      runtime·entersyscall(SB)
+       MOVD    a1+8(FP), R3
+       MOVD    a2+16(FP), R4
+       MOVD    a3+24(FP), R5
+       MOVD    R0, R6
+       MOVD    R0, R7
+       MOVD    R0, R8
+       MOVD    trap+0(FP), R9  // syscall entry
+       SYSCALL R9
+       BVC     ok
+       MOVD    $-1, R4
+       MOVD    R4, r1+32(FP)   // r1
+       MOVD    R0, r2+40(FP)   // r2
+       MOVD    R3, err+48(FP)  // errno
+       BL      runtime·exitsyscall(SB)
+       RETURN
+ok:
+       MOVD    R3, r1+32(FP)   // r1
+       MOVD    R4, r2+40(FP)   // r2
+       MOVD    R0, err+48(FP)  // errno
+       BL      runtime·exitsyscall(SB)
+       RETURN
+
+TEXT Â·Syscall6(SB),NOSPLIT,$0-80
+       BL      runtime·entersyscall(SB)
+       MOVD    a1+8(FP), R3
+       MOVD    a2+16(FP), R4
+       MOVD    a3+24(FP), R5
+       MOVD    a4+32(FP), R6
+       MOVD    a5+40(FP), R7
+       MOVD    a6+48(FP), R8
+       MOVD    trap+0(FP), R9  // syscall entry
+       SYSCALL R9
+       BVC     ok6
+       MOVD    $-1, R4
+       MOVD    R4, r1+56(FP)   // r1
+       MOVD    R0, r2+64(FP)   // r2
+       MOVD    R3, err+72(FP)  // errno
+       BL      runtime·exitsyscall(SB)
+       RETURN
+ok6:
+       MOVD    R3, r1+56(FP)   // r1
+       MOVD    R4, r2+64(FP)   // r2
+       MOVD    R0, err+72(FP)  // errno
+       BL      runtime·exitsyscall(SB)
+       RETURN
+
+TEXT Â·RawSyscall(SB),NOSPLIT,$0-56
+       MOVD    a1+8(FP), R3
+       MOVD    a2+16(FP), R4
+       MOVD    a3+24(FP), R5
+       MOVD    R0, R6
+       MOVD    R0, R7
+       MOVD    R0, R8
+       MOVD    trap+0(FP), R9  // syscall entry
+       SYSCALL R9
+       BVC     ok1
+       MOVD    $-1, R4
+       MOVD    R4, r1+32(FP)   // r1
+       MOVD    R0, r2+40(FP)   // r2
+       MOVD    R3, err+48(FP)  // errno
+       RETURN
+ok1:
+       MOVD    R3, r1+32(FP)   // r1
+       MOVD    R4, r2+40(FP)   // r2
+       MOVD    R0, err+48(FP)  // errno
+       RETURN
+
+TEXT Â·RawSyscall6(SB),NOSPLIT,$0-80
+       MOVD    a1+8(FP), R3
+       MOVD    a2+16(FP), R4
+       MOVD    a3+24(FP), R5
+       MOVD    a4+32(FP), R6
+       MOVD    a5+40(FP), R7
+       MOVD    a6+48(FP), R8
+       MOVD    trap+0(FP), R9  // syscall entry
+       SYSCALL R9
+       BVC     ok2
+       MOVD    $-1, R4
+       MOVD    R4, r1+56(FP)   // r1
+       MOVD    R0, r2+64(FP)   // r2
+       MOVD    R3, err+72(FP)  // errno
+       RETURN
+ok2:
+       MOVD    R3, r1+56(FP)   // r1
+       MOVD    R4, r2+64(FP)   // r2
+       MOVD    R0, err+72(FP)  // errno
+       RETURN
index 9cb82a608d53f281cc3dd68397b113a1eb5a8df4..febd5a2625fc41cc0ce0572cc315eaa1bb9605a4 100755 (executable)
@@ -107,6 +107,7 @@ case "$#" in
        exit 2
 esac
 
+GOOSARCH_in=syscall_$GOOSARCH.go
 case "$GOOSARCH" in
 _* | *_ | _)
        echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
@@ -176,6 +177,20 @@ linux_arm)
        mksysnum="curl -s 'http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/arch/arm/include/uapi/asm/unistd.h' | ./mksysnum_linux.pl"
        mktypes="GOARCH=$GOARCH go tool cgo -godefs"
        ;;
+linux_power64)
+       GOOSARCH_in=syscall_linux_power64x.go
+       unistd_h=/usr/include/asm/unistd.h
+       mkerrors="$mkerrors -m64"
+       mksysnum="./mksysnum_linux.pl $unistd_h"
+       mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+       ;;
+linux_power64le)
+       GOOSARCH_in=syscall_linux_power64x.go
+       unistd_h=/usr/include/powerpc64le-linux-gnu/asm/unistd.h
+       mkerrors="$mkerrors -m64"
+       mksysnum="./mksysnum_linux.pl $unistd_h"
+       mktypes="GOARCH=$GOARCH go tool cgo -godefs"
+       ;;
 nacl_386)
        mkerrors=""
        mksyscall="./mksyscall.pl -l32 -nacl"
@@ -254,7 +269,7 @@ esac
                        syscall_goos="syscall_bsd.go $syscall_goos"
                        ;;
                esac
-               if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos syscall_$GOOSARCH.go |gofmt >zsyscall_$GOOSARCH.go"; fi
+               if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go"; fi
                ;;
        esac
        if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
index cf0afe0bdd8966c001f60f553152551600b9e35c..4711f307a8e84cd3ae9feada25d398392ac02197 100755 (executable)
@@ -242,6 +242,7 @@ ccflags="$@"
                $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
                $2 ~ /^(SCM_SRCRT)$/ {next}
                $2 ~ /^(MAP_FAILED)$/ {next}
+               $2 ~ /^ELF_.*$/ {next}  # <asm/elf.h> contains ELF_ARCH, etc.
 
                $2 !~ /^ETH_/ &&
                $2 !~ /^EPROC_/ &&
diff --git a/src/syscall/syscall_linux_power64x.go b/src/syscall/syscall_linux_power64x.go
new file mode 100644 (file)
index 0000000..fd04362
--- /dev/null
@@ -0,0 +1,97 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build power64 power64le
+
+package syscall
+
+//sys  Chown(path string, uid int, gid int) (err error)
+//sys  Fchown(fd int, uid int, gid int) (err error)
+//sys  Fstat(fd int, stat *Stat_t) (err error)
+//sys  Fstatfs(fd int, buf *Statfs_t) (err error)
+//sys  Ftruncate(fd int, length int64) (err error)
+//sysnb        Getegid() (egid int)
+//sysnb        Geteuid() (euid int)
+//sysnb        Getgid() (gid int)
+//sysnb        Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT
+//sysnb        Getuid() (uid int)
+//sys  Ioperm(from int, num int, on int) (err error)
+//sys  Iopl(level int) (err error)
+//sys  Lchown(path string, uid int, gid int) (err error)
+//sys  Listen(s int, n int) (err error)
+//sys  Lstat(path string, stat *Stat_t) (err error)
+//sys  Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys  Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys  Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
+//sys  Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
+//sys  sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
+//sys  Setfsgid(gid int) (err error)
+//sys  Setfsuid(uid int) (err error)
+//sysnb        Setregid(rgid int, egid int) (err error)
+//sysnb        Setresgid(rgid int, egid int, sgid int) (err error)
+//sysnb        Setresuid(ruid int, euid int, suid int) (err error)
+//sysnb        Setrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb        Setreuid(ruid int, euid int) (err error)
+//sys  Shutdown(fd int, how int) (err error)
+//sys  Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
+//sys  Stat(path string, stat *Stat_t) (err error)
+//sys  Statfs(path string, buf *Statfs_t) (err error)
+//sys  SyncFileRange(fd int, off int64, n int64, flags int) (err error) = SYS_SYNC_FILE_RANGE2
+//sys  Truncate(path string, length int64) (err error)
+//sys  accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys  accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
+//sys  bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
+//sys  connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
+//sysnb        getgroups(n int, list *_Gid_t) (nn int, err error)
+//sysnb        setgroups(n int, list *_Gid_t) (err error)
+//sys  getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
+//sys  setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
+//sysnb        socket(domain int, typ int, proto int) (fd int, err error)
+//sysnb        socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
+//sysnb        getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sysnb        getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sys  recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
+//sys  sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
+//sys  recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys  sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys  mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
+
+func Getpagesize() int { return 65536 }
+
+//sysnb        Gettimeofday(tv *Timeval) (err error)
+//sysnb        Time(t *Time_t) (tt Time_t, err error)
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+       ts.Sec = nsec / 1e9
+       ts.Nsec = nsec % 1e9
+       return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+       nsec += 999 // round up to microsecond
+       tv.Sec = nsec / 1e9
+       tv.Usec = nsec % 1e9 / 1e3
+       return
+}
+
+func (r *PtraceRegs) PC() uint64 { return r.Nip }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Nip = pc }
+
+func (iov *Iovec) SetLen(length int) {
+       iov.Len = uint64(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+       msghdr.Controllen = uint64(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+       cmsg.Len = uint64(length)
+}
index e8396a41f3659fa10864f184c6f80e14e0cfc2d0..5e9f698cf1b2cad306ae348d41bd08b48ace8739 100644 (file)
@@ -77,8 +77,8 @@ struct sockaddr_any {
 // copied from /usr/include/linux/un.h
 struct my_sockaddr_un {
        sa_family_t sun_family;
-#ifdef __ARM_EABI__
-       // on ARM char is by default unsigned
+#if defined(__ARM_EABI__) || defined(__powerpc64__)
+       // on ARM and PPC char is by default unsigned
        signed char sun_path[108];
 #else
        char sun_path[108];
@@ -87,6 +87,8 @@ struct my_sockaddr_un {
 
 #ifdef __ARM_EABI__
 typedef struct user_regs PtraceRegs;
+#elif defined(__powerpc64__)
+typedef struct pt_regs PtraceRegs;
 #else
 typedef struct user_regs_struct PtraceRegs;
 #endif
@@ -382,103 +384,9 @@ const (
 type Termios C.struct_termios
 
 const (
-       VINTR    = C.VINTR
-       VQUIT    = C.VQUIT
-       VERASE   = C.VERASE
-       VKILL    = C.VKILL
-       VEOF     = C.VEOF
-       VTIME    = C.VTIME
-       VMIN     = C.VMIN
-       VSWTC    = C.VSWTC
-       VSTART   = C.VSTART
-       VSTOP    = C.VSTOP
-       VSUSP    = C.VSUSP
-       VEOL     = C.VEOL
-       VREPRINT = C.VREPRINT
-       VDISCARD = C.VDISCARD
-       VWERASE  = C.VWERASE
-       VLNEXT   = C.VLNEXT
-       VEOL2    = C.VEOL2
-       IGNBRK   = C.IGNBRK
-       BRKINT   = C.BRKINT
-       IGNPAR   = C.IGNPAR
-       PARMRK   = C.PARMRK
-       INPCK    = C.INPCK
-       ISTRIP   = C.ISTRIP
-       INLCR    = C.INLCR
-       IGNCR    = C.IGNCR
-       ICRNL    = C.ICRNL
-       IUCLC    = C.IUCLC
-       IXON     = C.IXON
-       IXANY    = C.IXANY
-       IXOFF    = C.IXOFF
-       IMAXBEL  = C.IMAXBEL
-       IUTF8    = C.IUTF8
-       OPOST    = C.OPOST
-       OLCUC    = C.OLCUC
-       ONLCR    = C.ONLCR
-       OCRNL    = C.OCRNL
-       ONOCR    = C.ONOCR
-       ONLRET   = C.ONLRET
-       OFILL    = C.OFILL
-       OFDEL    = C.OFDEL
-       B0       = C.B0
-       B50      = C.B50
-       B75      = C.B75
-       B110     = C.B110
-       B134     = C.B134
-       B150     = C.B150
-       B200     = C.B200
-       B300     = C.B300
-       B600     = C.B600
-       B1200    = C.B1200
-       B1800    = C.B1800
-       B2400    = C.B2400
-       B4800    = C.B4800
-       B9600    = C.B9600
-       B19200   = C.B19200
-       B38400   = C.B38400
-       CSIZE    = C.CSIZE
-       CS5      = C.CS5
-       CS6      = C.CS6
-       CS7      = C.CS7
-       CS8      = C.CS8
-       CSTOPB   = C.CSTOPB
-       CREAD    = C.CREAD
-       PARENB   = C.PARENB
-       PARODD   = C.PARODD
-       HUPCL    = C.HUPCL
-       CLOCAL   = C.CLOCAL
-       B57600   = C.B57600
-       B115200  = C.B115200
-       B230400  = C.B230400
-       B460800  = C.B460800
-       B500000  = C.B500000
-       B576000  = C.B576000
-       B921600  = C.B921600
-       B1000000 = C.B1000000
-       B1152000 = C.B1152000
-       B1500000 = C.B1500000
-       B2000000 = C.B2000000
-       B2500000 = C.B2500000
-       B3000000 = C.B3000000
-       B3500000 = C.B3500000
-       B4000000 = C.B4000000
-       ISIG     = C.ISIG
-       ICANON   = C.ICANON
-       XCASE    = C.XCASE
-       ECHO     = C.ECHO
-       ECHOE    = C.ECHOE
-       ECHOK    = C.ECHOK
-       ECHONL   = C.ECHONL
-       NOFLSH   = C.NOFLSH
-       TOSTOP   = C.TOSTOP
-       ECHOCTL  = C.ECHOCTL
-       ECHOPRT  = C.ECHOPRT
-       ECHOKE   = C.ECHOKE
-       FLUSHO   = C.FLUSHO
-       PENDIN   = C.PENDIN
-       IEXTEN   = C.IEXTEN
-       TCGETS   = C.TCGETS
-       TCSETS   = C.TCSETS
+       IUCLC  = C.IUCLC
+       OLCUC  = C.OLCUC
+       TCGETS = C.TCGETS
+       TCSETS = C.TCSETS
+       XCASE  = C.XCASE
 )
diff --git a/src/syscall/zerrors_linux_power64.go b/src/syscall/zerrors_linux_power64.go
new file mode 100644 (file)
index 0000000..15e0770
--- /dev/null
@@ -0,0 +1,1878 @@
+// mkerrors.sh -m64
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
+
+package syscall
+
+const (
+       AF_ALG                           = 0x26
+       AF_APPLETALK                     = 0x5
+       AF_ASH                           = 0x12
+       AF_ATMPVC                        = 0x8
+       AF_ATMSVC                        = 0x14
+       AF_AX25                          = 0x3
+       AF_BLUETOOTH                     = 0x1f
+       AF_BRIDGE                        = 0x7
+       AF_CAIF                          = 0x25
+       AF_CAN                           = 0x1d
+       AF_DECnet                        = 0xc
+       AF_ECONET                        = 0x13
+       AF_FILE                          = 0x1
+       AF_IEEE802154                    = 0x24
+       AF_INET                          = 0x2
+       AF_INET6                         = 0xa
+       AF_IPX                           = 0x4
+       AF_IRDA                          = 0x17
+       AF_ISDN                          = 0x22
+       AF_IUCV                          = 0x20
+       AF_KEY                           = 0xf
+       AF_LLC                           = 0x1a
+       AF_LOCAL                         = 0x1
+       AF_MAX                           = 0x28
+       AF_NETBEUI                       = 0xd
+       AF_NETLINK                       = 0x10
+       AF_NETROM                        = 0x6
+       AF_NFC                           = 0x27
+       AF_PACKET                        = 0x11
+       AF_PHONET                        = 0x23
+       AF_PPPOX                         = 0x18
+       AF_RDS                           = 0x15
+       AF_ROSE                          = 0xb
+       AF_ROUTE                         = 0x10
+       AF_RXRPC                         = 0x21
+       AF_SECURITY                      = 0xe
+       AF_SNA                           = 0x16
+       AF_TIPC                          = 0x1e
+       AF_UNIX                          = 0x1
+       AF_UNSPEC                        = 0x0
+       AF_WANPIPE                       = 0x19
+       AF_X25                           = 0x9
+       ARPHRD_ADAPT                     = 0x108
+       ARPHRD_APPLETLK                  = 0x8
+       ARPHRD_ARCNET                    = 0x7
+       ARPHRD_ASH                       = 0x30d
+       ARPHRD_ATM                       = 0x13
+       ARPHRD_AX25                      = 0x3
+       ARPHRD_BIF                       = 0x307
+       ARPHRD_CAIF                      = 0x336
+       ARPHRD_CAN                       = 0x118
+       ARPHRD_CHAOS                     = 0x5
+       ARPHRD_CISCO                     = 0x201
+       ARPHRD_CSLIP                     = 0x101
+       ARPHRD_CSLIP6                    = 0x103
+       ARPHRD_DDCMP                     = 0x205
+       ARPHRD_DLCI                      = 0xf
+       ARPHRD_ECONET                    = 0x30e
+       ARPHRD_EETHER                    = 0x2
+       ARPHRD_ETHER                     = 0x1
+       ARPHRD_EUI64                     = 0x1b
+       ARPHRD_FCAL                      = 0x311
+       ARPHRD_FCFABRIC                  = 0x313
+       ARPHRD_FCPL                      = 0x312
+       ARPHRD_FCPP                      = 0x310
+       ARPHRD_FDDI                      = 0x306
+       ARPHRD_FRAD                      = 0x302
+       ARPHRD_HDLC                      = 0x201
+       ARPHRD_HIPPI                     = 0x30c
+       ARPHRD_HWX25                     = 0x110
+       ARPHRD_IEEE1394                  = 0x18
+       ARPHRD_IEEE802                   = 0x6
+       ARPHRD_IEEE80211                 = 0x321
+       ARPHRD_IEEE80211_PRISM           = 0x322
+       ARPHRD_IEEE80211_RADIOTAP        = 0x323
+       ARPHRD_IEEE802154                = 0x324
+       ARPHRD_IEEE802154_MONITOR        = 0x325
+       ARPHRD_IEEE802_TR                = 0x320
+       ARPHRD_INFINIBAND                = 0x20
+       ARPHRD_IP6GRE                    = 0x337
+       ARPHRD_IPDDP                     = 0x309
+       ARPHRD_IPGRE                     = 0x30a
+       ARPHRD_IRDA                      = 0x30f
+       ARPHRD_LAPB                      = 0x204
+       ARPHRD_LOCALTLK                  = 0x305
+       ARPHRD_LOOPBACK                  = 0x304
+       ARPHRD_METRICOM                  = 0x17
+       ARPHRD_NETLINK                   = 0x338
+       ARPHRD_NETROM                    = 0x0
+       ARPHRD_NONE                      = 0xfffe
+       ARPHRD_PHONET                    = 0x334
+       ARPHRD_PHONET_PIPE               = 0x335
+       ARPHRD_PIMREG                    = 0x30b
+       ARPHRD_PPP                       = 0x200
+       ARPHRD_PRONET                    = 0x4
+       ARPHRD_RAWHDLC                   = 0x206
+       ARPHRD_ROSE                      = 0x10e
+       ARPHRD_RSRVD                     = 0x104
+       ARPHRD_SIT                       = 0x308
+       ARPHRD_SKIP                      = 0x303
+       ARPHRD_SLIP                      = 0x100
+       ARPHRD_SLIP6                     = 0x102
+       ARPHRD_TUNNEL                    = 0x300
+       ARPHRD_TUNNEL6                   = 0x301
+       ARPHRD_VOID                      = 0xffff
+       ARPHRD_X25                       = 0x10f
+       B0                               = 0x0
+       B1000000                         = 0x17
+       B110                             = 0x3
+       B115200                          = 0x11
+       B1152000                         = 0x18
+       B1200                            = 0x9
+       B134                             = 0x4
+       B150                             = 0x5
+       B1500000                         = 0x19
+       B1800                            = 0xa
+       B19200                           = 0xe
+       B200                             = 0x6
+       B2000000                         = 0x1a
+       B230400                          = 0x12
+       B2400                            = 0xb
+       B2500000                         = 0x1b
+       B300                             = 0x7
+       B3000000                         = 0x1c
+       B3500000                         = 0x1d
+       B38400                           = 0xf
+       B4000000                         = 0x1e
+       B460800                          = 0x13
+       B4800                            = 0xc
+       B50                              = 0x1
+       B500000                          = 0x14
+       B57600                           = 0x10
+       B576000                          = 0x15
+       B600                             = 0x8
+       B75                              = 0x2
+       B921600                          = 0x16
+       B9600                            = 0xd
+       BPF_A                            = 0x10
+       BPF_ABS                          = 0x20
+       BPF_ADD                          = 0x0
+       BPF_ALU                          = 0x4
+       BPF_AND                          = 0x50
+       BPF_B                            = 0x10
+       BPF_DIV                          = 0x30
+       BPF_H                            = 0x8
+       BPF_IMM                          = 0x0
+       BPF_IND                          = 0x40
+       BPF_JA                           = 0x0
+       BPF_JEQ                          = 0x10
+       BPF_JGE                          = 0x30
+       BPF_JGT                          = 0x20
+       BPF_JMP                          = 0x5
+       BPF_JSET                         = 0x40
+       BPF_K                            = 0x0
+       BPF_LD                           = 0x0
+       BPF_LDX                          = 0x1
+       BPF_LEN                          = 0x80
+       BPF_LSH                          = 0x60
+       BPF_MAJOR_VERSION                = 0x1
+       BPF_MAXINSNS                     = 0x1000
+       BPF_MEM                          = 0x60
+       BPF_MEMWORDS                     = 0x10
+       BPF_MINOR_VERSION                = 0x1
+       BPF_MISC                         = 0x7
+       BPF_MOD                          = 0x90
+       BPF_MSH                          = 0xa0
+       BPF_MUL                          = 0x20
+       BPF_NEG                          = 0x80
+       BPF_OR                           = 0x40
+       BPF_RET                          = 0x6
+       BPF_RSH                          = 0x70
+       BPF_ST                           = 0x2
+       BPF_STX                          = 0x3
+       BPF_SUB                          = 0x10
+       BPF_TAX                          = 0x0
+       BPF_TXA                          = 0x80
+       BPF_W                            = 0x0
+       BPF_X                            = 0x8
+       BPF_XOR                          = 0xa0
+       BRKINT                           = 0x2
+       CFLUSH                           = 0xf
+       CLOCAL                           = 0x8000
+       CLONE_CHILD_CLEARTID             = 0x200000
+       CLONE_CHILD_SETTID               = 0x1000000
+       CLONE_DETACHED                   = 0x400000
+       CLONE_FILES                      = 0x400
+       CLONE_FS                         = 0x200
+       CLONE_IO                         = 0x80000000
+       CLONE_NEWIPC                     = 0x8000000
+       CLONE_NEWNET                     = 0x40000000
+       CLONE_NEWNS                      = 0x20000
+       CLONE_NEWPID                     = 0x20000000
+       CLONE_NEWUSER                    = 0x10000000
+       CLONE_NEWUTS                     = 0x4000000
+       CLONE_PARENT                     = 0x8000
+       CLONE_PARENT_SETTID              = 0x100000
+       CLONE_PTRACE                     = 0x2000
+       CLONE_SETTLS                     = 0x80000
+       CLONE_SIGHAND                    = 0x800
+       CLONE_SYSVSEM                    = 0x40000
+       CLONE_THREAD                     = 0x10000
+       CLONE_UNTRACED                   = 0x800000
+       CLONE_VFORK                      = 0x4000
+       CLONE_VM                         = 0x100
+       CREAD                            = 0x800
+       CS5                              = 0x0
+       CS6                              = 0x100
+       CS7                              = 0x200
+       CS8                              = 0x300
+       CSIGNAL                          = 0xff
+       CSIZE                            = 0x300
+       CSTART                           = 0x11
+       CSTATUS                          = 0x0
+       CSTOP                            = 0x13
+       CSTOPB                           = 0x400
+       CSUSP                            = 0x1a
+       DT_BLK                           = 0x6
+       DT_CHR                           = 0x2
+       DT_DIR                           = 0x4
+       DT_FIFO                          = 0x1
+       DT_LNK                           = 0xa
+       DT_REG                           = 0x8
+       DT_SOCK                          = 0xc
+       DT_UNKNOWN                       = 0x0
+       DT_WHT                           = 0xe
+       ECHO                             = 0x8
+       ECHOCTL                          = 0x40
+       ECHOE                            = 0x2
+       ECHOK                            = 0x4
+       ECHOKE                           = 0x1
+       ECHONL                           = 0x10
+       ECHOPRT                          = 0x20
+       ENCODING_DEFAULT                 = 0x0
+       ENCODING_FM_MARK                 = 0x3
+       ENCODING_FM_SPACE                = 0x4
+       ENCODING_MANCHESTER              = 0x5
+       ENCODING_NRZ                     = 0x1
+       ENCODING_NRZI                    = 0x2
+       EPOLLERR                         = 0x8
+       EPOLLET                          = 0x80000000
+       EPOLLHUP                         = 0x10
+       EPOLLIN                          = 0x1
+       EPOLLMSG                         = 0x400
+       EPOLLONESHOT                     = 0x40000000
+       EPOLLOUT                         = 0x4
+       EPOLLPRI                         = 0x2
+       EPOLLRDBAND                      = 0x80
+       EPOLLRDHUP                       = 0x2000
+       EPOLLRDNORM                      = 0x40
+       EPOLLWAKEUP                      = 0x20000000
+       EPOLLWRBAND                      = 0x200
+       EPOLLWRNORM                      = 0x100
+       EPOLL_CLOEXEC                    = 0x80000
+       EPOLL_CTL_ADD                    = 0x1
+       EPOLL_CTL_DEL                    = 0x2
+       EPOLL_CTL_MOD                    = 0x3
+       EPOLL_NONBLOCK                   = 0x800
+       ETH_P_1588                       = 0x88f7
+       ETH_P_8021AD                     = 0x88a8
+       ETH_P_8021AH                     = 0x88e7
+       ETH_P_8021Q                      = 0x8100
+       ETH_P_802_2                      = 0x4
+       ETH_P_802_3                      = 0x1
+       ETH_P_802_3_MIN                  = 0x600
+       ETH_P_802_EX1                    = 0x88b5
+       ETH_P_AARP                       = 0x80f3
+       ETH_P_AF_IUCV                    = 0xfbfb
+       ETH_P_ALL                        = 0x3
+       ETH_P_AOE                        = 0x88a2
+       ETH_P_ARCNET                     = 0x1a
+       ETH_P_ARP                        = 0x806
+       ETH_P_ATALK                      = 0x809b
+       ETH_P_ATMFATE                    = 0x8884
+       ETH_P_ATMMPOA                    = 0x884c
+       ETH_P_AX25                       = 0x2
+       ETH_P_BATMAN                     = 0x4305
+       ETH_P_BPQ                        = 0x8ff
+       ETH_P_CAIF                       = 0xf7
+       ETH_P_CAN                        = 0xc
+       ETH_P_CANFD                      = 0xd
+       ETH_P_CONTROL                    = 0x16
+       ETH_P_CUST                       = 0x6006
+       ETH_P_DDCMP                      = 0x6
+       ETH_P_DEC                        = 0x6000
+       ETH_P_DIAG                       = 0x6005
+       ETH_P_DNA_DL                     = 0x6001
+       ETH_P_DNA_RC                     = 0x6002
+       ETH_P_DNA_RT                     = 0x6003
+       ETH_P_DSA                        = 0x1b
+       ETH_P_ECONET                     = 0x18
+       ETH_P_EDSA                       = 0xdada
+       ETH_P_FCOE                       = 0x8906
+       ETH_P_FIP                        = 0x8914
+       ETH_P_HDLC                       = 0x19
+       ETH_P_IEEE802154                 = 0xf6
+       ETH_P_IEEEPUP                    = 0xa00
+       ETH_P_IEEEPUPAT                  = 0xa01
+       ETH_P_IP                         = 0x800
+       ETH_P_IPV6                       = 0x86dd
+       ETH_P_IPX                        = 0x8137
+       ETH_P_IRDA                       = 0x17
+       ETH_P_LAT                        = 0x6004
+       ETH_P_LINK_CTL                   = 0x886c
+       ETH_P_LOCALTALK                  = 0x9
+       ETH_P_LOOP                       = 0x60
+       ETH_P_MOBITEX                    = 0x15
+       ETH_P_MPLS_MC                    = 0x8848
+       ETH_P_MPLS_UC                    = 0x8847
+       ETH_P_MVRP                       = 0x88f5
+       ETH_P_PAE                        = 0x888e
+       ETH_P_PAUSE                      = 0x8808
+       ETH_P_PHONET                     = 0xf5
+       ETH_P_PPPTALK                    = 0x10
+       ETH_P_PPP_DISC                   = 0x8863
+       ETH_P_PPP_MP                     = 0x8
+       ETH_P_PPP_SES                    = 0x8864
+       ETH_P_PRP                        = 0x88fb
+       ETH_P_PUP                        = 0x200
+       ETH_P_PUPAT                      = 0x201
+       ETH_P_QINQ1                      = 0x9100
+       ETH_P_QINQ2                      = 0x9200
+       ETH_P_QINQ3                      = 0x9300
+       ETH_P_RARP                       = 0x8035
+       ETH_P_SCA                        = 0x6007
+       ETH_P_SLOW                       = 0x8809
+       ETH_P_SNAP                       = 0x5
+       ETH_P_TDLS                       = 0x890d
+       ETH_P_TEB                        = 0x6558
+       ETH_P_TIPC                       = 0x88ca
+       ETH_P_TRAILER                    = 0x1c
+       ETH_P_TR_802_2                   = 0x11
+       ETH_P_WAN_PPP                    = 0x7
+       ETH_P_WCCP                       = 0x883e
+       ETH_P_X25                        = 0x805
+       EXTA                             = 0xe
+       EXTB                             = 0xf
+       EXTPROC                          = 0x10000000
+       FD_CLOEXEC                       = 0x1
+       FD_SETSIZE                       = 0x400
+       FLUSHO                           = 0x800000
+       F_DUPFD                          = 0x0
+       F_DUPFD_CLOEXEC                  = 0x406
+       F_EXLCK                          = 0x4
+       F_GETFD                          = 0x1
+       F_GETFL                          = 0x3
+       F_GETLEASE                       = 0x401
+       F_GETLK                          = 0x5
+       F_GETLK64                        = 0xc
+       F_GETOWN                         = 0x9
+       F_GETOWN_EX                      = 0x10
+       F_GETPIPE_SZ                     = 0x408
+       F_GETSIG                         = 0xb
+       F_LOCK                           = 0x1
+       F_NOTIFY                         = 0x402
+       F_OK                             = 0x0
+       F_RDLCK                          = 0x0
+       F_SETFD                          = 0x2
+       F_SETFL                          = 0x4
+       F_SETLEASE                       = 0x400
+       F_SETLK                          = 0xd
+       F_SETLK64                        = 0xd
+       F_SETLKW                         = 0xe
+       F_SETLKW64                       = 0xe
+       F_SETOWN                         = 0x8
+       F_SETOWN_EX                      = 0xf
+       F_SETPIPE_SZ                     = 0x407
+       F_SETSIG                         = 0xa
+       F_SHLCK                          = 0x8
+       F_TEST                           = 0x3
+       F_TLOCK                          = 0x2
+       F_ULOCK                          = 0x0
+       F_UNLCK                          = 0x2
+       F_WRLCK                          = 0x1
+       HUPCL                            = 0x4000
+       ICANON                           = 0x100
+       ICMPV6_FILTER                    = 0x1
+       ICRNL                            = 0x100
+       IEXTEN                           = 0x400
+       IFA_F_DADFAILED                  = 0x8
+       IFA_F_DEPRECATED                 = 0x20
+       IFA_F_HOMEADDRESS                = 0x10
+       IFA_F_NODAD                      = 0x2
+       IFA_F_OPTIMISTIC                 = 0x4
+       IFA_F_PERMANENT                  = 0x80
+       IFA_F_SECONDARY                  = 0x1
+       IFA_F_TEMPORARY                  = 0x1
+       IFA_F_TENTATIVE                  = 0x40
+       IFA_MAX                          = 0x7
+       IFF_802_1Q_VLAN                  = 0x1
+       IFF_ALLMULTI                     = 0x200
+       IFF_ATTACH_QUEUE                 = 0x200
+       IFF_AUTOMEDIA                    = 0x4000
+       IFF_BONDING                      = 0x20
+       IFF_BRIDGE_PORT                  = 0x4000
+       IFF_BROADCAST                    = 0x2
+       IFF_DEBUG                        = 0x4
+       IFF_DETACH_QUEUE                 = 0x400
+       IFF_DISABLE_NETPOLL              = 0x1000
+       IFF_DONT_BRIDGE                  = 0x800
+       IFF_DORMANT                      = 0x20000
+       IFF_DYNAMIC                      = 0x8000
+       IFF_EBRIDGE                      = 0x2
+       IFF_ECHO                         = 0x40000
+       IFF_ISATAP                       = 0x80
+       IFF_LIVE_ADDR_CHANGE             = 0x100000
+       IFF_LOOPBACK                     = 0x8
+       IFF_LOWER_UP                     = 0x10000
+       IFF_MACVLAN                      = 0x200000
+       IFF_MACVLAN_PORT                 = 0x2000
+       IFF_MASTER                       = 0x400
+       IFF_MASTER_8023AD                = 0x8
+       IFF_MASTER_ALB                   = 0x10
+       IFF_MASTER_ARPMON                = 0x100
+       IFF_MULTICAST                    = 0x1000
+       IFF_MULTI_QUEUE                  = 0x100
+       IFF_NOARP                        = 0x80
+       IFF_NOFILTER                     = 0x1000
+       IFF_NOTRAILERS                   = 0x20
+       IFF_NO_PI                        = 0x1000
+       IFF_ONE_QUEUE                    = 0x2000
+       IFF_OVS_DATAPATH                 = 0x8000
+       IFF_PERSIST                      = 0x800
+       IFF_POINTOPOINT                  = 0x10
+       IFF_PORTSEL                      = 0x2000
+       IFF_PROMISC                      = 0x100
+       IFF_RUNNING                      = 0x40
+       IFF_SLAVE                        = 0x800
+       IFF_SLAVE_INACTIVE               = 0x4
+       IFF_SLAVE_NEEDARP                = 0x40
+       IFF_SUPP_NOFCS                   = 0x80000
+       IFF_TAP                          = 0x2
+       IFF_TEAM_PORT                    = 0x40000
+       IFF_TUN                          = 0x1
+       IFF_TUN_EXCL                     = 0x8000
+       IFF_TX_SKB_SHARING               = 0x10000
+       IFF_UNICAST_FLT                  = 0x20000
+       IFF_UP                           = 0x1
+       IFF_VNET_HDR                     = 0x4000
+       IFF_VOLATILE                     = 0x70c5a
+       IFF_WAN_HDLC                     = 0x200
+       IFF_XMIT_DST_RELEASE             = 0x400
+       IFNAMSIZ                         = 0x10
+       IGNBRK                           = 0x1
+       IGNCR                            = 0x80
+       IGNPAR                           = 0x4
+       IMAXBEL                          = 0x2000
+       INLCR                            = 0x40
+       INPCK                            = 0x10
+       IN_ACCESS                        = 0x1
+       IN_ALL_EVENTS                    = 0xfff
+       IN_ATTRIB                        = 0x4
+       IN_CLASSA_HOST                   = 0xffffff
+       IN_CLASSA_MAX                    = 0x80
+       IN_CLASSA_NET                    = 0xff000000
+       IN_CLASSA_NSHIFT                 = 0x18
+       IN_CLASSB_HOST                   = 0xffff
+       IN_CLASSB_MAX                    = 0x10000
+       IN_CLASSB_NET                    = 0xffff0000
+       IN_CLASSB_NSHIFT                 = 0x10
+       IN_CLASSC_HOST                   = 0xff
+       IN_CLASSC_NET                    = 0xffffff00
+       IN_CLASSC_NSHIFT                 = 0x8
+       IN_CLOEXEC                       = 0x80000
+       IN_CLOSE                         = 0x18
+       IN_CLOSE_NOWRITE                 = 0x10
+       IN_CLOSE_WRITE                   = 0x8
+       IN_CREATE                        = 0x100
+       IN_DELETE                        = 0x200
+       IN_DELETE_SELF                   = 0x400
+       IN_DONT_FOLLOW                   = 0x2000000
+       IN_EXCL_UNLINK                   = 0x4000000
+       IN_IGNORED                       = 0x8000
+       IN_ISDIR                         = 0x40000000
+       IN_LOOPBACKNET                   = 0x7f
+       IN_MASK_ADD                      = 0x20000000
+       IN_MODIFY                        = 0x2
+       IN_MOVE                          = 0xc0
+       IN_MOVED_FROM                    = 0x40
+       IN_MOVED_TO                      = 0x80
+       IN_MOVE_SELF                     = 0x800
+       IN_NONBLOCK                      = 0x800
+       IN_ONESHOT                       = 0x80000000
+       IN_ONLYDIR                       = 0x1000000
+       IN_OPEN                          = 0x20
+       IN_Q_OVERFLOW                    = 0x4000
+       IN_UNMOUNT                       = 0x2000
+       IPPROTO_AH                       = 0x33
+       IPPROTO_COMP                     = 0x6c
+       IPPROTO_DCCP                     = 0x21
+       IPPROTO_DSTOPTS                  = 0x3c
+       IPPROTO_EGP                      = 0x8
+       IPPROTO_ENCAP                    = 0x62
+       IPPROTO_ESP                      = 0x32
+       IPPROTO_FRAGMENT                 = 0x2c
+       IPPROTO_GRE                      = 0x2f
+       IPPROTO_HOPOPTS                  = 0x0
+       IPPROTO_ICMP                     = 0x1
+       IPPROTO_ICMPV6                   = 0x3a
+       IPPROTO_IDP                      = 0x16
+       IPPROTO_IGMP                     = 0x2
+       IPPROTO_IP                       = 0x0
+       IPPROTO_IPIP                     = 0x4
+       IPPROTO_IPV6                     = 0x29
+       IPPROTO_MTP                      = 0x5c
+       IPPROTO_NONE                     = 0x3b
+       IPPROTO_PIM                      = 0x67
+       IPPROTO_PUP                      = 0xc
+       IPPROTO_RAW                      = 0xff
+       IPPROTO_ROUTING                  = 0x2b
+       IPPROTO_RSVP                     = 0x2e
+       IPPROTO_SCTP                     = 0x84
+       IPPROTO_TCP                      = 0x6
+       IPPROTO_TP                       = 0x1d
+       IPPROTO_UDP                      = 0x11
+       IPPROTO_UDPLITE                  = 0x88
+       IPV6_2292DSTOPTS                 = 0x4
+       IPV6_2292HOPLIMIT                = 0x8
+       IPV6_2292HOPOPTS                 = 0x3
+       IPV6_2292PKTINFO                 = 0x2
+       IPV6_2292PKTOPTIONS              = 0x6
+       IPV6_2292RTHDR                   = 0x5
+       IPV6_ADDRFORM                    = 0x1
+       IPV6_ADD_MEMBERSHIP              = 0x14
+       IPV6_AUTHHDR                     = 0xa
+       IPV6_CHECKSUM                    = 0x7
+       IPV6_DROP_MEMBERSHIP             = 0x15
+       IPV6_DSTOPTS                     = 0x3b
+       IPV6_HOPLIMIT                    = 0x34
+       IPV6_HOPOPTS                     = 0x36
+       IPV6_IPSEC_POLICY                = 0x22
+       IPV6_JOIN_ANYCAST                = 0x1b
+       IPV6_JOIN_GROUP                  = 0x14
+       IPV6_LEAVE_ANYCAST               = 0x1c
+       IPV6_LEAVE_GROUP                 = 0x15
+       IPV6_MTU                         = 0x18
+       IPV6_MTU_DISCOVER                = 0x17
+       IPV6_MULTICAST_HOPS              = 0x12
+       IPV6_MULTICAST_IF                = 0x11
+       IPV6_MULTICAST_LOOP              = 0x13
+       IPV6_NEXTHOP                     = 0x9
+       IPV6_PKTINFO                     = 0x32
+       IPV6_PMTUDISC_DO                 = 0x2
+       IPV6_PMTUDISC_DONT               = 0x0
+       IPV6_PMTUDISC_PROBE              = 0x3
+       IPV6_PMTUDISC_WANT               = 0x1
+       IPV6_RECVDSTOPTS                 = 0x3a
+       IPV6_RECVERR                     = 0x19
+       IPV6_RECVHOPLIMIT                = 0x33
+       IPV6_RECVHOPOPTS                 = 0x35
+       IPV6_RECVPKTINFO                 = 0x31
+       IPV6_RECVRTHDR                   = 0x38
+       IPV6_RECVTCLASS                  = 0x42
+       IPV6_ROUTER_ALERT                = 0x16
+       IPV6_RTHDR                       = 0x39
+       IPV6_RTHDRDSTOPTS                = 0x37
+       IPV6_RTHDR_LOOSE                 = 0x0
+       IPV6_RTHDR_STRICT                = 0x1
+       IPV6_RTHDR_TYPE_0                = 0x0
+       IPV6_RXDSTOPTS                   = 0x3b
+       IPV6_RXHOPOPTS                   = 0x36
+       IPV6_TCLASS                      = 0x43
+       IPV6_UNICAST_HOPS                = 0x10
+       IPV6_V6ONLY                      = 0x1a
+       IPV6_XFRM_POLICY                 = 0x23
+       IP_ADD_MEMBERSHIP                = 0x23
+       IP_ADD_SOURCE_MEMBERSHIP         = 0x27
+       IP_BLOCK_SOURCE                  = 0x26
+       IP_DEFAULT_MULTICAST_LOOP        = 0x1
+       IP_DEFAULT_MULTICAST_TTL         = 0x1
+       IP_DF                            = 0x4000
+       IP_DROP_MEMBERSHIP               = 0x24
+       IP_DROP_SOURCE_MEMBERSHIP        = 0x28
+       IP_FREEBIND                      = 0xf
+       IP_HDRINCL                       = 0x3
+       IP_IPSEC_POLICY                  = 0x10
+       IP_MAXPACKET                     = 0xffff
+       IP_MAX_MEMBERSHIPS               = 0x14
+       IP_MF                            = 0x2000
+       IP_MINTTL                        = 0x15
+       IP_MSFILTER                      = 0x29
+       IP_MSS                           = 0x240
+       IP_MTU                           = 0xe
+       IP_MTU_DISCOVER                  = 0xa
+       IP_MULTICAST_ALL                 = 0x31
+       IP_MULTICAST_IF                  = 0x20
+       IP_MULTICAST_LOOP                = 0x22
+       IP_MULTICAST_TTL                 = 0x21
+       IP_OFFMASK                       = 0x1fff
+       IP_OPTIONS                       = 0x4
+       IP_ORIGDSTADDR                   = 0x14
+       IP_PASSSEC                       = 0x12
+       IP_PKTINFO                       = 0x8
+       IP_PKTOPTIONS                    = 0x9
+       IP_PMTUDISC                      = 0xa
+       IP_PMTUDISC_DO                   = 0x2
+       IP_PMTUDISC_DONT                 = 0x0
+       IP_PMTUDISC_PROBE                = 0x3
+       IP_PMTUDISC_WANT                 = 0x1
+       IP_RECVERR                       = 0xb
+       IP_RECVOPTS                      = 0x6
+       IP_RECVORIGDSTADDR               = 0x14
+       IP_RECVRETOPTS                   = 0x7
+       IP_RECVTOS                       = 0xd
+       IP_RECVTTL                       = 0xc
+       IP_RETOPTS                       = 0x7
+       IP_RF                            = 0x8000
+       IP_ROUTER_ALERT                  = 0x5
+       IP_TOS                           = 0x1
+       IP_TRANSPARENT                   = 0x13
+       IP_TTL                           = 0x2
+       IP_UNBLOCK_SOURCE                = 0x25
+       IP_UNICAST_IF                    = 0x32
+       IP_XFRM_POLICY                   = 0x11
+       ISIG                             = 0x80
+       ISTRIP                           = 0x20
+       IUTF8                            = 0x4000
+       IXANY                            = 0x800
+       IXOFF                            = 0x400
+       IXON                             = 0x200
+       LINUX_REBOOT_CMD_CAD_OFF         = 0x0
+       LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
+       LINUX_REBOOT_CMD_HALT            = 0xcdef0123
+       LINUX_REBOOT_CMD_KEXEC           = 0x45584543
+       LINUX_REBOOT_CMD_POWER_OFF       = 0x4321fedc
+       LINUX_REBOOT_CMD_RESTART         = 0x1234567
+       LINUX_REBOOT_CMD_RESTART2        = 0xa1b2c3d4
+       LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
+       LINUX_REBOOT_MAGIC1              = 0xfee1dead
+       LINUX_REBOOT_MAGIC2              = 0x28121969
+       LOCK_EX                          = 0x2
+       LOCK_NB                          = 0x4
+       LOCK_SH                          = 0x1
+       LOCK_UN                          = 0x8
+       MADV_DODUMP                      = 0x11
+       MADV_DOFORK                      = 0xb
+       MADV_DONTDUMP                    = 0x10
+       MADV_DONTFORK                    = 0xa
+       MADV_DONTNEED                    = 0x4
+       MADV_HUGEPAGE                    = 0xe
+       MADV_HWPOISON                    = 0x64
+       MADV_MERGEABLE                   = 0xc
+       MADV_NOHUGEPAGE                  = 0xf
+       MADV_NORMAL                      = 0x0
+       MADV_RANDOM                      = 0x1
+       MADV_REMOVE                      = 0x9
+       MADV_SEQUENTIAL                  = 0x2
+       MADV_UNMERGEABLE                 = 0xd
+       MADV_WILLNEED                    = 0x3
+       MAP_ANON                         = 0x20
+       MAP_ANONYMOUS                    = 0x20
+       MAP_DENYWRITE                    = 0x800
+       MAP_EXECUTABLE                   = 0x1000
+       MAP_FILE                         = 0x0
+       MAP_FIXED                        = 0x10
+       MAP_GROWSDOWN                    = 0x100
+       MAP_HUGETLB                      = 0x40000
+       MAP_LOCKED                       = 0x80
+       MAP_NONBLOCK                     = 0x10000
+       MAP_NORESERVE                    = 0x40
+       MAP_POPULATE                     = 0x8000
+       MAP_PRIVATE                      = 0x2
+       MAP_SHARED                       = 0x1
+       MAP_STACK                        = 0x20000
+       MAP_TYPE                         = 0xf
+       MCL_CURRENT                      = 0x2000
+       MCL_FUTURE                       = 0x4000
+       MNT_DETACH                       = 0x2
+       MNT_EXPIRE                       = 0x4
+       MNT_FORCE                        = 0x1
+       MSG_CMSG_CLOEXEC                 = 0x40000000
+       MSG_CONFIRM                      = 0x800
+       MSG_CTRUNC                       = 0x8
+       MSG_DONTROUTE                    = 0x4
+       MSG_DONTWAIT                     = 0x40
+       MSG_EOR                          = 0x80
+       MSG_ERRQUEUE                     = 0x2000
+       MSG_FASTOPEN                     = 0x20000000
+       MSG_FIN                          = 0x200
+       MSG_MORE                         = 0x8000
+       MSG_NOSIGNAL                     = 0x4000
+       MSG_OOB                          = 0x1
+       MSG_PEEK                         = 0x2
+       MSG_PROXY                        = 0x10
+       MSG_RST                          = 0x1000
+       MSG_SYN                          = 0x400
+       MSG_TRUNC                        = 0x20
+       MSG_TRYHARD                      = 0x4
+       MSG_WAITALL                      = 0x100
+       MSG_WAITFORONE                   = 0x10000
+       MS_ACTIVE                        = 0x40000000
+       MS_ASYNC                         = 0x1
+       MS_BIND                          = 0x1000
+       MS_DIRSYNC                       = 0x80
+       MS_INVALIDATE                    = 0x2
+       MS_I_VERSION                     = 0x800000
+       MS_KERNMOUNT                     = 0x400000
+       MS_MANDLOCK                      = 0x40
+       MS_MGC_MSK                       = 0xffff0000
+       MS_MGC_VAL                       = 0xc0ed0000
+       MS_MOVE                          = 0x2000
+       MS_NOATIME                       = 0x400
+       MS_NODEV                         = 0x4
+       MS_NODIRATIME                    = 0x800
+       MS_NOEXEC                        = 0x8
+       MS_NOSUID                        = 0x2
+       MS_NOUSER                        = -0x80000000
+       MS_POSIXACL                      = 0x10000
+       MS_PRIVATE                       = 0x40000
+       MS_RDONLY                        = 0x1
+       MS_REC                           = 0x4000
+       MS_RELATIME                      = 0x200000
+       MS_REMOUNT                       = 0x20
+       MS_RMT_MASK                      = 0x800051
+       MS_SHARED                        = 0x100000
+       MS_SILENT                        = 0x8000
+       MS_SLAVE                         = 0x80000
+       MS_STRICTATIME                   = 0x1000000
+       MS_SYNC                          = 0x4
+       MS_SYNCHRONOUS                   = 0x10
+       MS_UNBINDABLE                    = 0x20000
+       NAME_MAX                         = 0xff
+       NETLINK_ADD_MEMBERSHIP           = 0x1
+       NETLINK_AUDIT                    = 0x9
+       NETLINK_BROADCAST_ERROR          = 0x4
+       NETLINK_CONNECTOR                = 0xb
+       NETLINK_CRYPTO                   = 0x15
+       NETLINK_DNRTMSG                  = 0xe
+       NETLINK_DROP_MEMBERSHIP          = 0x2
+       NETLINK_ECRYPTFS                 = 0x13
+       NETLINK_FIB_LOOKUP               = 0xa
+       NETLINK_FIREWALL                 = 0x3
+       NETLINK_GENERIC                  = 0x10
+       NETLINK_INET_DIAG                = 0x4
+       NETLINK_IP6_FW                   = 0xd
+       NETLINK_ISCSI                    = 0x8
+       NETLINK_KOBJECT_UEVENT           = 0xf
+       NETLINK_NETFILTER                = 0xc
+       NETLINK_NFLOG                    = 0x5
+       NETLINK_NO_ENOBUFS               = 0x5
+       NETLINK_PKTINFO                  = 0x3
+       NETLINK_RDMA                     = 0x14
+       NETLINK_ROUTE                    = 0x0
+       NETLINK_RX_RING                  = 0x6
+       NETLINK_SCSITRANSPORT            = 0x12
+       NETLINK_SELINUX                  = 0x7
+       NETLINK_SOCK_DIAG                = 0x4
+       NETLINK_TX_RING                  = 0x7
+       NETLINK_UNUSED                   = 0x1
+       NETLINK_USERSOCK                 = 0x2
+       NETLINK_XFRM                     = 0x6
+       NLA_ALIGNTO                      = 0x4
+       NLA_F_NESTED                     = 0x8000
+       NLA_F_NET_BYTEORDER              = 0x4000
+       NLA_HDRLEN                       = 0x4
+       NLMSG_ALIGNTO                    = 0x4
+       NLMSG_DONE                       = 0x3
+       NLMSG_ERROR                      = 0x2
+       NLMSG_HDRLEN                     = 0x10
+       NLMSG_MIN_TYPE                   = 0x10
+       NLMSG_NOOP                       = 0x1
+       NLMSG_OVERRUN                    = 0x4
+       NLM_F_ACK                        = 0x4
+       NLM_F_APPEND                     = 0x800
+       NLM_F_ATOMIC                     = 0x400
+       NLM_F_CREATE                     = 0x400
+       NLM_F_DUMP                       = 0x300
+       NLM_F_DUMP_INTR                  = 0x10
+       NLM_F_ECHO                       = 0x8
+       NLM_F_EXCL                       = 0x200
+       NLM_F_MATCH                      = 0x200
+       NLM_F_MULTI                      = 0x2
+       NLM_F_REPLACE                    = 0x100
+       NLM_F_REQUEST                    = 0x1
+       NLM_F_ROOT                       = 0x100
+       NOFLSH                           = 0x80000000
+       OCRNL                            = 0x8
+       OFDEL                            = 0x80
+       OFILL                            = 0x40
+       ONLCR                            = 0x2
+       ONLRET                           = 0x20
+       ONOCR                            = 0x10
+       OPOST                            = 0x1
+       O_ACCMODE                        = 0x3
+       O_APPEND                         = 0x400
+       O_ASYNC                          = 0x2000
+       O_CLOEXEC                        = 0x80000
+       O_CREAT                          = 0x40
+       O_DIRECT                         = 0x20000
+       O_DIRECTORY                      = 0x4000
+       O_DSYNC                          = 0x1000
+       O_EXCL                           = 0x80
+       O_FSYNC                          = 0x101000
+       O_LARGEFILE                      = 0x0
+       O_NDELAY                         = 0x800
+       O_NOATIME                        = 0x40000
+       O_NOCTTY                         = 0x100
+       O_NOFOLLOW                       = 0x8000
+       O_NONBLOCK                       = 0x800
+       O_PATH                           = 0x200000
+       O_RDONLY                         = 0x0
+       O_RDWR                           = 0x2
+       O_RSYNC                          = 0x101000
+       O_SYNC                           = 0x101000
+       O_TRUNC                          = 0x200
+       O_WRONLY                         = 0x1
+       PACKET_ADD_MEMBERSHIP            = 0x1
+       PACKET_AUXDATA                   = 0x8
+       PACKET_BROADCAST                 = 0x1
+       PACKET_COPY_THRESH               = 0x7
+       PACKET_DROP_MEMBERSHIP           = 0x2
+       PACKET_FANOUT                    = 0x12
+       PACKET_FANOUT_CPU                = 0x2
+       PACKET_FANOUT_FLAG_DEFRAG        = 0x8000
+       PACKET_FANOUT_FLAG_ROLLOVER      = 0x1000
+       PACKET_FANOUT_HASH               = 0x0
+       PACKET_FANOUT_LB                 = 0x1
+       PACKET_FANOUT_RND                = 0x4
+       PACKET_FANOUT_ROLLOVER           = 0x3
+       PACKET_FASTROUTE                 = 0x6
+       PACKET_HDRLEN                    = 0xb
+       PACKET_HOST                      = 0x0
+       PACKET_LOOPBACK                  = 0x5
+       PACKET_LOSS                      = 0xe
+       PACKET_MR_ALLMULTI               = 0x2
+       PACKET_MR_MULTICAST              = 0x0
+       PACKET_MR_PROMISC                = 0x1
+       PACKET_MR_UNICAST                = 0x3
+       PACKET_MULTICAST                 = 0x2
+       PACKET_ORIGDEV                   = 0x9
+       PACKET_OTHERHOST                 = 0x3
+       PACKET_OUTGOING                  = 0x4
+       PACKET_RECV_OUTPUT               = 0x3
+       PACKET_RESERVE                   = 0xc
+       PACKET_RX_RING                   = 0x5
+       PACKET_STATISTICS                = 0x6
+       PACKET_TIMESTAMP                 = 0x11
+       PACKET_TX_HAS_OFF                = 0x13
+       PACKET_TX_RING                   = 0xd
+       PACKET_TX_TIMESTAMP              = 0x10
+       PACKET_VERSION                   = 0xa
+       PACKET_VNET_HDR                  = 0xf
+       PARENB                           = 0x1000
+       PARITY_CRC16_PR0                 = 0x2
+       PARITY_CRC16_PR0_CCITT           = 0x4
+       PARITY_CRC16_PR1                 = 0x3
+       PARITY_CRC16_PR1_CCITT           = 0x5
+       PARITY_CRC32_PR0_CCITT           = 0x6
+       PARITY_CRC32_PR1_CCITT           = 0x7
+       PARITY_DEFAULT                   = 0x0
+       PARITY_NONE                      = 0x1
+       PARMRK                           = 0x8
+       PARODD                           = 0x2000
+       PENDIN                           = 0x20000000
+       PRIO_PGRP                        = 0x1
+       PRIO_PROCESS                     = 0x0
+       PRIO_USER                        = 0x2
+       PROT_EXEC                        = 0x4
+       PROT_GROWSDOWN                   = 0x1000000
+       PROT_GROWSUP                     = 0x2000000
+       PROT_NONE                        = 0x0
+       PROT_READ                        = 0x1
+       PROT_SAO                         = 0x10
+       PROT_WRITE                       = 0x2
+       PR_CAPBSET_DROP                  = 0x18
+       PR_CAPBSET_READ                  = 0x17
+       PR_ENDIAN_BIG                    = 0x0
+       PR_ENDIAN_LITTLE                 = 0x1
+       PR_ENDIAN_PPC_LITTLE             = 0x2
+       PR_FPEMU_NOPRINT                 = 0x1
+       PR_FPEMU_SIGFPE                  = 0x2
+       PR_FP_EXC_ASYNC                  = 0x2
+       PR_FP_EXC_DISABLED               = 0x0
+       PR_FP_EXC_DIV                    = 0x10000
+       PR_FP_EXC_INV                    = 0x100000
+       PR_FP_EXC_NONRECOV               = 0x1
+       PR_FP_EXC_OVF                    = 0x20000
+       PR_FP_EXC_PRECISE                = 0x3
+       PR_FP_EXC_RES                    = 0x80000
+       PR_FP_EXC_SW_ENABLE              = 0x80
+       PR_FP_EXC_UND                    = 0x40000
+       PR_GET_CHILD_SUBREAPER           = 0x25
+       PR_GET_DUMPABLE                  = 0x3
+       PR_GET_ENDIAN                    = 0x13
+       PR_GET_FPEMU                     = 0x9
+       PR_GET_FPEXC                     = 0xb
+       PR_GET_KEEPCAPS                  = 0x7
+       PR_GET_NAME                      = 0x10
+       PR_GET_NO_NEW_PRIVS              = 0x27
+       PR_GET_PDEATHSIG                 = 0x2
+       PR_GET_SECCOMP                   = 0x15
+       PR_GET_SECUREBITS                = 0x1b
+       PR_GET_TID_ADDRESS               = 0x28
+       PR_GET_TIMERSLACK                = 0x1e
+       PR_GET_TIMING                    = 0xd
+       PR_GET_TSC                       = 0x19
+       PR_GET_UNALIGN                   = 0x5
+       PR_MCE_KILL                      = 0x21
+       PR_MCE_KILL_CLEAR                = 0x0
+       PR_MCE_KILL_DEFAULT              = 0x2
+       PR_MCE_KILL_EARLY                = 0x1
+       PR_MCE_KILL_GET                  = 0x22
+       PR_MCE_KILL_LATE                 = 0x0
+       PR_MCE_KILL_SET                  = 0x1
+       PR_SET_CHILD_SUBREAPER           = 0x24
+       PR_SET_DUMPABLE                  = 0x4
+       PR_SET_ENDIAN                    = 0x14
+       PR_SET_FPEMU                     = 0xa
+       PR_SET_FPEXC                     = 0xc
+       PR_SET_KEEPCAPS                  = 0x8
+       PR_SET_MM                        = 0x23
+       PR_SET_MM_ARG_END                = 0x9
+       PR_SET_MM_ARG_START              = 0x8
+       PR_SET_MM_AUXV                   = 0xc
+       PR_SET_MM_BRK                    = 0x7
+       PR_SET_MM_END_CODE               = 0x2
+       PR_SET_MM_END_DATA               = 0x4
+       PR_SET_MM_ENV_END                = 0xb
+       PR_SET_MM_ENV_START              = 0xa
+       PR_SET_MM_EXE_FILE               = 0xd
+       PR_SET_MM_START_BRK              = 0x6
+       PR_SET_MM_START_CODE             = 0x1
+       PR_SET_MM_START_DATA             = 0x3
+       PR_SET_MM_START_STACK            = 0x5
+       PR_SET_NAME                      = 0xf
+       PR_SET_NO_NEW_PRIVS              = 0x26
+       PR_SET_PDEATHSIG                 = 0x1
+       PR_SET_PTRACER                   = 0x59616d61
+       PR_SET_PTRACER_ANY               = -0x1
+       PR_SET_SECCOMP                   = 0x16
+       PR_SET_SECUREBITS                = 0x1c
+       PR_SET_TIMERSLACK                = 0x1d
+       PR_SET_TIMING                    = 0xe
+       PR_SET_TSC                       = 0x1a
+       PR_SET_UNALIGN                   = 0x6
+       PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+       PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+       PR_TIMING_STATISTICAL            = 0x0
+       PR_TIMING_TIMESTAMP              = 0x1
+       PR_TSC_ENABLE                    = 0x1
+       PR_TSC_SIGSEGV                   = 0x2
+       PR_UNALIGN_NOPRINT               = 0x1
+       PR_UNALIGN_SIGBUS                = 0x2
+       PTRACE_ATTACH                    = 0x10
+       PTRACE_CONT                      = 0x7
+       PTRACE_DETACH                    = 0x11
+       PTRACE_EVENT_CLONE               = 0x3
+       PTRACE_EVENT_EXEC                = 0x4
+       PTRACE_EVENT_EXIT                = 0x6
+       PTRACE_EVENT_FORK                = 0x1
+       PTRACE_EVENT_SECCOMP             = 0x7
+       PTRACE_EVENT_STOP                = 0x80
+       PTRACE_EVENT_VFORK               = 0x2
+       PTRACE_EVENT_VFORK_DONE          = 0x5
+       PTRACE_GETEVENTMSG               = 0x4201
+       PTRACE_GETEVRREGS                = 0x14
+       PTRACE_GETFPREGS                 = 0xe
+       PTRACE_GETREGS                   = 0xc
+       PTRACE_GETREGS64                 = 0x16
+       PTRACE_GETREGSET                 = 0x4204
+       PTRACE_GETSIGINFO                = 0x4202
+       PTRACE_GETSIGMASK                = 0x420a
+       PTRACE_GETVRREGS                 = 0x12
+       PTRACE_GETVSRREGS                = 0x1b
+       PTRACE_GET_DEBUGREG              = 0x19
+       PTRACE_INTERRUPT                 = 0x4207
+       PTRACE_KILL                      = 0x8
+       PTRACE_LISTEN                    = 0x4208
+       PTRACE_O_EXITKILL                = 0x100000
+       PTRACE_O_MASK                    = 0x1000ff
+       PTRACE_O_TRACECLONE              = 0x8
+       PTRACE_O_TRACEEXEC               = 0x10
+       PTRACE_O_TRACEEXIT               = 0x40
+       PTRACE_O_TRACEFORK               = 0x2
+       PTRACE_O_TRACESECCOMP            = 0x80
+       PTRACE_O_TRACESYSGOOD            = 0x1
+       PTRACE_O_TRACEVFORK              = 0x4
+       PTRACE_O_TRACEVFORKDONE          = 0x20
+       PTRACE_PEEKDATA                  = 0x2
+       PTRACE_PEEKSIGINFO               = 0x4209
+       PTRACE_PEEKSIGINFO_SHARED        = 0x1
+       PTRACE_PEEKTEXT                  = 0x1
+       PTRACE_PEEKUSR                   = 0x3
+       PTRACE_POKEDATA                  = 0x5
+       PTRACE_POKETEXT                  = 0x4
+       PTRACE_POKEUSR                   = 0x6
+       PTRACE_SEIZE                     = 0x4206
+       PTRACE_SETEVRREGS                = 0x15
+       PTRACE_SETFPREGS                 = 0xf
+       PTRACE_SETOPTIONS                = 0x4200
+       PTRACE_SETREGS                   = 0xd
+       PTRACE_SETREGS64                 = 0x17
+       PTRACE_SETREGSET                 = 0x4205
+       PTRACE_SETSIGINFO                = 0x4203
+       PTRACE_SETSIGMASK                = 0x420b
+       PTRACE_SETVRREGS                 = 0x13
+       PTRACE_SETVSRREGS                = 0x1c
+       PTRACE_SET_DEBUGREG              = 0x1a
+       PTRACE_SINGLEBLOCK               = 0x100
+       PTRACE_SINGLESTEP                = 0x9
+       PTRACE_SYSCALL                   = 0x18
+       PTRACE_TRACEME                   = 0x0
+       PT_CCR                           = 0x26
+       PT_CTR                           = 0x23
+       PT_DAR                           = 0x29
+       PT_DSCR                          = 0x2c
+       PT_DSISR                         = 0x2a
+       PT_FPR0                          = 0x30
+       PT_FPSCR                         = 0x50
+       PT_LNK                           = 0x24
+       PT_MSR                           = 0x21
+       PT_NIP                           = 0x20
+       PT_ORIG_R3                       = 0x22
+       PT_R0                            = 0x0
+       PT_R1                            = 0x1
+       PT_R10                           = 0xa
+       PT_R11                           = 0xb
+       PT_R12                           = 0xc
+       PT_R13                           = 0xd
+       PT_R14                           = 0xe
+       PT_R15                           = 0xf
+       PT_R16                           = 0x10
+       PT_R17                           = 0x11
+       PT_R18                           = 0x12
+       PT_R19                           = 0x13
+       PT_R2                            = 0x2
+       PT_R20                           = 0x14
+       PT_R21                           = 0x15
+       PT_R22                           = 0x16
+       PT_R23                           = 0x17
+       PT_R24                           = 0x18
+       PT_R25                           = 0x19
+       PT_R26                           = 0x1a
+       PT_R27                           = 0x1b
+       PT_R28                           = 0x1c
+       PT_R29                           = 0x1d
+       PT_R3                            = 0x3
+       PT_R30                           = 0x1e
+       PT_R31                           = 0x1f
+       PT_R4                            = 0x4
+       PT_R5                            = 0x5
+       PT_R6                            = 0x6
+       PT_R7                            = 0x7
+       PT_R8                            = 0x8
+       PT_R9                            = 0x9
+       PT_REGS_COUNT                    = 0x2c
+       PT_RESULT                        = 0x2b
+       PT_SOFTE                         = 0x27
+       PT_TRAP                          = 0x28
+       PT_VR0                           = 0x52
+       PT_VRSAVE                        = 0x94
+       PT_VSCR                          = 0x93
+       PT_VSR0                          = 0x96
+       PT_VSR31                         = 0xd4
+       PT_XER                           = 0x25
+       RLIMIT_AS                        = 0x9
+       RLIMIT_CORE                      = 0x4
+       RLIMIT_CPU                       = 0x0
+       RLIMIT_DATA                      = 0x2
+       RLIMIT_FSIZE                     = 0x1
+       RLIMIT_NOFILE                    = 0x7
+       RLIMIT_STACK                     = 0x3
+       RLIM_INFINITY                    = -0x1
+       RTAX_ADVMSS                      = 0x8
+       RTAX_CWND                        = 0x7
+       RTAX_FEATURES                    = 0xc
+       RTAX_FEATURE_ALLFRAG             = 0x8
+       RTAX_FEATURE_ECN                 = 0x1
+       RTAX_FEATURE_SACK                = 0x2
+       RTAX_FEATURE_TIMESTAMP           = 0x4
+       RTAX_HOPLIMIT                    = 0xa
+       RTAX_INITCWND                    = 0xb
+       RTAX_INITRWND                    = 0xe
+       RTAX_LOCK                        = 0x1
+       RTAX_MAX                         = 0xf
+       RTAX_MTU                         = 0x2
+       RTAX_QUICKACK                    = 0xf
+       RTAX_REORDERING                  = 0x9
+       RTAX_RTO_MIN                     = 0xd
+       RTAX_RTT                         = 0x4
+       RTAX_RTTVAR                      = 0x5
+       RTAX_SSTHRESH                    = 0x6
+       RTAX_UNSPEC                      = 0x0
+       RTAX_WINDOW                      = 0x3
+       RTA_ALIGNTO                      = 0x4
+       RTA_MAX                          = 0x11
+       RTCF_DIRECTSRC                   = 0x4000000
+       RTCF_DOREDIRECT                  = 0x1000000
+       RTCF_LOG                         = 0x2000000
+       RTCF_MASQ                        = 0x400000
+       RTCF_NAT                         = 0x800000
+       RTCF_VALVE                       = 0x200000
+       RTF_ADDRCLASSMASK                = 0xf8000000
+       RTF_ADDRCONF                     = 0x40000
+       RTF_ALLONLINK                    = 0x20000
+       RTF_BROADCAST                    = 0x10000000
+       RTF_CACHE                        = 0x1000000
+       RTF_DEFAULT                      = 0x10000
+       RTF_DYNAMIC                      = 0x10
+       RTF_FLOW                         = 0x2000000
+       RTF_GATEWAY                      = 0x2
+       RTF_HOST                         = 0x4
+       RTF_INTERFACE                    = 0x40000000
+       RTF_IRTT                         = 0x100
+       RTF_LINKRT                       = 0x100000
+       RTF_LOCAL                        = 0x80000000
+       RTF_MODIFIED                     = 0x20
+       RTF_MSS                          = 0x40
+       RTF_MTU                          = 0x40
+       RTF_MULTICAST                    = 0x20000000
+       RTF_NAT                          = 0x8000000
+       RTF_NOFORWARD                    = 0x1000
+       RTF_NONEXTHOP                    = 0x200000
+       RTF_NOPMTUDISC                   = 0x4000
+       RTF_POLICY                       = 0x4000000
+       RTF_REINSTATE                    = 0x8
+       RTF_REJECT                       = 0x200
+       RTF_STATIC                       = 0x400
+       RTF_THROW                        = 0x2000
+       RTF_UP                           = 0x1
+       RTF_WINDOW                       = 0x80
+       RTF_XRESOLVE                     = 0x800
+       RTM_BASE                         = 0x10
+       RTM_DELACTION                    = 0x31
+       RTM_DELADDR                      = 0x15
+       RTM_DELADDRLABEL                 = 0x49
+       RTM_DELLINK                      = 0x11
+       RTM_DELMDB                       = 0x55
+       RTM_DELNEIGH                     = 0x1d
+       RTM_DELQDISC                     = 0x25
+       RTM_DELROUTE                     = 0x19
+       RTM_DELRULE                      = 0x21
+       RTM_DELTCLASS                    = 0x29
+       RTM_DELTFILTER                   = 0x2d
+       RTM_F_CLONED                     = 0x200
+       RTM_F_EQUALIZE                   = 0x400
+       RTM_F_NOTIFY                     = 0x100
+       RTM_F_PREFIX                     = 0x800
+       RTM_GETACTION                    = 0x32
+       RTM_GETADDR                      = 0x16
+       RTM_GETADDRLABEL                 = 0x4a
+       RTM_GETANYCAST                   = 0x3e
+       RTM_GETDCB                       = 0x4e
+       RTM_GETLINK                      = 0x12
+       RTM_GETMDB                       = 0x56
+       RTM_GETMULTICAST                 = 0x3a
+       RTM_GETNEIGH                     = 0x1e
+       RTM_GETNEIGHTBL                  = 0x42
+       RTM_GETNETCONF                   = 0x52
+       RTM_GETQDISC                     = 0x26
+       RTM_GETROUTE                     = 0x1a
+       RTM_GETRULE                      = 0x22
+       RTM_GETTCLASS                    = 0x2a
+       RTM_GETTFILTER                   = 0x2e
+       RTM_MAX                          = 0x57
+       RTM_NEWACTION                    = 0x30
+       RTM_NEWADDR                      = 0x14
+       RTM_NEWADDRLABEL                 = 0x48
+       RTM_NEWLINK                      = 0x10
+       RTM_NEWMDB                       = 0x54
+       RTM_NEWNDUSEROPT                 = 0x44
+       RTM_NEWNEIGH                     = 0x1c
+       RTM_NEWNEIGHTBL                  = 0x40
+       RTM_NEWNETCONF                   = 0x50
+       RTM_NEWPREFIX                    = 0x34
+       RTM_NEWQDISC                     = 0x24
+       RTM_NEWROUTE                     = 0x18
+       RTM_NEWRULE                      = 0x20
+       RTM_NEWTCLASS                    = 0x28
+       RTM_NEWTFILTER                   = 0x2c
+       RTM_NR_FAMILIES                  = 0x12
+       RTM_NR_MSGTYPES                  = 0x48
+       RTM_SETDCB                       = 0x4f
+       RTM_SETLINK                      = 0x13
+       RTM_SETNEIGHTBL                  = 0x43
+       RTNH_ALIGNTO                     = 0x4
+       RTNH_F_DEAD                      = 0x1
+       RTNH_F_ONLINK                    = 0x4
+       RTNH_F_PERVASIVE                 = 0x2
+       RTN_MAX                          = 0xb
+       RTPROT_BIRD                      = 0xc
+       RTPROT_BOOT                      = 0x3
+       RTPROT_DHCP                      = 0x10
+       RTPROT_DNROUTED                  = 0xd
+       RTPROT_GATED                     = 0x8
+       RTPROT_KERNEL                    = 0x2
+       RTPROT_MROUTED                   = 0x11
+       RTPROT_MRT                       = 0xa
+       RTPROT_NTK                       = 0xf
+       RTPROT_RA                        = 0x9
+       RTPROT_REDIRECT                  = 0x1
+       RTPROT_STATIC                    = 0x4
+       RTPROT_UNSPEC                    = 0x0
+       RTPROT_XORP                      = 0xe
+       RTPROT_ZEBRA                     = 0xb
+       RT_CLASS_DEFAULT                 = 0xfd
+       RT_CLASS_LOCAL                   = 0xff
+       RT_CLASS_MAIN                    = 0xfe
+       RT_CLASS_MAX                     = 0xff
+       RT_CLASS_UNSPEC                  = 0x0
+       RUSAGE_CHILDREN                  = -0x1
+       RUSAGE_SELF                      = 0x0
+       RUSAGE_THREAD                    = 0x1
+       SCM_CREDENTIALS                  = 0x2
+       SCM_RIGHTS                       = 0x1
+       SCM_TIMESTAMP                    = 0x1d
+       SCM_TIMESTAMPING                 = 0x25
+       SCM_TIMESTAMPNS                  = 0x23
+       SCM_WIFI_STATUS                  = 0x29
+       SHUT_RD                          = 0x0
+       SHUT_RDWR                        = 0x2
+       SHUT_WR                          = 0x1
+       SIOCADDDLCI                      = 0x8980
+       SIOCADDMULTI                     = 0x8931
+       SIOCADDRT                        = 0x890b
+       SIOCATMARK                       = 0x8905
+       SIOCDARP                         = 0x8953
+       SIOCDELDLCI                      = 0x8981
+       SIOCDELMULTI                     = 0x8932
+       SIOCDELRT                        = 0x890c
+       SIOCDEVPRIVATE                   = 0x89f0
+       SIOCDIFADDR                      = 0x8936
+       SIOCDRARP                        = 0x8960
+       SIOCGARP                         = 0x8954
+       SIOCGIFADDR                      = 0x8915
+       SIOCGIFBR                        = 0x8940
+       SIOCGIFBRDADDR                   = 0x8919
+       SIOCGIFCONF                      = 0x8912
+       SIOCGIFCOUNT                     = 0x8938
+       SIOCGIFDSTADDR                   = 0x8917
+       SIOCGIFENCAP                     = 0x8925
+       SIOCGIFFLAGS                     = 0x8913
+       SIOCGIFHWADDR                    = 0x8927
+       SIOCGIFINDEX                     = 0x8933
+       SIOCGIFMAP                       = 0x8970
+       SIOCGIFMEM                       = 0x891f
+       SIOCGIFMETRIC                    = 0x891d
+       SIOCGIFMTU                       = 0x8921
+       SIOCGIFNAME                      = 0x8910
+       SIOCGIFNETMASK                   = 0x891b
+       SIOCGIFPFLAGS                    = 0x8935
+       SIOCGIFSLAVE                     = 0x8929
+       SIOCGIFTXQLEN                    = 0x8942
+       SIOCGPGRP                        = 0x8904
+       SIOCGRARP                        = 0x8961
+       SIOCGSTAMP                       = 0x8906
+       SIOCGSTAMPNS                     = 0x8907
+       SIOCPROTOPRIVATE                 = 0x89e0
+       SIOCRTMSG                        = 0x890d
+       SIOCSARP                         = 0x8955
+       SIOCSIFADDR                      = 0x8916
+       SIOCSIFBR                        = 0x8941
+       SIOCSIFBRDADDR                   = 0x891a
+       SIOCSIFDSTADDR                   = 0x8918
+       SIOCSIFENCAP                     = 0x8926
+       SIOCSIFFLAGS                     = 0x8914
+       SIOCSIFHWADDR                    = 0x8924
+       SIOCSIFHWBROADCAST               = 0x8937
+       SIOCSIFLINK                      = 0x8911
+       SIOCSIFMAP                       = 0x8971
+       SIOCSIFMEM                       = 0x8920
+       SIOCSIFMETRIC                    = 0x891e
+       SIOCSIFMTU                       = 0x8922
+       SIOCSIFNAME                      = 0x8923
+       SIOCSIFNETMASK                   = 0x891c
+       SIOCSIFPFLAGS                    = 0x8934
+       SIOCSIFSLAVE                     = 0x8930
+       SIOCSIFTXQLEN                    = 0x8943
+       SIOCSPGRP                        = 0x8902
+       SIOCSRARP                        = 0x8962
+       SOCK_CLOEXEC                     = 0x80000
+       SOCK_DCCP                        = 0x6
+       SOCK_DGRAM                       = 0x2
+       SOCK_NONBLOCK                    = 0x800
+       SOCK_PACKET                      = 0xa
+       SOCK_RAW                         = 0x3
+       SOCK_RDM                         = 0x4
+       SOCK_SEQPACKET                   = 0x5
+       SOCK_STREAM                      = 0x1
+       SOL_AAL                          = 0x109
+       SOL_ATM                          = 0x108
+       SOL_DECNET                       = 0x105
+       SOL_ICMPV6                       = 0x3a
+       SOL_IP                           = 0x0
+       SOL_IPV6                         = 0x29
+       SOL_IRDA                         = 0x10a
+       SOL_PACKET                       = 0x107
+       SOL_RAW                          = 0xff
+       SOL_SOCKET                       = 0x1
+       SOL_TCP                          = 0x6
+       SOL_X25                          = 0x106
+       SOMAXCONN                        = 0x80
+       SO_ACCEPTCONN                    = 0x1e
+       SO_ATTACH_FILTER                 = 0x1a
+       SO_BINDTODEVICE                  = 0x19
+       SO_BROADCAST                     = 0x6
+       SO_BSDCOMPAT                     = 0xe
+       SO_BUSY_POLL                     = 0x2e
+       SO_DEBUG                         = 0x1
+       SO_DETACH_FILTER                 = 0x1b
+       SO_DOMAIN                        = 0x27
+       SO_DONTROUTE                     = 0x5
+       SO_ERROR                         = 0x4
+       SO_GET_FILTER                    = 0x1a
+       SO_KEEPALIVE                     = 0x9
+       SO_LINGER                        = 0xd
+       SO_LOCK_FILTER                   = 0x2c
+       SO_MARK                          = 0x24
+       SO_MAX_PACING_RATE               = 0x2f
+       SO_NOFCS                         = 0x2b
+       SO_NO_CHECK                      = 0xb
+       SO_OOBINLINE                     = 0xa
+       SO_PASSCRED                      = 0x14
+       SO_PASSSEC                       = 0x22
+       SO_PEEK_OFF                      = 0x2a
+       SO_PEERCRED                      = 0x15
+       SO_PEERNAME                      = 0x1c
+       SO_PEERSEC                       = 0x1f
+       SO_PRIORITY                      = 0xc
+       SO_PROTOCOL                      = 0x26
+       SO_RCVBUF                        = 0x8
+       SO_RCVBUFFORCE                   = 0x21
+       SO_RCVLOWAT                      = 0x10
+       SO_RCVTIMEO                      = 0x12
+       SO_REUSEADDR                     = 0x2
+       SO_REUSEPORT                     = 0xf
+       SO_RXQ_OVFL                      = 0x28
+       SO_SECURITY_AUTHENTICATION       = 0x16
+       SO_SECURITY_ENCRYPTION_NETWORK   = 0x18
+       SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
+       SO_SELECT_ERR_QUEUE              = 0x2d
+       SO_SNDBUF                        = 0x7
+       SO_SNDBUFFORCE                   = 0x20
+       SO_SNDLOWAT                      = 0x11
+       SO_SNDTIMEO                      = 0x13
+       SO_TIMESTAMP                     = 0x1d
+       SO_TIMESTAMPING                  = 0x25
+       SO_TIMESTAMPNS                   = 0x23
+       SO_TYPE                          = 0x3
+       SO_WIFI_STATUS                   = 0x29
+       S_BLKSIZE                        = 0x200
+       S_IEXEC                          = 0x40
+       S_IFBLK                          = 0x6000
+       S_IFCHR                          = 0x2000
+       S_IFDIR                          = 0x4000
+       S_IFIFO                          = 0x1000
+       S_IFLNK                          = 0xa000
+       S_IFMT                           = 0xf000
+       S_IFREG                          = 0x8000
+       S_IFSOCK                         = 0xc000
+       S_IREAD                          = 0x100
+       S_IRGRP                          = 0x20
+       S_IROTH                          = 0x4
+       S_IRUSR                          = 0x100
+       S_IRWXG                          = 0x38
+       S_IRWXO                          = 0x7
+       S_IRWXU                          = 0x1c0
+       S_ISGID                          = 0x400
+       S_ISUID                          = 0x800
+       S_ISVTX                          = 0x200
+       S_IWGRP                          = 0x10
+       S_IWOTH                          = 0x2
+       S_IWRITE                         = 0x80
+       S_IWUSR                          = 0x80
+       S_IXGRP                          = 0x8
+       S_IXOTH                          = 0x1
+       S_IXUSR                          = 0x40
+       TCFLSH                           = 0x2000741f
+       TCIFLUSH                         = 0x0
+       TCIOFLUSH                        = 0x2
+       TCOFLUSH                         = 0x1
+       TCP_CONGESTION                   = 0xd
+       TCP_CORK                         = 0x3
+       TCP_DEFER_ACCEPT                 = 0x9
+       TCP_INFO                         = 0xb
+       TCP_KEEPCNT                      = 0x6
+       TCP_KEEPIDLE                     = 0x4
+       TCP_KEEPINTVL                    = 0x5
+       TCP_LINGER2                      = 0x8
+       TCP_MAXSEG                       = 0x2
+       TCP_MAXWIN                       = 0xffff
+       TCP_MAX_WINSHIFT                 = 0xe
+       TCP_MD5SIG                       = 0xe
+       TCP_MD5SIG_MAXKEYLEN             = 0x50
+       TCP_MSS                          = 0x200
+       TCP_NODELAY                      = 0x1
+       TCP_QUICKACK                     = 0xc
+       TCP_SYNCNT                       = 0x7
+       TCP_WINDOW_CLAMP                 = 0xa
+       TCSAFLUSH                        = 0x2
+       TIOCCBRK                         = 0x5428
+       TIOCCONS                         = 0x541d
+       TIOCEXCL                         = 0x540c
+       TIOCGDEV                         = 0x40045432
+       TIOCGETC                         = 0x40067412
+       TIOCGETD                         = 0x5424
+       TIOCGETP                         = 0x40067408
+       TIOCGEXCL                        = 0x40045440
+       TIOCGICOUNT                      = 0x545d
+       TIOCGLCKTRMIOS                   = 0x5456
+       TIOCGLTC                         = 0x40067474
+       TIOCGPGRP                        = 0x40047477
+       TIOCGPKT                         = 0x40045438
+       TIOCGPTLCK                       = 0x40045439
+       TIOCGPTN                         = 0x40045430
+       TIOCGRS485                       = 0x542e
+       TIOCGSERIAL                      = 0x541e
+       TIOCGSID                         = 0x5429
+       TIOCGSOFTCAR                     = 0x5419
+       TIOCGWINSZ                       = 0x40087468
+       TIOCINQ                          = 0x4004667f
+       TIOCLINUX                        = 0x541c
+       TIOCMBIC                         = 0x5417
+       TIOCMBIS                         = 0x5416
+       TIOCMGET                         = 0x5415
+       TIOCMIWAIT                       = 0x545c
+       TIOCMSET                         = 0x5418
+       TIOCM_CAR                        = 0x40
+       TIOCM_CD                         = 0x40
+       TIOCM_CTS                        = 0x20
+       TIOCM_DSR                        = 0x100
+       TIOCM_DTR                        = 0x2
+       TIOCM_LE                         = 0x1
+       TIOCM_LOOP                       = 0x8000
+       TIOCM_OUT1                       = 0x2000
+       TIOCM_OUT2                       = 0x4000
+       TIOCM_RI                         = 0x80
+       TIOCM_RNG                        = 0x80
+       TIOCM_RTS                        = 0x4
+       TIOCM_SR                         = 0x10
+       TIOCM_ST                         = 0x8
+       TIOCNOTTY                        = 0x5422
+       TIOCNXCL                         = 0x540d
+       TIOCOUTQ                         = 0x40047473
+       TIOCPKT                          = 0x5420
+       TIOCPKT_DATA                     = 0x0
+       TIOCPKT_DOSTOP                   = 0x20
+       TIOCPKT_FLUSHREAD                = 0x1
+       TIOCPKT_FLUSHWRITE               = 0x2
+       TIOCPKT_IOCTL                    = 0x40
+       TIOCPKT_NOSTOP                   = 0x10
+       TIOCPKT_START                    = 0x8
+       TIOCPKT_STOP                     = 0x4
+       TIOCSBRK                         = 0x5427
+       TIOCSCTTY                        = 0x540e
+       TIOCSERCONFIG                    = 0x5453
+       TIOCSERGETLSR                    = 0x5459
+       TIOCSERGETMULTI                  = 0x545a
+       TIOCSERGSTRUCT                   = 0x5458
+       TIOCSERGWILD                     = 0x5454
+       TIOCSERSETMULTI                  = 0x545b
+       TIOCSERSWILD                     = 0x5455
+       TIOCSER_TEMT                     = 0x1
+       TIOCSETC                         = 0x80067411
+       TIOCSETD                         = 0x5423
+       TIOCSETN                         = 0x8006740a
+       TIOCSETP                         = 0x80067409
+       TIOCSIG                          = 0x80045436
+       TIOCSLCKTRMIOS                   = 0x5457
+       TIOCSLTC                         = 0x80067475
+       TIOCSPGRP                        = 0x80047476
+       TIOCSPTLCK                       = 0x80045431
+       TIOCSRS485                       = 0x542f
+       TIOCSSERIAL                      = 0x541f
+       TIOCSSOFTCAR                     = 0x541a
+       TIOCSTART                        = 0x2000746e
+       TIOCSTI                          = 0x5412
+       TIOCSTOP                         = 0x2000746f
+       TIOCSWINSZ                       = 0x80087467
+       TIOCVHANGUP                      = 0x5437
+       TOSTOP                           = 0x400000
+       TUNATTACHFILTER                  = 0x801054d5
+       TUNDETACHFILTER                  = 0x801054d6
+       TUNGETFEATURES                   = 0x400454cf
+       TUNGETFILTER                     = 0x401054db
+       TUNGETIFF                        = 0x400454d2
+       TUNGETSNDBUF                     = 0x400454d3
+       TUNGETVNETHDRSZ                  = 0x400454d7
+       TUNSETDEBUG                      = 0x800454c9
+       TUNSETGROUP                      = 0x800454ce
+       TUNSETIFF                        = 0x800454ca
+       TUNSETIFINDEX                    = 0x800454da
+       TUNSETLINK                       = 0x800454cd
+       TUNSETNOCSUM                     = 0x800454c8
+       TUNSETOFFLOAD                    = 0x800454d0
+       TUNSETOWNER                      = 0x800454cc
+       TUNSETPERSIST                    = 0x800454cb
+       TUNSETQUEUE                      = 0x800454d9
+       TUNSETSNDBUF                     = 0x800454d4
+       TUNSETTXFILTER                   = 0x800454d1
+       TUNSETVNETHDRSZ                  = 0x800454d8
+       VDISCARD                         = 0x10
+       VEOF                             = 0x4
+       VEOL                             = 0x6
+       VEOL2                            = 0x8
+       VERASE                           = 0x2
+       VINTR                            = 0x0
+       VKILL                            = 0x3
+       VLNEXT                           = 0xf
+       VMIN                             = 0x5
+       VQUIT                            = 0x1
+       VREPRINT                         = 0xb
+       VSTART                           = 0xd
+       VSTOP                            = 0xe
+       VSUSP                            = 0xc
+       VSWTC                            = 0x9
+       VT0                              = 0x0
+       VT1                              = 0x10000
+       VTDLY                            = 0x10000
+       VTIME                            = 0x7
+       VWERASE                          = 0xa
+       WALL                             = 0x40000000
+       WCLONE                           = 0x80000000
+       WCONTINUED                       = 0x8
+       WEXITED                          = 0x4
+       WNOHANG                          = 0x1
+       WNOTHREAD                        = 0x20000000
+       WNOWAIT                          = 0x1000000
+       WORDSIZE                         = 0x40
+       WSTOPPED                         = 0x2
+       WUNTRACED                        = 0x2
+)
+
+// Errors
+const (
+       E2BIG           = Errno(0x7)
+       EACCES          = Errno(0xd)
+       EADDRINUSE      = Errno(0x62)
+       EADDRNOTAVAIL   = Errno(0x63)
+       EADV            = Errno(0x44)
+       EAFNOSUPPORT    = Errno(0x61)
+       EAGAIN          = Errno(0xb)
+       EALREADY        = Errno(0x72)
+       EBADE           = Errno(0x34)
+       EBADF           = Errno(0x9)
+       EBADFD          = Errno(0x4d)
+       EBADMSG         = Errno(0x4a)
+       EBADR           = Errno(0x35)
+       EBADRQC         = Errno(0x38)
+       EBADSLT         = Errno(0x39)
+       EBFONT          = Errno(0x3b)
+       EBUSY           = Errno(0x10)
+       ECANCELED       = Errno(0x7d)
+       ECHILD          = Errno(0xa)
+       ECHRNG          = Errno(0x2c)
+       ECOMM           = Errno(0x46)
+       ECONNABORTED    = Errno(0x67)
+       ECONNREFUSED    = Errno(0x6f)
+       ECONNRESET      = Errno(0x68)
+       EDEADLK         = Errno(0x23)
+       EDEADLOCK       = Errno(0x3a)
+       EDESTADDRREQ    = Errno(0x59)
+       EDOM            = Errno(0x21)
+       EDOTDOT         = Errno(0x49)
+       EDQUOT          = Errno(0x7a)
+       EEXIST          = Errno(0x11)
+       EFAULT          = Errno(0xe)
+       EFBIG           = Errno(0x1b)
+       EHOSTDOWN       = Errno(0x70)
+       EHOSTUNREACH    = Errno(0x71)
+       EHWPOISON       = Errno(0x85)
+       EIDRM           = Errno(0x2b)
+       EILSEQ          = Errno(0x54)
+       EINPROGRESS     = Errno(0x73)
+       EINTR           = Errno(0x4)
+       EINVAL          = Errno(0x16)
+       EIO             = Errno(0x5)
+       EISCONN         = Errno(0x6a)
+       EISDIR          = Errno(0x15)
+       EISNAM          = Errno(0x78)
+       EKEYEXPIRED     = Errno(0x7f)
+       EKEYREJECTED    = Errno(0x81)
+       EKEYREVOKED     = Errno(0x80)
+       EL2HLT          = Errno(0x33)
+       EL2NSYNC        = Errno(0x2d)
+       EL3HLT          = Errno(0x2e)
+       EL3RST          = Errno(0x2f)
+       ELIBACC         = Errno(0x4f)
+       ELIBBAD         = Errno(0x50)
+       ELIBEXEC        = Errno(0x53)
+       ELIBMAX         = Errno(0x52)
+       ELIBSCN         = Errno(0x51)
+       ELNRNG          = Errno(0x30)
+       ELOOP           = Errno(0x28)
+       EMEDIUMTYPE     = Errno(0x7c)
+       EMFILE          = Errno(0x18)
+       EMLINK          = Errno(0x1f)
+       EMSGSIZE        = Errno(0x5a)
+       EMULTIHOP       = Errno(0x48)
+       ENAMETOOLONG    = Errno(0x24)
+       ENAVAIL         = Errno(0x77)
+       ENETDOWN        = Errno(0x64)
+       ENETRESET       = Errno(0x66)
+       ENETUNREACH     = Errno(0x65)
+       ENFILE          = Errno(0x17)
+       ENOANO          = Errno(0x37)
+       ENOBUFS         = Errno(0x69)
+       ENOCSI          = Errno(0x32)
+       ENODATA         = Errno(0x3d)
+       ENODEV          = Errno(0x13)
+       ENOENT          = Errno(0x2)
+       ENOEXEC         = Errno(0x8)
+       ENOKEY          = Errno(0x7e)
+       ENOLCK          = Errno(0x25)
+       ENOLINK         = Errno(0x43)
+       ENOMEDIUM       = Errno(0x7b)
+       ENOMEM          = Errno(0xc)
+       ENOMSG          = Errno(0x2a)
+       ENONET          = Errno(0x40)
+       ENOPKG          = Errno(0x41)
+       ENOPROTOOPT     = Errno(0x5c)
+       ENOSPC          = Errno(0x1c)
+       ENOSR           = Errno(0x3f)
+       ENOSTR          = Errno(0x3c)
+       ENOSYS          = Errno(0x26)
+       ENOTBLK         = Errno(0xf)
+       ENOTCONN        = Errno(0x6b)
+       ENOTDIR         = Errno(0x14)
+       ENOTEMPTY       = Errno(0x27)
+       ENOTNAM         = Errno(0x76)
+       ENOTRECOVERABLE = Errno(0x83)
+       ENOTSOCK        = Errno(0x58)
+       ENOTSUP         = Errno(0x5f)
+       ENOTTY          = Errno(0x19)
+       ENOTUNIQ        = Errno(0x4c)
+       ENXIO           = Errno(0x6)
+       EOPNOTSUPP      = Errno(0x5f)
+       EOVERFLOW       = Errno(0x4b)
+       EOWNERDEAD      = Errno(0x82)
+       EPERM           = Errno(0x1)
+       EPFNOSUPPORT    = Errno(0x60)
+       EPIPE           = Errno(0x20)
+       EPROTO          = Errno(0x47)
+       EPROTONOSUPPORT = Errno(0x5d)
+       EPROTOTYPE      = Errno(0x5b)
+       ERANGE          = Errno(0x22)
+       EREMCHG         = Errno(0x4e)
+       EREMOTE         = Errno(0x42)
+       EREMOTEIO       = Errno(0x79)
+       ERESTART        = Errno(0x55)
+       ERFKILL         = Errno(0x84)
+       EROFS           = Errno(0x1e)
+       ESHUTDOWN       = Errno(0x6c)
+       ESOCKTNOSUPPORT = Errno(0x5e)
+       ESPIPE          = Errno(0x1d)
+       ESRCH           = Errno(0x3)
+       ESRMNT          = Errno(0x45)
+       ESTALE          = Errno(0x74)
+       ESTRPIPE        = Errno(0x56)
+       ETIME           = Errno(0x3e)
+       ETIMEDOUT       = Errno(0x6e)
+       ETOOMANYREFS    = Errno(0x6d)
+       ETXTBSY         = Errno(0x1a)
+       EUCLEAN         = Errno(0x75)
+       EUNATCH         = Errno(0x31)
+       EUSERS          = Errno(0x57)
+       EWOULDBLOCK     = Errno(0xb)
+       EXDEV           = Errno(0x12)
+       EXFULL          = Errno(0x36)
+)
+
+// Signals
+const (
+       SIGABRT   = Signal(0x6)
+       SIGALRM   = Signal(0xe)
+       SIGBUS    = Signal(0x7)
+       SIGCHLD   = Signal(0x11)
+       SIGCLD    = Signal(0x11)
+       SIGCONT   = Signal(0x12)
+       SIGFPE    = Signal(0x8)
+       SIGHUP    = Signal(0x1)
+       SIGILL    = Signal(0x4)
+       SIGINT    = Signal(0x2)
+       SIGIO     = Signal(0x1d)
+       SIGIOT    = Signal(0x6)
+       SIGKILL   = Signal(0x9)
+       SIGPIPE   = Signal(0xd)
+       SIGPOLL   = Signal(0x1d)
+       SIGPROF   = Signal(0x1b)
+       SIGPWR    = Signal(0x1e)
+       SIGQUIT   = Signal(0x3)
+       SIGSEGV   = Signal(0xb)
+       SIGSTKFLT = Signal(0x10)
+       SIGSTOP   = Signal(0x13)
+       SIGSYS    = Signal(0x1f)
+       SIGTERM   = Signal(0xf)
+       SIGTRAP   = Signal(0x5)
+       SIGTSTP   = Signal(0x14)
+       SIGTTIN   = Signal(0x15)
+       SIGTTOU   = Signal(0x16)
+       SIGUNUSED = Signal(0x1f)
+       SIGURG    = Signal(0x17)
+       SIGUSR1   = Signal(0xa)
+       SIGUSR2   = Signal(0xc)
+       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:   "no such device or address",
+       7:   "argument list too long",
+       8:   "exec format error",
+       9:   "bad file descriptor",
+       10:  "no child processes",
+       11:  "resource temporarily unavailable",
+       12:  "cannot allocate memory",
+       13:  "permission denied",
+       14:  "bad address",
+       15:  "block device required",
+       16:  "device or resource busy",
+       17:  "file exists",
+       18:  "invalid cross-device link",
+       19:  "no such device",
+       20:  "not a directory",
+       21:  "is a directory",
+       22:  "invalid argument",
+       23:  "too many open files in system",
+       24:  "too many open files",
+       25:  "inappropriate ioctl for device",
+       26:  "text file busy",
+       27:  "file too large",
+       28:  "no space left on device",
+       29:  "illegal seek",
+       30:  "read-only file system",
+       31:  "too many links",
+       32:  "broken pipe",
+       33:  "numerical argument out of domain",
+       34:  "numerical result out of range",
+       35:  "resource deadlock avoided",
+       36:  "file name too long",
+       37:  "no locks available",
+       38:  "function not implemented",
+       39:  "directory not empty",
+       40:  "too many levels of symbolic links",
+       42:  "no message of desired type",
+       43:  "identifier removed",
+       44:  "channel number out of range",
+       45:  "level 2 not synchronized",
+       46:  "level 3 halted",
+       47:  "level 3 reset",
+       48:  "link number out of range",
+       49:  "protocol driver not attached",
+       50:  "no CSI structure available",
+       51:  "level 2 halted",
+       52:  "invalid exchange",
+       53:  "invalid request descriptor",
+       54:  "exchange full",
+       55:  "no anode",
+       56:  "invalid request code",
+       57:  "invalid slot",
+       58:  "file locking deadlock error",
+       59:  "bad font file format",
+       60:  "device not a stream",
+       61:  "no data available",
+       62:  "timer expired",
+       63:  "out of streams resources",
+       64:  "machine is not on the network",
+       65:  "package not installed",
+       66:  "object is remote",
+       67:  "link has been severed",
+       68:  "advertise error",
+       69:  "srmount error",
+       70:  "communication error on send",
+       71:  "protocol error",
+       72:  "multihop attempted",
+       73:  "RFS specific error",
+       74:  "bad message",
+       75:  "value too large for defined data type",
+       76:  "name not unique on network",
+       77:  "file descriptor in bad state",
+       78:  "remote address changed",
+       79:  "can not access a needed shared library",
+       80:  "accessing a corrupted shared library",
+       81:  ".lib section in a.out corrupted",
+       82:  "attempting to link in too many shared libraries",
+       83:  "cannot exec a shared library directly",
+       84:  "invalid or incomplete multibyte or wide character",
+       85:  "interrupted system call should be restarted",
+       86:  "streams pipe error",
+       87:  "too many users",
+       88:  "socket operation on non-socket",
+       89:  "destination address required",
+       90:  "message too long",
+       91:  "protocol wrong type for socket",
+       92:  "protocol not available",
+       93:  "protocol not supported",
+       94:  "socket type not supported",
+       95:  "operation not supported",
+       96:  "protocol family not supported",
+       97:  "address family not supported by protocol",
+       98:  "address already in use",
+       99:  "cannot assign requested address",
+       100: "network is down",
+       101: "network is unreachable",
+       102: "network dropped connection on reset",
+       103: "software caused connection abort",
+       104: "connection reset by peer",
+       105: "no buffer space available",
+       106: "transport endpoint is already connected",
+       107: "transport endpoint is not connected",
+       108: "cannot send after transport endpoint shutdown",
+       109: "too many references: cannot splice",
+       110: "connection timed out",
+       111: "connection refused",
+       112: "host is down",
+       113: "no route to host",
+       114: "operation already in progress",
+       115: "operation now in progress",
+       116: "stale NFS file handle",
+       117: "structure needs cleaning",
+       118: "not a XENIX named type file",
+       119: "no XENIX semaphores available",
+       120: "is a named type file",
+       121: "remote I/O error",
+       122: "disk quota exceeded",
+       123: "no medium found",
+       124: "wrong medium type",
+       125: "operation canceled",
+       126: "required key not available",
+       127: "key has expired",
+       128: "key has been revoked",
+       129: "key was rejected by service",
+       130: "owner died",
+       131: "state not recoverable",
+       132: "operation not possible due to RF-kill",
+       133: "memory page has hardware error",
+}
+
+// Signal table
+var signals = [...]string{
+       1:  "hangup",
+       2:  "interrupt",
+       3:  "quit",
+       4:  "illegal instruction",
+       5:  "trace/breakpoint trap",
+       6:  "aborted",
+       7:  "bus error",
+       8:  "floating point exception",
+       9:  "killed",
+       10: "user defined signal 1",
+       11: "segmentation fault",
+       12: "user defined signal 2",
+       13: "broken pipe",
+       14: "alarm clock",
+       15: "terminated",
+       16: "stack fault",
+       17: "child exited",
+       18: "continued",
+       19: "stopped (signal)",
+       20: "stopped",
+       21: "stopped (tty input)",
+       22: "stopped (tty output)",
+       23: "urgent I/O condition",
+       24: "CPU time limit exceeded",
+       25: "file size limit exceeded",
+       26: "virtual timer expired",
+       27: "profiling timer expired",
+       28: "window changed",
+       29: "I/O possible",
+       30: "power failure",
+       31: "bad system call",
+}
diff --git a/src/syscall/zerrors_linux_power64le.go b/src/syscall/zerrors_linux_power64le.go
new file mode 100644 (file)
index 0000000..fdecdf2
--- /dev/null
@@ -0,0 +1,1902 @@
+// mkerrors.sh -m64
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
+
+package syscall
+
+const (
+       AF_ALG                           = 0x26
+       AF_APPLETALK                     = 0x5
+       AF_ASH                           = 0x12
+       AF_ATMPVC                        = 0x8
+       AF_ATMSVC                        = 0x14
+       AF_AX25                          = 0x3
+       AF_BLUETOOTH                     = 0x1f
+       AF_BRIDGE                        = 0x7
+       AF_CAIF                          = 0x25
+       AF_CAN                           = 0x1d
+       AF_DECnet                        = 0xc
+       AF_ECONET                        = 0x13
+       AF_FILE                          = 0x1
+       AF_IEEE802154                    = 0x24
+       AF_INET                          = 0x2
+       AF_INET6                         = 0xa
+       AF_IPX                           = 0x4
+       AF_IRDA                          = 0x17
+       AF_ISDN                          = 0x22
+       AF_IUCV                          = 0x20
+       AF_KEY                           = 0xf
+       AF_LLC                           = 0x1a
+       AF_LOCAL                         = 0x1
+       AF_MAX                           = 0x29
+       AF_NETBEUI                       = 0xd
+       AF_NETLINK                       = 0x10
+       AF_NETROM                        = 0x6
+       AF_NFC                           = 0x27
+       AF_PACKET                        = 0x11
+       AF_PHONET                        = 0x23
+       AF_PPPOX                         = 0x18
+       AF_RDS                           = 0x15
+       AF_ROSE                          = 0xb
+       AF_ROUTE                         = 0x10
+       AF_RXRPC                         = 0x21
+       AF_SECURITY                      = 0xe
+       AF_SNA                           = 0x16
+       AF_TIPC                          = 0x1e
+       AF_UNIX                          = 0x1
+       AF_UNSPEC                        = 0x0
+       AF_VSOCK                         = 0x28
+       AF_WANPIPE                       = 0x19
+       AF_X25                           = 0x9
+       ARPHRD_ADAPT                     = 0x108
+       ARPHRD_APPLETLK                  = 0x8
+       ARPHRD_ARCNET                    = 0x7
+       ARPHRD_ASH                       = 0x30d
+       ARPHRD_ATM                       = 0x13
+       ARPHRD_AX25                      = 0x3
+       ARPHRD_BIF                       = 0x307
+       ARPHRD_CAIF                      = 0x336
+       ARPHRD_CAN                       = 0x118
+       ARPHRD_CHAOS                     = 0x5
+       ARPHRD_CISCO                     = 0x201
+       ARPHRD_CSLIP                     = 0x101
+       ARPHRD_CSLIP6                    = 0x103
+       ARPHRD_DDCMP                     = 0x205
+       ARPHRD_DLCI                      = 0xf
+       ARPHRD_ECONET                    = 0x30e
+       ARPHRD_EETHER                    = 0x2
+       ARPHRD_ETHER                     = 0x1
+       ARPHRD_EUI64                     = 0x1b
+       ARPHRD_FCAL                      = 0x311
+       ARPHRD_FCFABRIC                  = 0x313
+       ARPHRD_FCPL                      = 0x312
+       ARPHRD_FCPP                      = 0x310
+       ARPHRD_FDDI                      = 0x306
+       ARPHRD_FRAD                      = 0x302
+       ARPHRD_HDLC                      = 0x201
+       ARPHRD_HIPPI                     = 0x30c
+       ARPHRD_HWX25                     = 0x110
+       ARPHRD_IEEE1394                  = 0x18
+       ARPHRD_IEEE802                   = 0x6
+       ARPHRD_IEEE80211                 = 0x321
+       ARPHRD_IEEE80211_PRISM           = 0x322
+       ARPHRD_IEEE80211_RADIOTAP        = 0x323
+       ARPHRD_IEEE802154                = 0x324
+       ARPHRD_IEEE802154_MONITOR        = 0x325
+       ARPHRD_IEEE802_TR                = 0x320
+       ARPHRD_INFINIBAND                = 0x20
+       ARPHRD_IP6GRE                    = 0x337
+       ARPHRD_IPDDP                     = 0x309
+       ARPHRD_IPGRE                     = 0x30a
+       ARPHRD_IRDA                      = 0x30f
+       ARPHRD_LAPB                      = 0x204
+       ARPHRD_LOCALTLK                  = 0x305
+       ARPHRD_LOOPBACK                  = 0x304
+       ARPHRD_METRICOM                  = 0x17
+       ARPHRD_NETLINK                   = 0x338
+       ARPHRD_NETROM                    = 0x0
+       ARPHRD_NONE                      = 0xfffe
+       ARPHRD_PHONET                    = 0x334
+       ARPHRD_PHONET_PIPE               = 0x335
+       ARPHRD_PIMREG                    = 0x30b
+       ARPHRD_PPP                       = 0x200
+       ARPHRD_PRONET                    = 0x4
+       ARPHRD_RAWHDLC                   = 0x206
+       ARPHRD_ROSE                      = 0x10e
+       ARPHRD_RSRVD                     = 0x104
+       ARPHRD_SIT                       = 0x308
+       ARPHRD_SKIP                      = 0x303
+       ARPHRD_SLIP                      = 0x100
+       ARPHRD_SLIP6                     = 0x102
+       ARPHRD_TUNNEL                    = 0x300
+       ARPHRD_TUNNEL6                   = 0x301
+       ARPHRD_VOID                      = 0xffff
+       ARPHRD_X25                       = 0x10f
+       B0                               = 0x0
+       B1000000                         = 0x17
+       B110                             = 0x3
+       B115200                          = 0x11
+       B1152000                         = 0x18
+       B1200                            = 0x9
+       B134                             = 0x4
+       B150                             = 0x5
+       B1500000                         = 0x19
+       B1800                            = 0xa
+       B19200                           = 0xe
+       B200                             = 0x6
+       B2000000                         = 0x1a
+       B230400                          = 0x12
+       B2400                            = 0xb
+       B2500000                         = 0x1b
+       B300                             = 0x7
+       B3000000                         = 0x1c
+       B3500000                         = 0x1d
+       B38400                           = 0xf
+       B4000000                         = 0x1e
+       B460800                          = 0x13
+       B4800                            = 0xc
+       B50                              = 0x1
+       B500000                          = 0x14
+       B57600                           = 0x10
+       B576000                          = 0x15
+       B600                             = 0x8
+       B75                              = 0x2
+       B921600                          = 0x16
+       B9600                            = 0xd
+       BPF_A                            = 0x10
+       BPF_ABS                          = 0x20
+       BPF_ADD                          = 0x0
+       BPF_ALU                          = 0x4
+       BPF_AND                          = 0x50
+       BPF_B                            = 0x10
+       BPF_DIV                          = 0x30
+       BPF_H                            = 0x8
+       BPF_IMM                          = 0x0
+       BPF_IND                          = 0x40
+       BPF_JA                           = 0x0
+       BPF_JEQ                          = 0x10
+       BPF_JGE                          = 0x30
+       BPF_JGT                          = 0x20
+       BPF_JMP                          = 0x5
+       BPF_JSET                         = 0x40
+       BPF_K                            = 0x0
+       BPF_LD                           = 0x0
+       BPF_LDX                          = 0x1
+       BPF_LEN                          = 0x80
+       BPF_LSH                          = 0x60
+       BPF_MAJOR_VERSION                = 0x1
+       BPF_MAXINSNS                     = 0x1000
+       BPF_MEM                          = 0x60
+       BPF_MEMWORDS                     = 0x10
+       BPF_MINOR_VERSION                = 0x1
+       BPF_MISC                         = 0x7
+       BPF_MOD                          = 0x90
+       BPF_MSH                          = 0xa0
+       BPF_MUL                          = 0x20
+       BPF_NEG                          = 0x80
+       BPF_OR                           = 0x40
+       BPF_RET                          = 0x6
+       BPF_RSH                          = 0x70
+       BPF_ST                           = 0x2
+       BPF_STX                          = 0x3
+       BPF_SUB                          = 0x10
+       BPF_TAX                          = 0x0
+       BPF_TXA                          = 0x80
+       BPF_W                            = 0x0
+       BPF_X                            = 0x8
+       BPF_XOR                          = 0xa0
+       BRKINT                           = 0x2
+       CFLUSH                           = 0xf
+       CLOCAL                           = 0x8000
+       CLONE_CHILD_CLEARTID             = 0x200000
+       CLONE_CHILD_SETTID               = 0x1000000
+       CLONE_DETACHED                   = 0x400000
+       CLONE_FILES                      = 0x400
+       CLONE_FS                         = 0x200
+       CLONE_IO                         = 0x80000000
+       CLONE_NEWIPC                     = 0x8000000
+       CLONE_NEWNET                     = 0x40000000
+       CLONE_NEWNS                      = 0x20000
+       CLONE_NEWPID                     = 0x20000000
+       CLONE_NEWUSER                    = 0x10000000
+       CLONE_NEWUTS                     = 0x4000000
+       CLONE_PARENT                     = 0x8000
+       CLONE_PARENT_SETTID              = 0x100000
+       CLONE_PTRACE                     = 0x2000
+       CLONE_SETTLS                     = 0x80000
+       CLONE_SIGHAND                    = 0x800
+       CLONE_SYSVSEM                    = 0x40000
+       CLONE_THREAD                     = 0x10000
+       CLONE_UNTRACED                   = 0x800000
+       CLONE_VFORK                      = 0x4000
+       CLONE_VM                         = 0x100
+       CREAD                            = 0x800
+       CS5                              = 0x0
+       CS6                              = 0x100
+       CS7                              = 0x200
+       CS8                              = 0x300
+       CSIGNAL                          = 0xff
+       CSIZE                            = 0x300
+       CSTART                           = 0x11
+       CSTATUS                          = 0x0
+       CSTOP                            = 0x13
+       CSTOPB                           = 0x400
+       CSUSP                            = 0x1a
+       DT_BLK                           = 0x6
+       DT_CHR                           = 0x2
+       DT_DIR                           = 0x4
+       DT_FIFO                          = 0x1
+       DT_LNK                           = 0xa
+       DT_REG                           = 0x8
+       DT_SOCK                          = 0xc
+       DT_UNKNOWN                       = 0x0
+       DT_WHT                           = 0xe
+       ECHO                             = 0x8
+       ECHOCTL                          = 0x40
+       ECHOE                            = 0x2
+       ECHOK                            = 0x4
+       ECHOKE                           = 0x1
+       ECHONL                           = 0x10
+       ECHOPRT                          = 0x20
+       ENCODING_DEFAULT                 = 0x0
+       ENCODING_FM_MARK                 = 0x3
+       ENCODING_FM_SPACE                = 0x4
+       ENCODING_MANCHESTER              = 0x5
+       ENCODING_NRZ                     = 0x1
+       ENCODING_NRZI                    = 0x2
+       EPOLLERR                         = 0x8
+       EPOLLET                          = 0x80000000
+       EPOLLHUP                         = 0x10
+       EPOLLIN                          = 0x1
+       EPOLLMSG                         = 0x400
+       EPOLLONESHOT                     = 0x40000000
+       EPOLLOUT                         = 0x4
+       EPOLLPRI                         = 0x2
+       EPOLLRDBAND                      = 0x80
+       EPOLLRDHUP                       = 0x2000
+       EPOLLRDNORM                      = 0x40
+       EPOLLWAKEUP                      = 0x20000000
+       EPOLLWRBAND                      = 0x200
+       EPOLLWRNORM                      = 0x100
+       EPOLL_CLOEXEC                    = 0x80000
+       EPOLL_CTL_ADD                    = 0x1
+       EPOLL_CTL_DEL                    = 0x2
+       EPOLL_CTL_MOD                    = 0x3
+       ETH_P_1588                       = 0x88f7
+       ETH_P_8021AD                     = 0x88a8
+       ETH_P_8021AH                     = 0x88e7
+       ETH_P_8021Q                      = 0x8100
+       ETH_P_802_2                      = 0x4
+       ETH_P_802_3                      = 0x1
+       ETH_P_802_3_MIN                  = 0x600
+       ETH_P_802_EX1                    = 0x88b5
+       ETH_P_AARP                       = 0x80f3
+       ETH_P_AF_IUCV                    = 0xfbfb
+       ETH_P_ALL                        = 0x3
+       ETH_P_AOE                        = 0x88a2
+       ETH_P_ARCNET                     = 0x1a
+       ETH_P_ARP                        = 0x806
+       ETH_P_ATALK                      = 0x809b
+       ETH_P_ATMFATE                    = 0x8884
+       ETH_P_ATMMPOA                    = 0x884c
+       ETH_P_AX25                       = 0x2
+       ETH_P_BATMAN                     = 0x4305
+       ETH_P_BPQ                        = 0x8ff
+       ETH_P_CAIF                       = 0xf7
+       ETH_P_CAN                        = 0xc
+       ETH_P_CANFD                      = 0xd
+       ETH_P_CONTROL                    = 0x16
+       ETH_P_CUST                       = 0x6006
+       ETH_P_DDCMP                      = 0x6
+       ETH_P_DEC                        = 0x6000
+       ETH_P_DIAG                       = 0x6005
+       ETH_P_DNA_DL                     = 0x6001
+       ETH_P_DNA_RC                     = 0x6002
+       ETH_P_DNA_RT                     = 0x6003
+       ETH_P_DSA                        = 0x1b
+       ETH_P_ECONET                     = 0x18
+       ETH_P_EDSA                       = 0xdada
+       ETH_P_FCOE                       = 0x8906
+       ETH_P_FIP                        = 0x8914
+       ETH_P_HDLC                       = 0x19
+       ETH_P_IEEE802154                 = 0xf6
+       ETH_P_IEEEPUP                    = 0xa00
+       ETH_P_IEEEPUPAT                  = 0xa01
+       ETH_P_IP                         = 0x800
+       ETH_P_IPV6                       = 0x86dd
+       ETH_P_IPX                        = 0x8137
+       ETH_P_IRDA                       = 0x17
+       ETH_P_LAT                        = 0x6004
+       ETH_P_LINK_CTL                   = 0x886c
+       ETH_P_LOCALTALK                  = 0x9
+       ETH_P_LOOP                       = 0x60
+       ETH_P_MOBITEX                    = 0x15
+       ETH_P_MPLS_MC                    = 0x8848
+       ETH_P_MPLS_UC                    = 0x8847
+       ETH_P_MVRP                       = 0x88f5
+       ETH_P_PAE                        = 0x888e
+       ETH_P_PAUSE                      = 0x8808
+       ETH_P_PHONET                     = 0xf5
+       ETH_P_PPPTALK                    = 0x10
+       ETH_P_PPP_DISC                   = 0x8863
+       ETH_P_PPP_MP                     = 0x8
+       ETH_P_PPP_SES                    = 0x8864
+       ETH_P_PRP                        = 0x88fb
+       ETH_P_PUP                        = 0x200
+       ETH_P_PUPAT                      = 0x201
+       ETH_P_QINQ1                      = 0x9100
+       ETH_P_QINQ2                      = 0x9200
+       ETH_P_QINQ3                      = 0x9300
+       ETH_P_RARP                       = 0x8035
+       ETH_P_SCA                        = 0x6007
+       ETH_P_SLOW                       = 0x8809
+       ETH_P_SNAP                       = 0x5
+       ETH_P_TDLS                       = 0x890d
+       ETH_P_TEB                        = 0x6558
+       ETH_P_TIPC                       = 0x88ca
+       ETH_P_TRAILER                    = 0x1c
+       ETH_P_TR_802_2                   = 0x11
+       ETH_P_WAN_PPP                    = 0x7
+       ETH_P_WCCP                       = 0x883e
+       ETH_P_X25                        = 0x805
+       EXTA                             = 0xe
+       EXTB                             = 0xf
+       EXTPROC                          = 0x10000000
+       FD_CLOEXEC                       = 0x1
+       FD_SETSIZE                       = 0x400
+       FLUSHO                           = 0x800000
+       F_DUPFD                          = 0x0
+       F_DUPFD_CLOEXEC                  = 0x406
+       F_EXLCK                          = 0x4
+       F_GETFD                          = 0x1
+       F_GETFL                          = 0x3
+       F_GETLEASE                       = 0x401
+       F_GETLK                          = 0x5
+       F_GETLK64                        = 0xc
+       F_GETOWN                         = 0x9
+       F_GETOWN_EX                      = 0x10
+       F_GETPIPE_SZ                     = 0x408
+       F_GETSIG                         = 0xb
+       F_LOCK                           = 0x1
+       F_NOTIFY                         = 0x402
+       F_OK                             = 0x0
+       F_RDLCK                          = 0x0
+       F_SETFD                          = 0x2
+       F_SETFL                          = 0x4
+       F_SETLEASE                       = 0x400
+       F_SETLK                          = 0xd
+       F_SETLK64                        = 0xd
+       F_SETLKW                         = 0xe
+       F_SETLKW64                       = 0xe
+       F_SETOWN                         = 0x8
+       F_SETOWN_EX                      = 0xf
+       F_SETPIPE_SZ                     = 0x407
+       F_SETSIG                         = 0xa
+       F_SHLCK                          = 0x8
+       F_TEST                           = 0x3
+       F_TLOCK                          = 0x2
+       F_ULOCK                          = 0x0
+       F_UNLCK                          = 0x2
+       F_WRLCK                          = 0x1
+       HUPCL                            = 0x4000
+       ICANON                           = 0x100
+       ICMPV6_FILTER                    = 0x1
+       ICRNL                            = 0x100
+       IEXTEN                           = 0x400
+       IFA_F_DADFAILED                  = 0x8
+       IFA_F_DEPRECATED                 = 0x20
+       IFA_F_HOMEADDRESS                = 0x10
+       IFA_F_NODAD                      = 0x2
+       IFA_F_OPTIMISTIC                 = 0x4
+       IFA_F_PERMANENT                  = 0x80
+       IFA_F_SECONDARY                  = 0x1
+       IFA_F_TEMPORARY                  = 0x1
+       IFA_F_TENTATIVE                  = 0x40
+       IFA_MAX                          = 0x7
+       IFF_802_1Q_VLAN                  = 0x1
+       IFF_ALLMULTI                     = 0x200
+       IFF_ATTACH_QUEUE                 = 0x200
+       IFF_AUTOMEDIA                    = 0x4000
+       IFF_BONDING                      = 0x20
+       IFF_BRIDGE_PORT                  = 0x4000
+       IFF_BROADCAST                    = 0x2
+       IFF_DEBUG                        = 0x4
+       IFF_DETACH_QUEUE                 = 0x400
+       IFF_DISABLE_NETPOLL              = 0x1000
+       IFF_DONT_BRIDGE                  = 0x800
+       IFF_DORMANT                      = 0x20000
+       IFF_DYNAMIC                      = 0x8000
+       IFF_EBRIDGE                      = 0x2
+       IFF_ECHO                         = 0x40000
+       IFF_ISATAP                       = 0x80
+       IFF_LIVE_ADDR_CHANGE             = 0x100000
+       IFF_LOOPBACK                     = 0x8
+       IFF_LOWER_UP                     = 0x10000
+       IFF_MACVLAN                      = 0x200000
+       IFF_MACVLAN_PORT                 = 0x2000
+       IFF_MASTER                       = 0x400
+       IFF_MASTER_8023AD                = 0x8
+       IFF_MASTER_ALB                   = 0x10
+       IFF_MASTER_ARPMON                = 0x100
+       IFF_MULTICAST                    = 0x1000
+       IFF_MULTI_QUEUE                  = 0x100
+       IFF_NOARP                        = 0x80
+       IFF_NOFILTER                     = 0x1000
+       IFF_NOTRAILERS                   = 0x20
+       IFF_NO_PI                        = 0x1000
+       IFF_ONE_QUEUE                    = 0x2000
+       IFF_OVS_DATAPATH                 = 0x8000
+       IFF_PERSIST                      = 0x800
+       IFF_POINTOPOINT                  = 0x10
+       IFF_PORTSEL                      = 0x2000
+       IFF_PROMISC                      = 0x100
+       IFF_RUNNING                      = 0x40
+       IFF_SLAVE                        = 0x800
+       IFF_SLAVE_INACTIVE               = 0x4
+       IFF_SLAVE_NEEDARP                = 0x40
+       IFF_SUPP_NOFCS                   = 0x80000
+       IFF_TAP                          = 0x2
+       IFF_TEAM_PORT                    = 0x40000
+       IFF_TUN                          = 0x1
+       IFF_TUN_EXCL                     = 0x8000
+       IFF_TX_SKB_SHARING               = 0x10000
+       IFF_UNICAST_FLT                  = 0x20000
+       IFF_UP                           = 0x1
+       IFF_VNET_HDR                     = 0x4000
+       IFF_VOLATILE                     = 0x70c5a
+       IFF_WAN_HDLC                     = 0x200
+       IFF_XMIT_DST_RELEASE             = 0x400
+       IFNAMSIZ                         = 0x10
+       IGNBRK                           = 0x1
+       IGNCR                            = 0x80
+       IGNPAR                           = 0x4
+       IMAXBEL                          = 0x2000
+       INLCR                            = 0x40
+       INPCK                            = 0x10
+       IN_ACCESS                        = 0x1
+       IN_ALL_EVENTS                    = 0xfff
+       IN_ATTRIB                        = 0x4
+       IN_CLASSA_HOST                   = 0xffffff
+       IN_CLASSA_MAX                    = 0x80
+       IN_CLASSA_NET                    = 0xff000000
+       IN_CLASSA_NSHIFT                 = 0x18
+       IN_CLASSB_HOST                   = 0xffff
+       IN_CLASSB_MAX                    = 0x10000
+       IN_CLASSB_NET                    = 0xffff0000
+       IN_CLASSB_NSHIFT                 = 0x10
+       IN_CLASSC_HOST                   = 0xff
+       IN_CLASSC_NET                    = 0xffffff00
+       IN_CLASSC_NSHIFT                 = 0x8
+       IN_CLOEXEC                       = 0x80000
+       IN_CLOSE                         = 0x18
+       IN_CLOSE_NOWRITE                 = 0x10
+       IN_CLOSE_WRITE                   = 0x8
+       IN_CREATE                        = 0x100
+       IN_DELETE                        = 0x200
+       IN_DELETE_SELF                   = 0x400
+       IN_DONT_FOLLOW                   = 0x2000000
+       IN_EXCL_UNLINK                   = 0x4000000
+       IN_IGNORED                       = 0x8000
+       IN_ISDIR                         = 0x40000000
+       IN_LOOPBACKNET                   = 0x7f
+       IN_MASK_ADD                      = 0x20000000
+       IN_MODIFY                        = 0x2
+       IN_MOVE                          = 0xc0
+       IN_MOVED_FROM                    = 0x40
+       IN_MOVED_TO                      = 0x80
+       IN_MOVE_SELF                     = 0x800
+       IN_NONBLOCK                      = 0x800
+       IN_ONESHOT                       = 0x80000000
+       IN_ONLYDIR                       = 0x1000000
+       IN_OPEN                          = 0x20
+       IN_Q_OVERFLOW                    = 0x4000
+       IN_UNMOUNT                       = 0x2000
+       IPPROTO_AH                       = 0x33
+       IPPROTO_BEETPH                   = 0x5e
+       IPPROTO_COMP                     = 0x6c
+       IPPROTO_DCCP                     = 0x21
+       IPPROTO_DSTOPTS                  = 0x3c
+       IPPROTO_EGP                      = 0x8
+       IPPROTO_ENCAP                    = 0x62
+       IPPROTO_ESP                      = 0x32
+       IPPROTO_FRAGMENT                 = 0x2c
+       IPPROTO_GRE                      = 0x2f
+       IPPROTO_HOPOPTS                  = 0x0
+       IPPROTO_ICMP                     = 0x1
+       IPPROTO_ICMPV6                   = 0x3a
+       IPPROTO_IDP                      = 0x16
+       IPPROTO_IGMP                     = 0x2
+       IPPROTO_IP                       = 0x0
+       IPPROTO_IPIP                     = 0x4
+       IPPROTO_IPV6                     = 0x29
+       IPPROTO_MH                       = 0x87
+       IPPROTO_MTP                      = 0x5c
+       IPPROTO_NONE                     = 0x3b
+       IPPROTO_PIM                      = 0x67
+       IPPROTO_PUP                      = 0xc
+       IPPROTO_RAW                      = 0xff
+       IPPROTO_ROUTING                  = 0x2b
+       IPPROTO_RSVP                     = 0x2e
+       IPPROTO_SCTP                     = 0x84
+       IPPROTO_TCP                      = 0x6
+       IPPROTO_TP                       = 0x1d
+       IPPROTO_UDP                      = 0x11
+       IPPROTO_UDPLITE                  = 0x88
+       IPV6_2292DSTOPTS                 = 0x4
+       IPV6_2292HOPLIMIT                = 0x8
+       IPV6_2292HOPOPTS                 = 0x3
+       IPV6_2292PKTINFO                 = 0x2
+       IPV6_2292PKTOPTIONS              = 0x6
+       IPV6_2292RTHDR                   = 0x5
+       IPV6_ADDRFORM                    = 0x1
+       IPV6_ADD_MEMBERSHIP              = 0x14
+       IPV6_AUTHHDR                     = 0xa
+       IPV6_CHECKSUM                    = 0x7
+       IPV6_DROP_MEMBERSHIP             = 0x15
+       IPV6_DSTOPTS                     = 0x3b
+       IPV6_HOPLIMIT                    = 0x34
+       IPV6_HOPOPTS                     = 0x36
+       IPV6_IPSEC_POLICY                = 0x22
+       IPV6_JOIN_ANYCAST                = 0x1b
+       IPV6_JOIN_GROUP                  = 0x14
+       IPV6_LEAVE_ANYCAST               = 0x1c
+       IPV6_LEAVE_GROUP                 = 0x15
+       IPV6_MTU                         = 0x18
+       IPV6_MTU_DISCOVER                = 0x17
+       IPV6_MULTICAST_HOPS              = 0x12
+       IPV6_MULTICAST_IF                = 0x11
+       IPV6_MULTICAST_LOOP              = 0x13
+       IPV6_NEXTHOP                     = 0x9
+       IPV6_PKTINFO                     = 0x32
+       IPV6_PMTUDISC_DO                 = 0x2
+       IPV6_PMTUDISC_DONT               = 0x0
+       IPV6_PMTUDISC_PROBE              = 0x3
+       IPV6_PMTUDISC_WANT               = 0x1
+       IPV6_RECVDSTOPTS                 = 0x3a
+       IPV6_RECVERR                     = 0x19
+       IPV6_RECVHOPLIMIT                = 0x33
+       IPV6_RECVHOPOPTS                 = 0x35
+       IPV6_RECVPKTINFO                 = 0x31
+       IPV6_RECVRTHDR                   = 0x38
+       IPV6_RECVTCLASS                  = 0x42
+       IPV6_ROUTER_ALERT                = 0x16
+       IPV6_RTHDR                       = 0x39
+       IPV6_RTHDRDSTOPTS                = 0x37
+       IPV6_RTHDR_LOOSE                 = 0x0
+       IPV6_RTHDR_STRICT                = 0x1
+       IPV6_RTHDR_TYPE_0                = 0x0
+       IPV6_RXDSTOPTS                   = 0x3b
+       IPV6_RXHOPOPTS                   = 0x36
+       IPV6_TCLASS                      = 0x43
+       IPV6_UNICAST_HOPS                = 0x10
+       IPV6_V6ONLY                      = 0x1a
+       IPV6_XFRM_POLICY                 = 0x23
+       IP_ADD_MEMBERSHIP                = 0x23
+       IP_ADD_SOURCE_MEMBERSHIP         = 0x27
+       IP_BLOCK_SOURCE                  = 0x26
+       IP_DEFAULT_MULTICAST_LOOP        = 0x1
+       IP_DEFAULT_MULTICAST_TTL         = 0x1
+       IP_DF                            = 0x4000
+       IP_DROP_MEMBERSHIP               = 0x24
+       IP_DROP_SOURCE_MEMBERSHIP        = 0x28
+       IP_FREEBIND                      = 0xf
+       IP_HDRINCL                       = 0x3
+       IP_IPSEC_POLICY                  = 0x10
+       IP_MAXPACKET                     = 0xffff
+       IP_MAX_MEMBERSHIPS               = 0x14
+       IP_MF                            = 0x2000
+       IP_MINTTL                        = 0x15
+       IP_MSFILTER                      = 0x29
+       IP_MSS                           = 0x240
+       IP_MTU                           = 0xe
+       IP_MTU_DISCOVER                  = 0xa
+       IP_MULTICAST_ALL                 = 0x31
+       IP_MULTICAST_IF                  = 0x20
+       IP_MULTICAST_LOOP                = 0x22
+       IP_MULTICAST_TTL                 = 0x21
+       IP_OFFMASK                       = 0x1fff
+       IP_OPTIONS                       = 0x4
+       IP_ORIGDSTADDR                   = 0x14
+       IP_PASSSEC                       = 0x12
+       IP_PKTINFO                       = 0x8
+       IP_PKTOPTIONS                    = 0x9
+       IP_PMTUDISC                      = 0xa
+       IP_PMTUDISC_DO                   = 0x2
+       IP_PMTUDISC_DONT                 = 0x0
+       IP_PMTUDISC_PROBE                = 0x3
+       IP_PMTUDISC_WANT                 = 0x1
+       IP_RECVERR                       = 0xb
+       IP_RECVOPTS                      = 0x6
+       IP_RECVORIGDSTADDR               = 0x14
+       IP_RECVRETOPTS                   = 0x7
+       IP_RECVTOS                       = 0xd
+       IP_RECVTTL                       = 0xc
+       IP_RETOPTS                       = 0x7
+       IP_RF                            = 0x8000
+       IP_ROUTER_ALERT                  = 0x5
+       IP_TOS                           = 0x1
+       IP_TRANSPARENT                   = 0x13
+       IP_TTL                           = 0x2
+       IP_UNBLOCK_SOURCE                = 0x25
+       IP_UNICAST_IF                    = 0x32
+       IP_XFRM_POLICY                   = 0x11
+       ISIG                             = 0x80
+       ISTRIP                           = 0x20
+       IUTF8                            = 0x4000
+       IXANY                            = 0x800
+       IXOFF                            = 0x400
+       IXON                             = 0x200
+       LINUX_REBOOT_CMD_CAD_OFF         = 0x0
+       LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
+       LINUX_REBOOT_CMD_HALT            = 0xcdef0123
+       LINUX_REBOOT_CMD_KEXEC           = 0x45584543
+       LINUX_REBOOT_CMD_POWER_OFF       = 0x4321fedc
+       LINUX_REBOOT_CMD_RESTART         = 0x1234567
+       LINUX_REBOOT_CMD_RESTART2        = 0xa1b2c3d4
+       LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
+       LINUX_REBOOT_MAGIC1              = 0xfee1dead
+       LINUX_REBOOT_MAGIC2              = 0x28121969
+       LOCK_EX                          = 0x2
+       LOCK_NB                          = 0x4
+       LOCK_SH                          = 0x1
+       LOCK_UN                          = 0x8
+       MADV_DODUMP                      = 0x11
+       MADV_DOFORK                      = 0xb
+       MADV_DONTDUMP                    = 0x10
+       MADV_DONTFORK                    = 0xa
+       MADV_DONTNEED                    = 0x4
+       MADV_HUGEPAGE                    = 0xe
+       MADV_HWPOISON                    = 0x64
+       MADV_MERGEABLE                   = 0xc
+       MADV_NOHUGEPAGE                  = 0xf
+       MADV_NORMAL                      = 0x0
+       MADV_RANDOM                      = 0x1
+       MADV_REMOVE                      = 0x9
+       MADV_SEQUENTIAL                  = 0x2
+       MADV_UNMERGEABLE                 = 0xd
+       MADV_WILLNEED                    = 0x3
+       MAP_ANON                         = 0x20
+       MAP_ANONYMOUS                    = 0x20
+       MAP_DENYWRITE                    = 0x800
+       MAP_EXECUTABLE                   = 0x1000
+       MAP_FILE                         = 0x0
+       MAP_FIXED                        = 0x10
+       MAP_GROWSDOWN                    = 0x100
+       MAP_HUGETLB                      = 0x40000
+       MAP_HUGE_MASK                    = 0x3f
+       MAP_HUGE_SHIFT                   = 0x1a
+       MAP_LOCKED                       = 0x80
+       MAP_NONBLOCK                     = 0x10000
+       MAP_NORESERVE                    = 0x40
+       MAP_POPULATE                     = 0x8000
+       MAP_PRIVATE                      = 0x2
+       MAP_SHARED                       = 0x1
+       MAP_STACK                        = 0x20000
+       MAP_TYPE                         = 0xf
+       MCL_CURRENT                      = 0x2000
+       MCL_FUTURE                       = 0x4000
+       MNT_DETACH                       = 0x2
+       MNT_EXPIRE                       = 0x4
+       MNT_FORCE                        = 0x1
+       MSG_CMSG_CLOEXEC                 = 0x40000000
+       MSG_CONFIRM                      = 0x800
+       MSG_CTRUNC                       = 0x8
+       MSG_DONTROUTE                    = 0x4
+       MSG_DONTWAIT                     = 0x40
+       MSG_EOR                          = 0x80
+       MSG_ERRQUEUE                     = 0x2000
+       MSG_FASTOPEN                     = 0x20000000
+       MSG_FIN                          = 0x200
+       MSG_MORE                         = 0x8000
+       MSG_NOSIGNAL                     = 0x4000
+       MSG_OOB                          = 0x1
+       MSG_PEEK                         = 0x2
+       MSG_PROXY                        = 0x10
+       MSG_RST                          = 0x1000
+       MSG_SYN                          = 0x400
+       MSG_TRUNC                        = 0x20
+       MSG_TRYHARD                      = 0x4
+       MSG_WAITALL                      = 0x100
+       MSG_WAITFORONE                   = 0x10000
+       MS_ACTIVE                        = 0x40000000
+       MS_ASYNC                         = 0x1
+       MS_BIND                          = 0x1000
+       MS_DIRSYNC                       = 0x80
+       MS_INVALIDATE                    = 0x2
+       MS_I_VERSION                     = 0x800000
+       MS_KERNMOUNT                     = 0x400000
+       MS_MANDLOCK                      = 0x40
+       MS_MGC_MSK                       = 0xffff0000
+       MS_MGC_VAL                       = 0xc0ed0000
+       MS_MOVE                          = 0x2000
+       MS_NOATIME                       = 0x400
+       MS_NODEV                         = 0x4
+       MS_NODIRATIME                    = 0x800
+       MS_NOEXEC                        = 0x8
+       MS_NOSUID                        = 0x2
+       MS_NOUSER                        = -0x80000000
+       MS_POSIXACL                      = 0x10000
+       MS_PRIVATE                       = 0x40000
+       MS_RDONLY                        = 0x1
+       MS_REC                           = 0x4000
+       MS_RELATIME                      = 0x200000
+       MS_REMOUNT                       = 0x20
+       MS_RMT_MASK                      = 0x800051
+       MS_SHARED                        = 0x100000
+       MS_SILENT                        = 0x8000
+       MS_SLAVE                         = 0x80000
+       MS_STRICTATIME                   = 0x1000000
+       MS_SYNC                          = 0x4
+       MS_SYNCHRONOUS                   = 0x10
+       MS_UNBINDABLE                    = 0x20000
+       NAME_MAX                         = 0xff
+       NETLINK_ADD_MEMBERSHIP           = 0x1
+       NETLINK_AUDIT                    = 0x9
+       NETLINK_BROADCAST_ERROR          = 0x4
+       NETLINK_CONNECTOR                = 0xb
+       NETLINK_CRYPTO                   = 0x15
+       NETLINK_DNRTMSG                  = 0xe
+       NETLINK_DROP_MEMBERSHIP          = 0x2
+       NETLINK_ECRYPTFS                 = 0x13
+       NETLINK_FIB_LOOKUP               = 0xa
+       NETLINK_FIREWALL                 = 0x3
+       NETLINK_GENERIC                  = 0x10
+       NETLINK_INET_DIAG                = 0x4
+       NETLINK_IP6_FW                   = 0xd
+       NETLINK_ISCSI                    = 0x8
+       NETLINK_KOBJECT_UEVENT           = 0xf
+       NETLINK_NETFILTER                = 0xc
+       NETLINK_NFLOG                    = 0x5
+       NETLINK_NO_ENOBUFS               = 0x5
+       NETLINK_PKTINFO                  = 0x3
+       NETLINK_RDMA                     = 0x14
+       NETLINK_ROUTE                    = 0x0
+       NETLINK_RX_RING                  = 0x6
+       NETLINK_SCSITRANSPORT            = 0x12
+       NETLINK_SELINUX                  = 0x7
+       NETLINK_SOCK_DIAG                = 0x4
+       NETLINK_TX_RING                  = 0x7
+       NETLINK_UNUSED                   = 0x1
+       NETLINK_USERSOCK                 = 0x2
+       NETLINK_XFRM                     = 0x6
+       NLA_ALIGNTO                      = 0x4
+       NLA_F_NESTED                     = 0x8000
+       NLA_F_NET_BYTEORDER              = 0x4000
+       NLA_HDRLEN                       = 0x4
+       NLMSG_ALIGNTO                    = 0x4
+       NLMSG_DONE                       = 0x3
+       NLMSG_ERROR                      = 0x2
+       NLMSG_HDRLEN                     = 0x10
+       NLMSG_MIN_TYPE                   = 0x10
+       NLMSG_NOOP                       = 0x1
+       NLMSG_OVERRUN                    = 0x4
+       NLM_F_ACK                        = 0x4
+       NLM_F_APPEND                     = 0x800
+       NLM_F_ATOMIC                     = 0x400
+       NLM_F_CREATE                     = 0x400
+       NLM_F_DUMP                       = 0x300
+       NLM_F_DUMP_INTR                  = 0x10
+       NLM_F_ECHO                       = 0x8
+       NLM_F_EXCL                       = 0x200
+       NLM_F_MATCH                      = 0x200
+       NLM_F_MULTI                      = 0x2
+       NLM_F_REPLACE                    = 0x100
+       NLM_F_REQUEST                    = 0x1
+       NLM_F_ROOT                       = 0x100
+       NOFLSH                           = 0x80000000
+       OCRNL                            = 0x8
+       OFDEL                            = 0x80
+       OFILL                            = 0x40
+       ONLCR                            = 0x2
+       ONLRET                           = 0x20
+       ONOCR                            = 0x10
+       OPOST                            = 0x1
+       O_ACCMODE                        = 0x3
+       O_APPEND                         = 0x400
+       O_ASYNC                          = 0x2000
+       O_CLOEXEC                        = 0x80000
+       O_CREAT                          = 0x40
+       O_DIRECT                         = 0x20000
+       O_DIRECTORY                      = 0x4000
+       O_DSYNC                          = 0x1000
+       O_EXCL                           = 0x80
+       O_FSYNC                          = 0x101000
+       O_LARGEFILE                      = 0x0
+       O_NDELAY                         = 0x800
+       O_NOATIME                        = 0x40000
+       O_NOCTTY                         = 0x100
+       O_NOFOLLOW                       = 0x8000
+       O_NONBLOCK                       = 0x800
+       O_PATH                           = 0x200000
+       O_RDONLY                         = 0x0
+       O_RDWR                           = 0x2
+       O_RSYNC                          = 0x101000
+       O_SYNC                           = 0x101000
+       O_TMPFILE                        = 0x410000
+       O_TRUNC                          = 0x200
+       O_WRONLY                         = 0x1
+       PACKET_ADD_MEMBERSHIP            = 0x1
+       PACKET_AUXDATA                   = 0x8
+       PACKET_BROADCAST                 = 0x1
+       PACKET_COPY_THRESH               = 0x7
+       PACKET_DROP_MEMBERSHIP           = 0x2
+       PACKET_FANOUT                    = 0x12
+       PACKET_FANOUT_CPU                = 0x2
+       PACKET_FANOUT_FLAG_DEFRAG        = 0x8000
+       PACKET_FANOUT_FLAG_ROLLOVER      = 0x1000
+       PACKET_FANOUT_HASH               = 0x0
+       PACKET_FANOUT_LB                 = 0x1
+       PACKET_FANOUT_RND                = 0x4
+       PACKET_FANOUT_ROLLOVER           = 0x3
+       PACKET_FASTROUTE                 = 0x6
+       PACKET_HDRLEN                    = 0xb
+       PACKET_HOST                      = 0x0
+       PACKET_LOOPBACK                  = 0x5
+       PACKET_LOSS                      = 0xe
+       PACKET_MR_ALLMULTI               = 0x2
+       PACKET_MR_MULTICAST              = 0x0
+       PACKET_MR_PROMISC                = 0x1
+       PACKET_MR_UNICAST                = 0x3
+       PACKET_MULTICAST                 = 0x2
+       PACKET_ORIGDEV                   = 0x9
+       PACKET_OTHERHOST                 = 0x3
+       PACKET_OUTGOING                  = 0x4
+       PACKET_RECV_OUTPUT               = 0x3
+       PACKET_RESERVE                   = 0xc
+       PACKET_RX_RING                   = 0x5
+       PACKET_STATISTICS                = 0x6
+       PACKET_TIMESTAMP                 = 0x11
+       PACKET_TX_HAS_OFF                = 0x13
+       PACKET_TX_RING                   = 0xd
+       PACKET_TX_TIMESTAMP              = 0x10
+       PACKET_VERSION                   = 0xa
+       PACKET_VNET_HDR                  = 0xf
+       PARENB                           = 0x1000
+       PARITY_CRC16_PR0                 = 0x2
+       PARITY_CRC16_PR0_CCITT           = 0x4
+       PARITY_CRC16_PR1                 = 0x3
+       PARITY_CRC16_PR1_CCITT           = 0x5
+       PARITY_CRC32_PR0_CCITT           = 0x6
+       PARITY_CRC32_PR1_CCITT           = 0x7
+       PARITY_DEFAULT                   = 0x0
+       PARITY_NONE                      = 0x1
+       PARMRK                           = 0x8
+       PARODD                           = 0x2000
+       PENDIN                           = 0x20000000
+       PRIO_PGRP                        = 0x1
+       PRIO_PROCESS                     = 0x0
+       PRIO_USER                        = 0x2
+       PROT_EXEC                        = 0x4
+       PROT_GROWSDOWN                   = 0x1000000
+       PROT_GROWSUP                     = 0x2000000
+       PROT_NONE                        = 0x0
+       PROT_READ                        = 0x1
+       PROT_SAO                         = 0x10
+       PROT_WRITE                       = 0x2
+       PR_CAPBSET_DROP                  = 0x18
+       PR_CAPBSET_READ                  = 0x17
+       PR_ENDIAN_BIG                    = 0x0
+       PR_ENDIAN_LITTLE                 = 0x1
+       PR_ENDIAN_PPC_LITTLE             = 0x2
+       PR_FPEMU_NOPRINT                 = 0x1
+       PR_FPEMU_SIGFPE                  = 0x2
+       PR_FP_EXC_ASYNC                  = 0x2
+       PR_FP_EXC_DISABLED               = 0x0
+       PR_FP_EXC_DIV                    = 0x10000
+       PR_FP_EXC_INV                    = 0x100000
+       PR_FP_EXC_NONRECOV               = 0x1
+       PR_FP_EXC_OVF                    = 0x20000
+       PR_FP_EXC_PRECISE                = 0x3
+       PR_FP_EXC_RES                    = 0x80000
+       PR_FP_EXC_SW_ENABLE              = 0x80
+       PR_FP_EXC_UND                    = 0x40000
+       PR_GET_CHILD_SUBREAPER           = 0x25
+       PR_GET_DUMPABLE                  = 0x3
+       PR_GET_ENDIAN                    = 0x13
+       PR_GET_FPEMU                     = 0x9
+       PR_GET_FPEXC                     = 0xb
+       PR_GET_KEEPCAPS                  = 0x7
+       PR_GET_NAME                      = 0x10
+       PR_GET_NO_NEW_PRIVS              = 0x27
+       PR_GET_PDEATHSIG                 = 0x2
+       PR_GET_SECCOMP                   = 0x15
+       PR_GET_SECUREBITS                = 0x1b
+       PR_GET_TID_ADDRESS               = 0x28
+       PR_GET_TIMERSLACK                = 0x1e
+       PR_GET_TIMING                    = 0xd
+       PR_GET_TSC                       = 0x19
+       PR_GET_UNALIGN                   = 0x5
+       PR_MCE_KILL                      = 0x21
+       PR_MCE_KILL_CLEAR                = 0x0
+       PR_MCE_KILL_DEFAULT              = 0x2
+       PR_MCE_KILL_EARLY                = 0x1
+       PR_MCE_KILL_GET                  = 0x22
+       PR_MCE_KILL_LATE                 = 0x0
+       PR_MCE_KILL_SET                  = 0x1
+       PR_SET_CHILD_SUBREAPER           = 0x24
+       PR_SET_DUMPABLE                  = 0x4
+       PR_SET_ENDIAN                    = 0x14
+       PR_SET_FPEMU                     = 0xa
+       PR_SET_FPEXC                     = 0xc
+       PR_SET_KEEPCAPS                  = 0x8
+       PR_SET_MM                        = 0x23
+       PR_SET_MM_ARG_END                = 0x9
+       PR_SET_MM_ARG_START              = 0x8
+       PR_SET_MM_AUXV                   = 0xc
+       PR_SET_MM_BRK                    = 0x7
+       PR_SET_MM_END_CODE               = 0x2
+       PR_SET_MM_END_DATA               = 0x4
+       PR_SET_MM_ENV_END                = 0xb
+       PR_SET_MM_ENV_START              = 0xa
+       PR_SET_MM_EXE_FILE               = 0xd
+       PR_SET_MM_START_BRK              = 0x6
+       PR_SET_MM_START_CODE             = 0x1
+       PR_SET_MM_START_DATA             = 0x3
+       PR_SET_MM_START_STACK            = 0x5
+       PR_SET_NAME                      = 0xf
+       PR_SET_NO_NEW_PRIVS              = 0x26
+       PR_SET_PDEATHSIG                 = 0x1
+       PR_SET_PTRACER                   = 0x59616d61
+       PR_SET_PTRACER_ANY               = -0x1
+       PR_SET_SECCOMP                   = 0x16
+       PR_SET_SECUREBITS                = 0x1c
+       PR_SET_TIMERSLACK                = 0x1d
+       PR_SET_TIMING                    = 0xe
+       PR_SET_TSC                       = 0x1a
+       PR_SET_UNALIGN                   = 0x6
+       PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+       PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+       PR_TIMING_STATISTICAL            = 0x0
+       PR_TIMING_TIMESTAMP              = 0x1
+       PR_TSC_ENABLE                    = 0x1
+       PR_TSC_SIGSEGV                   = 0x2
+       PR_UNALIGN_NOPRINT               = 0x1
+       PR_UNALIGN_SIGBUS                = 0x2
+       PTRACE_ATTACH                    = 0x10
+       PTRACE_CONT                      = 0x7
+       PTRACE_DETACH                    = 0x11
+       PTRACE_EVENT_CLONE               = 0x3
+       PTRACE_EVENT_EXEC                = 0x4
+       PTRACE_EVENT_EXIT                = 0x6
+       PTRACE_EVENT_FORK                = 0x1
+       PTRACE_EVENT_SECCOMP             = 0x7
+       PTRACE_EVENT_STOP                = 0x80
+       PTRACE_EVENT_VFORK               = 0x2
+       PTRACE_EVENT_VFORK_DONE          = 0x5
+       PTRACE_GETEVENTMSG               = 0x4201
+       PTRACE_GETEVRREGS                = 0x14
+       PTRACE_GETFPREGS                 = 0xe
+       PTRACE_GETREGS                   = 0xc
+       PTRACE_GETREGS64                 = 0x16
+       PTRACE_GETREGSET                 = 0x4204
+       PTRACE_GETSIGINFO                = 0x4202
+       PTRACE_GETSIGMASK                = 0x420a
+       PTRACE_GETVRREGS                 = 0x12
+       PTRACE_GETVSRREGS                = 0x1b
+       PTRACE_GET_DEBUGREG              = 0x19
+       PTRACE_INTERRUPT                 = 0x4207
+       PTRACE_KILL                      = 0x8
+       PTRACE_LISTEN                    = 0x4208
+       PTRACE_O_EXITKILL                = 0x100000
+       PTRACE_O_MASK                    = 0x1000ff
+       PTRACE_O_TRACECLONE              = 0x8
+       PTRACE_O_TRACEEXEC               = 0x10
+       PTRACE_O_TRACEEXIT               = 0x40
+       PTRACE_O_TRACEFORK               = 0x2
+       PTRACE_O_TRACESECCOMP            = 0x80
+       PTRACE_O_TRACESYSGOOD            = 0x1
+       PTRACE_O_TRACEVFORK              = 0x4
+       PTRACE_O_TRACEVFORKDONE          = 0x20
+       PTRACE_PEEKDATA                  = 0x2
+       PTRACE_PEEKSIGINFO               = 0x4209
+       PTRACE_PEEKSIGINFO_SHARED        = 0x1
+       PTRACE_PEEKTEXT                  = 0x1
+       PTRACE_PEEKUSR                   = 0x3
+       PTRACE_POKEDATA                  = 0x5
+       PTRACE_POKETEXT                  = 0x4
+       PTRACE_POKEUSR                   = 0x6
+       PTRACE_SEIZE                     = 0x4206
+       PTRACE_SETEVRREGS                = 0x15
+       PTRACE_SETFPREGS                 = 0xf
+       PTRACE_SETOPTIONS                = 0x4200
+       PTRACE_SETREGS                   = 0xd
+       PTRACE_SETREGS64                 = 0x17
+       PTRACE_SETREGSET                 = 0x4205
+       PTRACE_SETSIGINFO                = 0x4203
+       PTRACE_SETSIGMASK                = 0x420b
+       PTRACE_SETVRREGS                 = 0x13
+       PTRACE_SETVSRREGS                = 0x1c
+       PTRACE_SET_DEBUGREG              = 0x1a
+       PTRACE_SINGLEBLOCK               = 0x100
+       PTRACE_SINGLESTEP                = 0x9
+       PTRACE_SYSCALL                   = 0x18
+       PTRACE_TRACEME                   = 0x0
+       PT_CCR                           = 0x26
+       PT_CTR                           = 0x23
+       PT_DAR                           = 0x29
+       PT_DSCR                          = 0x2c
+       PT_DSISR                         = 0x2a
+       PT_FPR0                          = 0x30
+       PT_FPSCR                         = 0x50
+       PT_LNK                           = 0x24
+       PT_MSR                           = 0x21
+       PT_NIP                           = 0x20
+       PT_ORIG_R3                       = 0x22
+       PT_R0                            = 0x0
+       PT_R1                            = 0x1
+       PT_R10                           = 0xa
+       PT_R11                           = 0xb
+       PT_R12                           = 0xc
+       PT_R13                           = 0xd
+       PT_R14                           = 0xe
+       PT_R15                           = 0xf
+       PT_R16                           = 0x10
+       PT_R17                           = 0x11
+       PT_R18                           = 0x12
+       PT_R19                           = 0x13
+       PT_R2                            = 0x2
+       PT_R20                           = 0x14
+       PT_R21                           = 0x15
+       PT_R22                           = 0x16
+       PT_R23                           = 0x17
+       PT_R24                           = 0x18
+       PT_R25                           = 0x19
+       PT_R26                           = 0x1a
+       PT_R27                           = 0x1b
+       PT_R28                           = 0x1c
+       PT_R29                           = 0x1d
+       PT_R3                            = 0x3
+       PT_R30                           = 0x1e
+       PT_R31                           = 0x1f
+       PT_R4                            = 0x4
+       PT_R5                            = 0x5
+       PT_R6                            = 0x6
+       PT_R7                            = 0x7
+       PT_R8                            = 0x8
+       PT_R9                            = 0x9
+       PT_REGS_COUNT                    = 0x2c
+       PT_RESULT                        = 0x2b
+       PT_SOFTE                         = 0x27
+       PT_TRAP                          = 0x28
+       PT_VR0                           = 0x52
+       PT_VRSAVE                        = 0x94
+       PT_VSCR                          = 0x93
+       PT_VSR0                          = 0x96
+       PT_VSR31                         = 0xd4
+       PT_XER                           = 0x25
+       RLIMIT_AS                        = 0x9
+       RLIMIT_CORE                      = 0x4
+       RLIMIT_CPU                       = 0x0
+       RLIMIT_DATA                      = 0x2
+       RLIMIT_FSIZE                     = 0x1
+       RLIMIT_NOFILE                    = 0x7
+       RLIMIT_STACK                     = 0x3
+       RLIM_INFINITY                    = -0x1
+       RTAX_ADVMSS                      = 0x8
+       RTAX_CWND                        = 0x7
+       RTAX_FEATURES                    = 0xc
+       RTAX_FEATURE_ALLFRAG             = 0x8
+       RTAX_FEATURE_ECN                 = 0x1
+       RTAX_FEATURE_SACK                = 0x2
+       RTAX_FEATURE_TIMESTAMP           = 0x4
+       RTAX_HOPLIMIT                    = 0xa
+       RTAX_INITCWND                    = 0xb
+       RTAX_INITRWND                    = 0xe
+       RTAX_LOCK                        = 0x1
+       RTAX_MAX                         = 0xf
+       RTAX_MTU                         = 0x2
+       RTAX_QUICKACK                    = 0xf
+       RTAX_REORDERING                  = 0x9
+       RTAX_RTO_MIN                     = 0xd
+       RTAX_RTT                         = 0x4
+       RTAX_RTTVAR                      = 0x5
+       RTAX_SSTHRESH                    = 0x6
+       RTAX_UNSPEC                      = 0x0
+       RTAX_WINDOW                      = 0x3
+       RTA_ALIGNTO                      = 0x4
+       RTA_MAX                          = 0x11
+       RTCF_DIRECTSRC                   = 0x4000000
+       RTCF_DOREDIRECT                  = 0x1000000
+       RTCF_LOG                         = 0x2000000
+       RTCF_MASQ                        = 0x400000
+       RTCF_NAT                         = 0x800000
+       RTCF_VALVE                       = 0x200000
+       RTF_ADDRCLASSMASK                = 0xf8000000
+       RTF_ADDRCONF                     = 0x40000
+       RTF_ALLONLINK                    = 0x20000
+       RTF_BROADCAST                    = 0x10000000
+       RTF_CACHE                        = 0x1000000
+       RTF_DEFAULT                      = 0x10000
+       RTF_DYNAMIC                      = 0x10
+       RTF_FLOW                         = 0x2000000
+       RTF_GATEWAY                      = 0x2
+       RTF_HOST                         = 0x4
+       RTF_INTERFACE                    = 0x40000000
+       RTF_IRTT                         = 0x100
+       RTF_LINKRT                       = 0x100000
+       RTF_LOCAL                        = 0x80000000
+       RTF_MODIFIED                     = 0x20
+       RTF_MSS                          = 0x40
+       RTF_MTU                          = 0x40
+       RTF_MULTICAST                    = 0x20000000
+       RTF_NAT                          = 0x8000000
+       RTF_NOFORWARD                    = 0x1000
+       RTF_NONEXTHOP                    = 0x200000
+       RTF_NOPMTUDISC                   = 0x4000
+       RTF_POLICY                       = 0x4000000
+       RTF_REINSTATE                    = 0x8
+       RTF_REJECT                       = 0x200
+       RTF_STATIC                       = 0x400
+       RTF_THROW                        = 0x2000
+       RTF_UP                           = 0x1
+       RTF_WINDOW                       = 0x80
+       RTF_XRESOLVE                     = 0x800
+       RTM_BASE                         = 0x10
+       RTM_DELACTION                    = 0x31
+       RTM_DELADDR                      = 0x15
+       RTM_DELADDRLABEL                 = 0x49
+       RTM_DELLINK                      = 0x11
+       RTM_DELMDB                       = 0x55
+       RTM_DELNEIGH                     = 0x1d
+       RTM_DELQDISC                     = 0x25
+       RTM_DELROUTE                     = 0x19
+       RTM_DELRULE                      = 0x21
+       RTM_DELTCLASS                    = 0x29
+       RTM_DELTFILTER                   = 0x2d
+       RTM_F_CLONED                     = 0x200
+       RTM_F_EQUALIZE                   = 0x400
+       RTM_F_NOTIFY                     = 0x100
+       RTM_F_PREFIX                     = 0x800
+       RTM_GETACTION                    = 0x32
+       RTM_GETADDR                      = 0x16
+       RTM_GETADDRLABEL                 = 0x4a
+       RTM_GETANYCAST                   = 0x3e
+       RTM_GETDCB                       = 0x4e
+       RTM_GETLINK                      = 0x12
+       RTM_GETMDB                       = 0x56
+       RTM_GETMULTICAST                 = 0x3a
+       RTM_GETNEIGH                     = 0x1e
+       RTM_GETNEIGHTBL                  = 0x42
+       RTM_GETNETCONF                   = 0x52
+       RTM_GETQDISC                     = 0x26
+       RTM_GETROUTE                     = 0x1a
+       RTM_GETRULE                      = 0x22
+       RTM_GETTCLASS                    = 0x2a
+       RTM_GETTFILTER                   = 0x2e
+       RTM_MAX                          = 0x57
+       RTM_NEWACTION                    = 0x30
+       RTM_NEWADDR                      = 0x14
+       RTM_NEWADDRLABEL                 = 0x48
+       RTM_NEWLINK                      = 0x10
+       RTM_NEWMDB                       = 0x54
+       RTM_NEWNDUSEROPT                 = 0x44
+       RTM_NEWNEIGH                     = 0x1c
+       RTM_NEWNEIGHTBL                  = 0x40
+       RTM_NEWNETCONF                   = 0x50
+       RTM_NEWPREFIX                    = 0x34
+       RTM_NEWQDISC                     = 0x24
+       RTM_NEWROUTE                     = 0x18
+       RTM_NEWRULE                      = 0x20
+       RTM_NEWTCLASS                    = 0x28
+       RTM_NEWTFILTER                   = 0x2c
+       RTM_NR_FAMILIES                  = 0x12
+       RTM_NR_MSGTYPES                  = 0x48
+       RTM_SETDCB                       = 0x4f
+       RTM_SETLINK                      = 0x13
+       RTM_SETNEIGHTBL                  = 0x43
+       RTNH_ALIGNTO                     = 0x4
+       RTNH_F_DEAD                      = 0x1
+       RTNH_F_ONLINK                    = 0x4
+       RTNH_F_PERVASIVE                 = 0x2
+       RTN_MAX                          = 0xb
+       RTPROT_BIRD                      = 0xc
+       RTPROT_BOOT                      = 0x3
+       RTPROT_DHCP                      = 0x10
+       RTPROT_DNROUTED                  = 0xd
+       RTPROT_GATED                     = 0x8
+       RTPROT_KERNEL                    = 0x2
+       RTPROT_MROUTED                   = 0x11
+       RTPROT_MRT                       = 0xa
+       RTPROT_NTK                       = 0xf
+       RTPROT_RA                        = 0x9
+       RTPROT_REDIRECT                  = 0x1
+       RTPROT_STATIC                    = 0x4
+       RTPROT_UNSPEC                    = 0x0
+       RTPROT_XORP                      = 0xe
+       RTPROT_ZEBRA                     = 0xb
+       RT_CLASS_DEFAULT                 = 0xfd
+       RT_CLASS_LOCAL                   = 0xff
+       RT_CLASS_MAIN                    = 0xfe
+       RT_CLASS_MAX                     = 0xff
+       RT_CLASS_UNSPEC                  = 0x0
+       RUSAGE_CHILDREN                  = -0x1
+       RUSAGE_SELF                      = 0x0
+       RUSAGE_THREAD                    = 0x1
+       SCM_CREDENTIALS                  = 0x2
+       SCM_RIGHTS                       = 0x1
+       SCM_TIMESTAMP                    = 0x1d
+       SCM_TIMESTAMPING                 = 0x25
+       SCM_TIMESTAMPNS                  = 0x23
+       SCM_WIFI_STATUS                  = 0x29
+       SHUT_RD                          = 0x0
+       SHUT_RDWR                        = 0x2
+       SHUT_WR                          = 0x1
+       SIOCADDDLCI                      = 0x8980
+       SIOCADDMULTI                     = 0x8931
+       SIOCADDRT                        = 0x890b
+       SIOCATMARK                       = 0x8905
+       SIOCDARP                         = 0x8953
+       SIOCDELDLCI                      = 0x8981
+       SIOCDELMULTI                     = 0x8932
+       SIOCDELRT                        = 0x890c
+       SIOCDEVPRIVATE                   = 0x89f0
+       SIOCDIFADDR                      = 0x8936
+       SIOCDRARP                        = 0x8960
+       SIOCGARP                         = 0x8954
+       SIOCGIFADDR                      = 0x8915
+       SIOCGIFBR                        = 0x8940
+       SIOCGIFBRDADDR                   = 0x8919
+       SIOCGIFCONF                      = 0x8912
+       SIOCGIFCOUNT                     = 0x8938
+       SIOCGIFDSTADDR                   = 0x8917
+       SIOCGIFENCAP                     = 0x8925
+       SIOCGIFFLAGS                     = 0x8913
+       SIOCGIFHWADDR                    = 0x8927
+       SIOCGIFINDEX                     = 0x8933
+       SIOCGIFMAP                       = 0x8970
+       SIOCGIFMEM                       = 0x891f
+       SIOCGIFMETRIC                    = 0x891d
+       SIOCGIFMTU                       = 0x8921
+       SIOCGIFNAME                      = 0x8910
+       SIOCGIFNETMASK                   = 0x891b
+       SIOCGIFPFLAGS                    = 0x8935
+       SIOCGIFSLAVE                     = 0x8929
+       SIOCGIFTXQLEN                    = 0x8942
+       SIOCGPGRP                        = 0x8904
+       SIOCGRARP                        = 0x8961
+       SIOCGSTAMP                       = 0x8906
+       SIOCGSTAMPNS                     = 0x8907
+       SIOCPROTOPRIVATE                 = 0x89e0
+       SIOCRTMSG                        = 0x890d
+       SIOCSARP                         = 0x8955
+       SIOCSIFADDR                      = 0x8916
+       SIOCSIFBR                        = 0x8941
+       SIOCSIFBRDADDR                   = 0x891a
+       SIOCSIFDSTADDR                   = 0x8918
+       SIOCSIFENCAP                     = 0x8926
+       SIOCSIFFLAGS                     = 0x8914
+       SIOCSIFHWADDR                    = 0x8924
+       SIOCSIFHWBROADCAST               = 0x8937
+       SIOCSIFLINK                      = 0x8911
+       SIOCSIFMAP                       = 0x8971
+       SIOCSIFMEM                       = 0x8920
+       SIOCSIFMETRIC                    = 0x891e
+       SIOCSIFMTU                       = 0x8922
+       SIOCSIFNAME                      = 0x8923
+       SIOCSIFNETMASK                   = 0x891c
+       SIOCSIFPFLAGS                    = 0x8934
+       SIOCSIFSLAVE                     = 0x8930
+       SIOCSIFTXQLEN                    = 0x8943
+       SIOCSPGRP                        = 0x8902
+       SIOCSRARP                        = 0x8962
+       SOCK_CLOEXEC                     = 0x80000
+       SOCK_DCCP                        = 0x6
+       SOCK_DGRAM                       = 0x2
+       SOCK_NONBLOCK                    = 0x800
+       SOCK_PACKET                      = 0xa
+       SOCK_RAW                         = 0x3
+       SOCK_RDM                         = 0x4
+       SOCK_SEQPACKET                   = 0x5
+       SOCK_STREAM                      = 0x1
+       SOL_AAL                          = 0x109
+       SOL_ATM                          = 0x108
+       SOL_DECNET                       = 0x105
+       SOL_ICMPV6                       = 0x3a
+       SOL_IP                           = 0x0
+       SOL_IPV6                         = 0x29
+       SOL_IRDA                         = 0x10a
+       SOL_PACKET                       = 0x107
+       SOL_RAW                          = 0xff
+       SOL_SOCKET                       = 0x1
+       SOL_TCP                          = 0x6
+       SOL_X25                          = 0x106
+       SOMAXCONN                        = 0x80
+       SO_ACCEPTCONN                    = 0x1e
+       SO_ATTACH_FILTER                 = 0x1a
+       SO_BINDTODEVICE                  = 0x19
+       SO_BROADCAST                     = 0x6
+       SO_BSDCOMPAT                     = 0xe
+       SO_BUSY_POLL                     = 0x2e
+       SO_DEBUG                         = 0x1
+       SO_DETACH_FILTER                 = 0x1b
+       SO_DOMAIN                        = 0x27
+       SO_DONTROUTE                     = 0x5
+       SO_ERROR                         = 0x4
+       SO_GET_FILTER                    = 0x1a
+       SO_KEEPALIVE                     = 0x9
+       SO_LINGER                        = 0xd
+       SO_LOCK_FILTER                   = 0x2c
+       SO_MARK                          = 0x24
+       SO_MAX_PACING_RATE               = 0x2f
+       SO_NOFCS                         = 0x2b
+       SO_NO_CHECK                      = 0xb
+       SO_OOBINLINE                     = 0xa
+       SO_PASSCRED                      = 0x14
+       SO_PASSSEC                       = 0x22
+       SO_PEEK_OFF                      = 0x2a
+       SO_PEERCRED                      = 0x15
+       SO_PEERNAME                      = 0x1c
+       SO_PEERSEC                       = 0x1f
+       SO_PRIORITY                      = 0xc
+       SO_PROTOCOL                      = 0x26
+       SO_RCVBUF                        = 0x8
+       SO_RCVBUFFORCE                   = 0x21
+       SO_RCVLOWAT                      = 0x10
+       SO_RCVTIMEO                      = 0x12
+       SO_REUSEADDR                     = 0x2
+       SO_REUSEPORT                     = 0xf
+       SO_RXQ_OVFL                      = 0x28
+       SO_SECURITY_AUTHENTICATION       = 0x16
+       SO_SECURITY_ENCRYPTION_NETWORK   = 0x18
+       SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
+       SO_SELECT_ERR_QUEUE              = 0x2d
+       SO_SNDBUF                        = 0x7
+       SO_SNDBUFFORCE                   = 0x20
+       SO_SNDLOWAT                      = 0x11
+       SO_SNDTIMEO                      = 0x13
+       SO_TIMESTAMP                     = 0x1d
+       SO_TIMESTAMPING                  = 0x25
+       SO_TIMESTAMPNS                   = 0x23
+       SO_TYPE                          = 0x3
+       SO_WIFI_STATUS                   = 0x29
+       S_BLKSIZE                        = 0x200
+       S_IEXEC                          = 0x40
+       S_IFBLK                          = 0x6000
+       S_IFCHR                          = 0x2000
+       S_IFDIR                          = 0x4000
+       S_IFIFO                          = 0x1000
+       S_IFLNK                          = 0xa000
+       S_IFMT                           = 0xf000
+       S_IFREG                          = 0x8000
+       S_IFSOCK                         = 0xc000
+       S_IREAD                          = 0x100
+       S_IRGRP                          = 0x20
+       S_IROTH                          = 0x4
+       S_IRUSR                          = 0x100
+       S_IRWXG                          = 0x38
+       S_IRWXO                          = 0x7
+       S_IRWXU                          = 0x1c0
+       S_ISGID                          = 0x400
+       S_ISUID                          = 0x800
+       S_ISVTX                          = 0x200
+       S_IWGRP                          = 0x10
+       S_IWOTH                          = 0x2
+       S_IWRITE                         = 0x80
+       S_IWUSR                          = 0x80
+       S_IXGRP                          = 0x8
+       S_IXOTH                          = 0x1
+       S_IXUSR                          = 0x40
+       TCFLSH                           = 0x2000741f
+       TCIFLUSH                         = 0x0
+       TCIOFLUSH                        = 0x2
+       TCOFLUSH                         = 0x1
+       TCP_CONGESTION                   = 0xd
+       TCP_COOKIE_IN_ALWAYS             = 0x1
+       TCP_COOKIE_MAX                   = 0x10
+       TCP_COOKIE_MIN                   = 0x8
+       TCP_COOKIE_OUT_NEVER             = 0x2
+       TCP_COOKIE_PAIR_SIZE             = 0x20
+       TCP_COOKIE_TRANSACTIONS          = 0xf
+       TCP_CORK                         = 0x3
+       TCP_DEFER_ACCEPT                 = 0x9
+       TCP_FASTOPEN                     = 0x17
+       TCP_INFO                         = 0xb
+       TCP_KEEPCNT                      = 0x6
+       TCP_KEEPIDLE                     = 0x4
+       TCP_KEEPINTVL                    = 0x5
+       TCP_LINGER2                      = 0x8
+       TCP_MAXSEG                       = 0x2
+       TCP_MAXWIN                       = 0xffff
+       TCP_MAX_WINSHIFT                 = 0xe
+       TCP_MD5SIG                       = 0xe
+       TCP_MD5SIG_MAXKEYLEN             = 0x50
+       TCP_MSS                          = 0x200
+       TCP_MSS_DEFAULT                  = 0x218
+       TCP_MSS_DESIRED                  = 0x4c4
+       TCP_NODELAY                      = 0x1
+       TCP_QUEUE_SEQ                    = 0x15
+       TCP_QUICKACK                     = 0xc
+       TCP_REPAIR                       = 0x13
+       TCP_REPAIR_OPTIONS               = 0x16
+       TCP_REPAIR_QUEUE                 = 0x14
+       TCP_SYNCNT                       = 0x7
+       TCP_S_DATA_IN                    = 0x4
+       TCP_S_DATA_OUT                   = 0x8
+       TCP_THIN_DUPACK                  = 0x11
+       TCP_THIN_LINEAR_TIMEOUTS         = 0x10
+       TCP_TIMESTAMP                    = 0x18
+       TCP_USER_TIMEOUT                 = 0x12
+       TCP_WINDOW_CLAMP                 = 0xa
+       TCSAFLUSH                        = 0x2
+       TIOCCBRK                         = 0x5428
+       TIOCCONS                         = 0x541d
+       TIOCEXCL                         = 0x540c
+       TIOCGDEV                         = 0x40045432
+       TIOCGETC                         = 0x40067412
+       TIOCGETD                         = 0x5424
+       TIOCGETP                         = 0x40067408
+       TIOCGEXCL                        = 0x40045440
+       TIOCGICOUNT                      = 0x545d
+       TIOCGLCKTRMIOS                   = 0x5456
+       TIOCGLTC                         = 0x40067474
+       TIOCGPGRP                        = 0x40047477
+       TIOCGPKT                         = 0x40045438
+       TIOCGPTLCK                       = 0x40045439
+       TIOCGPTN                         = 0x40045430
+       TIOCGRS485                       = 0x542e
+       TIOCGSERIAL                      = 0x541e
+       TIOCGSID                         = 0x5429
+       TIOCGSOFTCAR                     = 0x5419
+       TIOCGWINSZ                       = 0x40087468
+       TIOCINQ                          = 0x4004667f
+       TIOCLINUX                        = 0x541c
+       TIOCMBIC                         = 0x5417
+       TIOCMBIS                         = 0x5416
+       TIOCMGET                         = 0x5415
+       TIOCMIWAIT                       = 0x545c
+       TIOCMSET                         = 0x5418
+       TIOCM_CAR                        = 0x40
+       TIOCM_CD                         = 0x40
+       TIOCM_CTS                        = 0x20
+       TIOCM_DSR                        = 0x100
+       TIOCM_DTR                        = 0x2
+       TIOCM_LE                         = 0x1
+       TIOCM_LOOP                       = 0x8000
+       TIOCM_OUT1                       = 0x2000
+       TIOCM_OUT2                       = 0x4000
+       TIOCM_RI                         = 0x80
+       TIOCM_RNG                        = 0x80
+       TIOCM_RTS                        = 0x4
+       TIOCM_SR                         = 0x10
+       TIOCM_ST                         = 0x8
+       TIOCNOTTY                        = 0x5422
+       TIOCNXCL                         = 0x540d
+       TIOCOUTQ                         = 0x40047473
+       TIOCPKT                          = 0x5420
+       TIOCPKT_DATA                     = 0x0
+       TIOCPKT_DOSTOP                   = 0x20
+       TIOCPKT_FLUSHREAD                = 0x1
+       TIOCPKT_FLUSHWRITE               = 0x2
+       TIOCPKT_IOCTL                    = 0x40
+       TIOCPKT_NOSTOP                   = 0x10
+       TIOCPKT_START                    = 0x8
+       TIOCPKT_STOP                     = 0x4
+       TIOCSBRK                         = 0x5427
+       TIOCSCTTY                        = 0x540e
+       TIOCSERCONFIG                    = 0x5453
+       TIOCSERGETLSR                    = 0x5459
+       TIOCSERGETMULTI                  = 0x545a
+       TIOCSERGSTRUCT                   = 0x5458
+       TIOCSERGWILD                     = 0x5454
+       TIOCSERSETMULTI                  = 0x545b
+       TIOCSERSWILD                     = 0x5455
+       TIOCSER_TEMT                     = 0x1
+       TIOCSETC                         = 0x80067411
+       TIOCSETD                         = 0x5423
+       TIOCSETN                         = 0x8006740a
+       TIOCSETP                         = 0x80067409
+       TIOCSIG                          = 0x80045436
+       TIOCSLCKTRMIOS                   = 0x5457
+       TIOCSLTC                         = 0x80067475
+       TIOCSPGRP                        = 0x80047476
+       TIOCSPTLCK                       = 0x80045431
+       TIOCSRS485                       = 0x542f
+       TIOCSSERIAL                      = 0x541f
+       TIOCSSOFTCAR                     = 0x541a
+       TIOCSTART                        = 0x2000746e
+       TIOCSTI                          = 0x5412
+       TIOCSTOP                         = 0x2000746f
+       TIOCSWINSZ                       = 0x80087467
+       TIOCVHANGUP                      = 0x5437
+       TOSTOP                           = 0x400000
+       TUNATTACHFILTER                  = 0x801054d5
+       TUNDETACHFILTER                  = 0x801054d6
+       TUNGETFEATURES                   = 0x400454cf
+       TUNGETFILTER                     = 0x401054db
+       TUNGETIFF                        = 0x400454d2
+       TUNGETSNDBUF                     = 0x400454d3
+       TUNGETVNETHDRSZ                  = 0x400454d7
+       TUNSETDEBUG                      = 0x800454c9
+       TUNSETGROUP                      = 0x800454ce
+       TUNSETIFF                        = 0x800454ca
+       TUNSETIFINDEX                    = 0x800454da
+       TUNSETLINK                       = 0x800454cd
+       TUNSETNOCSUM                     = 0x800454c8
+       TUNSETOFFLOAD                    = 0x800454d0
+       TUNSETOWNER                      = 0x800454cc
+       TUNSETPERSIST                    = 0x800454cb
+       TUNSETQUEUE                      = 0x800454d9
+       TUNSETSNDBUF                     = 0x800454d4
+       TUNSETTXFILTER                   = 0x800454d1
+       TUNSETVNETHDRSZ                  = 0x800454d8
+       VDISCARD                         = 0x10
+       VEOF                             = 0x4
+       VEOL                             = 0x6
+       VEOL2                            = 0x8
+       VERASE                           = 0x2
+       VINTR                            = 0x0
+       VKILL                            = 0x3
+       VLNEXT                           = 0xf
+       VMIN                             = 0x5
+       VQUIT                            = 0x1
+       VREPRINT                         = 0xb
+       VSTART                           = 0xd
+       VSTOP                            = 0xe
+       VSUSP                            = 0xc
+       VSWTC                            = 0x9
+       VT0                              = 0x0
+       VT1                              = 0x10000
+       VTDLY                            = 0x10000
+       VTIME                            = 0x7
+       VWERASE                          = 0xa
+       WALL                             = 0x40000000
+       WCLONE                           = 0x80000000
+       WCONTINUED                       = 0x8
+       WEXITED                          = 0x4
+       WNOHANG                          = 0x1
+       WNOTHREAD                        = 0x20000000
+       WNOWAIT                          = 0x1000000
+       WORDSIZE                         = 0x40
+       WSTOPPED                         = 0x2
+       WUNTRACED                        = 0x2
+)
+
+// Errors
+const (
+       E2BIG           = Errno(0x7)
+       EACCES          = Errno(0xd)
+       EADDRINUSE      = Errno(0x62)
+       EADDRNOTAVAIL   = Errno(0x63)
+       EADV            = Errno(0x44)
+       EAFNOSUPPORT    = Errno(0x61)
+       EAGAIN          = Errno(0xb)
+       EALREADY        = Errno(0x72)
+       EBADE           = Errno(0x34)
+       EBADF           = Errno(0x9)
+       EBADFD          = Errno(0x4d)
+       EBADMSG         = Errno(0x4a)
+       EBADR           = Errno(0x35)
+       EBADRQC         = Errno(0x38)
+       EBADSLT         = Errno(0x39)
+       EBFONT          = Errno(0x3b)
+       EBUSY           = Errno(0x10)
+       ECANCELED       = Errno(0x7d)
+       ECHILD          = Errno(0xa)
+       ECHRNG          = Errno(0x2c)
+       ECOMM           = Errno(0x46)
+       ECONNABORTED    = Errno(0x67)
+       ECONNREFUSED    = Errno(0x6f)
+       ECONNRESET      = Errno(0x68)
+       EDEADLK         = Errno(0x23)
+       EDEADLOCK       = Errno(0x3a)
+       EDESTADDRREQ    = Errno(0x59)
+       EDOM            = Errno(0x21)
+       EDOTDOT         = Errno(0x49)
+       EDQUOT          = Errno(0x7a)
+       EEXIST          = Errno(0x11)
+       EFAULT          = Errno(0xe)
+       EFBIG           = Errno(0x1b)
+       EHOSTDOWN       = Errno(0x70)
+       EHOSTUNREACH    = Errno(0x71)
+       EHWPOISON       = Errno(0x85)
+       EIDRM           = Errno(0x2b)
+       EILSEQ          = Errno(0x54)
+       EINPROGRESS     = Errno(0x73)
+       EINTR           = Errno(0x4)
+       EINVAL          = Errno(0x16)
+       EIO             = Errno(0x5)
+       EISCONN         = Errno(0x6a)
+       EISDIR          = Errno(0x15)
+       EISNAM          = Errno(0x78)
+       EKEYEXPIRED     = Errno(0x7f)
+       EKEYREJECTED    = Errno(0x81)
+       EKEYREVOKED     = Errno(0x80)
+       EL2HLT          = Errno(0x33)
+       EL2NSYNC        = Errno(0x2d)
+       EL3HLT          = Errno(0x2e)
+       EL3RST          = Errno(0x2f)
+       ELIBACC         = Errno(0x4f)
+       ELIBBAD         = Errno(0x50)
+       ELIBEXEC        = Errno(0x53)
+       ELIBMAX         = Errno(0x52)
+       ELIBSCN         = Errno(0x51)
+       ELNRNG          = Errno(0x30)
+       ELOOP           = Errno(0x28)
+       EMEDIUMTYPE     = Errno(0x7c)
+       EMFILE          = Errno(0x18)
+       EMLINK          = Errno(0x1f)
+       EMSGSIZE        = Errno(0x5a)
+       EMULTIHOP       = Errno(0x48)
+       ENAMETOOLONG    = Errno(0x24)
+       ENAVAIL         = Errno(0x77)
+       ENETDOWN        = Errno(0x64)
+       ENETRESET       = Errno(0x66)
+       ENETUNREACH     = Errno(0x65)
+       ENFILE          = Errno(0x17)
+       ENOANO          = Errno(0x37)
+       ENOBUFS         = Errno(0x69)
+       ENOCSI          = Errno(0x32)
+       ENODATA         = Errno(0x3d)
+       ENODEV          = Errno(0x13)
+       ENOENT          = Errno(0x2)
+       ENOEXEC         = Errno(0x8)
+       ENOKEY          = Errno(0x7e)
+       ENOLCK          = Errno(0x25)
+       ENOLINK         = Errno(0x43)
+       ENOMEDIUM       = Errno(0x7b)
+       ENOMEM          = Errno(0xc)
+       ENOMSG          = Errno(0x2a)
+       ENONET          = Errno(0x40)
+       ENOPKG          = Errno(0x41)
+       ENOPROTOOPT     = Errno(0x5c)
+       ENOSPC          = Errno(0x1c)
+       ENOSR           = Errno(0x3f)
+       ENOSTR          = Errno(0x3c)
+       ENOSYS          = Errno(0x26)
+       ENOTBLK         = Errno(0xf)
+       ENOTCONN        = Errno(0x6b)
+       ENOTDIR         = Errno(0x14)
+       ENOTEMPTY       = Errno(0x27)
+       ENOTNAM         = Errno(0x76)
+       ENOTRECOVERABLE = Errno(0x83)
+       ENOTSOCK        = Errno(0x58)
+       ENOTSUP         = Errno(0x5f)
+       ENOTTY          = Errno(0x19)
+       ENOTUNIQ        = Errno(0x4c)
+       ENXIO           = Errno(0x6)
+       EOPNOTSUPP      = Errno(0x5f)
+       EOVERFLOW       = Errno(0x4b)
+       EOWNERDEAD      = Errno(0x82)
+       EPERM           = Errno(0x1)
+       EPFNOSUPPORT    = Errno(0x60)
+       EPIPE           = Errno(0x20)
+       EPROTO          = Errno(0x47)
+       EPROTONOSUPPORT = Errno(0x5d)
+       EPROTOTYPE      = Errno(0x5b)
+       ERANGE          = Errno(0x22)
+       EREMCHG         = Errno(0x4e)
+       EREMOTE         = Errno(0x42)
+       EREMOTEIO       = Errno(0x79)
+       ERESTART        = Errno(0x55)
+       ERFKILL         = Errno(0x84)
+       EROFS           = Errno(0x1e)
+       ESHUTDOWN       = Errno(0x6c)
+       ESOCKTNOSUPPORT = Errno(0x5e)
+       ESPIPE          = Errno(0x1d)
+       ESRCH           = Errno(0x3)
+       ESRMNT          = Errno(0x45)
+       ESTALE          = Errno(0x74)
+       ESTRPIPE        = Errno(0x56)
+       ETIME           = Errno(0x3e)
+       ETIMEDOUT       = Errno(0x6e)
+       ETOOMANYREFS    = Errno(0x6d)
+       ETXTBSY         = Errno(0x1a)
+       EUCLEAN         = Errno(0x75)
+       EUNATCH         = Errno(0x31)
+       EUSERS          = Errno(0x57)
+       EWOULDBLOCK     = Errno(0xb)
+       EXDEV           = Errno(0x12)
+       EXFULL          = Errno(0x36)
+)
+
+// Signals
+const (
+       SIGABRT   = Signal(0x6)
+       SIGALRM   = Signal(0xe)
+       SIGBUS    = Signal(0x7)
+       SIGCHLD   = Signal(0x11)
+       SIGCLD    = Signal(0x11)
+       SIGCONT   = Signal(0x12)
+       SIGFPE    = Signal(0x8)
+       SIGHUP    = Signal(0x1)
+       SIGILL    = Signal(0x4)
+       SIGINT    = Signal(0x2)
+       SIGIO     = Signal(0x1d)
+       SIGIOT    = Signal(0x6)
+       SIGKILL   = Signal(0x9)
+       SIGPIPE   = Signal(0xd)
+       SIGPOLL   = Signal(0x1d)
+       SIGPROF   = Signal(0x1b)
+       SIGPWR    = Signal(0x1e)
+       SIGQUIT   = Signal(0x3)
+       SIGSEGV   = Signal(0xb)
+       SIGSTKFLT = Signal(0x10)
+       SIGSTOP   = Signal(0x13)
+       SIGSYS    = Signal(0x1f)
+       SIGTERM   = Signal(0xf)
+       SIGTRAP   = Signal(0x5)
+       SIGTSTP   = Signal(0x14)
+       SIGTTIN   = Signal(0x15)
+       SIGTTOU   = Signal(0x16)
+       SIGUNUSED = Signal(0x1f)
+       SIGURG    = Signal(0x17)
+       SIGUSR1   = Signal(0xa)
+       SIGUSR2   = Signal(0xc)
+       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:   "no such device or address",
+       7:   "argument list too long",
+       8:   "exec format error",
+       9:   "bad file descriptor",
+       10:  "no child processes",
+       11:  "resource temporarily unavailable",
+       12:  "cannot allocate memory",
+       13:  "permission denied",
+       14:  "bad address",
+       15:  "block device required",
+       16:  "device or resource busy",
+       17:  "file exists",
+       18:  "invalid cross-device link",
+       19:  "no such device",
+       20:  "not a directory",
+       21:  "is a directory",
+       22:  "invalid argument",
+       23:  "too many open files in system",
+       24:  "too many open files",
+       25:  "inappropriate ioctl for device",
+       26:  "text file busy",
+       27:  "file too large",
+       28:  "no space left on device",
+       29:  "illegal seek",
+       30:  "read-only file system",
+       31:  "too many links",
+       32:  "broken pipe",
+       33:  "numerical argument out of domain",
+       34:  "numerical result out of range",
+       35:  "resource deadlock avoided",
+       36:  "file name too long",
+       37:  "no locks available",
+       38:  "function not implemented",
+       39:  "directory not empty",
+       40:  "too many levels of symbolic links",
+       42:  "no message of desired type",
+       43:  "identifier removed",
+       44:  "channel number out of range",
+       45:  "level 2 not synchronized",
+       46:  "level 3 halted",
+       47:  "level 3 reset",
+       48:  "link number out of range",
+       49:  "protocol driver not attached",
+       50:  "no CSI structure available",
+       51:  "level 2 halted",
+       52:  "invalid exchange",
+       53:  "invalid request descriptor",
+       54:  "exchange full",
+       55:  "no anode",
+       56:  "invalid request code",
+       57:  "invalid slot",
+       58:  "file locking deadlock error",
+       59:  "bad font file format",
+       60:  "device not a stream",
+       61:  "no data available",
+       62:  "timer expired",
+       63:  "out of streams resources",
+       64:  "machine is not on the network",
+       65:  "package not installed",
+       66:  "object is remote",
+       67:  "link has been severed",
+       68:  "advertise error",
+       69:  "srmount error",
+       70:  "communication error on send",
+       71:  "protocol error",
+       72:  "multihop attempted",
+       73:  "RFS specific error",
+       74:  "bad message",
+       75:  "value too large for defined data type",
+       76:  "name not unique on network",
+       77:  "file descriptor in bad state",
+       78:  "remote address changed",
+       79:  "can not access a needed shared library",
+       80:  "accessing a corrupted shared library",
+       81:  ".lib section in a.out corrupted",
+       82:  "attempting to link in too many shared libraries",
+       83:  "cannot exec a shared library directly",
+       84:  "invalid or incomplete multibyte or wide character",
+       85:  "interrupted system call should be restarted",
+       86:  "streams pipe error",
+       87:  "too many users",
+       88:  "socket operation on non-socket",
+       89:  "destination address required",
+       90:  "message too long",
+       91:  "protocol wrong type for socket",
+       92:  "protocol not available",
+       93:  "protocol not supported",
+       94:  "socket type not supported",
+       95:  "operation not supported",
+       96:  "protocol family not supported",
+       97:  "address family not supported by protocol",
+       98:  "address already in use",
+       99:  "cannot assign requested address",
+       100: "network is down",
+       101: "network is unreachable",
+       102: "network dropped connection on reset",
+       103: "software caused connection abort",
+       104: "connection reset by peer",
+       105: "no buffer space available",
+       106: "transport endpoint is already connected",
+       107: "transport endpoint is not connected",
+       108: "cannot send after transport endpoint shutdown",
+       109: "too many references: cannot splice",
+       110: "connection timed out",
+       111: "connection refused",
+       112: "host is down",
+       113: "no route to host",
+       114: "operation already in progress",
+       115: "operation now in progress",
+       116: "stale file handle",
+       117: "structure needs cleaning",
+       118: "not a XENIX named type file",
+       119: "no XENIX semaphores available",
+       120: "is a named type file",
+       121: "remote I/O error",
+       122: "disk quota exceeded",
+       123: "no medium found",
+       124: "wrong medium type",
+       125: "operation canceled",
+       126: "required key not available",
+       127: "key has expired",
+       128: "key has been revoked",
+       129: "key was rejected by service",
+       130: "owner died",
+       131: "state not recoverable",
+       132: "operation not possible due to RF-kill",
+       133: "memory page has hardware error",
+}
+
+// Signal table
+var signals = [...]string{
+       1:  "hangup",
+       2:  "interrupt",
+       3:  "quit",
+       4:  "illegal instruction",
+       5:  "trace/breakpoint trap",
+       6:  "aborted",
+       7:  "bus error",
+       8:  "floating point exception",
+       9:  "killed",
+       10: "user defined signal 1",
+       11: "segmentation fault",
+       12: "user defined signal 2",
+       13: "broken pipe",
+       14: "alarm clock",
+       15: "terminated",
+       16: "stack fault",
+       17: "child exited",
+       18: "continued",
+       19: "stopped (signal)",
+       20: "stopped",
+       21: "stopped (tty input)",
+       22: "stopped (tty output)",
+       23: "urgent I/O condition",
+       24: "CPU time limit exceeded",
+       25: "file size limit exceeded",
+       26: "virtual timer expired",
+       27: "profiling timer expired",
+       28: "window changed",
+       29: "I/O possible",
+       30: "power failure",
+       31: "bad system call",
+}
diff --git a/src/syscall/zsyscall_linux_power64.go b/src/syscall/zsyscall_linux_power64.go
new file mode 100644 (file)
index 0000000..7808059
--- /dev/null
@@ -0,0 +1,1931 @@
+// mksyscall.pl syscall_linux.go syscall_linux_power64x.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 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 openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]_C_int) (err error) {
+       _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags int) (err error) {
+       _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, times *[2]Timeval) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
+       _, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getcwd(buf []byte) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(buf) > 0 {
+               _p0 = unsafe.Pointer(&buf[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = 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 ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
+       _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(arg)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(source)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(target)
+       if err != nil {
+               return
+       }
+       var _p2 *byte
+       _p2, err = BytePtrFromString(fstype)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+       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 Acct(path string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtimex(buf *Timex) (state int, err error) {
+       r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
+       state = int(r0)
+       if e1 != 0 {
+               err = 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 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 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 Creat(path string, mode uint32) (fd int, err error) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_DUP, uintptr(oldfd), 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 Dup2(oldfd int, newfd int) (err error) {
+       _, _, e1 := RawSyscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup3(oldfd int, newfd int, flags int) (err error) {
+       _, _, e1 := RawSyscall(SYS_DUP3, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate(size int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+       _, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(events) > 0 {
+               _p0 = unsafe.Pointer(&events[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+       Syscall(SYS_EXIT_GROUP, uintptr(code), 0, 0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
+       _, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+       _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+       if e1 != 0 {
+               err = 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 Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+       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 Fdatasync(fd int) (err error) {
+       _, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
+       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 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 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_GETDENTS64, 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 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() (pid int) {
+       r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0)
+       pid = 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 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 Gettid() (tid int) {
+       r0, _, _ := RawSyscall(SYS_GETTID, 0, 0, 0)
+       tid = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(attr)
+       if err != nil {
+               return
+       }
+       var _p2 unsafe.Pointer
+       if len(dest) > 0 {
+               _p2 = unsafe.Pointer(&dest[0])
+       } else {
+               _p2 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+       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) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit() (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit1(flags int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+       r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
+       success = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+       _, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Klogctl(typ int, buf []byte) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(buf) > 0 {
+               _p0 = unsafe.Pointer(&buf[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(oldpath string, newpath string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(oldpath)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(newpath)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_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
+       }
+       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 Mkdirat(dirfd int, path string, mode uint32) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+       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 Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
+       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 Pause() (err error) {
+       _, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func PivotRoot(newroot string, putold string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(newroot)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(putold)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+       _, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+       if e1 != 0 {
+               err = 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 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) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(oldpath)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(newpath)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
+       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 Setdomainname(p []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sethostname(p []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
+       if e1 != 0 {
+               err = 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 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(tv *Timeval) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, 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 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 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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Symlink(oldpath string, newpath string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(oldpath)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(newpath)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_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() {
+       Syscall(SYS_SYNC, 0, 0, 0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sysinfo(info *Sysinfo_t) (err error) {
+       _, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
+       r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
+       n = int64(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tgkill(tgid int, tid int, sig Signal) (err error) {
+       _, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+       r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
+       ticks = uintptr(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(mask int) (oldmask int) {
+       r0, _, _ := RawSyscall(SYS_UMASK, uintptr(mask), 0, 0)
+       oldmask = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+       _, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
+       if e1 != 0 {
+               err = 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 Unlinkat(dirfd int, path string) (err error) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(target string, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(target)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unshare(flags int) (err error) {
+       _, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
+       _, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Utime(path string, buf *Utimbuf) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+       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 exitThread(code int) (err error) {
+       _, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, p *byte, np int) (n int, err error) {
+       r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, p *byte, np int) (n int, err error) {
+       r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+       n = int(r0)
+       if e1 != 0 {
+               err = 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 Madvise(b []byte, advice int) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (err error) {
+       _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (err error) {
+       _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+       if e1 != 0 {
+               err = 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 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 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, buf *Statfs_t) (err error) {
+       _, _, e1 := Syscall(SYS_FSTATFS, 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 Ftruncate(fd int, length int64) (err error) {
+       _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 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() (euid int) {
+       r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+       euid = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+       r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+       gid = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+       _, _, e1 := RawSyscall(SYS_UGETRLIMIT, 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)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ioperm(from int, num int, on int) (err error) {
+       _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Iopl(level int) (err error) {
+       _, _, e1 := Syscall(SYS_IOPL, uintptr(level), 0, 0)
+       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 Listen(s int, n int) (err error) {
+       _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 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 Pread(fd int, p []byte, offset int64) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+       r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
+       off = int64(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+       r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+       r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
+       written = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsgid(gid int) (err error) {
+       _, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsuid(uid int) (err error) {
+       _, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
+       if e1 != 0 {
+               err = 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 Setresgid(rgid int, egid int, sgid int) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresuid(ruid int, euid int, suid int) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+       if e1 != 0 {
+               err = 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 Shutdown(fd int, how int) (err error) {
+       _, _, e1 := Syscall(SYS_SHUTDOWN, 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 Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+       r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
+       n = int64(r0)
+       if e1 != 0 {
+               err = 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, buf *Statfs_t) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
+       _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 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), 0)
+       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 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 unsafe.Pointer, 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 unsafe.Pointer, 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 getgroups(n int, list *_Gid_t) (nn int, err error) {
+       r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+       nn = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(n int, list *_Gid_t) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+       _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+       _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+       if e1 != 0 {
+               err = 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 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 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 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 unsafe.Pointer, addrlen _Socklen) (err error) {
+       var _p0 unsafe.Pointer
+       if len(buf) > 0 {
+               _p0 = unsafe.Pointer(&buf[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+       if e1 != 0 {
+               err = 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) (n int, err error) {
+       r0, _, e1 := Syscall(SYS_SENDMSG, 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 mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
+       r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
+       xaddr = uintptr(r0)
+       if e1 != 0 {
+               err = 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 Time(t *Time_t) (tt Time_t, err error) {
+       r0, _, e1 := RawSyscall(SYS_TIME, uintptr(unsafe.Pointer(t)), 0, 0)
+       tt = Time_t(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
diff --git a/src/syscall/zsyscall_linux_power64le.go b/src/syscall/zsyscall_linux_power64le.go
new file mode 100644 (file)
index 0000000..7808059
--- /dev/null
@@ -0,0 +1,1931 @@
+// mksyscall.pl syscall_linux.go syscall_linux_power64x.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 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 openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe(p *[2]_C_int) (err error) {
+       _, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags int) (err error) {
+       _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, times *[2]Timeval) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
+       _, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getcwd(buf []byte) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(buf) > 0 {
+               _p0 = unsafe.Pointer(&buf[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = 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 ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
+       _, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(arg)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(source)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(target)
+       if err != nil {
+               return
+       }
+       var _p2 *byte
+       _p2, err = BytePtrFromString(fstype)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+       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 Acct(path string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtimex(buf *Timex) (state int, err error) {
+       r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
+       state = int(r0)
+       if e1 != 0 {
+               err = 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 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 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 Creat(path string, mode uint32) (fd int, err error) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_DUP, uintptr(oldfd), 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 Dup2(oldfd int, newfd int) (err error) {
+       _, _, e1 := RawSyscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup3(oldfd int, newfd int, flags int) (err error) {
+       _, _, e1 := RawSyscall(SYS_DUP3, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate(size int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+       _, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(events) > 0 {
+               _p0 = unsafe.Pointer(&events[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+       Syscall(SYS_EXIT_GROUP, uintptr(code), 0, 0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
+       _, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+       _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+       if e1 != 0 {
+               err = 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 Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+       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 Fdatasync(fd int) (err error) {
+       _, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
+       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 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 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_GETDENTS64, 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 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() (pid int) {
+       r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0)
+       pid = 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 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 Gettid() (tid int) {
+       r0, _, _ := RawSyscall(SYS_GETTID, 0, 0, 0)
+       tid = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(attr)
+       if err != nil {
+               return
+       }
+       var _p2 unsafe.Pointer
+       if len(dest) > 0 {
+               _p2 = unsafe.Pointer(&dest[0])
+       } else {
+               _p2 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+       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) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit() (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit1(flags int) (fd int, err error) {
+       r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
+       fd = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+       r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
+       success = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+       _, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Klogctl(typ int, buf []byte) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(buf) > 0 {
+               _p0 = unsafe.Pointer(&buf[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Link(oldpath string, newpath string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(oldpath)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(newpath)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_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
+       }
+       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 Mkdirat(dirfd int, path string, mode uint32) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+       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 Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
+       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 Pause() (err error) {
+       _, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func PivotRoot(newroot string, putold string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(newroot)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(putold)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+       _, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+       if e1 != 0 {
+               err = 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 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) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(oldpath)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(newpath)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
+       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 Setdomainname(p []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sethostname(p []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
+       if e1 != 0 {
+               err = 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 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(tv *Timeval) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, 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 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 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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Symlink(oldpath string, newpath string) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(oldpath)
+       if err != nil {
+               return
+       }
+       var _p1 *byte
+       _p1, err = BytePtrFromString(newpath)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_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() {
+       Syscall(SYS_SYNC, 0, 0, 0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sysinfo(info *Sysinfo_t) (err error) {
+       _, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
+       r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
+       n = int64(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tgkill(tgid int, tid int, sig Signal) (err error) {
+       _, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+       r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
+       ticks = uintptr(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(mask int) (oldmask int) {
+       r0, _, _ := RawSyscall(SYS_UMASK, uintptr(mask), 0, 0)
+       oldmask = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+       _, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
+       if e1 != 0 {
+               err = 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 Unlinkat(dirfd int, path string) (err error) {
+       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
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(target string, flags int) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(target)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unshare(flags int) (err error) {
+       _, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
+       _, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Utime(path string, buf *Utimbuf) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+       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 exitThread(code int) (err error) {
+       _, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, p *byte, np int) (n int, err error) {
+       r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, p *byte, np int) (n int, err error) {
+       r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+       n = int(r0)
+       if e1 != 0 {
+               err = 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 Madvise(b []byte, advice int) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (err error) {
+       var _p0 unsafe.Pointer
+       if len(b) > 0 {
+               _p0 = unsafe.Pointer(&b[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (err error) {
+       _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (err error) {
+       _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+       if e1 != 0 {
+               err = 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 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 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, buf *Statfs_t) (err error) {
+       _, _, e1 := Syscall(SYS_FSTATFS, 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 Ftruncate(fd int, length int64) (err error) {
+       _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 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() (euid int) {
+       r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+       euid = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+       r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+       gid = int(r0)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+       _, _, e1 := RawSyscall(SYS_UGETRLIMIT, 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)
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ioperm(from int, num int, on int) (err error) {
+       _, _, e1 := Syscall(SYS_IOPERM, uintptr(from), uintptr(num), uintptr(on))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Iopl(level int) (err error) {
+       _, _, e1 := Syscall(SYS_IOPL, uintptr(level), 0, 0)
+       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 Listen(s int, n int) (err error) {
+       _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 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 Pread(fd int, p []byte, offset int64) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+       var _p0 unsafe.Pointer
+       if len(p) > 0 {
+               _p0 = unsafe.Pointer(&p[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+       r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
+       off = int64(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+       r0, _, e1 := Syscall6(SYS_SELECT, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+       n = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+       r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
+       written = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsgid(gid int) (err error) {
+       _, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsuid(uid int) (err error) {
+       _, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
+       if e1 != 0 {
+               err = 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 Setresgid(rgid int, egid int, sgid int) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresuid(ruid int, euid int, suid int) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+       if e1 != 0 {
+               err = 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 Shutdown(fd int, how int) (err error) {
+       _, _, e1 := Syscall(SYS_SHUTDOWN, 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 Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+       r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
+       n = int64(r0)
+       if e1 != 0 {
+               err = 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, buf *Statfs_t) (err error) {
+       var _p0 *byte
+       _p0, err = BytePtrFromString(path)
+       if err != nil {
+               return
+       }
+       _, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
+       _, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 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), 0)
+       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 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 unsafe.Pointer, 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 unsafe.Pointer, 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 getgroups(n int, list *_Gid_t) (nn int, err error) {
+       r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+       nn = int(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(n int, list *_Gid_t) (err error) {
+       _, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+       _, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+       _, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+       if e1 != 0 {
+               err = 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 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 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 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 unsafe.Pointer, addrlen _Socklen) (err error) {
+       var _p0 unsafe.Pointer
+       if len(buf) > 0 {
+               _p0 = unsafe.Pointer(&buf[0])
+       } else {
+               _p0 = unsafe.Pointer(&_zero)
+       }
+       _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+       if e1 != 0 {
+               err = 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) (n int, err error) {
+       r0, _, e1 := Syscall(SYS_SENDMSG, 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 mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
+       r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
+       xaddr = uintptr(r0)
+       if e1 != 0 {
+               err = 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 Time(t *Time_t) (tt Time_t, err error) {
+       r0, _, e1 := RawSyscall(SYS_TIME, uintptr(unsafe.Pointer(t)), 0, 0)
+       tt = Time_t(r0)
+       if e1 != 0 {
+               err = e1
+       }
+       return
+}
diff --git a/src/syscall/zsysnum_linux_power64.go b/src/syscall/zsysnum_linux_power64.go
new file mode 100644 (file)
index 0000000..0567fd0
--- /dev/null
@@ -0,0 +1,351 @@
+// mksysnum_linux.pl /usr/include/asm/unistd.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+       SYS_RESTART_SYSCALL        = 0
+       SYS_EXIT                   = 1
+       SYS_FORK                   = 2
+       SYS_READ                   = 3
+       SYS_WRITE                  = 4
+       SYS_OPEN                   = 5
+       SYS_CLOSE                  = 6
+       SYS_WAITPID                = 7
+       SYS_CREAT                  = 8
+       SYS_LINK                   = 9
+       SYS_UNLINK                 = 10
+       SYS_EXECVE                 = 11
+       SYS_CHDIR                  = 12
+       SYS_TIME                   = 13
+       SYS_MKNOD                  = 14
+       SYS_CHMOD                  = 15
+       SYS_LCHOWN                 = 16
+       SYS_BREAK                  = 17
+       SYS_OLDSTAT                = 18
+       SYS_LSEEK                  = 19
+       SYS_GETPID                 = 20
+       SYS_MOUNT                  = 21
+       SYS_UMOUNT                 = 22
+       SYS_SETUID                 = 23
+       SYS_GETUID                 = 24
+       SYS_STIME                  = 25
+       SYS_PTRACE                 = 26
+       SYS_ALARM                  = 27
+       SYS_OLDFSTAT               = 28
+       SYS_PAUSE                  = 29
+       SYS_UTIME                  = 30
+       SYS_STTY                   = 31
+       SYS_GTTY                   = 32
+       SYS_ACCESS                 = 33
+       SYS_NICE                   = 34
+       SYS_FTIME                  = 35
+       SYS_SYNC                   = 36
+       SYS_KILL                   = 37
+       SYS_RENAME                 = 38
+       SYS_MKDIR                  = 39
+       SYS_RMDIR                  = 40
+       SYS_DUP                    = 41
+       SYS_PIPE                   = 42
+       SYS_TIMES                  = 43
+       SYS_PROF                   = 44
+       SYS_BRK                    = 45
+       SYS_SETGID                 = 46
+       SYS_GETGID                 = 47
+       SYS_SIGNAL                 = 48
+       SYS_GETEUID                = 49
+       SYS_GETEGID                = 50
+       SYS_ACCT                   = 51
+       SYS_UMOUNT2                = 52
+       SYS_LOCK                   = 53
+       SYS_IOCTL                  = 54
+       SYS_FCNTL                  = 55
+       SYS_MPX                    = 56
+       SYS_SETPGID                = 57
+       SYS_ULIMIT                 = 58
+       SYS_OLDOLDUNAME            = 59
+       SYS_UMASK                  = 60
+       SYS_CHROOT                 = 61
+       SYS_USTAT                  = 62
+       SYS_DUP2                   = 63
+       SYS_GETPPID                = 64
+       SYS_GETPGRP                = 65
+       SYS_SETSID                 = 66
+       SYS_SIGACTION              = 67
+       SYS_SGETMASK               = 68
+       SYS_SSETMASK               = 69
+       SYS_SETREUID               = 70
+       SYS_SETREGID               = 71
+       SYS_SIGSUSPEND             = 72
+       SYS_SIGPENDING             = 73
+       SYS_SETHOSTNAME            = 74
+       SYS_SETRLIMIT              = 75
+       SYS_GETRLIMIT              = 76
+       SYS_GETRUSAGE              = 77
+       SYS_GETTIMEOFDAY           = 78
+       SYS_SETTIMEOFDAY           = 79
+       SYS_GETGROUPS              = 80
+       SYS_SETGROUPS              = 81
+       SYS_SELECT                 = 82
+       SYS_SYMLINK                = 83
+       SYS_OLDLSTAT               = 84
+       SYS_READLINK               = 85
+       SYS_USELIB                 = 86
+       SYS_SWAPON                 = 87
+       SYS_REBOOT                 = 88
+       SYS_READDIR                = 89
+       SYS_MMAP                   = 90
+       SYS_MUNMAP                 = 91
+       SYS_TRUNCATE               = 92
+       SYS_FTRUNCATE              = 93
+       SYS_FCHMOD                 = 94
+       SYS_FCHOWN                 = 95
+       SYS_GETPRIORITY            = 96
+       SYS_SETPRIORITY            = 97
+       SYS_PROFIL                 = 98
+       SYS_STATFS                 = 99
+       SYS_FSTATFS                = 100
+       SYS_IOPERM                 = 101
+       SYS_SOCKETCALL             = 102
+       SYS_SYSLOG                 = 103
+       SYS_SETITIMER              = 104
+       SYS_GETITIMER              = 105
+       SYS_STAT                   = 106
+       SYS_LSTAT                  = 107
+       SYS_FSTAT                  = 108
+       SYS_OLDUNAME               = 109
+       SYS_IOPL                   = 110
+       SYS_VHANGUP                = 111
+       SYS_IDLE                   = 112
+       SYS_VM86                   = 113
+       SYS_WAIT4                  = 114
+       SYS_SWAPOFF                = 115
+       SYS_SYSINFO                = 116
+       SYS_IPC                    = 117
+       SYS_FSYNC                  = 118
+       SYS_SIGRETURN              = 119
+       SYS_CLONE                  = 120
+       SYS_SETDOMAINNAME          = 121
+       SYS_UNAME                  = 122
+       SYS_MODIFY_LDT             = 123
+       SYS_ADJTIMEX               = 124
+       SYS_MPROTECT               = 125
+       SYS_SIGPROCMASK            = 126
+       SYS_CREATE_MODULE          = 127
+       SYS_INIT_MODULE            = 128
+       SYS_DELETE_MODULE          = 129
+       SYS_GET_KERNEL_SYMS        = 130
+       SYS_QUOTACTL               = 131
+       SYS_GETPGID                = 132
+       SYS_FCHDIR                 = 133
+       SYS_BDFLUSH                = 134
+       SYS_SYSFS                  = 135
+       SYS_PERSONALITY            = 136
+       SYS_AFS_SYSCALL            = 137
+       SYS_SETFSUID               = 138
+       SYS_SETFSGID               = 139
+       SYS__LLSEEK                = 140
+       SYS_GETDENTS               = 141
+       SYS__NEWSELECT             = 142
+       SYS_FLOCK                  = 143
+       SYS_MSYNC                  = 144
+       SYS_READV                  = 145
+       SYS_WRITEV                 = 146
+       SYS_GETSID                 = 147
+       SYS_FDATASYNC              = 148
+       SYS__SYSCTL                = 149
+       SYS_MLOCK                  = 150
+       SYS_MUNLOCK                = 151
+       SYS_MLOCKALL               = 152
+       SYS_MUNLOCKALL             = 153
+       SYS_SCHED_SETPARAM         = 154
+       SYS_SCHED_GETPARAM         = 155
+       SYS_SCHED_SETSCHEDULER     = 156
+       SYS_SCHED_GETSCHEDULER     = 157
+       SYS_SCHED_YIELD            = 158
+       SYS_SCHED_GET_PRIORITY_MAX = 159
+       SYS_SCHED_GET_PRIORITY_MIN = 160
+       SYS_SCHED_RR_GET_INTERVAL  = 161
+       SYS_NANOSLEEP              = 162
+       SYS_MREMAP                 = 163
+       SYS_SETRESUID              = 164
+       SYS_GETRESUID              = 165
+       SYS_QUERY_MODULE           = 166
+       SYS_POLL                   = 167
+       SYS_NFSSERVCTL             = 168
+       SYS_SETRESGID              = 169
+       SYS_GETRESGID              = 170
+       SYS_PRCTL                  = 171
+       SYS_RT_SIGRETURN           = 172
+       SYS_RT_SIGACTION           = 173
+       SYS_RT_SIGPROCMASK         = 174
+       SYS_RT_SIGPENDING          = 175
+       SYS_RT_SIGTIMEDWAIT        = 176
+       SYS_RT_SIGQUEUEINFO        = 177
+       SYS_RT_SIGSUSPEND          = 178
+       SYS_PREAD64                = 179
+       SYS_PWRITE64               = 180
+       SYS_CHOWN                  = 181
+       SYS_GETCWD                 = 182
+       SYS_CAPGET                 = 183
+       SYS_CAPSET                 = 184
+       SYS_SIGALTSTACK            = 185
+       SYS_SENDFILE               = 186
+       SYS_GETPMSG                = 187
+       SYS_PUTPMSG                = 188
+       SYS_VFORK                  = 189
+       SYS_UGETRLIMIT             = 190
+       SYS_READAHEAD              = 191
+       SYS_PCICONFIG_READ         = 198
+       SYS_PCICONFIG_WRITE        = 199
+       SYS_PCICONFIG_IOBASE       = 200
+       SYS_MULTIPLEXER            = 201
+       SYS_GETDENTS64             = 202
+       SYS_PIVOT_ROOT             = 203
+       SYS_MADVISE                = 205
+       SYS_MINCORE                = 206
+       SYS_GETTID                 = 207
+       SYS_TKILL                  = 208
+       SYS_SETXATTR               = 209
+       SYS_LSETXATTR              = 210
+       SYS_FSETXATTR              = 211
+       SYS_GETXATTR               = 212
+       SYS_LGETXATTR              = 213
+       SYS_FGETXATTR              = 214
+       SYS_LISTXATTR              = 215
+       SYS_LLISTXATTR             = 216
+       SYS_FLISTXATTR             = 217
+       SYS_REMOVEXATTR            = 218
+       SYS_LREMOVEXATTR           = 219
+       SYS_FREMOVEXATTR           = 220
+       SYS_FUTEX                  = 221
+       SYS_SCHED_SETAFFINITY      = 222
+       SYS_SCHED_GETAFFINITY      = 223
+       SYS_TUXCALL                = 225
+       SYS_IO_SETUP               = 227
+       SYS_IO_DESTROY             = 228
+       SYS_IO_GETEVENTS           = 229
+       SYS_IO_SUBMIT              = 230
+       SYS_IO_CANCEL              = 231
+       SYS_SET_TID_ADDRESS        = 232
+       SYS_FADVISE64              = 233
+       SYS_EXIT_GROUP             = 234
+       SYS_LOOKUP_DCOOKIE         = 235
+       SYS_EPOLL_CREATE           = 236
+       SYS_EPOLL_CTL              = 237
+       SYS_EPOLL_WAIT             = 238
+       SYS_REMAP_FILE_PAGES       = 239
+       SYS_TIMER_CREATE           = 240
+       SYS_TIMER_SETTIME          = 241
+       SYS_TIMER_GETTIME          = 242
+       SYS_TIMER_GETOVERRUN       = 243
+       SYS_TIMER_DELETE           = 244
+       SYS_CLOCK_SETTIME          = 245
+       SYS_CLOCK_GETTIME          = 246
+       SYS_CLOCK_GETRES           = 247
+       SYS_CLOCK_NANOSLEEP        = 248
+       SYS_SWAPCONTEXT            = 249
+       SYS_TGKILL                 = 250
+       SYS_UTIMES                 = 251
+       SYS_STATFS64               = 252
+       SYS_FSTATFS64              = 253
+       SYS_RTAS                   = 255
+       SYS_SYS_DEBUG_SETCONTEXT   = 256
+       SYS_MIGRATE_PAGES          = 258
+       SYS_MBIND                  = 259
+       SYS_GET_MEMPOLICY          = 260
+       SYS_SET_MEMPOLICY          = 261
+       SYS_MQ_OPEN                = 262
+       SYS_MQ_UNLINK              = 263
+       SYS_MQ_TIMEDSEND           = 264
+       SYS_MQ_TIMEDRECEIVE        = 265
+       SYS_MQ_NOTIFY              = 266
+       SYS_MQ_GETSETATTR          = 267
+       SYS_KEXEC_LOAD             = 268
+       SYS_ADD_KEY                = 269
+       SYS_REQUEST_KEY            = 270
+       SYS_KEYCTL                 = 271
+       SYS_WAITID                 = 272
+       SYS_IOPRIO_SET             = 273
+       SYS_IOPRIO_GET             = 274
+       SYS_INOTIFY_INIT           = 275
+       SYS_INOTIFY_ADD_WATCH      = 276
+       SYS_INOTIFY_RM_WATCH       = 277
+       SYS_SPU_RUN                = 278
+       SYS_SPU_CREATE             = 279
+       SYS_PSELECT6               = 280
+       SYS_PPOLL                  = 281
+       SYS_UNSHARE                = 282
+       SYS_SPLICE                 = 283
+       SYS_TEE                    = 284
+       SYS_VMSPLICE               = 285
+       SYS_OPENAT                 = 286
+       SYS_MKDIRAT                = 287
+       SYS_MKNODAT                = 288
+       SYS_FCHOWNAT               = 289
+       SYS_FUTIMESAT              = 290
+       SYS_NEWFSTATAT             = 291
+       SYS_UNLINKAT               = 292
+       SYS_RENAMEAT               = 293
+       SYS_LINKAT                 = 294
+       SYS_SYMLINKAT              = 295
+       SYS_READLINKAT             = 296
+       SYS_FCHMODAT               = 297
+       SYS_FACCESSAT              = 298
+       SYS_GET_ROBUST_LIST        = 299
+       SYS_SET_ROBUST_LIST        = 300
+       SYS_MOVE_PAGES             = 301
+       SYS_GETCPU                 = 302
+       SYS_EPOLL_PWAIT            = 303
+       SYS_UTIMENSAT              = 304
+       SYS_SIGNALFD               = 305
+       SYS_TIMERFD_CREATE         = 306
+       SYS_EVENTFD                = 307
+       SYS_SYNC_FILE_RANGE2       = 308
+       SYS_FALLOCATE              = 309
+       SYS_SUBPAGE_PROT           = 310
+       SYS_TIMERFD_SETTIME        = 311
+       SYS_TIMERFD_GETTIME        = 312
+       SYS_SIGNALFD4              = 313
+       SYS_EVENTFD2               = 314
+       SYS_EPOLL_CREATE1          = 315
+       SYS_DUP3                   = 316
+       SYS_PIPE2                  = 317
+       SYS_INOTIFY_INIT1          = 318
+       SYS_PERF_EVENT_OPEN        = 319
+       SYS_PREADV                 = 320
+       SYS_PWRITEV                = 321
+       SYS_RT_TGSIGQUEUEINFO      = 322
+       SYS_FANOTIFY_INIT          = 323
+       SYS_FANOTIFY_MARK          = 324
+       SYS_PRLIMIT64              = 325
+       SYS_SOCKET                 = 326
+       SYS_BIND                   = 327
+       SYS_CONNECT                = 328
+       SYS_LISTEN                 = 329
+       SYS_ACCEPT                 = 330
+       SYS_GETSOCKNAME            = 331
+       SYS_GETPEERNAME            = 332
+       SYS_SOCKETPAIR             = 333
+       SYS_SEND                   = 334
+       SYS_SENDTO                 = 335
+       SYS_RECV                   = 336
+       SYS_RECVFROM               = 337
+       SYS_SHUTDOWN               = 338
+       SYS_SETSOCKOPT             = 339
+       SYS_GETSOCKOPT             = 340
+       SYS_SENDMSG                = 341
+       SYS_RECVMSG                = 342
+       SYS_RECVMMSG               = 343
+       SYS_ACCEPT4                = 344
+       SYS_NAME_TO_HANDLE_AT      = 345
+       SYS_OPEN_BY_HANDLE_AT      = 346
+       SYS_CLOCK_ADJTIME          = 347
+       SYS_SYNCFS                 = 348
+       SYS_SENDMMSG               = 349
+       SYS_SETNS                  = 350
+       SYS_PROCESS_VM_READV       = 351
+       SYS_PROCESS_VM_WRITEV      = 352
+       SYS_FINIT_MODULE           = 353
+       SYS_KCMP                   = 354
+)
diff --git a/src/syscall/zsysnum_linux_power64le.go b/src/syscall/zsysnum_linux_power64le.go
new file mode 100644 (file)
index 0000000..52c63e3
--- /dev/null
@@ -0,0 +1,351 @@
+// mksysnum_linux.pl /usr/include/powerpc64le-linux-gnu/asm/unistd.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+       SYS_RESTART_SYSCALL        = 0
+       SYS_EXIT                   = 1
+       SYS_FORK                   = 2
+       SYS_READ                   = 3
+       SYS_WRITE                  = 4
+       SYS_OPEN                   = 5
+       SYS_CLOSE                  = 6
+       SYS_WAITPID                = 7
+       SYS_CREAT                  = 8
+       SYS_LINK                   = 9
+       SYS_UNLINK                 = 10
+       SYS_EXECVE                 = 11
+       SYS_CHDIR                  = 12
+       SYS_TIME                   = 13
+       SYS_MKNOD                  = 14
+       SYS_CHMOD                  = 15
+       SYS_LCHOWN                 = 16
+       SYS_BREAK                  = 17
+       SYS_OLDSTAT                = 18
+       SYS_LSEEK                  = 19
+       SYS_GETPID                 = 20
+       SYS_MOUNT                  = 21
+       SYS_UMOUNT                 = 22
+       SYS_SETUID                 = 23
+       SYS_GETUID                 = 24
+       SYS_STIME                  = 25
+       SYS_PTRACE                 = 26
+       SYS_ALARM                  = 27
+       SYS_OLDFSTAT               = 28
+       SYS_PAUSE                  = 29
+       SYS_UTIME                  = 30
+       SYS_STTY                   = 31
+       SYS_GTTY                   = 32
+       SYS_ACCESS                 = 33
+       SYS_NICE                   = 34
+       SYS_FTIME                  = 35
+       SYS_SYNC                   = 36
+       SYS_KILL                   = 37
+       SYS_RENAME                 = 38
+       SYS_MKDIR                  = 39
+       SYS_RMDIR                  = 40
+       SYS_DUP                    = 41
+       SYS_PIPE                   = 42
+       SYS_TIMES                  = 43
+       SYS_PROF                   = 44
+       SYS_BRK                    = 45
+       SYS_SETGID                 = 46
+       SYS_GETGID                 = 47
+       SYS_SIGNAL                 = 48
+       SYS_GETEUID                = 49
+       SYS_GETEGID                = 50
+       SYS_ACCT                   = 51
+       SYS_UMOUNT2                = 52
+       SYS_LOCK                   = 53
+       SYS_IOCTL                  = 54
+       SYS_FCNTL                  = 55
+       SYS_MPX                    = 56
+       SYS_SETPGID                = 57
+       SYS_ULIMIT                 = 58
+       SYS_OLDOLDUNAME            = 59
+       SYS_UMASK                  = 60
+       SYS_CHROOT                 = 61
+       SYS_USTAT                  = 62
+       SYS_DUP2                   = 63
+       SYS_GETPPID                = 64
+       SYS_GETPGRP                = 65
+       SYS_SETSID                 = 66
+       SYS_SIGACTION              = 67
+       SYS_SGETMASK               = 68
+       SYS_SSETMASK               = 69
+       SYS_SETREUID               = 70
+       SYS_SETREGID               = 71
+       SYS_SIGSUSPEND             = 72
+       SYS_SIGPENDING             = 73
+       SYS_SETHOSTNAME            = 74
+       SYS_SETRLIMIT              = 75
+       SYS_GETRLIMIT              = 76
+       SYS_GETRUSAGE              = 77
+       SYS_GETTIMEOFDAY           = 78
+       SYS_SETTIMEOFDAY           = 79
+       SYS_GETGROUPS              = 80
+       SYS_SETGROUPS              = 81
+       SYS_SELECT                 = 82
+       SYS_SYMLINK                = 83
+       SYS_OLDLSTAT               = 84
+       SYS_READLINK               = 85
+       SYS_USELIB                 = 86
+       SYS_SWAPON                 = 87
+       SYS_REBOOT                 = 88
+       SYS_READDIR                = 89
+       SYS_MMAP                   = 90
+       SYS_MUNMAP                 = 91
+       SYS_TRUNCATE               = 92
+       SYS_FTRUNCATE              = 93
+       SYS_FCHMOD                 = 94
+       SYS_FCHOWN                 = 95
+       SYS_GETPRIORITY            = 96
+       SYS_SETPRIORITY            = 97
+       SYS_PROFIL                 = 98
+       SYS_STATFS                 = 99
+       SYS_FSTATFS                = 100
+       SYS_IOPERM                 = 101
+       SYS_SOCKETCALL             = 102
+       SYS_SYSLOG                 = 103
+       SYS_SETITIMER              = 104
+       SYS_GETITIMER              = 105
+       SYS_STAT                   = 106
+       SYS_LSTAT                  = 107
+       SYS_FSTAT                  = 108
+       SYS_OLDUNAME               = 109
+       SYS_IOPL                   = 110
+       SYS_VHANGUP                = 111
+       SYS_IDLE                   = 112
+       SYS_VM86                   = 113
+       SYS_WAIT4                  = 114
+       SYS_SWAPOFF                = 115
+       SYS_SYSINFO                = 116
+       SYS_IPC                    = 117
+       SYS_FSYNC                  = 118
+       SYS_SIGRETURN              = 119
+       SYS_CLONE                  = 120
+       SYS_SETDOMAINNAME          = 121
+       SYS_UNAME                  = 122
+       SYS_MODIFY_LDT             = 123
+       SYS_ADJTIMEX               = 124
+       SYS_MPROTECT               = 125
+       SYS_SIGPROCMASK            = 126
+       SYS_CREATE_MODULE          = 127
+       SYS_INIT_MODULE            = 128
+       SYS_DELETE_MODULE          = 129
+       SYS_GET_KERNEL_SYMS        = 130
+       SYS_QUOTACTL               = 131
+       SYS_GETPGID                = 132
+       SYS_FCHDIR                 = 133
+       SYS_BDFLUSH                = 134
+       SYS_SYSFS                  = 135
+       SYS_PERSONALITY            = 136
+       SYS_AFS_SYSCALL            = 137
+       SYS_SETFSUID               = 138
+       SYS_SETFSGID               = 139
+       SYS__LLSEEK                = 140
+       SYS_GETDENTS               = 141
+       SYS__NEWSELECT             = 142
+       SYS_FLOCK                  = 143
+       SYS_MSYNC                  = 144
+       SYS_READV                  = 145
+       SYS_WRITEV                 = 146
+       SYS_GETSID                 = 147
+       SYS_FDATASYNC              = 148
+       SYS__SYSCTL                = 149
+       SYS_MLOCK                  = 150
+       SYS_MUNLOCK                = 151
+       SYS_MLOCKALL               = 152
+       SYS_MUNLOCKALL             = 153
+       SYS_SCHED_SETPARAM         = 154
+       SYS_SCHED_GETPARAM         = 155
+       SYS_SCHED_SETSCHEDULER     = 156
+       SYS_SCHED_GETSCHEDULER     = 157
+       SYS_SCHED_YIELD            = 158
+       SYS_SCHED_GET_PRIORITY_MAX = 159
+       SYS_SCHED_GET_PRIORITY_MIN = 160
+       SYS_SCHED_RR_GET_INTERVAL  = 161
+       SYS_NANOSLEEP              = 162
+       SYS_MREMAP                 = 163
+       SYS_SETRESUID              = 164
+       SYS_GETRESUID              = 165
+       SYS_QUERY_MODULE           = 166
+       SYS_POLL                   = 167
+       SYS_NFSSERVCTL             = 168
+       SYS_SETRESGID              = 169
+       SYS_GETRESGID              = 170
+       SYS_PRCTL                  = 171
+       SYS_RT_SIGRETURN           = 172
+       SYS_RT_SIGACTION           = 173
+       SYS_RT_SIGPROCMASK         = 174
+       SYS_RT_SIGPENDING          = 175
+       SYS_RT_SIGTIMEDWAIT        = 176
+       SYS_RT_SIGQUEUEINFO        = 177
+       SYS_RT_SIGSUSPEND          = 178
+       SYS_PREAD64                = 179
+       SYS_PWRITE64               = 180
+       SYS_CHOWN                  = 181
+       SYS_GETCWD                 = 182
+       SYS_CAPGET                 = 183
+       SYS_CAPSET                 = 184
+       SYS_SIGALTSTACK            = 185
+       SYS_SENDFILE               = 186
+       SYS_GETPMSG                = 187
+       SYS_PUTPMSG                = 188
+       SYS_VFORK                  = 189
+       SYS_UGETRLIMIT             = 190
+       SYS_READAHEAD              = 191
+       SYS_PCICONFIG_READ         = 198
+       SYS_PCICONFIG_WRITE        = 199
+       SYS_PCICONFIG_IOBASE       = 200
+       SYS_MULTIPLEXER            = 201
+       SYS_GETDENTS64             = 202
+       SYS_PIVOT_ROOT             = 203
+       SYS_MADVISE                = 205
+       SYS_MINCORE                = 206
+       SYS_GETTID                 = 207
+       SYS_TKILL                  = 208
+       SYS_SETXATTR               = 209
+       SYS_LSETXATTR              = 210
+       SYS_FSETXATTR              = 211
+       SYS_GETXATTR               = 212
+       SYS_LGETXATTR              = 213
+       SYS_FGETXATTR              = 214
+       SYS_LISTXATTR              = 215
+       SYS_LLISTXATTR             = 216
+       SYS_FLISTXATTR             = 217
+       SYS_REMOVEXATTR            = 218
+       SYS_LREMOVEXATTR           = 219
+       SYS_FREMOVEXATTR           = 220
+       SYS_FUTEX                  = 221
+       SYS_SCHED_SETAFFINITY      = 222
+       SYS_SCHED_GETAFFINITY      = 223
+       SYS_TUXCALL                = 225
+       SYS_IO_SETUP               = 227
+       SYS_IO_DESTROY             = 228
+       SYS_IO_GETEVENTS           = 229
+       SYS_IO_SUBMIT              = 230
+       SYS_IO_CANCEL              = 231
+       SYS_SET_TID_ADDRESS        = 232
+       SYS_FADVISE64              = 233
+       SYS_EXIT_GROUP             = 234
+       SYS_LOOKUP_DCOOKIE         = 235
+       SYS_EPOLL_CREATE           = 236
+       SYS_EPOLL_CTL              = 237
+       SYS_EPOLL_WAIT             = 238
+       SYS_REMAP_FILE_PAGES       = 239
+       SYS_TIMER_CREATE           = 240
+       SYS_TIMER_SETTIME          = 241
+       SYS_TIMER_GETTIME          = 242
+       SYS_TIMER_GETOVERRUN       = 243
+       SYS_TIMER_DELETE           = 244
+       SYS_CLOCK_SETTIME          = 245
+       SYS_CLOCK_GETTIME          = 246
+       SYS_CLOCK_GETRES           = 247
+       SYS_CLOCK_NANOSLEEP        = 248
+       SYS_SWAPCONTEXT            = 249
+       SYS_TGKILL                 = 250
+       SYS_UTIMES                 = 251
+       SYS_STATFS64               = 252
+       SYS_FSTATFS64              = 253
+       SYS_RTAS                   = 255
+       SYS_SYS_DEBUG_SETCONTEXT   = 256
+       SYS_MIGRATE_PAGES          = 258
+       SYS_MBIND                  = 259
+       SYS_GET_MEMPOLICY          = 260
+       SYS_SET_MEMPOLICY          = 261
+       SYS_MQ_OPEN                = 262
+       SYS_MQ_UNLINK              = 263
+       SYS_MQ_TIMEDSEND           = 264
+       SYS_MQ_TIMEDRECEIVE        = 265
+       SYS_MQ_NOTIFY              = 266
+       SYS_MQ_GETSETATTR          = 267
+       SYS_KEXEC_LOAD             = 268
+       SYS_ADD_KEY                = 269
+       SYS_REQUEST_KEY            = 270
+       SYS_KEYCTL                 = 271
+       SYS_WAITID                 = 272
+       SYS_IOPRIO_SET             = 273
+       SYS_IOPRIO_GET             = 274
+       SYS_INOTIFY_INIT           = 275
+       SYS_INOTIFY_ADD_WATCH      = 276
+       SYS_INOTIFY_RM_WATCH       = 277
+       SYS_SPU_RUN                = 278
+       SYS_SPU_CREATE             = 279
+       SYS_PSELECT6               = 280
+       SYS_PPOLL                  = 281
+       SYS_UNSHARE                = 282
+       SYS_SPLICE                 = 283
+       SYS_TEE                    = 284
+       SYS_VMSPLICE               = 285
+       SYS_OPENAT                 = 286
+       SYS_MKDIRAT                = 287
+       SYS_MKNODAT                = 288
+       SYS_FCHOWNAT               = 289
+       SYS_FUTIMESAT              = 290
+       SYS_NEWFSTATAT             = 291
+       SYS_UNLINKAT               = 292
+       SYS_RENAMEAT               = 293
+       SYS_LINKAT                 = 294
+       SYS_SYMLINKAT              = 295
+       SYS_READLINKAT             = 296
+       SYS_FCHMODAT               = 297
+       SYS_FACCESSAT              = 298
+       SYS_GET_ROBUST_LIST        = 299
+       SYS_SET_ROBUST_LIST        = 300
+       SYS_MOVE_PAGES             = 301
+       SYS_GETCPU                 = 302
+       SYS_EPOLL_PWAIT            = 303
+       SYS_UTIMENSAT              = 304
+       SYS_SIGNALFD               = 305
+       SYS_TIMERFD_CREATE         = 306
+       SYS_EVENTFD                = 307
+       SYS_SYNC_FILE_RANGE2       = 308
+       SYS_FALLOCATE              = 309
+       SYS_SUBPAGE_PROT           = 310
+       SYS_TIMERFD_SETTIME        = 311
+       SYS_TIMERFD_GETTIME        = 312
+       SYS_SIGNALFD4              = 313
+       SYS_EVENTFD2               = 314
+       SYS_EPOLL_CREATE1          = 315
+       SYS_DUP3                   = 316
+       SYS_PIPE2                  = 317
+       SYS_INOTIFY_INIT1          = 318
+       SYS_PERF_EVENT_OPEN        = 319
+       SYS_PREADV                 = 320
+       SYS_PWRITEV                = 321
+       SYS_RT_TGSIGQUEUEINFO      = 322
+       SYS_FANOTIFY_INIT          = 323
+       SYS_FANOTIFY_MARK          = 324
+       SYS_PRLIMIT64              = 325
+       SYS_SOCKET                 = 326
+       SYS_BIND                   = 327
+       SYS_CONNECT                = 328
+       SYS_LISTEN                 = 329
+       SYS_ACCEPT                 = 330
+       SYS_GETSOCKNAME            = 331
+       SYS_GETPEERNAME            = 332
+       SYS_SOCKETPAIR             = 333
+       SYS_SEND                   = 334
+       SYS_SENDTO                 = 335
+       SYS_RECV                   = 336
+       SYS_RECVFROM               = 337
+       SYS_SHUTDOWN               = 338
+       SYS_SETSOCKOPT             = 339
+       SYS_GETSOCKOPT             = 340
+       SYS_SENDMSG                = 341
+       SYS_RECVMSG                = 342
+       SYS_RECVMMSG               = 343
+       SYS_ACCEPT4                = 344
+       SYS_NAME_TO_HANDLE_AT      = 345
+       SYS_OPEN_BY_HANDLE_AT      = 346
+       SYS_CLOCK_ADJTIME          = 347
+       SYS_SYNCFS                 = 348
+       SYS_SENDMMSG               = 349
+       SYS_SETNS                  = 350
+       SYS_PROCESS_VM_READV       = 351
+       SYS_PROCESS_VM_WRITEV      = 352
+       SYS_FINIT_MODULE           = 353
+       SYS_KCMP                   = 354
+)
diff --git a/src/syscall/ztypes_linux_power64.go b/src/syscall/ztypes_linux_power64.go
new file mode 100644 (file)
index 0000000..204d806
--- /dev/null
@@ -0,0 +1,602 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+       sizeofPtr      = 0x8
+       sizeofShort    = 0x2
+       sizeofInt      = 0x4
+       sizeofLong     = 0x8
+       sizeofLongLong = 0x8
+       PathMax        = 0x1000
+)
+
+type (
+       _C_short     int16
+       _C_int       int32
+       _C_long      int64
+       _C_long_long int64
+)
+
+type Timespec struct {
+       Sec  int64
+       Nsec int64
+}
+
+type Timeval struct {
+       Sec  int64
+       Usec int64
+}
+
+type Timex struct {
+       Modes     uint32
+       Pad_cgo_0 [4]byte
+       Offset    int64
+       Freq      int64
+       Maxerror  int64
+       Esterror  int64
+       Status    int32
+       Pad_cgo_1 [4]byte
+       Constant  int64
+       Precision int64
+       Tolerance int64
+       Time      Timeval
+       Tick      int64
+       Ppsfreq   int64
+       Jitter    int64
+       Shift     int32
+       Pad_cgo_2 [4]byte
+       Stabil    int64
+       Jitcnt    int64
+       Calcnt    int64
+       Errcnt    int64
+       Stbcnt    int64
+       Tai       int32
+       Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+       Utime  int64
+       Stime  int64
+       Cutime int64
+       Cstime int64
+}
+
+type Utimbuf struct {
+       Actime  int64
+       Modtime int64
+}
+
+type Rusage struct {
+       Utime    Timeval
+       Stime    Timeval
+       Maxrss   int64
+       Ixrss    int64
+       Idrss    int64
+       Isrss    int64
+       Minflt   int64
+       Majflt   int64
+       Nswap    int64
+       Inblock  int64
+       Oublock  int64
+       Msgsnd   int64
+       Msgrcv   int64
+       Nsignals int64
+       Nvcsw    int64
+       Nivcsw   int64
+}
+
+type Rlimit struct {
+       Cur uint64
+       Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+       Dev        uint64
+       Ino        uint64
+       Nlink      uint64
+       Mode       uint32
+       Uid        uint32
+       Gid        uint32
+       X__pad2    int32
+       Rdev       uint64
+       Size       int64
+       Blksize    int64
+       Blocks     int64
+       Atim       Timespec
+       Mtim       Timespec
+       Ctim       Timespec
+       X__unused4 uint64
+       X__unused5 uint64
+       X__unused6 uint64
+}
+
+type Statfs_t struct {
+       Type    int64
+       Bsize   int64
+       Blocks  uint64
+       Bfree   uint64
+       Bavail  uint64
+       Files   uint64
+       Ffree   uint64
+       Fsid    Fsid
+       Namelen int64
+       Frsize  int64
+       Flags   int64
+       Spare   [4]int64
+}
+
+type Dirent struct {
+       Ino       uint64
+       Off       int64
+       Reclen    uint16
+       Type      uint8
+       Name      [256]uint8
+       Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+       X__val [2]int32
+}
+
+type Flock_t struct {
+       Type      int16
+       Whence    int16
+       Pad_cgo_0 [4]byte
+       Start     int64
+       Len       int64
+       Pid       int32
+       Pad_cgo_1 [4]byte
+}
+
+type RawSockaddrInet4 struct {
+       Family uint16
+       Port   uint16
+       Addr   [4]byte /* in_addr */
+       Zero   [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+       Family   uint16
+       Port     uint16
+       Flowinfo uint32
+       Addr     [16]byte /* in6_addr */
+       Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+       Family uint16
+       Path   [108]int8
+}
+
+type RawSockaddrLinklayer struct {
+       Family   uint16
+       Protocol uint16
+       Ifindex  int32
+       Hatype   uint16
+       Pkttype  uint8
+       Halen    uint8
+       Addr     [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+       Family uint16
+       Pad    uint16
+       Pid    uint32
+       Groups uint32
+}
+
+type RawSockaddr struct {
+       Family uint16
+       Data   [14]uint8
+}
+
+type RawSockaddrAny struct {
+       Addr RawSockaddr
+       Pad  [96]uint8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+       Onoff  int32
+       Linger int32
+}
+
+type Iovec struct {
+       Base *byte
+       Len  uint64
+}
+
+type IPMreq struct {
+       Multiaddr [4]byte /* in_addr */
+       Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+       Multiaddr [4]byte /* in_addr */
+       Address   [4]byte /* in_addr */
+       Ifindex   int32
+}
+
+type IPv6Mreq struct {
+       Multiaddr [16]byte /* in6_addr */
+       Interface uint32
+}
+
+type Msghdr struct {
+       Name       *byte
+       Namelen    uint32
+       Pad_cgo_0  [4]byte
+       Iov        *Iovec
+       Iovlen     uint64
+       Control    *byte
+       Controllen uint64
+       Flags      int32
+       Pad_cgo_1  [4]byte
+}
+
+type Cmsghdr struct {
+       Len          uint64
+       Level        int32
+       Type         int32
+       X__cmsg_data [0]uint8
+}
+
+type Inet4Pktinfo struct {
+       Ifindex  int32
+       Spec_dst [4]byte /* in_addr */
+       Addr     [4]byte /* in_addr */
+}
+
+type Inet6Pktinfo struct {
+       Addr    [16]byte /* in6_addr */
+       Ifindex uint32
+}
+
+type IPv6MTUInfo struct {
+       Addr RawSockaddrInet6
+       Mtu  uint32
+}
+
+type ICMPv6Filter struct {
+       Data [8]uint32
+}
+
+type Ucred struct {
+       Pid int32
+       Uid uint32
+       Gid uint32
+}
+
+type TCPInfo struct {
+       State          uint8
+       Ca_state       uint8
+       Retransmits    uint8
+       Probes         uint8
+       Backoff        uint8
+       Options        uint8
+       Pad_cgo_0      [2]byte
+       Rto            uint32
+       Ato            uint32
+       Snd_mss        uint32
+       Rcv_mss        uint32
+       Unacked        uint32
+       Sacked         uint32
+       Lost           uint32
+       Retrans        uint32
+       Fackets        uint32
+       Last_data_sent uint32
+       Last_ack_sent  uint32
+       Last_data_recv uint32
+       Last_ack_recv  uint32
+       Pmtu           uint32
+       Rcv_ssthresh   uint32
+       Rtt            uint32
+       Rttvar         uint32
+       Snd_ssthresh   uint32
+       Snd_cwnd       uint32
+       Advmss         uint32
+       Reordering     uint32
+       Rcv_rtt        uint32
+       Rcv_space      uint32
+       Total_retrans  uint32
+}
+
+const (
+       SizeofSockaddrInet4     = 0x10
+       SizeofSockaddrInet6     = 0x1c
+       SizeofSockaddrAny       = 0x70
+       SizeofSockaddrUnix      = 0x6e
+       SizeofSockaddrLinklayer = 0x14
+       SizeofSockaddrNetlink   = 0xc
+       SizeofLinger            = 0x8
+       SizeofIPMreq            = 0x8
+       SizeofIPMreqn           = 0xc
+       SizeofIPv6Mreq          = 0x14
+       SizeofMsghdr            = 0x38
+       SizeofCmsghdr           = 0x10
+       SizeofInet4Pktinfo      = 0xc
+       SizeofInet6Pktinfo      = 0x14
+       SizeofIPv6MTUInfo       = 0x20
+       SizeofICMPv6Filter      = 0x20
+       SizeofUcred             = 0xc
+       SizeofTCPInfo           = 0x68
+)
+
+const (
+       IFA_UNSPEC          = 0x0
+       IFA_ADDRESS         = 0x1
+       IFA_LOCAL           = 0x2
+       IFA_LABEL           = 0x3
+       IFA_BROADCAST       = 0x4
+       IFA_ANYCAST         = 0x5
+       IFA_CACHEINFO       = 0x6
+       IFA_MULTICAST       = 0x7
+       IFLA_UNSPEC         = 0x0
+       IFLA_ADDRESS        = 0x1
+       IFLA_BROADCAST      = 0x2
+       IFLA_IFNAME         = 0x3
+       IFLA_MTU            = 0x4
+       IFLA_LINK           = 0x5
+       IFLA_QDISC          = 0x6
+       IFLA_STATS          = 0x7
+       IFLA_COST           = 0x8
+       IFLA_PRIORITY       = 0x9
+       IFLA_MASTER         = 0xa
+       IFLA_WIRELESS       = 0xb
+       IFLA_PROTINFO       = 0xc
+       IFLA_TXQLEN         = 0xd
+       IFLA_MAP            = 0xe
+       IFLA_WEIGHT         = 0xf
+       IFLA_OPERSTATE      = 0x10
+       IFLA_LINKMODE       = 0x11
+       IFLA_LINKINFO       = 0x12
+       IFLA_NET_NS_PID     = 0x13
+       IFLA_IFALIAS        = 0x14
+       IFLA_MAX            = 0x22
+       RT_SCOPE_UNIVERSE   = 0x0
+       RT_SCOPE_SITE       = 0xc8
+       RT_SCOPE_LINK       = 0xfd
+       RT_SCOPE_HOST       = 0xfe
+       RT_SCOPE_NOWHERE    = 0xff
+       RT_TABLE_UNSPEC     = 0x0
+       RT_TABLE_COMPAT     = 0xfc
+       RT_TABLE_DEFAULT    = 0xfd
+       RT_TABLE_MAIN       = 0xfe
+       RT_TABLE_LOCAL      = 0xff
+       RT_TABLE_MAX        = 0xffffffff
+       RTA_UNSPEC          = 0x0
+       RTA_DST             = 0x1
+       RTA_SRC             = 0x2
+       RTA_IIF             = 0x3
+       RTA_OIF             = 0x4
+       RTA_GATEWAY         = 0x5
+       RTA_PRIORITY        = 0x6
+       RTA_PREFSRC         = 0x7
+       RTA_METRICS         = 0x8
+       RTA_MULTIPATH       = 0x9
+       RTA_FLOW            = 0xb
+       RTA_CACHEINFO       = 0xc
+       RTA_TABLE           = 0xf
+       RTN_UNSPEC          = 0x0
+       RTN_UNICAST         = 0x1
+       RTN_LOCAL           = 0x2
+       RTN_BROADCAST       = 0x3
+       RTN_ANYCAST         = 0x4
+       RTN_MULTICAST       = 0x5
+       RTN_BLACKHOLE       = 0x6
+       RTN_UNREACHABLE     = 0x7
+       RTN_PROHIBIT        = 0x8
+       RTN_THROW           = 0x9
+       RTN_NAT             = 0xa
+       RTN_XRESOLVE        = 0xb
+       RTNLGRP_NONE        = 0x0
+       RTNLGRP_LINK        = 0x1
+       RTNLGRP_NOTIFY      = 0x2
+       RTNLGRP_NEIGH       = 0x3
+       RTNLGRP_TC          = 0x4
+       RTNLGRP_IPV4_IFADDR = 0x5
+       RTNLGRP_IPV4_MROUTE = 0x6
+       RTNLGRP_IPV4_ROUTE  = 0x7
+       RTNLGRP_IPV4_RULE   = 0x8
+       RTNLGRP_IPV6_IFADDR = 0x9
+       RTNLGRP_IPV6_MROUTE = 0xa
+       RTNLGRP_IPV6_ROUTE  = 0xb
+       RTNLGRP_IPV6_IFINFO = 0xc
+       RTNLGRP_IPV6_PREFIX = 0x12
+       RTNLGRP_IPV6_RULE   = 0x13
+       RTNLGRP_ND_USEROPT  = 0x14
+       SizeofNlMsghdr      = 0x10
+       SizeofNlMsgerr      = 0x14
+       SizeofRtGenmsg      = 0x1
+       SizeofNlAttr        = 0x4
+       SizeofRtAttr        = 0x4
+       SizeofIfInfomsg     = 0x10
+       SizeofIfAddrmsg     = 0x8
+       SizeofRtMsg         = 0xc
+       SizeofRtNexthop     = 0x8
+)
+
+type NlMsghdr struct {
+       Len   uint32
+       Type  uint16
+       Flags uint16
+       Seq   uint32
+       Pid   uint32
+}
+
+type NlMsgerr struct {
+       Error int32
+       Msg   NlMsghdr
+}
+
+type RtGenmsg struct {
+       Family uint8
+}
+
+type NlAttr struct {
+       Len  uint16
+       Type uint16
+}
+
+type RtAttr struct {
+       Len  uint16
+       Type uint16
+}
+
+type IfInfomsg struct {
+       Family     uint8
+       X__ifi_pad uint8
+       Type       uint16
+       Index      int32
+       Flags      uint32
+       Change     uint32
+}
+
+type IfAddrmsg struct {
+       Family    uint8
+       Prefixlen uint8
+       Flags     uint8
+       Scope     uint8
+       Index     uint32
+}
+
+type RtMsg struct {
+       Family   uint8
+       Dst_len  uint8
+       Src_len  uint8
+       Tos      uint8
+       Table    uint8
+       Protocol uint8
+       Scope    uint8
+       Type     uint8
+       Flags    uint32
+}
+
+type RtNexthop struct {
+       Len     uint16
+       Flags   uint8
+       Hops    uint8
+       Ifindex int32
+}
+
+const (
+       SizeofSockFilter = 0x8
+       SizeofSockFprog  = 0x10
+)
+
+type SockFilter struct {
+       Code uint16
+       Jt   uint8
+       Jf   uint8
+       K    uint32
+}
+
+type SockFprog struct {
+       Len       uint16
+       Pad_cgo_0 [6]byte
+       Filter    *SockFilter
+}
+
+type InotifyEvent struct {
+       Wd     int32
+       Mask   uint32
+       Cookie uint32
+       Len    uint32
+       Name   [0]uint8
+}
+
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+       Gpr       [32]uint64
+       Nip       uint64
+       Msr       uint64
+       Orig_gpr3 uint64
+       Ctr       uint64
+       Link      uint64
+       Xer       uint64
+       Ccr       uint64
+       Softe     uint64
+       Trap      uint64
+       Dar       uint64
+       Dsisr     uint64
+       Result    uint64
+}
+
+type FdSet struct {
+       Bits [16]int64
+}
+
+type Sysinfo_t struct {
+       Uptime    int64
+       Loads     [3]uint64
+       Totalram  uint64
+       Freeram   uint64
+       Sharedram uint64
+       Bufferram uint64
+       Totalswap uint64
+       Freeswap  uint64
+       Procs     uint16
+       Pad       uint16
+       Pad_cgo_0 [4]byte
+       Totalhigh uint64
+       Freehigh  uint64
+       Unit      uint32
+       X_f       [0]byte
+       Pad_cgo_1 [4]byte
+}
+
+type Utsname struct {
+       Sysname    [65]uint8
+       Nodename   [65]uint8
+       Release    [65]uint8
+       Version    [65]uint8
+       Machine    [65]uint8
+       Domainname [65]uint8
+}
+
+type Ustat_t struct {
+       Tfree     int32
+       Pad_cgo_0 [4]byte
+       Tinode    uint64
+       Fname     [6]uint8
+       Fpack     [6]uint8
+       Pad_cgo_1 [4]byte
+}
+
+type EpollEvent struct {
+       Events uint32
+       Fd     int32
+       Pad    int32
+}
+
+const (
+       _AT_FDCWD = -0x64
+)
+
+type Termios struct {
+       Iflag     uint32
+       Oflag     uint32
+       Cflag     uint32
+       Lflag     uint32
+       Line      uint8
+       Cc        [32]uint8
+       Pad_cgo_0 [3]byte
+       Ispeed    uint32
+       Ospeed    uint32
+}
+
+const (
+       IUCLC  = 0x1000
+       OLCUC  = 0x4
+       TCGETS = 0x403c7413
+       TCSETS = 0x803c7414
+       XCASE  = 0x4000
+)
diff --git a/src/syscall/ztypes_linux_power64le.go b/src/syscall/ztypes_linux_power64le.go
new file mode 100644 (file)
index 0000000..df481f5
--- /dev/null
@@ -0,0 +1,602 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+       sizeofPtr      = 0x8
+       sizeofShort    = 0x2
+       sizeofInt      = 0x4
+       sizeofLong     = 0x8
+       sizeofLongLong = 0x8
+       PathMax        = 0x1000
+)
+
+type (
+       _C_short     int16
+       _C_int       int32
+       _C_long      int64
+       _C_long_long int64
+)
+
+type Timespec struct {
+       Sec  int64
+       Nsec int64
+}
+
+type Timeval struct {
+       Sec  int64
+       Usec int64
+}
+
+type Timex struct {
+       Modes     uint32
+       Pad_cgo_0 [4]byte
+       Offset    int64
+       Freq      int64
+       Maxerror  int64
+       Esterror  int64
+       Status    int32
+       Pad_cgo_1 [4]byte
+       Constant  int64
+       Precision int64
+       Tolerance int64
+       Time      Timeval
+       Tick      int64
+       Ppsfreq   int64
+       Jitter    int64
+       Shift     int32
+       Pad_cgo_2 [4]byte
+       Stabil    int64
+       Jitcnt    int64
+       Calcnt    int64
+       Errcnt    int64
+       Stbcnt    int64
+       Tai       int32
+       Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+       Utime  int64
+       Stime  int64
+       Cutime int64
+       Cstime int64
+}
+
+type Utimbuf struct {
+       Actime  int64
+       Modtime int64
+}
+
+type Rusage struct {
+       Utime    Timeval
+       Stime    Timeval
+       Maxrss   int64
+       Ixrss    int64
+       Idrss    int64
+       Isrss    int64
+       Minflt   int64
+       Majflt   int64
+       Nswap    int64
+       Inblock  int64
+       Oublock  int64
+       Msgsnd   int64
+       Msgrcv   int64
+       Nsignals int64
+       Nvcsw    int64
+       Nivcsw   int64
+}
+
+type Rlimit struct {
+       Cur uint64
+       Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+       Dev                uint64
+       Ino                uint64
+       Nlink              uint64
+       Mode               uint32
+       Uid                uint32
+       Gid                uint32
+       X__pad2            int32
+       Rdev               uint64
+       Size               int64
+       Blksize            int64
+       Blocks             int64
+       Atim               Timespec
+       Mtim               Timespec
+       Ctim               Timespec
+       X__glibc_reserved4 uint64
+       X__glibc_reserved5 uint64
+       X__glibc_reserved6 uint64
+}
+
+type Statfs_t struct {
+       Type    int64
+       Bsize   int64
+       Blocks  uint64
+       Bfree   uint64
+       Bavail  uint64
+       Files   uint64
+       Ffree   uint64
+       Fsid    Fsid
+       Namelen int64
+       Frsize  int64
+       Flags   int64
+       Spare   [4]int64
+}
+
+type Dirent struct {
+       Ino       uint64
+       Off       int64
+       Reclen    uint16
+       Type      uint8
+       Name      [256]uint8
+       Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+       X__val [2]int32
+}
+
+type Flock_t struct {
+       Type      int16
+       Whence    int16
+       Pad_cgo_0 [4]byte
+       Start     int64
+       Len       int64
+       Pid       int32
+       Pad_cgo_1 [4]byte
+}
+
+type RawSockaddrInet4 struct {
+       Family uint16
+       Port   uint16
+       Addr   [4]byte /* in_addr */
+       Zero   [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+       Family   uint16
+       Port     uint16
+       Flowinfo uint32
+       Addr     [16]byte /* in6_addr */
+       Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+       Family uint16
+       Path   [108]int8
+}
+
+type RawSockaddrLinklayer struct {
+       Family   uint16
+       Protocol uint16
+       Ifindex  int32
+       Hatype   uint16
+       Pkttype  uint8
+       Halen    uint8
+       Addr     [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+       Family uint16
+       Pad    uint16
+       Pid    uint32
+       Groups uint32
+}
+
+type RawSockaddr struct {
+       Family uint16
+       Data   [14]uint8
+}
+
+type RawSockaddrAny struct {
+       Addr RawSockaddr
+       Pad  [96]uint8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+       Onoff  int32
+       Linger int32
+}
+
+type Iovec struct {
+       Base *byte
+       Len  uint64
+}
+
+type IPMreq struct {
+       Multiaddr [4]byte /* in_addr */
+       Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+       Multiaddr [4]byte /* in_addr */
+       Address   [4]byte /* in_addr */
+       Ifindex   int32
+}
+
+type IPv6Mreq struct {
+       Multiaddr [16]byte /* in6_addr */
+       Interface uint32
+}
+
+type Msghdr struct {
+       Name       *byte
+       Namelen    uint32
+       Pad_cgo_0  [4]byte
+       Iov        *Iovec
+       Iovlen     uint64
+       Control    *byte
+       Controllen uint64
+       Flags      int32
+       Pad_cgo_1  [4]byte
+}
+
+type Cmsghdr struct {
+       Len          uint64
+       Level        int32
+       Type         int32
+       X__cmsg_data [0]uint8
+}
+
+type Inet4Pktinfo struct {
+       Ifindex  int32
+       Spec_dst [4]byte /* in_addr */
+       Addr     [4]byte /* in_addr */
+}
+
+type Inet6Pktinfo struct {
+       Addr    [16]byte /* in6_addr */
+       Ifindex uint32
+}
+
+type IPv6MTUInfo struct {
+       Addr RawSockaddrInet6
+       Mtu  uint32
+}
+
+type ICMPv6Filter struct {
+       Data [8]uint32
+}
+
+type Ucred struct {
+       Pid int32
+       Uid uint32
+       Gid uint32
+}
+
+type TCPInfo struct {
+       State          uint8
+       Ca_state       uint8
+       Retransmits    uint8
+       Probes         uint8
+       Backoff        uint8
+       Options        uint8
+       Pad_cgo_0      [2]byte
+       Rto            uint32
+       Ato            uint32
+       Snd_mss        uint32
+       Rcv_mss        uint32
+       Unacked        uint32
+       Sacked         uint32
+       Lost           uint32
+       Retrans        uint32
+       Fackets        uint32
+       Last_data_sent uint32
+       Last_ack_sent  uint32
+       Last_data_recv uint32
+       Last_ack_recv  uint32
+       Pmtu           uint32
+       Rcv_ssthresh   uint32
+       Rtt            uint32
+       Rttvar         uint32
+       Snd_ssthresh   uint32
+       Snd_cwnd       uint32
+       Advmss         uint32
+       Reordering     uint32
+       Rcv_rtt        uint32
+       Rcv_space      uint32
+       Total_retrans  uint32
+}
+
+const (
+       SizeofSockaddrInet4     = 0x10
+       SizeofSockaddrInet6     = 0x1c
+       SizeofSockaddrAny       = 0x70
+       SizeofSockaddrUnix      = 0x6e
+       SizeofSockaddrLinklayer = 0x14
+       SizeofSockaddrNetlink   = 0xc
+       SizeofLinger            = 0x8
+       SizeofIPMreq            = 0x8
+       SizeofIPMreqn           = 0xc
+       SizeofIPv6Mreq          = 0x14
+       SizeofMsghdr            = 0x38
+       SizeofCmsghdr           = 0x10
+       SizeofInet4Pktinfo      = 0xc
+       SizeofInet6Pktinfo      = 0x14
+       SizeofIPv6MTUInfo       = 0x20
+       SizeofICMPv6Filter      = 0x20
+       SizeofUcred             = 0xc
+       SizeofTCPInfo           = 0x68
+)
+
+const (
+       IFA_UNSPEC          = 0x0
+       IFA_ADDRESS         = 0x1
+       IFA_LOCAL           = 0x2
+       IFA_LABEL           = 0x3
+       IFA_BROADCAST       = 0x4
+       IFA_ANYCAST         = 0x5
+       IFA_CACHEINFO       = 0x6
+       IFA_MULTICAST       = 0x7
+       IFLA_UNSPEC         = 0x0
+       IFLA_ADDRESS        = 0x1
+       IFLA_BROADCAST      = 0x2
+       IFLA_IFNAME         = 0x3
+       IFLA_MTU            = 0x4
+       IFLA_LINK           = 0x5
+       IFLA_QDISC          = 0x6
+       IFLA_STATS          = 0x7
+       IFLA_COST           = 0x8
+       IFLA_PRIORITY       = 0x9
+       IFLA_MASTER         = 0xa
+       IFLA_WIRELESS       = 0xb
+       IFLA_PROTINFO       = 0xc
+       IFLA_TXQLEN         = 0xd
+       IFLA_MAP            = 0xe
+       IFLA_WEIGHT         = 0xf
+       IFLA_OPERSTATE      = 0x10
+       IFLA_LINKMODE       = 0x11
+       IFLA_LINKINFO       = 0x12
+       IFLA_NET_NS_PID     = 0x13
+       IFLA_IFALIAS        = 0x14
+       IFLA_MAX            = 0x22
+       RT_SCOPE_UNIVERSE   = 0x0
+       RT_SCOPE_SITE       = 0xc8
+       RT_SCOPE_LINK       = 0xfd
+       RT_SCOPE_HOST       = 0xfe
+       RT_SCOPE_NOWHERE    = 0xff
+       RT_TABLE_UNSPEC     = 0x0
+       RT_TABLE_COMPAT     = 0xfc
+       RT_TABLE_DEFAULT    = 0xfd
+       RT_TABLE_MAIN       = 0xfe
+       RT_TABLE_LOCAL      = 0xff
+       RT_TABLE_MAX        = 0xffffffff
+       RTA_UNSPEC          = 0x0
+       RTA_DST             = 0x1
+       RTA_SRC             = 0x2
+       RTA_IIF             = 0x3
+       RTA_OIF             = 0x4
+       RTA_GATEWAY         = 0x5
+       RTA_PRIORITY        = 0x6
+       RTA_PREFSRC         = 0x7
+       RTA_METRICS         = 0x8
+       RTA_MULTIPATH       = 0x9
+       RTA_FLOW            = 0xb
+       RTA_CACHEINFO       = 0xc
+       RTA_TABLE           = 0xf
+       RTN_UNSPEC          = 0x0
+       RTN_UNICAST         = 0x1
+       RTN_LOCAL           = 0x2
+       RTN_BROADCAST       = 0x3
+       RTN_ANYCAST         = 0x4
+       RTN_MULTICAST       = 0x5
+       RTN_BLACKHOLE       = 0x6
+       RTN_UNREACHABLE     = 0x7
+       RTN_PROHIBIT        = 0x8
+       RTN_THROW           = 0x9
+       RTN_NAT             = 0xa
+       RTN_XRESOLVE        = 0xb
+       RTNLGRP_NONE        = 0x0
+       RTNLGRP_LINK        = 0x1
+       RTNLGRP_NOTIFY      = 0x2
+       RTNLGRP_NEIGH       = 0x3
+       RTNLGRP_TC          = 0x4
+       RTNLGRP_IPV4_IFADDR = 0x5
+       RTNLGRP_IPV4_MROUTE = 0x6
+       RTNLGRP_IPV4_ROUTE  = 0x7
+       RTNLGRP_IPV4_RULE   = 0x8
+       RTNLGRP_IPV6_IFADDR = 0x9
+       RTNLGRP_IPV6_MROUTE = 0xa
+       RTNLGRP_IPV6_ROUTE  = 0xb
+       RTNLGRP_IPV6_IFINFO = 0xc
+       RTNLGRP_IPV6_PREFIX = 0x12
+       RTNLGRP_IPV6_RULE   = 0x13
+       RTNLGRP_ND_USEROPT  = 0x14
+       SizeofNlMsghdr      = 0x10
+       SizeofNlMsgerr      = 0x14
+       SizeofRtGenmsg      = 0x1
+       SizeofNlAttr        = 0x4
+       SizeofRtAttr        = 0x4
+       SizeofIfInfomsg     = 0x10
+       SizeofIfAddrmsg     = 0x8
+       SizeofRtMsg         = 0xc
+       SizeofRtNexthop     = 0x8
+)
+
+type NlMsghdr struct {
+       Len   uint32
+       Type  uint16
+       Flags uint16
+       Seq   uint32
+       Pid   uint32
+}
+
+type NlMsgerr struct {
+       Error int32
+       Msg   NlMsghdr
+}
+
+type RtGenmsg struct {
+       Family uint8
+}
+
+type NlAttr struct {
+       Len  uint16
+       Type uint16
+}
+
+type RtAttr struct {
+       Len  uint16
+       Type uint16
+}
+
+type IfInfomsg struct {
+       Family     uint8
+       X__ifi_pad uint8
+       Type       uint16
+       Index      int32
+       Flags      uint32
+       Change     uint32
+}
+
+type IfAddrmsg struct {
+       Family    uint8
+       Prefixlen uint8
+       Flags     uint8
+       Scope     uint8
+       Index     uint32
+}
+
+type RtMsg struct {
+       Family   uint8
+       Dst_len  uint8
+       Src_len  uint8
+       Tos      uint8
+       Table    uint8
+       Protocol uint8
+       Scope    uint8
+       Type     uint8
+       Flags    uint32
+}
+
+type RtNexthop struct {
+       Len     uint16
+       Flags   uint8
+       Hops    uint8
+       Ifindex int32
+}
+
+const (
+       SizeofSockFilter = 0x8
+       SizeofSockFprog  = 0x10
+)
+
+type SockFilter struct {
+       Code uint16
+       Jt   uint8
+       Jf   uint8
+       K    uint32
+}
+
+type SockFprog struct {
+       Len       uint16
+       Pad_cgo_0 [6]byte
+       Filter    *SockFilter
+}
+
+type InotifyEvent struct {
+       Wd     int32
+       Mask   uint32
+       Cookie uint32
+       Len    uint32
+       Name   [0]uint8
+}
+
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+       Gpr       [32]uint64
+       Nip       uint64
+       Msr       uint64
+       Orig_gpr3 uint64
+       Ctr       uint64
+       Link      uint64
+       Xer       uint64
+       Ccr       uint64
+       Softe     uint64
+       Trap      uint64
+       Dar       uint64
+       Dsisr     uint64
+       Result    uint64
+}
+
+type FdSet struct {
+       Bits [16]int64
+}
+
+type Sysinfo_t struct {
+       Uptime    int64
+       Loads     [3]uint64
+       Totalram  uint64
+       Freeram   uint64
+       Sharedram uint64
+       Bufferram uint64
+       Totalswap uint64
+       Freeswap  uint64
+       Procs     uint16
+       Pad       uint16
+       Pad_cgo_0 [4]byte
+       Totalhigh uint64
+       Freehigh  uint64
+       Unit      uint32
+       X_f       [0]byte
+       Pad_cgo_1 [4]byte
+}
+
+type Utsname struct {
+       Sysname    [65]uint8
+       Nodename   [65]uint8
+       Release    [65]uint8
+       Version    [65]uint8
+       Machine    [65]uint8
+       Domainname [65]uint8
+}
+
+type Ustat_t struct {
+       Tfree     int32
+       Pad_cgo_0 [4]byte
+       Tinode    uint64
+       Fname     [6]uint8
+       Fpack     [6]uint8
+       Pad_cgo_1 [4]byte
+}
+
+type EpollEvent struct {
+       Events uint32
+       Fd     int32
+       Pad    int32
+}
+
+const (
+       _AT_FDCWD = -0x64
+)
+
+type Termios struct {
+       Iflag     uint32
+       Oflag     uint32
+       Cflag     uint32
+       Lflag     uint32
+       Line      uint8
+       Cc        [32]uint8
+       Pad_cgo_0 [3]byte
+       Ispeed    uint32
+       Ospeed    uint32
+}
+
+const (
+       IUCLC  = 0x1000
+       OLCUC  = 0x4
+       TCGETS = 0x403c7413
+       TCSETS = 0x803c7414
+       XCASE  = 0x4000
+)
diff --git a/test/clearfat.go b/test/clearfat.go
new file mode 100644 (file)
index 0000000..45d5393
--- /dev/null
@@ -0,0 +1,68 @@
+// runoutput
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that {5,6,8,9}g/ggen.c:clearfat is zeroing the entire object.
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "strconv"
+       "strings"
+)
+
+const ntest = 1100
+
+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("poison$()\n\tclearfat$()\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
+
+$DECLS
+
+func main() {
+       $CALLS
+       if count != 0 {
+               println("failed", count, "case(s)")
+       }
+}
+`
+
+const decl = `
+func poison$() {
+       // Grow and poison the stack space that will be used by clearfat$
+       var t [2*$]byte
+       for i := range t {
+               t[i] = 0xff
+       }
+}
+
+func clearfat$() {
+       var t [$]byte
+
+       for _, x := range t {
+               if x != 0 {
+//                     println("clearfat$: index", i, "expected 0, got", x)
+                       count++
+                       break
+               }
+       }
+}
+`
index f15bb74ba1896f804bc005bce8923a1e7b0c60dc..f69d0a4c1e62e1e21a025301c42e7fdaf30f39e4 100644 (file)
@@ -614,8 +614,8 @@ func newT40() *T40 {
 
 func bad40() {
        t := newT40()
-       println()
        _ = t
+       println()
 }
 
 func good40() {
index 2757daef0b7b564a9726c320ff60d8891904207b..9d65e1e91b6d0ced57642d662fe1a2d6c980eb07 100644 (file)
@@ -1,4 +1,6 @@
 // errorcheck -0 -d=nil
+// Fails on power64x because of incomplete optimization.  See issue 9058.
+// +build !power64,!power64le
 
 // Copyright 2013 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
index 953a5bf0a61b627745f5c70fe632885eaa77d95c..3a63e8731d92ba14c777032484804499bca5ea86 100644 (file)
@@ -127,8 +127,9 @@ main 136 nosplit; REJECT
 # Calling a nosplit function from a nosplit function requires
 # having room for the saved caller PC and the called frame.
 # Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
+# Because Power64 doesn't save LR in the leaf, it gets an extra 8 bytes.
 main 112 nosplit call f; f 0 nosplit
-main 116 nosplit call f; f 0 nosplit; REJECT amd64
+main 116 nosplit call f; f 0 nosplit
 main 120 nosplit call f; f 0 nosplit; REJECT amd64
 main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
 main 128 nosplit call f; f 0 nosplit; REJECT
@@ -137,8 +138,8 @@ main 136 nosplit call f; f 0 nosplit; REJECT
 
 # Calling a splitting function from a nosplit function requires
 # having room for the saved caller PC of the call but also the
-# saved caller PC for the call to morestack. Again the ARM works
-# in less space.
+# saved caller PC for the call to morestack.
+# Again the ARM and Power64 work in less space.
 main 104 nosplit call f; f 0 call f
 main 108 nosplit call f; f 0 call f
 main 112 nosplit call f; f 0 call f; REJECT amd64
@@ -234,9 +235,17 @@ TestCases:
                fmt.Fprintf(&gobuf, "package main\n")
 
                var buf bytes.Buffer
-               if goarch == "arm" {
+               ptrSize := 4
+               switch goarch {
+               case "power64", "power64le":
+                       ptrSize = 8
+                       fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n#define RET RETURN\n")
+               case "arm":
                        fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n")
-               } else {
+               case "amd64":
+                       ptrSize = 8
+                       fmt.Fprintf(&buf, "#define REGISTER AX\n")
+               default:
                        fmt.Fprintf(&buf, "#define REGISTER AX\n")
                }
 
@@ -266,7 +275,7 @@ TestCases:
                                        size += 384 - 128
                                }
 
-                               if goarch == "amd64" && size%8 == 4 {
+                               if size%ptrSize == 4 {
                                        continue TestCases
                                }
                                nosplit := m[3]