summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-11-14 11:37:54 -0500
committerRuss Cox <rsc@golang.org>2014-11-14 11:37:54 -0500
commitf4110c2e9cc8f316e14f3a4a35789bc821b326bf (patch)
tree3a2b461d76cc134f7b71e5e1ef63bc37e7d25059
parent78d351d121615f1101f28f88920029f20884c689 (diff)
parent4664f7441b495d8fa8aa5001755cb5f85e790b19 (diff)
downloadgo-f4110c2e9cc8f316e14f3a4a35789bc821b326bf.tar.gz
[dev.garbage] all: merge default (f38460037b72) into dev.garbage
This is the revision that dev.cc is branched from. LGTM=austin R=austin CC=golang-codereviews https://codereview.appspot.com/169590043
-rw-r--r--.hgignore6
-rw-r--r--include/link.h27
-rw-r--r--lib/codereview/codereview.cfg1
-rw-r--r--lib/codereview/codereview.py16
-rw-r--r--src/cmd/5a/a.h3
-rw-r--r--src/cmd/5a/a.y26
-rw-r--r--src/cmd/5a/y.tab.c2049
-rw-r--r--src/cmd/5a/y.tab.h68
-rw-r--r--src/cmd/6a/a.h3
-rw-r--r--src/cmd/6a/a.y25
-rw-r--r--src/cmd/6a/y.tab.c1054
-rw-r--r--src/cmd/8a/a.h3
-rw-r--r--src/cmd/8a/a.y25
-rw-r--r--src/cmd/8a/y.tab.c1050
-rw-r--r--src/cmd/9a/Makefile10
-rw-r--r--src/cmd/9a/a.h170
-rw-r--r--src/cmd/9a/a.y991
-rw-r--r--src/cmd/9a/doc.go21
-rw-r--r--src/cmd/9a/lex.c725
-rw-r--r--src/cmd/9a/y.tab.c3398
-rw-r--r--src/cmd/9a/y.tab.h188
-rw-r--r--src/cmd/9c/Makefile5
-rw-r--r--src/cmd/9c/Notes14
-rw-r--r--src/cmd/9c/cgen.c1147
-rw-r--r--src/cmd/9c/doc.go17
-rw-r--r--src/cmd/9c/gc.h350
-rw-r--r--src/cmd/9c/list.c37
-rw-r--r--src/cmd/9c/machcap.c105
-rw-r--r--src/cmd/9c/mul.c638
-rw-r--r--src/cmd/9c/peep.c1076
-rw-r--r--src/cmd/9c/reg.c1163
-rw-r--r--src/cmd/9c/sgen.c291
-rw-r--r--src/cmd/9c/swt.c407
-rw-r--r--src/cmd/9c/txt.c1537
-rw-r--r--src/cmd/9g/cgen.c1763
-rw-r--r--src/cmd/9g/doc.go16
-rw-r--r--src/cmd/9g/galign.c54
-rw-r--r--src/cmd/9g/gg.h117
-rw-r--r--src/cmd/9g/ggen.c1034
-rw-r--r--src/cmd/9g/gobj.c240
-rw-r--r--src/cmd/9g/gsubr.c1705
-rw-r--r--src/cmd/9g/opt.h219
-rw-r--r--src/cmd/9g/peep.c94
-rw-r--r--src/cmd/9g/prog.c138
-rw-r--r--src/cmd/9g/reg.c161
-rw-r--r--src/cmd/9l/9.out.h514
-rw-r--r--src/cmd/9l/Makefile5
-rw-r--r--src/cmd/9l/asm.c338
-rw-r--r--src/cmd/9l/doc.go16
-rw-r--r--src/cmd/9l/l.h100
-rw-r--r--src/cmd/9l/list.c40
-rw-r--r--src/cmd/9l/obj.c108
-rw-r--r--src/cmd/api/goapi.go1
-rw-r--r--src/cmd/cc/lexbody25
-rw-r--r--src/cmd/cc/pgen.c4
-rw-r--r--src/cmd/cgo/main.go20
-rw-r--r--src/cmd/dist/build.c49
-rw-r--r--src/cmd/dist/buildgc.c2
-rw-r--r--src/cmd/dist/buildruntime.c7
-rw-r--r--src/cmd/dist/unix.c4
-rw-r--r--src/cmd/gc/builtin.c31
-rw-r--r--src/cmd/gc/go.h1
-rw-r--r--src/cmd/gc/pgen.c4
-rw-r--r--src/cmd/gc/plive.c19
-rw-r--r--src/cmd/gc/popt.c4
-rw-r--r--src/cmd/gc/reflect.c8
-rw-r--r--src/cmd/gc/runtime.go33
-rw-r--r--src/cmd/gc/typecheck.c6
-rw-r--r--src/cmd/gc/walk.c70
-rw-r--r--src/cmd/ld/data.c4
-rw-r--r--src/cmd/ld/doc.go6
-rw-r--r--src/cmd/ld/dwarf.c4
-rw-r--r--src/cmd/ld/elf.c29
-rw-r--r--src/cmd/ld/ldelf.c6
-rw-r--r--src/cmd/ld/lib.c36
-rw-r--r--src/cmd/ld/macho.c1
-rw-r--r--src/cmd/ld/symtab.c1
-rw-r--r--src/debug/elf/elf.go178
-rw-r--r--src/debug/elf/file.go50
-rw-r--r--src/debug/elf/file_test.go6
-rw-r--r--src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.objbin0 -> 3016 bytes
-rw-r--r--src/go/build/build.go2
-rw-r--r--src/go/build/syslist.go2
-rw-r--r--src/hash/crc32/crc32_generic.go2
-rw-r--r--src/liblink/asm9.c2784
-rw-r--r--src/liblink/list9.c409
-rw-r--r--src/liblink/obj9.c1086
-rw-r--r--src/liblink/objfile.c9
-rw-r--r--src/liblink/sched9.c835
-rw-r--r--src/math/abs_power64x.s14
-rw-r--r--src/math/big/arith_power64x.s46
-rw-r--r--src/math/stubs_power64x.s91
-rw-r--r--src/os/signal/sig.s8
-rw-r--r--src/reflect/all_test.go5
-rw-r--r--src/reflect/asm_power64x.s29
-rw-r--r--src/reflect/type.go8
-rwxr-xr-xsrc/run.bash3
-rw-r--r--src/runtime/arch_power64.go8
-rw-r--r--src/runtime/arch_power64.h14
-rw-r--r--src/runtime/arch_power64le.go8
-rw-r--r--src/runtime/arch_power64le.h14
-rw-r--r--src/runtime/asm_386.s64
-rw-r--r--src/runtime/asm_amd64.s84
-rw-r--r--src/runtime/asm_amd64p32.s64
-rw-r--r--src/runtime/asm_arm.s24
-rw-r--r--src/runtime/asm_power64x.s981
-rw-r--r--src/runtime/atomic.go38
-rw-r--r--src/runtime/atomic_power64x.s40
-rw-r--r--src/runtime/debug/stubs.s6
-rw-r--r--src/runtime/defs1_linux.go6
-rw-r--r--src/runtime/defs3_linux.go43
-rw-r--r--src/runtime/defs_linux.go11
-rw-r--r--src/runtime/defs_linux_power64.h204
-rw-r--r--src/runtime/defs_linux_power64le.h204
-rw-r--r--src/runtime/export_test.go2
-rw-r--r--src/runtime/gcinfo_test.go10
-rw-r--r--src/runtime/heapdump.c15
-rw-r--r--src/runtime/lfstack.c14
-rw-r--r--src/runtime/lfstack_test.go2
-rw-r--r--src/runtime/malloc.go78
-rw-r--r--src/runtime/malloc.h5
-rw-r--r--src/runtime/mcache.c2
-rw-r--r--src/runtime/mem_linux.c16
-rw-r--r--src/runtime/memclr_386.s46
-rw-r--r--src/runtime/memclr_amd64.s44
-rw-r--r--src/runtime/memclr_plan9_386.s24
-rw-r--r--src/runtime/memclr_power64x.s20
-rw-r--r--src/runtime/memmove_power64x.s40
-rw-r--r--src/runtime/mgc0.c1431
-rw-r--r--src/runtime/mgc0.go131
-rw-r--r--src/runtime/mgc0.h10
-rw-r--r--src/runtime/noasm.go (renamed from src/runtime/noasm_arm.go)2
-rw-r--r--src/runtime/os_darwin.c3
-rw-r--r--src/runtime/os_dragonfly.c3
-rw-r--r--src/runtime/os_freebsd.c3
-rw-r--r--src/runtime/os_linux.c40
-rw-r--r--src/runtime/os_nacl.c3
-rw-r--r--src/runtime/os_netbsd.c3
-rw-r--r--src/runtime/os_openbsd.c3
-rw-r--r--src/runtime/os_plan9.c6
-rw-r--r--src/runtime/os_solaris.c3
-rw-r--r--src/runtime/panic.c2
-rw-r--r--src/runtime/panic.go4
-rw-r--r--src/runtime/print1.go30
-rw-r--r--src/runtime/proc.c42
-rw-r--r--src/runtime/proc.go3
-rw-r--r--src/runtime/race_amd64.s18
-rw-r--r--src/runtime/rt0_linux_power64.s17
-rw-r--r--src/runtime/rt0_linux_power64le.s14
-rw-r--r--src/runtime/runtime.c6
-rw-r--r--src/runtime/runtime.h37
-rw-r--r--src/runtime/select.go7
-rw-r--r--src/runtime/signal_linux_power64.h49
-rw-r--r--src/runtime/signal_linux_power64le.h49
-rw-r--r--src/runtime/signal_power64x.c137
-rw-r--r--src/runtime/stack.c83
-rw-r--r--src/runtime/string.c2
-rw-r--r--src/runtime/string.go4
-rw-r--r--src/runtime/stubs.go13
-rw-r--r--src/runtime/sys_darwin_386.s4
-rw-r--r--src/runtime/sys_darwin_amd64.s4
-rw-r--r--src/runtime/sys_dragonfly_386.s4
-rw-r--r--src/runtime/sys_freebsd_386.s4
-rw-r--r--src/runtime/sys_linux_amd64.s8
-rw-r--r--src/runtime/sys_linux_arm.s8
-rw-r--r--src/runtime/sys_linux_power64x.s383
-rw-r--r--src/runtime/sys_nacl_386.s4
-rw-r--r--src/runtime/sys_nacl_amd64p32.s1
-rw-r--r--src/runtime/sys_nacl_arm.s1
-rw-r--r--src/runtime/sys_openbsd_386.s4
-rw-r--r--src/runtime/sys_power64x.c38
-rw-r--r--src/runtime/sys_solaris_amd64.s12
-rw-r--r--src/runtime/sys_windows_386.s12
-rw-r--r--src/runtime/sys_windows_amd64.s12
-rw-r--r--src/runtime/sys_x86.c1
-rw-r--r--src/runtime/thunk.s6
-rw-r--r--src/runtime/wbfat.go190
-rw-r--r--src/runtime/wbfat_gen.go41
-rw-r--r--src/sync/atomic/asm_power64x.s184
-rw-r--r--src/sync/atomic/atomic_test.go8
-rw-r--r--src/syscall/asm.s7
-rw-r--r--src/syscall/asm_linux_power64x.s104
-rwxr-xr-xsrc/syscall/mkall.sh17
-rwxr-xr-xsrc/syscall/mkerrors.sh1
-rw-r--r--src/syscall/syscall_linux_power64x.go97
-rw-r--r--src/syscall/types_linux.go110
-rw-r--r--src/syscall/zerrors_linux_power64.go1878
-rw-r--r--src/syscall/zerrors_linux_power64le.go1902
-rw-r--r--src/syscall/zsyscall_linux_power64.go1931
-rw-r--r--src/syscall/zsyscall_linux_power64le.go1931
-rw-r--r--src/syscall/zsysnum_linux_power64.go351
-rw-r--r--src/syscall/zsysnum_linux_power64le.go351
-rw-r--r--src/syscall/ztypes_linux_power64.go602
-rw-r--r--src/syscall/ztypes_linux_power64le.go602
-rw-r--r--test/live.go152
-rw-r--r--test/live2.go6
-rw-r--r--test/nosplit.go21
197 files changed, 41189 insertions, 3342 deletions
diff --git a/.hgignore b/.hgignore
index 007116113..a833065f2 100644
--- 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/include/link.h b/include/link.h
index 05e117c87..c80f46758 100644
--- a/include/link.h
+++ b/include/link.h
@@ -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,10 @@ struct Prog
int32 lineno;
Prog* link;
short as;
- uchar reg; // arm only
+ uchar reg; // arm, power64 only
uchar scond; // arm only
Addr from;
+ Addr from3; // power64 only, fma and rlwm
Addr to;
// for 5g, 6g, 8g internal use
@@ -103,11 +104,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 +234,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 +532,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 +582,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 +618,24 @@ char* headstr(int);
extern char* anames5[];
extern char* anames6[];
extern char* anames8[];
+extern char* anames9[];
extern char* cnames5[];
+extern char* cnames9[];
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.
diff --git a/lib/codereview/codereview.cfg b/lib/codereview/codereview.cfg
index 2801ebf8d..43dbf3ce3 100644
--- a/lib/codereview/codereview.cfg
+++ b/lib/codereview/codereview.cfg
@@ -1 +1,2 @@
defaultcc: golang-codereviews@googlegroups.com
+contributors: http://go.googlecode.com/hg/CONTRIBUTORS
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 416702c63..0c9b27a31 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -2024,13 +2024,13 @@ def submit(ui, repo, *pats, **opts):
# push to remote; if it fails for any reason, roll back
try:
new_heads = len(hg_heads(ui, repo).split())
- if old_heads != new_heads and not (old_heads == 0 and new_heads == 1):
+ if cl.desc.find("create new branch") < 0 and old_heads != new_heads and not (old_heads == 0 and new_heads == 1):
# Created new head, so we weren't up to date.
need_sync()
# Push changes to remote. If it works, we're committed. If not, roll back.
try:
- if hg_push(ui, repo):
+ if hg_push(ui, repo, new_branch=cl.desc.find("create new branch")>=0):
raise hg_util.Abort("push error")
except hg_error.Abort, e:
if e.message.find("push creates new heads") >= 0:
@@ -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],
diff --git a/src/cmd/5a/a.h b/src/cmd/5a/a.h
index bb60fe7de..df9838ad3 100644
--- a/src/cmd/5a/a.h
+++ b/src/cmd/5a/a.h
@@ -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);
diff --git a/src/cmd/5a/a.y b/src/cmd/5a/a.y
index ad647606e..d365c7534 100644
--- a/src/cmd/5a/a.y
+++ b/src/cmd/5a/a.y
@@ -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;
}
diff --git a/src/cmd/5a/y.tab.c b/src/cmd/5a/y.tab.c
index a6251b835..ace80c7e0 100644
--- a/src/cmd/5a/y.tab.c
+++ b/src/cmd/5a/y.tab.c
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Bison implementation for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -26,7 +29,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -44,7 +47,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.7.12-4996"
+#define YYBISON_VERSION "2.3"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -52,55 +55,10 @@
/* Pure parsers. */
#define YYPURE 0
-/* Push parsers. */
-#define YYPUSH 0
-
-/* Pull parsers. */
-#define YYPULL 1
-
-
-
-
-/* Copy the first part of user declarations. */
-/* Line 371 of yacc.c */
-#line 31 "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
+
#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 */
+
/*-----------------------------------------------.
| 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;
+ }
+}
+
+/* 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:
}
+
diff --git a/src/cmd/5a/y.tab.h b/src/cmd/5a/y.tab.h
index f11fb85c6..f75cb22a7 100644
--- a/src/cmd/5a/y.tab.h
+++ b/src/cmd/5a/y.tab.h
@@ -1,21 +1,24 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996. */
+/* A Bison parser, made by GNU Bison 2.3. */
-/* Bison interface for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -26,20 +29,10 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -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/6a/a.h b/src/cmd/6a/a.h
index b3fb0bb19..e1927b6d4 100644
--- a/src/cmd/6a/a.h
+++ b/src/cmd/6a/a.h
@@ -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);
diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y
index 1089d4061..29011c7ff 100644
--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -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;
}
diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c
index b69fd95b5..a698079d2 100644
--- a/src/cmd/6a/y.tab.c
+++ b/src/cmd/6a/y.tab.c
@@ -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/8a/a.h b/src/cmd/8a/a.h
index adc388ca9..a1aca07ae 100644
--- a/src/cmd/8a/a.h
+++ b/src/cmd/8a/a.h
@@ -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);
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index 6bcf1313b..c810d3857 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -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;
}
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
index 85279c21f..f284d8ea2 100644
--- a/src/cmd/8a/y.tab.c
+++ b/src/cmd/8a/y.tab.c
@@ -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/9a/Makefile b/src/cmd/9a/Makefile
new file mode 100644
index 000000000..27290ddd7
--- /dev/null
+++ b/src/cmd/9a/Makefile
@@ -0,0 +1,10 @@
+# Copyright 2012 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../Make.dist
+
+install: y.tab.h
+
+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
index 000000000..7a01fc947
--- /dev/null
+++ b/src/cmd/9a/a.h
@@ -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
index 000000000..b36614615
--- /dev/null
+++ b/src/cmd/9a/a.y
@@ -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
index 000000000..44bf89dc0
--- /dev/null
+++ b/src/cmd/9a/doc.go
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +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
index 000000000..26f21f743
--- /dev/null
+++ b/src/cmd/9a/lex.c
@@ -0,0 +1,725 @@
+// 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,
+ "R30", LREG, 30,
+ "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,
+
+ "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
index 000000000..6025a2402
--- /dev/null
+++ b/src/cmd/9a/y.tab.c
@@ -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
+
+
+
+#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 */
+
+
+/*-----------------------------------------------.
+| 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;
+ }
+}
+
+
+/* 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
index 000000000..e6b93a2ec
--- /dev/null
+++ b/src/cmd/9a/y.tab.h
@@ -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/9c/Makefile b/src/cmd/9c/Makefile
new file mode 100644
index 000000000..3f528d751
--- /dev/null
+++ b/src/cmd/9c/Makefile
@@ -0,0 +1,5 @@
+# Copyright 2012 The Go 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/9c/Notes b/src/cmd/9c/Notes
new file mode 100644
index 000000000..92dd9deb3
--- /dev/null
+++ b/src/cmd/9c/Notes
@@ -0,0 +1,14 @@
+- effect of register expansion on 32-bit shifts and masks etc
+9c
+- multab
+- floating-point conversions
+- conversions of constants
+- nodtype for loads
+- sign-extension instruction (32-64) when in register?
+- double indexing
+- SLW (eg, in cat)
+- scheduling
+
+9l
+- D_QCONST, DWORD
+- maskgen
diff --git a/src/cmd/9c/cgen.c b/src/cmd/9c/cgen.c
new file mode 100644
index 000000000..bd1f7b28f
--- /dev/null
+++ b/src/cmd/9c/cgen.c
@@ -0,0 +1,1147 @@
+// cmd/9c/cgen.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 "gc.h"
+#include "../../runtime/funcdata.h"
+
+void
+cgen(Node *n, Node *nn)
+{
+ Node *l, *r;
+ Prog *p1;
+ Node nod, nod1, nod2, nod3, nod4;
+ int o;
+ int32 v, curs;
+
+ 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->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) {
+ if(nn != Z || r->addable < INDEXED) {
+ regalloc(&nod, r, nn);
+ cgen(r, &nod);
+ gmove(&nod, l);
+ 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 OXOR:
+ if(nn != Z)
+ if(r->op == OCONST && r->vconst == -1){
+ cgen(l, nn);
+ gopcode(OCOM, nn, Z, nn);
+ break;
+ }
+
+ case OADD:
+ case OSUB:
+ case OAND:
+ case OOR:
+ case OLSHR:
+ case OASHL:
+ case OASHR:
+ /*
+ * immediate operands
+ */
+ if(nn != Z &&
+ r->op == OCONST &&
+ !typefd[n->type->etype] &&
+ immconst(r)) {
+ cgen(l, nn);
+ if(r->vconst == 0)
+ if(o != OAND)
+ break;
+ if(nn != Z)
+ gopcode(o, r, Z, nn);
+ break;
+ }
+
+ case OMUL:
+ case OLMUL:
+ case OLDIV:
+ case OLMOD:
+ case ODIV:
+ case OMOD:
+ if(nn == Z) {
+ nullwarn(l, r);
+ break;
+ }
+ if(o == OMUL || o == OLMUL) {
+ if(mulcon(n, nn))
+ break;
+ if(debug['M'])
+ print("%L multiply\n", n->lineno);
+ }
+ if(l->complex >= r->complex) {
+ regalloc(&nod, l, nn);
+ cgen(l, &nod);
+ regalloc(&nod1, l, Z); /* note: l used for type, so shifts work! */
+ cgen(r, &nod1);
+ gopcode(o, &nod1, Z, &nod);
+ } else {
+ regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
+ 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 &&
+ !typefd[n->type->etype] &&
+ immconst(r)) {
+ if(l->addable < INDEXED)
+ reglcgen(&nod2, l, Z);
+ else
+ nod2 = *l;
+ regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
+ 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(&nod, n, nn);
+ cgen(r, &nod);
+ } else {
+ regalloc(&nod, n, nn);
+ cgen(r, &nod);
+ if(l->addable < INDEXED)
+ reglcgen(&nod2, l, Z);
+ else
+ nod2 = *l;
+ }
+ regalloc(&nod1, n, Z);
+ gopcode(OAS, &nod2, Z, &nod1);
+ if(nod1.type->etype != nod.type->etype){
+ regalloc(&nod3, &nod, Z);
+ gmove(&nod1, &nod3);
+ regfree(&nod1);
+ nod1 = nod3;
+ }
+ gopcode(o, &nod, &nod1, &nod);
+ gmove(&nod, &nod2);
+ if(nn != Z)
+ gmove(&nod, nn);
+ regfree(&nod);
+ regfree(&nod1);
+ if(l->addable < INDEXED)
+ regfree(&nod2);
+ break;
+
+ asbitop:
+ regalloc(&nod4, n, nn);
+ regalloc(&nod3, r, Z);
+ if(l->complex >= r->complex) {
+ bitload(l, &nod, &nod1, &nod2, &nod4);
+ cgen(r, &nod3);
+ } else {
+ cgen(r, &nod3);
+ bitload(l, &nod, &nod1, &nod2, &nod4);
+ }
+ gmove(&nod, &nod4);
+ gopcode(n->op, &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); // update maxarg if nothing else
+ if(nn != Z)
+ gopcode(OAS, &nod, Z, nn);
+ if(nod.op == OREGISTER)
+ regfree(&nod);
+ break;
+
+ case OIND:
+ if(nn == Z) {
+ cgen(l, nn);
+ 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);
+ 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) && nocast(n->type, nn->type)) {
+ /* both null, gen l->nn */
+ cgen(l, nn);
+ break;
+ }
+ regalloc(&nod, l, nn);
+ cgen(l, &nod);
+ regalloc(&nod1, n, &nod);
+ 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);
+ if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
+ gins(ANOP, l, Z);
+
+ 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;
+}
+
+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;
+ }
+ 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:
+ if(n->op == OCONST) {
+ o = vconst(n);
+ if(!true)
+ o = !o;
+ gbranch(OGOTO);
+ if(o) {
+ p1 = p;
+ gbranch(OGOTO);
+ patch(p1, pc);
+ }
+ goto com;
+ }
+ regalloc(&nod, n, nn);
+ cgen(n, &nod);
+ o = ONE;
+ if(true)
+ o = comrel[relindex(o)];
+ if(typefd[n->type->etype]) {
+ nodreg(&nod1, n, NREG+FREGZERO);
+ gopcode(o, &nod, Z, &nod1);
+ } else
+ gopcode(o, &nod, Z, nodconst(0));
+ regfree(&nod);
+ 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);
+ cgen(r, &nod);
+ regsalloc(&nod1, r);
+ gopcode(OAS, &nod, Z, &nod1);
+ regfree(&nod);
+ nod = *n;
+ nod.right = &nod1;
+ boolgen(&nod, true, nn);
+ break;
+ }
+ if(sconst(r)) {
+ regalloc(&nod, l, nn);
+ cgen(l, &nod);
+ gopcode(o, &nod, Z, r);
+ regfree(&nod);
+ goto com;
+ }
+ if(l->complex >= r->complex) {
+ regalloc(&nod1, l, nn);
+ cgen(l, &nod1);
+ regalloc(&nod, r, Z);
+ cgen(r, &nod);
+ } else {
+ regalloc(&nod, r, nn);
+ cgen(r, &nod);
+ regalloc(&nod1, l, Z);
+ cgen(l, &nod1);
+ }
+ gopcode(o, &nod1, Z, &nod);
+ regfree(&nod);
+ regfree(&nod1);
+
+ com:
+ if(nn != Z) {
+ p1 = p;
+ gopcode(OAS, nodconst(1L), Z, nn);
+ gbranch(OGOTO);
+ p2 = p;
+ patch(p1, pc);
+ gopcode(OAS, nodconst(0L), 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(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
+ gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
+ else
+ gopcode(OAS, nod32const(n->vconst), Z, &nod1);
+ nod1.xoffset += SZ_LONG;
+ if(align(0, types[TCHAR], Aarg1, nil)) /* 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 effects
+ */
+ if(nn != Z && side(nn)) {
+ nod1 = *n;
+ nod1.type = typ(TIND, n->type);
+ regalloc(&nod2, &nod1, Z);
+ 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;
+
+ /* prtree(&nod0, "hand craft"); /* */
+ cgen(&nod0, Z);
+ }
+ break;
+
+ case OAS:
+ if(nn == Z) {
+ if(n->addable < INDEXED)
+ sugen(n->right, n->left, w);
+ break;
+ }
+ /* BOTCH -- functions can clobber rathole */
+ 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;
+ }
+
+ if(n->complex > nn->complex) {
+ t = n->type;
+ n->type = types[TLONG];
+ reglcgen(&nod1, n, Z);
+ n->type = t;
+
+ t = nn->type;
+ nn->type = types[TLONG];
+ reglcgen(&nod2, nn, Z);
+ nn->type = t;
+ } else {
+ t = nn->type;
+ nn->type = types[TLONG];
+ reglcgen(&nod2, nn, Z);
+ nn->type = t;
+
+ t = n->type;
+ n->type = types[TLONG];
+ reglcgen(&nod1, n, Z);
+ n->type = t;
+ }
+
+ w /= SZ_LONG;
+ if(w <= 5) {
+ layout(&nod1, &nod2, w, 0, Z);
+ goto out;
+ }
+
+ /*
+ * minimize space for unrolling loop
+ * 3,4,5 times. (6 or more is never minimum)
+ * if small structure, try 2 also.
+ */
+ c = 0; /* set */
+ m = 100;
+ i = 3;
+ if(w <= 15)
+ i = 2;
+ for(; i<=5; i++)
+ if(i + w%i <= m) {
+ c = i;
+ m = c + w%c;
+ }
+
+ regalloc(&nod3, &regnode, Z);
+ layout(&nod1, &nod2, w%c, w/c, &nod3);
+
+ pc1 = pc;
+ layout(&nod1, &nod2, c, 0, Z);
+
+ gopcode(OSUB, nodconst(1L), Z, &nod3);
+ nod1.op = OREGISTER;
+ gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
+ nod2.op = OREGISTER;
+ gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
+
+ gopcode(OGT, &nod3, Z, nodconst(0));
+ patch(p, pc1);
+
+ regfree(&nod3);
+out:
+ regfree(&nod1);
+ regfree(&nod2);
+}
+
+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, &regnode, Z);
+ regalloc(&t2, &regnode, Z);
+ if(c > 0) {
+ gopcode(OAS, f, Z, &t1);
+ f->xoffset += SZ_LONG;
+ }
+ if(cn != Z)
+ gopcode(OAS, nodconst(cv), Z, cn);
+ if(c > 1) {
+ gopcode(OAS, f, Z, &t2);
+ f->xoffset += SZ_LONG;
+ }
+ if(c > 0) {
+ gopcode(OAS, &t1, Z, t);
+ t->xoffset += SZ_LONG;
+ }
+ if(c > 2) {
+ gopcode(OAS, f, Z, &t1);
+ f->xoffset += SZ_LONG;
+ }
+ if(c > 1) {
+ gopcode(OAS, &t2, Z, t);
+ t->xoffset += SZ_LONG;
+ }
+ if(c > 2) {
+ gopcode(OAS, &t1, Z, t);
+ t->xoffset += SZ_LONG;
+ }
+ regfree(&t1);
+ regfree(&t2);
+}
diff --git a/src/cmd/9c/doc.go b/src/cmd/9c/doc.go
new file mode 100644
index 000000000..6c9b4762d
--- /dev/null
+++ b/src/cmd/9c/doc.go
@@ -0,0 +1,17 @@
+// 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
+
+/*
+
+9c 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 Power64, referred to by these tools as
+power64 (big endian) or power64le (little endian).
+
+*/
+package main
diff --git a/src/cmd/9c/gc.h b/src/cmd/9c/gc.h
new file mode 100644
index 000000000..fbe5099fe
--- /dev/null
+++ b/src/cmd/9c/gc.h
@@ -0,0 +1,350 @@
+// cmd/9c/gc.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 "../cc/cc.h"
+#include "../9l/9.out.h"
+
+/*
+ * 9c/powerpc64
+ */
+#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 Multab Multab;
+typedef struct Hintab Hintab;
+typedef struct Reg Reg;
+typedef struct Rgn Rgn;
+
+#define A ((Adr*)0)
+
+#define INDEXED 9
+#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 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 */
+
+ union
+ {
+ 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 Node vconstnode;
+EXTERN int32 continpc;
+EXTERN int32 curarg;
+EXTERN int32 cursafe;
+EXTERN Prog* lastp;
+extern int hintabsize;
+EXTERN int32 maxargsafe;
+EXTERN Multab multab[20];
+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 qregnode;
+EXTERN char string[NSNAME];
+EXTERN Sym* symrathole;
+EXTERN Node znode;
+EXTERN Prog zprog;
+EXTERN int reg[NREG+NREG];
+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 Var var[NVAR];
+EXTERN int32* idom;
+EXTERN Reg** rpo2r;
+EXTERN int32 maxnr;
+
+#define R0ISZERO (debug['0']==0)
+
+extern char* anames[];
+extern Hintab hintab[];
+
+/*
+ * sgen.c
+ */
+void codgen(Node*, Node*);
+void gen(Node*);
+void usedset(Node*, int);
+void noretval(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*);
+
+/*
+ * 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);
+Node* nodgconst(vlong v, Type *t);
+void nodreg(Node*, 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 raddr(Node*, Prog*);
+void naddr(Node*, Addr*);
+void gmove(Node*, Node*);
+void gins(int a, Node*, Node*);
+void gopcode(int, Node*, Node*, Node*);
+int samaddr(Node*, Node*);
+void gbranch(int);
+int immconst(Node*);
+void patch(Prog*, int32);
+int sconst(Node*);
+int sval(int32);
+int uconst(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*, Node*);
+void newcase(void);
+void bitload(Node*, Node*, Node*, Node*, Node*);
+void bitstore(Node*, Node*, Node*, Node*, Node*);
+int32 outstring(char*, int32);
+int mulcon(Node*, Node*);
+Multab* mulcon0(Node*, int32);
+int mulcon1(Node*, int32, Node*);
+void nullwarn(Node*, Node*);
+void sextern(Sym*, Node*, int32, int32);
+void gextern(Sym*, Node*, int32, int32);
+void outcode(void);
+
+/*
+ * list
+ */
+void listinit(void);
+int Pconv(Fmt*);
+int Aconv(Fmt*);
+int Dconv(Fmt*);
+int Sconv(Fmt*);
+int Nconv(Fmt*);
+int Bconv(Fmt*);
+
+/*
+ * 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 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);
+
+/*
+ * com64.c
+ */
+int com64(Node*);
+void com64init(void);
+void bool64(Node*);
+
+#pragma varargck type "A" int
+#pragma varargck type "B" Bits
+#pragma varargck type "D" Addr*
+#pragma varargck type "N" Addr*
+#pragma varargck type "P" Prog*
+#pragma varargck type "S" char*
diff --git a/src/cmd/9c/list.c b/src/cmd/9c/list.c
new file mode 100644
index 000000000..5cfc442cb
--- /dev/null
+++ b/src/cmd/9c/list.c
@@ -0,0 +1,37 @@
+// cmd/9c/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.
+
+#define EXTERN
+#include "gc.h"
+
+void
+listinit(void)
+{
+ listinit9();
+}
diff --git a/src/cmd/9c/machcap.c b/src/cmd/9c/machcap.c
new file mode 100644
index 000000000..af44bc820
--- /dev/null
+++ b/src/cmd/9c/machcap.c
@@ -0,0 +1,105 @@
+// cmd/9c/machcap.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 "gc.h"
+
+int
+machcap(Node *n)
+{
+
+ if(n == Z)
+ return 1; /* test */
+
+ switch(n->op) {
+ case OMUL:
+ case OLMUL:
+ case OASMUL:
+ case OASLMUL:
+ if(typechlv[n->type->etype])
+ return 1;
+ break;
+
+ 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;
+ case ONEG:
+ case OCOM:
+ break;
+ }
+ return 0;
+}
diff --git a/src/cmd/9c/mul.c b/src/cmd/9c/mul.c
new file mode 100644
index 000000000..353376f15
--- /dev/null
+++ b/src/cmd/9c/mul.c
@@ -0,0 +1,638 @@
+// cmd/9c/mul.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 "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 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(Node *n, 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("%L: multiply table failure %ld\n", n->lineno, v);
+ m->code[0] = 0;
+ return 0;
+
+no:
+ /*
+ * try to search
+ */
+ hint[0] = 0;
+ for(g=1; g<=6; g++) {
+ if(g >= 6 && v >= 65535)
+ break;
+ mulcp = hint+g;
+ *mulcp = 0;
+ if(gen1(g)) {
+ if(docode(hint, m->code, 1, 0))
+ return m;
+ print("%L: multiply table failure (g=%d h=%s) %ld\n",
+ n->lineno, g, hint, v);
+ break;
+ }
+ }
+
+ /*
+ * try a recur followed by a shift
+ */
+ g = 0;
+ while(!(v & 1)) {
+ g++;
+ v >>= 1;
+ }
+ if(g) {
+ m1 = mulcon0(n, 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/9c/peep.c b/src/cmd/9c/peep.c
new file mode 100644
index 000000000..2e8e2adcc
--- /dev/null
+++ b/src/cmd/9c/peep.c
@@ -0,0 +1,1076 @@
+// cmd/9c/peep.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 "gc.h"
+
+/*
+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;
+ }
+ }
+
+loop1:
+ t = 0;
+ for(r=firstr; r!=R; r=r->link) {
+ p = r->prog;
+ if(p->as == AMOVW || p->as == AMOVD || p->as == AFMOVS || p->as == AFMOVD)
+ if(regtyp(&p->to)) {
+ 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(regzer(&p->from))
+ if(p->to.type == D_REG) {
+ p->from.type = D_REG;
+ p->from.reg = REGZERO;
+ 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 AMOVH:
+ case AMOVHZ:
+ case AMOVB:
+ case AMOVBZ:
+ case AMOVW:
+ case AMOVWZ:
+ 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);
+ }
+
+ if(debug['D'] > 1)
+ return; /* allow following code improvement to be suppressed */
+
+ /*
+ * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
+ * when OP can set condition codes correctly
+ */
+ for(r=firstr; r!=R; r=r->link) {
+ p = r->prog;
+ switch(p->as) {
+ case ACMP:
+ case ACMPW: /* always safe? */
+ if(!regzer(&p->to))
+ continue;
+ r1 = r->s1;
+ if(r1 == R)
+ continue;
+ switch(r1->prog->as) {
+ default:
+ continue;
+ case ABCL:
+ case ABC:
+ /* the conditions can be complex and these are currently little used */
+ continue;
+ case ABEQ:
+ case ABGE:
+ case ABGT:
+ case ABLE:
+ case ABLT:
+ case ABNE:
+ case ABVC:
+ case ABVS:
+ 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 || p1->to.reg != p->from.reg)
+ continue;
+ switch(p1->as) {
+ case ASUB:
+ case AADD:
+ case AXOR:
+ case AOR:
+ /* irregular instructions */
+ if(p1->from.type == D_CONST)
+ continue;
+ break;
+ }
+ switch(p1->as) {
+ default:
+ continue;
+ case AMOVW:
+ case AMOVD:
+ if(p1->from.type != D_REG)
+ continue;
+ continue;
+ case AANDCC:
+ case AANDNCC:
+ case AORCC:
+ case AORNCC:
+ case AXORCC:
+ case ASUBCC:
+ case ASUBECC:
+ case ASUBMECC:
+ case ASUBZECC:
+ case AADDCC:
+ case AADDCCC:
+ case AADDECC:
+ case AADDMECC:
+ case AADDZECC:
+ case ARLWMICC:
+ case ARLWNMCC:
+ t = p1->as;
+ break;
+ /* don't deal with floating point instructions for now */
+/*
+ case AFABS: t = AFABSCC; break;
+ case AFADD: t = AFADDCC; break;
+ case AFADDS: t = AFADDSCC; break;
+ case AFCTIW: t = AFCTIWCC; break;
+ case AFCTIWZ: t = AFCTIWZCC; break;
+ case AFDIV: t = AFDIVCC; break;
+ case AFDIVS: t = AFDIVSCC; break;
+ case AFMADD: t = AFMADDCC; break;
+ case AFMADDS: t = AFMADDSCC; break;
+ case AFMOVD: t = AFMOVDCC; break;
+ case AFMSUB: t = AFMSUBCC; break;
+ case AFMSUBS: t = AFMSUBSCC; break;
+ case AFMUL: t = AFMULCC; break;
+ case AFMULS: t = AFMULSCC; break;
+ case AFNABS: t = AFNABSCC; break;
+ case AFNEG: t = AFNEGCC; break;
+ case AFNMADD: t = AFNMADDCC; break;
+ case AFNMADDS: t = AFNMADDSCC; break;
+ case AFNMSUB: t = AFNMSUBCC; break;
+ case AFNMSUBS: t = AFNMSUBSCC; break;
+ case AFRSP: t = AFRSPCC; break;
+ case AFSUB: t = AFSUBCC; break;
+ case AFSUBS: t = AFSUBSCC; break;
+ case ACNTLZW: t = ACNTLZWCC; break;
+ case AMTFSB0: t = AMTFSB0CC; break;
+ case AMTFSB1: t = AMTFSB1CC; break;
+*/
+ case AADD: t = AADDCC; break;
+ case AADDV: t = AADDVCC; break;
+ case AADDC: t = AADDCCC; break;
+ case AADDCV: t = AADDCVCC; break;
+ case AADDME: t = AADDMECC; break;
+ case AADDMEV: t = AADDMEVCC; break;
+ case AADDE: t = AADDECC; break;
+ case AADDEV: t = AADDEVCC; break;
+ case AADDZE: t = AADDZECC; break;
+ case AADDZEV: t = AADDZEVCC; break;
+ case AAND: t = AANDCC; break;
+ case AANDN: t = AANDNCC; break;
+ case ADIVW: t = ADIVWCC; break;
+ case ADIVWV: t = ADIVWVCC; break;
+ case ADIVWU: t = ADIVWUCC; break;
+ case ADIVWUV: t = ADIVWUVCC; break;
+ case ADIVD: t = ADIVDCC; break;
+ case ADIVDV: t = ADIVDVCC; break;
+ case ADIVDU: t = ADIVDUCC; break;
+ case ADIVDUV: t = ADIVDUVCC; break;
+ case AEQV: t = AEQVCC; break;
+ case AEXTSB: t = AEXTSBCC; break;
+ case AEXTSH: t = AEXTSHCC; break;
+ case AEXTSW: t = AEXTSWCC; break;
+ case AMULHW: t = AMULHWCC; break;
+ case AMULHWU: t = AMULHWUCC; break;
+ case AMULLW: t = AMULLWCC; break;
+ case AMULLWV: t = AMULLWVCC; break;
+ case AMULHD: t = AMULHDCC; break;
+ case AMULHDU: t = AMULHDUCC; break;
+ case AMULLD: t = AMULLDCC; break;
+ case AMULLDV: t = AMULLDVCC; break;
+ case ANAND: t = ANANDCC; break;
+ case ANEG: t = ANEGCC; break;
+ case ANEGV: t = ANEGVCC; break;
+ case ANOR: t = ANORCC; break;
+ case AOR: t = AORCC; break;
+ case AORN: t = AORNCC; break;
+ case AREM: t = AREMCC; break;
+ case AREMV: t = AREMVCC; break;
+ case AREMU: t = AREMUCC; break;
+ case AREMUV: t = AREMUVCC; break;
+ case AREMD: t = AREMDCC; break;
+ case AREMDV: t = AREMDVCC; break;
+ case AREMDU: t = AREMDUCC; break;
+ case AREMDUV: t = AREMDUVCC; break;
+ case ARLWMI: t = ARLWMICC; break;
+ case ARLWNM: t = ARLWNMCC; break;
+ case ASLW: t = ASLWCC; break;
+ case ASRAW: t = ASRAWCC; break;
+ case ASRW: t = ASRWCC; break;
+ case ASLD: t = ASLDCC; break;
+ case ASRAD: t = ASRADCC; break;
+ case ASRD: t = ASRDCC; break;
+ case ASUB: t = ASUBCC; break;
+ case ASUBV: t = ASUBVCC; break;
+ case ASUBC: t = ASUBCCC; break;
+ case ASUBCV: t = ASUBCVCC; break;
+ case ASUBME: t = ASUBMECC; break;
+ case ASUBMEV: t = ASUBMEVCC; break;
+ case ASUBE: t = ASUBECC; break;
+ case ASUBEV: t = ASUBEVCC; break;
+ case ASUBZE: t = ASUBZECC; break;
+ case ASUBZEV: t = ASUBZEVCC; break;
+ case AXOR: t = AXORCC; break;
+ break;
+ }
+ if(debug['D'])
+ print("cmp %P; %P -> ", p1, p);
+ p1->as = t;
+ if(debug['D'])
+ print("%P\n", p1);
+ excise(r);
+ continue;
+ }
+ }
+}
+
+void
+excise(Reg *r)
+{
+ Prog *p;
+
+ p = r->prog;
+ p->as = ANOP;
+ p->from = zprog.from;
+ p->from3 = zprog.from3;
+ 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;
+}
+
+/*
+ * if the system forces R0 to be zero,
+ * convert references to $0 to references to R0.
+ */
+int
+regzer(Addr *a)
+{
+ if(R0ISZERO) {
+ if(a->type == D_CONST)
+ if(a->sym == nil)
+ if(a->offset == 0)
+ return 1;
+ if(a->type == D_REG)
+ if(a->reg == REGZERO)
+ return 1;
+ }
+ return 0;
+}
+
+int
+regtyp(Addr *a)
+{
+
+ if(a->type == D_REG) {
+ if(!R0ISZERO || a->reg != REGZERO)
+ return 1;
+ return 0;
+ }
+ 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 AADD:
+ case AADDC:
+ case AADDCC:
+ case AADDE:
+ case AADDECC:
+ case ASUB:
+ case ASUBCC:
+ case ASUBC:
+ case ASUBCCC:
+ case ASUBE:
+ case ASUBECC:
+ case ASLW:
+ case ASRW:
+ case ASRWCC:
+ case ASRAW:
+ case ASRAWCC:
+ case ASLD:
+ case ASRD:
+ case ASRAD:
+ case AOR:
+ case AORCC:
+ case AORN:
+ case AORNCC:
+ case AAND:
+ case AANDCC:
+ case AANDN:
+ case AANDNCC:
+ case ANAND:
+ case ANANDCC:
+ case ANOR:
+ case ANORCC:
+ case AXOR:
+ case AXORCC:
+ case AMULHW:
+ case AMULHWU:
+ case AMULLW:
+ case AMULLD:
+ case ADIVW:
+ case ADIVWU:
+ case ADIVD:
+ case ADIVDU:
+ case AREM:
+ case AREMU:
+ case AREMD:
+ case AREMDU:
+ case ARLWNM:
+ case ARLWNMCC:
+
+ case AFADD:
+ case AFADDS:
+ case AFSUB:
+ case AFSUBS:
+ case AFMUL:
+ case AFMULS:
+ case AFDIV:
+ case AFDIVS:
+ 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 AADDME:
+ case AADDMECC:
+ case AADDZE:
+ case AADDZECC:
+ case ASUBME:
+ case ASUBMECC:
+ case ASUBZE:
+ case ASUBZECC:
+ case ANEG:
+ case ANEGCC:
+ case AFNEG:
+ case AFNEGCC:
+ case AFMOVS:
+ case AFMOVD:
+ case AMOVW:
+ case AMOVD:
+ if(p->to.type == v1->type)
+ if(p->to.reg == v1->reg)
+ goto gotit;
+ 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, nil);
+ switch(t) {
+ case 2: /* rar, cant 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, nil);
+ 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;
+}
+
+/*
+ * 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 ANOP: /* read, write */
+ case AMOVH:
+ case AMOVHZ:
+ case AMOVB:
+ case AMOVBZ:
+ case AMOVW:
+ case AMOVWZ:
+ case AMOVD:
+
+ case ANEG:
+ case ANEGCC:
+ case AADDME:
+ case AADDMECC:
+ case AADDZE:
+ case AADDZECC:
+ case ASUBME:
+ case ASUBMECC:
+ case ASUBZE:
+ case ASUBZECC:
+
+ case AFCTIW:
+ case AFCTIWZ:
+ case AFMOVS:
+ case AFMOVD:
+ case AFRSP:
+ case AFNEG:
+ case AFNEGCC:
+ if(s != nil) {
+ 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 ARLWMI: /* read read rar */
+ case ARLWMICC:
+ if(copyas(&p->to, v))
+ return 2;
+ /* fall through */
+
+ case AADD: /* read read write */
+ case AADDC:
+ case AADDE:
+ case ASUB:
+ case ASLW:
+ case ASRW:
+ case ASRAW:
+ case ASLD:
+ case ASRD:
+ case ASRAD:
+ case AOR:
+ case AORCC:
+ case AORN:
+ case AORNCC:
+ case AAND:
+ case AANDCC:
+ case AANDN:
+ case AANDNCC:
+ case ANAND:
+ case ANANDCC:
+ case ANOR:
+ case ANORCC:
+ case AXOR:
+ case AMULHW:
+ case AMULHWU:
+ case AMULLW:
+ case AMULLD:
+ case ADIVW:
+ case ADIVD:
+ case ADIVWU:
+ case ADIVDU:
+ case AREM:
+ case AREMU:
+ case AREMD:
+ case AREMDU:
+ case ARLWNM:
+ case ARLWNMCC:
+
+ case AFADDS:
+ case AFADD:
+ case AFSUBS:
+ case AFSUB:
+ case AFMULS:
+ case AFMUL:
+ case AFDIVS:
+ case AFDIV:
+ if(s != nil) {
+ 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:
+ case ABGT:
+ case ABGE:
+ case ABLT:
+ case ABLE:
+ case ABNE:
+ case ABVC:
+ case ABVS:
+ break;
+
+ case ACMP: /* read read */
+ case ACMPU:
+ case ACMPW:
+ case ACMPWU:
+ case AFCMPO:
+ case AFCMPU:
+ if(s != nil) {
+ 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 ABR: /* funny */
+ if(s != nil) {
+ if(copysub(&p->to, v, s, 1))
+ return 1;
+ return 0;
+ }
+ if(copyau(&p->to, v))
+ return 1;
+ return 0;
+
+ case ARETURN: /* 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 != nil) {
+ 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;
+ }
+ return 0;
+}
+
+int
+a2type(Prog *p)
+{
+
+ switch(p->as) {
+ case AADD:
+ case AADDC:
+ case AADDCC:
+ case AADDCCC:
+ case AADDE:
+ case AADDECC:
+ case AADDME:
+ case AADDMECC:
+ case AADDZE:
+ case AADDZECC:
+ case ASUB:
+ case ASUBC:
+ case ASUBCC:
+ case ASUBCCC:
+ case ASUBE:
+ case ASUBECC:
+ case ASUBME:
+ case ASUBMECC:
+ case ASUBZE:
+ case ASUBZECC:
+ case ASLW:
+ case ASLWCC:
+ case ASRW:
+ case ASRWCC:
+ case ASRAW:
+ case ASRAWCC:
+ case ASLD:
+ case ASLDCC:
+ case ASRD:
+ case ASRDCC:
+ case ASRAD:
+ case ASRADCC:
+ case AOR:
+ case AORCC:
+ case AORN:
+ case AORNCC:
+ case AAND:
+ case AANDCC:
+ case AANDN:
+ case AANDNCC:
+ case AXOR:
+ case AXORCC:
+ case ANEG:
+ case ANEGCC:
+ case AMULHW:
+ case AMULHWU:
+ case AMULLW:
+ case AMULLWCC:
+ case ADIVW:
+ case ADIVWCC:
+ case ADIVWU:
+ case ADIVWUCC:
+ case AREM:
+ case AREMCC:
+ case AREMU:
+ case AREMUCC:
+ case AMULLD:
+ case AMULLDCC:
+ case ADIVD:
+ case ADIVDCC:
+ case ADIVDU:
+ case ADIVDUCC:
+ case AREMD:
+ case AREMDCC:
+ case AREMDU:
+ case AREMDUCC:
+ case ANAND:
+ case ANANDCC:
+ case ANOR:
+ case ANORCC:
+ case ARLWMI:
+ case ARLWMICC:
+ case ARLWNM:
+ case ARLWNMCC:
+ return D_REG;
+
+ case AFADDS:
+ case AFADDSCC:
+ case AFADD:
+ case AFADDCC:
+ case AFSUBS:
+ case AFSUBSCC:
+ case AFSUB:
+ case AFSUBCC:
+ case AFMULS:
+ case AFMULSCC:
+ case AFMUL:
+ case AFMULCC:
+ case AFDIVS:
+ case AFDIVSCC:
+ case AFDIV:
+ case AFDIVCC:
+ case AFNEG:
+ case AFNEGCC:
+ 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;
+ 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;
+ return 0;
+}
+
+int
+copyau1(Prog *p, Addr *v)
+{
+
+ if(regtyp(v))
+ if(p->from.type == v->type || p->to.type == 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))
+ 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;
+}
diff --git a/src/cmd/9c/reg.c b/src/cmd/9c/reg.c
new file mode 100644
index 000000000..81a7c7fe4
--- /dev/null
+++ b/src/cmd/9c/reg.c
@@ -0,0 +1,1163 @@
+// cmd/9c/reg.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 "gc.h"
+
+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)
+{
+ const Rgn *p1, *p2;
+ int c1, c2;
+
+ p1 = a1;
+ p2 = 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 ARETURN:
+ case ABR:
+ case ARFI:
+ case ARFCI:
+ case ARFID:
+ r->p1 = R;
+ r1->s1 = R;
+ }
+
+ /*
+ * left side always read
+ */
+ bit = mkvar(&p->from, p->as==AMOVW || p->as == AMOVWZ || p->as == AMOVD);
+ 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 AMOVBU:
+ case AMOVBZ:
+ case AMOVBZU:
+ case AMOVH:
+ case AMOVHBR:
+ case AMOVWBR:
+ case AMOVHU:
+ case AMOVHZ:
+ case AMOVHZU:
+ case AMOVW:
+ case AMOVWU:
+ case AMOVWZ:
+ case AMOVWZU:
+ case AMOVD:
+ case AMOVDU:
+ case AFMOVD:
+ case AFMOVDCC:
+ case AFMOVDU:
+ case AFMOVS:
+ case AFMOVSU:
+ case AFRSP:
+ for(z=0; z<BITS; z++)
+ r->set.b[z] |= bit.b[z];
+ break;
+
+ /*
+ * funny
+ */
+ case ABL:
+ for(z=0; z<BITS; z++)
+ addrs.b[z] |= bit.b[z];
+ 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.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("%ld:%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 == ARETURN)
+ 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\n set = %B; rah = %B; cal = %B\n",
+ r->prog, r->set, r->refahead, r->calahead);
+ 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 an 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']) {
+ 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;
+ }
+}
+
+/*
+ * 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 = AMOVB;
+ if(v->etype == TSHORT || v->etype == TUSHORT)
+ p1->as = AMOVH;
+ if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
+ p1->as = AMOVD;
+ if(v->etype == TFLOAT)
+ p1->as = AFMOVS;
+ if(v->etype == TDOUBLE)
+ p1->as = AFMOVD;
+
+ 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 = AMOVBZ;
+ if(v->etype == TUSHORT)
+ p1->as = AMOVHZ;
+ if(v->etype == TUINT || v->etype == TULONG)
+ p1->as = AMOVWZ;
+ }
+ 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;
+ int64 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] || typev[et])) /* funny punning */
+ for(z=0; z<BITS; z++)
+ addrs.b[z] |= bit.b[z];
+ if(t == D_CONST) {
+ if((int32)o != o)
+ v->etype = TVLONG;
+ 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 ARETURN:
+ 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 TVLONG:
+ case TUVLONG:
+ 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+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("%ld%P\tld %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->to.type == D_FREG && (p->as == AMOVW || p->as == AMOVD))
+ change = -CINF; /* cant go Rreg to Freg */
+ if(debug['R'] && debug['v'])
+ print("%ld%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->from.type == D_FREG && (p->as == AMOVW || p->as == AMOVD))
+ change = -CINF; /* cant go Rreg to Freg */
+ if(debug['R'] && debug['v'])
+ print("%ld%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("%ld%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;
+ }
+}
+
+/*
+ * track register variables including external registers:
+ * bit reg
+ * 0 R7
+ * 1 R8
+ * ... ...
+ * 21 R28
+ */
+int32
+RtoB(int r)
+{
+
+ if(r >= REGMIN && r <= REGMAX)
+ return 1L << (r-REGMIN);
+ return 0;
+}
+
+int
+BtoR(int32 b)
+{
+ b &= 0x001fffffL;
+ if(b == 0)
+ return 0;
+ return bitno(b) + REGMIN;
+}
+
+/*
+ * bit reg
+ * 22 F17
+ * 23 F18
+ * ... ...
+ * 31 F26
+ */
+int32
+FtoB(int f)
+{
+ if(f < FREGMIN || f > FREGEXT)
+ return 0;
+ return 1L << (f - FREGMIN + 22);
+}
+
+int
+BtoF(int32 b)
+{
+
+ b &= 0xffc00000L;
+ if(b == 0)
+ return 0;
+ return bitno(b) - 22 + FREGMIN;
+}
diff --git a/src/cmd/9c/sgen.c b/src/cmd/9c/sgen.c
new file mode 100644
index 000000000..b03c17267
--- /dev/null
+++ b/src/cmd/9c/sgen.c
@@ -0,0 +1,291 @@
+// cmd/9c/sgen.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 "gc.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 = 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 v;
+
+ 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 OASMUL:
+ case OASLMUL:
+ xcom(l);
+ xcom(r);
+ v = vlog(r);
+ if(v >= 0) {
+ n->op = OASASHL;
+ r->vconst = v;
+ r->type = types[TINT];
+ }
+ break;
+
+ case OMUL:
+ case OLMUL:
+ xcom(l);
+ xcom(r);
+ v = vlog(r);
+ if(v >= 0) {
+ n->op = OASHL;
+ r->vconst = v;
+ r->type = types[TINT];
+ }
+ v = vlog(l);
+ if(v >= 0) {
+ n->op = OASHL;
+ n->left = r;
+ n->right = l;
+ r = l;
+ l = n->left;
+ r->vconst = v;
+ r->type = types[TINT];
+ simplifyshift(n);
+ }
+ break;
+
+ case OASLDIV:
+ xcom(l);
+ xcom(r);
+ v = vlog(r);
+ if(v >= 0) {
+ n->op = OASLSHR;
+ r->vconst = v;
+ r->type = types[TINT];
+ }
+ break;
+
+ case OLDIV:
+ xcom(l);
+ xcom(r);
+ v = vlog(r);
+ if(v >= 0) {
+ n->op = OLSHR;
+ r->vconst = v;
+ r->type = types[TINT];
+ simplifyshift(n);
+ }
+ break;
+
+ case OASLMOD:
+ xcom(l);
+ xcom(r);
+ v = vlog(r);
+ if(v >= 0) {
+ n->op = OASAND;
+ r->vconst--;
+ }
+ break;
+
+ case OLMOD:
+ xcom(l);
+ xcom(r);
+ v = vlog(r);
+ if(v >= 0) {
+ n->op = OAND;
+ r->vconst--;
+ }
+ break;
+
+ case OLSHR:
+ case OASHL:
+ case OASHR:
+ xcom(l);
+ xcom(r);
+ simplifyshift(n);
+ 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 OEQ:
+ case ONE:
+ case OLE:
+ case OLT:
+ case OGE:
+ case OGT:
+ case OHI:
+ case OHS:
+ case OLO:
+ case OLS:
+ /*
+ * immediate operators, make const on right
+ */
+ if(l->op == OCONST) {
+ n->left = r;
+ n->right = l;
+ n->op = invrel[relindex(n->op)];
+ }
+ 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;
+ }
+}
+
diff --git a/src/cmd/9c/swt.c b/src/cmd/9c/swt.c
new file mode 100644
index 000000000..a63db60b2
--- /dev/null
+++ b/src/cmd/9c/swt.c
@@ -0,0 +1,407 @@
+// cmd/9c/swt.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 "gc.h"
+
+void
+swit1(C1 *q, int nc, int32 def, Node *n)
+{
+ Node tn, nod;
+
+ regalloc(&nod, n, Z);
+ /* always signed */
+ if(typev[n->type->etype])
+ nod.type = types[TVLONG];
+ else
+ nod.type = types[TLONG];
+ cgen(n, &nod);
+ regalloc(&tn, &regnode, Z);
+ swit2(q, nc, def, &nod, &tn);
+ regfree(&tn);
+ regfree(&nod);
+}
+
+void
+swit2(C1 *q, int nc, int32 def, Node *n, Node *tn)
+{
+ C1 *r;
+ int i;
+ Prog *sp;
+
+ if(nc < 5) {
+ for(i=0; i<nc; i++) {
+ if(sval(q->val)) {
+ gopcode(OEQ, n, Z, nodconst(q->val));
+ } else {
+ gopcode(OSUB, nodconst(q->val), n, tn);
+ gopcode(OEQ, tn, Z, nodconst(0));
+ }
+ patch(p, q->label);
+ q++;
+ }
+ gbranch(OGOTO);
+ patch(p, def);
+ return;
+ }
+ i = nc / 2;
+ r = q+i;
+ if(sval(r->val)) {
+ gopcode(OGT, n, Z, nodconst(r->val));
+ sp = p;
+ } else {
+ gopcode(OSUB, nodconst(r->val), n, tn);
+ gopcode(OGT, tn, Z, nodconst(0));
+ sp = p;
+ }
+ gbranch(OGOTO);
+ p->as = ABEQ;
+ patch(p, r->label);
+ swit2(q, i, def, n, tn);
+
+ patch(sp, pc);
+ swit2(r+1, nc-i-1, def, n, tn);
+}
+
+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;
+ 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(n, v);
+ if(!m) {
+ if(debug['M'])
+ print("%L multiply table: %lld\n", n->lineno, r->vconst);
+ return 0;
+ }
+
+ 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);
+ if(v < 0)
+ gopcode(ONEG, &nod1, Z, &nod1);
+ regalloc(&nod2, n, Z);
+
+loop:
+ switch(*p) {
+ case 0:
+ regfree(&nod2);
+ 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)
+{
+ 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 = nil;
+}
+
+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 allign 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 */
+ w = ewidth[t->etype];
+ if(w <= 0 || w >= SZ_VLONG) {
+ w = SZ_VLONG;
+ break;
+ }
+ w = 1;
+ break;
+
+ case Aarg2: /* width of a parameter */
+ o += t->width;
+ 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;
+ if(debug['A'])
+ print("align %s %ld %T = %ld\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/9c/txt.c b/src/cmd/9c/txt.c
new file mode 100644
index 000000000..e46aba84e
--- /dev/null
+++ b/src/cmd/9c/txt.c
@@ -0,0 +1,1537 @@
+// cmd/9c/txt.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 "gc.h"
+
+static int resvreg[nelem(reg)];
+
+#define isv(et) ((et) == TVLONG || (et) == TUVLONG || (et) == TIND)
+
+int thechar = '9';
+char *thestring = "power64";
+
+LinkArch *thelinkarch;
+
+void
+linkarchinit(void)
+{
+ thestring = getgoarch();
+ if(strcmp(thestring, "power64le") == 0)
+ thelinkarch = &linkpower64le;
+ else
+ thelinkarch = &linkpower64;
+}
+
+
+void
+ginit(void)
+{
+ Type *t;
+
+ dodefine("_64BITREG");
+ dodefine("_64BIT");
+ exregoffset = REGEXT;
+ exfregoffset = FREGEXT;
+ listinit();
+ nstring = 0;
+ mnstring = 0;
+ nrathole = 0;
+ pc = 0;
+ breakpc = -1;
+ continpc = -1;
+ cases = C;
+ lastp = P;
+ tfield = types[TLONG];
+
+ typeword = typechlvp;
+ typecmplx = typesu;
+ /* TO DO */
+ memmove(typechlpv, typechlp, sizeof(typechlpv));
+ typechlpv[TVLONG] = 1;
+ typechlpv[TUVLONG] = 1;
+
+ zprog.link = P;
+ zprog.as = AGOK;
+ zprog.reg = NREG;
+ zprog.from.type = D_NONE;
+ zprog.from.name = D_NONE;
+ zprog.from.reg = NREG;
+ zprog.from3 = zprog.from;
+ zprog.to = zprog.from;
+
+ regnode.op = OREGISTER;
+ regnode.class = CEXREG;
+ regnode.reg = 0;
+ regnode.complex = 0;
+ regnode.addable = 11;
+ regnode.type = types[TLONG];
+
+ qregnode = regnode;
+ 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);
+
+ com64init();
+
+ memset(reg, 0, sizeof(reg));
+ reg[REGZERO] = 1; /* don't use */
+ reg[REGTMP] = 1;
+ reg[FREGCVI+NREG] = 1;
+ reg[FREGZERO+NREG] = 1;
+ reg[FREGHALF+NREG] = 1;
+ reg[FREGONE+NREG] = 1;
+ reg[FREGTWO+NREG] = 1;
+ memmove(resvreg, reg, sizeof(reg));
+}
+
+void
+gclean(void)
+{
+ int i;
+ Sym *s;
+
+ for(i=0; i<NREG; i++)
+ if(reg[i] && !resvreg[i])
+ diag(Z, "reg %d left allocated", i);
+ for(i=NREG; i<NREG+NREG; i++)
+ if(reg[i] && !resvreg[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;
+ p->pc = pc;
+ pc++;
+ if(lastp == P) {
+ 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(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);
+ gopcode(OAS, n, Z, tn2);
+ 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*
+nod32const(vlong v)
+{
+ constnode.vconst = v & MASK(32);
+ return &constnode;
+}
+
+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;
+}
+
+void
+nodreg(Node *n, Node *nn, int reg)
+{
+ *n = qregnode;
+ 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+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, j;
+ static int lasti;
+
+ 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 > 0 && i < NREG)
+ goto out;
+ }
+ j = lasti + REGRET+1;
+ for(i=REGRET+1; i<NREG; i++) {
+ if(j >= NREG)
+ j = REGRET+1;
+ if(reg[j] == 0) {
+ i = j;
+ goto out;
+ }
+ j++;
+ }
+ diag(tn, "out of fixed registers");
+ goto err;
+
+ case TFLOAT:
+ case TDOUBLE:
+ if(o != Z && o->op == OREGISTER) {
+ i = o->reg;
+ if(i >= NREG && i < NREG+NREG)
+ goto out;
+ }
+ j = lasti + NREG;
+ for(i=NREG; i<NREG+NREG; i++) {
+ if(j >= NREG+NREG)
+ j = NREG;
+ if(reg[j] == 0) {
+ i = j;
+ goto out;
+ }
+ j++;
+ }
+ diag(tn, "out of float registers");
+ goto err;
+ }
+ diag(tn, "unknown type in regalloc: %T", tn->type);
+err:
+ i = 0;
+out:
+ if(i)
+ reg[i]++;
+ lasti++;
+ if(lasti >= 5)
+ lasti = 0;
+ 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 >= sizeof(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)
+ 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_VLONG;
+ 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 = REGZERO;
+ }
+ 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:
+ prtree(n, "naddr");
+ diag(n, "%L: !bad in naddr: %O", n->lineno, 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
+gmove(Node *f, Node *t)
+{
+ int ft, tt, a;
+ Node nod, fxc0, fxc1, fxc2, fxrat;
+ Prog *p1;
+ double d;
+
+ ft = f->type->etype;
+ tt = t->type->etype;
+
+ if(ft == TDOUBLE && f->op == OCONST) {
+ d = f->fconst;
+ if(d == 0.0) {
+ a = FREGZERO;
+ goto ffreg;
+ }
+ if(d == 0.5) {
+ a = FREGHALF;
+ goto ffreg;
+ }
+ if(d == 1.0) {
+ a = FREGONE;
+ goto ffreg;
+ }
+ if(d == 2.0) {
+ a = FREGTWO;
+ goto ffreg;
+ }
+ if(d == -.5) {
+ fop(OSUB, FREGHALF, FREGZERO, t);
+ return;
+ }
+ if(d == -1.0) {
+ fop(OSUB, FREGONE, FREGZERO, t);
+ return;
+ }
+ if(d == -2.0) {
+ fop(OSUB, FREGTWO, FREGZERO, t);
+ return;
+ }
+ if(d == 1.5) {
+ fop(OADD, FREGONE, FREGHALF, t);
+ return;
+ }
+ if(d == 2.5) {
+ fop(OADD, FREGTWO, FREGHALF, t);
+ return;
+ }
+ if(d == 3.0) {
+ fop(OADD, FREGTWO, FREGONE, t);
+ return;
+ }
+ }
+ if(ft == TFLOAT && f->op == OCONST) {
+ d = f->fconst;
+ if(d == 0) {
+ a = FREGZERO;
+ ffreg:
+ nodreg(&nod, f, NREG+a);
+ gmove(&nod, t);
+ return;
+ }
+ }
+ /*
+ * 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:
+ if(ewidth[ft] == 4){
+ if(typeu[ft])
+ a = AMOVWZ;
+ else
+ a = AMOVW;
+ }else
+ a = AMOVD;
+ break;
+ case TINT:
+ a = AMOVW;
+ break;
+ case TUINT:
+ a = AMOVWZ;
+ break;
+ case TFLOAT:
+ a = AFMOVS;
+ break;
+ case TDOUBLE:
+ a = AFMOVD;
+ break;
+ case TCHAR:
+ a = AMOVB;
+ break;
+ case TUCHAR:
+ a = AMOVBZ;
+ break;
+ case TSHORT:
+ a = AMOVH;
+ break;
+ case TUSHORT:
+ a = AMOVHZ;
+ break;
+ }
+ 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:
+ if(ewidth[tt] == 4)
+ a = AMOVW;
+ else
+ a = AMOVD;
+ break;
+ case TINT:
+ a = AMOVW;
+ break;
+ case TUINT:
+ a = AMOVWZ;
+ break;
+ case TUCHAR:
+ a = AMOVBZ;
+ break;
+ case TCHAR:
+ a = AMOVB;
+ break;
+ case TUSHORT:
+ a = AMOVHZ;
+ break;
+ case TSHORT:
+ a = AMOVH;
+ break;
+ case TFLOAT:
+ a = AFMOVS;
+ break;
+ case TDOUBLE:
+ a = AFMOVD;
+ break;
+ }
+ if(!typefd[ft] && vconst(f) == 0) {
+ gins(a, f, t);
+ return;
+ }
+ 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 TFLOAT:
+ switch(tt) {
+ case TDOUBLE:
+ a = AFMOVD;
+ if(ft == TFLOAT)
+ a = AFMOVS; /* AFMOVSD */
+ break;
+ case TFLOAT:
+ a = AFRSP;
+ if(ft == TFLOAT)
+ a = AFMOVS;
+ break;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TIND:
+ case TSHORT:
+ case TUSHORT:
+ case TCHAR:
+ case TUCHAR:
+ /* BUG: not right for unsigned int32 */
+ regalloc(&nod, f, Z); /* should be type float */
+ regsalloc(&fxrat, f);
+ gins(AFCTIWZ, f, &nod);
+ gins(AFMOVD, &nod, &fxrat);
+ regfree(&nod);
+ fxrat.type = nodrat->type;
+ fxrat.etype = nodrat->etype;
+ fxrat.xoffset += 4;
+ gins(AMOVW, &fxrat, t); /* TO DO */
+ gmove(t, t);
+ return;
+ case TVLONG:
+ case TUVLONG:
+ /* BUG: not right for unsigned int32 */
+ regalloc(&nod, f, Z); /* should be type float */
+ regsalloc(&fxrat, f);
+ gins(AFCTIDZ, f, &nod);
+ gins(AFMOVD, &nod, &fxrat);
+ regfree(&nod);
+ fxrat.type = nodrat->type;
+ fxrat.etype = nodrat->etype;
+ gins(AMOVD, &fxrat, t);
+ gmove(t, t);
+ return;
+ }
+ break;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ switch(tt) {
+ case TDOUBLE:
+ case TFLOAT:
+ goto fxtofl;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TSHORT:
+ case TUSHORT:
+ case TCHAR:
+ case TUCHAR:
+ if(typeu[tt])
+ a = AMOVWZ;
+ else
+ a = AMOVW;
+ break;
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ a = AMOVD;
+ break;
+ }
+ break;
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ switch(tt) {
+ case TDOUBLE:
+ case TFLOAT:
+ goto fxtofl;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ case TSHORT:
+ case TUSHORT:
+ case TCHAR:
+ case TUCHAR:
+ a = AMOVD; /* TO DO: conversion done? */
+ break;
+ }
+ break;
+ case TSHORT:
+ switch(tt) {
+ case TDOUBLE:
+ case TFLOAT:
+ goto fxtofl;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ a = AMOVH;
+ break;
+ case TSHORT:
+ case TUSHORT:
+ case TCHAR:
+ case TUCHAR:
+ a = AMOVD;
+ break;
+ }
+ break;
+ case TUSHORT:
+ switch(tt) {
+ case TDOUBLE:
+ case TFLOAT:
+ goto fxtofl;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ a = AMOVHZ;
+ break;
+ case TSHORT:
+ case TUSHORT:
+ case TCHAR:
+ case TUCHAR:
+ a = AMOVD;
+ break;
+ }
+ break;
+ case TCHAR:
+ switch(tt) {
+ case TDOUBLE:
+ case TFLOAT:
+ goto fxtofl;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ case TSHORT:
+ case TUSHORT:
+ a = AMOVB;
+ break;
+ case TCHAR:
+ case TUCHAR:
+ a = AMOVD;
+ break;
+ }
+ break;
+ case TUCHAR:
+ switch(tt) {
+ case TDOUBLE:
+ case TFLOAT:
+ fxtofl:
+ /*
+ * rat[0] = 0x43300000; rat[1] = f^0x80000000;
+ * t = *(double*)rat - FREGCVI;
+ * is-unsigned(t) => if(t<0) t += 2^32;
+ * could be streamlined for int-to-float
+ */
+ regalloc(&fxc0, f, Z);
+ regalloc(&fxc2, f, Z);
+ regsalloc(&fxrat, t); /* should be type float */
+ gins(AMOVW, nodconst(0x43300000L), &fxc0);
+ gins(AMOVW, f, &fxc2);
+ gins(AXOR, nodconst(0x80000000L), &fxc2);
+ if(ctxt->arch->endian == BigEndian) {
+ gins(AMOVW, &fxc0, &fxrat);
+ fxc1 = fxrat;
+ fxc1.type = nodrat->type;
+ fxc1.etype = nodrat->etype;
+ fxc1.xoffset += SZ_LONG;
+ gins(AMOVW, &fxc2, &fxc1);
+ } else {
+ gins(AMOVW, &fxc2, &fxrat);
+ fxc1 = fxrat;
+ fxc1.type = nodrat->type;
+ fxc1.etype = nodrat->etype;
+ fxc1.xoffset += SZ_LONG;
+ gins(AMOVW, &fxc0, &fxc1);
+ }
+ regfree(&fxc2);
+ regfree(&fxc0);
+ regalloc(&nod, t, t); /* should be type float */
+ gins(AFMOVD, &fxrat, &nod);
+ nodreg(&fxc1, t, NREG+FREGCVI);
+ gins(AFSUB, &fxc1, &nod);
+ a = AFMOVD;
+ if(tt == TFLOAT)
+ a = AFRSP;
+ gins(a, &nod, t);
+ regfree(&nod);
+ if(ft == TULONG) {
+ regalloc(&nod, t, Z);
+ if(tt == TFLOAT) {
+ gins(AFCMPU, t, Z);
+ p->to.type = D_FREG;
+ p->to.reg = FREGZERO;
+ gins(ABGE, Z, Z);
+ p1 = p;
+ gins(AFMOVS, nodfconst(4294967296.), &nod);
+ gins(AFADDS, &nod, t);
+ } else {
+ gins(AFCMPU, t, Z);
+ p->to.type = D_FREG;
+ p->to.reg = FREGZERO;
+ gins(ABGE, Z, Z);
+ p1 = p;
+ gins(AFMOVD, nodfconst(4294967296.), &nod);
+ gins(AFADD, &nod, t);
+ }
+ patch(p1, pc);
+ regfree(&nod);
+ }
+ return;
+ case TINT:
+ case TUINT:
+ case TLONG:
+ case TULONG:
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ case TSHORT:
+ case TUSHORT:
+ a = AMOVBZ;
+ break;
+ case TCHAR:
+ case TUCHAR:
+ a = AMOVD;
+ break;
+ }
+ break;
+ }
+ if(a == AGOK)
+ diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
+ if(a == AMOVD || (a == AMOVW || a == AMOVWZ) && ewidth[ft] == ewidth[tt] || a == AFMOVS || a == AFMOVD)
+ if(samaddr(f, t))
+ return;
+ 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;
+ int uns;
+
+ uns = 0;
+ et = TLONG;
+ if(f1 != Z && f1->type != T) {
+ if(f1->op == OCONST && t != Z && t->type != T)
+ et = t->type->etype;
+ else
+ et = f1->type->etype;
+ }
+ a = AGOK;
+ switch(o) {
+ case OAS:
+ gmove(f1, t);
+ return;
+
+ case OASADD:
+ case OADD:
+ a = AADD;
+ if(et == TFLOAT)
+ a = AFADDS;
+ else
+ if(et == TDOUBLE)
+ a = AFADD;
+ break;
+
+ case OASSUB:
+ case OSUB:
+ a = ASUB;
+ if(et == TFLOAT)
+ a = AFSUBS;
+ else
+ if(et == TDOUBLE)
+ a = AFSUB;
+ break;
+
+ case OASOR:
+ case OOR:
+ a = AOR;
+ break;
+
+ case OASAND:
+ case OAND:
+ a = AAND;
+ if(f1->op == OCONST)
+ a = AANDCC;
+ break;
+
+ case OASXOR:
+ case OXOR:
+ a = AXOR;
+ break;
+
+ case OASLSHR:
+ case OLSHR:
+ a = ASRW;
+ if(isv(et))
+ a = ASRD;
+ break;
+
+ case OASASHR:
+ case OASHR:
+ a = ASRAW;
+ if(isv(et))
+ a = ASRAD;
+ break;
+
+ case OASASHL:
+ case OASHL:
+ a = ASLW;
+ if(isv(et))
+ a = ASLD;
+ break;
+
+ case OFUNC:
+ a = ABL;
+ break;
+
+ case OASLMUL:
+ case OLMUL:
+ case OASMUL:
+ case OMUL:
+ if(et == TFLOAT) {
+ a = AFMULS;
+ break;
+ } else
+ if(et == TDOUBLE) {
+ a = AFMUL;
+ break;
+ }
+ a = AMULLW;
+ if(isv(et))
+ a = AMULLD;
+ break;
+
+ case OASDIV:
+ case ODIV:
+ if(et == TFLOAT) {
+ a = AFDIVS;
+ break;
+ } else
+ if(et == TDOUBLE) {
+ a = AFDIV;
+ break;
+ } else
+ a = ADIVW;
+ if(isv(et))
+ a = ADIVD;
+ break;
+
+ case OASMOD:
+ case OMOD:
+ a = AREM;
+ if(isv(et))
+ a = AREMD;
+ break;
+
+ case OASLMOD:
+ case OLMOD:
+ a = AREMU;
+ if(isv(et))
+ a = AREMDU;
+ break;
+
+ case OASLDIV:
+ case OLDIV:
+ a = ADIVWU;
+ if(isv(et))
+ a = ADIVDU;
+ break;
+
+ case OCOM:
+ a = ANOR;
+ break;
+
+ case ONEG:
+ a = ANEG;
+ if(et == TFLOAT || et == TDOUBLE)
+ a = AFNEG;
+ break;
+
+ case OEQ:
+ a = ABEQ;
+ goto cmp;
+
+ case ONE:
+ a = ABNE;
+ goto cmp;
+
+ case OLT:
+ a = ABLT;
+ goto cmp;
+
+ case OLE:
+ a = ABLE;
+ goto cmp;
+
+ case OGE:
+ a = ABGE;
+ goto cmp;
+
+ case OGT:
+ a = ABGT;
+ goto cmp;
+
+ case OLO:
+ a = ABLT;
+ goto cmpu;
+
+ case OLS:
+ a = ABLE;
+ goto cmpu;
+
+ case OHS:
+ a = ABGE;
+ goto cmpu;
+
+ case OHI:
+ a = ABGT;
+ goto cmpu;
+
+ cmpu:
+ uns = 1;
+ cmp:
+ nextpc();
+ switch(et){
+ case TINT:
+ case TLONG:
+ p->as = ACMPW;
+ break;
+ case TUINT:
+ case TULONG:
+ p->as = ACMPWU;
+ break;
+ case TFLOAT:
+ case TDOUBLE:
+ p->as = AFCMPU;
+ break;
+ default:
+ p->as = uns? ACMPU: ACMP;
+ break;
+ }
+ if(f1 != Z)
+ naddr(f1, &p->from);
+ if(t != Z)
+ naddr(t, &p->to);
+ if(f1 == Z || t == Z || f2 != Z)
+ diag(Z, "bad cmp in gopcode %O", o);
+ if(debug['g'])
+ print("%P\n", p);
+ f1 = Z;
+ f2 = Z;
+ t = 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(ta.type == D_CONST && ta.offset == 0) {
+ if(R0ISZERO)
+ p->reg = REGZERO;
+ else
+ diag(Z, "REGZERO in gopcode %O", o);
+ }
+ }
+ if(t != Z)
+ naddr(t, &p->to);
+ if(debug['g'])
+ print("%P\n", p);
+}
+
+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 = ARETURN;
+ break;
+ case OGOTO:
+ a = ABR;
+ 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);
+
+ switch(a) {
+ case ATEXT:
+ p->reg = textflag;
+ textflag = 0;
+ break;
+ case AGLOBL:
+ p->reg = s->dataflag;
+ break;
+ }
+
+ p->from.name = D_EXTERN;
+ if(s->class == CSTATIC)
+ p->from.name = D_STATIC;
+ naddr(n, &p->to);
+ if(a == ADATA || a == AGLOBL)
+ pc--;
+}
+
+int
+sval(int32 v)
+{
+
+ if(v >= -(1<<15) && v < (1<<15))
+ return 1;
+ return 0;
+}
+
+void
+gpcdata(int index, int value)
+{
+ Node n1;
+
+ n1 = *nodconst(index);
+ gins(APCDATA, &n1, nodconst(value));
+}
+
+void
+gprefetch(Node *n)
+{
+ // TODO(minux)
+ USED(n);
+ /*
+ Node n1;
+
+ regalloc(&n1, n, Z);
+ gmove(n, &n1);
+ n1.op = OINDREG;
+ gins(ADCBT, &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)1)<<15) && vv < (((vlong)1)<<15))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+uconst(Node *n)
+{
+ vlong vv;
+
+ if(n->op == OCONST) {
+ if(!typefd[n->type->etype]) {
+ vv = n->vconst;
+ if(vv >= 0 && vv < (((vlong)1)<<16))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+immconst(Node *n)
+{
+ vlong v;
+
+ if(n->op != OCONST || typefd[n->type->etype])
+ return 0;
+ v = n->vconst;
+ if((v & 0xFFFF) == 0)
+ v >>= 16;
+ if(v >= 0 && v < ((vlong)1<<16))
+ return 1;
+ if(v >= -((vlong)1<<15) && v <= ((vlong)1<<15))
+ return 1;
+ return 0;
+}
+
+int32
+exreg(Type *t)
+{
+ int32 o;
+
+ if(typechlpv[t->etype]) {
+ if(exregoffset <= 3)
+ return 0;
+ o = exregoffset;
+ exregoffset--;
+ return o;
+ }
+ if(typefd[t->etype]) {
+ if(exfregoffset <= 16)
+ 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, /* [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] */
+};
diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c
new file mode 100644
index 000000000..e38936001
--- /dev/null
+++ b/src/cmd/9g/cgen.c
@@ -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
index 000000000..200be2eda
--- /dev/null
+++ b/src/cmd/9g/doc.go
@@ -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
index 000000000..97a5a5d06
--- /dev/null
+++ b/src/cmd/9g/galign.c
@@ -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
index 000000000..703fbd0a8
--- /dev/null
+++ b/src/cmd/9g/gg.h
@@ -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
index 000000000..c41d8eb41
--- /dev/null
+++ b/src/cmd/9g/ggen.c
@@ -0,0 +1,1034 @@
+// 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;
+ 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);
+ } 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);
+ } else
+ for(t = 0; t < q; t++) {
+ p = gins(AMOVD, &r0, &dst);
+ p->to.type = D_OREG;
+ p->to.offset = 8*t;
+ }
+
+ for(t = 0; t < c; t++) {
+ p = gins(AMOVB, &r0, &dst);
+ p->to.type = D_OREG;
+ p->to.offset = t;
+ }
+ 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
index 000000000..fdd7606bc
--- /dev/null
+++ b/src/cmd/9g/gobj.c
@@ -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 = TINT32;
+}
+
+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
index 000000000..d8b62b1da
--- /dev/null
+++ b/src/cmd/9g/gsubr.c
@@ -0,0 +1,1705 @@
+// 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;
+
+ 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);
+
+ // TODO(minux): enable these.
+ // right now it fails on MOVD $type."".TypeAssertionError(SB) [width=1], R7 [width=8]
+ /*
+ 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:
+ w = 8;
+ break;
+ }
+ if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) {
+ dump("f", f);
+ dump("t", t);
+ fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
+ }
+ */
+
+ return p;
+}
+
+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->width = 0;
+ a->reg = NREG;
+ if(n->type != T) {
+ a->etype = simtype[n->type->etype];
+ a->width = n->type->width;
+ }
+ 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; // len(nil)
+ break;
+
+ case OSPTR:
+ // pointer in a string or slice
+ naddr(n->left, a, canemitcode);
+ if(a->type == D_CONST && a->offset == 0)
+ break; // ptr(nil)
+ a->etype = simtype[tptr];
+ 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;
+ 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;
+ 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);
+ }
+ }
+}
+
+/*
+ * 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
index 000000000..d3cbcb957
--- /dev/null
+++ b/src/cmd/9g/opt.h
@@ -0,0 +1,219 @@
+// 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; // variables written by this instruction.
+ Bits use1; // variables read by prog->from.
+ Bits use2; // variables read by prog->to.
+
+ Bits refbehind;
+ Bits refahead;
+ Bits calbehind;
+ Bits calahead;
+ Bits regdiff;
+ Bits act;
+
+ int32 regu; // register used bitmap
+};
+#define R ((Reg*)0)
+/*c2go extern Reg *R; */
+
+#define NRGN 600
+/*c2go enum { NRGN = 600 }; */
+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;
+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 nreload;
+ int32 ndelmov;
+ int32 nvar;
+ int32 naddr;
+} 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);
+uint32 allreg(uint32, Rgn*);
+void paint1(Reg*, int);
+uint32 paint2(Reg*, int);
+void paint3(Reg*, int, int32, 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; // required registers used by this instruction
+ uint64 regset; // required registers 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: address taken, read, write.
+ LeftAddr = 1<<9,
+ LeftRead = 1<<10,
+ LeftWrite = 1<<11,
+
+ // Register in middle; never written.
+ RegRead = 1<<12,
+ CanRegRead = 1<<13,
+
+ // Right side: address taken, read, write.
+ RightAddr = 1<<14,
+ RightRead = 1<<15,
+ RightWrite = 1<<16,
+
+ 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,
+};
diff --git a/src/cmd/9g/peep.c b/src/cmd/9g/peep.c
new file mode 100644
index 000000000..5721d7b04
--- /dev/null
+++ b/src/cmd/9g/peep.c
@@ -0,0 +1,94 @@
+// 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)
+// 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"
+
+void
+peep(Prog *p)
+{
+ USED(p);
+ // TODO(minux)
+ return;
+}
+
+void
+excise(Flow *r)
+{
+ Prog *p;
+
+ p = r->prog;
+ if(debug['P'] && debug['v'])
+ print("%P ===delete===\n", p);
+ *p = zprog;
+ p->as = ANOP;
+ ostats.ndelmov++;
+}
+
+int
+regtyp(Adr *a)
+{
+ switch(a->type) {
+ default:
+ return 0;
+ case D_REG:
+ case D_FREG:
+ return 1;
+ }
+}
+
+int
+sameaddr(Addr *a, Addr *v)
+{
+ 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
+smallindir(Addr *a, Addr *reg)
+{
+ return reg->type == D_REG && a->type == D_OREG &&
+ a->reg == reg->reg &&
+ 0 <= a->offset && a->offset < 4096;
+}
+
+int
+stackaddr(Addr *a)
+{
+ 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
index 000000000..0a51a533a
--- /dev/null
+++ b/src/cmd/9g/prog.c
@@ -0,0 +1,138 @@
+// Copyright 2014 The Go 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},
+ // In addtion, duffzero reads R0,R2 and writes R2. This fact must be
+ // encoded in peep.c (TODO)
+ [ADUFFZERO]= {Call},
+ // In addtion, duffcopy reads R0,R2,R3 and writes R2,R3. This fact must be
+ // encoded in peep.c (TODO)
+ [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.reg != NREG) {
+ info->reguse |= RtoB(p->from.reg);
+ if(info->flags & PostInc) {
+ info->regset |= RtoB(p->from.reg);
+ }
+ }
+ if(p->to.type == D_OREG && p->to.reg != NREG) {
+ info->reguse |= 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;
+ }
+}
diff --git a/src/cmd/9g/reg.c b/src/cmd/9g/reg.c
new file mode 100644
index 000000000..bbebf3fe0
--- /dev/null
+++ b/src/cmd/9g/reg.c
@@ -0,0 +1,161 @@
+// 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"
+
+void
+regopt(Prog *p)
+{
+ USED(p);
+ // TODO(minux)
+ return;
+}
+
+/*
+ * 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 &= 0xffffffff;
+ 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");
+ }
+// r1 = r->s1;
+// if(r1 != R) {
+// print(" succ:");
+// for(; r1 != R; r1 = r1->s1)
+// print(" %.4ud", (int)r1->prog->pc);
+// print("\n");
+// }
+ }
+}
diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h
new file mode 100644
index 000000000..e494e90ca
--- /dev/null
+++ b/src/cmd/9l/9.out.h
@@ -0,0 +1,514 @@
+// 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 as
+{
+ 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.
+
+/* reg names for 9g OREGISTER */
+ D_R0 = 0, // type is D_REG
+ D_F0 = D_R0+NREG, // type is D_FREG
+
+/* reg names 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"
diff --git a/src/cmd/9l/Makefile b/src/cmd/9l/Makefile
new file mode 100644
index 000000000..3f528d751
--- /dev/null
+++ b/src/cmd/9l/Makefile
@@ -0,0 +1,5 @@
+# Copyright 2012 The Go 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/9l/asm.c b/src/cmd/9l/asm.c
new file mode 100644
index 000000000..b8ca777c3
--- /dev/null
+++ b/src/cmd/9l/asm.c
@@ -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;
+}
diff --git a/src/cmd/9l/doc.go b/src/cmd/9l/doc.go
new file mode 100644
index 000000000..9df5dc614
--- /dev/null
+++ b/src/cmd/9l/doc.go
@@ -0,0 +1,16 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+
+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
index 000000000..dda741c56
--- /dev/null
+++ b/src/cmd/9l/l.h
@@ -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
+};
diff --git a/src/cmd/9l/list.c b/src/cmd/9l/list.c
new file mode 100644
index 000000000..af8dc1588
--- /dev/null
+++ b/src/cmd/9l/list.c
@@ -0,0 +1,40 @@
+// 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)
+// 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.
+
+// Printing.
+
+#include "l.h"
+#include "../ld/lib.h"
+
+void
+listinit(void)
+{
+ listinit9();
+}
diff --git a/src/cmd/9l/obj.c b/src/cmd/9l/obj.c
new file mode 100644
index 000000000..badb72a1a
--- /dev/null
+++ b/src/cmd/9l/obj.c
@@ -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/api/goapi.go b/src/cmd/api/goapi.go
index 5a8c87603..e49ba33bb 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -405,6 +405,7 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
" note struct{};" +
" p struct{};" +
" parfor struct{};" +
+ " slice struct{};" +
" slicetype struct{};" +
" stkframe struct{};" +
" sudog struct{};" +
diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody
index e24db1bc0..f586aaa20 100644
--- a/src/cmd/cc/lexbody
+++ b/src/cmd/cc/lexbody
@@ -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/pgen.c b/src/cmd/cc/pgen.c
index db9aae916..54cf0c5e1 100644
--- a/src/cmd/cc/pgen.c
+++ b/src/cmd/cc/pgen.c
@@ -65,14 +65,14 @@ argsize(int doret)
}
//print(" %d %T\n", s, t);
}
- if(thechar == '6')
+ if(thechar == '6' || thechar == '9')
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')
+ if(thechar == '6' || thechar == '9')
s = (s+7) & ~7;
else
s = (s+3) & ~3;
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 17b0cdd16..0dc22dcd4 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -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
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index d638ae4eb..9c81dd8b2 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -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,6 +524,7 @@ static struct {
"anames5.c",
"anames6.c",
"anames8.c",
+ "anames9.c",
}},
{"cmd/cc", {
"-pgen.c",
@@ -549,6 +553,11 @@ static struct {
"../cc/pswt.c",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
}},
+ {"cmd/9c", {
+ "../cc/pgen.c",
+ "../cc/pswt.c",
+ "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
+ }},
{"cmd/5g", {
"../gc/cplx.c",
"../gc/pgen.c",
@@ -573,6 +582,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 +599,9 @@ static struct {
{"cmd/8l", {
"../ld/*",
}},
+ {"cmd/9l", {
+ "../ld/*",
+ }},
{"cmd/go", {
"zdefaultcc.go",
}},
@@ -618,6 +638,7 @@ static struct {
{"anames5.c", mkanames},
{"anames6.c", mkanames},
{"anames8.c", mkanames},
+ {"anames9.c", mkanames},
{"zasm_", mkzasm},
{"zdefaultcc.go", mkzdefaultcc},
{"zsys_", mkzsys},
@@ -1156,12 +1177,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"))
@@ -1358,6 +1393,10 @@ static char *cleantab[] = {
"cmd/8c",
"cmd/8g",
"cmd/8l",
+ "cmd/9a",
+ "cmd/9c",
+ "cmd/9g",
+ "cmd/9l",
"cmd/cc",
"cmd/gc",
"cmd/go",
diff --git a/src/cmd/dist/buildgc.c b/src/cmd/dist/buildgc.c
index 66adf6857..1c3329758 100644
--- a/src/cmd/dist/buildgc.c
+++ b/src/cmd/dist/buildgc.c
@@ -63,7 +63,7 @@ gcopnames(char *dir, char *file)
vfree(&fields);
}
-// mkanames reads [568].out.h and writes anames[568].c
+// 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.
void
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index bb774e05f..d22e09955 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -148,6 +148,13 @@ static struct {
{"arm", "",
"#define LR R14\n"
},
+
+ {"power64", "",
+ "#define g R30\n"
+ },
+ {"power64le", "",
+ "#define g R30\n"
+ },
};
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index 4a78684b4..893ed5cdd 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -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);
}
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index fbca4ee5f..aeeadedca 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -24,6 +24,8 @@ char *runtimeimport =
"func @\"\".printslice (? any)\n"
"func @\"\".printnl ()\n"
"func @\"\".printsp ()\n"
+ "func @\"\".printlock ()\n"
+ "func @\"\".printunlock ()\n"
"func @\"\".concatstring2 (? string, ? string) (? string)\n"
"func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
"func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
@@ -86,10 +88,33 @@ char *runtimeimport =
"func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n"
"func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n"
"func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n"
- "func @\"\".writebarrierfat2 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
- "func @\"\".writebarrierfat3 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
- "func @\"\".writebarrierfat4 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat01 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat10 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat11 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat0111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1000 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
+ "func @\"\".writebarrierfat1111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
"func @\"\".writebarrierfat (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n"
+ "func @\"\".writebarriercopy (@\"\".typ·2 *byte, @\"\".dst·3 any, @\"\".src·4 any) (? int)\n"
"func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n"
"func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n"
"func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n"
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 965a0550d..cc590416b 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -1464,6 +1464,7 @@ void walk(Node *fn);
void walkexpr(Node **np, NodeList **init);
void walkexprlist(NodeList *l, NodeList **init);
void walkexprlistsafe(NodeList *l, NodeList **init);
+void walkexprlistcheap(NodeList *l, NodeList **init);
void walkstmt(Node **np);
void walkstmtlist(NodeList *l);
Node* conv(Node*, Type*);
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index 39028e3f8..259cec85a 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -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);
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
index 0feb2c710..3bfa69b1f 100644
--- a/src/cmd/gc/plive.c
+++ b/src/cmd/gc/plive.c
@@ -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++)
diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c
index 993bb2482..6e6db88ef 100644
--- a/src/cmd/gc/popt.c
+++ b/src/cmd/gc/popt.c
@@ -847,6 +847,10 @@ nilopt(Prog *firstp)
Graph *g;
int ncheck, nkill;
+ // TODO(minux): nilopt on power64 throw away seemly random segment of code.
+ if(thechar == '9')
+ return;
+
g = flowstart(firstp, sizeof(NilFlow));
if(g == nil)
return;
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b2ff2fbc5..0f8802abc 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1525,11 +1525,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:
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 0fb15c265..c6007714c 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -36,6 +36,8 @@ func printeface(any)
func printslice(any)
func printnl()
func printsp()
+func printlock()
+func printunlock()
func concatstring2(string, string) string
func concatstring3(string, string, string) string
@@ -115,10 +117,35 @@ func writebarrieriface(dst *any, src any)
// The unused *byte argument makes sure that src is 2-pointer-aligned,
// which is the maximum alignment on NaCl amd64p32
// (and possibly on 32-bit systems if we start 64-bit aligning uint64s).
-func writebarrierfat2(dst *any, _ *byte, src any)
-func writebarrierfat3(dst *any, _ *byte, src any)
-func writebarrierfat4(dst *any, _ *byte, src any)
+// The bitmap in the name tells which words being copied are pointers.
+func writebarrierfat01(dst *any, _ *byte, src any)
+func writebarrierfat10(dst *any, _ *byte, src any)
+func writebarrierfat11(dst *any, _ *byte, src any)
+func writebarrierfat001(dst *any, _ *byte, src any)
+func writebarrierfat010(dst *any, _ *byte, src any)
+func writebarrierfat011(dst *any, _ *byte, src any)
+func writebarrierfat100(dst *any, _ *byte, src any)
+func writebarrierfat101(dst *any, _ *byte, src any)
+func writebarrierfat110(dst *any, _ *byte, src any)
+func writebarrierfat111(dst *any, _ *byte, src any)
+func writebarrierfat0001(dst *any, _ *byte, src any)
+func writebarrierfat0010(dst *any, _ *byte, src any)
+func writebarrierfat0011(dst *any, _ *byte, src any)
+func writebarrierfat0100(dst *any, _ *byte, src any)
+func writebarrierfat0101(dst *any, _ *byte, src any)
+func writebarrierfat0110(dst *any, _ *byte, src any)
+func writebarrierfat0111(dst *any, _ *byte, src any)
+func writebarrierfat1000(dst *any, _ *byte, src any)
+func writebarrierfat1001(dst *any, _ *byte, src any)
+func writebarrierfat1010(dst *any, _ *byte, src any)
+func writebarrierfat1011(dst *any, _ *byte, src any)
+func writebarrierfat1100(dst *any, _ *byte, src any)
+func writebarrierfat1101(dst *any, _ *byte, src any)
+func writebarrierfat1110(dst *any, _ *byte, src any)
+func writebarrierfat1111(dst *any, _ *byte, src any)
+
func writebarrierfat(typ *byte, dst *any, src *any)
+func writebarriercopy(typ *byte, dst any, src any) int
func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 714c66268..f05d8022d 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -2891,7 +2891,8 @@ typecheckas(Node *n)
case OSLICE3:
case OSLICESTR:
// For x = x[0:y], x can be updated in place, without touching pointer.
- if(samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left)))
+ // TODO(rsc): Reenable once it is actually updated in place without touching the pointer.
+ if(0 && samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left)))
n->right->reslice = 1;
break;
@@ -2899,7 +2900,8 @@ typecheckas(Node *n)
// For x = append(x, ...), x can be updated in place when there is capacity,
// without touching the pointer; otherwise the emitted code to growslice
// can take care of updating the pointer, and only in that case.
- if(n->right->list != nil && samesafeexpr(n->left, n->right->list->n))
+ // TODO(rsc): Reenable once the emitted code does update the pointer.
+ if(0 && n->right->list != nil && samesafeexpr(n->left, n->right->list->n))
n->right->reslice = 1;
break;
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index ff9b36208..37bd62dea 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -6,6 +6,7 @@
#include <libc.h>
#include "go.h"
#include "../ld/textflag.h"
+#include "../../runtime/mgc0.h"
static Node* walkprint(Node*, NodeList**);
static Node* writebarrierfn(char*, Type*, Type*);
@@ -363,6 +364,15 @@ walkexprlistsafe(NodeList *l, NodeList **init)
}
void
+walkexprlistcheap(NodeList *l, NodeList **init)
+{
+ for(; l; l=l->next) {
+ l->n = cheapexpr(l->n, init);
+ walkexpr(&l->n, init);
+ }
+}
+
+void
walkexpr(Node **np, NodeList **init)
{
Node *r, *l, *var, *a;
@@ -1772,6 +1782,11 @@ walkprint(Node *nn, NodeList **init)
calls = nil;
notfirst = 0;
+ // Hoist all the argument evaluation up before the lock.
+ walkexprlistcheap(all, init);
+
+ calls = list(calls, mkcall("printlock", T, init));
+
for(l=all; l; l=l->next) {
if(notfirst) {
calls = list(calls, mkcall("printsp", T, init));
@@ -1852,6 +1867,9 @@ walkprint(Node *nn, NodeList **init)
if(op == OPRINTN)
calls = list(calls, mkcall("printnl", T, nil));
+
+ calls = list(calls, mkcall("printunlock", T, init));
+
typechecklist(calls, Etop);
walkexprlist(calls, init);
@@ -1988,6 +2006,9 @@ applywritebarrier(Node *n, NodeList **init)
{
Node *l, *r;
Type *t;
+ vlong x;
+ static Bvec *bv;
+ char name[32];
if(n->left && n->right && needwritebarrier(n->left, n->right)) {
t = n->left->type;
@@ -2005,14 +2026,35 @@ applywritebarrier(Node *n, NodeList **init)
} else if(isinter(t)) {
n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init,
l, n->right);
- } else if(t->width == 2*widthptr) {
- n = mkcall1(writebarrierfn("writebarrierfat2", t, n->right->type), T, init,
- l, nodnil(), n->right);
- } else if(t->width == 3*widthptr) {
- n = mkcall1(writebarrierfn("writebarrierfat3", t, n->right->type), T, init,
- l, nodnil(), n->right);
- } else if(t->width == 4*widthptr) {
- n = mkcall1(writebarrierfn("writebarrierfat4", t, n->right->type), T, init,
+ } else if(t->width <= 4*widthptr) {
+ x = 0;
+ if(bv == nil)
+ bv = bvalloc(BitsPerPointer*4);
+ bvresetall(bv);
+ twobitwalktype1(t, &x, bv);
+ // The bvgets are looking for BitsPointer in successive slots.
+ enum {
+ PtrBit = 1,
+ };
+ if(BitsPointer != (1<<PtrBit))
+ fatal("wrong PtrBit");
+ switch(t->width/widthptr) {
+ default:
+ fatal("found writebarrierfat for %d-byte object of type %T", (int)t->width, t);
+ case 2:
+ snprint(name, sizeof name, "writebarrierfat%d%d",
+ bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit));
+ break;
+ case 3:
+ snprint(name, sizeof name, "writebarrierfat%d%d%d",
+ bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit));
+ break;
+ case 4:
+ snprint(name, sizeof name, "writebarrierfat%d%d%d%d",
+ bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit), bvget(bv, 3*BitsPerPointer+PtrBit));
+ break;
+ }
+ n = mkcall1(writebarrierfn(name, t, n->right->type), T, init,
l, nodnil(), n->right);
} else {
r = n->right;
@@ -2874,6 +2916,11 @@ copyany(Node *n, NodeList **init, int runtimecall)
{
Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn;
NodeList *l;
+
+ if(haspointers(n->left->type->type)) {
+ fn = writebarrierfn("writebarriercopy", n->left->type, n->right->type);
+ return mkcall1(fn, n->type, init, typename(n->left->type->type), n->left, n->right);
+ }
if(runtimecall) {
if(n->right->type->etype == TSTRING)
@@ -3301,6 +3348,9 @@ walkrotate(Node **np)
int w, sl, sr, s;
Node *l, *r;
Node *n;
+
+ if(thechar == '9')
+ return;
n = *np;
@@ -3426,6 +3476,10 @@ walkdiv(Node **np, NodeList **init)
Type *twide;
Magic m;
+ // TODO(minux)
+ if(thechar == '9')
+ return;
+
n = *np;
if(n->right->op != OLITERAL)
return;
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 61847546a..92c6fb57c 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -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++)
diff --git a/src/cmd/ld/doc.go b/src/cmd/ld/doc.go
index 5b5833db5..ad35df740 100644
--- a/src/cmd/ld/doc.go
+++ b/src/cmd/ld/doc.go
@@ -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:
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index a3ba52325..fbb5699bd 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -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;
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 3196961f3..6ac6b6ee8 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -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)
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index b5d081949..ec8e7c4ea 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -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.
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index f889aba8a..64608d226 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -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);
}
}
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index fe7e10e46..ffb20b3a5 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -44,6 +44,7 @@ machoinit(void)
switch(thechar) {
// 64-bit architectures
case '6':
+ case '9':
macho64 = 1;
break;
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 156270c8f..c3a72c3cf 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -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);
diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go
index cde296c79..46e9d5735 100644
--- a/src/debug/elf/elf.go
+++ b/src/debug/elf/elf.go
@@ -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
diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go
index de8a3a24f..74d1db306 100644
--- a/src/debug/elf/file.go
+++ b/src/debug/elf/file.go
@@ -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
diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go
index 5e5ba52f3..d57aaab0e 100644
--- a/src/debug/elf/file_test.go
+++ b/src/debug/elf/file_test.go
@@ -267,6 +267,12 @@ var relocationTests = []relocationTest{
},
},
{
+ "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{
{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)"}, {Attr: dwarf.AttrLanguage, Val: int64(12)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c"}, {Attr: dwarf.AttrStmtList, Val: int64(0)}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}}}},
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj b/src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
new file mode 100644
index 000000000..dad744548
--- /dev/null
+++ b/src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
Binary files differ
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 7a51cf3c0..ed79df293 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -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)
}
diff --git a/src/go/build/syslist.go b/src/go/build/syslist.go
index 965f873df..2ab53bb9c 100644
--- a/src/go/build/syslist.go
+++ b/src/go/build/syslist.go
@@ -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 "
diff --git a/src/hash/crc32/crc32_generic.go b/src/hash/crc32/crc32_generic.go
index c3fdcd685..1c7f806c6 100644
--- a/src/hash/crc32/crc32_generic.go
+++ b/src/hash/crc32/crc32_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build 386 arm
+// +build 386 arm power64 power64le
package crc32
diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c
new file mode 100644
index 000000000..c5a78e53c
--- /dev/null
+++ b/src/liblink/asm9.c
@@ -0,0 +1,2784 @@
+// 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);
+
+ bflag = 0;
+ 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;
+}
+
diff --git a/src/liblink/list9.c b/src/liblink/list9.c
new file mode 100644
index 000000000..041c6884f
--- /dev/null
+++ b/src/liblink/list9.c
@@ -0,0 +1,409 @@
+// 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(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 & 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+%.5lux(BRANCH)", a->sym->name, v);
+ else
+ sprint(str, "%.5lux(BRANCH)", v);
+ } 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, a->offset);
+ 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
index 000000000..0bae64d0b
--- /dev/null
+++ b/src/liblink/obj9.c
@@ -0,0 +1,1086 @@
+// 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 autoffset, 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);
+ autoffset = textstksiz;
+ if(autoffset < 0)
+ autoffset = 0;
+
+ 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,
+};
diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c
index b2478ec17..6d8694953 100644
--- a/src/liblink/objfile.c
+++ b/src/liblink/objfile.c
@@ -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);
}
}
@@ -777,7 +782,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
index 000000000..a9083df9b
--- /dev/null
+++ b/src/liblink/sched9.c
@@ -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
index 000000000..3ba8201b3
--- /dev/null
+++ b/src/math/abs_power64x.s
@@ -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
index 000000000..c33a9209f
--- /dev/null
+++ b/src/math/big/arith_power64x.s
@@ -0,0 +1,46 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 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
index 000000000..36b762554
--- /dev/null
+++ b/src/math/stubs_power64x.s
@@ -0,0 +1,91 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 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)
diff --git a/src/os/signal/sig.s b/src/os/signal/sig.s
index d54c284b5..1826c37fb 100644
--- a/src/os/signal/sig.s
+++ b/src/os/signal/sig.s
@@ -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)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 268a9e319..c62f227f4 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -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
index 000000000..e430cdf04
--- /dev/null
+++ b/src/reflect/asm_power64x.s
@@ -0,0 +1,29 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "textflag.h"
+
+// makeFuncStub is the code half of the function returned by MakeFunc.
+// See the comment on the declaration of makeFuncStub in makefunc.go
+// for more details.
+// No argsize here, gc generates argsize info at call site.
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+ 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 argsize here, gc generates argsize info at call site.
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+ MOVD R11, 8(R1)
+ MOVD $argframe+0(FP), R3
+ MOVD R3, 16(R1)
+ BL ·callMethod(SB)
+ RETURN
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 572e611fa..2064922f6 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -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++ {
diff --git a/src/run.bash b/src/run.bash
index 3c9430c87..91f12a174 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -66,7 +66,8 @@ go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
# Race detector only supported on Linux, FreeBSD and OS X,
# and only on amd64, and only when cgo is enabled.
-case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
+# DISABLED until we get garbage collection working.
+case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED-XXX-DISABLED" in
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
echo
echo '# Testing race detector.'
diff --git a/src/runtime/arch_power64.go b/src/runtime/arch_power64.go
new file mode 100644
index 000000000..270cd7b95
--- /dev/null
+++ b/src/runtime/arch_power64.go
@@ -0,0 +1,8 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type uintreg uint64
+type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/arch_power64.h b/src/runtime/arch_power64.h
new file mode 100644
index 000000000..7cfb9da2f
--- /dev/null
+++ b/src/runtime/arch_power64.h
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+enum {
+ thechar = '9',
+ BigEndian = 1,
+ CacheLineSize = 64,
+ RuntimeGogoBytes = 64,
+ PhysPageSize = 65536,
+ PCQuantum = 4,
+ Int64Align = 8
+};
+
diff --git a/src/runtime/arch_power64le.go b/src/runtime/arch_power64le.go
new file mode 100644
index 000000000..270cd7b95
--- /dev/null
+++ b/src/runtime/arch_power64le.go
@@ -0,0 +1,8 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type uintreg uint64
+type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/arch_power64le.h b/src/runtime/arch_power64le.h
new file mode 100644
index 000000000..684ac9953
--- /dev/null
+++ b/src/runtime/arch_power64le.h
@@ -0,0 +1,14 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+enum {
+ thechar = '9',
+ BigEndian = 0,
+ CacheLineSize = 64,
+ RuntimeGogoBytes = 64,
+ PhysPageSize = 65536,
+ PCQuantum = 4,
+ Int64Align = 8
+};
+
diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s
index b4b81d739..501e64b09 100644
--- a/src/runtime/asm_386.s
+++ b/src/runtime/asm_386.s
@@ -486,11 +486,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 +502,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 +537,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 +555,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)
@@ -1356,29 +1356,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 +1387,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 +1416,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 +1455,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
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 39d7c78f2..1aa2d71a8 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -461,11 +461,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 +489,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 +541,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 +559,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)
@@ -890,24 +890,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 +1050,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 +1184,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 +1216,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 +1241,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 +1313,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 +1371,7 @@ failure:
RET
// handle for lengths < 16
-indexbyte_small:
+small:
MOVQ BX, CX
REPN; SCASB
JZ success
diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index a1116b5d4..153564b14 100644
--- a/src/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -444,11 +444,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 +460,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 +512,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 +530,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 +834,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 +868,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 +895,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 +969,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 +1027,7 @@ failure:
RET
// handle for lengths < 16
-indexbyte_small:
+small:
MOVL BX, CX
REPN; SCASB
JZ success
diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s
index 0f3b5eeb8..58aebf388 100644
--- a/src/runtime/asm_arm.s
+++ b/src/runtime/asm_arm.s
@@ -492,7 +492,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 +501,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
@@ -751,13 +751,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 +780,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 +801,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
diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s
new file mode 100644
index 000000000..fd0c6be16
--- /dev/null
+++ b/src/runtime/asm_power64x.s
@@ -0,0 +1,981 @@
+// Copyright 2014 The Go 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 "zasm_GOOS_GOARCH.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 gobuf+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 gobuf+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)
+
+// switchtoM is a dummy routine that onM leaves at the bottom
+// of the G stack. We need to distinguish the routine that
+// lives at the bottom of the G stack from the one that lives
+// at the top of the M stack because the one at the top of
+// the M stack terminates the stack walk (see topofstack()).
+TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
+ UNDEF
+ BL (LR) // make sure this function is not leaf
+ RETURN
+
+// func onM_signalok(fn func())
+TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8
+ MOVD g, R3 // R3 = g
+ MOVD g_m(R3), R4 // R4 = g->m
+ MOVD m_gsignal(R4), R4 // R4 = g->m->gsignal
+ MOVD fn+0(FP), R11 // context for call below
+ CMP R3, R4
+ BEQ onsignal
+ MOVD R11, 8(R1)
+ BL runtime·onM(SB)
+ RETURN
+
+onsignal:
+ MOVD 0(R11), R3 // code pointer
+ MOVD R3, CTR
+ BL (CTR)
+ RETURN
+
+// void onM(fn func())
+TEXT runtime·onM(SB), NOSPLIT, $0-8
+ MOVD fn+0(FP), R3 // R3 = fn
+ MOVD R3, R11 // context
+ MOVD g_m(g), R4 // R4 = m
+
+ MOVD m_g0(R4), R5 // R5 = g0
+ CMP g, R5
+ BEQ onm
+
+ MOVD m_curg(R4), R6
+ CMP g, R6
+ BEQ oncurg
+
+ // Not g0, not curg. Must be gsignal, but that's not allowed.
+ // Hide call from linker nosplit analysis.
+ MOVD $runtime·badonm(SB), R3
+ MOVD R3, CTR
+ BL (CTR)
+
+oncurg:
+ // save our state in g->sched. Pretend to
+ // be switchtoM if the G stack is scanned.
+ MOVD $runtime·switchtoM(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 onM 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
+
+onm:
+ // 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
+ MOVW argsize+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 argptr+8(FP), R3; \
+ MOVW argsize+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 argptr+8(FP), R3; \
+ MOVW argsize+16(FP), R4; \
+ MOVW 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(int32 *val, int32 old, int32 new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime·cas(SB), NOSPLIT, $0-17
+ MOVD p+0(FP), R3
+ MOVW old+8(FP), R4
+ MOVW 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 *val, uint64 old, uint64 new)
+// Atomically:
+// if(*val == *old){
+// *val = new;
+// return 1;
+// } else {
+// return 0;
+// }
+TEXT runtime·cas64(SB), NOSPLIT, $0-25
+ MOVD p+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 *val, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime·xadd(SB), NOSPLIT, $0-20
+ MOVD p+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 p+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 p+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 p+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 sp+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 count+16(FP), R5
+ SUB $1, R3
+ SUB $1, R4
+ ADD R3, R5, R8
+loop:
+ CMP R3, R8
+ BNE 4(PC)
+ MOVD $1, R3
+ MOVB R3, ret+24(FP)
+ RETURN
+ 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
+// R3 is updated as a side effect.
+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
+ CMP 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)
diff --git a/src/runtime/atomic.go b/src/runtime/atomic.go
index 7e9d9b3aa..a0e4d84e9 100644
--- a/src/runtime/atomic.go
+++ b/src/runtime/atomic.go
@@ -20,8 +20,16 @@ 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
+// Cannot use noescape here: ptr does not but new does escape.
+// Instead use noescape(ptr) in wrapper below.
+func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
+
+//go:nosplit
+func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
+ old := xchgp1(noescape(ptr), new)
+ writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
+ return old
+}
//go:noescape
func xchguintptr(ptr *uintptr, new uintptr) uintptr
@@ -47,5 +55,27 @@ func atomicstore(ptr *uint32, val uint32)
//go:noescape
func atomicstore64(ptr *uint64, val uint64)
-//go:noescape
-func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer)
+// Cannot use noescape here: ptr does not but val does escape.
+// Instead use noescape(ptr) in wrapper below.
+func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
+
+//go:nosplit
+func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer) {
+ atomicstorep1(noescape(ptr), val)
+ // TODO(rsc): Why does the compiler think writebarrierptr_nostore's dst argument escapes?
+ writebarrierptr_nostore((*uintptr)(noescape(ptr)), uintptr(val))
+}
+
+// Cannot use noescape here: ptr does not but new does escape.
+// Instead use noescape(ptr) in wrapper below.
+func casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
+
+//go:nosplit
+func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
+ ok := casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), old, new)
+ if !ok {
+ return false
+ }
+ writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
+ return true
+}
diff --git a/src/runtime/atomic_power64x.s b/src/runtime/atomic_power64x.s
new file mode 100644
index 000000000..e72871761
--- /dev/null
+++ b/src/runtime/atomic_power64x.s
@@ -0,0 +1,40 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 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/debug/stubs.s b/src/runtime/debug/stubs.s
index d56274f2d..1e883b72c 100644
--- a/src/runtime/debug/stubs.s
+++ b/src/runtime/debug/stubs.s
@@ -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/defs1_linux.go b/src/runtime/defs1_linux.go
index 392cc4ab5..87c6e02a4 100644
--- a/src/runtime/defs1_linux.go
+++ b/src/runtime/defs1_linux.go
@@ -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/defs3_linux.go b/src/runtime/defs3_linux.go
new file mode 100644
index 000000000..3551a4fa9
--- /dev/null
+++ b/src/runtime/defs3_linux.go
@@ -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_linux.go b/src/runtime/defs_linux.go
index 8657dbb0e..553366a50 100644
--- a/src/runtime/defs_linux.go
+++ b/src/runtime/defs_linux.go
@@ -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_power64.h b/src/runtime/defs_linux_power64.h
new file mode 100644
index 000000000..93742fa34
--- /dev/null
+++ b/src/runtime/defs_linux_power64.h
@@ -0,0 +1,204 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_linux.go defs3_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_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 Sigset Sigset;
+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 Sigset {
+// uint64 sig[1];
+//};
+//typedef uint64 Sigset;
+
+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 Pad_cgo_0[4];
+ byte data[8]; // unaligned uintptr
+};
+
+
+#pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+
+enum {
+ O_RDONLY = 0x0,
+ O_CLOEXEC = 0x80000,
+ SA_RESTORER = 0,
+};
+
+typedef struct Ptregs Ptregs;
+typedef struct Vreg Vreg;
+typedef struct SigaltstackT SigaltstackT;
+typedef struct Sigcontext Sigcontext;
+typedef struct Ucontext Ucontext;
+
+#pragma pack on
+
+struct Ptregs {
+ uint64 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;
+};
+typedef uint64 Gregset[48];
+typedef float64 FPregset[33];
+struct Vreg {
+ uint32 u[4];
+};
+
+struct SigaltstackT {
+ byte *ss_sp;
+ int32 ss_flags;
+ byte Pad_cgo_0[4];
+ uint64 ss_size;
+};
+
+struct Sigcontext {
+ uint64 _unused[4];
+ int32 signal;
+ int32 _pad0;
+ uint64 handler;
+ uint64 oldmask;
+ Ptregs *regs;
+ uint64 gp_regs[48];
+ float64 fp_regs[33];
+ Vreg *v_regs;
+ int64 vmx_reserve[101];
+};
+struct Ucontext {
+ uint64 uc_flags;
+ Ucontext *uc_link;
+ SigaltstackT uc_stack;
+ uint64 uc_sigmask;
+ uint64 __unused[15];
+ Sigcontext uc_mcontext;
+};
+
+
+#pragma pack off
diff --git a/src/runtime/defs_linux_power64le.h b/src/runtime/defs_linux_power64le.h
new file mode 100644
index 000000000..93742fa34
--- /dev/null
+++ b/src/runtime/defs_linux_power64le.h
@@ -0,0 +1,204 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_linux.go defs3_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_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 Sigset Sigset;
+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 Sigset {
+// uint64 sig[1];
+//};
+//typedef uint64 Sigset;
+
+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 Pad_cgo_0[4];
+ byte data[8]; // unaligned uintptr
+};
+
+
+#pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_linux.go defs3_linux.go
+
+
+enum {
+ O_RDONLY = 0x0,
+ O_CLOEXEC = 0x80000,
+ SA_RESTORER = 0,
+};
+
+typedef struct Ptregs Ptregs;
+typedef struct Vreg Vreg;
+typedef struct SigaltstackT SigaltstackT;
+typedef struct Sigcontext Sigcontext;
+typedef struct Ucontext Ucontext;
+
+#pragma pack on
+
+struct Ptregs {
+ uint64 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;
+};
+typedef uint64 Gregset[48];
+typedef float64 FPregset[33];
+struct Vreg {
+ uint32 u[4];
+};
+
+struct SigaltstackT {
+ byte *ss_sp;
+ int32 ss_flags;
+ byte Pad_cgo_0[4];
+ uint64 ss_size;
+};
+
+struct Sigcontext {
+ uint64 _unused[4];
+ int32 signal;
+ int32 _pad0;
+ uint64 handler;
+ uint64 oldmask;
+ Ptregs *regs;
+ uint64 gp_regs[48];
+ float64 fp_regs[33];
+ Vreg *v_regs;
+ int64 vmx_reserve[101];
+};
+struct Ucontext {
+ uint64 uc_flags;
+ Ucontext *uc_link;
+ SigaltstackT uc_stack;
+ uint64 uc_sigmask;
+ uint64 __unused[15];
+ Sigcontext uc_mcontext;
+};
+
+
+#pragma pack off
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index be352557f..65e918e84 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -26,7 +26,7 @@ var Exitsyscall = exitsyscall
var LockedOSThread = lockedOSThread
type LFNode struct {
- Next *LFNode
+ Next uint64
Pushcnt uintptr
}
diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go
index 88f6703f9..1a33f3b3b 100644
--- a/src/runtime/gcinfo_test.go
+++ b/src/runtime/gcinfo_test.go
@@ -153,6 +153,12 @@ func infoBigStruct() []byte {
BitsScalar, BitsScalar, BitsDead, BitsScalar, BitsScalar, // t int; y uint16; u uint64
BitsPointer, BitsDead, // i string
}
+ case "power64", "power64le":
+ return []byte{
+ BitsPointer, BitsScalar, BitsScalar, BitsScalar,
+ BitsMultiWord, BitsSlice, BitsScalar, BitsScalar,
+ BitsScalar, BitsScalar, BitsMultiWord, BitsString,
+ }
default:
panic("unknown arch")
}
@@ -188,6 +194,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/heapdump.c b/src/runtime/heapdump.c
index eddbc1d1c..da14f2d24 100644
--- a/src/runtime/heapdump.c
+++ b/src/runtime/heapdump.c
@@ -261,20 +261,7 @@ dumpbv(BitVector *bv, uintptr offset)
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;
- }
+ runtime·throw("bumpbv unexpected garbage collection bits");
}
}
}
diff --git a/src/runtime/lfstack.c b/src/runtime/lfstack.c
index 57e0af282..0ced839c2 100644
--- a/src/runtime/lfstack.c
+++ b/src/runtime/lfstack.c
@@ -46,7 +46,7 @@ runtime·lfstackpush(uint64 *head, LFNode *node)
new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS);
for(;;) {
old = runtime·atomicload64(head);
- node->next = (LFNode*)(uintptr)(old&PTR_MASK);
+ node->next = old;
if(runtime·cas64(head, old, new))
break;
}
@@ -55,19 +55,17 @@ runtime·lfstackpush(uint64 *head, LFNode *node)
LFNode*
runtime·lfstackpop(uint64 *head)
{
- LFNode *node, *node2;
- uint64 old, new;
+ LFNode *node;
+ uint64 old, next;
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))
+ next = runtime·atomicload64(&node->next);
+
+ if(runtime·cas64(head, old, next))
return node;
}
}
diff --git a/src/runtime/lfstack_test.go b/src/runtime/lfstack_test.go
index e51877704..68f221d6e 100644
--- a/src/runtime/lfstack_test.go
+++ b/src/runtime/lfstack_test.go
@@ -121,7 +121,7 @@ func TestLFStackStress(t *testing.T) {
}
cnt++
sum2 += node.data
- node.Next = nil
+ node.Next = 0
}
}
if cnt != K {
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 8cf1c3d34..fab8cf269 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -4,9 +4,7 @@
package runtime
-import (
- "unsafe"
-)
+import "unsafe"
const (
debugMalloc = false
@@ -247,6 +245,8 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
masksize = masksize * pointersPerByte / 8 // 4 bits per word
masksize++ // unroll flag in the beginning
if masksize > maxGCMask && typ.gc[1] != 0 {
+ // write barriers have not been updated to deal with this case yet.
+ gothrow("maxGCMask too small for now")
// If the mask is too large, unroll the program directly
// into the GC bitmap. It's 7 times slower than copying
// from the pre-unrolled mask, but saves 1/16 of type size
@@ -261,8 +261,10 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
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 {
+ // 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 {
mp := acquirem()
mp.ptrarg[0] = unsafe.Pointer(typ)
onM(unrollgcprog_m)
@@ -304,6 +306,18 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
}
}
marked:
+
+ // GCmarkterminate allocates black
+ // All slots hold nil so no scanning is needed.
+ // This may be racing with GC so do it atomically if there can be
+ // a race marking the bit.
+ if gcphase == _GCmarktermination {
+ mp := acquirem()
+ mp.ptrarg[0] = x
+ onM(gcmarknewobject_m)
+ releasem(mp)
+ }
+
if raceenabled {
racemalloc(x, size)
}
@@ -344,6 +358,37 @@ marked:
return x
}
+func loadPtrMask(typ *_type) []uint8 {
+ var ptrmask *uint8
+ nptr := (uintptr(typ.size) + ptrSize - 1) / ptrSize
+ if typ.kind&kindGCProg != 0 {
+ masksize := nptr
+ if masksize%2 != 0 {
+ masksize *= 2 // repeated
+ }
+ masksize = masksize * pointersPerByte / 8 // 4 bits per word
+ masksize++ // unroll flag in the beginning
+ if masksize > maxGCMask && typ.gc[1] != 0 {
+ // write barriers have not been updated to deal with this case yet.
+ gothrow("maxGCMask too small for now")
+ }
+ ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0])))
+ // 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 {
+ mp := acquirem()
+ mp.ptrarg[0] = unsafe.Pointer(typ)
+ onM(unrollgcprog_m)
+ releasem(mp)
+ }
+ ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
+ } else {
+ ptrmask = (*uint8)(unsafe.Pointer(typ.gc[0])) // pointer to unrolled mask
+ }
+ return (*[1 << 30]byte)(unsafe.Pointer(ptrmask))[:(nptr+1)/2]
+}
+
// implementation of new builtin
func newobject(typ *_type) unsafe.Pointer {
flags := uint32(0)
@@ -438,7 +483,20 @@ func gogc(force int32) {
mp = acquirem()
mp.gcing = 1
releasem(mp)
+
onM(stoptheworld)
+ onM(finishsweep_m) // finish sweep before we start concurrent scan.
+ if false { // To turn on concurrent scan and mark set to true...
+ onM(starttheworld)
+ // Do a concurrent heap scan before we stop the world.
+ onM(gcscan_m)
+ onM(stoptheworld)
+ onM(gcinstallmarkwb_m)
+ onM(starttheworld)
+ onM(gcmark_m)
+ onM(stoptheworld)
+ onM(gcinstalloffwb_m)
+ }
if mp != acquirem() {
gothrow("gogc: rescheduled")
}
@@ -469,6 +527,8 @@ func gogc(force int32) {
onM(gc_m)
}
+ onM(gccheckmark_m)
+
// all done
mp.gcing = 0
semrelease(&worldsema)
@@ -483,6 +543,14 @@ func gogc(force int32) {
}
}
+func GCcheckmarkenable() {
+ onM(gccheckmarkenable_m)
+}
+
+func GCcheckmarkdisable() {
+ onM(gccheckmarkdisable_m)
+}
+
// GC runs a garbage collection.
func GC() {
gogc(2)
diff --git a/src/runtime/malloc.h b/src/runtime/malloc.h
index adb8d3d67..522b11bba 100644
--- a/src/runtime/malloc.h
+++ b/src/runtime/malloc.h
@@ -86,6 +86,7 @@ typedef struct MSpan MSpan;
typedef struct MStats MStats;
typedef struct MLink MLink;
typedef struct GCStats GCStats;
+typedef struct Workbuf Workbuf;
enum
{
@@ -344,8 +345,6 @@ struct MCache
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)
@@ -356,7 +355,7 @@ struct MCache
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);
+void runtime·gcworkbuffree(Workbuf *b);
enum
{
diff --git a/src/runtime/mcache.c b/src/runtime/mcache.c
index 5fdbe3266..95ddced3e 100644
--- a/src/runtime/mcache.c
+++ b/src/runtime/mcache.c
@@ -39,12 +39,12 @@ runtime·allocmcache(void)
return c;
}
+// mheap.lock needs to be held to release the gcworkbuf.
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);
diff --git a/src/runtime/mem_linux.c b/src/runtime/mem_linux.c
index bfb405607..52e02b34e 100644
--- a/src/runtime/mem_linux.c
+++ b/src/runtime/mem_linux.c
@@ -11,7 +11,7 @@
enum
{
- _PAGE_SIZE = 4096,
+ _PAGE_SIZE = PhysPageSize,
EACCES = 13,
};
@@ -36,8 +36,9 @@ addrspace_free(void *v, uintptr n)
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)
+ if (errval != -ENOMEM && errval != ENOMEM) {
return 0;
+ }
}
return 1;
}
@@ -48,12 +49,15 @@ 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)) {
+ if(p != v) {
+ if(p > (void*)4096) {
+ runtime·munmap(p, n);
+ p = nil;
+ }
// 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);
+ if(addrspace_free(v, n))
+ p = runtime·mmap(v, n, prot, flags|MAP_FIXED, fd, offset);
}
return p;
}
diff --git a/src/runtime/memclr_386.s b/src/runtime/memclr_386.s
index 1520aea2e..3f20b69c8 100644
--- a/src/runtime/memclr_386.s
+++ b/src/runtime/memclr_386.s
@@ -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
diff --git a/src/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s
index 94a2c7f23..ec24f1db2 100644
--- a/src/runtime/memclr_amd64.s
+++ b/src/runtime/memclr_amd64.s
@@ -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)
diff --git a/src/runtime/memclr_plan9_386.s b/src/runtime/memclr_plan9_386.s
index b4b671f77..50f327b4e 100644
--- a/src/runtime/memclr_plan9_386.s
+++ b/src/runtime/memclr_plan9_386.s
@@ -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
index 000000000..dfad64b6f
--- /dev/null
+++ b/src/runtime/memclr_power64x.s
@@ -0,0 +1,20 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +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
index 000000000..2b04d8319
--- /dev/null
+++ b/src/runtime/memmove_power64x.s
@@ -0,0 +1,40 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 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/mgc0.c b/src/runtime/mgc0.c
index 7754bad89..3248b0f49 100644
--- a/src/runtime/mgc0.c
+++ b/src/runtime/mgc0.c
@@ -4,22 +4,72 @@
// 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)
+// The GC runs concurrently with mutator threads, is type accurate (aka precise), allows multiple GC
+// thread to run in parallel. It is a concurrent mark and sweep that uses a write barrier. It is
+// non-generational and non-compacting. Allocation is done using size segregated per P allocation
+// areas to minimize fragmentation while eliminating locks in the common case.
//
-// 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).
+// The algorithm decomposes into several steps.
+// This is a high level description of the algorithm being used. For an overview of GC a good
+// place to start is Richard Jones' gchandbook.org.
+//
+// The algorithm's intellectual heritage includes Dijkstra's on-the-fly algorithm, see
+// Edsger W. Dijkstra, Leslie Lamport, A. J. Martin, C. S. Scholten, and E. F. M. Steffens. 1978.
+// On-the-fly garbage collection: an exercise in cooperation. Commun. ACM 21, 11 (November 1978), 966-975.
+// For journal quality proofs that these steps are complete, correct, and terminate see
+// Hudson, R., and Moss, J.E.B. Copying Garbage Collection without stopping the world.
+// Concurrency and Computation: Practice and Experience 15(3-5), 2003.
//
+// 0. Set phase = GCscan from GCoff.
+// 1. Wait for all P's to acknowledge phase change.
+// At this point all goroutines have passed through a GC safepoint and
+// know we are in the GCscan phase.
+// 2. GC scans all goroutine stacks, mark and enqueues all encountered pointers
+// (marking avoids most duplicate enqueuing but races may produce duplication which is benign).
+// Preempted goroutines are scanned before P schedules next goroutine.
+// 3. Set phase = GCmark.
+// 4. Wait for all P's to acknowledge phase change.
+// 5. Now write barrier marks and enqueues black, grey, or white to white pointers.
+// Malloc still allocates white (non-marked) objects.
+// 6. Meanwhile GC transitively walks the heap marking reachable objects.
+// 7. When GC finishes marking heap, it preempts P's one-by-one and
+// retakes partial wbufs (filled by write barrier or during a stack scan of the goroutine
+// currently scheduled on the P).
+// 8. Once the GC has exhausted all available marking work it sets phase = marktermination.
+// 9. Wait for all P's to acknowledge phase change.
+// 10. Malloc now allocates black objects, so number of unmarked reachable objects
+// monotonically decreases.
+// 11. GC preempts P's one-by-one taking partial wbufs and marks all unmarked yet reachable objects.
+// 12. When GC completes a full cycle over P's and discovers no new grey
+// objects, (which means all reachable objects are marked) set phase = GCsweep.
+// 13. Wait for all P's to acknowledge phase change.
+// 14. Now malloc allocates white (but sweeps spans before use).
+// Write barrier becomes nop.
+// 15. GC does background sweeping, see description below.
+// 16. When sweeping is complete set phase to GCoff.
+// 17. When sufficient allocation has taken place replay the sequence starting at 0 above,
+// see discussion of GC rate below.
+
+// Changing phases.
+// Phases are changed by setting the gcphase to the next phase and possibly calling ackgcphase.
+// All phase action must be benign in the presence of a change.
+// Starting with GCoff
+// GCoff to GCscan
+// GSscan scans stacks and globals greying them and never marks an object black.
+// Once all the P's are aware of the new phase they will scan gs on preemption.
+// This means that the scanning of preempted gs can't start until all the Ps
+// have acknowledged.
+// GCscan to GCmark
+// GCMark turns on the write barrier which also only greys objects. No scanning
+// of objects (making them black) can happen until all the Ps have acknowledged
+// the phase change.
+// GCmark to GCmarktermination
+// The only change here is that we start allocating black so the Ps must acknowledge
+// the change before we begin the termination algorithm
+// GCmarktermination to GSsweep
+// Object currently on the freelist must be marked black for this to work.
+// Are things on the free lists black or white? How does the sweep phase work?
+
// 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)
@@ -50,6 +100,14 @@
// 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).
+// 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).
+
#include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
@@ -64,10 +122,8 @@
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,
@@ -80,7 +136,7 @@ enum {
// ptrmask for an allocation containing a single pointer.
static byte oneptr[] = {BitsPointer};
-// Initialized from $GOGC. GOGC=off means no gc.
+// 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.
@@ -98,12 +154,16 @@ extern int32 runtime·gcpercent;
//
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];
+// It is a bug if bits does not have bitBoundary set but
+// there are still some cases where this happens related
+// to stack spans.
+typedef struct Markbits Markbits;
+struct Markbits {
+ byte *bitp; // pointer to the byte holding xbits
+ byte shift; // bits xbits needs to be shifted to get bits
+ byte xbits; // byte holding all the bits from *bitp
+ byte bits; // mark and boundary bits relevant to corresponding slot.
+ byte tbits; // pointer||scalar bits relevant to corresponding slot.
};
extern byte runtime·data[];
@@ -128,26 +188,40 @@ BitVector runtime·gcbssmask;
Mutex runtime·gclock;
-static uintptr badblock[1024];
-static int32 nbadblock;
-
+static Workbuf* getpartialorempty(void);
+static void putpartial(Workbuf*);
static Workbuf* getempty(Workbuf*);
static Workbuf* getfull(Workbuf*);
static void putempty(Workbuf*);
+static void putfull(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);
+static bool scanframe(Stkframe*, void*);
+static void scanstack(G*);
+static BitVector unrollglobgcprog(byte*, uintptr);
+static void scanblock(byte*, uintptr, byte*);
+static byte* objectstart(byte*, Markbits*);
+static Workbuf* greyobject(byte*, Markbits*, Workbuf*);
+static bool inheap(byte*);
+static bool shaded(byte*);
+static void shade(byte*);
+static void slottombits(byte*, Markbits*);
+static void atomicxor8(byte*, byte);
+static bool ischeckmarked(Markbits*);
+static bool ismarked(Markbits*);
+static void clearcheckmarkbits(void);
+static void clearcheckmarkbitsspan(MSpan*);
void runtime·bgsweep(void);
+void runtime·finishsweep_m(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
+ uint64 full; // lock-free list of full blocks
+ uint64 empty; // lock-free list of empty blocks
+ uint64 partial; // lock-free list of partially filled blocks
byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait
uint32 nproc;
int64 tstart;
@@ -162,315 +236,422 @@ struct WorkData {
};
WorkData runtime·work;
-// Is _cgo_allocate linked into the binary?
+// To help debug the concurrent GC we remark with the world
+// stopped ensuring that any object encountered has their normal
+// mark bit set. To do this we use an orthogonal bit
+// pattern to indicate the object is marked. The following pattern
+// uses the upper two bits in the object's bounday nibble.
+// 01: scalar not marked
+// 10: pointer not marked
+// 11: pointer marked
+// 00: scalar marked
+// Xoring with 01 will flip the pattern from marked to unmarked and vica versa.
+// The higher bit is 1 for pointers and 0 for scalars, whether the object
+// is marked or not.
+// The first nibble no longer holds the bitsDead pattern indicating that the
+// there are no more pointers in the object. This information is held
+// in the second nibble.
+
+// When marking an object if the bool checkmark is true one uses the above
+// encoding, otherwise one uses the bitMarked bit in the lower two bits
+// of the nibble.
+static bool checkmark = false;
+static bool gccheckmarkenable = true;
+
+// Is address b in the known heap. If it doesn't have a valid gcmap
+// returns false. For example pointers into stacks will return false.
static bool
-have_cgo_allocate(void)
+inheap(byte *b)
{
- extern byte go·weak·runtime·_cgo_allocate_internal[1];
- return go·weak·runtime·_cgo_allocate_internal != nil;
+ MSpan *s;
+ pageID k;
+ uintptr x;
+
+ if(b == nil || b < runtime·mheap.arena_start || b >= runtime·mheap.arena_used)
+ return false;
+ // Not a beginning of a block, consult span table to find the block beginning.
+ k = (uintptr)b>>PageShift;
+ x = k;
+ x -= (uintptr)runtime·mheap.arena_start>>PageShift;
+ s = runtime·mheap.spans[x];
+ if(s == nil || k < s->start || b >= s->limit || s->state != MSpanInUse)
+ return false;
+ return true;
}
-// 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.
+// Given an address in the heap return the relevant byte from the gcmap. This routine
+// can be used on addresses to the start of an object or to the interior of the an object.
static void
-scanblock(byte *b, uintptr n, byte *ptrmask)
+slottombits(byte *obj, Markbits *mbits)
{
- 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;
+ uintptr off;
+
+ off = (uintptr*)((uintptr)obj&~(PtrSize-1)) - (uintptr*)runtime·mheap.arena_start;
+ mbits->bitp = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
+ mbits->shift = (off % wordsPerBitmapByte) * gcBits;
+ mbits->xbits = *mbits->bitp;
+ mbits->bits = (mbits->xbits >> mbits->shift) & bitMask;
+ mbits->tbits = ((mbits->xbits >> mbits->shift) & bitPtrMask) >> 2;
+}
+
+// b is a pointer into the heap.
+// Find the start of the object refered to by b.
+// Set mbits to the associated bits from the bit map.
+// If b is not a valid heap object return nil and
+// undefined values in mbits.
+static byte*
+objectstart(byte *b, Markbits *mbits)
+{
+ byte *obj, *p;
MSpan *s;
pageID k;
- bool keepworking;
+ uintptr x, size, idx;
- // Cache memory arena parameters in local vars.
- arena_start = runtime·mheap.arena_start;
- arena_used = runtime·mheap.arena_used;
+ obj = (byte*)((uintptr)b&~(PtrSize-1));
+ for(;;) {
+ slottombits(obj, mbits);
+ if((mbits->bits&bitBoundary) == bitBoundary)
+ break;
- 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;
+ // Not a beginning of a block, consult span table to find the block beginning.
+ k = (uintptr)obj>>PageShift;
+ x = k;
+ x -= (uintptr)runtime·mheap.arena_start>>PageShift;
+ s = runtime·mheap.spans[x];
+ if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse){
+ if(s != nil && s->state == MSpanStack) {
+ return nil; // This is legit.
+ }
+ // The following ensures that we are rigorous about what data
+ // structures hold valid pointers
+ if(0) {
+ // Still happens sometimes. We don't know why.
+ runtime·printf("runtime:objectstart Span weird: obj=%p, k=%p", obj, k);
+ if (s == nil)
+ runtime·printf(" s=nil\n");
+ else
+ runtime·printf(" s->start=%p s->limit=%p, s->state=%d\n", s->start*PageSize, s->limit, s->state);
+ runtime·throw("objectstart: bad pointer in unexpected span");
+ }
+ return nil;
+ }
+ 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;
+ }
+ // if size(obj.firstfield) < PtrSize, the &obj.secondfield could map to the boundary bit
+ // Clear any low bits to get to the start of the object.
+ // greyobject depends on this.
+ return obj;
+}
+
+// Slow for now as we serialize this, since this is on a debug path
+// speed is not critical at this point.
+static Mutex andlock;
+static void
+atomicand8(byte *src, byte val)
+{
+ runtime·lock(&andlock);
+ *src = *src&val;
+ runtime·unlock(&andlock);
+}
+
+// Mark using the checkmark scheme.
+void
+docheckmark(Markbits *mbits)
+{
+ // xor 01 moves 01(scalar unmarked) to 00(scalar marked)
+ // and 10(pointer unmarked) to 11(pointer marked)
+ if(mbits->tbits == BitsScalar)
+ atomicand8(mbits->bitp, ~(byte)(BitsCheckMarkXor<<mbits->shift<<2));
+ else if(mbits->tbits == BitsPointer)
+ runtime·atomicor8(mbits->bitp, BitsCheckMarkXor<<mbits->shift<<2);
+
+ // reload bits for ischeckmarked
+ mbits->xbits = *mbits->bitp;
+ mbits->bits = (mbits->xbits >> mbits->shift) & bitMask;
+ mbits->tbits = ((mbits->xbits >> mbits->shift) & bitPtrMask) >> 2;
+
+ return;
+}
+
+// In the default scheme does mbits refer to a marked object.
+static bool
+ismarked(Markbits *mbits)
+{
+ if((mbits->bits&bitBoundary) != bitBoundary)
+ runtime·throw("ismarked: bits should have boundary bit set");
+ return (mbits->bits&bitMarked) == bitMarked;
+}
+
+// In the checkmark scheme does mbits refer to a marked object.
+static bool
+ischeckmarked(Markbits *mbits)
+{
+ if((mbits->bits&bitBoundary) != bitBoundary)
+ runtime·printf("runtime:ischeckmarked: bits should have boundary bit set\n");
+ return mbits->tbits==BitsScalarMarked || mbits->tbits==BitsPointerMarked;
+}
+
+// When in GCmarkterminate phase we allocate black.
+void
+runtime·gcmarknewobject_m(void)
+{
+ Markbits mbits;
+ byte *obj;
+
+ if(runtime·gcphase != GCmarktermination)
+ runtime·throw("marking new object while not in mark termination phase");
+ if(checkmark) // The world should be stopped so this should not happen.
+ runtime·throw("gcmarknewobject called while doing checkmark");
+
+ obj = g->m->ptrarg[0];
+ slottombits((byte*)((uintptr)obj & (PtrSize-1)), &mbits);
+
+ if((mbits.bits&bitMarked) != 0)
+ return;
+
+ // Each byte of GC bitmap holds info for two words.
+ // If the current object is larger than two words, or if the object is one word
+ // but the object it shares the byte with is already marked,
+ // then all the possible concurrent updates are trying to set the same bit,
+ // so we can use a non-atomic update.
+ if((mbits.xbits&(bitMask|(bitMask<<gcBits))) != (bitBoundary|(bitBoundary<<gcBits)) || runtime·work.nproc == 1)
+ *mbits.bitp = mbits.xbits | (bitMarked<<mbits.shift);
+ else
+ runtime·atomicor8(mbits.bitp, bitMarked<<mbits.shift);
+ return;
+}
+
+// obj is the start of an object with mark mbits.
+// If it isn't already marked, mark it and enqueue into workbuf.
+// Return possibly new workbuf to use.
+static Workbuf*
+greyobject(byte *obj, Markbits *mbits, Workbuf *wbuf)
+{
+ // obj should be start of allocation, and so must be at least pointer-aligned.
+ if(((uintptr)obj & (PtrSize-1)) != 0)
+ runtime·throw("greyobject: obj not pointer-aligned");
+
+ if(checkmark) {
+ if(!ismarked(mbits)) {
+ MSpan *s;
+ pageID k;
+ uintptr x, i;
+
+ runtime·printf("runtime:greyobject: checkmarks finds unexpected unmarked object obj=%p, mbits->bits=%x, *mbits->bitp=%x\n", obj, mbits->bits, *mbits->bitp);
+
+ k = (uintptr)obj>>PageShift;
+ x = k;
+ x -= (uintptr)runtime·mheap.arena_start>>PageShift;
+ s = runtime·mheap.spans[x];
+ runtime·printf("runtime:greyobject Span: obj=%p, k=%p", obj, k);
+ if (s == nil) {
+ runtime·printf(" s=nil\n");
+ } else {
+ runtime·printf(" s->start=%p s->limit=%p, s->state=%d, s->sizeclass=%d, s->elemsize=%D \n", s->start*PageSize, s->limit, s->state, s->sizeclass, s->elemsize);
+ for(i=0; i<s->sizeclass; i++) {
+ runtime·printf(" ((uintptr*)obj)[%D]=%p\n", i, ((uintptr*)obj)[i]);
+ }
+ }
+ runtime·throw("checkmark found unmarked object");
+ }
+ if(ischeckmarked(mbits))
+ return wbuf;
+ docheckmark(mbits);
+ if(!ischeckmarked(mbits)) {
+ runtime·printf("mbits xbits=%x bits=%x tbits=%x shift=%d\n", mbits->xbits, mbits->bits, mbits->tbits, mbits->shift);
+ runtime·throw("docheckmark and ischeckmarked disagree");
+ }
+ } else {
+ // If marked we have nothing to do.
+ if((mbits->bits&bitMarked) != 0)
+ return wbuf;
+
+ // Each byte of GC bitmap holds info for two words.
+ // If the current object is larger than two words, or if the object is one word
+ // but the object it shares the byte with is already marked,
+ // then all the possible concurrent updates are trying to set the same bit,
+ // so we can use a non-atomic update.
+ if((mbits->xbits&(bitMask|(bitMask<<gcBits))) != (bitBoundary|(bitBoundary<<gcBits)) || runtime·work.nproc == 1)
+ *mbits->bitp = mbits->xbits | (bitMarked<<mbits->shift);
+ else
+ runtime·atomicor8(mbits->bitp, bitMarked<<mbits->shift);
+ }
+
+ if (!checkmark && (((mbits->xbits>>(mbits->shift+2))&BitsMask) == BitsDead))
+ return wbuf; // noscan object
+
+ // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but
+ // seems like a nice optimization that can be added back in.
+ // There needs to be time between the PREFETCH and the use.
+ // Previously we put the obj in an 8 element buffer that is drained at a rate
+ // to give the PREFETCH time to do its work.
+ // Use of PREFETCHNTA might be more appropriate than PREFETCH
+
+ // If workbuf is full, obtain an empty one.
+ if(wbuf->nobj >= nelem(wbuf->obj)) {
+ wbuf = getempty(wbuf);
+ }
+
+ wbuf->obj[wbuf->nobj] = obj;
+ wbuf->nobj++;
+ return wbuf;
+}
+
+// Scan the object b of size n, adding pointers to wbuf.
+// Return possibly new wbuf to use.
+// If ptrmask != nil, it specifies where pointers are in b.
+// If ptrmask == nil, the GC bitmap should be consulted.
+// In this case, n may be an overestimate of the size; the GC bitmap
+// must also be used to make sure the scan stops at the end of b.
+static Workbuf*
+scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf)
+{
+ byte *obj, *arena_start, *arena_used, *ptrbitp;
+ uintptr i, j;
+ int32 bits;
+ Markbits mbits;
+
+ arena_start = (byte*)runtime·mheap.arena_start;
+ arena_used = runtime·mheap.arena_used;
ptrbitp = nil;
+ // Find bits of the beginning of the object.
+ if(ptrmask == nil) {
+ b = objectstart(b, &mbits);
+ if(b == nil)
+ return wbuf;
+ ptrbitp = mbits.bitp; //arena_start - off/wordsPerBitmapByte - 1;
+ }
+ for(i = 0; i < n; i += PtrSize) {
+ // Find bits for this word.
+ if(ptrmask != nil) {
+ // dense mask (stack or data)
+ bits = (ptrmask[(i/PtrSize)/4]>>(((i/PtrSize)%4)*BitsPerPointer))&BitsMask;
+ } else {
+ // Check if we have reached end of span.
+ // n is an overestimate of the size of the object.
+ 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; // j indicates upper nibble or lower nibble
+ bits >>= gcBits*j;
+ if(i == 0)
+ bits &= ~bitBoundary;
+ ptrbitp -= j;
+
+ if((bits&bitBoundary) != 0 && i != 0)
+ break; // reached beginning of the next object
+ bits = (bits&bitPtrMask)>>2; // bits refer to the type bits.
+
+ if(i != 0 && bits == BitsDead) // BitsDead in first nibble not valid during checkmark
+ break; // reached no-scan part of the object
+ }
+
+ if(bits <= BitsScalar) // Bits Scalar ||
+ // BitsDead || // default encoding
+ // BitsScalarMarked // checkmark encoding
+ continue;
+
+ if((bits&BitsPointer) != BitsPointer) {
+ runtime·printf("gc checkmark=%d, b=%p ptrmask=%p, mbits.bitp=%p, mbits.xbits=%x, bits=%x\n", checkmark, b, ptrmask, mbits.bitp, mbits.xbits, bits);
+ runtime·throw("unexpected garbage collection bits");
+ }
+
+ obj = *(byte**)(b+i);
+ // At this point we have extracted the next potential pointer.
+ // Check if it points into heap.
+ if(obj == nil || obj < arena_start || obj >= arena_used)
+ continue;
+ // Mark the object. return some important bits.
+ // We we combine the following two rotines we don't have to pass mbits or obj around.
+ obj = objectstart(obj, &mbits);
+ // In the case of the span being MSpan_Stack mbits is useless and will not have
+ // the boundary bit set. It does not need to be greyed since it will be
+ // scanned using the scan stack mechanism.
+ if(obj == nil)
+ continue;
+ wbuf = greyobject(obj, &mbits, wbuf);
+ }
+ return wbuf;
+}
+
+// scanblock starts by scanning b as scanobject would.
+// If the gcphase is GCscan, that's all scanblock does.
+// Otherwise it traverses some fraction of the pointers it found in b, recursively.
+// As a special case, scanblock(nil, 0, nil) means to scan previously queued work,
+// stopping only when no work is left in the system.
+static void
+scanblock(byte *b, uintptr n, byte *ptrmask)
+{
+ Workbuf *wbuf;
+ bool keepworking;
+
+ wbuf = getpartialorempty();
+ if(b != nil) {
+ wbuf = scanobject(b, n, ptrmask, wbuf);
+ if(runtime·gcphase == GCscan) {
+ if(inheap(b) && !ptrmask)
+ // b is in heap, we are in GCscan so there should be a ptrmask.
+ runtime·throw("scanblock: In GCscan phase and inheap is true.");
+ // GCscan only goes one level deep since mark wb not turned on.
+ putpartial(wbuf);
+ return;
+ }
+ }
+ if(runtime·gcphase == GCscan) {
+ runtime·throw("scanblock: In GCscan phase but no b passed in.");
+ }
+
+ keepworking = b == 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(wbuf->nobj == 0) {
if(!keepworking) {
putempty(wbuf);
return;
}
// Refill workbuf from global queue.
wbuf = getfull(wbuf);
- if(wbuf == nil)
+ if(wbuf == nil) // nil means out of work barrier reached
return;
- nobj = wbuf->nobj;
- wp = &wbuf->obj[nobj];
+
+ if(wbuf->nobj<=0) {
+ runtime·throw("runtime:scanblock getfull returns empty buffer");
+ }
+
}
// If another proc wants a pointer, give it some.
- if(runtime·work.nwait > 0 && nobj > 4 && runtime·work.full == 0) {
- wbuf->nobj = nobj;
+ if(runtime·work.nwait > 0 && wbuf->nobj > 4 && runtime·work.full == 0) {
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");
- }
- }
+ // This might be a good place to add prefetch code...
+ // if(wbuf->nobj > 4) {
+ // PREFETCH(wbuf->obj[wbuf->nobj - 3];
+ // }
+ --wbuf->nobj;
+ b = wbuf->obj[wbuf->nobj];
+ wbuf = scanobject(b, runtime·mheap.arena_used - b, nil, wbuf);
}
}
@@ -484,7 +665,7 @@ markroot(ParFor *desc, uint32 i)
void *p;
uint32 status;
bool restart;
-
+
USED(&desc);
// Note: if you add a case here, please also update heapdump.c:dumproots.
switch(i) {
@@ -511,7 +692,8 @@ markroot(ParFor *desc, uint32 i)
s = runtime·work.spans[spanidx];
if(s->state != MSpanInUse)
continue;
- if(s->sweepgen != sg) {
+ if(!checkmark && s->sweepgen != sg) {
+ // sweepgen was updated (+2) during non-checkmark GC pass
runtime·printf("sweep %d %d\n", s->sweepgen, sg);
runtime·throw("gc: unswept span");
}
@@ -523,14 +705,16 @@ markroot(ParFor *desc, uint32 i)
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);
+ if(runtime·gcphase != GCscan)
+ scanblock(p, s->elemsize, nil); // Scanned during mark phase
scanblock((void*)&spf->fn, PtrSize, oneptr);
}
}
break;
case RootFlushCaches:
- flushallmcaches();
+ if (runtime·gcphase != GCscan) // Do not flush mcaches during GCscan phase.
+ flushallmcaches();
break;
default:
@@ -540,17 +724,37 @@ markroot(ParFor *desc, uint32 i)
gp = runtime·allg[i - RootCount];
// remember when we've first observed the G blocked
// needed only to output in traceback
- status = runtime·readgstatus(gp);
+ status = runtime·readgstatus(gp); // We are not in a scan state
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)
+ // Shrink a stack if not much of it is being used but not in the scan phase.
+ if (runtime·gcphase != GCscan) // Do not shrink during GCscan phase.
+ runtime·shrinkstack(gp);
+ if(runtime·readgstatus(gp) == Gdead)
gp->gcworkdone = true;
else
gp->gcworkdone = false;
restart = runtime·stopg(gp);
- scanstack(gp);
+
+ // goroutine will scan its own stack when it stops running.
+ // Wait until it has.
+ while(runtime·readgstatus(gp) == Grunning && !gp->gcworkdone) {
+ }
+
+ // scanstack(gp) is done as part of gcphasework
+ // But to make sure we finished we need to make sure that
+ // the stack traps have all responded so drop into
+ // this while loop until they respond.
+ 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 == Gwaiting || status == Grunnable)
+ restart = runtime·stopg(gp);
+ }
if(restart)
runtime·restartg(gp);
break;
@@ -562,53 +766,95 @@ markroot(ParFor *desc, uint32 i)
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) {
+ putfull(b);
+ b = nil;
}
- if(b == nil)
+ if(runtime·work.empty)
b = (Workbuf*)runtime·lfstackpop(&runtime·work.empty);
- if(b == nil)
+
+ if(b && b->nobj != 0) {
+ runtime·printf("m%d: getempty: popped b=%p with non-zero b->nobj=%d\n", g->m->id, b, (uint32)b->nobj);
+ runtime·throw("getempty: workbuffer not empty, b->nobj not 0");
+ }
+ if(b == nil) {
b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys);
- b->nobj = 0;
+ b->nobj = 0;
+ }
return b;
}
static void
putempty(Workbuf *b)
{
- MCache *c;
-
- c = g->m->mcache;
- if(c->gcworkbuf == nil) {
- c->gcworkbuf = b;
- return;
+ if(b->nobj != 0) {
+ runtime·throw("putempty: b->nobj not 0\n");
}
runtime·lfstackpush(&runtime·work.empty, &b->node);
}
-void
-runtime·gcworkbuffree(void *b)
+// Put a full or partially full workbuf on the full list.
+static void
+putfull(Workbuf *b)
{
- if(b != nil)
- putempty(b);
+ if(b->nobj <= 0) {
+ runtime·throw("putfull: b->nobj <= 0\n");
+ }
+ runtime·lfstackpush(&runtime·work.full, &b->node);
}
-// Get a full work buffer off the work.full list, or return nil.
+// Get an partially empty work buffer
+// if none are available get an empty one.
+static Workbuf*
+getpartialorempty(void)
+{
+ Workbuf *b;
+
+ b = (Workbuf*)runtime·lfstackpop(&runtime·work.partial);
+ if(b == nil)
+ b = getempty(nil);
+ return b;
+}
+
+static void
+putpartial(Workbuf *b)
+{
+
+ if(b->nobj == 0)
+ runtime·lfstackpush(&runtime·work.empty, &b->node);
+ else if (b->nobj < nelem(b->obj))
+ runtime·lfstackpush(&runtime·work.partial, &b->node);
+ else if (b->nobj == nelem(b->obj))
+ runtime·lfstackpush(&runtime·work.full, &b->node);
+ else {
+ runtime·printf("b=%p, b->nobj=%d, nelem(b->obj)=%d\n", b, (uint32)b->nobj, (uint32)nelem(b->obj));
+ runtime·throw("putpartial: bad Workbuf b->nobj");
+ }
+}
+
+// Get a full work buffer off the work.full or a partially
+// filled one off the work.partial list. If nothing is available
+// wait until all the other gc helpers have finished and then
+// return nil.
+// getfull acts as a barrier for work.nproc helpers. As long as one
+// gchelper is actively marking objects it
+// may create a workbuffer that the other helpers can work on.
+// The for loop either exits when a work buffer is found
+// or when _all_ of the work.nproc GC helpers are in the loop
+// looking for work and thus not capable of creating new work.
+// This is in fact the termination condition for the STW mark
+// phase.
static Workbuf*
getfull(Workbuf *b)
{
int32 i;
if(b != nil)
- runtime·lfstackpush(&runtime·work.empty, &b->node);
+ putempty(b);
+
b = (Workbuf*)runtime·lfstackpop(&runtime·work.full);
+ if(b==nil)
+ b = (Workbuf*)runtime·lfstackpop(&runtime·work.partial);
if(b != nil || runtime·work.nproc == 1)
return b;
@@ -617,7 +863,9 @@ getfull(Workbuf *b)
if(runtime·work.full != 0) {
runtime·xadd(&runtime·work.nwait, -1);
b = (Workbuf*)runtime·lfstackpop(&runtime·work.full);
- if(b != nil)
+ if(b==nil)
+ b = (Workbuf*)runtime·lfstackpop(&runtime·work.partial);
+ if(b != nil)
return b;
runtime·xadd(&runtime·work.nwait, +1);
}
@@ -737,7 +985,7 @@ scanframe(Stkframe *frame, void *unused)
}
bv = runtime·stackmapdata(stackmap, pcdata);
}
- scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
+ scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata);
}
return true;
}
@@ -760,8 +1008,7 @@ scanstack(G *gp)
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");
+ runtime·throw("scanstack: - goroutine not stopped");
case Grunnable:
case Gsyscall:
case Gwaiting:
@@ -778,8 +1025,117 @@ scanstack(G *gp)
runtime·tracebackdefers(gp, &fn, nil);
}
-// The gp has been moved to a gc safepoint. If there is gcphase specific
-// work it is done here.
+// If the slot is grey or black return true, if white return false.
+// If the slot is not in the known heap and thus does not have a valid GC bitmap then
+// it is considered grey. Globals and stacks can hold such slots.
+// The slot is grey if its mark bit is set and it is enqueued to be scanned.
+// The slot is black if it has already been scanned.
+// It is white if it has a valid mark bit and the bit is not set.
+static bool
+shaded(byte *slot)
+{
+ Markbits mbits;
+ byte *valid;
+
+ if(!inheap(slot)) // non-heap slots considered grey
+ return true;
+
+ valid = objectstart(slot, &mbits);
+ if(valid == nil)
+ return true;
+
+ if(checkmark)
+ return ischeckmarked(&mbits);
+
+ return (mbits.bits&bitMarked) != 0;
+}
+
+// Shade the object if it isn't already.
+// The object is not nil and known to be in the heap.
+static void
+shade(byte *b)
+{
+ byte *obj;
+ Workbuf *wbuf;
+ Markbits mbits;
+
+ if(!inheap(b))
+ runtime·throw("shade: passed an address not in the heap");
+
+ wbuf = getpartialorempty();
+ // Mark the object, return some important bits.
+ // If we combine the following two rotines we don't have to pass mbits or obj around.
+ obj = objectstart(b, &mbits);
+ if(obj != nil)
+ wbuf = greyobject(obj, &mbits, wbuf); // augments the wbuf
+
+ putpartial(wbuf);
+ return;
+}
+
+// This is the Dijkstra barrier coarsened to always shade the ptr (dst) object.
+// The original Dijkstra barrier only shaded ptrs being placed in black slots.
+//
+// Shade indicates that it has seen a white pointer by adding the referent
+// to wbuf as well as marking it.
+//
+// slot is the destination (dst) in go code
+// ptr is the value that goes into the slot (src) in the go code
+//
+// Dijkstra pointed out that maintaining the no black to white
+// pointers means that white to white pointers not need
+// to be noted by the write barrier. Furthermore if either
+// white object dies before it is reached by the
+// GC then the object can be collected during this GC cycle
+// instead of waiting for the next cycle. Unfortunately the cost of
+// ensure that the object holding the slot doesn't concurrently
+// change to black without the mutator noticing seems prohibitive.
+//
+// Consider the following example where the mutator writes into
+// a slot and then loads the slot's mark bit while the GC thread
+// writes to the slot's mark bit and then as part of scanning reads
+// the slot.
+//
+// Initially both [slot] and [slotmark] are 0 (nil)
+// Mutator thread GC thread
+// st [slot], ptr st [slotmark], 1
+//
+// ld r1, [slotmark] ld r2, [slot]
+//
+// This is a classic example of independent reads of independent writes,
+// aka IRIW. The question is if r1==r2==0 is allowed and for most HW the
+// answer is yes without inserting a memory barriers between the st and the ld.
+// These barriers are expensive so we have decided that we will
+// always grey the ptr object regardless of the slot's color.
+//
+void
+runtime·gcmarkwb_m()
+{
+ byte *ptr;
+ ptr = (byte*)g->m->scalararg[1];
+
+ switch(runtime·gcphase) {
+ default:
+ runtime·throw("gcphasework in bad gcphase");
+ case GCoff:
+ case GCquiesce:
+ case GCstw:
+ case GCsweep:
+ case GCscan:
+ break;
+ case GCmark:
+ if(ptr != nil && inheap(ptr))
+ shade(ptr);
+ break;
+ case GCmarktermination:
+ if(ptr != nil && inheap(ptr))
+ shade(ptr);
+ break;
+ }
+}
+
+// The gp has been moved to a GC safepoint. GC phase specific
+// work is done here.
void
runtime·gcphasework(G *gp)
{
@@ -790,12 +1146,18 @@ runtime·gcphasework(G *gp)
case GCquiesce:
case GCstw:
case GCsweep:
- // No work for now.
+ // No work.
+ break;
+ case GCscan:
+ // scan the stack, mark the objects, put pointers in work buffers
+ // hanging off the P where this is being run.
+ scanstack(gp);
break;
case GCmark:
- // Disabled until concurrent GC is implemented
- // but indicate the scan has been done.
- // scanstack(gp);
+ break;
+ case GCmarktermination:
+ scanstack(gp);
+ // All available mark work will be emptied before returning.
break;
}
gp->gcworkdone = true;
@@ -885,6 +1247,7 @@ runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType*
}
}
+// Returns only when span s has been swept.
void
runtime·MSpan_EnsureSwept(MSpan *s)
{
@@ -899,6 +1262,7 @@ runtime·MSpan_EnsureSwept(MSpan *s)
sg = runtime·mheap.sweepgen;
if(runtime·atomicload(&s->sweepgen) == sg)
return;
+ // The caller must be sure that the span is a MSpanInUse span.
if(runtime·cas(&s->sweepgen, sg-2, sg-1)) {
runtime·MSpan_Sweep(s, false);
return;
@@ -926,6 +1290,9 @@ runtime·MSpan_Sweep(MSpan *s, bool preserve)
Special *special, **specialp, *y;
bool res, sweepgenset;
+ if(checkmark)
+ runtime·throw("MSpan_Sweep: checkmark only runs in STW and after the sweep.");
+
// 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)
@@ -1173,6 +1540,7 @@ runtime·gosweepdone(void)
return runtime·mheap.sweepdone;
}
+
void
runtime·gchelper(void)
{
@@ -1181,13 +1549,11 @@ runtime·gchelper(void)
g->m->traceback = 2;
gchelperstart();
- // parallel mark for over gc roots
+ // 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·gcphase != GCscan)
+ scanblock(nil, 0, nil); // blocks in getfull
+ nproc = runtime·work.nproc; // work.nproc can change right after we increment work.ndone
if(runtime·xadd(&runtime·work.ndone, +1) == nproc-1)
runtime·notewakeup(&runtime·work.alldone);
g->m->traceback = 0;
@@ -1353,6 +1719,7 @@ runtime·gcinit(void)
runtime·gcbssmask = unrollglobgcprog(runtime·gcbss, runtime·ebss - runtime·bss);
}
+// Called from malloc.go using onM, stopping and starting the world handled in caller.
void
runtime·gc_m(void)
{
@@ -1366,17 +1733,296 @@ runtime·gc_m(void)
a.start_time = (uint64)(g->m->scalararg[0]) | ((uint64)(g->m->scalararg[1]) << 32);
a.eagersweep = g->m->scalararg[2];
gc(&a);
+ runtime·casgstatus(gp, Gwaiting, Grunning);
+}
+
+// Similar to clearcheckmarkbits but works on a single span.
+// It preforms two tasks.
+// 1. When used before the checkmark phase it converts BitsDead (00) to bitsScalar (01)
+// for nibbles with the BoundaryBit set.
+// 2. When used after the checkmark phase it converts BitsPointerMark (11) to BitsPointer 10 and
+// BitsScalarMark (00) to BitsScalar (01), thus clearing the checkmark mark encoding.
+// For the second case it is possible to restore the BitsDead pattern but since
+// clearmark is a debug tool performance has a lower priority than simplicity.
+// The span is MSpanInUse and the world is stopped.
+static void
+clearcheckmarkbitsspan(MSpan *s)
+{
+ int32 cl, n, npages, i;
+ uintptr size, off, step;
+ byte *p, *bitp, *arena_start, b;
+
+ if(s->state != MSpanInUse) {
+ runtime·printf("runtime:clearcheckmarkbitsspan: state=%d\n",
+ s->state);
+ runtime·throw("clearcheckmarkbitsspan: 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;
+ }
+
+ // MSpan_Sweep has similar code but instead of overloading and
+ // complicating that routine we do a simpler walk here.
+ // 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;
+ step = size/(PtrSize*wordsPerBitmapByte);
+
+ // The type bit values are:
+ // 00 - BitsDead, for us BitsScalarMarked
+ // 01 - BitsScalar
+ // 10 - BitsPointer
+ // 11 - unused, for us BitsPointerMarked
+ //
+ // When called to prepare for the checkmark phase (checkmark==1),
+ // we change BitsDead to BitsScalar, so that there are no BitsScalarMarked
+ // type bits anywhere.
+ //
+ // The checkmark phase marks by changing BitsScalar to BitsScalarMarked
+ // and BitsPointer to BitsPointerMarked.
+ //
+ // When called to clean up after the checkmark phase (checkmark==0),
+ // we unmark by changing BitsScalarMarked back to BitsScalar and
+ // BitsPointerMarked back to BitsPointer.
+ //
+ // There are two problems with the scheme as just described.
+ // First, the setup rewrites BitsDead to BitsScalar, but the type bits
+ // following a BitsDead are uninitialized and must not be used.
+ // Second, objects that are free are expected to have their type
+ // bits zeroed (BitsDead), so in the cleanup we need to restore
+ // any BitsDeads that were there originally.
+ //
+ // In a one-word object (8-byte allocation on 64-bit system),
+ // there is no difference between BitsScalar and BitsDead, because
+ // neither is a pointer and there are no more words in the object,
+ // so using BitsScalar during the checkmark is safe and mapping
+ // both back to BitsDead during cleanup is also safe.
+ //
+ // In a larger object, we need to be more careful. During setup,
+ // if the type of the first word is BitsDead, we change it to BitsScalar
+ // (as we must) but also initialize the type of the second
+ // word to BitsDead, so that a scan during the checkmark phase
+ // will still stop before seeing the uninitialized type bits in the
+ // rest of the object. The sequence 'BitsScalar BitsDead' never
+ // happens in real type bitmaps - BitsDead is always as early
+ // as possible, so immediately after the last BitsPointer.
+ // During cleanup, if we see a BitsScalar, we can check to see if it
+ // is followed by BitsDead. If so, it was originally BitsDead and
+ // we can change it back.
- 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");
+ if(step == 0) {
+ // updating top and bottom nibbles, all boundaries
+ for(i=0; i<n/2; i++, bitp--) {
+ if((*bitp & bitBoundary) != bitBoundary)
+ runtime·throw("missing bitBoundary");
+ b = (*bitp & bitPtrMask)>>2;
+ if(!checkmark && (b == BitsScalar || b == BitsScalarMarked))
+ *bitp &= ~0x0c; // convert to BitsDead
+ else if(b == BitsScalarMarked || b == BitsPointerMarked)
+ *bitp ^= BitsCheckMarkXor<<2;
+
+ if(((*bitp>>gcBits) & bitBoundary) != bitBoundary)
+ runtime·throw("missing bitBoundary");
+ b = ((*bitp>>gcBits) & bitPtrMask)>>2;
+ if(!checkmark && (b == BitsScalar || b == BitsScalarMarked))
+ *bitp &= ~0xc0; // convert to BitsDead
+ else if(b == BitsScalarMarked || b == BitsPointerMarked)
+ *bitp ^= BitsCheckMarkXor<<(2+gcBits);
+ }
+ } else {
+ // updating bottom nibble for first word of each object
+ for(i=0; i<n; i++, bitp -= step) {
+ if((*bitp & bitBoundary) != bitBoundary)
+ runtime·throw("missing bitBoundary");
+ b = (*bitp & bitPtrMask)>>2;
+
+ if(checkmark && b == BitsDead) {
+ // move BitsDead into second word.
+ // set bits to BitsScalar in preparation for checkmark phase.
+ *bitp &= ~0xc0;
+ *bitp |= BitsScalar<<2;
+ } else if(!checkmark && (b == BitsScalar || b == BitsScalarMarked) && (*bitp & 0xc0) == 0) {
+ // Cleaning up after checkmark phase.
+ // First word is scalar or dead (we forgot)
+ // and second word is dead.
+ // First word might as well be dead too.
+ *bitp &= ~0x0c;
+ } else if(b == BitsScalarMarked || b == BitsPointerMarked)
+ *bitp ^= BitsCheckMarkXor<<2;
}
}
+}
- runtime·casgstatus(gp, Gwaiting, Grunning);
+// clearcheckmarkbits preforms two tasks.
+// 1. When used before the checkmark phase it converts BitsDead (00) to bitsScalar (01)
+// for nibbles with the BoundaryBit set.
+// 2. When used after the checkmark phase it converts BitsPointerMark (11) to BitsPointer 10 and
+// BitsScalarMark (00) to BitsScalar (01), thus clearing the checkmark mark encoding.
+// This is a bit expensive but preserves the BitsDead encoding during the normal marking.
+// BitsDead remains valid for every nibble except the ones with BitsBoundary set.
+static void
+clearcheckmarkbits(void)
+{
+ uint32 idx;
+ MSpan *s;
+ for(idx=0; idx<runtime·work.nspan; idx++) {
+ s = runtime·work.spans[idx];
+ if(s->state == MSpanInUse) {
+ clearcheckmarkbitsspan(s);
+ }
+ }
+}
+
+// Called from malloc.go using onM.
+// The world is stopped. Rerun the scan and mark phases
+// using the bitMarkedCheck bit instead of the
+// bitMarked bit. If the marking encounters an
+// bitMarked bit that is not set then we throw.
+void
+runtime·gccheckmark_m(void)
+{
+ if(!gccheckmarkenable)
+ return;
+
+ if(checkmark)
+ runtime·throw("gccheckmark_m, entered with checkmark already true.");
+
+ checkmark = true;
+ clearcheckmarkbits(); // Converts BitsDead to BitsScalar.
+ runtime·gc_m(); // turns off checkmark
+ // Work done, fixed up the GC bitmap to remove the checkmark bits.
+ clearcheckmarkbits();
+}
+
+// checkmarkenable is initially false
+void
+runtime·gccheckmarkenable_m(void)
+{
+ gccheckmarkenable = true;
+}
+
+void
+runtime·gccheckmarkdisable_m(void)
+{
+ gccheckmarkenable = false;
+}
+
+void
+runtime·finishsweep_m(void)
+{
+ uint32 i, sg;
+ MSpan *s;
+
+ // The world is stopped so we should be able to complete the sweeps
+ // quickly.
+ while(runtime·sweepone() != -1)
+ runtime·sweep.npausesweep++;
+
+ // There may be some other spans being swept concurrently that
+ // we need to wait for. If finishsweep_m is done with the world stopped
+ // this code is not required.
+ sg = runtime·mheap.sweepgen;
+ for(i=0; i<runtime·work.nspan; i++) {
+ s = runtime·work.spans[i];
+ if(s->sweepgen == sg) {
+ continue;
+ }
+ if(s->state != MSpanInUse) // Span is not part of the GCed heap so no need to ensure it is swept.
+ continue;
+ runtime·MSpan_EnsureSwept(s);
+ }
+}
+
+// Scan all of the stacks, greying (or graying if in America) the referents
+// but not blackening them since the mark write barrier isn't installed.
+void
+runtime·gcscan_m(void)
+{
+ uint32 i, allglen, oldphase;
+ G *gp, *mastergp, **allg;
+
+ // Grab the g that called us and potentially allow rescheduling.
+ // This allows it to be scanned like other goroutines.
+ mastergp = g->m->curg;
+
+ runtime·casgstatus(mastergp, Grunning, Gwaiting);
+ mastergp->waitreason = runtime·gostringnocopy((byte*)"garbage collection scan");
+
+ // Span sweeping has been done by finishsweep_m.
+ // Long term we will want to make this goroutine runnable
+ // by placing it onto a scanenqueue state and then calling
+ // runtime·restartg(mastergp) to make it Grunnable.
+ // At the bottom we will want to return this p back to the scheduler.
+
+ oldphase = runtime·gcphase;
+
+ runtime·lock(&runtime·allglock);
+ allglen = runtime·allglen;
+ allg = runtime·allg;
+ // Prepare flag indicating that the scan has not been completed.
+ for(i = 0; i < allglen; i++) {
+ gp = allg[i];
+ gp->gcworkdone = false; // set to true in gcphasework
+ }
+ runtime·unlock(&runtime·allglock);
+
+ runtime·work.nwait = 0;
+ runtime·work.ndone = 0;
+ runtime·work.nproc = 1; // For now do not do this in parallel.
+ runtime·gcphase = GCscan;
+ // ackgcphase is not needed since we are not scanning running goroutines.
+ runtime·parforsetup(runtime·work.markfor, runtime·work.nproc, RootCount + allglen, nil, false, markroot);
+ runtime·parfordo(runtime·work.markfor);
+
+ runtime·lock(&runtime·allglock);
+
+ allg = runtime·allg;
+ // Check that gc work is done.
+ for(i = 0; i < allglen; i++) {
+ gp = allg[i];
+ if(!gp->gcworkdone) {
+ runtime·throw("scan missed a g");
+ }
+ }
+ runtime·unlock(&runtime·allglock);
+
+ runtime·gcphase = oldphase;
+ runtime·casgstatus(mastergp, Gwaiting, Grunning);
+ // Let the g that called us continue to run.
+}
+
+// Mark all objects that are known about.
+void
+runtime·gcmark_m(void)
+{
+ scanblock(nil, 0, nil);
+}
+
+// For now this must be bracketed with a stoptheworld and a starttheworld to ensure
+// all go routines see the new barrier.
+void
+runtime·gcinstallmarkwb_m(void)
+{
+ runtime·gcphase = GCmark;
+}
+
+// For now this must be bracketed with a stoptheworld and a starttheworld to ensure
+// all go routines see the new barrier.
+void
+runtime·gcinstalloffwb_m(void)
+{
+ runtime·gcphase = GCoff;
}
static void
@@ -1385,9 +2031,9 @@ gc(struct gc_args *args)
int64 t0, t1, t2, t3, t4;
uint64 heap0, heap1, obj;
GCStats stats;
-
- if(DebugPtrs)
- runtime·printf("GC start\n");
+ uint32 oldphase;
+ uint32 i;
+ G *gp;
if(runtime·debug.allocfreetrace)
runtime·tracegc();
@@ -1400,11 +2046,10 @@ gc(struct gc_args *args)
if(runtime·debug.gctrace)
t1 = runtime·nanotime();
- // Sweep what is not sweeped by bgsweep.
- while(runtime·sweepone() != -1)
- runtime·sweep.npausesweep++;
+ if(!checkmark)
+ runtime·finishsweep_m(); // skip during checkmark debug phase.
- // Cache runtime.mheap.allspans in work.spans to avoid conflicts with
+ // 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:
@@ -1421,10 +2066,19 @@ gc(struct gc_args *args)
runtime·work.spans = runtime·mheap.allspans;
runtime·work.nspan = runtime·mheap.nspan;
runtime·unlock(&runtime·mheap.lock);
+ oldphase = runtime·gcphase;
runtime·work.nwait = 0;
runtime·work.ndone = 0;
- runtime·work.nproc = runtime·gcprocs();
+ runtime·work.nproc = runtime·gcprocs();
+ runtime·gcphase = GCmarktermination;
+
+ // World is stopped so allglen will not change.
+ for(i = 0; i < runtime·allglen; i++) {
+ gp = runtime·allg[i];
+ gp->gcworkdone = false; // set to true in gcphasework
+ }
+
runtime·parforsetup(runtime·work.markfor, runtime·work.nproc, RootCount + runtime·allglen, nil, false, markroot);
if(runtime·work.nproc > 1) {
runtime·noteclear(&runtime·work.alldone);
@@ -1437,8 +2091,15 @@ gc(struct gc_args *args)
gchelperstart();
runtime·parfordo(runtime·work.markfor);
+
scanblock(nil, 0, nil);
+ if(runtime·work.full)
+ runtime·throw("runtime·work.full != nil");
+ if(runtime·work.partial)
+ runtime·throw("runtime·work.partial != nil");
+
+ runtime·gcphase = oldphase;
t3 = 0;
if(runtime·debug.gctrace)
t3 = runtime·nanotime();
@@ -1499,6 +2160,16 @@ gc(struct gc_args *args)
// 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);
+
+ if(gccheckmarkenable) {
+ if(!checkmark) {
+ // first half of two-pass; don't set up sweep
+ runtime·unlock(&runtime·mheap.lock);
+ return;
+ }
+ checkmark = false; // done checking marks
+ }
+
// Cache the current array for sweeping.
runtime·mheap.gcspans = runtime·mheap.allspans;
runtime·mheap.sweepgen += 2;
@@ -1508,6 +2179,7 @@ gc(struct gc_args *args)
runtime·sweep.spanidx = 0;
runtime·unlock(&runtime·mheap.lock);
+
if(ConcurrentSweep && !args->eagersweep) {
runtime·lock(&runtime·gclock);
if(runtime·sweep.g == nil)
@@ -1527,9 +2199,6 @@ gc(struct gc_args *args)
runtime·mProf_GC();
g->m->traceback = 0;
-
- if(DebugPtrs)
- runtime·printf("GC end\n");
}
extern uintptr runtime·sizeof_C_MStats;
@@ -1784,7 +2453,7 @@ runtime·unrollgcprog_m(void)
Type *typ;
byte *mask, *prog;
uintptr pos;
- uint32 x;
+ uintptr x;
typ = g->m->ptrarg[0];
g->m->ptrarg[0] = nil;
@@ -1802,9 +2471,11 @@ runtime·unrollgcprog_m(void)
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);
+ x = *(uintptr*)mask;
+ ((byte*)&x)[0] = 1;
+ runtime·atomicstorep((void**)mask, (void*)x);
}
runtime·unlock(&lock);
}
diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go
index 3a7204b54..dc4eec519 100644
--- a/src/runtime/mgc0.go
+++ b/src/runtime/mgc0.go
@@ -83,54 +83,139 @@ func bgsweep() {
}
}
+const (
+ _PoisonGC = 0xf969696969696969 & (1<<(8*ptrSize) - 1)
+ _PoisonStack = 0x6868686868686868 & (1<<(8*ptrSize) - 1)
+)
+
// NOTE: Really dst *unsafe.Pointer, src unsafe.Pointer,
// but if we do that, Go inserts a write barrier on *dst = src.
//go:nosplit
func writebarrierptr(dst *uintptr, src uintptr) {
*dst = src
+ writebarrierptr_nostore(dst, src)
+}
+
+// Like writebarrierptr, but the store has already been applied.
+// Do not reapply.
+//go:nosplit
+func writebarrierptr_nostore(dst *uintptr, src uintptr) {
+ if getg() == nil { // very low-level startup
+ return
+ }
+
+ if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) {
+ onM(func() { gothrow("bad pointer in write barrier") })
+ }
+
+ mp := acquirem()
+ if mp.inwb || mp.dying > 0 {
+ releasem(mp)
+ return
+ }
+ mp.inwb = true
+ oldscalar0 := mp.scalararg[0]
+ oldscalar1 := mp.scalararg[1]
+ mp.scalararg[0] = uintptr(unsafe.Pointer(dst))
+ mp.scalararg[1] = src
+ onM_signalok(gcmarkwb_m)
+ mp.scalararg[0] = oldscalar0
+ mp.scalararg[1] = oldscalar1
+ mp.inwb = false
+ releasem(mp)
}
//go:nosplit
func writebarrierstring(dst *[2]uintptr, src [2]uintptr) {
- dst[0] = src[0]
+ writebarrierptr(&dst[0], src[0])
dst[1] = src[1]
}
//go:nosplit
func writebarrierslice(dst *[3]uintptr, src [3]uintptr) {
- dst[0] = src[0]
+ writebarrierptr(&dst[0], src[0])
dst[1] = src[1]
dst[2] = src[2]
}
//go:nosplit
func writebarrieriface(dst *[2]uintptr, src [2]uintptr) {
- dst[0] = src[0]
- dst[1] = src[1]
-}
-
-//go:nosplit
-func writebarrierfat2(dst *[2]uintptr, _ *byte, src [2]uintptr) {
- dst[0] = src[0]
- dst[1] = src[1]
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
}
-//go:nosplit
-func writebarrierfat3(dst *[3]uintptr, _ *byte, src [3]uintptr) {
- dst[0] = src[0]
- dst[1] = src[1]
- dst[2] = src[2]
-}
+//go:generate go run wbfat_gen.go -- wbfat.go
+//
+// The above line generates multiword write barriers for
+// all the combinations of ptr+scalar up to four words.
+// The implementations are written to wbfat.go.
//go:nosplit
-func writebarrierfat4(dst *[4]uintptr, _ *byte, src [4]uintptr) {
- dst[0] = src[0]
- dst[1] = src[1]
- dst[2] = src[2]
- dst[3] = src[3]
+func writebarrierfat(typ *_type, dst, src unsafe.Pointer) {
+ mask := loadPtrMask(typ)
+ nptr := typ.size / ptrSize
+ for i := uintptr(0); i < nptr; i += 2 {
+ bits := mask[i/2]
+ if (bits>>2)&_BitsMask == _BitsPointer {
+ writebarrierptr((*uintptr)(dst), *(*uintptr)(src))
+ } else {
+ *(*uintptr)(dst) = *(*uintptr)(src)
+ }
+ dst = add(dst, ptrSize)
+ src = add(src, ptrSize)
+ if i+1 == nptr {
+ break
+ }
+ bits >>= 4
+ if (bits>>2)&_BitsMask == _BitsPointer {
+ writebarrierptr((*uintptr)(dst), *(*uintptr)(src))
+ } else {
+ *(*uintptr)(dst) = *(*uintptr)(src)
+ }
+ dst = add(dst, ptrSize)
+ src = add(src, ptrSize)
+ }
}
//go:nosplit
-func writebarrierfat(typ *_type, dst, src unsafe.Pointer) {
- memmove(dst, src, typ.size)
+func writebarriercopy(typ *_type, dst, src slice) int {
+ n := dst.len
+ if n > src.len {
+ n = src.len
+ }
+ if n == 0 {
+ return 0
+ }
+ dstp := unsafe.Pointer(dst.array)
+ srcp := unsafe.Pointer(src.array)
+
+ if uintptr(srcp) < uintptr(dstp) && uintptr(srcp)+uintptr(n)*typ.size > uintptr(dstp) {
+ // Overlap with src before dst.
+ // Copy backward, being careful not to move dstp/srcp
+ // out of the array they point into.
+ dstp = add(dstp, uintptr(n-1)*typ.size)
+ srcp = add(srcp, uintptr(n-1)*typ.size)
+ i := uint(0)
+ for {
+ writebarrierfat(typ, dstp, srcp)
+ if i++; i >= n {
+ break
+ }
+ dstp = add(dstp, -typ.size)
+ srcp = add(srcp, -typ.size)
+ }
+ } else {
+ // Copy forward, being careful not to move dstp/srcp
+ // out of the array they point into.
+ i := uint(0)
+ for {
+ writebarrierfat(typ, dstp, srcp)
+ if i++; i >= n {
+ break
+ }
+ dstp = add(dstp, typ.size)
+ srcp = add(srcp, typ.size)
+ }
+ }
+ return int(n)
}
diff --git a/src/runtime/mgc0.h b/src/runtime/mgc0.h
index 64f818914..519d7206e 100644
--- a/src/runtime/mgc0.h
+++ b/src/runtime/mgc0.h
@@ -45,8 +45,12 @@ enum {
// If you change these, also change scanblock.
// scanblock does "if(bits == BitsScalar || bits == BitsDead)" as "if(bits <= BitsScalar)".
BitsDead = 0,
- BitsScalar = 1,
- BitsPointer = 2,
+ BitsScalar = 1, // 01
+ BitsPointer = 2, // 10
+ BitsCheckMarkXor = 1, // 10
+ BitsScalarMarked = BitsScalar ^ BitsCheckMarkXor, // 00
+ BitsPointerMarked = BitsPointer ^ BitsCheckMarkXor, // 11
+
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.
@@ -56,7 +60,7 @@ enum {
BitsEface = 3,
// 64 bytes cover objects of size 1024/512 on 64/32 bits, respectively.
- MaxGCMask = 64,
+ MaxGCMask = 65536, // TODO(rsc): change back to 64
};
// Bits in per-word bitmap.
diff --git a/src/runtime/noasm_arm.go b/src/runtime/noasm.go
index dd3ef8267..43c16860b 100644
--- a/src/runtime/noasm_arm.go
+++ b/src/runtime/noasm.go
@@ -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 {
diff --git a/src/runtime/os_darwin.c b/src/runtime/os_darwin.c
index bbd29282b..b866863d0 100644
--- a/src/runtime/os_darwin.c
+++ b/src/runtime/os_darwin.c
@@ -135,7 +135,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_dragonfly.c b/src/runtime/os_dragonfly.c
index e372205ec..051192ad3 100644
--- a/src/runtime/os_dragonfly.c
+++ b/src/runtime/os_dragonfly.c
@@ -195,7 +195,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_freebsd.c b/src/runtime/os_freebsd.c
index a513cb604..1c126547a 100644
--- a/src/runtime/os_freebsd.c
+++ b/src/runtime/os_freebsd.c
@@ -203,7 +203,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_linux.c b/src/runtime/os_linux.c
index 0d8ffc995..cc23774e3 100644
--- a/src/runtime/os_linux.c
+++ b/src/runtime/os_linux.c
@@ -49,9 +49,22 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
runtime·futex(addr, FUTEX_WAIT, val, nil, nil, 0);
return;
}
- // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
+
+ // 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.
+ // Sorry for the #ifdef.
+ // For what it's worth, the #ifdef eliminated an implicit little-endian assumption.
+#ifdef _64BIT
+ ts.tv_sec = ns / 1000000000LL;
+ ts.tv_nsec = ns % 1000000000LL;
+#else
ts.tv_nsec = 0;
ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec);
+#endif
runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
}
@@ -98,19 +111,22 @@ static int32
getproccount(void)
{
uintptr buf[16], t;
- int32 r, cnt, i;
+ int32 r, n, i;
- cnt = 0;
r = runtime·sched_getaffinity(0, sizeof(buf), buf);
- if(r > 0)
+ if(r <= 0)
+ return 1;
+ n = 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);
+ while(t != 0) {
+ n += t&1;
+ t >>= 1;
+ }
}
-
- return cnt ? cnt : 1;
+ if(n < 1)
+ n = 1;
+ return n;
}
// Clone, the Linux rfork.
@@ -217,7 +233,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
@@ -298,7 +317,8 @@ runtime·setsig(int32 i, GoSighandler *fn, bool restart)
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
sa.sa_handler = fn;
- if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
+ // Qemu rejects rt_sigaction of SIGRTMAX (64).
+ if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0 && i != 64)
runtime·throw("rt_sigaction failure");
}
diff --git a/src/runtime/os_nacl.c b/src/runtime/os_nacl.c
index 14b558303..ad72cc7c6 100644
--- a/src/runtime/os_nacl.c
+++ b/src/runtime/os_nacl.c
@@ -20,7 +20,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_netbsd.c b/src/runtime/os_netbsd.c
index 58e5bedf2..28929ea57 100644
--- a/src/runtime/os_netbsd.c
+++ b/src/runtime/os_netbsd.c
@@ -271,7 +271,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_openbsd.c b/src/runtime/os_openbsd.c
index eebaa13ee..960aaffff 100644
--- a/src/runtime/os_openbsd.c
+++ b/src/runtime/os_openbsd.c
@@ -217,7 +217,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_plan9.c b/src/runtime/os_plan9.c
index f8c543f6f..18460fc12 100644
--- a/src/runtime/os_plan9.c
+++ b/src/runtime/os_plan9.c
@@ -20,12 +20,18 @@ runtime·mpreinit(M *mp)
{
// Initialize stack and goroutine for note handling.
mp->gsignal = runtime·malg(32*1024);
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
+
mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan);
+ runtime·writebarrierptr_nostore(&mp->notesig, mp->notesig);
// Initialize stack for handling strings from the
// errstr system call, as used in package syscall.
mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan);
+ runtime·writebarrierptr_nostore(&mp->errstr, mp->errstr);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_solaris.c b/src/runtime/os_solaris.c
index e16b8e637..bee91d8e6 100644
--- a/src/runtime/os_solaris.c
+++ b/src/runtime/os_solaris.c
@@ -176,7 +176,10 @@ void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
+ runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal);
+
mp->gsignal->m = mp;
+ runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m);
}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/panic.c b/src/runtime/panic.c
index 24eb6dbfe..46683b2b0 100644
--- a/src/runtime/panic.c
+++ b/src/runtime/panic.c
@@ -70,7 +70,7 @@ runtime·recovery_m(G *gp)
// (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')
+ if(thechar == '5' || thechar == '9')
gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr);
else
gp->sched.sp = (uintptr)argp - 2*sizeof(uintptr);
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index 685ff5ca0..91b5da294 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -61,7 +61,7 @@ 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()
@@ -494,12 +494,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/print1.go b/src/runtime/print1.go
index 8f8268873..3d812bd04 100644
--- a/src/runtime/print1.go
+++ b/src/runtime/print1.go
@@ -41,7 +41,31 @@ func snprintf(dst *byte, n int32, s *byte) {
gp.writebuf = nil
}
-//var debuglock mutex
+var debuglock mutex
+
+// The compiler emits calls to printlock and printunlock around
+// the multiple calls that implement a single Go print or println
+// statement. Some of the print helpers (printsp, for example)
+// call print recursively. There is also the problem of a crash
+// happening during the print routines and needing to acquire
+// the print lock to print information about the crash.
+// For both these reasons, let a thread acquire the printlock 'recursively'.
+
+func printlock() {
+ mp := getg().m
+ mp.printlock++
+ if mp.printlock == 1 {
+ lock(&debuglock)
+ }
+}
+
+func printunlock() {
+ mp := getg().m
+ mp.printlock--
+ if mp.printlock == 0 {
+ unlock(&debuglock)
+ }
+}
// write to goroutine-local buffer if diverting output,
// or else standard error.
@@ -80,7 +104,7 @@ func printnl() {
// Very simple printf. Only for debugging prints.
// Do not add to this without checking with Rob.
func vprintf(str string, arg unsafe.Pointer) {
- //lock(&debuglock);
+ printlock()
s := bytes(str)
start := 0
@@ -160,7 +184,7 @@ func vprintf(str string, arg unsafe.Pointer) {
gwrite(s[start:i])
}
- //unlock(&debuglock);
+ printunlock()
}
func printpc(p unsafe.Pointer) {
diff --git a/src/runtime/proc.c b/src/runtime/proc.c
index 91e3fe16d..ce39db4ab 100644
--- a/src/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -423,13 +423,7 @@ runtime·casgstatus(G *gp, uint32 oldval, uint32 newval)
// 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);
- }
+
}
}
@@ -504,6 +498,13 @@ runtime·stopg(G *gp)
return false;
case Grunning:
+ if(runtime·gcphase == GCscan) {
+ gp->gcworkdone = true;
+ return false;
+ // Running routines not scanned during
+ // GCscan phase, we only scan non-running routines.
+ }
+
// Claim goroutine, so we aren't racing with a status
// transition away from Grunning.
if(!runtime·castogscanstatus(gp, Grunning, Gscanrunning))
@@ -581,9 +582,10 @@ mquiesce(G *gpmaster)
uint32 status;
uint32 activeglen;
- activeglen = runtime·allglen;
// enqueue the calling goroutine.
runtime·restartg(gpmaster);
+
+ activeglen = runtime·allglen;
for(i = 0; i < activeglen; i++) {
gp = runtime·allg[i];
if(runtime·readgstatus(gp) == Gdead)
@@ -874,7 +876,9 @@ runtime·allocm(P *p)
mp->g0 = runtime·malg(-1);
else
mp->g0 = runtime·malg(8192);
+ runtime·writebarrierptr_nostore(&mp->g0, mp->g0);
mp->g0->m = mp;
+ runtime·writebarrierptr_nostore(&mp->g0->m, mp->g0->m);
if(p == g->m->p)
releasep();
@@ -1058,7 +1062,7 @@ runtime·dropm(void)
unlockextra(mp);
}
-#define MLOCKED ((M*)1)
+#define MLOCKED 1
// lockextra locks the extra list and returns the list head.
// The caller must unlock the list by storing a new list head
@@ -1069,28 +1073,28 @@ runtime·dropm(void)
static M*
lockextra(bool nilokay)
{
- M *mp;
+ uintptr mpx;
void (*yield)(void);
for(;;) {
- mp = runtime·atomicloadp(&runtime·extram);
- if(mp == MLOCKED) {
+ mpx = runtime·atomicloaduintptr((uintptr*)&runtime·extram);
+ if(mpx == MLOCKED) {
yield = runtime·osyield;
yield();
continue;
}
- if(mp == nil && !nilokay) {
+ if(mpx == 0 && !nilokay) {
runtime·usleep(1);
continue;
}
- if(!runtime·casp(&runtime·extram, mp, MLOCKED)) {
+ if(!runtime·casuintptr((uintptr*)&runtime·extram, mpx, MLOCKED)) {
yield = runtime·osyield;
yield();
continue;
}
break;
}
- return mp;
+ return (M*)mpx;
}
#pragma textflag NOSPLIT
@@ -1915,6 +1919,7 @@ exitsyscallfast(void)
// Freezetheworld sets stopwait but does not retake P's.
if(runtime·sched.stopwait) {
+ g->m->mcache = nil;
g->m->p = nil;
return false;
}
@@ -1927,6 +1932,7 @@ exitsyscallfast(void)
return true;
}
// Try to get any other idle P.
+ g->m->mcache = nil;
g->m->p = nil;
if(runtime·sched.pidle) {
fn = exitsyscallfast_pidle;
@@ -2122,7 +2128,7 @@ runtime·newproc(int32 siz, FuncVal* fn, ...)
byte *argp;
void (*mfn)(void);
- if(thechar == '5')
+ if(thechar == '5' || thechar == '9')
argp = (byte*)(&fn+2); // skip caller's saved LR
else
argp = (byte*)(&fn+1);
@@ -2182,7 +2188,7 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
sp -= 4*sizeof(uintreg); // extra space in case of reads slightly beyond frame
sp -= siz;
runtime·memmove(sp, argp, narg);
- if(thechar == '5') {
+ if(thechar == '5' || thechar == '9') {
// caller's LR
sp -= sizeof(void*);
*(void**)sp = nil;
@@ -2615,6 +2621,8 @@ runtime·setcpuprofilerate_m(void)
P *runtime·newP(void);
// Change number of processors. The world is stopped, sched is locked.
+// gcworkbufs are not being modified by either the GC or
+// the write barrier code.
static void
procresize(int32 new)
{
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 5b8c7d8ae..f41ffbff3 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -165,6 +165,9 @@ func acquireSudog() *sudog {
// which keeps the garbage collector from being invoked.
mp := acquirem()
p := new(sudog)
+ if p.elem != nil {
+ gothrow("acquireSudog: found p.elem != nil after new")
+ }
releasem(mp)
return p
}
diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s
index bdea28c7c..15b18ff8f 100644
--- a/src/runtime/race_amd64.s
+++ b/src/runtime/race_amd64.s
@@ -140,20 +140,20 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0
MOVQ g_racectx(R14), RARG0 // goroutine context
// Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss).
CMPQ RARG1, runtime·racearenastart(SB)
- JB racecalladdr_data
+ JB data
CMPQ RARG1, runtime·racearenaend(SB)
- JB racecalladdr_call
-racecalladdr_data:
+ JB call
+data:
MOVQ $runtime·noptrdata(SB), R13
CMPQ RARG1, R13
- JB racecalladdr_ret
+ JB ret
MOVQ $runtime·enoptrbss(SB), R13
CMPQ RARG1, R13
- 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)
@@ -335,9 +335,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
diff --git a/src/runtime/rt0_linux_power64.s b/src/runtime/rt0_linux_power64.s
new file mode 100644
index 000000000..970b6a673
--- /dev/null
+++ b/src/runtime/rt0_linux_power64.s
@@ -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
index 000000000..85ce84733
--- /dev/null
+++ b/src/runtime/rt0_linux_power64le.s
@@ -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)
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
index c823691ec..f19f8e4be 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -185,6 +185,7 @@ runtime·check(void)
float64 j, j1;
byte *k, *k1;
uint16* l;
+ byte m[4];
struct x1 {
byte x;
};
@@ -236,6 +237,11 @@ runtime·check(void)
if(k != k1)
runtime·throw("casp3");
+ m[0] = m[1] = m[2] = m[3] = 0x1;
+ runtime·atomicor8(&m[1], 0xf0);
+ if (m[0] != 0x1 || m[1] != 0xf1 || m[2] != 0x1 || m[3] != 0x1)
+ runtime·throw("atomicor8");
+
*(uint64*)&j = ~0ULL;
if(j == j)
runtime·throw("float64nan");
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 977c4547d..330ed429b 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -94,6 +94,7 @@ typedef struct PollDesc PollDesc;
typedef struct DebugVars DebugVars;
typedef struct ForceGCState ForceGCState;
typedef struct Stack Stack;
+typedef struct Workbuf Workbuf;
/*
* Per-CPU declaration.
@@ -304,7 +305,7 @@ struct G
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
+ bool throwsplit; // must not split stack
int8 raceignore; // ignore race detection events
M* m; // for debuggers, but offset not hard-coded
M* lockedm;
@@ -344,6 +345,8 @@ struct M
int32 helpgc;
bool spinning; // M is out of work and is actively looking for work
bool blocked; // M is blocked on a Note
+ bool inwb; // M is executing a write barrier
+ int8 printlock;
uint32 fastrand;
uint64 ncgocall; // number of cgo calls in total
int32 ncgo; // number of cgo calls currently in progress
@@ -570,9 +573,10 @@ enum {
#endif
// Lock-free stack node.
+// Also known to export_test.go.
struct LFNode
{
- LFNode *next;
+ uint64 next;
uintptr pushcnt;
};
@@ -598,6 +602,16 @@ struct ParFor
uint64 nsleep;
};
+enum {
+ WorkbufSize = 4*1024,
+};
+struct Workbuf
+{
+ LFNode node; // must be first
+ uintptr nobj;
+ byte* obj[(WorkbufSize-sizeof(LFNode)-sizeof(uintptr))/PtrSize];
+};
+
// Track memory allocated by code not written in Go during a cgo call,
// so that the garbage collector can see them.
struct CgoMal
@@ -620,12 +634,14 @@ struct DebugVars
// 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
+{ // Action WB installation
+ GCoff = 0, // stop and start no wb
+ GCquiesce, // stop and start no wb
+ GCstw, // stop the ps nop
+ GCscan, // scan the stacks prior to marking
+ GCmark, // mark use wbufs from GCscan and globals, scan the stacks, then go to GCtermination
+ GCmarktermination, // mark termination detection. Allocate black, Ps help out GC
+ GCsweep, // stop and start nop
};
struct ForceGCState
@@ -636,6 +652,7 @@ struct ForceGCState
};
extern uint32 runtime·gcphase;
+extern Mutex runtime·allglock;
/*
* defined macros
@@ -666,6 +683,7 @@ enum {
uint32 runtime·readgstatus(G*);
void runtime·casgstatus(G*, uint32, uint32);
+bool runtime·castogscanstatus(G*, uint32, uint32);
void runtime·quiesce(G*);
bool runtime·stopg(G*);
void runtime·restartg(G*);
@@ -882,6 +900,7 @@ int32 runtime·round2(int32 x); // round x up to a power of 2.
bool runtime·cas(uint32*, uint32, uint32);
bool runtime·cas64(uint64*, uint64, uint64);
bool runtime·casp(void**, void*, void*);
+bool runtime·casuintptr(uintptr*, uintptr, uintptr);
// Don't confuse with XADD x86 instruction,
// this one is actually 'addx', that is, add-and-fetch.
uint32 runtime·xadd(uint32 volatile*, int32);
@@ -1108,6 +1127,8 @@ void runtime·osyield(void);
void runtime·lockOSThread(void);
void runtime·unlockOSThread(void);
+void runtime·writebarrierptr_nostore(void*, void*);
+
bool runtime·showframe(Func*, G*);
void runtime·printcreatedby(G*);
diff --git a/src/runtime/select.go b/src/runtime/select.go
index efe68c1f5..d703e1d79 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -377,12 +377,7 @@ loop:
// iterating through the linked list they are in reverse order.
cas = nil
sglist = gp.waiting
- // Clear all selectdone and elem before unlinking from gp.waiting.
- // They must be cleared before being put back into the sudog cache.
- // Clear before unlinking, because if a stack copy happens after the unlink,
- // they will not be updated, they will be left pointing to the old stack,
- // which creates dangling pointers, which may be detected by the
- // garbage collector.
+ // Clear all elem before unlinking from gp.waiting.
for sg1 := gp.waiting; sg1 != nil; sg1 = sg1.waitlink {
sg1.selectdone = nil
sg1.elem = nil
diff --git a/src/runtime/signal_linux_power64.h b/src/runtime/signal_linux_power64.h
new file mode 100644
index 000000000..840648920
--- /dev/null
+++ b/src/runtime/signal_linux_power64.h
@@ -0,0 +1,49 @@
+// Copyright 2014 The Go 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)->regs)
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
+#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
+#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
+#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
+#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
+#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
+#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
+#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
+#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
+#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
+#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
+#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
+#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
+#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
+#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
+#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
+#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
+
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
+#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
+#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
+#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
+#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
+#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
+
+#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
+#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)
diff --git a/src/runtime/signal_linux_power64le.h b/src/runtime/signal_linux_power64le.h
new file mode 100644
index 000000000..840648920
--- /dev/null
+++ b/src/runtime/signal_linux_power64le.h
@@ -0,0 +1,49 @@
+// Copyright 2014 The Go 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)->regs)
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
+#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
+#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
+#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
+#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
+#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
+#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
+#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
+#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
+#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
+#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
+#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
+#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
+#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
+#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
+#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
+#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
+
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
+#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
+#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
+#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
+#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
+#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
+
+#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
+#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)
diff --git a/src/runtime/signal_power64x.c b/src/runtime/signal_power64x.c
new file mode 100644
index 000000000..89c5c7848
--- /dev/null
+++ b/src/runtime/signal_power64x.c
@@ -0,0 +1,137 @@
+// Copyright 2014 The Go 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 "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("r0 %X\t", SIG_R0(info, ctxt));
+ runtime·printf("r1 %X\n", SIG_R1(info, ctxt));
+ runtime·printf("r2 %X\t", SIG_R2(info, ctxt));
+ runtime·printf("r3 %X\n", SIG_R3(info, ctxt));
+ runtime·printf("r4 %X\t", SIG_R4(info, ctxt));
+ runtime·printf("r5 %X\n", SIG_R5(info, ctxt));
+ runtime·printf("r6 %X\t", SIG_R6(info, ctxt));
+ runtime·printf("r7 %X\n", SIG_R7(info, ctxt));
+ runtime·printf("r8 %X\t", SIG_R8(info, ctxt));
+ runtime·printf("r9 %X\n", SIG_R9(info, ctxt));
+ runtime·printf("r10 %X\t", SIG_R10(info, ctxt));
+ runtime·printf("r11 %X\n", SIG_R11(info, ctxt));
+ runtime·printf("r12 %X\t", SIG_R12(info, ctxt));
+ runtime·printf("r13 %X\n", SIG_R13(info, ctxt));
+ runtime·printf("r14 %X\t", SIG_R14(info, ctxt));
+ runtime·printf("r15 %X\n", SIG_R15(info, ctxt));
+ runtime·printf("r16 %X\t", SIG_R16(info, ctxt));
+ runtime·printf("r17 %X\n", SIG_R17(info, ctxt));
+ runtime·printf("r18 %X\t", SIG_R18(info, ctxt));
+ runtime·printf("r19 %X\n", SIG_R19(info, ctxt));
+ runtime·printf("r20 %X\t", SIG_R20(info, ctxt));
+ runtime·printf("r21 %X\n", SIG_R21(info, ctxt));
+ runtime·printf("r22 %X\t", SIG_R22(info, ctxt));
+ runtime·printf("r23 %X\n", SIG_R23(info, ctxt));
+ runtime·printf("r24 %X\t", SIG_R24(info, ctxt));
+ runtime·printf("r25 %X\n", SIG_R25(info, ctxt));
+ runtime·printf("r26 %X\t", SIG_R26(info, ctxt));
+ runtime·printf("r27 %X\n", SIG_R27(info, ctxt));
+ runtime·printf("r28 %X\t", SIG_R28(info, ctxt));
+ runtime·printf("r29 %X\n", SIG_R29(info, ctxt));
+ runtime·printf("r30 %X\t", SIG_R30(info, ctxt));
+ runtime·printf("r31 %X\n", SIG_R31(info, ctxt));
+ runtime·printf("pc %X\t", SIG_PC(info, ctxt));
+ runtime·printf("ctr %X\n", SIG_CTR(info, ctxt));
+ runtime·printf("link %X\t", SIG_LINK(info, ctxt));
+ runtime·printf("xer %X\n", SIG_XER(info, ctxt));
+ runtime·printf("ccr %X\t", SIG_CCR(info, ctxt));
+ runtime·printf("trap %X\n", SIG_TRAP(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_LINK(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 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.
+ SIG_SP(info, ctxt) -= sizeof(uintptr);
+ *(uintptr*)SIG_SP(info, ctxt) = SIG_LINK(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_LINK(info, ctxt) = gp->sigpc;
+ // In case we are panicking from external C code
+ SIG_R0(info, ctxt) = 0;
+ SIG_R30(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·traceback(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(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/stack.c b/src/runtime/stack.c
index 072bc242b..ffae73a2a 100644
--- a/src/runtime/stack.c
+++ b/src/runtime/stack.c
@@ -382,8 +382,6 @@ 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;
@@ -415,43 +413,7 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f)
}
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;
+ runtime·throw("adjustpointers: unexpected garbage collection bits");
}
}
}
@@ -587,13 +549,13 @@ adjustsudogs(G *gp, AdjustInfo *adjinfo)
}
// Copies gp's stack to a new stack of a different size.
+// Caller must have changed gp status to Gcopystack.
static void
copystack(G *gp, uintptr newsize)
{
Stack old, new;
uintptr used;
AdjustInfo adjinfo;
- uint32 oldstatus;
bool (*cb)(Stkframe*, void*);
byte *p, *ep;
@@ -637,20 +599,11 @@ copystack(G *gp, uintptr newsize)
}
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;
@@ -700,6 +653,7 @@ void
runtime·newstack(void)
{
int32 oldsize, newsize;
+ uint32 oldstatus;
uintptr sp;
G *gp;
Gobuf morebuf;
@@ -752,6 +706,14 @@ runtime·newstack(void)
runtime·printf("runtime: split stack overflow: %p < %p\n", sp, gp->stack.lo);
runtime·throw("runtime: split stack overflow");
}
+
+ if(gp->sched.ctxt != nil) {
+ // morestack wrote sched.ctxt on its way in here,
+ // without a write barrier. Run the write barrier now.
+ // It is not possible to be preempted between then
+ // and now, so it's okay.
+ runtime·writebarrierptr_nostore(&gp->sched.ctxt, gp->sched.ctxt);
+ }
if(gp->stackguard0 == (uintptr)StackPreempt) {
if(gp == g->m->g0)
@@ -789,12 +751,15 @@ runtime·newstack(void)
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.
+ oldstatus = runtime·readgstatus(gp);
+ oldstatus &= ~Gscan;
+ runtime·casgstatus(gp, oldstatus, Gcopystack); // oldstatus is Gwaiting or Grunnable
+ // The concurrent GC will not scan the stack while we are doing the copy since
+ // the gp is in a Gcopystack status.
copystack(gp, newsize);
if(StackDebug >= 1)
runtime·printf("stack grow done\n");
- runtime·casgstatus(gp, Gwaiting, Grunning);
+ runtime·casgstatus(gp, Gcopystack, Grunning);
runtime·gogo(&gp->sched);
}
@@ -825,6 +790,7 @@ void
runtime·shrinkstack(G *gp)
{
uintptr used, oldsize, newsize;
+ uint32 oldstatus;
if(runtime·readgstatus(gp) == Gdead) {
if(gp->stack.lo != 0) {
@@ -858,8 +824,19 @@ runtime·shrinkstack(G *gp)
#endif
if(StackDebug > 0)
runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uint64)newsize);
+ // This is being done in a Gscan state and was initiated by the GC so no need to move to
+ // the Gcopystate.
+ // The world is stopped, so the goroutine must be Gwaiting or Grunnable,
+ // and what it is is not changing underfoot.
+
+ oldstatus = runtime·readgstatus(gp);
+ oldstatus &= ~Gscan;
+ if(oldstatus != Gwaiting && oldstatus != Grunnable)
+ runtime·throw("status is not Gwaiting or Grunnable");
+ runtime·casgstatus(gp, oldstatus, Gcopystack);
copystack(gp, newsize);
-}
+ runtime·casgstatus(gp, Gcopystack, oldstatus);
+ }
// Do any delayed stack freeing that was queued up during GC.
void
diff --git a/src/runtime/string.c b/src/runtime/string.c
index ed5debc33..475ea2de6 100644
--- a/src/runtime/string.c
+++ b/src/runtime/string.c
@@ -48,7 +48,7 @@ runtime·gostringnocopy(byte *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))
+ if(s.len <= ms || runtime·casuintptr(&runtime·maxstring, ms, s.len))
return s;
}
}
diff --git a/src/runtime/string.go b/src/runtime/string.go
index 0809f89bc..882281605 100644
--- a/src/runtime/string.go
+++ b/src/runtime/string.go
@@ -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[:])
}
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index fe8f9c922..9889567d6 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -106,6 +106,16 @@ func recovery_m(*g)
func mcacheRefill_m()
func largeAlloc_m()
func gc_m()
+func gcscan_m()
+func gcmark_m()
+func gccheckmark_m()
+func gccheckmarkenable_m()
+func gccheckmarkdisable_m()
+func gcinstallmarkwb_m()
+func gcinstalloffwb_m()
+func gcmarknewobject_m()
+func gcmarkwb_m()
+func finishsweep_m()
func scavenge_m()
func setFinalizer_m()
func removeFinalizer_m()
@@ -204,9 +214,6 @@ func write(fd uintptr, p unsafe.Pointer, n int32) int32
func cas(ptr *uint32, old, new uint32) bool
//go:noescape
-func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
-
-//go:noescape
func casuintptr(ptr *uintptr, old, new uintptr) bool
//go:noescape
diff --git a/src/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s
index a961c71a8..3bf8b1d41 100644
--- a/src/runtime/sys_darwin_386.s
+++ b/src/runtime/sys_darwin_386.s
@@ -248,7 +248,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 +275,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
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index bd397d72a..8a8928e06 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -211,7 +211,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 +233,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
diff --git a/src/runtime/sys_dragonfly_386.s b/src/runtime/sys_dragonfly_386.s
index 161eaec19..71ece9ecb 100644
--- a/src/runtime/sys_dragonfly_386.s
+++ b/src/runtime/sys_dragonfly_386.s
@@ -217,7 +217,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 +243,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
diff --git a/src/runtime/sys_freebsd_386.s b/src/runtime/sys_freebsd_386.s
index 2c40fc433..66d03c27d 100644
--- a/src/runtime/sys_freebsd_386.s
+++ b/src/runtime/sys_freebsd_386.s
@@ -197,7 +197,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 +223,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
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 33b91e872..d8d86ffad 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -115,7 +115,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 +124,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 +141,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 +153,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
diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
index bd285f399..033a03642 100644
--- a/src/runtime/sys_linux_arm.s
+++ b/src/runtime/sys_linux_arm.s
@@ -373,20 +373,20 @@ 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
diff --git a/src/runtime/sys_linux_power64x.s b/src/runtime/sys_linux_power64x.s
new file mode 100644
index 000000000..fb24d3e79
--- /dev/null
+++ b/src/runtime/sys_linux_power64x.s
@@ -0,0 +1,383 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build power64 power64le
+
+//
+// System calls and other sys.stuff for Power64, Linux
+//
+
+#include "zasm_GOOS_GOARCH.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
diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s
index 47985f31f..16cd721d9 100644
--- a/src/runtime/sys_nacl_386.s
+++ b/src/runtime/sys_nacl_386.s
@@ -293,7 +293,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 +317,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)
diff --git a/src/runtime/sys_nacl_amd64p32.s b/src/runtime/sys_nacl_amd64p32.s
index 4eb4aacdd..9cfbef6ef 100644
--- a/src/runtime/sys_nacl_amd64p32.s
+++ b/src/runtime/sys_nacl_amd64p32.s
@@ -338,7 +338,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)
diff --git a/src/runtime/sys_nacl_arm.s b/src/runtime/sys_nacl_arm.s
index d354ab483..432deadf4 100644
--- a/src/runtime/sys_nacl_arm.s
+++ b/src/runtime/sys_nacl_arm.s
@@ -269,7 +269,6 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
// restore g
MOVW 20(R13), g
-sigtramp_ret:
// Enable exceptions again.
NACL_SYSCALL(SYS_exception_clear_flag)
diff --git a/src/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s
index 5cda7768a..b1ae5ecee 100644
--- a/src/runtime/sys_openbsd_386.s
+++ b/src/runtime/sys_openbsd_386.s
@@ -186,7 +186,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 +212,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
diff --git a/src/runtime/sys_power64x.c b/src/runtime/sys_power64x.c
new file mode 100644
index 000000000..79d976255
--- /dev/null
+++ b/src/runtime/sys_power64x.c
@@ -0,0 +1,38 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#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) == 0x4b && (inst&3) == 0) {
+ //runtime·printf("runtime: rewind pc=%p to pc=%p\n", gobuf->pc, gobuf->pc + ((int32)(inst<<8)>>8));
+ gobuf->pc += (int32)(inst<<8)>>8;
+ return;
+ }
+ runtime·printf("runtime: pc=%p %x\n", gobuf->pc, inst);
+ runtime·throw("runtime: misuse of rewindmorestack");
+}
+
diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s
index 0ebdab6ee..3981893b0 100644
--- a/src/runtime/sys_solaris_amd64.s
+++ b/src/runtime/sys_solaris_amd64.s
@@ -287,24 +287,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,7 +313,7 @@ usleep1_switch:
MOVQ 0(SP), SP
RET
-usleep1_noswitch:
+noswitch:
// Not a Go-managed thread. Do not switch stack.
CALL AX
RET
diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
index 932fe9dd2..13fb5bdc9 100644
--- a/src/runtime/sys_windows_386.s
+++ b/src/runtime/sys_windows_386.s
@@ -106,7 +106,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 +123,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)
@@ -383,12 +383,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 +396,7 @@ usleep1_switch:
CALL AX
MOVL 0(SP), SP
-usleep1_ret:
+ret:
get_tls(CX)
MOVL g(CX), BP
MOVL g_m(BP), BP
diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
index e6190ce68..8b95f6d6c 100644
--- a/src/runtime/sys_windows_amd64.s
+++ b/src/runtime/sys_windows_amd64.s
@@ -138,7 +138,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 +157,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)
@@ -407,12 +407,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 +420,7 @@ usleep1_switch:
CALL AX
MOVQ 0(SP), SP
-usleep1_ret:
+ret:
MOVQ $0, m_libcallsp(R13)
RET
diff --git a/src/runtime/sys_x86.c b/src/runtime/sys_x86.c
index a450b3e58..edbe47ff4 100644
--- a/src/runtime/sys_x86.c
+++ b/src/runtime/sys_x86.c
@@ -20,6 +20,7 @@ runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt)
gobuf->sp = (uintptr)sp;
gobuf->pc = (uintptr)fn;
gobuf->ctxt = ctxt;
+ runtime·writebarrierptr_nostore(&gobuf->ctxt, ctxt);
}
// Called to rewind context saved during morestack back to beginning of function.
diff --git a/src/runtime/thunk.s b/src/runtime/thunk.s
index 0a0f147c4..1a5b65502 100644
--- a/src/runtime/thunk.s
+++ b/src/runtime/thunk.s
@@ -10,6 +10,12 @@
#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)
diff --git a/src/runtime/wbfat.go b/src/runtime/wbfat.go
new file mode 100644
index 000000000..75c58b26b
--- /dev/null
+++ b/src/runtime/wbfat.go
@@ -0,0 +1,190 @@
+// generated by wbfat_gen.go; use go generate
+
+package runtime
+
+//go:nosplit
+func writebarrierfat01(dst *[2]uintptr, _ *byte, src [2]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+}
+
+//go:nosplit
+func writebarrierfat10(dst *[2]uintptr, _ *byte, src [2]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+}
+
+//go:nosplit
+func writebarrierfat11(dst *[2]uintptr, _ *byte, src [2]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+}
+
+//go:nosplit
+func writebarrierfat001(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ writebarrierptr(&dst[2], src[2])
+}
+
+//go:nosplit
+func writebarrierfat010(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+ dst[2] = src[2]
+}
+
+//go:nosplit
+func writebarrierfat011(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+ writebarrierptr(&dst[2], src[2])
+}
+
+//go:nosplit
+func writebarrierfat100(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+ dst[2] = src[2]
+}
+
+//go:nosplit
+func writebarrierfat101(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+ writebarrierptr(&dst[2], src[2])
+}
+
+//go:nosplit
+func writebarrierfat110(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+ dst[2] = src[2]
+}
+
+//go:nosplit
+func writebarrierfat111(dst *[3]uintptr, _ *byte, src [3]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+ writebarrierptr(&dst[2], src[2])
+}
+
+//go:nosplit
+func writebarrierfat0001(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ dst[2] = src[2]
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat0010(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ writebarrierptr(&dst[2], src[2])
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat0011(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ dst[1] = src[1]
+ writebarrierptr(&dst[2], src[2])
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat0100(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+ dst[2] = src[2]
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat0101(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+ dst[2] = src[2]
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat0110(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+ writebarrierptr(&dst[2], src[2])
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat0111(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ dst[0] = src[0]
+ writebarrierptr(&dst[1], src[1])
+ writebarrierptr(&dst[2], src[2])
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat1000(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+ dst[2] = src[2]
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat1001(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+ dst[2] = src[2]
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat1010(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+ writebarrierptr(&dst[2], src[2])
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat1011(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ dst[1] = src[1]
+ writebarrierptr(&dst[2], src[2])
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat1100(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+ dst[2] = src[2]
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat1101(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+ dst[2] = src[2]
+ writebarrierptr(&dst[3], src[3])
+}
+
+//go:nosplit
+func writebarrierfat1110(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+ writebarrierptr(&dst[2], src[2])
+ dst[3] = src[3]
+}
+
+//go:nosplit
+func writebarrierfat1111(dst *[4]uintptr, _ *byte, src [4]uintptr) {
+ writebarrierptr(&dst[0], src[0])
+ writebarrierptr(&dst[1], src[1])
+ writebarrierptr(&dst[2], src[2])
+ writebarrierptr(&dst[3], src[3])
+}
diff --git a/src/runtime/wbfat_gen.go b/src/runtime/wbfat_gen.go
new file mode 100644
index 000000000..78d5b6271
--- /dev/null
+++ b/src/runtime/wbfat_gen.go
@@ -0,0 +1,41 @@
+// Copyright 2014 The Go 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 (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+)
+
+func main() {
+ flag.Parse()
+ if flag.NArg() > 0 {
+ f, err := os.Create(flag.Arg(0))
+ if err != nil {
+ log.Fatal(err)
+ }
+ os.Stdout = f
+ }
+ fmt.Printf("// generated by wbfat_gen.go; use go generate\n\n")
+ fmt.Printf("package runtime\n")
+ for i := uint(2); i <= 4; i++ {
+ for j := 1; j < 1<<i; j++ {
+ fmt.Printf("\n//go:nosplit\n")
+ fmt.Printf("func writebarrierfat%0*b(dst *[%d]uintptr, _ *byte, src [%d]uintptr) {\n", int(i), j, i, i)
+ for k := uint(0); k < i; k++ {
+ if j&(1<<(i-1-k)) != 0 {
+ fmt.Printf("\twritebarrierptr(&dst[%d], src[%d])\n", k, k)
+ } else {
+ fmt.Printf("\tdst[%d] = src[%d]\n", k, k)
+ }
+ }
+ fmt.Printf("}\n")
+ }
+ }
+}
diff --git a/src/sync/atomic/asm_power64x.s b/src/sync/atomic/asm_power64x.s
new file mode 100644
index 000000000..1130d3c16
--- /dev/null
+++ b/src/sync/atomic/asm_power64x.s
@@ -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)
diff --git a/src/sync/atomic/atomic_test.go b/src/sync/atomic/atomic_test.go
index 9f13af48b..ec573aa8c 100644
--- a/src/sync/atomic/atomic_test.go
+++ b/src/sync/atomic/atomic_test.go
@@ -164,7 +164,7 @@ func TestSwapPointer(t *testing.T) {
x.before = magicptr
x.after = magicptr
var j uintptr
- for delta := uintptr(1); delta+delta > delta; delta += delta {
+ for delta := uintptr(1 << 16); delta+delta > delta; delta += delta {
k := SwapPointer(&x.i, unsafe.Pointer(delta))
if uintptr(x.i) != delta || uintptr(k) != j {
t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
@@ -456,7 +456,7 @@ func TestCompareAndSwapPointer(t *testing.T) {
magicptr := uintptr(m)
x.before = magicptr
x.after = magicptr
- for val := uintptr(1); val+val > val; val += val {
+ for val := uintptr(1 << 16); val+val > val; val += val {
x.i = unsafe.Pointer(val)
if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
t.Fatalf("should have swapped %#x %#x", val, val+1)
@@ -595,7 +595,7 @@ func TestLoadPointer(t *testing.T) {
magicptr := uintptr(m)
x.before = magicptr
x.after = magicptr
- for delta := uintptr(1); delta+delta > delta; delta += delta {
+ for delta := uintptr(1 << 16); delta+delta > delta; delta += delta {
k := LoadPointer(&x.i)
if k != x.i {
t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
@@ -731,7 +731,7 @@ func TestStorePointer(t *testing.T) {
x.before = magicptr
x.after = magicptr
v := unsafe.Pointer(uintptr(0))
- for delta := uintptr(1); delta+delta > delta; delta += delta {
+ for delta := uintptr(1 << 16); delta+delta > delta; delta += delta {
StorePointer(&x.i, unsafe.Pointer(v))
if x.i != v {
t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
diff --git a/src/syscall/asm.s b/src/syscall/asm.s
index d4ca868f1..43561e201 100644
--- a/src/syscall/asm.s
+++ b/src/syscall/asm.s
@@ -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
index 000000000..be8518a45
--- /dev/null
+++ b/src/syscall/asm_linux_power64x.s
@@ -0,0 +1,104 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build 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
diff --git a/src/syscall/mkall.sh b/src/syscall/mkall.sh
index 9cb82a608..febd5a262 100755
--- a/src/syscall/mkall.sh
+++ b/src/syscall/mkall.sh
@@ -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
diff --git a/src/syscall/mkerrors.sh b/src/syscall/mkerrors.sh
index cf0afe0bd..4711f307a 100755
--- a/src/syscall/mkerrors.sh
+++ b/src/syscall/mkerrors.sh
@@ -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
index 000000000..fd043627a
--- /dev/null
+++ b/src/syscall/syscall_linux_power64x.go
@@ -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)
+}
diff --git a/src/syscall/types_linux.go b/src/syscall/types_linux.go
index e8396a41f..5e9f698cf 100644
--- a/src/syscall/types_linux.go
+++ b/src/syscall/types_linux.go
@@ -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
index 000000000..15e0770c1
--- /dev/null
+++ b/src/syscall/zerrors_linux_power64.go
@@ -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
index 000000000..fdecdf24d
--- /dev/null
+++ b/src/syscall/zerrors_linux_power64le.go
@@ -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
index 000000000..7808059cc
--- /dev/null
+++ b/src/syscall/zsyscall_linux_power64.go
@@ -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
index 000000000..7808059cc
--- /dev/null
+++ b/src/syscall/zsyscall_linux_power64le.go
@@ -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
index 000000000..0567fd0ea
--- /dev/null
+++ b/src/syscall/zsysnum_linux_power64.go
@@ -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
index 000000000..52c63e3d3
--- /dev/null
+++ b/src/syscall/zsysnum_linux_power64le.go
@@ -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
index 000000000..204d80685
--- /dev/null
+++ b/src/syscall/ztypes_linux_power64.go
@@ -0,0 +1,602 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+ sizeofPtr = 0x8
+ sizeofShort = 0x2
+ sizeofInt = 0x4
+ sizeofLong = 0x8
+ sizeofLongLong = 0x8
+ PathMax = 0x1000
+)
+
+type (
+ _C_short int16
+ _C_int int32
+ _C_long int64
+ _C_long_long int64
+)
+
+type Timespec struct {
+ Sec int64
+ Nsec int64
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int64
+}
+
+type Timex struct {
+ Modes uint32
+ Pad_cgo_0 [4]byte
+ Offset int64
+ Freq int64
+ Maxerror int64
+ Esterror int64
+ Status int32
+ Pad_cgo_1 [4]byte
+ Constant int64
+ Precision int64
+ Tolerance int64
+ Time Timeval
+ Tick int64
+ Ppsfreq int64
+ Jitter int64
+ Shift int32
+ Pad_cgo_2 [4]byte
+ Stabil int64
+ Jitcnt int64
+ Calcnt int64
+ Errcnt int64
+ Stbcnt int64
+ Tai int32
+ Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+ Utime int64
+ Stime int64
+ Cutime int64
+ Cstime int64
+}
+
+type Utimbuf struct {
+ Actime int64
+ Modtime int64
+}
+
+type Rusage struct {
+ Utime Timeval
+ Stime Timeval
+ Maxrss int64
+ Ixrss int64
+ Idrss int64
+ Isrss int64
+ Minflt int64
+ Majflt int64
+ Nswap int64
+ Inblock int64
+ Oublock int64
+ Msgsnd int64
+ Msgrcv int64
+ Nsignals int64
+ Nvcsw int64
+ Nivcsw int64
+}
+
+type Rlimit struct {
+ Cur uint64
+ Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+ Dev 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
index 000000000..df481f5c7
--- /dev/null
+++ b/src/syscall/ztypes_linux_power64le.go
@@ -0,0 +1,602 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+ sizeofPtr = 0x8
+ sizeofShort = 0x2
+ sizeofInt = 0x4
+ sizeofLong = 0x8
+ sizeofLongLong = 0x8
+ PathMax = 0x1000
+)
+
+type (
+ _C_short int16
+ _C_int int32
+ _C_long int64
+ _C_long_long int64
+)
+
+type Timespec struct {
+ Sec int64
+ Nsec int64
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int64
+}
+
+type Timex struct {
+ Modes uint32
+ Pad_cgo_0 [4]byte
+ Offset int64
+ Freq int64
+ Maxerror int64
+ Esterror int64
+ Status int32
+ Pad_cgo_1 [4]byte
+ Constant int64
+ Precision int64
+ Tolerance int64
+ Time Timeval
+ Tick int64
+ Ppsfreq int64
+ Jitter int64
+ Shift int32
+ Pad_cgo_2 [4]byte
+ Stabil int64
+ Jitcnt int64
+ Calcnt int64
+ Errcnt int64
+ Stbcnt int64
+ Tai int32
+ Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+ Utime int64
+ Stime int64
+ Cutime int64
+ Cstime int64
+}
+
+type Utimbuf struct {
+ Actime int64
+ Modtime int64
+}
+
+type Rusage struct {
+ Utime Timeval
+ Stime Timeval
+ Maxrss int64
+ Ixrss int64
+ Idrss int64
+ Isrss int64
+ Minflt int64
+ Majflt int64
+ Nswap int64
+ Inblock int64
+ Oublock int64
+ Msgsnd int64
+ Msgrcv int64
+ Nsignals int64
+ Nvcsw int64
+ Nivcsw int64
+}
+
+type Rlimit struct {
+ Cur uint64
+ Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+ Dev 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/live.go b/test/live.go
index f15bb74ba..55a1bd35d 100644
--- a/test/live.go
+++ b/test/live.go
@@ -9,20 +9,39 @@
package main
+func printnl()
+
+//go:noescape
+func printpointer(**int)
+
+//go:noescape
+func printintpointer(*int)
+
+//go:noescape
+func printstringpointer(*string)
+
+//go:noescape
+func printstring(string)
+
+//go:noescape
+func printbytepointer(*byte)
+
+func printint(int)
+
func f1() {
var x *int
- print(&x) // ERROR "live at call to printpointer: x$"
- print(&x) // ERROR "live at call to printpointer: x$"
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
}
func f2(b bool) {
if b {
- print(0) // nothing live here
+ printint(0) // nothing live here
return
}
var x *int
- print(&x) // ERROR "live at call to printpointer: x$"
- print(&x) // ERROR "live at call to printpointer: x$"
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
}
func f3(b bool) {
@@ -30,22 +49,22 @@ func f3(b bool) {
// live throughout the function, to avoid being poisoned
// in GODEBUG=gcdead=1 mode.
- print(0) // ERROR "live at call to printint: x y$"
+ printint(0) // ERROR "live at call to printint: x y$"
if b == false {
- print(0) // ERROR "live at call to printint: x y$"
+ printint(0) // ERROR "live at call to printint: x y$"
return
}
if b {
var x *int
- print(&x) // ERROR "live at call to printpointer: x y$"
- print(&x) // ERROR "live at call to printpointer: x y$"
+ printpointer(&x) // ERROR "live at call to printpointer: x y$"
+ printpointer(&x) // ERROR "live at call to printpointer: x y$"
} else {
var y *int
- print(&y) // ERROR "live at call to printpointer: x y$"
- print(&y) // ERROR "live at call to printpointer: x y$"
+ printpointer(&y) // ERROR "live at call to printpointer: x y$"
+ printpointer(&y) // ERROR "live at call to printpointer: x y$"
}
- print(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
+ printint(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
}
// The old algorithm treated x as live on all code that
@@ -56,20 +75,20 @@ func f3(b bool) {
func f4(b1, b2 bool) { // x not live here
if b2 {
- print(0) // x not live here
+ printint(0) // x not live here
return
}
var z **int
x := new(int)
*x = 42
z = &x
- print(**z) // ERROR "live at call to printint: x z$"
+ printint(**z) // ERROR "live at call to printint: x z$"
if b2 {
- print(1) // ERROR "live at call to printint: x$"
+ printint(1) // ERROR "live at call to printint: x$"
return
}
for {
- print(**z) // ERROR "live at call to printint: x z$"
+ printint(**z) // ERROR "live at call to printint: x z$"
}
}
@@ -84,7 +103,7 @@ func f5(b1 bool) {
*y = 54
z = &y
}
- print(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
+ printint(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
}
// confusion about the _ result used to cause spurious "live at entry to f6: _".
@@ -155,8 +174,8 @@ func f11b() *int {
// At this point p is dead: the code here cannot
// get to the bottom of the function.
// This used to have a spurious "live at call to printint: p".
- print(1) // nothing live here!
- select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
+ printint(1) // nothing live here!
+ select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
case <-c: // ERROR "live at call to selectrecv: autotmp"
return nil
case <-c: // ERROR "live at call to selectrecv: autotmp"
@@ -172,8 +191,8 @@ func f11c() *int {
if b {
// Unlike previous, the cases in this select fall through,
// so we can get to the println, so p is not dead.
- print(1) // ERROR "live at call to printint: p"
- select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p"
+ printint(1) // ERROR "live at call to printint: p"
+ select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p"
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
}
@@ -209,7 +228,7 @@ func h13(string, string) string
func f14() {
x := g14()
- print(&x) // ERROR "live at call to printpointer: x"
+ printstringpointer(&x) // ERROR "live at call to printstringpointer: x"
}
func g14() string
@@ -217,8 +236,8 @@ func g14() string
func f15() {
var x string
_ = &x
- x = g15() // ERROR "live at call to g15: x"
- print(x) // ERROR "live at call to printstring: x"
+ x = g15() // ERROR "live at call to g15: x"
+ printstring(x) // ERROR "live at call to printstring: x"
}
func g15() string
@@ -282,7 +301,7 @@ func f18() {
}
z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- print(z)
+ printbytepointer(z)
}
var ch chan *byte
@@ -296,7 +315,7 @@ func f19() {
}
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
- print(z)
+ printbytepointer(z)
}
func f20() {
@@ -316,7 +335,7 @@ func f21() {
}
z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- print(z)
+ printbytepointer(z)
}
func f23() {
@@ -328,7 +347,8 @@ func f23() {
}
z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
- print(z, ok)
+ printbytepointer(z)
+ print(ok)
}
func f24() {
@@ -350,8 +370,8 @@ func f25(b bool) {
}
var x string
_ = &x
- x = g15() // ERROR "live at call to g15: x"
- print(x) // ERROR "live at call to printstring: x"
+ x = g15() // ERROR "live at call to g15: x"
+ printstring(x) // ERROR "live at call to printstring: x"
} // ERROR "live at call to deferreturn: x"
func g25()
@@ -366,7 +386,7 @@ func f26(b bool) {
}
print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
- println()
+ printnl()
}
//go:noescape
@@ -381,7 +401,7 @@ func f27(b bool) {
}
call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
- println()
+ printnl()
}
// but defer does escape to later execution in the function
@@ -392,7 +412,7 @@ func f27defer(b bool) {
defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
}
defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
- println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
+ printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
// and newproc (go) escapes to the heap
@@ -403,7 +423,7 @@ func f27go(b bool) {
go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
}
go call27(func() { x++ }) // ERROR "live at call to newobject: &x"
- println()
+ printnl()
}
//go:noescape
@@ -415,10 +435,10 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
func f28(b bool) {
if b {
- print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
}
- print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
- print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
}
// map iterator should die on end of range loop
@@ -426,14 +446,14 @@ func f28(b bool) {
func f29(b bool) {
if b {
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
- print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
+ printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
}
}
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
- print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
+ printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
}
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
- print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
+ printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
}
}
@@ -446,14 +466,14 @@ func f30(b bool) {
// the copy of ptrarr and the internal iterator pointer.
if b {
for _, p := range ptrarr {
- print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
+ printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
}
}
for _, p := range ptrarr {
- print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
+ printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
}
for _, p := range ptrarr {
- print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
+ printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
}
}
@@ -503,44 +523,44 @@ var m33 map[interface{}]int
func f33() {
if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- println()
+ printnl()
return
} else {
- println()
+ printnl()
}
- println()
+ printnl()
}
func f34() {
if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- println()
+ printnl()
return
}
- println()
+ printnl()
}
func f35() {
if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- println()
+ printnl()
return
}
- println()
+ printnl()
}
func f36() {
if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- println()
+ printnl()
return
}
- println()
+ printnl()
}
func f37() {
if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
- println()
+ printnl()
return
}
- println()
+ printnl()
}
// select temps should disappear in the case bodies
@@ -558,44 +578,44 @@ func f38(b bool) {
if b {
select { // ERROR "live at call"
case <-fc38(): // ERROR "live at call"
- println()
+ printnl()
case fc38() <- *fi38(1): // ERROR "live at call"
- println()
+ printnl()
case *fi38(2) = <-fc38(): // ERROR "live at call"
- println()
+ printnl()
case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call"
- println()
+ printnl()
}
- println()
+ printnl()
}
- println()
+ printnl()
}
// issue 8097: mishandling of x = x during return.
func f39() (x []int) {
x = []int{1}
- println() // ERROR "live at call to printnl: x"
+ printnl() // ERROR "live at call to printnl: x"
return x
}
func f39a() (x []int) {
x = []int{1}
- println() // ERROR "live at call to printnl: x"
+ printnl() // ERROR "live at call to printnl: x"
return
}
func f39b() (x [10]*int) {
x = [10]*int{}
x[0] = new(int) // ERROR "live at call to newobject: x"
- println() // ERROR "live at call to printnl: x"
+ printnl() // ERROR "live at call to printnl: x"
return x
}
func f39c() (x [10]*int) {
x = [10]*int{}
x[0] = new(int) // ERROR "live at call to newobject: x"
- println() // ERROR "live at call to printnl: x"
+ printnl() // ERROR "live at call to printnl: x"
return
}
@@ -614,7 +634,7 @@ func newT40() *T40 {
func bad40() {
t := newT40()
- println()
+ printnl()
_ = t
}
@@ -622,6 +642,6 @@ func good40() {
ret := T40{}
ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
t := &ret
- println() // ERROR "live at call to printnl: ret"
+ printnl() // ERROR "live at call to printnl: ret"
_ = t
}
diff --git a/test/live2.go b/test/live2.go
index ef6ad994c..1bd0af2cc 100644
--- a/test/live2.go
+++ b/test/live2.go
@@ -12,6 +12,8 @@ package main
// issue 8142: lost 'addrtaken' bit on inlined variables.
// no inlining in this test, so just checking that non-inlined works.
+func printnl()
+
type T40 struct {
m map[int]int
}
@@ -24,7 +26,7 @@ func newT40() *T40 {
func bad40() {
t := newT40() // ERROR "live at call to makemap: ret"
- println() // ERROR "live at call to printnl: ret"
+ printnl() // ERROR "live at call to printnl: ret"
_ = t
}
@@ -32,6 +34,6 @@ func good40() {
ret := T40{}
ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
t := &ret
- println() // ERROR "live at call to printnl: ret"
+ printnl() // ERROR "live at call to printnl: ret"
_ = t
}
diff --git a/test/nosplit.go b/test/nosplit.go
index 953a5bf0a..3a63e8731 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -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]