summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-10-27 17:17:06 -0400
committerAustin Clements <austin@google.com>2014-10-27 17:17:06 -0400
commit87729004ae12c22611b6bccf42211cb1f712ddb0 (patch)
tree35f11e6f80feaa92f9f0b3f985a711d691d92665
parente7797eae182f602d8d08d936f74257a93484d5fd (diff)
parentfcceea1097e0f86dac0d71bd2fa0b37ab66d8143 (diff)
downloadgo-87729004ae12c22611b6bccf42211cb1f712ddb0.tar.gz
[dev.power64] all: merge default into dev.power64
LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/164110043
-rw-r--r--.hgignore6
-rw-r--r--include/link.h27
-rw-r--r--lib/codereview/codereview.cfg1
-rw-r--r--lib/codereview/codereview.py12
-rw-r--r--src/cmd/9a/Makefile10
-rw-r--r--src/cmd/9a/a.h167
-rw-r--r--src/cmd/9a/a.y997
-rw-r--r--src/cmd/9a/doc.go21
-rw-r--r--src/cmd/9a/lex.c726
-rw-r--r--src/cmd/9a/y.tab.c3794
-rw-r--r--src/cmd/9a/y.tab.h192
-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/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/pgen.c4
-rw-r--r--src/cmd/gc/popt.c4
-rw-r--r--src/cmd/gc/walk.c7
-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.c1083
-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/runtime/arch_power64.h14
-rw-r--r--src/runtime/arch_power64le.h14
-rw-r--r--src/runtime/asm_power64x.s1045
-rw-r--r--src/runtime/atomic_power64x.s37
-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.h211
-rw-r--r--src/runtime/defs_linux_power64le.h211
-rw-r--r--src/runtime/gcinfo_test.go6
-rw-r--r--src/runtime/malloc.go10
-rw-r--r--src/runtime/mem_linux.c16
-rw-r--r--src/runtime/memclr_power64x.s20
-rw-r--r--src/runtime/memmove_power64x.s40
-rw-r--r--src/runtime/mgc0.c10
-rw-r--r--src/runtime/noasm.go (renamed from src/runtime/noasm_arm.go)2
-rw-r--r--src/runtime/os_linux.c37
-rw-r--r--src/runtime/panic.c2
-rw-r--r--src/runtime/panic.go4
-rw-r--r--src/runtime/proc.c4
-rw-r--r--src/runtime/rt0_linux_power64.s17
-rw-r--r--src/runtime/rt0_linux_power64le.s14
-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/string.go4
-rw-r--r--src/runtime/sys_linux_power64x.s367
-rw-r--r--src/runtime/sys_power64x.c38
-rw-r--r--src/runtime/thunk.s6
-rw-r--r--src/sync/atomic/asm_power64x.s184
-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/nosplit.go21
121 files changed, 37430 insertions, 219 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 fdf11d1f4..263385b79 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -3603,11 +3603,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/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..629543f13
--- /dev/null
+++ b/src/cmd/9a/a.h
@@ -0,0 +1,167 @@
+// 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 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);
+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..41776fd3c
--- /dev/null
+++ b/src/cmd/9a/a.y
@@ -0,0 +1,997 @@
+// 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:
+ LLAB ':'
+ {
+ if($1->value != pc)
+ yyerror("redeclaration of %s", $1->name);
+ $1->value = pc;
+ }
+ line
+| LNAME ':'
+ {
+ $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
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTEXT name ',' con ',' imm
+ {
+ $6.offset &= 0xffffffffull;
+ $6.offset |= (vlong)ArgsSizeUnknown << 32;
+ outcode($1, &$2, $4, &$6);
+ }
+| LTEXT name ',' con ',' imm '-' con
+ {
+ $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
+ {
+ $$ = nullgen;
+ if(pass == 2)
+ yyerror("undefined label: %s", $1->name);
+ $$.type = D_BRANCH;
+ $$.offset = $2;
+ }
+| LLAB offset
+ {
+ $$ = nullgen;
+ $$.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..bd38493d5
--- /dev/null
+++ b/src/cmd/9a/lex.c
@@ -0,0 +1,726 @@
+// cmd/9a/lex.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#define EXTERN
+#include <u.h>
+#include <libc.h>
+#include "a.h"
+#include "y.tab.h"
+
+enum
+{
+ Plan9 = 1<<0,
+ Unix = 1<<1,
+ Windows = 1<<2,
+};
+
+int
+systemtype(int sys)
+{
+#ifdef _WIN32
+ return sys&Windows;
+#else
+ return sys&Plan9;
+#endif
+}
+
+int
+pathchar(void)
+{
+ return '/';
+}
+
+int
+Lconv(Fmt *fp)
+{
+ return linklinefmt(ctxt, fp);
+}
+
+void
+dodef(char *p)
+{
+ if(nDlist%8 == 0)
+ Dlist = allocn(Dlist, nDlist*sizeof(char *),
+ 8*sizeof(char *));
+ Dlist[nDlist++] = p;
+}
+
+LinkArch* thelinkarch = &linkpower64;
+
+void
+usage(void)
+{
+ print("usage: %ca [options] file.c...\n", thechar);
+ flagprint(1);
+ errorexit();
+}
+
+void
+main(int argc, char *argv[])
+{
+ char *p;
+
+ thechar = '9';
+ thestring = "power64";
+
+ // Allow GOARCH=thestring or GOARCH=thestringsuffix,
+ // but not other values.
+ p = getgoarch();
+ if(strncmp(p, thestring, strlen(thestring)) != 0)
+ sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
+ if(strcmp(p, "power64le") == 0)
+ thelinkarch = &linkpower64le;
+
+ ctxt = linknew(thelinkarch);
+ ctxt->diag = yyerror;
+ ctxt->bso = &bstdout;
+ ctxt->enforce_data_order = 1;
+ Binit(&bstdout, 1, OWRITE);
+ listinit9();
+ fmtinstall('L', Lconv);
+
+ ensuresymb(NSYMB);
+ memset(debug, 0, sizeof(debug));
+ cinit();
+ outfile = 0;
+ setinclude(".");
+
+ flagfn1("D", "name[=value]: add #define", dodef);
+ flagfn1("I", "dir: add dir to include path", setinclude);
+ flagcount("S", "print assembly and machine code", &debug['S']);
+ flagcount("m", "debug preprocessor macros", &debug['m']);
+ flagstr("o", "file: set output file", &outfile);
+ flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
+
+ flagparse(&argc, &argv, usage);
+ ctxt->debugasm = debug['S'];
+
+ if(argc < 1)
+ usage();
+ if(argc > 1){
+ print("can't assemble multiple files\n");
+ errorexit();
+ }
+
+ if(assemble(argv[0]))
+ errorexit();
+ Bflush(&bstdout);
+ exits(0);
+}
+
+int
+assemble(char *file)
+{
+ char *ofile, *p;
+ int i, of;
+
+ ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
+ strcpy(ofile, file);
+ p = utfrrune(ofile, pathchar());
+ if(p) {
+ include[0] = ofile;
+ *p++ = 0;
+ } else
+ p = ofile;
+ if(outfile == 0) {
+ outfile = p;
+ if(outfile){
+ p = utfrrune(outfile, '.');
+ if(p)
+ if(p[1] == 's' && p[2] == 0)
+ p[0] = 0;
+ p = utfrune(outfile, 0);
+ p[0] = '.';
+ p[1] = thechar;
+ p[2] = 0;
+ } else
+ outfile = "/dev/null";
+ }
+
+ of = create(outfile, OWRITE, 0664);
+ if(of < 0) {
+ yyerror("%ca: cannot create %s", thechar, outfile);
+ errorexit();
+ }
+ Binit(&obuf, of, OWRITE);
+ Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
+ Bprint(&obuf, "!\n");
+
+ for(pass = 1; pass <= 2; pass++) {
+ nosched = 0;
+ pinit(file);
+ for(i=0; i<nDlist; i++)
+ dodefine(Dlist[i]);
+ yyparse();
+ cclean();
+ if(nerrors)
+ return nerrors;
+ }
+
+ writeobj(ctxt, &obuf);
+ Bflush(&obuf);
+ return 0;
+}
+
+struct
+{
+ char *name;
+ ushort type;
+ ushort value;
+} itab[] =
+{
+ "SP", LSP, D_AUTO,
+ "SB", LSB, D_EXTERN,
+ "FP", LFP, D_PARAM,
+ "PC", LPC, D_BRANCH,
+
+ "LR", LLR, D_LR,
+ "CTR", LCTR, D_CTR,
+
+ "XER", LSPREG, D_XER,
+ "MSR", LMSR, D_MSR,
+ "FPSCR", LFPSCR, D_FPSCR,
+ "SPR", LSPR, D_SPR,
+ "DCR", LSPR, D_DCR,
+
+ "CR", LCR, 0,
+ "CR0", LCREG, 0,
+ "CR1", LCREG, 1,
+ "CR2", LCREG, 2,
+ "CR3", LCREG, 3,
+ "CR4", LCREG, 4,
+ "CR5", LCREG, 5,
+ "CR6", LCREG, 6,
+ "CR7", LCREG, 7,
+
+ "R", LR, 0,
+ "R0", LREG, 0,
+ "R1", LREG, 1,
+ "R2", LREG, 2,
+ "R3", LREG, 3,
+ "R4", LREG, 4,
+ "R5", LREG, 5,
+ "R6", LREG, 6,
+ "R7", LREG, 7,
+ "R8", LREG, 8,
+ "R9", LREG, 9,
+ "R10", LREG, 10,
+ "R11", LREG, 11,
+ "R12", LREG, 12,
+ "R13", LREG, 13,
+ "R14", LREG, 14,
+ "R15", LREG, 15,
+ "R16", LREG, 16,
+ "R17", LREG, 17,
+ "R18", LREG, 18,
+ "R19", LREG, 19,
+ "R20", LREG, 20,
+ "R21", LREG, 21,
+ "R22", LREG, 22,
+ "R23", LREG, 23,
+ "R24", LREG, 24,
+ "R25", LREG, 25,
+ "R26", LREG, 26,
+ "R27", LREG, 27,
+ "R28", LREG, 28,
+ "R29", LREG, 29,
+ "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->to = *g2;
+ p->from3 = *g3;
+ p->pc = pc;
+ print("oc: %P\n", p);
+
+ 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..e81db9924
--- /dev/null
+++ b/src/cmd/9a/y.tab.c
@@ -0,0 +1,3794 @@
+/* A Bison parser, made by GNU Bison 2.5. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ 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.
+
+ 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/>. */
+
+/* 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.5"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 268 of yacc.c */
+#line 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"
+
+
+/* Line 268 of yacc.c */
+#line 80 "y.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* 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 293 of yacc.c */
+#line 38 "a.y"
+
+ Sym *sym;
+ vlong lval;
+ double dval;
+ char sval[8];
+ Addr addr;
+
+
+
+/* Line 293 of yacc.c */
+#line 250 "y.tab.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 343 of yacc.c */
+#line 262 "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 yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#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 EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# 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 EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS && (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_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* 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)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# 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
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 2
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 836
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 81
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 32
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 186
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 459
+
+/* 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, 14, 19, 24,
+ 29, 32, 34, 37, 40, 45, 50, 55, 60, 65,
+ 70, 75, 80, 85, 90, 95, 100, 105, 110, 115,
+ 120, 125, 130, 135, 140, 147, 152, 157, 162, 169,
+ 174, 179, 186, 193, 200, 205, 210, 217, 222, 229,
+ 234, 241, 246, 251, 254, 261, 266, 271, 276, 283,
+ 288, 293, 298, 303, 308, 313, 318, 323, 326, 329,
+ 334, 338, 342, 348, 353, 358, 365, 370, 375, 382,
+ 389, 396, 405, 410, 415, 419, 422, 427, 432, 439,
+ 448, 453, 460, 465, 470, 477, 484, 493, 502, 511,
+ 520, 525, 530, 535, 542, 547, 554, 559, 564, 567,
+ 570, 574, 578, 582, 586, 589, 593, 597, 602, 607,
+ 610, 615, 622, 631, 638, 645, 652, 655, 660, 663,
+ 666, 668, 670, 672, 674, 676, 678, 680, 682, 687,
+ 689, 691, 696, 698, 703, 705, 710, 712, 716, 719,
+ 722, 725, 729, 732, 734, 739, 743, 749, 751, 756,
+ 761, 767, 775, 776, 778, 779, 782, 785, 787, 789,
+ 791, 793, 795, 798, 801, 804, 808, 810, 814, 818,
+ 822, 826, 830, 835, 840, 844, 848
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 82, 0, -1, -1, 82, 83, -1, -1, 71, 73,
+ 84, 83, -1, -1, 70, 73, 85, 83, -1, 70,
+ 74, 112, 75, -1, 72, 74, 112, 75, -1, 57,
+ 75, -1, 75, -1, 86, 75, -1, 1, 75, -1,
+ 13, 88, 76, 88, -1, 13, 106, 76, 88, -1,
+ 13, 105, 76, 88, -1, 14, 88, 76, 88, -1,
+ 14, 106, 76, 88, -1, 14, 105, 76, 88, -1,
+ 22, 106, 76, 97, -1, 22, 105, 76, 97, -1,
+ 22, 102, 76, 97, -1, 22, 97, 76, 97, -1,
+ 22, 97, 76, 106, -1, 22, 97, 76, 105, -1,
+ 13, 88, 76, 106, -1, 13, 88, 76, 105, -1,
+ 14, 88, 76, 106, -1, 14, 88, 76, 105, -1,
+ 13, 97, 76, 106, -1, 13, 97, 76, 105, -1,
+ 13, 95, 76, 97, -1, 13, 97, 76, 95, -1,
+ 13, 97, 76, 103, 76, 95, -1, 13, 95, 76,
+ 98, -1, 13, 103, 76, 96, -1, 66, 103, 76,
+ 111, -1, 13, 88, 76, 103, 76, 91, -1, 13,
+ 88, 76, 98, -1, 13, 88, 76, 91, -1, 18,
+ 88, 76, 104, 76, 88, -1, 18, 103, 76, 104,
+ 76, 88, -1, 18, 88, 76, 103, 76, 88, -1,
+ 18, 88, 76, 88, -1, 18, 103, 76, 88, -1,
+ 16, 88, 76, 104, 76, 88, -1, 16, 88, 76,
+ 88, -1, 17, 88, 76, 104, 76, 88, -1, 17,
+ 88, 76, 88, -1, 17, 103, 76, 104, 76, 88,
+ -1, 17, 103, 76, 88, -1, 15, 88, 76, 88,
+ -1, 15, 88, -1, 67, 88, 76, 104, 76, 88,
+ -1, 13, 103, 76, 88, -1, 13, 101, 76, 88,
+ -1, 20, 99, 76, 99, -1, 20, 99, 76, 111,
+ 76, 99, -1, 13, 98, 76, 98, -1, 13, 94,
+ 76, 98, -1, 13, 91, 76, 88, -1, 13, 94,
+ 76, 88, -1, 13, 89, 76, 88, -1, 13, 88,
+ 76, 89, -1, 13, 98, 76, 94, -1, 13, 88,
+ 76, 94, -1, 21, 87, -1, 21, 106, -1, 21,
+ 77, 89, 78, -1, 21, 76, 87, -1, 21, 76,
+ 106, -1, 21, 76, 77, 89, 78, -1, 21, 98,
+ 76, 87, -1, 21, 98, 76, 106, -1, 21, 98,
+ 76, 77, 89, 78, -1, 21, 111, 76, 87, -1,
+ 21, 111, 76, 106, -1, 21, 111, 76, 77, 89,
+ 78, -1, 21, 111, 76, 111, 76, 87, -1, 21,
+ 111, 76, 111, 76, 106, -1, 21, 111, 76, 111,
+ 76, 77, 89, 78, -1, 27, 88, 76, 104, -1,
+ 27, 103, 76, 104, -1, 27, 88, 108, -1, 27,
+ 108, -1, 23, 97, 76, 97, -1, 25, 97, 76,
+ 97, -1, 25, 97, 76, 97, 76, 97, -1, 26,
+ 97, 76, 97, 76, 97, 76, 97, -1, 24, 97,
+ 76, 97, -1, 24, 97, 76, 97, 76, 98, -1,
+ 19, 88, 76, 88, -1, 19, 88, 76, 103, -1,
+ 19, 88, 76, 88, 76, 98, -1, 19, 88, 76,
+ 103, 76, 98, -1, 62, 103, 76, 88, 76, 103,
+ 76, 88, -1, 62, 103, 76, 88, 76, 100, 76,
+ 88, -1, 62, 88, 76, 88, 76, 103, 76, 88,
+ -1, 62, 88, 76, 88, 76, 100, 76, 88, -1,
+ 63, 106, 76, 88, -1, 63, 88, 76, 106, -1,
+ 58, 105, 76, 88, -1, 58, 105, 76, 103, 76,
+ 88, -1, 59, 88, 76, 105, -1, 59, 88, 76,
+ 103, 76, 105, -1, 61, 105, 76, 88, -1, 61,
+ 88, 76, 105, -1, 60, 105, -1, 29, 108, -1,
+ 29, 88, 108, -1, 29, 97, 108, -1, 29, 76,
+ 88, -1, 29, 76, 97, -1, 29, 103, -1, 32,
+ 103, 108, -1, 32, 101, 108, -1, 55, 103, 76,
+ 103, -1, 56, 103, 76, 106, -1, 30, 108, -1,
+ 33, 107, 76, 103, -1, 33, 107, 76, 111, 76,
+ 103, -1, 33, 107, 76, 111, 76, 103, 9, 111,
+ -1, 34, 107, 11, 111, 76, 103, -1, 34, 107,
+ 11, 111, 76, 101, -1, 34, 107, 11, 111, 76,
+ 102, -1, 35, 108, -1, 111, 77, 40, 78, -1,
+ 70, 109, -1, 71, 109, -1, 104, -1, 90, -1,
+ 92, -1, 49, -1, 46, -1, 50, -1, 54, -1,
+ 52, -1, 51, 77, 111, 78, -1, 93, -1, 48,
+ -1, 48, 77, 111, 78, -1, 44, -1, 47, 77,
+ 111, 78, -1, 41, -1, 46, 77, 111, 78, -1,
+ 111, -1, 111, 76, 111, -1, 79, 106, -1, 79,
+ 69, -1, 79, 68, -1, 79, 9, 68, -1, 79,
+ 111, -1, 43, -1, 45, 77, 111, 78, -1, 77,
+ 104, 78, -1, 77, 104, 8, 104, 78, -1, 107,
+ -1, 111, 77, 104, 78, -1, 111, 77, 110, 78,
+ -1, 70, 109, 77, 110, 78, -1, 70, 6, 7,
+ 109, 77, 38, 78, -1, -1, 76, -1, -1, 8,
+ 111, -1, 9, 111, -1, 38, -1, 37, -1, 39,
+ -1, 36, -1, 72, -1, 9, 111, -1, 8, 111,
+ -1, 80, 111, -1, 77, 112, 78, -1, 111, -1,
+ 112, 8, 112, -1, 112, 9, 112, -1, 112, 10,
+ 112, -1, 112, 11, 112, -1, 112, 12, 112, -1,
+ 112, 6, 6, 112, -1, 112, 7, 7, 112, -1,
+ 112, 5, 112, -1, 112, 4, 112, -1, 112, 3,
+ 112, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 66, 66, 67, 71, 70, 78, 77, 83, 88,
+ 94, 98, 99, 100, 106, 110, 114, 118, 122, 126,
+ 133, 137, 141, 145, 149, 153, 160, 164, 168, 172,
+ 179, 183, 190, 194, 198, 202, 206, 210, 217, 221,
+ 225, 235, 239, 243, 247, 251, 255, 259, 263, 267,
+ 271, 275, 279, 283, 290, 297, 301, 308, 312, 320,
+ 324, 328, 332, 336, 340, 344, 348, 357, 361, 365,
+ 369, 373, 377, 381, 385, 389, 393, 397, 401, 405,
+ 413, 421, 432, 436, 440, 444, 451, 455, 459, 463,
+ 467, 471, 478, 482, 486, 490, 497, 501, 505, 509,
+ 516, 520, 528, 532, 536, 540, 544, 548, 552, 559,
+ 563, 567, 571, 575, 579, 586, 590, 597, 606, 617,
+ 624, 628, 634, 643, 647, 651, 658, 664, 670, 678,
+ 686, 694, 695, 698, 706, 714, 722, 729, 735, 741,
+ 744, 752, 760, 766, 774, 780, 788, 796, 817, 822,
+ 830, 836, 843, 851, 852, 860, 867, 877, 878, 887,
+ 895, 903, 912, 913, 916, 919, 923, 929, 930, 931,
+ 934, 935, 939, 943, 947, 951, 957, 958, 962, 966,
+ 970, 974, 978, 982, 986, 990, 994
+};
+#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", "$@2", "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, 85, 83, 83, 83,
+ 83, 83, 83, 83, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 87, 87, 87,
+ 88, 89, 89, 90, 91, 92, 93, 94, 94, 94,
+ 95, 96, 97, 97, 98, 98, 99, 100, 101, 101,
+ 102, 102, 103, 104, 104, 105, 105, 106, 106, 107,
+ 107, 107, 108, 108, 109, 109, 109, 110, 110, 110,
+ 111, 111, 111, 111, 111, 111, 112, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 0, 2, 0, 4, 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, 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 reduction number in state STATE-NUM.
+ Performed when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 162, 162,
+ 162, 0, 0, 0, 162, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 11,
+ 3, 0, 13, 0, 0, 170, 144, 153, 142, 0,
+ 134, 0, 140, 133, 135, 0, 137, 136, 164, 171,
+ 0, 0, 0, 0, 0, 131, 0, 132, 139, 0,
+ 0, 0, 0, 0, 0, 130, 0, 0, 157, 0,
+ 0, 0, 0, 53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 146, 0, 164, 164, 0, 0, 67,
+ 0, 68, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 163, 162, 0, 85, 163, 162, 162, 114,
+ 109, 119, 162, 162, 0, 0, 0, 126, 0, 0,
+ 10, 0, 0, 0, 108, 0, 0, 0, 0, 0,
+ 0, 0, 0, 6, 0, 4, 0, 12, 173, 172,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 176,
+ 0, 149, 148, 152, 174, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 152, 0, 0, 0, 0, 0, 0, 128,
+ 129, 0, 70, 71, 0, 0, 0, 0, 0, 0,
+ 150, 0, 0, 0, 0, 0, 0, 0, 0, 163,
+ 84, 0, 112, 113, 110, 111, 116, 115, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 164, 165, 166, 0, 0, 155, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 175, 14, 64,
+ 40, 66, 39, 0, 27, 26, 63, 61, 62, 60,
+ 32, 35, 33, 0, 31, 30, 65, 59, 56, 0,
+ 55, 36, 16, 15, 168, 167, 169, 0, 0, 17,
+ 29, 28, 19, 18, 52, 47, 130, 49, 130, 51,
+ 130, 44, 0, 130, 45, 130, 92, 93, 57, 146,
+ 0, 69, 0, 73, 74, 0, 76, 77, 0, 0,
+ 151, 23, 25, 24, 22, 21, 20, 86, 90, 87,
+ 0, 82, 83, 120, 0, 0, 117, 118, 102, 0,
+ 0, 104, 107, 106, 0, 0, 101, 100, 37, 0,
+ 7, 8, 5, 9, 154, 145, 143, 138, 0, 0,
+ 0, 186, 185, 184, 0, 0, 177, 178, 179, 180,
+ 181, 0, 0, 0, 158, 159, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 72, 0, 0, 0, 127,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 160, 156, 182, 183, 134, 38, 34, 0, 46,
+ 48, 50, 43, 41, 42, 94, 95, 58, 75, 78,
+ 0, 79, 80, 91, 88, 0, 121, 0, 124, 125,
+ 123, 103, 105, 0, 0, 0, 0, 0, 54, 0,
+ 141, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 161, 81, 89, 122, 99, 98, 147, 97, 96
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 1, 40, 235, 233, 41, 99, 63, 64, 65,
+ 66, 67, 68, 69, 70, 281, 71, 72, 92, 433,
+ 73, 105, 74, 75, 76, 162, 78, 115, 157, 288,
+ 159, 160
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -178
+static const yytype_int16 yypact[] =
+{
+ -178, 471, -178, -66, 567, 640, 32, 32, -26, -26,
+ 32, 756, 626, 24, 55, 55, 55, 55, -14, 73,
+ -60, -54, 743, 743, -60, -44, -44, -32, -23, 32,
+ -23, -1, -26, 644, -44, 32, 35, 17, -10, -178,
+ -178, 48, -178, 756, 756, -178, -178, -178, -178, 4,
+ 63, 88, -178, -178, -178, 94, -178, -178, 130, -178,
+ 710, 508, 756, 101, 114, -178, 117, -178, -178, 123,
+ 128, 140, 155, 166, 170, -178, 172, 177, -178, 174,
+ 181, 190, 192, 193, 202, 756, 203, 206, 208, 220,
+ 221, 756, 224, -178, 63, 130, 175, 700, 42, -178,
+ 229, -178, 143, 6, 232, 235, 238, 240, 245, 246,
+ 255, 257, -178, 259, 262, -178, 285, -60, -60, -178,
+ -178, -178, -60, -60, 265, 268, 306, -178, 270, 271,
+ -178, 32, 272, 301, -178, 302, 315, 316, 317, 319,
+ 320, 321, 324, -178, 756, -178, 756, -178, -178, -178,
+ 756, 756, 756, 756, 394, 756, 756, 328, 15, -178,
+ 347, -178, -178, 174, -178, 614, 32, 32, 86, 26,
+ 665, 258, 32, -9, 32, 32, 18, 640, 32, 32,
+ 32, 32, -178, 32, 32, -26, 32, -26, 756, 328,
+ -178, 42, -178, -178, 330, 332, 714, 725, 157, 340,
+ -178, 696, 55, 55, 55, 55, 55, 55, 55, 32,
+ -178, 32, -178, -178, -178, -178, -178, -178, 390, 106,
+ 756, -44, 743, -26, 49, -23, 32, 32, 32, 743,
+ 32, 756, 32, 534, 357, 534, 377, 335, 337, 338,
+ 339, 175, -178, -178, 106, 32, -178, 756, 756, 756,
+ 406, 411, 756, 756, 756, 756, 756, -178, -178, -178,
+ -178, -178, -178, 343, -178, -178, -178, -178, -178, -178,
+ -178, -178, -178, 351, -178, -178, -178, -178, -178, 352,
+ -178, -178, -178, -178, -178, -178, -178, 350, 353, -178,
+ -178, -178, -178, -178, -178, -178, 361, -178, 362, -178,
+ 363, -178, 366, 369, -178, 370, 371, 372, -178, 373,
+ 375, -178, 42, -178, -178, 42, -178, -178, 184, 376,
+ -178, -178, -178, -178, -178, -178, -178, -178, 374, 379,
+ 380, -178, -178, -178, 381, 382, -178, -178, -178, 383,
+ 388, -178, -178, -178, 389, 392, -178, -178, -178, 397,
+ -178, -178, -178, -178, -178, -178, -178, -178, 398, 396,
+ 399, 620, 513, 147, 756, 756, 216, 216, -178, -178,
+ -178, 405, 418, 756, -178, -178, 32, 32, 32, 32,
+ 32, 32, 59, 59, 756, -178, 403, 404, 739, -178,
+ 59, 55, 55, -44, 420, 32, -23, 390, 390, 32,
+ 438, -178, -178, 283, 283, -178, -178, -178, 424, -178,
+ -178, -178, -178, -178, -178, -178, -178, -178, -178, -178,
+ 42, -178, -178, -178, -178, 431, 499, 334, -178, -178,
+ -178, -178, -178, 436, 439, 460, 463, 464, -178, 467,
+ -178, 484, 55, 756, 721, 32, 32, 756, 32, 32,
+ -178, -178, -178, -178, -178, -178, -178, -178, -178
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -178, -178, 8, -178, -178, -178, -90, -5, -76, -178,
+ -157, -178, -178, -153, -160, -178, 69, 40, -177, 167,
+ -15, 176, 116, 104, 82, 33, 241, 127, -75, 327,
+ 36, 71
+};
+
+/* 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 -1
+static const yytype_uint16 yytable[] =
+{
+ 80, 83, 84, 86, 88, 90, 122, 192, 260, 42,
+ 272, 308, 261, 113, 117, 199, 112, 47, 276, 49,
+ 189, 190, 195, 245, 133, 61, 135, 137, 139, 47,
+ 142, 49, 43, 44, 47, 85, 49, 77, 82, 279,
+ 79, 79, 47, 130, 49, 101, 107, 93, 102, 79,
+ 43, 44, 100, 85, 131, 284, 285, 286, 125, 125,
+ 45, 47, 112, 49, 146, 85, 140, 46, 48, 79,
+ 48, 51, 94, 51, 200, 47, 131, 49, 45, 148,
+ 149, 150, 104, 108, 109, 110, 111, 81, 118, 259,
+ 145, 53, 54, 246, 58, 106, 59, 163, 164, 48,
+ 46, 60, 51, 103, 62, 94, 313, 316, 143, 144,
+ 132, 212, 134, 136, 59, 310, 47, 48, 49, 91,
+ 51, 182, 62, 147, 87, 89, 131, 46, 85, 47,
+ 193, 49, 94, 194, 114, 119, 154, 123, 155, 156,
+ 151, 128, 129, 284, 285, 286, 120, 121, 138, 116,
+ 141, 127, 85, 250, 251, 252, 253, 254, 255, 256,
+ 258, 266, 267, 268, 158, 152, 358, 278, 280, 282,
+ 283, 153, 289, 292, 293, 294, 295, 165, 297, 299,
+ 301, 304, 306, 155, 156, 213, 237, 238, 239, 240,
+ 166, 242, 243, 167, 284, 285, 286, 319, 265, 168,
+ 47, 79, 49, 275, 169, 262, 79, 417, 269, 271,
+ 291, 277, 407, 79, 406, 234, 170, 236, 338, 197,
+ 198, 343, 344, 345, 309, 347, 254, 255, 256, 314,
+ 317, 171, 194, 318, 323, 158, 386, 79, 270, 387,
+ 210, 350, 172, 352, 214, 215, 173, 264, 174, 216,
+ 217, 176, 274, 175, 334, 337, 335, 177, 79, 290,
+ 388, 198, 346, 124, 126, 79, 178, 348, 179, 180,
+ 321, 324, 325, 326, 327, 328, 329, 330, 181, 183,
+ 287, 263, 184, 322, 185, 296, 273, 298, 300, 303,
+ 305, 252, 253, 254, 255, 256, 186, 187, 421, 46,
+ 188, 302, 287, 307, 94, 196, 341, 342, 201, 55,
+ 56, 202, 57, 331, 203, 332, 204, 220, 361, 362,
+ 363, 205, 206, 366, 367, 368, 369, 370, 47, 48,
+ 49, 207, 51, 208, 333, 209, 349, 336, 211, 339,
+ 340, 218, 43, 444, 441, 219, 221, 222, 223, 360,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 45, 409, 410, 411, 412, 413, 414, 224, 225, 428,
+ 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+ 431, 226, 227, 228, 438, 229, 230, 231, 43, 44,
+ 232, 241, 200, 161, 58, 244, 59, 198, 320, 408,
+ 311, 91, 364, 354, 62, 355, 356, 357, 365, 371,
+ 93, 422, 415, 416, 194, 257, 45, 372, 374, 373,
+ 423, 375, 351, 435, 435, 403, 404, 376, 377, 378,
+ 454, 455, 379, 457, 458, 380, 381, 382, 383, 384,
+ 390, 405, 353, 385, 389, 391, 392, 393, 394, 395,
+ 424, 425, 59, 163, 396, 397, 52, 91, 398, 85,
+ 62, 2, 3, 399, 401, 400, 439, 402, 432, 453,
+ 149, 418, 419, 456, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 427,
+ 19, 20, 440, 21, 22, 23, 24, 442, 443, 426,
+ 430, 452, 445, 434, 437, 446, 43, 44, 249, 250,
+ 251, 252, 253, 254, 255, 256, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 3, 447, 34, 35, 448,
+ 449, 36, 37, 38, 45, 450, 39, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 451, 19, 20, 436, 21, 22, 23, 24,
+ 429, 359, 0, 0, 0, 43, 44, 161, 58, 0,
+ 59, 0, 0, 0, 0, 91, 0, 0, 62, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 0, 0,
+ 34, 35, 0, 45, 36, 37, 38, 0, 46, 39,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 0, 57, 43, 44, 248, 249, 250, 251, 252, 253,
+ 254, 255, 256, 0, 43, 44, 0, 58, 0, 59,
+ 0, 0, 0, 0, 60, 0, 61, 62, 43, 44,
+ 45, 0, 43, 44, 0, 46, 0, 47, 0, 49,
+ 50, 0, 45, 53, 54, 55, 56, 46, 57, 0,
+ 0, 0, 94, 43, 44, 0, 45, 0, 0, 0,
+ 45, 0, 0, 47, 58, 49, 59, 47, 0, 49,
+ 0, 60, 0, 85, 62, 0, 95, 96, 59, 0,
+ 0, 45, 97, 98, 43, 44, 62, 0, 43, 44,
+ 58, 0, 59, 52, 58, 0, 59, 60, 43, 44,
+ 62, 91, 43, 44, 62, 0, 0, 0, 0, 43,
+ 44, 0, 45, 43, 44, 58, 45, 59, 0, 0,
+ 48, 0, 60, 51, 85, 62, 45, 43, 44, 0,
+ 45, 43, 44, 47, 0, 49, 0, 45, 0, 0,
+ 0, 45, 0, 0, 43, 44, 58, 0, 59, 0,
+ 95, 96, 59, 60, 0, 45, 62, 191, 0, 45,
+ 62, 0, 59, 0, 95, 96, 59, 91, 0, 320,
+ 62, 312, 45, 59, 62, 95, 96, 59, 91, 0,
+ 0, 62, 315, 0, 0, 62, 0, 0, 0, 95,
+ 96, 59, 0, 58, 0, 59, 420, 0, 0, 62,
+ 91, 0, 0, 62, 0, 0, 0, 0, 59, 0,
+ 0, 0, 0, 91, 0, 0, 62
+};
+
+#define yypact_value_is_default(yystate) \
+ ((yystate) == (-178))
+
+#define yytable_value_is_error(yytable_value) \
+ YYID (0)
+
+static const yytype_int16 yycheck[] =
+{
+ 5, 6, 7, 8, 9, 10, 21, 97, 165, 75,
+ 170, 188, 165, 18, 19, 9, 76, 43, 171, 45,
+ 95, 96, 98, 8, 29, 79, 31, 32, 33, 43,
+ 35, 45, 8, 9, 43, 79, 45, 4, 5, 48,
+ 4, 5, 43, 75, 45, 12, 13, 11, 12, 13,
+ 8, 9, 12, 79, 77, 37, 38, 39, 22, 23,
+ 36, 43, 76, 45, 74, 79, 33, 41, 44, 33,
+ 44, 47, 46, 47, 68, 43, 77, 45, 36, 43,
+ 44, 77, 13, 14, 15, 16, 17, 5, 19, 165,
+ 73, 49, 50, 78, 70, 13, 72, 61, 62, 44,
+ 41, 77, 47, 79, 80, 46, 196, 197, 73, 74,
+ 28, 116, 30, 31, 72, 191, 43, 44, 45, 77,
+ 47, 85, 80, 75, 8, 9, 77, 41, 79, 43,
+ 97, 45, 46, 97, 18, 19, 6, 21, 8, 9,
+ 77, 25, 26, 37, 38, 39, 19, 20, 32, 76,
+ 34, 24, 79, 6, 7, 8, 9, 10, 11, 12,
+ 165, 166, 167, 168, 60, 77, 241, 172, 173, 174,
+ 175, 77, 177, 178, 179, 180, 181, 76, 183, 184,
+ 185, 186, 187, 8, 9, 116, 150, 151, 152, 153,
+ 76, 155, 156, 76, 37, 38, 39, 40, 165, 76,
+ 43, 165, 45, 170, 76, 165, 170, 384, 168, 169,
+ 177, 171, 372, 177, 371, 144, 76, 146, 223, 76,
+ 77, 226, 227, 228, 188, 230, 10, 11, 12, 196,
+ 197, 76, 196, 197, 201, 131, 312, 201, 169, 315,
+ 113, 233, 76, 235, 117, 118, 76, 165, 76, 122,
+ 123, 77, 170, 76, 218, 222, 220, 76, 222, 177,
+ 76, 77, 229, 22, 23, 229, 76, 231, 76, 76,
+ 201, 202, 203, 204, 205, 206, 207, 208, 76, 76,
+ 176, 165, 76, 201, 76, 181, 170, 183, 184, 185,
+ 186, 8, 9, 10, 11, 12, 76, 76, 388, 41,
+ 76, 185, 198, 187, 46, 76, 224, 225, 76, 51,
+ 52, 76, 54, 209, 76, 211, 76, 11, 247, 248,
+ 249, 76, 76, 252, 253, 254, 255, 256, 43, 44,
+ 45, 76, 47, 76, 218, 76, 232, 221, 76, 223,
+ 224, 76, 8, 9, 420, 77, 76, 76, 76, 245,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 36, 376, 377, 378, 379, 380, 381, 76, 76, 394,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 395, 76, 76, 76, 399, 76, 76, 76, 8, 9,
+ 76, 7, 68, 69, 70, 77, 72, 77, 68, 373,
+ 78, 77, 6, 78, 80, 78, 78, 78, 7, 76,
+ 384, 388, 382, 383, 388, 78, 36, 76, 78, 77,
+ 390, 78, 75, 397, 398, 364, 365, 76, 76, 76,
+ 445, 446, 76, 448, 449, 76, 76, 76, 76, 76,
+ 76, 46, 75, 78, 78, 76, 76, 76, 76, 76,
+ 391, 392, 72, 427, 76, 76, 48, 77, 76, 79,
+ 80, 0, 1, 76, 78, 77, 38, 78, 396, 443,
+ 444, 78, 78, 447, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 79,
+ 29, 30, 78, 32, 33, 34, 35, 76, 9, 393,
+ 394, 442, 76, 397, 398, 76, 8, 9, 5, 6,
+ 7, 8, 9, 10, 11, 12, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 1, 76, 66, 67, 76,
+ 76, 70, 71, 72, 36, 78, 75, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 78, 29, 30, 398, 32, 33, 34, 35,
+ 394, 244, -1, -1, -1, 8, 9, 69, 70, -1,
+ 72, -1, -1, -1, -1, 77, -1, -1, 80, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
+ 66, 67, -1, 36, 70, 71, 72, -1, 41, 75,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ -1, 54, 8, 9, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, -1, 8, 9, -1, 70, -1, 72,
+ -1, -1, -1, -1, 77, -1, 79, 80, 8, 9,
+ 36, -1, 8, 9, -1, 41, -1, 43, -1, 45,
+ 46, -1, 36, 49, 50, 51, 52, 41, 54, -1,
+ -1, -1, 46, 8, 9, -1, 36, -1, -1, -1,
+ 36, -1, -1, 43, 70, 45, 72, 43, -1, 45,
+ -1, 77, -1, 79, 80, -1, 70, 71, 72, -1,
+ -1, 36, 76, 77, 8, 9, 80, -1, 8, 9,
+ 70, -1, 72, 48, 70, -1, 72, 77, 8, 9,
+ 80, 77, 8, 9, 80, -1, -1, -1, -1, 8,
+ 9, -1, 36, 8, 9, 70, 36, 72, -1, -1,
+ 44, -1, 77, 47, 79, 80, 36, 8, 9, -1,
+ 36, 8, 9, 43, -1, 45, -1, 36, -1, -1,
+ -1, 36, -1, -1, 8, 9, 70, -1, 72, -1,
+ 70, 71, 72, 77, -1, 36, 80, 77, -1, 36,
+ 80, -1, 72, -1, 70, 71, 72, 77, -1, 68,
+ 80, 77, 36, 72, 80, 70, 71, 72, 77, -1,
+ -1, 80, 77, -1, -1, 80, -1, -1, -1, 70,
+ 71, 72, -1, 70, -1, 72, 77, -1, -1, 80,
+ 77, -1, -1, 80, -1, -1, -1, -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, 71, 72, 75,
+ 83, 86, 75, 8, 9, 36, 41, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 54, 70, 72,
+ 77, 79, 80, 88, 89, 90, 91, 92, 93, 94,
+ 95, 97, 98, 101, 103, 104, 105, 106, 107, 111,
+ 88, 105, 106, 88, 88, 79, 88, 103, 88, 103,
+ 88, 77, 99, 111, 46, 70, 71, 76, 77, 87,
+ 98, 106, 111, 79, 97, 102, 105, 106, 97, 97,
+ 97, 97, 76, 88, 103, 108, 76, 88, 97, 103,
+ 108, 108, 101, 103, 107, 111, 107, 108, 103, 103,
+ 75, 77, 105, 88, 105, 88, 105, 88, 103, 88,
+ 106, 103, 88, 73, 74, 73, 74, 75, 111, 111,
+ 77, 77, 77, 77, 6, 8, 9, 109, 104, 111,
+ 112, 69, 106, 111, 111, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 77, 76, 76, 76,
+ 76, 76, 111, 76, 76, 76, 76, 76, 76, 109,
+ 109, 77, 87, 106, 111, 89, 76, 76, 77, 9,
+ 68, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 108, 76, 88, 97, 108, 108, 108, 108, 76, 77,
+ 11, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 85, 112, 84, 112, 111, 111, 111,
+ 111, 7, 111, 111, 77, 8, 78, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 78, 88, 89,
+ 91, 94, 98, 103, 105, 106, 88, 88, 88, 98,
+ 97, 98, 95, 103, 105, 106, 94, 98, 88, 48,
+ 88, 96, 88, 88, 37, 38, 39, 104, 110, 88,
+ 105, 106, 88, 88, 88, 88, 104, 88, 104, 88,
+ 104, 88, 103, 104, 88, 104, 88, 103, 99, 111,
+ 89, 78, 77, 87, 106, 77, 87, 106, 111, 40,
+ 68, 97, 105, 106, 97, 97, 97, 97, 97, 97,
+ 97, 104, 104, 103, 111, 111, 103, 106, 88, 103,
+ 103, 105, 105, 88, 88, 88, 106, 88, 111, 104,
+ 83, 75, 83, 75, 78, 78, 78, 78, 109, 110,
+ 104, 112, 112, 112, 6, 7, 112, 112, 112, 112,
+ 112, 76, 76, 77, 78, 78, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 78, 89, 89, 76, 78,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 77, 78, 78, 112, 112, 46, 91, 95, 111, 88,
+ 88, 88, 88, 88, 88, 98, 98, 99, 78, 78,
+ 77, 87, 106, 98, 97, 97, 103, 79, 101, 102,
+ 103, 88, 105, 100, 103, 111, 100, 103, 88, 38,
+ 78, 89, 76, 9, 9, 76, 76, 76, 76, 76,
+ 78, 78, 97, 111, 88, 88, 111, 88, 88
+};
+
+#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. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ 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
+
+
+/* This macro is provided for backward compatibility. */
+
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# 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 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ 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++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (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 *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)
+{
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = 0;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - Assume YYFAIL is not used. It's too flawed to consider. See
+ <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+ for details. YYERROR is fine as it does not invoke this
+ function.
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+
+ 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_
+ }
+
+ yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ 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;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*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 lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead 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;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* 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_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, 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));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead 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 (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ 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 1806 of yacc.c */
+#line 71 "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 6:
+
+/* Line 1806 of yacc.c */
+#line 78 "a.y"
+ {
+ (yyvsp[(1) - (2)].sym)->type = LLAB;
+ (yyvsp[(1) - (2)].sym)->value = pc;
+ }
+ break;
+
+ case 8:
+
+/* Line 1806 of yacc.c */
+#line 84 "a.y"
+ {
+ (yyvsp[(1) - (4)].sym)->type = LVAR;
+ (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
+ }
+ break;
+
+ case 9:
+
+/* Line 1806 of yacc.c */
+#line 89 "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 10:
+
+/* Line 1806 of yacc.c */
+#line 95 "a.y"
+ {
+ nosched = (yyvsp[(1) - (2)].lval);
+ }
+ break;
+
+ case 14:
+
+/* Line 1806 of yacc.c */
+#line 107 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 15:
+
+/* Line 1806 of yacc.c */
+#line 111 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 16:
+
+/* Line 1806 of yacc.c */
+#line 115 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 17:
+
+/* Line 1806 of yacc.c */
+#line 119 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 18:
+
+/* Line 1806 of yacc.c */
+#line 123 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 19:
+
+/* Line 1806 of yacc.c */
+#line 127 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 20:
+
+/* Line 1806 of yacc.c */
+#line 134 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 21:
+
+/* Line 1806 of yacc.c */
+#line 138 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 22:
+
+/* Line 1806 of yacc.c */
+#line 142 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 23:
+
+/* Line 1806 of yacc.c */
+#line 146 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 24:
+
+/* Line 1806 of yacc.c */
+#line 150 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 25:
+
+/* Line 1806 of yacc.c */
+#line 154 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 26:
+
+/* Line 1806 of yacc.c */
+#line 161 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 27:
+
+/* Line 1806 of yacc.c */
+#line 165 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 28:
+
+/* Line 1806 of yacc.c */
+#line 169 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 29:
+
+/* Line 1806 of yacc.c */
+#line 173 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 30:
+
+/* Line 1806 of yacc.c */
+#line 180 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 31:
+
+/* Line 1806 of yacc.c */
+#line 184 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 32:
+
+/* Line 1806 of yacc.c */
+#line 191 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 33:
+
+/* Line 1806 of yacc.c */
+#line 195 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 34:
+
+/* Line 1806 of yacc.c */
+#line 199 "a.y"
+ {
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 35:
+
+/* Line 1806 of yacc.c */
+#line 203 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 36:
+
+/* Line 1806 of yacc.c */
+#line 207 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 37:
+
+/* Line 1806 of yacc.c */
+#line 211 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+ }
+ break;
+
+ case 38:
+
+/* Line 1806 of yacc.c */
+#line 218 "a.y"
+ {
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 39:
+
+/* Line 1806 of yacc.c */
+#line 222 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 40:
+
+/* Line 1806 of yacc.c */
+#line 226 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 41:
+
+/* Line 1806 of yacc.c */
+#line 236 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 42:
+
+/* Line 1806 of yacc.c */
+#line 240 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 43:
+
+/* Line 1806 of yacc.c */
+#line 244 "a.y"
+ {
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 44:
+
+/* Line 1806 of yacc.c */
+#line 248 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 45:
+
+/* Line 1806 of yacc.c */
+#line 252 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 46:
+
+/* Line 1806 of yacc.c */
+#line 256 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 47:
+
+/* Line 1806 of yacc.c */
+#line 260 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 48:
+
+/* Line 1806 of yacc.c */
+#line 264 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 49:
+
+/* Line 1806 of yacc.c */
+#line 268 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 50:
+
+/* Line 1806 of yacc.c */
+#line 272 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 51:
+
+/* Line 1806 of yacc.c */
+#line 276 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 52:
+
+/* Line 1806 of yacc.c */
+#line 280 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 53:
+
+/* Line 1806 of yacc.c */
+#line 284 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &(yyvsp[(2) - (2)].addr));
+ }
+ break;
+
+ case 54:
+
+/* Line 1806 of yacc.c */
+#line 291 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 55:
+
+/* Line 1806 of yacc.c */
+#line 298 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 56:
+
+/* Line 1806 of yacc.c */
+#line 302 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 57:
+
+/* Line 1806 of yacc.c */
+#line 309 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 58:
+
+/* Line 1806 of yacc.c */
+#line 313 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 59:
+
+/* Line 1806 of yacc.c */
+#line 321 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 60:
+
+/* Line 1806 of yacc.c */
+#line 325 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 61:
+
+/* Line 1806 of yacc.c */
+#line 329 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 62:
+
+/* Line 1806 of yacc.c */
+#line 333 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 63:
+
+/* Line 1806 of yacc.c */
+#line 337 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 64:
+
+/* Line 1806 of yacc.c */
+#line 341 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 65:
+
+/* Line 1806 of yacc.c */
+#line 345 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 66:
+
+/* Line 1806 of yacc.c */
+#line 349 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 67:
+
+/* Line 1806 of yacc.c */
+#line 358 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
+ }
+ break;
+
+ case 68:
+
+/* Line 1806 of yacc.c */
+#line 362 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr));
+ }
+ break;
+
+ case 69:
+
+/* Line 1806 of yacc.c */
+#line 366 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &nullgen, NREG, &(yyvsp[(3) - (4)].addr));
+ }
+ break;
+
+ case 70:
+
+/* Line 1806 of yacc.c */
+#line 370 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ }
+ break;
+
+ case 71:
+
+/* Line 1806 of yacc.c */
+#line 374 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ }
+ break;
+
+ case 72:
+
+/* Line 1806 of yacc.c */
+#line 378 "a.y"
+ {
+ outcode((yyvsp[(1) - (5)].lval), &nullgen, NREG, &(yyvsp[(4) - (5)].addr));
+ }
+ break;
+
+ case 73:
+
+/* Line 1806 of yacc.c */
+#line 382 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 74:
+
+/* Line 1806 of yacc.c */
+#line 386 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 75:
+
+/* Line 1806 of yacc.c */
+#line 390 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(5) - (6)].addr));
+ }
+ break;
+
+ case 76:
+
+/* Line 1806 of yacc.c */
+#line 394 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 77:
+
+/* Line 1806 of yacc.c */
+#line 398 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 78:
+
+/* Line 1806 of yacc.c */
+#line 402 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &nullgen, (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr));
+ }
+ break;
+
+ case 79:
+
+/* Line 1806 of yacc.c */
+#line 406 "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 80:
+
+/* Line 1806 of yacc.c */
+#line 414 "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 81:
+
+/* Line 1806 of yacc.c */
+#line 422 "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 82:
+
+/* Line 1806 of yacc.c */
+#line 433 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+ }
+ break;
+
+ case 83:
+
+/* Line 1806 of yacc.c */
+#line 437 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
+ }
+ break;
+
+ case 84:
+
+/* Line 1806 of yacc.c */
+#line 441 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 85:
+
+/* Line 1806 of yacc.c */
+#line 445 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ }
+ break;
+
+ case 86:
+
+/* Line 1806 of yacc.c */
+#line 452 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 87:
+
+/* Line 1806 of yacc.c */
+#line 456 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 88:
+
+/* Line 1806 of yacc.c */
+#line 460 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 89:
+
+/* Line 1806 of yacc.c */
+#line 464 "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 90:
+
+/* Line 1806 of yacc.c */
+#line 468 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 91:
+
+/* Line 1806 of yacc.c */
+#line 472 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+ }
+ break;
+
+ case 92:
+
+/* Line 1806 of yacc.c */
+#line 479 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 93:
+
+/* Line 1806 of yacc.c */
+#line 483 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 94:
+
+/* Line 1806 of yacc.c */
+#line 487 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+ }
+ break;
+
+ case 95:
+
+/* Line 1806 of yacc.c */
+#line 491 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
+ }
+ break;
+
+ case 96:
+
+/* Line 1806 of yacc.c */
+#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 97:
+
+/* Line 1806 of yacc.c */
+#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 98:
+
+/* Line 1806 of yacc.c */
+#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 99:
+
+/* Line 1806 of yacc.c */
+#line 510 "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 100:
+
+/* Line 1806 of yacc.c */
+#line 517 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 101:
+
+/* Line 1806 of yacc.c */
+#line 521 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 102:
+
+/* Line 1806 of yacc.c */
+#line 529 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 103:
+
+/* Line 1806 of yacc.c */
+#line 533 "a.y"
+ {
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 104:
+
+/* Line 1806 of yacc.c */
+#line 537 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 105:
+
+/* Line 1806 of yacc.c */
+#line 541 "a.y"
+ {
+ outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 106:
+
+/* Line 1806 of yacc.c */
+#line 545 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 107:
+
+/* Line 1806 of yacc.c */
+#line 549 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 108:
+
+/* Line 1806 of yacc.c */
+#line 553 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 109:
+
+/* Line 1806 of yacc.c */
+#line 560 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ }
+ break;
+
+ case 110:
+
+/* Line 1806 of yacc.c */
+#line 564 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 111:
+
+/* Line 1806 of yacc.c */
+#line 568 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 112:
+
+/* Line 1806 of yacc.c */
+#line 572 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ }
+ break;
+
+ case 113:
+
+/* Line 1806 of yacc.c */
+#line 576 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr));
+ }
+ break;
+
+ case 114:
+
+/* Line 1806 of yacc.c */
+#line 580 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 115:
+
+/* Line 1806 of yacc.c */
+#line 587 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 116:
+
+/* Line 1806 of yacc.c */
+#line 591 "a.y"
+ {
+ outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen);
+ }
+ break;
+
+ case 117:
+
+/* Line 1806 of yacc.c */
+#line 598 "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 118:
+
+/* Line 1806 of yacc.c */
+#line 607 "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 119:
+
+/* Line 1806 of yacc.c */
+#line 618 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ }
+ break;
+
+ case 120:
+
+/* Line 1806 of yacc.c */
+#line 625 "a.y"
+ {
+ outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr));
+ }
+ break;
+
+ case 121:
+
+/* Line 1806 of yacc.c */
+#line 629 "a.y"
+ {
+ (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 122:
+
+/* Line 1806 of yacc.c */
+#line 635 "a.y"
+ {
+ (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 123:
+
+/* Line 1806 of yacc.c */
+#line 644 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 124:
+
+/* Line 1806 of yacc.c */
+#line 648 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 125:
+
+/* Line 1806 of yacc.c */
+#line 652 "a.y"
+ {
+ outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
+ }
+ break;
+
+ case 126:
+
+/* Line 1806 of yacc.c */
+#line 659 "a.y"
+ {
+ outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen);
+ }
+ break;
+
+ case 127:
+
+/* Line 1806 of yacc.c */
+#line 665 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_BRANCH;
+ (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
+ }
+ break;
+
+ case 128:
+
+/* Line 1806 of yacc.c */
+#line 671 "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 129:
+
+/* Line 1806 of yacc.c */
+#line 679 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_BRANCH;
+ (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 130:
+
+/* Line 1806 of yacc.c */
+#line 687 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 133:
+
+/* Line 1806 of yacc.c */
+#line 699 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_SPR;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 134:
+
+/* Line 1806 of yacc.c */
+#line 707 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_CREG;
+ (yyval.addr).reg = NREG; /* whole register */
+ }
+ break;
+
+ case 135:
+
+/* Line 1806 of yacc.c */
+#line 715 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_SPR;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 136:
+
+/* Line 1806 of yacc.c */
+#line 723 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_MSR;
+ }
+ break;
+
+ case 137:
+
+/* Line 1806 of yacc.c */
+#line 730 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_SPR;
+ (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 138:
+
+/* Line 1806 of yacc.c */
+#line 736 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = (yyvsp[(1) - (4)].lval);
+ (yyval.addr).offset = (yyvsp[(3) - (4)].lval);
+ }
+ break;
+
+ case 140:
+
+/* Line 1806 of yacc.c */
+#line 745 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_FPSCR;
+ (yyval.addr).reg = NREG;
+ }
+ break;
+
+ case 141:
+
+/* Line 1806 of yacc.c */
+#line 753 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_FPSCR;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+ }
+ break;
+
+ case 142:
+
+/* Line 1806 of yacc.c */
+#line 761 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_FREG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 143:
+
+/* Line 1806 of yacc.c */
+#line 767 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_FREG;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+ }
+ break;
+
+ case 144:
+
+/* Line 1806 of yacc.c */
+#line 775 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_CREG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 145:
+
+/* Line 1806 of yacc.c */
+#line 781 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_CREG;
+ (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
+ }
+ break;
+
+ case 146:
+
+/* Line 1806 of yacc.c */
+#line 789 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_REG;
+ (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
+ }
+ break;
+
+ case 147:
+
+/* Line 1806 of yacc.c */
+#line 797 "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 148:
+
+/* Line 1806 of yacc.c */
+#line 818 "a.y"
+ {
+ (yyval.addr) = (yyvsp[(2) - (2)].addr);
+ (yyval.addr).type = D_CONST;
+ }
+ break;
+
+ case 149:
+
+/* Line 1806 of yacc.c */
+#line 823 "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 150:
+
+/* Line 1806 of yacc.c */
+#line 831 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_FCONST;
+ (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
+ }
+ break;
+
+ case 151:
+
+/* Line 1806 of yacc.c */
+#line 837 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_FCONST;
+ (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
+ }
+ break;
+
+ case 152:
+
+/* Line 1806 of yacc.c */
+#line 844 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_CONST;
+ (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 154:
+
+/* Line 1806 of yacc.c */
+#line 853 "a.y"
+ {
+ if((yyval.lval) < 0 || (yyval.lval) >= NREG)
+ print("register value out of range\n");
+ (yyval.lval) = (yyvsp[(3) - (4)].lval);
+ }
+ break;
+
+ case 155:
+
+/* Line 1806 of yacc.c */
+#line 861 "a.y"
+ {
+ (yyval.addr) = nullgen;
+ (yyval.addr).type = D_OREG;
+ (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
+ (yyval.addr).offset = 0;
+ }
+ break;
+
+ case 156:
+
+/* Line 1806 of yacc.c */
+#line 868 "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 158:
+
+/* Line 1806 of yacc.c */
+#line 879 "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 159:
+
+/* Line 1806 of yacc.c */
+#line 888 "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 160:
+
+/* Line 1806 of yacc.c */
+#line 896 "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 161:
+
+/* Line 1806 of yacc.c */
+#line 904 "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 164:
+
+/* Line 1806 of yacc.c */
+#line 916 "a.y"
+ {
+ (yyval.lval) = 0;
+ }
+ break;
+
+ case 165:
+
+/* Line 1806 of yacc.c */
+#line 920 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 166:
+
+/* Line 1806 of yacc.c */
+#line 924 "a.y"
+ {
+ (yyval.lval) = -(yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 171:
+
+/* Line 1806 of yacc.c */
+#line 936 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
+ }
+ break;
+
+ case 172:
+
+/* Line 1806 of yacc.c */
+#line 940 "a.y"
+ {
+ (yyval.lval) = -(yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 173:
+
+/* Line 1806 of yacc.c */
+#line 944 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 174:
+
+/* Line 1806 of yacc.c */
+#line 948 "a.y"
+ {
+ (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
+ }
+ break;
+
+ case 175:
+
+/* Line 1806 of yacc.c */
+#line 952 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(2) - (3)].lval);
+ }
+ break;
+
+ case 177:
+
+/* Line 1806 of yacc.c */
+#line 959 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 178:
+
+/* Line 1806 of yacc.c */
+#line 963 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 179:
+
+/* Line 1806 of yacc.c */
+#line 967 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 180:
+
+/* Line 1806 of yacc.c */
+#line 971 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 181:
+
+/* Line 1806 of yacc.c */
+#line 975 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 182:
+
+/* Line 1806 of yacc.c */
+#line 979 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
+ }
+ break;
+
+ case 183:
+
+/* Line 1806 of yacc.c */
+#line 983 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
+ }
+ break;
+
+ case 184:
+
+/* Line 1806 of yacc.c */
+#line 987 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 185:
+
+/* Line 1806 of yacc.c */
+#line 991 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+ case 186:
+
+/* Line 1806 of yacc.c */
+#line 995 "a.y"
+ {
+ (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
+ }
+ break;
+
+
+
+/* Line 1806 of yacc.c */
+#line 3566 "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);
+ 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:
+ /* 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)
+ {
+ ++yynerrs;
+#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;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead 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 lookahead 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 (!yypact_value_is_default (yyn))
+ {
+ 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);
+ }
+
+ *++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;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#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);
+ }
+ /* 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..f1b4a7223
--- /dev/null
+++ b/src/cmd/9a/y.tab.h
@@ -0,0 +1,192 @@
+/* A Bison parser, made by GNU Bison 2.5. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ 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.
+
+ 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/>. */
+
+/* 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 2068 of yacc.c */
+#line 38 "a.y"
+
+ Sym *sym;
+ vlong lval;
+ double dval;
+ char sval[8];
+ Addr addr;
+
+
+
+/* Line 2068 of yacc.c */
+#line 184 "y.tab.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 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/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 31c4da381..8fd2e998a 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},
@@ -1163,12 +1184,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"))
@@ -1367,6 +1402,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/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/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/walk.c b/src/cmd/gc/walk.c
index b761662d1..eaa044055 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -3368,6 +3368,9 @@ walkrotate(Node **np)
int w, sl, sr, s;
Node *l, *r;
Node *n;
+
+ if(thechar == '9')
+ return;
n = *np;
@@ -3493,6 +3496,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..fa8af5f83
--- /dev/null
+++ b/src/liblink/obj9.c
@@ -0,0 +1,1083 @@
+// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <link.h>
+#include "../cmd/9l/9.out.h"
+#include "../runtime/stack.h"
+#include "../runtime/funcdata.h"
+
+static Prog zprg = {
+ .as = AGOK,
+ .reg = NREG,
+ .from = {
+ .name = D_NONE,
+ .type = D_NONE,
+ .reg = NREG,
+ },
+ .from3 = {
+ .name = D_NONE,
+ .type = D_NONE,
+ .reg = NREG,
+ },
+ .to = {
+ .name = D_NONE,
+ .type = D_NONE,
+ .reg = NREG,
+ },
+};
+
+static int
+symtype(Addr *a)
+{
+ return a->name;
+}
+
+static int
+isdata(Prog *p)
+{
+ return p->as == ADATA || p->as == AGLOBL;
+}
+
+static int
+iscall(Prog *p)
+{
+ return p->as == ABL;
+}
+
+static int
+datasize(Prog *p)
+{
+ return p->reg;
+}
+
+static int
+textflag(Prog *p)
+{
+ return p->reg;
+}
+
+static void
+settextflag(Prog *p, int f)
+{
+ p->reg = f;
+}
+
+static void
+progedit(Link *ctxt, Prog *p)
+{
+ char literal[64];
+ LSym *s;
+
+ USED(ctxt);
+
+ p->from.class = 0;
+ p->to.class = 0;
+
+ // Rewrite BR/BL to symbol as D_BRANCH.
+ switch(p->as) {
+ case ABR:
+ case ABL:
+ case ARETURN:
+ case ADUFFZERO:
+ case ADUFFCOPY:
+ if(p->to.sym != nil)
+ p->to.type = D_BRANCH;
+ break;
+ }
+
+ // Rewrite float constants to values stored in memory.
+ switch(p->as) {
+ case AFMOVS:
+ if(p->from.type == D_FCONST) {
+ int32 i32;
+ float32 f32;
+ f32 = p->from.u.dval;
+ memmove(&i32, &f32, 4);
+ sprint(literal, "$f32.%08ux", (uint32)i32);
+ s = linklookup(ctxt, literal, 0);
+ s->size = 4;
+ p->from.type = D_OREG;
+ p->from.sym = s;
+ p->from.name = D_EXTERN;
+ p->from.offset = 0;
+ }
+ break;
+ case AFMOVD:
+ if(p->from.type == D_FCONST) {
+ int64 i64;
+ memmove(&i64, &p->from.u.dval, 8);
+ sprint(literal, "$f64.%016llux", (uvlong)i64);
+ s = linklookup(ctxt, literal, 0);
+ s->size = 8;
+ p->from.type = D_OREG;
+ p->from.sym = s;
+ p->from.name = D_EXTERN;
+ p->from.offset = 0;
+ }
+ break;
+ case AMOVD:
+ if(p->from.type == D_CONST && p->from.name == D_NONE && (int64)(uint32)p->from.offset != p->from.offset) {
+ sprint(literal, "$i64.%016llux", (uvlong)p->from.offset);
+ s = linklookup(ctxt, literal, 0);
+ s->size = 8;
+ p->from.type = D_OREG;
+ p->from.sym = s;
+ p->from.name = D_EXTERN;
+ p->from.offset = 0;
+ }
+ }
+
+ // Rewrite SUB constants into ADD.
+ switch(p->as) {
+ case ASUBC:
+ if(p->from.type == D_CONST) {
+ p->from.offset = -p->from.offset;
+ p->as = AADDC;
+ }
+ break;
+
+ case ASUBCCC:
+ if(p->from.type == D_CONST) {
+ p->from.offset = -p->from.offset;
+ p->as = AADDCCC;
+ }
+ break;
+
+ case ASUB:
+ if(p->from.type == D_CONST) {
+ p->from.offset = -p->from.offset;
+ p->as = AADD;
+ }
+ break;
+ }
+}
+
+static Prog* stacksplit(Link*, Prog*, int32, int);
+
+static void
+parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
+{
+ *textstksiz = arg & 0xffffffffLL;
+ if(*textstksiz & 0x80000000LL)
+ *textstksiz = -(-*textstksiz & 0xffffffffLL);
+
+ *textarg = (arg >> 32) & 0xffffffffLL;
+ if(*textarg & 0x80000000LL)
+ *textarg = 0;
+ *textarg = (*textarg+7) & ~7LL;
+}
+
+static void
+addstacksplit(Link *ctxt, LSym *cursym)
+{
+ Prog *p, *q, *p1, *p2, *q1;
+ int o, mov, aoffset;
+ vlong textstksiz, textarg;
+ int32 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.
+
+
+ p = appendp(ctxt, p);
+ p->as = AMOVD;
+ p->from.type = D_OREG;
+ p->from.reg = REGG;
+ p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
+ p->to.type = D_REG;
+ p->to.reg = 3;
+
+ p = appendp(ctxt, p);
+ p->as = ACMP;
+ p->from.type = D_REG;
+ p->from.reg = 0;
+ p->to.type = D_REG;
+ p->to.reg = 3;
+
+ p = appendp(ctxt, p);
+ p->as = ABEQ;
+ p->to.type = D_BRANCH;
+ p1 = p;
+
+ p = appendp(ctxt, p);
+ p->as = AMOVD;
+ p->from.type = D_OREG;
+ p->from.reg = 3;
+ p->from.offset = 0; // Panic.argp
+ p->to.type = D_REG;
+ p->to.reg = 4;
+
+ p = appendp(ctxt, p);
+ p->as = AADD;
+ p->from.type = D_CONST;
+ p->from.offset = autosize+8;
+ p->reg = REGSP;
+ p->to.type = D_REG;
+ p->to.reg = 5;
+
+ p = appendp(ctxt, p);
+ p->as = ACMP;
+ p->from.type = D_REG;
+ p->from.reg = 4;
+ p->to.type = D_REG;
+ p->to.reg = 5;
+
+ p = appendp(ctxt, p);
+ p->as = ABNE;
+ p->to.type = D_BRANCH;
+ p2 = p;
+
+ p = appendp(ctxt, p);
+ p->as = AADD;
+ p->from.type = D_CONST;
+ p->from.offset = 8;
+ p->reg = REGSP;
+ p->to.type = D_REG;
+ p->to.reg = 6;
+
+ p = appendp(ctxt, p);
+ p->as = AMOVD;
+ p->from.type = D_REG;
+ p->from.reg = 6;
+ p->to.type = D_OREG;
+ p->to.reg = 3;
+ p->to.offset = 0; // Panic.argp
+
+ p = appendp(ctxt, p);
+ p->as = ANOP;
+ p1->pcond = p;
+ p2->pcond = p;
+ }
+
+ 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 *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;
+
+ 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;
+
+ 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;
+
+ // 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..0cb86144a
--- /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 "../../cmd/ld/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/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.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_power64x.s b/src/runtime/asm_power64x.s
new file mode 100644
index 000000000..a0511de8e
--- /dev/null
+++ b/src/runtime/asm_power64x.s
@@ -0,0 +1,1045 @@
+// Copyright 2014 The Go Authors. 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 "../../cmd/ld/textflag.h"
+
+TEXT _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_stackguard(g)
+ MOVD R3, g_stackguard0(g)
+ MOVD R1, g_stackbase(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·hashinit(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)
+ ARGSIZE(24)
+ BL runtime·newproc(SB)
+ ARGSIZE(-1)
+ 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(void (*fn)(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), R4
+ MOVD R4, CTR
+ MOVD (g_sched+gobuf_sp)(g), R1
+ 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-8
+ UNDEF
+ BL (LR) // make sure this function is not leaf
+ RETURN
+
+// void onM(void (*fn)())
+// calls fn() on the M stack.
+// switches to the M stack if not already on it, and
+// switches back when fn() returns.
+TEXT runtime·onM(SB), NOSPLIT, $0-8
+ MOVD fn+0(FP), R3 // R3 = fn
+ MOVD R3, CTR
+ MOVD g_m(g), R4 // R4 = m
+ MOVD m_g0(R4), R5 // R5 = g0
+ CMP g, R5
+ BEQ onm
+
+ // 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), R1
+
+ // call target function
+ ARGSIZE(0)
+ 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
+ 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)
+
+ MOVW R3, m_moreframesize(R7)
+ MOVW R4, m_moreargsize(R7)
+
+ // 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 $8(R1), R8 // f's argument pointer
+ MOVD R8, m_moreargp(R7)
+ 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)
+
+// Called from panic. Mimics morestack,
+// reuses stack growth code to create a frame
+// with the desired args running the desired function.
+//
+// func call(fn *byte, arg *byte, argsize uint32).
+TEXT runtime·newstackcall(SB), NOSPLIT, $-8-20
+ // Save our caller's state as the PC and SP to restore when
+ // returning from f.
+ MOVD g_m(g), R5
+ MOVD LR, R31
+ MOVD R31, (m_morebuf+gobuf_pc)(R5) // our caller's PC
+ MOVD R1, (m_morebuf+gobuf_sp)(R5) // our caller's SP
+ MOVD g, (m_morebuf+gobuf_g)(R5)
+
+ // Save our own state as the PC and SP to restore if this
+ // goroutine needs to be restarted.
+ MOVD $runtime·newstackcall(SB), R7
+ MOVD R7, (g_sched+gobuf_pc)(g)
+ MOVD LR, R31
+ MOVD R31, (g_sched+gobuf_lr)(g)
+ MOVD R1, (g_sched+gobuf_sp)(g)
+
+ // Set up morestack arguments to call f on a new stack.
+ // We set f's frame size to 1, as a hint to newstack that
+ // this is a call from runtime.newstackcall.
+ // If it turns out that f needs a larger frame than the
+ // default stack, f's usual stack growth prolog will
+ // allocate a new segment (and recopy the arguments).
+ MOVD fn+0(FP), R7
+ MOVD args+8(FP), R8
+ MOVW n+16(FP), R9
+
+ MOVD R7, m_cret(R5)
+ MOVD R8, m_moreargp(R5)
+ MOVW R9, m_moreargsize(R5)
+ MOVD $1, R10
+ MOVW R10, m_moreframesize(R5)
+
+ // call newstack on m->g0's stack
+ MOVD m_g0(R5), g
+ MOVD (g_sched+gobuf_sp)(g), R1
+ BR runtime·newstack(SB)
+
+// reflect·call: call a function with the given argument list
+// func call(f *FuncVal, arg *byte, argsize 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 $runtime·NAME(SB), R31; \
+ MOVD R31, CTR; \
+ BR (CTR)
+
+// Note: can't just "BR runtime·NAME(SB)" - bad inlining results.
+TEXT reflect·call(SB), NOSPLIT, $-8-24
+ MOVW argsize+16(FP), R3
+ DISPATCH(call16, 16)
+ DISPATCH(call32, 32)
+ DISPATCH(call64, 64)
+ DISPATCH(call128, 128)
+ DISPATCH(call256, 256)
+ DISPATCH(call512, 512)
+ DISPATCH(call1024, 1024)
+ DISPATCH(call2048, 2048)
+ DISPATCH(call4096, 4096)
+ DISPATCH(call8192, 8192)
+ DISPATCH(call16384, 16384)
+ DISPATCH(call32768, 32768)
+ DISPATCH(call65536, 65536)
+ DISPATCH(call131072, 131072)
+ DISPATCH(call262144, 262144)
+ DISPATCH(call524288, 524288)
+ DISPATCH(call1048576, 1048576)
+ DISPATCH(call2097152, 2097152)
+ DISPATCH(call4194304, 4194304)
+ DISPATCH(call8388608, 8388608)
+ DISPATCH(call16777216, 16777216)
+ DISPATCH(call33554432, 33554432)
+ DISPATCH(call67108864, 67108864)
+ DISPATCH(call134217728, 134217728)
+ DISPATCH(call268435456, 268435456)
+ DISPATCH(call536870912, 536870912)
+ DISPATCH(call1073741824, 1073741824)
+ MOVD $runtime·badreflectcall(SB), R31
+ MOVD R31, CTR
+ BR (CTR)
+
+// Argument map for the callXX frames. Each has one
+// stack map (for the single call) with 3 arguments.
+DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
+DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args
+DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4))
+GLOBL gcargs_reflectcall<>(SB),RODATA,$12
+
+// callXX frames have no locals
+DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
+DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals
+GLOBL gclocals_reflectcall<>(SB),RODATA,$8
+
+#define CALLFN(NAME,MAXSIZE) \
+TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \
+ FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \
+ FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\
+ /* 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)
+
+// Return point when leaving stack.
+//
+// Lessstack can appear in stack traces for the same reason
+// as morestack; in that context, it has 0 arguments.
+TEXT runtime·lessstack(SB), NOSPLIT, $-8-0
+ // Save return value in m->cret
+ MOVD g_m(g), R5
+ MOVD R3, m_cret(R5)
+
+ // Call oldstack on m->g0's stack.
+ MOVD m_g0(R5), g
+ MOVD (g_sched+gobuf_sp)(g), R1
+ BL runtime·oldstack(SB)
+
+// 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-16
+ MOVD p+0(FP), R3
+ MOVW old+8(FP), R4
+ MOVW new+12(FP), R5
+ SYNC
+ LWAR (R3), R6
+ CMPW R6, R4
+ BNE 7(PC)
+ STWCCC R5, (R3)
+ BNE -5(PC)
+ MOVD $1, R3
+ SYNC
+ ISYNC
+ RETURN
+ MOVD $0, R3
+ BR -4(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-24
+ MOVD p+0(FP), R3
+ MOVD old+8(FP), R4
+ MOVD new+16(FP), R5
+ SYNC
+ LDAR (R3), R6
+ CMP R6, R4
+ BNE 7(PC)
+ STDCCC R5, (R3)
+ BNE -5(PC)
+ MOVD $1, R3
+ SYNC
+ ISYNC
+ RETURN
+ MOVD $0, R3
+ BR -4(PC)
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+// if(*val == old){
+// *val = new;
+// return 1;
+// } else
+// return 0;
+TEXT runtime·casp(SB), NOSPLIT, $0-24
+ BR runtime·cas64(SB)
+
+// uint32 xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+// *val += delta;
+// return *val;
+TEXT runtime·xadd(SB), NOSPLIT, $0-12
+ 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, R3
+ RETURN
+
+TEXT runtime·xadd64(SB), NOSPLIT, $0-16
+ 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
+ RETURN
+
+TEXT runtime·xchg(SB), NOSPLIT, $0-12
+ MOVD p+0(FP), R4
+ MOVW new+8(FP), R5
+ SYNC
+ LWAR (R4), R3
+ STWCCC R5, (R4)
+ BNE -3(PC)
+ SYNC
+ ISYNC
+ RETURN
+
+TEXT runtime·xchg64(SB), NOSPLIT, $0-16
+ MOVD p+0(FP), R4
+ MOVD new+8(FP), R5
+ SYNC
+ LDAR (R4), R3
+ STDCCC R5, (R4)
+ BNE -3(PC)
+ SYNC
+ ISYNC
+ RETURN
+
+TEXT runtime·xchgp(SB), NOSPLIT, $0-16
+ BR runtime·xchg64(SB)
+
+TEXT runtime·procyield(SB),NOSPLIT,$0-0
+ RETURN
+
+TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16
+ BR runtime·atomicstore64(SB)
+
+TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
+ MOVD 0(FP), R3
+ MOVW 8(FP), R4
+ SYNC
+ MOVW R4, 0(R3)
+ RETURN
+
+TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
+ MOVD 0(FP), R3
+ MOVD 8(FP), R4
+ SYNC
+ MOVD R4, 0(R3)
+ RETURN
+
+// void jmpdefer(fn, 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 fn+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 runtime·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 runtime·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-16
+ 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-8
+ MOVD 0(R1), R3
+ 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 x+8(FP),R3 // addr of first arg
+ MOVD R3, 0(R1) // set calling pc
+ RETURN
+
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-8
+ MOVD sp+0(FP), R3
+ SUB $8, R3
+ RETURN
+
+TEXT runtime·abort(SB),NOSPLIT,$-4-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-0
+ MOVW SPR(TBRU), R4
+ MOVW SPR(TBRL), R3
+ MOVW SPR(TBRU), R5
+ CMPW R4, R5
+ BNE -4(PC)
+ SLD $32, R5
+ OR R5, R3
+ RETURN
+
+TEXT runtime·stackguard(SB),NOSPLIT,$0-16
+ MOVD R1, R3
+ MOVD R3, sp+0(FP)
+ MOVD g_stackguard(g), R3
+ MOVD R3, limit+8(FP)
+ RETURN
+
+GLOBL runtime·tls0(SB), $64
+
+// 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-24
+ 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
+_next:
+ CMP R3, R8
+ BNE 3(PC)
+ MOVD $1, R3
+ RETURN
+ MOVBZU 1(R3), R6
+ MOVBZU 1(R4), R7
+ CMP R6, R7
+ BEQ _next
+
+ MOVD $0, R3
+ RETURN
+
+TEXT runtime·gomemeq(SB),NOSPLIT,$0-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
+_next2:
+ 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 _next2
+
+ MOVB R0, ret+24(FP)
+ RETURN
+
+// eqstring tests whether two strings are equal.
+// See runtime_test.go:eqstring_generic for
+// equivlaent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
+ MOVD s1len+8(FP), R4
+ MOVD s2len+24(FP), R5
+ CMP R4, R5
+ BNE str_noteq
+
+ MOVD s1str+0(FP), R3
+ MOVD s2str+16(FP), R4
+ SUB $1, R3
+ SUB $1, R4
+ ADD R3, R5, R8
+eq_next:
+ 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 eq_next
+str_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 _notequal
+
+ MOVD a+0(FP), R5
+ MOVD b+24(FP), R6
+ SUB $1, R5
+ SUB $1, R6
+ ADD R5, R3 // end-1
+
+_byteseq_next:
+ CMP R5, R3
+ BEQ _equal // reached the end
+ MOVBZU 1(R5), R4
+ MOVBZU 1(R6), R7
+ CMP R4, R7
+ BEQ _byteseq_next
+
+_notequal:
+ 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
+
+_index_loop:
+ CMP R3, R4
+ BEQ _index_notfound
+ MOVBZU 1(R3), R7
+ CMP R7, R5
+ BNE _index_loop
+
+ SUB R6, R3 // remove base
+ MOVD R3, ret+32(FP)
+ RETURN
+
+_index_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
+
+_index2_loop:
+ CMP R3, R4
+ BEQ _index2_notfound
+ MOVBZU 1(R3), R7
+ CMP R7, R5
+ BNE _index2_loop
+
+ SUB R6, R3 // remove base
+ MOVD R3, ret+24(FP)
+ RETURN
+
+_index2_notfound:
+ MOVD $-1, R3
+ MOVD R3, ret+24(FP)
+ RETURN
+
+
+TEXT runtime·timenow(SB), NOSPLIT, $0-0
+ BR time·now(SB)
+
+// A Duff's device for zeroing memory.
+// The compiler jumps to computed addresses within
+// this routine to zero chunks of memory. Do not
+// 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·fastrand2(SB), NOSPLIT, $0-4
+ MOVD g_m(g), R4
+ MOVD m_fastrand(R4), R3
+ ADD R3, R3
+ CMP R3, $0
+ BGE 2(PC)
+ XOR $0x88888eef, R3
+ MOVD R3, m_fastrand(R4)
+ MOVD R3, ret+0(FP)
+ RETURN
+
+// The gohash and goeq trampolines are necessary while we have
+// both Go and C calls to alg functions. Once we move all call
+// sites to Go, we can redo the hash/eq functions to use the
+// Go calling convention and remove these.
+
+// convert call to:
+// func (alg unsafe.Pointer, p unsafe.Pointer, size uintpr, seed uintptr) uintptr
+// to:
+// func (hash *uintptr, size uintptr, p unsafe.Pointer)
+TEXT runtime·gohash(SB), NOSPLIT, $24-40
+ FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_gohash<>(SB)
+ FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_gohash<>(SB)
+ MOVD a+0(FP), R3
+ MOVD alg_hash(R3), R3
+ MOVD R3, CTR
+ MOVD p+8(FP), R4
+ MOVD size+16(FP), R5
+ MOVD seed+24(FP), R6
+ MOVD R6, ret+32(FP)
+ MOVD $ret+32(FP), R7
+ MOVD R7, 8(R1)
+ MOVD R5, 16(R1)
+ MOVD R4, 24(R1)
+ PCDATA $PCDATA_StackMapIndex, $0
+ BL (CTR)
+ RETURN
+
+DATA gcargs_gohash<>+0x00(SB)/4, $1 // 1 stackmap
+DATA gcargs_gohash<>+0x04(SB)/4, $10 // 5 args
+DATA gcargs_gohash<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2))
+GLOBL gcargs_gohash<>(SB),RODATA,$12
+
+DATA gclocals_gohash<>+0x00(SB)/4, $1 // 1 stackmap
+DATA gclocals_gohash<>+0x04(SB)/4, $0 // 0 locals
+GLOBL gclocals_gohash<>(SB),RODATA,$8
+
+// convert call to:
+// func (alg unsafe.Pointer, p, q unsafe.Pointer, size uintptr) bool
+// to:
+// func (eq *bool, size uintptr, p, q unsafe.Pointer)
+TEXT runtime·goeq(SB), NOSPLIT, $32-33
+ FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_goeq<>(SB)
+ FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_goeq<>(SB)
+ MOVD alg+0(FP), R3
+ MOVD alg_equal(R3), R3
+ MOVD R3, CTR
+ MOVD p+8(FP), R4
+ MOVD q+16(FP), R5
+ MOVD size+24(FP), R6
+ MOVD $ret+32(FP), R7
+ MOVD R7, 8(R1)
+ MOVD R6, 16(R1)
+ MOVD R5, 24(R1)
+ MOVD R4, 32(R1)
+ PCDATA $PCDATA_StackMapIndex, $0
+ BL (CTR)
+ RETURN
+
+DATA gcargs_goeq<>+0x00(SB)/4, $1 // 1 stackmap
+DATA gcargs_goeq<>+0x04(SB)/4, $10 // 5 args
+DATA gcargs_goeq<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsPointer<<4))
+GLOBL gcargs_goeq<>(SB),RODATA,$12
+
+DATA gclocals_goeq<>+0x00(SB)/4, $1 // 1 stackmap
+DATA gclocals_goeq<>+0x04(SB)/4, $0 // 0 locals
+GLOBL gclocals_goeq<>(SB),RODATA,$8
diff --git a/src/runtime/atomic_power64x.s b/src/runtime/atomic_power64x.s
new file mode 100644
index 000000000..c08590ac9
--- /dev/null
+++ b/src/runtime/atomic_power64x.s
@@ -0,0 +1,37 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build power64 power64le
+
+#include "../../cmd/ld/textflag.h"
+
+// uint32 runtime·atomicload(uint32 volatile* addr)
+TEXT ·atomicload(SB),NOSPLIT,$-8-8
+ MOVD 0(FP), R3
+ SYNC
+ MOVWZ 0(R3), R3
+ CMPW R3, R3, CR7
+ BC 4, 30, 1(PC) // bne- cr7,0x4
+ ISYNC
+ RETURN
+
+// uint64 runtime·atomicload64(uint64 volatile* addr)
+TEXT ·atomicload64(SB),NOSPLIT,$-8-8
+ MOVD 0(FP), R3
+ SYNC
+ MOVD 0(R3), R3
+ CMP R3, R3, CR7
+ BC 4, 30, 1(PC) // bne- cr7,0x4
+ ISYNC
+ RETURN
+
+// void *runtime·atomicloadp(void *volatile *addr)
+TEXT ·atomicloadp(SB),NOSPLIT,$-8-8
+ MOVD 0(FP), R3
+ SYNC
+ MOVD 0(R3), R3
+ CMP R3, R3, CR7
+ BC 4, 30, 1(PC) // bne- cr7,0x4
+ ISYNC
+ RETURN
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..64f145672
--- /dev/null
+++ b/src/runtime/defs_linux_power64.h
@@ -0,0 +1,211 @@
+// 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 Sigaction Sigaction;
+typedef struct Siginfo Siginfo;
+typedef struct Itimerval Itimerval;
+typedef struct EpollEvent EpollEvent;
+typedef uint64 Usigset;
+
+#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 Sigaction {
+ void *sa_handler;
+ uint64 sa_flags;
+ void *sa_restorer;
+ Usigset 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];
+ uint64 data;
+};
+
+
+#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 Usigset Usigset;
+typedef struct Ptregs Ptregs;
+typedef struct Vreg Vreg;
+typedef struct SigaltstackT SigaltstackT;
+typedef struct Sigcontext Sigcontext;
+typedef struct Ucontext Ucontext;
+
+#pragma pack on
+
+//struct Usigset {
+// uint64 sig[1];
+//};
+//typedef Sigset Usigset;
+
+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;
+ Usigset uc_sigmask;
+ Usigset __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..64f145672
--- /dev/null
+++ b/src/runtime/defs_linux_power64le.h
@@ -0,0 +1,211 @@
+// 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 Sigaction Sigaction;
+typedef struct Siginfo Siginfo;
+typedef struct Itimerval Itimerval;
+typedef struct EpollEvent EpollEvent;
+typedef uint64 Usigset;
+
+#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 Sigaction {
+ void *sa_handler;
+ uint64 sa_flags;
+ void *sa_restorer;
+ Usigset 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];
+ uint64 data;
+};
+
+
+#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 Usigset Usigset;
+typedef struct Ptregs Ptregs;
+typedef struct Vreg Vreg;
+typedef struct SigaltstackT SigaltstackT;
+typedef struct Sigcontext Sigcontext;
+typedef struct Ucontext Ucontext;
+
+#pragma pack on
+
+//struct Usigset {
+// uint64 sig[1];
+//};
+//typedef Sigset Usigset;
+
+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;
+ Usigset uc_sigmask;
+ Usigset __unused[15];
+ Sigcontext uc_mcontext;
+};
+
+
+#pragma pack off
diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go
index 88f6703f9..7d432983b 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")
}
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 9b4264f2b..294bc4870 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -4,9 +4,7 @@
package runtime
-import (
- "unsafe"
-)
+import "unsafe"
const (
debugMalloc = false
@@ -261,8 +259,10 @@ func mallocgc(size uintptr, typ *_type, flags int) 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)
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_power64x.s b/src/runtime/memclr_power64x.s
new file mode 100644
index 000000000..4a2437c20
--- /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 "../../cmd/ld/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..b618f0ad7
--- /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 "../../cmd/ld/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 2ff64aaa3..02f7eba12 100644
--- a/src/runtime/mgc0.c
+++ b/src/runtime/mgc0.c
@@ -65,7 +65,7 @@
enum {
Debug = 0,
DebugPtrs = 0, // if 1, print trace of every pointer load during GC
- ConcurrentSweep = 1,
+ ConcurrentSweep = 0,
WorkbufSize = 4*1024,
FinBlockSize = 4*1024,
@@ -1779,7 +1779,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;
@@ -1797,9 +1797,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/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_linux.c b/src/runtime/os_linux.c
index 0d8ffc995..9bd123d59 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.
@@ -298,7 +314,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/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/proc.c b/src/runtime/proc.c
index 1426790f4..11af6a1ea 100644
--- a/src/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -2124,7 +2124,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);
@@ -2184,7 +2184,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;
diff --git a/src/runtime/rt0_linux_power64.s b/src/runtime/rt0_linux_power64.s
new file mode 100644
index 000000000..e944bcdbf
--- /dev/null
+++ b/src/runtime/rt0_linux_power64.s
@@ -0,0 +1,17 @@
+#include "../../cmd/ld/textflag.h"
+
+// actually a function descriptor for _main<>(SB)
+TEXT _rt0_power64_linux(SB),7,$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 $_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..051815dbc
--- /dev/null
+++ b/src/runtime/rt0_linux_power64le.s
@@ -0,0 +1,14 @@
+#include "../../cmd/ld/textflag.h"
+
+TEXT _rt0_power64le_linux(SB),7,$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 $_rt0_go(SB), R31
+ MOVD R31, CTR
+ BR (CTR)
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/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/sys_linux_power64x.s b/src/runtime/sys_linux_power64x.s
new file mode 100644
index 000000000..fbd59a052
--- /dev/null
+++ b/src/runtime/sys_linux_power64x.s
@@ -0,0 +1,367 @@
+// Copyright 2014 The Go Authors. 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 "../../cmd/ld/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-8
+ MOVW 8(R1), R3
+ SYSCALL $SYS_exit_group
+ RETURN
+
+TEXT runtime·exit1(SB),NOSPLIT,$-8-8
+ MOVW 8(R1), R3
+ SYSCALL $SYS_exit
+ RETURN
+
+TEXT runtime·open(SB),NOSPLIT,$-8-16
+ MOVD 8(R1), R3
+ MOVW 16(R1), R4
+ MOVW 20(R1), R5
+ SYSCALL $SYS_open
+ RETURN
+
+TEXT runtime·close(SB),NOSPLIT,$-8-16
+ MOVW 8(R1), R3
+ SYSCALL $SYS_close
+ RETURN
+
+TEXT runtime·write(SB),NOSPLIT,$-8-24
+ MOVD 8(R1), R3
+ MOVD 16(R1), R4
+ MOVW 24(R1), R5
+ SYSCALL $SYS_write
+ RETURN
+
+TEXT runtime·read(SB),NOSPLIT,$-8-24
+ MOVW 8(R1), R3
+ MOVD 16(R1), R4
+ MOVW 24(R1), R5
+ SYSCALL $SYS_read
+ RETURN
+
+TEXT runtime·getrlimit(SB),NOSPLIT,$-8-24
+ MOVW 8(R1), R3
+ MOVD 16(R1), R4
+ SYSCALL $SYS_ugetrlimit
+ RETURN
+
+TEXT runtime·usleep(SB),NOSPLIT,$-8-16
+ 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 8(R1), R3
+ MOVD 16(R1), R4
+ MOVD 24(R1), R5
+ SYSCALL $SYS_setitimer
+ RETURN
+
+TEXT runtime·mincore(SB),NOSPLIT,$-8-24
+ MOVD 8(R1), R3
+ MOVD 16(R1), R4
+ MOVD 24(R1), R5
+ SYSCALL $SYS_mincore
+ 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
+ RETURN
+
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-32
+ MOVW 8(R1), R3
+ MOVD 16(R1), R4
+ MOVD 24(R1), R5
+ MOVW 32(R1), R6
+ SYSCALL $SYS_rt_sigprocmask
+ BVC 2(PC)
+ MOVD R0, 0xf1(R0) // crash
+ RETURN
+
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-32
+ MOVD 8(R1), R3
+ MOVD 16(R1), R4
+ MOVD 24(R1), R5
+ MOVD 32(R1), R6
+ SYSCALL $SYS_rt_sigaction
+ 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 8(R1), R3
+ MOVD 16(R1), R4
+ MOVW 24(R1), R5
+ MOVW 28(R1), R6
+ MOVW 32(R1), R7
+ MOVW 36(R1), R8
+
+ SYSCALL $SYS_mmap
+ RETURN
+
+TEXT runtime·munmap(SB),NOSPLIT,$-8
+ MOVD 8(R1), R3
+ MOVD 16(R1), R4
+ SYSCALL $SYS_munmap
+ BVC 2(PC)
+ MOVD R0, 0xf3(R0)
+ RETURN
+
+TEXT runtime·madvise(SB),NOSPLIT,$-8
+ MOVD 8(R1), R3
+ MOVD 16(R1), R4
+ MOVD 24(R1), 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 8(R1), R3
+ MOVW 16(R1), R4
+ MOVW 20(R1), R5
+ MOVD 24(R1), R6
+ MOVD 32(R1), R7
+ MOVW 40(R1), R8
+ SYSCALL $SYS_futex
+ RETURN
+
+// int64 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·clone(SB),NOSPLIT,$-8
+ MOVW flags+0(FP), R3
+ MOVD stack+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 2(PC)
+ 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 8(R1), R3
+ MOVD 16(R1), R4
+ MOVD 24(R1), R5
+ SYSCALL $SYS_sched_getaffinity
+ RETURN
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),NOSPLIT,$-8
+ MOVW 8(R1), R3
+ SYSCALL $SYS_epoll_create
+ RETURN
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
+ MOVW 8(R1), R3
+ SYSCALL $SYS_epoll_create1
+ RETURN
+
+// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
+TEXT runtime·epollctl(SB),NOSPLIT,$-8
+ MOVW 8(R1), R3
+ MOVW 12(R1), R4
+ MOVW 16(R1), R5
+ MOVD 24(R1), R6
+ SYSCALL $SYS_epoll_ctl
+ RETURN
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),NOSPLIT,$-8
+ MOVW 8(R1), R3
+ MOVD 16(R1), R4
+ MOVW 24(R1), R5
+ MOVW 28(R1), R6
+ SYSCALL $SYS_epoll_wait
+ RETURN
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),NOSPLIT,$-8
+ MOVW 8(R1), R3 // fd
+ MOVD $2, R4 // F_SETFD
+ MOVD $1, R5 // FD_CLOEXEC
+ SYSCALL $SYS_fcntl
+ RETURN
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/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/sync/atomic/asm_power64x.s b/src/sync/atomic/asm_power64x.s
new file mode 100644
index 000000000..bdb1dcff4
--- /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 "../../../cmd/ld/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/syscall/asm_linux_power64x.s b/src/syscall/asm_linux_power64x.s
new file mode 100644
index 000000000..c9b0fe320
--- /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 "../../cmd/ld/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/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]