From 29ff84d03b5db4464b4ad5a67388825c56ecc95e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 Aug 2014 14:58:17 -0400 Subject: cmd/dist, go/build: add power64, power64le to known GOARCH lists LGTM=dave, minux, aram R=minux, dave, bradfitz, aram CC=golang-codereviews https://codereview.appspot.com/119470043 --- src/cmd/dist/build.c | 4 +++- src/pkg/go/build/build.go | 2 ++ src/pkg/go/build/syslist.go | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index a99436735..70b7fb105 100644 --- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -40,7 +40,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[] = { @@ -49,6 +49,8 @@ static char *okgoarch[] = { "amd64", "amd64p32", "386", + "power64", + "power64le", }; // The known operating systems. diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go index 09730d635..e8bfc4a61 100644 --- a/src/pkg/go/build/build.go +++ b/src/pkg/go/build/build.go @@ -1230,6 +1230,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/pkg/go/build/syslist.go b/src/pkg/go/build/syslist.go index 965f873df..2ab53bb9c 100644 --- a/src/pkg/go/build/syslist.go +++ b/src/pkg/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 " -- cgit v1.2.1 From 54f10d52d5e4d8a9bf552f83bd2b90caa0447ff4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 Aug 2014 15:12:08 -0400 Subject: cmd/dist: generate anames9.c LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/120690043 --- src/cmd/dist/build.c | 2 ++ src/cmd/dist/buildgc.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index 70b7fb105..2e0f5b636 100644 --- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -524,6 +524,7 @@ static struct { "anames5.c", "anames6.c", "anames8.c", + "anames9.c", }}, {"cmd/cc", { "-pgen.c", @@ -622,6 +623,7 @@ static struct { {"anames5.c", mkanames}, {"anames6.c", mkanames}, {"anames8.c", mkanames}, + {"anames9.c", mkanames}, {"zasm_", mkzasm}, {"zdefaultcc.go", mkzdefaultcc}, {"zsys_", mkzsys}, 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 -- cgit v1.2.1 From 4713c26148ea86146834842771b809f05ae208d9 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 16:16:28 -0400 Subject: [dev.power64] cmd/dist: recognize power64 and power64le as GOHOSTARCH LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125760043 --- src/cmd/dist/unix.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c index 8b943a2d9..668b189ca 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); } -- cgit v1.2.1 From 190eb820b96c43eb96845b393b6db7771ccefc8b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 23:41:29 -0400 Subject: [dev.power64] cmd/9a, cmd/9c, cmd/9l, liblink: import code from Vita Nuova. No modifications other than adding copyright header to each file, and concatenating several cmd/9l files together to form the liblink files. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123840043 --- src/cmd/9a/a.h | 229 ++++++ src/cmd/9a/a.y | 975 ++++++++++++++++++++++ src/cmd/9a/lex.c | 906 ++++++++++++++++++++ src/cmd/9c/Notes | 14 + src/cmd/9c/cgen.c | 1133 +++++++++++++++++++++++++ src/cmd/9c/gc.h | 381 +++++++++ src/cmd/9c/list.c | 260 ++++++ src/cmd/9c/machcap.c | 107 +++ src/cmd/9c/mul.c | 640 +++++++++++++++ src/cmd/9c/peep.c | 1073 ++++++++++++++++++++++++ src/cmd/9c/reg.c | 1165 ++++++++++++++++++++++++++ src/cmd/9c/sgen.c | 279 +++++++ src/cmd/9c/swt.c | 659 +++++++++++++++ src/cmd/9c/txt.c | 1448 ++++++++++++++++++++++++++++++++ src/cmd/9l/9.out.h | 448 ++++++++++ src/cmd/9l/l.h | 384 +++++++++ src/liblink/asm9.c | 1889 ++++++++++++++++++++++++++++++++++++++++++ src/liblink/list9.c | 342 ++++++++ src/liblink/obj9.c | 2233 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/liblink/sched9.c | 835 +++++++++++++++++++ 20 files changed, 15400 insertions(+) create mode 100644 src/cmd/9a/a.h create mode 100644 src/cmd/9a/a.y create mode 100644 src/cmd/9a/lex.c create mode 100644 src/cmd/9c/Notes create mode 100644 src/cmd/9c/cgen.c create mode 100644 src/cmd/9c/gc.h create mode 100644 src/cmd/9c/list.c create mode 100644 src/cmd/9c/machcap.c create mode 100644 src/cmd/9c/mul.c create mode 100644 src/cmd/9c/peep.c create mode 100644 src/cmd/9c/reg.c create mode 100644 src/cmd/9c/sgen.c create mode 100644 src/cmd/9c/swt.c create mode 100644 src/cmd/9c/txt.c create mode 100644 src/cmd/9l/9.out.h create mode 100644 src/cmd/9l/l.h create mode 100644 src/liblink/asm9.c create mode 100644 src/liblink/list9.c create mode 100644 src/liblink/obj9.c create mode 100644 src/liblink/sched9.c (limited to 'src') diff --git a/src/cmd/9a/a.h b/src/cmd/9a/a.h new file mode 100644 index 000000000..2f5ff6d81 --- /dev/null +++ b/src/cmd/9a/a.h @@ -0,0 +1,229 @@ +// 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 +#include +#include +#include "../9c/9.out.h" + +#ifndef EXTERN +#define EXTERN extern +#endif + +typedef struct Sym Sym; +typedef struct Gen Gen; +typedef struct Io Io; +typedef struct Hist Hist; + +#define MAXALIGN 7 +#define FPCHIP 1 +#define NSYMB 8192 +#define BUFSIZ 8192 +#define HISTSZ 20 +#define NINCLUDE 10 +#define NHUNK 10000 +#define EOF (-1) +#define IGN (-2) +#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff) +#define NHASH 503 +#define STRINGSZ 200 +#define NMACRO 10 + +#define ALLOC(lhs, type)\ + while(nhunk < sizeof(type))\ + gethunk();\ + lhs = (type*)hunk;\ + nhunk -= sizeof(type);\ + hunk += sizeof(type); + +#define ALLOCN(lhs, len, n)\ + if(lhs+len != hunk || nhunk < n) {\ + while(nhunk <= len)\ + gethunk();\ + memmove(hunk, lhs, len);\ + lhs = hunk;\ + hunk += len;\ + nhunk -= len;\ + }\ + hunk += n;\ + nhunk -= n; + +struct Sym +{ + Sym* link; + char* macro; + vlong value; + ushort type; + char *name; + char sym; +}; +#define S ((Sym*)0) + +struct +{ + char* p; + int c; +} fi; + +struct Io +{ + Io* link; + char b[BUFSIZ]; + char* p; + short c; + short f; +}; +#define I ((Io*)0) + +struct +{ + Sym* sym; + short type; +} h[NSYM]; + +struct Gen +{ + Sym* sym; + vlong offset; + short type; + short reg; + short xreg; + short name; + ushort mask; + double dval; + char sval[8]; +}; + +struct Hist +{ + Hist* link; + char* name; + long line; + vlong offset; +}; +#define H ((Hist*)0) + +enum +{ + CLAST, + CMACARG, + CMACRO, + CPREPROC +}; + +EXTERN char debug[256]; +EXTERN Sym* hash[NHASH]; +EXTERN char* Dlist[30]; +EXTERN int nDlist; +EXTERN Hist* ehist; +EXTERN int newflag; +EXTERN Hist* hist; +EXTERN char* hunk; +EXTERN char* include[NINCLUDE]; +EXTERN Io* iofree; +EXTERN Io* ionext; +EXTERN Io* iostack; +EXTERN long lineno; +EXTERN int nerrors; +EXTERN long nhunk; +EXTERN int nosched; +EXTERN int ninclude; +EXTERN Gen nullgen; +EXTERN char* outfile; +EXTERN int pass; +EXTERN char* pathname; +EXTERN long pc; +EXTERN int peekc; +EXTERN int sym; +EXTERN char symb[NSYMB]; +EXTERN int thechar; +EXTERN char* thestring; +EXTERN long thunk; +EXTERN Biobuf obuf; + +void errorexit(void); +void pushio(void); +void newio(void); +void newfile(char*, int); +Sym* slookup(char*); +Sym* lookup(void); +void syminit(Sym*); +long 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, Gen*, int, Gen*); +void outgcode(int, Gen*, int, Gen*, Gen*); +void zname(char*, int, int); +void zaddr(Gen*, int); +void ieeedtod(Ieee*, double); +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(long); +void outhist(void); +void linehist(char*, int); +void gethunk(void); +void yyerror(char*, ...); +int yyparse(void); +void setinclude(char*); +int assemble(char*); + +/* + * system-dependent stuff from ../cc/compat.c + */ +enum /* keep in synch with ../cc/cc.h */ +{ + Plan9 = 1<<0, + Unix = 1<<1, + Windows = 1<<2 +}; +int mywait(int*); +int mycreat(char*, int); +int systemtype(int); +int pathchar(void); +char* mygetwd(char*, int); +int myexec(char*, char*[]); +int mydup(int, int); +int myfork(void); +int mypipe(int*); +void* mysbrk(ulong); diff --git a/src/cmd/9a/a.y b/src/cmd/9a/a.y new file mode 100644 index 000000000..e77d78c6d --- /dev/null +++ b/src/cmd/9a/a.y @@ -0,0 +1,975 @@ +// 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 "a.h" +%} +%union +{ + Sym *sym; + vlong lval; + double dval; + char sval[8]; + Gen gen; +} +%left '|' +%left '^' +%left '&' +%left '<' '>' +%left '+' '-' +%left '*' '/' '%' +%token LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP +%token LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW +%token LNOP LEND LRETT LWORD LTEXT LDATA LRETRN +%token LCONST LSP LSB LFP LPC LCREG LFLUSH +%token LREG LFREG LR LCR LF LFPSCR +%token LLR LCTR LSPR LSPREG LSEG LMSR +%token LSCHED LXLD LXST LXOP LXMV +%token LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA +%token LFCONST +%token LSCONST +%token LNAME LLAB LVAR +%type con expr pointer offset sreg +%type addr rreg regaddr name creg freg xlreg lr ctr +%type 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 + { + Gen g; + g = nullgen; + g.type = D_CONST; + g.offset = $2; + outcode($1, &g, $4, &$6); + } +| LBRA con ',' con ',' addr + { + Gen g; + g = nullgen; + g.type = D_CONST; + g.offset = $2; + outcode($1, &g, $4, &$6); + } +| LBRA con ',' con ',' '(' xlreg ')' + { + Gen 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); + } +/* + * word + */ +| LWORD imm comma + { + if($1 == ADWORD && $2.type == D_CONST) + $2.type = D_DCONST; + outcode($1, &$2, NREG, &nullgen); + } +| LWORD ximm comma + { + if($1 == ADWORD && $2.type == D_CONST) + $2.type = D_DCONST; + outcode($1, &$2, NREG, &nullgen); + } +/* + * END + */ +| LEND comma + { + outcode($1, &nullgen, NREG, &nullgen); + } +/* + * TEXT/GLOBL + */ +| LTEXT name ',' imm + { + outcode($1, &$2, NREG, &$4); + } +| LTEXT name ',' con ',' imm + { + outcode($1, &$2, $4, &$6); + } +| LTEXT name ',' imm ':' imm + { + outgcode($1, &$2, NREG, &$6, &$4); + } +| LTEXT name ',' con ',' imm ':' imm + { + outgcode($1, &$2, $4, &$8, &$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; + $$.sym = $1; + $$.offset = $2; + } +| LLAB offset + { + $$ = nullgen; + $$.type = D_BRANCH; + $$.sym = $1; + $$.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; + ulong 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 = ((ulong)~0L>>mb) & (~0L<<(31-me)); + else + v = ~(((ulong)~0L>>(me+1)) & (~0L<<(31-(mb-1)))); + $$.offset = v; + } + +ximm: + '$' addr + { + $$ = $2; + $$.type = D_CONST; + } +| '$' LSCONST + { + $$ = nullgen; + $$.type = D_SCONST; + memcpy($$.sval, $2, sizeof($$.sval)); + } + +fimm: + '$' LFCONST + { + $$ = nullgen; + $$.type = D_FCONST; + $$.dval = $2; + } +| '$' '-' LFCONST + { + $$ = nullgen; + $$.type = D_FCONST; + $$.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; + $$.xreg = $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 = S; + $$.offset = $1; + } +| LNAME offset '(' pointer ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.name = $4; + $$.sym = $1; + $$.offset = $2; + } +| LNAME '<' '>' offset '(' LSB ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.name = D_STATIC; + $$.sym = $1; + $$.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/lex.c b/src/cmd/9a/lex.c new file mode 100644 index 000000000..a7dbc45fa --- /dev/null +++ b/src/cmd/9a/lex.c @@ -0,0 +1,906 @@ +// 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. + +// +build ignore + +#define EXTERN +#include "a.h" +#include "y.tab.h" +#include + +void +main(int argc, char *argv[]) +{ + char *p; + int nout, nproc, status, i, c; + + thechar = '9'; + thestring = "power64"; + memset(debug, 0, sizeof(debug)); + cinit(); + outfile = 0; + include[ninclude++] = "."; + ARGBEGIN { + default: + c = ARGC(); + if(c >= 0 || c < sizeof(debug)) + debug[c] = 1; + break; + + case 'o': + outfile = ARGF(); + break; + + case 'D': + p = ARGF(); + if(p) + Dlist[nDlist++] = p; + break; + + case 'I': + p = ARGF(); + setinclude(p); + break; + } ARGEND + if(*argv == 0) { + print("usage: %ca [-options] file.s\n", thechar); + errorexit(); + } + if(argc > 1 && systemtype(Windows)){ + print("can't assemble multiple files on windows\n"); + errorexit(); + } + if(argc > 1) { + nproc = 1; + if(p = getenv("NPROC")) + nproc = atol(p); + c = 0; + nout = 0; + for(;;) { + while(nout < nproc && argc > 0) { + i = myfork(); + if(i < 0) { + i = mywait(&status); + if(i < 0) + errorexit(); + if(status) + c++; + nout--; + continue; + } + if(i == 0) { + print("%s:\n", *argv); + if(assemble(*argv)) + errorexit(); + exits(0); + } + nout++; + argc--; + argv++; + } + i = mywait(&status); + if(i < 0) { + if(c) + errorexit(); + exits(0); + } + if(status) + c++; + nout--; + } + } + if(assemble(argv[0])) + errorexit(); + exits(0); +} + +int +assemble(char *file) +{ + char ofile[100], incfile[20], *p; + int i, of; + + strcpy(ofile, file); + if(p = strrchr(ofile, pathchar())) { + include[0] = ofile; + *p++ = 0; + } else + p = ofile; + if(outfile == 0) { + outfile = p; + if(p = strrchr(outfile, '.')) + if(p[1] == 's' && p[2] == 0) + p[0] = 0; + p = strrchr(outfile, 0); + p[0] = '.'; + p[1] = thechar; + p[2] = 0; + } + p = getenv("INCLUDE"); + if(p) { + setinclude(p); + } else { + if(systemtype(Plan9)) { + sprint(incfile,"/%s/include", thestring); + setinclude(strdup(incfile)); + } + } + + of = mycreat(outfile, 0664); + if(of < 0) { + yyerror("%ca: cannot create %s", thechar, outfile); + errorexit(); + } + Binit(&obuf, of, OWRITE); + + pass = 1; + nosched = 0; + pinit(file); + for(i=0; itype = itab[i].type; + s->value = itab[i].value; + } + ALLOCN(pathname, 0, 100); + if(mygetwd(pathname, 99) == 0) { + ALLOCN(pathname, 100, 900); + if(mygetwd(pathname, 999) == 0) + strcpy(pathname, "/???"); + } +} + +void +syminit(Sym *s) +{ + + s->type = LNAME; + s->value = 0; +} + +void +cclean(void) +{ + + outcode(AEND, &nullgen, NREG, &nullgen); + Bflush(&obuf); +} + +void +zname(char *n, int t, int s) +{ + + Bputc(&obuf, ANAME); + Bputc(&obuf, ANAME>>8); + Bputc(&obuf, t); /* type */ + Bputc(&obuf, s); /* sym */ + while(*n) { + Bputc(&obuf, *n); + n++; + } + Bputc(&obuf, 0); +} + +void +zaddr(Gen *a, int s) +{ + long l; + int i; + char *n; + Ieee e; + + if(a->type == D_CONST){ + l = a->offset; + if((vlong)l != a->offset) + a->type = D_DCONST; + } + Bputc(&obuf, a->type); + Bputc(&obuf, a->reg); + Bputc(&obuf, s); + Bputc(&obuf, a->name); + switch(a->type) { + default: + print("unknown type %d\n", a->type); + exits("arg"); + + case D_NONE: + case D_REG: + case D_FREG: + case D_CREG: + case D_FPSCR: + case D_MSR: + case D_OPT: + break; + + case D_DCR: + case D_SPR: + case D_OREG: + case D_CONST: + case D_BRANCH: + l = a->offset; + Bputc(&obuf, l); + Bputc(&obuf, l>>8); + Bputc(&obuf, l>>16); + Bputc(&obuf, l>>24); + break; + + case D_DCONST: + l = a->offset; + Bputc(&obuf, l); + Bputc(&obuf, l>>8); + Bputc(&obuf, l>>16); + Bputc(&obuf, l>>24); + l = a->offset>>32; + Bputc(&obuf, l); + Bputc(&obuf, l>>8); + Bputc(&obuf, l>>16); + Bputc(&obuf, l>>24); + break; + + case D_SCONST: + n = a->sval; + for(i=0; idval); + Bputc(&obuf, e.l); + Bputc(&obuf, e.l>>8); + Bputc(&obuf, e.l>>16); + Bputc(&obuf, e.l>>24); + Bputc(&obuf, e.h); + Bputc(&obuf, e.h>>8); + Bputc(&obuf, e.h>>16); + Bputc(&obuf, e.h>>24); + break; + } +} + +int +outsim(Gen *g) +{ + Sym *s; + int sno, t; + + s = g->sym; + if(s == S) + return 0; + sno = s->sym; + if(sno < 0 || sno >= NSYM) + sno = 0; + t = g->name; + if(h[sno].type == t && h[sno].sym == s) + return sno; + zname(s->name, t, sym); + s->sym = sym; + h[sym].sym = s; + h[sym].type = t; + sno = sym; + sym++; + if(sym >= NSYM) + sym = 1; + return sno; +} + +void +outcode(int a, Gen *g1, int reg, Gen *g2) +{ + int sf, st; + + if(a != AGLOBL && a != ADATA) + pc++; + if(pass == 1) + return; + if(g1->xreg != NREG) { + if(reg != NREG || g2->xreg != NREG) + yyerror("bad addressing modes"); + reg = g1->xreg; + } else + if(g2->xreg != NREG) { + if(reg != NREG) + yyerror("bad addressing modes"); + reg = g2->xreg; + } + do { + sf = outsim(g1); + st = outsim(g2); + } while(sf != 0 && st == sf); + Bputc(&obuf, a); + Bputc(&obuf, a>>8); + Bputc(&obuf, reg|nosched); + Bputc(&obuf, lineno); + Bputc(&obuf, lineno>>8); + Bputc(&obuf, lineno>>16); + Bputc(&obuf, lineno>>24); + zaddr(g1, sf); + zaddr(g2, st); +} + +void +outgcode(int a, Gen *g1, int reg, Gen *g2, Gen *g3) +{ + int s1, s2, s3, flag; + + if(a != AGLOBL && a != ADATA) + pc++; + if(pass == 1) + return; + do { + s1 = outsim(g1); + s2 = outsim(g2); + s3 = outsim(g3); + } while(s1 && (s2 && s1 == s2 || s3 && s1 == s3) || s2 && (s3 && s2 == s3)); + flag = 0; + if(g2->type != D_NONE) + flag = 0x40; /* flags extra operand */ + Bputc(&obuf, a); + Bputc(&obuf, a>>8); + Bputc(&obuf, reg | nosched | flag); + Bputc(&obuf, lineno); + Bputc(&obuf, lineno>>8); + Bputc(&obuf, lineno>>16); + Bputc(&obuf, lineno>>24); + zaddr(g1, s1); + if(flag) + zaddr(g2, s2); + zaddr(g3, s3); +} + +void +outhist(void) +{ + Gen g; + Hist *h; + char *p, *q, *op, c; + int n; + + g = nullgen; + c = pathchar(); + for(h = hist; h != H; h = h->link) { + p = h->name; + op = 0; + /* on windows skip drive specifier in pathname */ + if(systemtype(Windows) && p && p[1] == ':'){ + p += 2; + c = *p; + } + if(p && p[0] != c && h->offset == 0 && pathname){ + /* on windows skip drive specifier in pathname */ + if(systemtype(Windows) && pathname[1] == ':') { + op = p; + p = pathname+2; + c = *p; + } else if(pathname[0] == c){ + op = p; + p = pathname; + } + } + while(p) { + q = strchr(p, c); + if(q) { + n = q-p; + if(n == 0){ + n = 1; /* leading "/" */ + *p = '/'; /* don't emit "\" on windows */ + } + q++; + } else { + n = strlen(p); + q = 0; + } + if(n) { + Bputc(&obuf, ANAME); + Bputc(&obuf, ANAME>>8); + Bputc(&obuf, D_FILE); /* type */ + Bputc(&obuf, 1); /* sym */ + Bputc(&obuf, '<'); + Bwrite(&obuf, p, n); + Bputc(&obuf, 0); + } + p = q; + if(p == 0 && op) { + p = op; + op = 0; + } + } + g.offset = h->offset; + + Bputc(&obuf, AHISTORY); + Bputc(&obuf, AHISTORY>>8); + Bputc(&obuf, 0); + Bputc(&obuf, h->line); + Bputc(&obuf, h->line>>8); + Bputc(&obuf, h->line>>16); + Bputc(&obuf, h->line>>24); + zaddr(&nullgen, 0); + zaddr(&g, 0); + } +} + +#include "../cc/lexbody" +#include "../cc/macbody" +#include "../cc/compat" 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..93bb010aa --- /dev/null +++ b/src/cmd/9c/cgen.c @@ -0,0 +1,1133 @@ +// 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. + +// +build ignore + +#include "gc.h" + +void +cgen(Node *n, Node *nn) +{ + Node *l, *r; + Prog *p1; + Node nod, nod1, nod2, nod3, nod4; + int o; + long v, curs; + + if(debug['g']) { + prtree(nn, "cgen lhs"); + prtree(n, "cgen"); + } + if(n == Z || n->type == T) + return; + if(typesu[n->type->etype]) { + 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); + 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); + 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; + } + 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]--; + if(nn != Z) { + regret(&nod, n); + gopcode(OAS, &nod, Z, nn); + 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 += (long)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; + long 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; + long 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); + 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, long w) +{ + Prog *p1; + Node nod0, nod1, nod2, nod3, nod4, *l, *r; + Type *t; + long 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)) /* 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)) /* 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 += (long)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(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, ®node, 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, ®node, Z); + regalloc(&t2, ®node, 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/gc.h b/src/cmd/9c/gc.h new file mode 100644 index 000000000..2b718b9f9 --- /dev/null +++ b/src/cmd/9c/gc.h @@ -0,0 +1,381 @@ +// 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 "../cc/cc.h" +#include "../9c/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 Adr Adr; +typedef struct Prog Prog; +typedef struct Case Case; +typedef struct C1 C1; +typedef struct Multab Multab; +typedef struct Hintab Hintab; +typedef struct Var Var; +typedef struct Reg Reg; +typedef struct Rgn Rgn; + +struct Adr +{ + union + { + vlong offset; + double dval; + char sval[NSNAME]; + }; + Sym* sym; + char type; + char reg; + char name; + char etype; +}; +#define A ((Adr*)0) + +#define INDEXED 9 +struct Prog +{ + Adr from; + Adr from3; /* third argument for fmadd, fmsub, ... */ + Adr to; + Prog* link; + long lineno; + short as; + char reg; +}; +#define P ((Prog*)0) + +struct Case +{ + Case* link; + vlong val; + long label; + char def; + char isv; +}; +#define C ((Case*)0) + +struct C1 +{ + vlong val; + long label; +}; + +struct Multab +{ + long val; + char code[20]; +}; + +struct Hintab +{ + ushort val; + char hint[10]; +}; + +struct Var +{ + vlong offset; + Sym* sym; + char name; + char etype; +}; + +struct Reg +{ + long pc; + long rpo; /* reverse post ordering */ + + Bits set; + Bits use1; + Bits use2; + + Bits refbehind; + Bits refahead; + Bits calbehind; + Bits calahead; + Bits regdiff; + Bits act; + + long regu; + long loop; /* could be shorter */ + + union + { + Reg* log5; + long 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 long breakpc; +EXTERN long nbreak; +EXTERN Case* cases; +EXTERN Node constnode; +EXTERN Node fconstnode; +EXTERN Node vconstnode; +EXTERN long continpc; +EXTERN long curarg; +EXTERN long cursafe; +EXTERN Prog* firstp; +EXTERN Prog* lastp; +EXTERN int hintabsize; +EXTERN long maxargsafe; +EXTERN Multab multab[20]; +EXTERN int mnstring; +EXTERN Node* nodrat; +EXTERN Node* nodret; +EXTERN Node* nodsafe; +EXTERN long nrathole; +EXTERN long nstring; +EXTERN Prog* p; +EXTERN long 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 long exregoffset; +EXTERN long 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 long regbits; +EXTERN long exregbits; + +EXTERN int change; +EXTERN int suppress; + +EXTERN Reg* firstr; +EXTERN Reg* lastr; +EXTERN Reg zreg; +EXTERN Reg* freer; +EXTERN Var var[NVAR]; +EXTERN long* idom; +EXTERN Reg** rpo2r; +EXTERN long 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*); + +/* + * 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*, long); +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(long); +Node* nod32const(vlong); +Node* nodfconst(double); +void nodreg(Node*, Node*, int); +void regret(Node*, Node*); +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*, Adr*); +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*, long); +int sconst(Node*); +int sval(long); +int uconst(Node*); +void gpseudo(int, Sym*, Node*); + +/* + * swt.c + */ +int swcmp(void*, void*); +void doswit(Node*); +void swit1(C1*, int, long, Node*); +void swit2(C1*, int, long, Node*, Node*); +void casf(void); +void bitload(Node*, Node*, Node*, Node*, Node*); +void bitstore(Node*, Node*, Node*, Node*, Node*); +long outstring(char*, long); +int mulcon(Node*, Node*); +Multab* mulcon0(Node*, long); +int mulcon1(Node*, long, Node*); +void nullwarn(Node*, Node*); +void sextern(Sym*, Node*, long, long); +void gextern(Sym*, Node*, long, long); +void outcode(void); +void ieeedtod(Ieee*, double); + +/* + * 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(void*, void*); +void regopt(Prog*); +void addmove(Reg*, int, int, int); +Bits mkvar(Adr*, int); +void prop(Reg*, Bits, Bits); +void loopit(Reg*, long); +void synch(Reg*, Bits); +ulong allreg(ulong, Rgn*); +void paint1(Reg*, int); +ulong paint2(Reg*, int); +void paint3(Reg*, int, long, int); +void addreg(Adr*, int); + +/* + * peep.c + */ +void peep(void); +void excise(Reg*); +Reg* uniqp(Reg*); +Reg* uniqs(Reg*); +int regtyp(Adr*); +int regzer(Adr*); +int anyvar(Adr*); +int subprop(Reg*); +int copyprop(Reg*); +int copy1(Adr*, Adr*, Reg*, int); +int copyu(Prog*, Adr*, Adr*); + +int copyas(Adr*, Adr*); +int copyau(Adr*, Adr*); +int copyau1(Prog*, Adr*); +int copysub(Adr*, Adr*, Adr*, int); +int copysub1(Prog*, Adr*, Adr*, int); + +long RtoB(int); +long FtoB(int); +int BtoR(long); +int BtoF(long); + +/* + * 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" Adr* +#pragma varargck type "N" Adr* +#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..ed6213dba --- /dev/null +++ b/src/cmd/9c/list.c @@ -0,0 +1,260 @@ +// 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. + +// +build ignore + +#define EXTERN +#include "gc.h" + +void +listinit(void) +{ + + fmtinstall('A', Aconv); + fmtinstall('P', Pconv); + fmtinstall('S', Sconv); + fmtinstall('N', Nconv); + fmtinstall('D', Dconv); + fmtinstall('B', Bconv); +} + +int +Bconv(Fmt *fp) +{ + char str[STRINGSZ], ss[STRINGSZ], *s; + Bits bits; + int i; + + str[0] = 0; + bits = va_arg(fp->args, Bits); + while(bany(&bits)) { + i = bnum(bits); + if(str[0]) + strcat(str, " "); + if(var[i].sym == S) { + sprint(ss, "$%lld", var[i].offset); + s = ss; + } else + s = var[i].sym->name; + if(strlen(str) + strlen(s) + 1 >= STRINGSZ) + break; + strcat(str, s); + bits.b[i/32] &= ~(1L << (i%32)); + } + return fmtstrcpy(fp, str); +} + +int +Pconv(Fmt *fp) +{ + char str[STRINGSZ]; + Prog *p; + int a; + + p = va_arg(fp->args, Prog*); + a = p->as; + if(a == ADATA) + sprint(str, " %A %D/%d,%D", a, &p->from, p->reg, &p->to); + else + if(p->as == ATEXT) + sprint(str, " %A %D,%d,%D", a, &p->from, p->reg, &p->to); + else + if(p->reg == NREG) + sprint(str, " %A %D,%D", a, &p->from, &p->to); + else + if(p->from.type != D_FREG) + sprint(str, " %A %D,R%d,%D", a, &p->from, p->reg, &p->to); + else + sprint(str, " %A %D,F%d,%D", a, &p->from, p->reg, &p->to); + return fmtstrcpy(fp, str); +} + +int +Aconv(Fmt *fp) +{ + char *s; + int a; + + a = va_arg(fp->args, int); + s = "???"; + if(a >= AXXX && a <= ALAST) + s = anames[a]; + return fmtstrcpy(fp, s); +} + +int +Dconv(Fmt *fp) +{ + char str[STRINGSZ]; + Adr *a; + + a = va_arg(fp->args, Adr*); + 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 != S) + sprint(str, "%N(R%d)(NONE)", a, a->reg); + break; + + case D_CONST: + if(a->reg != NREG) + sprint(str, "$%N(R%d)", a, a->reg); + else + sprint(str, "$%N", a); + break; + + case D_OREG: + if(a->reg != NREG) + sprint(str, "%N(R%d)", a, a->reg); + else + sprint(str, "%N", a); + break; + + case D_REG: + sprint(str, "R%d", a->reg); + if(a->name != D_NONE || a->sym != S) + sprint(str, "%N(R%d)(REG)", a, a->reg); + break; + + case D_FREG: + sprint(str, "F%d", a->reg); + if(a->name != D_NONE || a->sym != S) + sprint(str, "%N(F%d)(REG)", a, a->reg); + break; + + case D_CREG: + sprint(str, "C%d", a->reg); + if(a->name != D_NONE || a->sym != S) + sprint(str, "%N(C%d)(REG)", a, a->reg); + break; + + case D_BRANCH: + sprint(str, "%lld(PC)", a->offset-pc); + break; + + case D_FCONST: + sprint(str, "$%.17e", a->dval); + break; + + case D_SCONST: + sprint(str, "$\"%S\"", a->sval); + break; + } + return fmtstrcpy(fp, str); +} + +int +Sconv(Fmt *fp) +{ + int i, c; + char str[STRINGSZ], *p, *a; + + a = va_arg(fp->args, char*); + p = str; + for(i=0; i= '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; + case '\r': + *p++ = 'r'; + continue; + case '\f': + *p++ = 'f'; + continue; + } + *p++ = (c>>6) + '0'; + *p++ = ((c>>3) & 7) + '0'; + *p++ = (c & 7) + '0'; + } + *p = 0; + return fmtstrcpy(fp, str); +} + +int +Nconv(Fmt *fp) +{ + char str[STRINGSZ]; + Adr *a; + Sym *s; + + a = va_arg(fp->args, Adr*); + s = a->sym; + if(s == S) { + sprint(str, "%lld", a->offset); + goto out; + } + switch(a->name) { + default: + sprint(str, "GOK-name(%d)", a->name); + break; + + case D_EXTERN: + sprint(str, "%s+%lld(SB)", s->name, a->offset); + break; + + case D_STATIC: + sprint(str, "%s<>+%lld(SB)", s->name, a->offset); + break; + + case D_AUTO: + sprint(str, "%s-%lld(SP)", s->name, -a->offset); + break; + + case D_PARAM: + sprint(str, "%s+%lld(FP)", s->name, a->offset); + break; + } +out: + return fmtstrcpy(fp, str); +} diff --git a/src/cmd/9c/machcap.c b/src/cmd/9c/machcap.c new file mode 100644 index 000000000..1d66146be --- /dev/null +++ b/src/cmd/9c/machcap.c @@ -0,0 +1,107 @@ +// 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. + +// +build ignore + +#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..fdbf0fcb2 --- /dev/null +++ b/src/cmd/9c/mul.c @@ -0,0 +1,640 @@ +// 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. + +// +build ignore + +#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 long mulval; +static char* mulcp; +static long 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, long r1); +static int gen3(int len, long r0, long 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, long v) +{ + int a1, a2, g; + Multab *m, *m1; + char hint[10]; + + if(v < 0) + v = -v; + + /* + * look in cache + */ + m = multab; + for(g=0; gval == 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<= mulval) + break; + } + if(mulval == 1) + return 1; + + len--; + for(i=1; i<=shmax; i++) + if(gen2(len, 1<= 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< 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< 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< 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< 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<= 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..6cb09dd42 --- /dev/null +++ b/src/cmd/9c/peep.c @@ -0,0 +1,1073 @@ +// 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. + +// +build ignore + +#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. + */ +regzer(Adr *a) +{ + if(R0ISZERO) { + if(a->type == D_CONST) + if(a->sym == S) + if(a->offset == 0) + return 1; + if(a->type == D_REG) + if(a->reg == REGZERO) + return 1; + } + return 0; +} + +regtyp(Adr *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; + Adr *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; + Adr *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); +} + +copy1(Adr *v1, Adr *v2, Reg *r, int f) +{ + int t; + Prog *p; + + if(r->active) { + if(debug['P']) + print("act set; return 1\n"); + return 1; + } + r->active = 1; + if(debug['P']) + print("copy %D->%D f=%d\n", v1, v2, f); + for(; r != R; r = r->s1) { + p = r->prog; + if(debug['P']) + print("%P", p); + if(!f && uniqp(r) == R) { + f = 1; + if(debug['P']) + print("; merge; f=%d", f); + } + t = copyu(p, v2, A); + switch(t) { + case 2: /* rar, 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, A); + if(!f && (t == 2 || t == 3 || t == 4)) { + f = 1; + if(debug['P']) + print("; %Dset and !f; f=%d", v1, f); + } + } + if(debug['P']) + print("\n"); + if(r->s2) + if(!copy1(v1, v2, r->s2, f)) + return 0; + } + return 1; +} + +/* + * 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, Adr *v, Adr *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 != A) { + if(copysub(&p->from, v, s, 1)) + return 1; + if(!copyas(&p->to, v)) + if(copysub(&p->to, v, s, 1)) + return 1; + return 0; + } + if(copyas(&p->to, v)) { + if(copyau(&p->from, v)) + return 4; + return 3; + } + if(copyau(&p->from, v)) + return 1; + if(copyau(&p->to, v)) + return 1; + return 0; + + case 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 != A) { + if(copysub(&p->from, v, s, 1)) + return 1; + if(copysub1(p, v, s, 1)) + return 1; + if(!copyas(&p->to, v)) + if(copysub(&p->to, v, s, 1)) + return 1; + return 0; + } + if(copyas(&p->to, v)) { + if(p->reg == NREG) + p->reg = p->to.reg; + if(copyau(&p->from, v)) + return 4; + if(copyau1(p, v)) + return 4; + return 3; + } + if(copyau(&p->from, v)) + return 1; + if(copyau1(p, v)) + return 1; + if(copyau(&p->to, v)) + return 1; + return 0; + + case ABEQ: + 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 != A) { + if(copysub(&p->from, v, s, 1)) + return 1; + return copysub(&p->to, v, s, 1); + } + if(copyau(&p->from, v)) + return 1; + if(copyau(&p->to, v)) + return 1; + break; + + case ABR: /* funny */ + if(s != A) { + if(copysub(&p->to, v, s, 1)) + return 1; + return 0; + } + if(copyau(&p->to, v)) + return 1; + return 0; + + case 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 != A) { + if(copysub(&p->to, v, s, 1)) + return 1; + return 0; + } + if(copyau(&p->to, v)) + return 4; + return 3; + + case ATEXT: /* funny */ + if(v->type == D_REG) + if(v->reg == REGARG) + return 3; + return 0; + } + 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(Adr *a, Adr *v) +{ + + if(regtyp(v)) + if(a->type == v->type) + if(a->reg == v->reg) + return 1; + return 0; +} + +/* + * either direct or indirect + */ +int +copyau(Adr *a, Adr *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, Adr *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(Adr *a, Adr *v, Adr *s, int f) +{ + + if(f) + if(copyau(a, v)) + a->reg = s->reg; + return 0; +} + +int +copysub1(Prog *p1, Adr *v, Adr *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..ee48588c7 --- /dev/null +++ b/src/cmd/9c/reg.c @@ -0,0 +1,1165 @@ +// 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. + +// +build ignore + +#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(void *a1, void *a2) +{ + 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; + long initpc, val, npc; + ulong vreg; + Bits bit; + struct + { + long m; + long c; + Reg* p; + } log5[6], *lp; + + firstr = R; + lastr = R; + nvar = 0; + regbits = 0; + for(z=0; zm = 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: + 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; zuse1.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; zset.b[z] |= bit.b[z]; + break; + + /* + * funny + */ + case ABL: + for(z=0; zlink) { + 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; zuse1.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; zrefahead.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; zset.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; zact.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) { + warn(Z, "too many regions"); + goto brk; + } + rgp++; + } + } +brk: + qsort(region, nregion, sizeof(region[0]), rcmp); + + /* + * pass 6 + * determine used registers (paint2) + * replace code (paint3) + */ + rgp = region; + for(i=0; ivarno); + 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: + 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; + 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; + Adr *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 == S) + 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(Adr *a, int docon) +{ + Var *v; + int i, t, n, et, z; + long o; + Bits bit; + Sym *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 == S) { + if(t != D_CONST || !docon || a->reg != NREG) + goto none; + et = TLONG; + } + if(t == D_CONST) { + if(s == S && sval(o)) + goto none; + } + n = a->name; + v = var; + for(i=0; isym) + if(n == v->name) + if(o == v->offset) + goto out; + v++; + } + if(s) + if(s->name[0] == '.') + goto none; + if(nvar >= NVAR) { + if(debug['w'] > 1 && s) + warn(Z, "variable not optimized: %s", s->name); + goto none; + } + 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; zetype != et || !(typechlpfd[et] || typev[et])) /* funny punning */ + for(z=0; zp1) { + for(z=0; zrefahead.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; zset.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 + */ +long +postorder(Reg *r, Reg **rpo2r, long 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; +} + +long +rpolca(long *idom, long rpo1, long rpo2) +{ + long 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(long *idom, long r, long s) +{ + while(s > r) + s = idom[s]; + return s == r; +} + +int +loophead(long *idom, Reg *r) +{ + long 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, long 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, long nr) +{ + Reg *r1; + long i, d, me; + + if(nr > maxnr) { + rpo2r = alloc(nr * sizeof(Reg*)); + idom = alloc(nr * sizeof(long)); + 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; zrefbehind.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; zcalbehind.b[z] & r1->calahead.b[z]); + if(r1->s2 != R) + synch(r1->s2, dif); + } +} + +ulong +allreg(ulong 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; + ulong 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; + } +} + +ulong +paint2(Reg *r, int bn) +{ + Reg *r1; + int z; + ulong 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, long rb, int rn) +{ + Reg *r1; + Prog *p; + int z; + ulong 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(Adr *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 + */ +long +RtoB(int r) +{ + + if(r >= REGMIN && r <= REGMAX) + return 1L << (r-REGMIN); + return 0; +} + +int +BtoR(long b) +{ + b &= 0x001fffffL; + if(b == 0) + return 0; + return bitno(b) + REGMIN; +} + +/* + * bit reg + * 22 F17 + * 23 F18 + * ... ... + * 31 F26 + */ +long +FtoB(int f) +{ + if(f < FREGMIN || f > FREGEXT) + return 0; + return 1L << (f - FREGMIN + 22); +} + +int +BtoF(long 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..bad9a9c8a --- /dev/null +++ b/src/cmd/9c/sgen.c @@ -0,0 +1,279 @@ +// 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. + +// +build ignore + +#include "gc.h" + +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..d6f9833be --- /dev/null +++ b/src/cmd/9c/swt.c @@ -0,0 +1,659 @@ +// 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. + +// +build ignore + +#include "gc.h" + +void +swit1(C1 *q, int nc, long def, Node *n) +{ + Node tn; + + regalloc(&tn, ®node, Z); + swit2(q, nc, def, n, &tn); + regfree(&tn); +} + +void +swit2(C1 *q, int nc, long def, Node *n, Node *tn) +{ + C1 *r; + int i; + Prog *sp; + + if(nc < 5) { + for(i=0; ival)) { + 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; + long 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) +{ + long 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); +} + +long +outstring(char *s, long n) +{ + long 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.sval, string, NSNAME); + mnstring = 0; + } + n--; + } + return r; +} + +int +mulcon(Node *n, Node *nn) +{ + Node *l, *r, nod1, nod2; + Multab *m; + long 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, long o, long w) +{ + long e, lw; + + for(e=0; efrom.offset += o+e; + p->reg = lw; + p->to.type = D_SCONST; + memmove(p->to.sval, a->cstring+e, lw); + } +} + +void +gextern(Sym *s, Node *a, long o, long w) +{ + if(a->op == OCONST && typev[a->type->etype]) { + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gpseudo(ADATA, s, nod32const(a->vconst>>32)); + else + gpseudo(ADATA, s, nod32const(a->vconst)); + p->from.offset += o; + p->reg = 4; + if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + gpseudo(ADATA, s, nod32const(a->vconst)); + else + gpseudo(ADATA, s, nod32const(a->vconst>>32)); + p->from.offset += o + 4; + p->reg = 4; + return; + } + gpseudo(ADATA, s, a); + p->from.offset += o; + p->reg = w; + if(p->to.type == D_OREG) + p->to.type = D_CONST; +} + +void zname(Biobuf*, Sym*, int); +char* zaddr(char*, Adr*, int); +void zwrite(Biobuf*, Prog*, int, int); +void outhist(Biobuf*); + +void +outcode(void) +{ + struct { Sym *sym; short type; } h[NSYM]; + Prog *p; + Sym *s; + int sf, st, t, sym; + + if(debug['S']) { + for(p = firstp; p != P; p = p->link) + if(p->as != ADATA && p->as != AGLOBL) + pc--; + for(p = firstp; p != P; p = p->link) { + print("%P\n", p); + if(p->as != ADATA && p->as != AGLOBL) + pc++; + } + } + outhist(&outbuf); + for(sym=0; symlink) { + jackpot: + sf = 0; + s = p->from.sym; + while(s != S) { + sf = s->sym; + if(sf < 0 || sf >= NSYM) + sf = 0; + t = p->from.name; + if(h[sf].type == t) + if(h[sf].sym == s) + break; + s->sym = sym; + zname(&outbuf, s, t); + h[sym].sym = s; + h[sym].type = t; + sf = sym; + sym++; + if(sym >= NSYM) + sym = 1; + break; + } + st = 0; + s = p->to.sym; + while(s != S) { + st = s->sym; + if(st < 0 || st >= NSYM) + st = 0; + t = p->to.name; + if(h[st].type == t) + if(h[st].sym == s) + break; + s->sym = sym; + zname(&outbuf, s, t); + h[sym].sym = s; + h[sym].type = t; + st = sym; + sym++; + if(sym >= NSYM) + sym = 1; + if(st == sf) + goto jackpot; + break; + } + zwrite(&outbuf, p, sf, st); + } + firstp = P; + lastp = P; +} + +void +zwrite(Biobuf *b, Prog *p, int sf, int st) +{ + char bf[100], *bp; + long l; + + bf[0] = p->as; + bf[1] = p->as>>8; + bf[2] = p->reg; + l = p->lineno; + bf[3] = l; + bf[4] = l>>8; + bf[5] = l>>16; + bf[6] = l>>24; + bp = zaddr(bf+7, &p->from, sf); + bp = zaddr(bp, &p->to, st); + Bwrite(b, bf, bp-bf); +} + +void +outhist(Biobuf *b) +{ + Hist *h; + char *p, *q, *op, c; + Prog pg; + int n; + + pg = zprog; + pg.as = AHISTORY; + c = pathchar(); + for(h = hist; h != H; h = h->link) { + p = h->name; + op = 0; + /* on windows skip drive specifier in pathname */ + if(systemtype(Windows) && p && p[1] == ':'){ + p += 2; + c = *p; + } + if(p && p[0] != c && h->offset == 0 && pathname){ + /* on windows skip drive specifier in pathname */ + if(systemtype(Windows) && pathname[1] == ':') { + op = p; + p = pathname+2; + c = *p; + } else if(pathname[0] == c){ + op = p; + p = pathname; + } + } + while(p) { + q = utfrune(p, c); + if(q) { + n = q-p; + if(n == 0){ + n = 1; /* leading "/" */ + *p = '/'; /* don't emit "\" on windows */ + } + q++; + } else { + n = strlen(p); + q = 0; + } + if(n) { + Bputc(b, ANAME); + Bputc(b, ANAME>>8); + Bputc(b, D_FILE); + Bputc(b, 1); + Bputc(b, '<'); + Bwrite(b, p, n); + Bputc(b, 0); + } + p = q; + if(p == 0 && op) { + p = op; + op = 0; + } + } + pg.lineno = h->line; + pg.to.type = zprog.to.type; + pg.to.offset = h->offset; + if(h->offset) + pg.to.type = D_CONST; + + zwrite(b, &pg, 0, 0); + } +} + +void +zname(Biobuf *b, Sym *s, int t) +{ + char *n, bf[8]; + ulong sig; + + n = s->name; + if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ + sig = sign(s); + bf[0] = ASIGNAME; + bf[1] = ASIGNAME>>8; + bf[2] = sig; + bf[3] = sig>>8; + bf[4] = sig>>16; + bf[5] = sig>>24; + bf[6] = t; + bf[7] = s->sym; + Bwrite(b, bf, 8); + s->sig = SIGDONE; + } + else{ + bf[0] = ANAME; + bf[1] = ANAME>>8; + bf[2] = t; /* type */ + bf[3] = s->sym; /* sym */ + Bwrite(b, bf, 4); + } + Bwrite(b, n, strlen(n)+1); +} + +char* +zaddr(char *bp, Adr *a, int s) +{ + long l; + Ieee e; + + if(a->type == D_CONST){ + l = a->offset; + if((vlong)l != a->offset) + a->type = D_DCONST; + } + bp[0] = a->type; + bp[1] = a->reg; + bp[2] = s; + bp[3] = a->name; + bp += 4; + switch(a->type) { + default: + diag(Z, "unknown type %d in zaddr", a->type); + + case D_NONE: + case D_REG: + case D_FREG: + case D_CREG: + break; + + case D_OREG: + case D_CONST: + case D_BRANCH: + l = a->offset; + bp[0] = l; + bp[1] = l>>8; + bp[2] = l>>16; + bp[3] = l>>24; + bp += 4; + break; + + case D_DCONST: + l = a->offset; + bp[0] = l; + bp[1] = l>>8; + bp[2] = l>>16; + bp[3] = l>>24; + bp += 4; + l = a->offset>>32; + bp[0] = l; + bp[1] = l>>8; + bp[2] = l>>16; + bp[3] = l>>24; + bp += 4; + break; + + case D_SCONST: + memmove(bp, a->sval, NSNAME); + bp += NSNAME; + break; + + case D_FCONST: + ieeedtod(&e, a->dval); + l = e.l; + bp[0] = l; + bp[1] = l>>8; + bp[2] = l>>16; + bp[3] = l>>24; + bp += 4; + l = e.h; + bp[0] = l; + bp[1] = l>>8; + bp[2] = l>>16; + bp[3] = l>>24; + bp += 4; + break; + } + return bp; +} + +long +align(long i, Type *t, int op) +{ + long o; + Type *v; + int w; + + o = i; + w = 1; + switch(op) { + default: + diag(Z, "unknown align opcode %d", op); + break; + + case Asu2: /* padding at end of a struct */ + w = SZ_VLONG; + if(packflg) + w = packflg; + break; + + case Ael1: /* initial allign of struct element */ + for(v=t; v->etype==TARRAY; v=v->link) + ; + w = ewidth[v->etype]; + if(w <= 0 || w >= SZ_VLONG) + w = SZ_VLONG; + if(packflg) + w = 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); + o = align(o, types[TIND], Aarg2); + } + break; + + case Aarg1: /* initial align of parameter */ + w = ewidth[t->etype]; + if(w <= 0 || w >= SZ_VLONG) { + w = SZ_VLONG; + break; + } + o += SZ_VLONG - w; /* big endian adjustment */ + w = 1; + break; + + case Aarg2: /* width of a parameter */ + o += t->width; + w = SZ_VLONG; + break; + + case Aaut3: /* total align of automatic */ + o = align(o, t, Ael1); + o = align(o, t, Ael2); + break; + } + o = round(o, w); + if(debug['A']) + print("align %s %ld %T = %ld\n", bnames[op], i, t, o); + return o; +} + +long +maxround(long max, long v) +{ + v = round(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..4cf23fc6a --- /dev/null +++ b/src/cmd/9c/txt.c @@ -0,0 +1,1448 @@ +// 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. + +// +build ignore + +#include "gc.h" + +static int resvreg[nelem(reg)]; + +#define isv(et) ((et) == TVLONG || (et) == TUVLONG || (et) == TIND) + +void +ginit(void) +{ + Type *t; + + thechar = '9'; + thestring = "power64"; + exregoffset = REGEXT; + exfregoffset = FREGEXT; + listinit(); + nstring = 0; + mnstring = 0; + nrathole = 0; + pc = 0; + breakpc = -1; + continpc = -1; + cases = C; + firstp = P; + lastp = P; + tfield = types[TLONG]; + + typeword = typechlvp; + typeswitch = typechlv; + 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.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; itype->width = nstring; + symrathole->type->width = nrathole; + for(i=0; ilink) { + 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) +{ + + p = alloc(sizeof(*p)); + *p = zprog; + p->lineno = nearln; + pc++; + if(firstp == P) { + firstp = p; + lastp = p; + return; + } + lastp->link = p; + lastp = p; +} + +void +gargs(Node *n, Node *tn1, Node *tn2) +{ + long 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((long)v); + vconstnode.vconst = v; + return &vconstnode; +} + +Node* +nodconst(long 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) +{ + int r; + + r = REGRET; + if(typefd[nn->type->etype]) + r = FREGRET+NREG; + nodreg(n, nn, r); + reg[r]++; +} + +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) + 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) + 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); + 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) +{ + nodreg(n, nn, REGARG); + reg[REGARG]++; + curarg = align(curarg, nn->type, Aarg1); + curarg = align(curarg, nn->type, Aarg2); + maxargsafe = maxround(maxargsafe, cursafe+curarg); +} + +void +regaalloc(Node *n, Node *nn) +{ + curarg = align(curarg, nn->type, Aarg1); + *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); + 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) +{ + Adr 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: "); + p->reg = NREG; + } else + p->reg = a.reg; +} + +void +naddr(Node *n, Adr *a) +{ + long v; + + a->type = D_NONE; + if(n == Z) + return; + switch(n->op) { + default: + bad: + diag(n, "bad in naddr: %O", n->op); + break; + + case OREGISTER: + a->type = D_REG; + a->sym = S; + 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 = S; + 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 = 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 = S; + a->reg = NREG; + if(typefd[n->type->etype]) { + a->type = D_FCONST; + a->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 long */ + 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 long */ + 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(AMOVW, &fxc0, &fxrat); + gins(AXOR, nodconst(0x80000000L), &fxc2); + fxc1 = fxrat; + fxc1.type = nodrat->type; + fxc1.etype = nodrat->etype; + fxc1.xoffset += SZ_LONG; + gins(AMOVW, &fxc2, &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; + Adr 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, long 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 = s; + if(a == ATEXT) + p->reg = (profileflg ? 0 : NOPROF); + 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(long v) +{ + + if(v >= -(1<<15) && v < (1<<15)) + return 1; + return 0; +} + +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; +} + +long +exreg(Type *t) +{ + long 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] */ +}; +long 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/9l/9.out.h b/src/cmd/9l/9.out.h new file mode 100644 index 000000000..8ad2f7d06 --- /dev/null +++ b/src/cmd/9l/9.out.h @@ -0,0 +1,448 @@ +// 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 + +#define NOPROF (1<<0) +#define DUPOK (1<<1) + +enum +{ + REGZERO = 0, /* set to zero */ + REGSP = 1, + REGSB = 2, + REGRET = 3, + REGARG = 3, + REGMIN = 7, /* register variables allocated from here to REGMAX */ + REGMAX = 27, + REGEXT = 30, /* external registers allocated from here down */ + REGTMP = 31, /* used by the linker */ + + FREGRET = 0, + FREGMIN = 17, /* first register variable */ + 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 as +{ + AXXX = 0, + 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, + + 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, + +/* 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 "__.SYMDEF" + +/* + * this is the simulated IEEE floating point + */ +typedef struct ieee Ieee; +struct ieee +{ + long l; /* contains ls-man 0xffffffff */ + long h; /* contains sign 0x80000000 + exp 0x7ff00000 + ms-man 0x000fffff */ +}; diff --git a/src/cmd/9l/l.h b/src/cmd/9l/l.h new file mode 100644 index 000000000..0f2fd60a8 --- /dev/null +++ b/src/cmd/9l/l.h @@ -0,0 +1,384 @@ +// 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 +#include +#include +#include "../9c/9.out.h" +#include "../8l/elf.h" + +#ifndef EXTERN +#define EXTERN extern +#endif + +#define LIBNAMELEN 300 + +typedef struct Adr Adr; +typedef struct Sym Sym; +typedef struct Autom Auto; +typedef struct Prog Prog; +typedef struct Optab Optab; + +#define P ((Prog*)0) +#define S ((Sym*)0) +#define TNAME (curtext&&curtext->from.sym?curtext->from.sym->name:noname) + +struct Adr +{ + union + { + vlong u0offset; + char u0sval[NSNAME]; + Ieee u0ieee; + }u0; + Sym *sym; + Auto *autom; + char type; + uchar reg; + char name; + char class; +}; + +#define offset u0.u0offset +#define sval u0.u0sval +#define ieee u0.u0ieee + +struct Prog +{ + Adr from; + Adr from3; /* fma and rlwm */ + Adr to; + Prog *forwd; + Prog *cond; + Prog *link; + vlong pc; + long regused; + short line; + short mark; + short optab; /* could be uchar */ + short as; + char reg; +}; +struct Sym +{ + char *name; + short type; + short version; + short become; + short frame; + uchar subtype; + ushort file; + vlong value; + long sig; + Sym *link; +}; +struct Autom +{ + Sym *sym; + Auto *link; + vlong aoffset; + short type; +}; +struct Optab +{ + short as; + char a1; + char a2; + char a3; + char a4; + char type; + char size; + char param; +}; +struct +{ + Optab* start; + Optab* stop; +} oprange[ALAST]; + +enum +{ + FPCHIP = 1, + BIG = 32768-8, + STRINGSZ = 200, + MAXIO = 8192, + MAXHIST = 20, /* limit of path elements for history symbols */ + DATBLK = 1024, + NHASH = 10007, + NHUNK = 100000, + MINSIZ = 64, + NENT = 100, + NSCHED = 20, + +/* 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, + + STEXT = 1, + SDATA, + SBSS, + SDATA1, + SXREF, + SLEAF, + SFILE, + SCONST, + SUNDEF, + + SIMPORT, + SEXPORT, + + C_NONE = 0, + 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, + + Roffset = 22, /* no. bits for offset in relocation address */ + Rindex = 10 /* no. bits for index in relocation address */ +}; + +EXTERN union +{ + struct + { + uchar obuf[MAXIO]; /* output buffer */ + uchar ibuf[MAXIO]; /* input buffer */ + } u; + char dbuf[1]; +} buf; + +#define cbuf u.obuf +#define xbuf u.ibuf + +EXTERN long HEADR; /* length of header */ +EXTERN int HEADTYPE; /* type of header */ +EXTERN vlong INITDAT; /* data location */ +EXTERN long INITRND; /* data round above text location */ +EXTERN vlong INITTEXT; /* text location */ +EXTERN long INITTEXTP; /* text location (physical) */ +EXTERN char* INITENTRY; /* entry point */ +EXTERN long autosize; +EXTERN Biobuf bso; +EXTERN long bsssize; +EXTERN int cbc; +EXTERN uchar* cbp; +EXTERN int cout; +EXTERN Auto* curauto; +EXTERN Auto* curhist; +EXTERN Prog* curp; +EXTERN Prog* curtext; +EXTERN Prog* datap; +EXTERN Prog* prog_movsw; +EXTERN Prog* prog_movdw; +EXTERN Prog* prog_movws; +EXTERN Prog* prog_movwd; +EXTERN vlong datsize; +EXTERN char debug[128]; +EXTERN Prog* firstp; +EXTERN uchar fnuxi8[8]; +EXTERN uchar fnuxi4[4]; +EXTERN Sym* hash[NHASH]; +EXTERN Sym* histfrog[MAXHIST]; +EXTERN int histfrogp; +EXTERN int histgen; +EXTERN char* library[50]; +EXTERN char* libraryobj[50]; +EXTERN int libraryp; +EXTERN int xrefresolv; +EXTERN char* hunk; +EXTERN uchar inuxi1[1]; +EXTERN uchar inuxi2[2]; +EXTERN uchar inuxi4[4]; +EXTERN uchar inuxi8[8]; +EXTERN Prog* lastp; +EXTERN long lcsize; +EXTERN char literal[32]; +EXTERN int nerrors; +EXTERN long nhunk; +EXTERN char* noname; +EXTERN vlong instoffset; +EXTERN char* outfile; +EXTERN vlong pc; +EXTERN int r0iszero; +EXTERN long symsize; +EXTERN long staticgen; +EXTERN Prog* textp; +EXTERN vlong textsize; +EXTERN long tothunk; +EXTERN char xcmp[C_NCLASS][C_NCLASS]; +EXTERN int version; +EXTERN Prog zprg; +EXTERN int dtype; + +EXTERN int doexp, dlm; +EXTERN int imports, nimports; +EXTERN int exports, nexports, allexport; +EXTERN char* EXPTAB; +EXTERN Prog undefp; + +#define UP (&undefp) + +extern Optab optab[]; +extern char* anames[]; +extern char* cnames[]; + +int Aconv(Fmt*); +int Dconv(Fmt*); +int Nconv(Fmt*); +int Pconv(Fmt*); +int Sconv(Fmt*); +int Rconv(Fmt*); +int aclass(Adr*); +void addhist(long, int); +void histtoauto(void); +void addlibpath(char*); +void addnop(Prog*); +void append(Prog*, Prog*); +void asmb(void); +void asmdyn(void); +void asmlc(void); +int asmout(Prog*, Optab*, int); +void asmsym(void); +vlong atolwhex(char*); +Prog* brloop(Prog*); +void buildop(void); +void cflush(void); +void ckoff(Sym*, vlong); +int cmp(int, int); +void cput(long); +int compound(Prog*); +double cputime(void); +void datblk(long, long); +void diag(char*, ...); +void dodata(void); +void doprof1(void); +void doprof2(void); +void dynreloc(Sym*, long, int, int, int); +vlong entryvalue(void); +void errorexit(void); +void exchange(Prog*); +void export(void); +int fileexists(char*); +int find1(long, int); +char* findlib(char*); +void follow(void); +void gethunk(void); +double ieeedtod(Ieee*); +long ieeedtof(Ieee*); +void import(void); +int isint32(vlong); +int isuint32(uvlong); +int isnop(Prog*); +void ldobj(int, long, char*); +void loadlib(void); +void listinit(void); +void initmuldiv(void); +Sym* lookup(char*, int); +void llput(vlong); +void llputl(vlong); +void lput(long); +void lputl(long); +void mkfwd(void); +void* mysbrk(ulong); +void names(void); +void nocache(Prog*); +void noops(void); +void nopout(Prog*); +void nuxiinit(void); +void objfile(char*); +int ocmp(void*, void*); +long opcode(int); +Optab* oplook(Prog*); +void patch(void); +void prasm(Prog*); +void prepend(Prog*, Prog*); +Prog* prg(void); +int pseudo(Prog*); +void putsymb(char*, int, vlong, int); +void readundefs(char*, int); +long regoff(Adr*); +int relinv(int); +vlong rnd(vlong, long); +void sched(Prog*, Prog*); +void span(void); +void strnput(char*, int); +void undef(void); +void undefsym(Sym*); +vlong vregoff(Adr*); +void wput(long); +void wputl(long); +void xdefine(char*, int, vlong); +void xfol(Prog*); +void zerosig(char*); + +#pragma varargck type "D" Adr* +#pragma varargck type "N" Adr* +#pragma varargck type "P" Prog* +#pragma varargck type "R" int +#pragma varargck type "A" int +#pragma varargck type "S" char* +#pragma varargck argpos diag 1 diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c new file mode 100644 index 000000000..ea510df79 --- /dev/null +++ b/src/liblink/asm9.c @@ -0,0 +1,1889 @@ +// 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. + +// +build ignore + +#include "l.h" + +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 }, + { 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 }, + + { 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_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, 8, 4, REGSB }, + { AFMOVD, C_LAUTO,C_NONE, C_NONE, C_FREG, 8, 4, REGSP }, + { AFMOVD, C_LOREG,C_NONE, C_NONE, C_FREG, 8, 4, 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, 7, 4, REGSB }, + { AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 7, 4, REGSP }, + { AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 7, 4, 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 }, + + { 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 }, + { AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0 }, + { AREMD, 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 }, + + { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, +}; + +#include "l.h" + +#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) + +long oprrr(int), opirr(int), opload(int), opstore(int), oploadx(int), opstorex(int); + +/* + * 32-bit masks + */ +int +getmask(uchar *m, ulong v) +{ + int i; + + m[0] = m[1] = 0; + if(v != ~0L && 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; +} + +void +maskgen(Prog *p, uchar *m, ulong v) +{ + if(!getmask(m, v)) + diag("cannot generate mask #%lux\n%P", v, p); +} + +/* + * 64-bit masks (rldic etc) + */ +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; +} + +void +maskgen64(Prog *p, uchar *m, uvlong v) +{ + if(!getmask64(m, v)) + diag("cannot generate mask #%llux\n%P", v, p); +} + +static void +reloc(Adr *a, long pc, int sext) +{ + if(a->name == D_EXTERN || a->name == D_STATIC) + dynreloc(a->sym, pc, 1, 1, sext); +} + +static ulong +loadu32(int r, vlong d) +{ + long v; + + v = d>>16; + if(isuint32(d)) + return LOP_IRR(OP_ORIS, r, REGZERO, v); + return AOP_IRR(OP_ADDIS, r, REGZERO, v); +} + +int +asmout(Prog *p, Optab *o, int aflag) +{ + long o1, o2, o3, o4, o5, v, t; + vlong d; + Prog *ct; + int r, a; + uchar mask[2]; + + o1 = 0; + o2 = 0; + o3 = 0; + o4 = 0; + o5 = 0; + switch(o->type) { + default: + if(aflag) + return 0; + diag("unknown type %d", o->type); + if(!debug['a']) + prasm(p); + break; + + case 0: /* pseudo ops */ + if(aflag) { + if(p->link) { + if(p->as == ATEXT) { + ct = curtext; + o2 = autosize; + curtext = p; + autosize = p->to.offset + 8; + o1 = asmout(p->link, oplook(p->link), aflag); + curtext = ct; + autosize = o2; + } else + o1 = asmout(p->link, oplook(p->link), aflag); + } + return o1; + } + break; + + case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */ + if(p->to.reg == REGZERO && p->from.type == D_CONST) { + v = regoff(&p->from); + if(r0iszero && v != 0) { + nerrors--; + 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(p->as), p->to.reg, r, p->from.reg); + break; + + case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */ + d = vregoff(&p->from); + v = d; + r = p->from.reg; + if(r == NREG) + r = o->param; + if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0)) + diag("literal operation on R0\n%P", p); + a = OP_ADDI; + if(o->a1 == C_UCON) { + v >>= 16; + if(r == REGZERO && isuint32(d)){ + o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v); + break; + } + a = OP_ADDIS; + } + o1 = AOP_IRR(a, p->to.reg, r, v); + break; + + case 4: /* add/mul $scon,[r1],r2 */ + v = regoff(&p->from); + r = p->reg; + if(r == NREG) + r = p->to.reg; + if(r0iszero && p->to.reg == 0) + diag("literal operation on R0\n%P", p); + o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v); + break; + + case 5: /* syscall */ + if(aflag) + return 0; + o1 = oprrr(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(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(&p->to); + if(p->to.type == D_OREG && p->reg != NREG) { + if(v) + diag("illegal indexed instruction\n%P", p); + o1 = AOP_RRR(opstorex(p->as), p->from.reg, p->reg, r); + } else + o1 = AOP_IRR(opstore(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(&p->from); + if(p->from.type == D_OREG && p->reg != NREG) { + if(v) + diag("illegal indexed instruction\n%P", p); + o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r); + } else + o1 = AOP_IRR(opload(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(&p->from); + if(p->from.type == D_OREG && p->reg != NREG) { + if(v) + diag("illegal indexed instruction\n%P", p); + o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r); + } else + o1 = AOP_IRR(opload(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(p->as), p->to.reg, p->from.reg, r); + break; + + case 11: /* br/bl lbra */ + if(aflag) + return 0; + v = 0; + if(p->cond == UP){ + if(p->to.sym->type != SUNDEF) + diag("bad branch sym type"); + v = (ulong)p->to.sym->value >> (Roffset-2); + dynreloc(p->to.sym, p->pc, 0, 0, 0); + } + else if(p->cond) + v = p->cond->pc - p->pc; + if(v & 03) { + diag("odd branch target address\n%P", p); + v &= ~03; + } + if(v < -(1L<<25) || v >= (1L<<24)) + diag("branch too far\n%P", p); + o1 = OP_BR(opirr(p->as), v, 0); + break; + + case 12: /* movb r,r (extsb); movw r,r (extsw) */ + if(p->to.reg == REGZERO && p->from.type == D_CONST) { + v = regoff(&p->from); + if(r0iszero && v != 0) { + nerrors--; + 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 + 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(&p->from3); + maskgen64(p, mask, d); + switch(p->as){ + case ARLDCL: case ARLDCLCC: + a = mask[0]; /* MB */ + if(mask[1] != 63) + 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) + diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p); + break; + default: + diag("unexpected op in rldc case\n%P", p); + a = 0; + } + o1 = LOP_RRR(oprrr(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 */ + if(aflag) + return 0; + a = 0; + if(p->from.type == D_CONST) + a = regoff(&p->from); + r = p->reg; + if(r == NREG) + r = 0; + v = 0; + if(p->cond) + v = p->cond->pc - p->pc; + if(v & 03) { + diag("odd branch target address\n%P", p); + v &= ~03; + } + if(v < -(1L<<16) || v >= (1L<<15)) + diag("branch too far\n%P", p); + o1 = OP_BC(opirr(p->as), a, r, v, 0); + break; + + case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */ + if(aflag) + return 0; + if(p->as == ABC || p->as == ABCL) + v = regoff(&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(aflag) + return 0; + if(p->as == ABC || p->as == ABCL) + v = regoff(&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: + 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(&p->from); + o1 = loadu32(p->to.reg, d); + o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (long)d); + if(dlm) + reloc(&p->from, p->pc, 0); + break; + + case 20: /* add $ucon,,r */ + v = regoff(&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)) + diag("literal operation on R0\n%P", p); + o1 = AOP_IRR(opirr(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) + diag("cant synthesize large constant\n%P", p); + d = vregoff(&p->from); + o1 = loadu32(REGTMP, d); + o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (long)d); + r = p->reg; + if(r == NREG) + r = p->to.reg; + o3 = AOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r); + 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) + diag("cant synthesize large constant\n%P", p); + d = vregoff(&p->from); + o1 = loadu32(REGTMP, d); + o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (long)d); + r = p->reg; + if(r == NREG) + r = p->to.reg; + o3 = LOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r); + 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(&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: + 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) + diag("can't synthesize large constant\n%P", p); + v = regoff(&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(&p->from3); + r = p->from.reg; + o1 = AOP_IRR(opirr(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) + diag("can't synthesize large constant\n%P", p); + v = regoff(&p->from3); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); + o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v); + o3 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, REGTMP); + 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(&p->from); + d = vregoff(&p->from3); + maskgen64(p, mask, d); + switch(p->as){ + case ARLDC: case ARLDCCC: + a = mask[0]; /* MB */ + if(mask[1] != (63-v)) + 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) + 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) + diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); + break; + default: + diag("unexpected op in rldic case\n%P", p); + a = 0; + } + o1 = AOP_RRR(opirr(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(&p->from); + d = vregoff(&p->from3); + maskgen64(p, mask, d); + if(mask[1] != (63-v)) + diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); + o1 = AOP_RRR(opirr(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 */ + if(aflag) + return 0; + d = vregoff(&p->from); + o1 = d>>32; + o2 = d; + break; + + case 32: /* fmul frc,fra,frd */ + r = p->reg; + if(r == NREG) + r = p->to.reg; + o1 = AOP_RRR(oprrr(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(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(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(&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(p->as), p->from.reg, REGTMP, v); + break; + + case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */ + v = regoff(&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(p->as), p->to.reg, REGTMP, v); + break; + + case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */ + v = regoff(&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(p->as), p->to.reg, REGTMP, v); + o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); + break; + + case 40: /* word */ + if(aflag) + return 0; + o1 = regoff(&p->from); + break; + + case 41: /* stswi */ + o1 = AOP_RRR(opirr(p->as), p->from.reg, p->to.reg, 0) | ((regoff(&p->from3)&0x7F)<<11); + break; + + case 42: /* lswi */ + o1 = AOP_RRR(opirr(p->as), p->to.reg, p->from.reg, 0) | ((regoff(&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(p->as), 0, r, p->from.reg); + break; + + case 44: /* indexed store */ + r = p->reg; + if(r == NREG) + r = 0; + o1 = AOP_RRR(opstorex(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(p->as), p->to.reg, r, p->from.reg); + break; + + case 46: /* plain op */ + o1 = oprrr(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(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(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(&p->from) & 1; + o1 = AOP_RRR(oprrr(p->as), 0, 0, p->to.reg) | (v<<21); + }else + o1 = AOP_RRR(oprrr(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(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); + break; + + case 51: /* remd[u] r1[,r2],r3 */ + r = p->reg; + if(r == NREG) + r = p->to.reg; + v = oprrr(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(&p->from)&31L; + o1 = AOP_RRR(oprrr(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(p->as), p->to.reg, 0, p->from.reg); + break; + + case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */ + v = regoff(&p->from); + r = p->reg; + if(r == NREG) + r = p->to.reg; + o1 = AOP_RRR(opirr(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(&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) + 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(&p->from); + r = p->reg; + if(r == NREG) + r = p->to.reg; + o1 = LOP_IRR(opirr(p->as), p->to.reg, r, v); + break; + + case 59: /* or/and $ucon,,r */ + v = regoff(&p->from); + r = p->reg; + if(r == NREG) + r = p->to.reg; + o1 = LOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */ + break; + + case 60: /* tw to,a,b */ + r = regoff(&p->from)&31L; + o1 = AOP_RRR(oprrr(p->as), r, p->reg, p->to.reg); + break; + + case 61: /* tw to,a,$simm */ + r = regoff(&p->from)&31L; + v = regoff(&p->to); + o1 = AOP_IRR(opirr(p->as), r, p->reg, v); + break; + + case 62: /* rlwmi $sh,s,$mask,a */ + v = regoff(&p->from); + maskgen(p, mask, regoff(&p->from3)); + o1 = AOP_RRR(opirr(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(p, mask, regoff(&p->from3)); + o1 = AOP_RRR(opirr(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(&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) + diag("must specify FPSCR(n)\n%P", p); + o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(&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) + 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) + diag("can't use both mask and CR(n)\n%P", p); + v = regoff(&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(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(p->as), r, p->from.reg, 0) | (regoff(&p->to)&0xffff); + break; + + case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */ + o1 = AOP_RRR(oprrr(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) + 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; + + /* relocation operations */ + + case 74: + v = regoff(&p->to); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); + o2 = AOP_IRR(opstore(p->as), p->from.reg, REGTMP, v); + if(dlm) + reloc(&p->to, p->pc, 1); + break; + + case 75: + v = regoff(&p->from); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); + o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v); + if(dlm) + reloc(&p->from, p->pc, 1); + break; + + case 76: + v = regoff(&p->from); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); + o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v); + o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); + if(dlm) + reloc(&p->from, p->pc, 1); + break; + + } + if(aflag) + return o1; + v = p->pc; + switch(o->size) { + default: + if(debug['a']) + Bprint(&bso, " %.8lux:\t\t%P\n", v, p); + break; + case 4: + if(debug['a']) + Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); + lput(o1); + break; + case 8: + if(debug['a']) + Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); + lput(o1); + lput(o2); + break; + case 12: + if(debug['a']) + Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); + lput(o1); + lput(o2); + lput(o3); + break; + case 16: + if(debug['a']) + Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", + v, o1, o2, o3, o4, p); + lput(o1); + lput(o2); + lput(o3); + lput(o4); + break; + case 20: + if(debug['a']) + Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", + v, o1, o2, o3, o4, o5, p); + lput(o1); + lput(o2); + lput(o3); + lput(o4); + lput(o5); + break; + } + return 0; +} + +long +oprrr(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); + } + diag("bad r/r opcode %A", a); + return 0; +} + +long +opirr(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 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 */ + } + diag("bad opcode i/r %A", a); + return 0; +} + +/* + * load o(a),d + */ +long +opload(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 */ + } + diag("bad load opcode %A", a); + return 0; +} + +/* + * indexed load a(b),d + */ +long +oploadx(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 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 */ + } + diag("bad loadx opcode %A", a); + return 0; +} + +/* + * store s,o(d) + */ +long +opstore(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 */ + } + diag("unknown store opcode %A", a); + return 0; +} + +/* + * indexed store s,a(b) + */ +long +opstorex(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 */ + } + 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..f9de2bf11 --- /dev/null +++ b/src/liblink/list9.c @@ -0,0 +1,342 @@ +// 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. + +// +build ignore + +#include "l.h" + +void +listinit(void) +{ + + fmtinstall('A', Aconv); + fmtinstall('D', Dconv); + fmtinstall('P', Pconv); + fmtinstall('S', Sconv); + fmtinstall('N', Nconv); + fmtinstall('R', Rconv); +} + +void +prasm(Prog *p) +{ + print("%P\n", p); +} + +int +Pconv(Fmt *fp) +{ + char str[STRINGSZ], *s; + Prog *p; + int a; + + p = va_arg(fp->args, Prog*); + curp = p; + a = p->as; + if(a == ADATA || a == AINIT || a == ADYNT) + sprint(str, "(%d) %A %D/%d,%D", p->line, a, &p->from, p->reg, &p->to); + else { + s = str; + if(p->mark & NOSCHED) + s += sprint(s, "*"); + if(p->reg == NREG && p->from3.type == D_NONE) + sprint(s, "(%d) %A %D,%D", p->line, a, &p->from, &p->to); + else + if(a != ATEXT && p->from.type == D_OREG) { + sprint(s, "(%d) %A %lld(R%d+R%d),%D", p->line, a, + p->from.offset, p->from.reg, p->reg, &p->to); + } else + if(p->to.type == D_OREG) { + sprint(s, "(%d) %A %D,%lld(R%d+R%d)", p->line, a, + &p->from, p->to.offset, p->to.reg, p->reg); + } else { + s += sprint(s, "(%d) %A %D", p->line, 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); + } + } + return fmtstrcpy(fp, str); +} + +int +Aconv(Fmt *fp) +{ + char *s; + int a; + + a = va_arg(fp->args, int); + s = "???"; + if(a >= AXXX && a < ALAST) + s = anames[a]; + return fmtstrcpy(fp, s); +} + +int +Dconv(Fmt *fp) +{ + char str[STRINGSZ]; + Adr *a; + long v; + + a = va_arg(fp->args, Adr*); + 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 != S) + sprint(str, "%N(R%d)(NONE)", a, a->reg); + break; + + case D_CONST: + case D_DCONST: + if(a->reg != NREG) + sprint(str, "$%N(R%d)", a, a->reg); + else + sprint(str, "$%N", a); + break; + + case D_OREG: + if(a->reg != NREG) + sprint(str, "%N(R%d)", a, a->reg); + else + sprint(str, "%N", a); + break; + + case D_REG: + sprint(str, "R%d", a->reg); + if(a->name != D_NONE || a->sym != S) + sprint(str, "%N(R%d)(REG)", a, a->reg); + break; + + case D_FREG: + sprint(str, "F%d", a->reg); + if(a->name != D_NONE || a->sym != S) + sprint(str, "%N(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 != S) + sprint(str, "%N(C%d)(REG)", a, a->reg); + break; + + case D_SPR: + if(a->name == D_NONE && a->sym == S) { + 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 != S) + sprint(str, "%N(SPR-GOK%d)(REG)", a, a->reg); + break; + + case D_DCR: + if(a->name == D_NONE && a->sym == S) { + sprint(str, "DCR(%lld)", a->offset); + break; + } + sprint(str, "DCR-GOK(%d)", a->reg); + if(a->name != D_NONE || a->sym != S) + sprint(str, "%N(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(curp->cond != P) { + v = curp->cond->pc; + if(v >= INITTEXT) + v -= INITTEXT-HEADR; + if(a->sym != S) + sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v); + else + sprint(str, "%.5lux(BRANCH)", v); + } else + if(a->sym != S) + 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); + break; + + case D_SCONST: + sprint(str, "$\"%S\"", a->sval); + break; + } + return fmtstrcpy(fp, str); +} + +int +Nconv(Fmt *fp) +{ + char str[STRINGSZ]; + Adr *a; + Sym *s; + long l; + + a = va_arg(fp->args, Adr*); + s = a->sym; + if(s == S) { + 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_EXTERN: + sprint(str, "%s+%lld(SB)", s->name, a->offset); + break; + + case D_STATIC: + sprint(str, "%s<>+%lld(SB)", s->name, a->offset); + break; + + case D_AUTO: + sprint(str, "%s-%lld(SP)", s->name, -a->offset); + break; + + case D_PARAM: + sprint(str, "%s+%lld(FP)", s->name, a->offset); + break; + } +out: + return fmtstrcpy(fp, str); +} + +int +Rconv(Fmt *fp) +{ + char *s; + int a; + + a = va_arg(fp->args, int); + s = "C_??"; + if(a >= C_NONE && a <= C_NCLASS) + s = cnames[a]; + return fmtstrcpy(fp, s); +} + +int +Sconv(Fmt *fp) +{ + int i, c; + char str[STRINGSZ], *p, *a; + + a = va_arg(fp->args, char*); + p = str; + for(i=0; i= '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); +} + +void +diag(char *fmt, ...) +{ + char buf[STRINGSZ], *tn; + va_list arg; + + tn = "??none??"; + if(curtext != P && curtext->from.sym != S) + tn = curtext->from.sym->name; + va_start(arg, fmt); + vseprint(buf, buf+sizeof(buf), fmt, arg); + va_end(arg); + print("%s: %s\n", tn, buf); + + nerrors++; + if(nerrors > 10) { + print("too many errors\n"); + errorexit(); + } +} diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c new file mode 100644 index 000000000..cf073ec36 --- /dev/null +++ b/src/liblink/obj9.c @@ -0,0 +1,2233 @@ +// 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. + +// +build ignore + +#include "l.h" + +void +noops(void) +{ + Prog *p, *p1, *q, *q1; + int o, mov, aoffset, curframe, curbecome, maxbecome; + + /* + * find leaf subroutines + * become sizes + * frame sizes + * strip NOPs + * expand RET + * expand BECOME pseudo + */ + + if(debug['v']) + Bprint(&bso, "%5.2f noops\n", cputime()); + Bflush(&bso); + + curframe = 0; + curbecome = 0; + maxbecome = 0; + curtext = 0; + q = P; + for(p = firstp; p != P; p = p->link) { + + /* find out how much arg space is used in this TEXT */ + if(p->to.type == D_OREG && p->to.reg == REGSP) + if(p->to.offset > curframe) + curframe = p->to.offset; + + switch(p->as) { + /* too hard, just leave alone */ + case ATEXT: + if(curtext && curtext->from.sym) { + curtext->from.sym->frame = curframe; + curtext->from.sym->become = curbecome; + if(curbecome > maxbecome) + maxbecome = curbecome; + } + curframe = 0; + curbecome = 0; + + q = p; + p->mark |= LABEL|LEAF|SYNC; + if(p->link) + p->link->mark |= LABEL; + curtext = p; + 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: + if(curtext != P) + curtext->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->cond; + if(q1 != P) { + while(q1->as == ANOP) { + q1 = q1->link; + p->cond = q1; + } + if(!(q1->mark & LEAF)) + q1->mark |= LABEL; + } else + p->mark |= LABEL; + q1 = p->link; + if(q1 != P) + q1->mark |= LABEL; + continue; + + case AFCMPO: + case AFCMPU: + q = p; + p->mark |= FCMP|FLOAT; + continue; + + case ARETURN: + /* special form of RETURN is BECOME */ + if(p->from.type == D_CONST) + if(p->from.offset > curbecome) + curbecome = p->from.offset; + + q = p; + if(p->link != P) + 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; + } + } + if(curtext && curtext->from.sym) { + curtext->from.sym->frame = curframe; + curtext->from.sym->become = curbecome; + if(curbecome > maxbecome) + maxbecome = curbecome; + } + + if(debug['b']) + print("max become = %d\n", maxbecome); + xdefine("ALEFbecome", STEXT, maxbecome); + + curtext = 0; + for(p = firstp; p != P; p = p->link) { + switch(p->as) { + case ATEXT: + curtext = p; + break; + + case ABL: /* ABCL? */ + if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { + o = maxbecome - curtext->from.sym->frame; + if(o <= 0) + break; + /* calling a become or calling a variable */ + if(p->to.sym == S || p->to.sym->become) { + curtext->to.offset += o; + if(debug['b']) { + curp = p; + print("%D calling %D increase %d\n", + &curtext->from, &p->to, o); + } + } + } + break; + } + } + + curtext = P; + for(p = firstp; p != P; p = p->link) { + o = p->as; + switch(o) { + case ATEXT: + mov = AMOVD; + aoffset = 0; + curtext = p; + autosize = p->to.offset + 8; + if((p->mark & LEAF) && autosize <= 8) + autosize = 0; + else + if(autosize & 4) + autosize += 4; + p->to.offset = autosize - 8; + + q = p; + if(autosize) { + /* use MOVDU to adjust R1 when saving R31, if autosize is small */ + if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) { + mov = AMOVDU; + aoffset = -autosize; + } else { + q = prg(); + q->as = AADD; + q->line = p->line; + q->from.type = D_CONST; + q->from.offset = -autosize; + q->to.type = D_REG; + q->to.reg = REGSP; + + q->link = p->link; + p->link = q; + } + } else + if(!(curtext->mark & LEAF)) { + if(debug['v']) + Bprint(&bso, "save suppressed in: %s\n", + curtext->from.sym->name); + curtext->mark |= LEAF; + } + + if(curtext->mark & LEAF) { + if(curtext->from.sym) + curtext->from.sym->type = SLEAF; + break; + } + + q1 = prg(); + q1->as = mov; + q1->line = p->line; + q1->from.type = D_REG; + q1->from.reg = REGTMP; + q1->to.type = D_OREG; + q1->to.offset = aoffset; + q1->to.reg = REGSP; + + q1->link = q->link; + q->link = q1; + + q1 = prg(); + q1->as = AMOVD; + q1->line = p->line; + q1->from.type = D_SPR; + q1->from.offset = D_LR; + q1->to.type = D_REG; + q1->to.reg = REGTMP; + + q1->link = q->link; + q->link = q1; + break; + + case ARETURN: + if(p->from.type == D_CONST) + goto become; + if(curtext->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; + + q = prg(); + q->as = ABR; + q->line = p->line; + q->to.type = D_SPR; + q->to.offset = D_LR; + q->mark |= BRANCH; + + 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 = prg(); + q->as = AMOVD; + q->line = p->line; + 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 = prg(); + q->as = AADD; + q->line = p->line; + q->from.type = D_CONST; + q->from.offset = autosize; + q->to.type = D_REG; + q->to.reg = REGSP; + + q->link = p->link; + p->link = q; + } + + q1 = prg(); + q1->as = ABR; + q1->line = p->line; + q1->to.type = D_SPR; + q1->to.offset = D_LR; + q1->mark |= BRANCH; + + q1->link = q->link; + q->link = q1; + break; + + become: + if(curtext->mark & LEAF) { + + q = prg(); + q->line = p->line; + q->as = ABR; + q->from = zprg.from; + q->to = p->to; + q->cond = p->cond; + q->link = p->link; + q->mark |= BRANCH; + p->link = q; + + p->as = AADD; + p->from = zprg.from; + p->from.type = D_CONST; + p->from.offset = autosize; + p->to = zprg.to; + p->to.type = D_REG; + p->to.reg = REGSP; + + break; + } + q = prg(); + q->line = p->line; + q->as = ABR; + q->from = zprg.from; + q->to = p->to; + q->cond = p->cond; + q->mark |= BRANCH; + q->link = p->link; + p->link = q; + + q = prg(); + q->line = p->line; + q->as = AADD; + q->from.type = D_CONST; + q->from.offset = autosize; + q->to.type = D_REG; + q->to.reg = REGSP; + q->link = p->link; + p->link = q; + + q = prg(); + q->line = p->line; + q->as = AMOVD; + q->line = p->line; + 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->as = AMOVD; + p->from = zprg.from; + p->from.type = D_OREG; + p->from.offset = 0; + p->from.reg = REGSP; + p->to = zprg.to; + p->to.type = D_REG; + p->to.reg = REGTMP; + + break; + } + } + + if(debug['Q'] == 0) + return; + + curtext = P; + q = P; /* p - 1 */ + q1 = firstp; /* top of block */ + o = 0; /* count of instructions */ + for(p = firstp; p != P; p = p1) { + p1 = p->link; + o++; + if(p->mark & NOSCHED){ + if(q1 != p){ + sched(q1, q); + } + for(; p != P; 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; + } +} + +void +addnop(Prog *p) +{ + Prog *q; + + q = prg(); + q->as = AOR; + q->line = p->line; + q->from.type = D_REG; + q->from.reg = REGZERO; + q->to.type = D_REG; + q->to.reg = REGZERO; + + q->link = p->link; + p->link = q; +} + +#include "l.h" + +void +dodata(void) +{ + int i, t; + Sym *s; + Prog *p, *p1; + vlong orig, orig1, v; + + if(debug['v']) + Bprint(&bso, "%5.2f dodata\n", cputime()); + Bflush(&bso); + for(p = datap; p != P; p = p->link) { + s = p->from.sym; + if(p->as == ADYNT || p->as == AINIT) + s->value = dtype; + if(s->type == SBSS) + s->type = SDATA; + if(s->type != SDATA) + diag("initialize non-data (%d): %s\n%P", + s->type, s->name, p); + v = p->from.offset + p->reg; + if(v > s->value) + diag("initialize bounds (%lld): %s\n%P", + s->value, s->name, p); + } + + /* + * pass 1 + * assign 'small' variables to data segment + * (rational is that data segment is more easily + * addressed through offset on REGSB) + */ + orig = 0; + for(i=0; ilink) { + t = s->type; + if(t != SDATA && t != SBSS) + continue; + v = s->value; + if(v == 0) { + diag("%s: no size", s->name); + v = 1; + } + v = rnd(v, 4); + s->value = v; + if(v > MINSIZ) + continue; + if(v >= 8) + orig = rnd(orig, 8); + s->value = orig; + orig += v; + s->type = SDATA1; + } + orig1 = orig; + + /* + * pass 2 + * assign 'data' variables to data segment + */ + for(i=0; ilink) { + t = s->type; + if(t != SDATA) { + if(t == SDATA1) + s->type = SDATA; + continue; + } + v = s->value; + if(v >= 8) + orig = rnd(orig, 8); + s->value = orig; + orig += v; + s->type = SDATA1; + } + + if(orig) + orig = rnd(orig, 8); + datsize = orig; + + /* + * pass 3 + * everything else to bss segment + */ + for(i=0; ilink) { + if(s->type != SBSS) + continue; + v = s->value; + if(v >= 8) + orig = rnd(orig, 8); + s->value = orig; + orig += v; + } + if(orig) + orig = rnd(orig, 8); + bsssize = orig-datsize; + + /* + * pass 4 + * add literals to all large values. + * at this time: + * small data is allocated DATA + * large data is allocated DATA1 + * large bss is allocated BSS + * the new literals are loaded between + * small data and large data. + */ + orig = 0; + for(p = firstp; p != P; p = p->link) { + if(p->as != AMOVW) + continue; + if(p->from.type != D_CONST) + continue; + if(s = p->from.sym) { + t = s->type; + if(t != SDATA && t != SDATA1 && t != SBSS) + continue; + t = p->from.name; + if(t != D_EXTERN && t != D_STATIC) + continue; + v = s->value + p->from.offset; + if(v >= 0 && v <= 0xffff) + continue; + if(!strcmp(s->name, "setSB")) + continue; + /* size should be 19 max */ + if(strlen(s->name) >= 10) /* has loader address */ + sprint(literal, "$%p.%llux", s, p->from.offset); + else + sprint(literal, "$%s.%d.%llux", s->name, s->version, p->from.offset); + } else { + if(p->from.name != D_NONE) + continue; + if(p->from.reg != NREG) + continue; + v = p->from.offset; + if(v >= -0x7fff-1 && v <= 0x7fff) + continue; + if(!(v & 0xffff)) + continue; + if(v) + continue; /* quicker to build it than load it */ + /* size should be 9 max */ + sprint(literal, "$%llux", v); + } + s = lookup(literal, 0); + if(s->type == 0) { + s->type = SDATA; + s->value = orig1+orig; + orig += 4; + p1 = prg(); + p1->as = ADATA; + p1->line = p->line; + p1->from.type = D_OREG; + p1->from.sym = s; + p1->from.name = D_EXTERN; + p1->reg = 4; + p1->to = p->from; + p1->link = datap; + datap = p1; + } + if(s->type != SDATA) + diag("literal not data: %s", s->name); + p->from.type = D_OREG; + p->from.sym = s; + p->from.name = D_EXTERN; + p->from.offset = 0; + continue; + } + while(orig & 7) + orig++; + /* + * pass 5 + * re-adjust offsets + */ + for(i=0; ilink) { + t = s->type; + if(t == SBSS) { + s->value += orig; + continue; + } + if(t == SDATA1) { + s->type = SDATA; + s->value += orig; + continue; + } + } + datsize += orig; + xdefine("setSB", SDATA, 0+BIG); + xdefine("bdata", SDATA, 0); + xdefine("edata", SDATA, datsize); + xdefine("end", SBSS, datsize+bsssize); + xdefine("etext", STEXT, 0); +} + +void +undef(void) +{ + int i; + Sym *s; + + for(i=0; ilink) + if(s->type == SXREF) + diag("%s: not defined", s->name); +} + +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; +} + +void +follow(void) +{ + + if(debug['v']) + Bprint(&bso, "%5.2f follow\n", cputime()); + Bflush(&bso); + + firstp = prg(); + lastp = firstp; + + xfol(textp); + + firstp = firstp->link; + lastp->link = P; +} + +void +xfol(Prog *p) +{ + Prog *q, *r; + int a, b, i; + +loop: + if(p == P) + return; + a = p->as; + if(a == ATEXT) + curtext = p; + if(a == ABR) { + q = p->cond; + if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){ + p->mark |= FOLL; + lastp->link = p; + lastp = p; + p = p->link; + xfol(p); + p = q; + if(p && !(p->mark & FOLL)) + goto loop; + return; + } + if(q != P) { + 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 == lastp || (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->cond || (q->cond->mark&FOLL)) + continue; + b = relinv(a); + if(!b) + continue; + copy: + for(;;) { + r = prg(); + *r = *p; + if(!(r->mark&FOLL)) + print("cant happen 1\n"); + r->mark |= FOLL; + if(p != q) { + p = p->link; + lastp->link = r; + lastp = r; + continue; + } + lastp->link = r; + lastp = r; + if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID) + return; + r->as = b; + r->cond = p->link; + r->link = p->cond; + if(!(r->link->mark&FOLL)) + xfol(r->link); + if(!(r->cond->mark&FOLL)) + print("cant happen 2\n"); + return; + } + } + + a = ABR; + q = prg(); + q->as = a; + q->line = p->line; + q->to.type = D_BRANCH; + q->to.offset = p->pc; + q->cond = p; + p = q; + } + p->mark |= FOLL; + lastp->link = p; + lastp = 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->cond != P) + if(a != ABL && p->link != P) { + xfol(p->link); + p = p->cond; + if(p == P || (p->mark&FOLL)) + return; + goto loop; + } + p = p->link; + goto loop; +} + +void +patch(void) +{ + long c; + Prog *p, *q; + Sym *s; + int a; + vlong vexit; + + if(debug['v']) + Bprint(&bso, "%5.2f patch\n", cputime()); + Bflush(&bso); + mkfwd(); + s = lookup("exit", 0); + vexit = s->value; + for(p = firstp; p != P; p = p->link) { + a = p->as; + if(a == ATEXT) + curtext = p; + if((a == ABL || a == ARETURN) && p->to.sym != S) { + s = p->to.sym; + if(s->type != STEXT && s->type != SUNDEF) { + diag("undefined: %s\n%P", s->name, p); + s->type = STEXT; + s->value = vexit; + } + if(s->type == SUNDEF){ + p->to.offset = 0; + p->cond = UP; + } + else + p->to.offset = s->value; + p->to.type = D_BRANCH; + } + if(p->to.type != D_BRANCH || p->cond == UP) + continue; + c = p->to.offset; + for(q = firstp; q != P;) { + if(q->forwd != P) + if(c >= q->forwd->pc) { + q = q->forwd; + continue; + } + if(c == q->pc) + break; + q = q->link; + } + if(q == P) { + diag("branch out of range %ld\n%P", c, p); + p->to.type = D_NONE; + } + p->cond = q; + } + + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) + curtext = p; + p->mark = 0; /* initialization for follow */ + if(p->cond != P && p->cond != UP) { + p->cond = brloop(p->cond); + if(p->cond != P) + if(p->to.type == D_BRANCH) + p->to.offset = p->cond->pc; + } + } +} + +#define LOG 5 +void +mkfwd(void) +{ + Prog *p; + long dwn[LOG], cnt[LOG], i; + Prog *lst[LOG]; + + for(i=0; ilink) { + if(p->as == ATEXT) + curtext = p; + i--; + if(i < 0) + i = LOG-1; + p->forwd = P; + dwn[i]--; + if(dwn[i] <= 0) { + dwn[i] = cnt[i]; + if(lst[i] != P) + lst[i]->forwd = p; + lst[i] = p; + } + } +} + +Prog* +brloop(Prog *p) +{ + Prog *q; + int c; + + for(c=0; p!=P;) { + if(p->as != ABR || (p->mark&NOSCHED)) + return p; + q = p->cond; + if(q <= p) { + c++; + if(q == p || c > 5000) + break; + } + p = q; + } + return P; +} + +vlong +atolwhex(char *s) +{ + vlong n; + int f; + + n = 0; + f = 0; + while(*s == ' ' || *s == '\t') + s++; + if(*s == '-' || *s == '+') { + if(*s++ == '-') + f = 1; + while(*s == ' ' || *s == '\t') + s++; + } + if(s[0]=='0' && s[1]){ + if(s[1]=='x' || s[1]=='X'){ + s += 2; + for(;;){ + if(*s >= '0' && *s <= '9') + n = n*16 + *s++ - '0'; + else if(*s >= 'a' && *s <= 'f') + n = n*16 + *s++ - 'a' + 10; + else if(*s >= 'A' && *s <= 'F') + n = n*16 + *s++ - 'A' + 10; + else + break; + } + } else + while(*s >= '0' && *s <= '7') + n = n*8 + *s++ - '0'; + } else + while(*s >= '0' && *s <= '9') + n = n*10 + *s++ - '0'; + if(f) + n = -n; + return n; +} + +vlong +rnd(vlong v, long r) +{ + vlong c; + + if(r <= 0) + return v; + v += r - 1; + c = v % r; + if(c < 0) + c += r; + v -= c; + return v; +} + +void +import(void) +{ + int i; + Sym *s; + + for(i = 0; i < NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ + undefsym(s); + Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, s->value); + if(debug['S']) + s->sig = 0; + } +} + +void +ckoff(Sym *s, vlong v) +{ + if(v < 0 || v >= 1<name); +} + +static Prog* +newdata(Sym *s, int o, int w, int t) +{ + Prog *p; + + p = prg(); + p->link = datap; + datap = p; + p->as = ADATA; + p->reg = w; + p->from.type = D_OREG; + p->from.name = t; + p->from.sym = s; + p->from.offset = o; + p->to.type = D_CONST; + p->to.name = D_NONE; + return p; +} + +void +export(void) +{ + int i, j, n, off, nb, sv, ne; + Sym *s, *et, *str, **esyms; + Prog *p; + char buf[NSNAME], *t; + + n = 0; + for(i = 0; i < NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport)) + n++; + esyms = malloc(n*sizeof(Sym*)); + ne = n; + n = 0; + for(i = 0; i < NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport)) + esyms[n++] = s; + for(i = 0; i < ne-1; i++) + for(j = i+1; j < ne; j++) + if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ + s = esyms[i]; + esyms[i] = esyms[j]; + esyms[j] = s; + } + + nb = 0; + off = 0; + et = lookup(EXPTAB, 0); + if(et->type != 0 && et->type != SXREF) + diag("%s already defined", EXPTAB); + et->type = SDATA; + str = lookup(".string", 0); + if(str->type == 0) + str->type = SDATA; + sv = str->value; + for(i = 0; i < ne; i++){ + s = esyms[i]; + Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); + + /* signature */ + p = newdata(et, off, sizeof(long), D_EXTERN); + off += sizeof(long); + p->to.offset = s->sig; + + /* address */ + p = newdata(et, off, sizeof(long), D_EXTERN); + off += sizeof(long); /* TO DO: bug */ + p->to.name = D_EXTERN; + p->to.sym = s; + + /* string */ + t = s->name; + n = strlen(t)+1; + for(;;){ + buf[nb++] = *t; + sv++; + if(nb >= NSNAME){ + p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); + p->to.type = D_SCONST; + memmove(p->to.sval, buf, NSNAME); + nb = 0; + } + if(*t++ == 0) + break; + } + + /* name */ + p = newdata(et, off, sizeof(long), D_EXTERN); + off += sizeof(long); + p->to.name = D_STATIC; + p->to.sym = str; + p->to.offset = sv-n; + } + + if(nb > 0){ + p = newdata(str, sv-nb, nb, D_STATIC); + p->to.type = D_SCONST; + memmove(p->to.sval, buf, nb); + } + + for(i = 0; i < 3; i++){ + newdata(et, off, sizeof(long), D_EXTERN); + off += sizeof(long); + } + et->value = off; + if(sv == 0) + sv = 1; + str->value = sv; + exports = ne; + free(esyms); +} + +#include "l.h" + +void +span(void) +{ + Prog *p, *q; + Sym *setext; + Optab *o; + int m, bflag; + vlong c, otxt; + + if(debug['v']) + Bprint(&bso, "%5.2f span\n", cputime()); + Bflush(&bso); + + bflag = 0; + c = INITTEXT; + otxt = c; + for(p = firstp; p != P; p = p->link) { + p->pc = c; + o = oplook(p); + m = o->size; + if(m == 0) { + if(p->as == ATEXT) { + curtext = p; + autosize = p->to.offset + 8; + if(p->from3.type == D_CONST) { + if(p->from3.offset & 3) + diag("illegal origin\n%P", p); + if(c > p->from3.offset) + diag("passed origin (#%llux)\n%P", c, p); + else + c = p->from3.offset; + p->pc = c; + } + if(p->from.sym != S) + p->from.sym->value = c; + /* need passes to resolve branches? */ + if(c-otxt >= (1L<<15)) + bflag = c; + otxt = c; + continue; + } + if(p->as != ANOP) + diag("zero-width instruction\n%P", p); + continue; + } + c += m; + } + + /* + * 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. + */ + while(bflag) { + if(debug['v']) + Bprint(&bso, "%5.2f span1\n", cputime()); + bflag = 0; + c = INITTEXT; + for(p = firstp; p != P; p = p->link) { + p->pc = c; + o = oplook(p); + if((o->type == 16 || o->type == 17) && p->cond) { + otxt = p->cond->pc - c; + if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = p->cond; + p->cond = q; + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = q->link->link; + addnop(p->link); + addnop(p); + bflag = 1; + } + } + m = o->size; + if(m == 0) { + if(p->as == ATEXT) { + curtext = p; + autosize = p->to.offset + 8; + if(p->from.sym != S) + p->from.sym->value = c; + continue; + } + if(p->as != ANOP) + diag("zero-width instruction\n%P", p); + continue; + } + c += m; + } + } + + c = rnd(c, 8); + + setext = lookup("etext", 0); + if(setext != S) { + setext->value = c; + textsize = c - INITTEXT; + } + if(INITRND) + INITDAT = rnd(c, INITRND); + if(debug['v']) + Bprint(&bso, "tsize = %llux\n", textsize); + Bflush(&bso); +} + +void +xdefine(char *p, int t, vlong v) +{ + Sym *s; + + s = lookup(p, 0); + if(s->type == 0 || s->type == SXREF) { + s->type = t; + s->value = v; + } +} + +vlong +vregoff(Adr *a) +{ + + instoffset = 0; + aclass(a); + return instoffset; +} + +long +regoff(Adr *a) +{ + return vregoff(a); +} + +int +isint32(vlong v) +{ + long l; + + l = v; + return (vlong)l == v; +} + +int +isuint32(uvlong v) +{ + ulong l; + + l = v; + return (uvlong)l == v; +} + +int +aclass(Adr *a) +{ + Sym *s; + int t; + + 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 == S) + break; + t = a->sym->type; + if(t == 0 || t == SXREF) { + diag("undefined external: %s in %s", + a->sym->name, TNAME); + a->sym->type = SDATA; + } + if(dlm){ + instoffset = a->sym->value + a->offset; + switch(a->sym->type){ + case STEXT: + case SLEAF: + case SCONST: + case SUNDEF: + break; + default: + instoffset += INITDAT; + } + return C_ADDR; + } + instoffset = a->sym->value + a->offset - BIG; + if(instoffset >= -BIG && instoffset < BIG) + return C_SEXT; + return C_LEXT; + case D_AUTO: + instoffset = autosize + a->offset; + if(instoffset >= -BIG && instoffset < BIG) + return C_SAUTO; + return C_LAUTO; + case D_PARAM: + instoffset = autosize + a->offset + 8L; + if(instoffset >= -BIG && instoffset < BIG) + return C_SAUTO; + return C_LAUTO; + case D_NONE: + instoffset = a->offset; + if(instoffset == 0) + return C_ZOREG; + if(instoffset >= -BIG && instoffset < BIG) + return C_SOREG; + return C_LOREG; + } + return C_GOK; + + case D_OPT: + instoffset = a->offset & 31L; + if(a->name == D_NONE) + return C_SCON; + return C_GOK; + + case D_CONST: + switch(a->name) { + + case D_NONE: + instoffset = a->offset; + consize: + if(instoffset >= 0) { + if(instoffset == 0) + return C_ZCON; + if(instoffset <= 0x7fff) + return C_SCON; + if(instoffset <= 0xffff) + return C_ANDCON; + if((instoffset & 0xffff) == 0 && isuint32(instoffset)) /* && (instoffset & (1<<31)) == 0) */ + return C_UCON; + if(isint32(instoffset) || isuint32(instoffset)) + return C_LCON; + return C_DCON; + } + if(instoffset >= -0x8000) + return C_ADDCON; + if((instoffset & 0xffff) == 0 && isint32(instoffset)) + return C_UCON; + if(isint32(instoffset)) + return C_LCON; + return C_DCON; + + case D_EXTERN: + case D_STATIC: + s = a->sym; + if(s == S) + break; + t = s->type; + if(t == 0 || t == SXREF) { + diag("undefined external: %s in %s", + s->name, TNAME); + s->type = SDATA; + } + if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) { + instoffset = s->value + a->offset; + return C_LCON; + } + if(s->type == SCONST) { + instoffset = s->value + a->offset; + if(dlm) + return C_LCON; + goto consize; + } + if(!dlm){ + instoffset = s->value + a->offset - BIG; + if(instoffset >= -BIG && instoffset < BIG && instoffset != 0) + return C_SECON; + } + instoffset = s->value + a->offset + INITDAT; + if(dlm) + return C_LCON; + /* not sure why this barfs */ + return C_LCON; + /* + if(instoffset == 0) + return C_ZCON; + if(instoffset >= -0x8000 && instoffset <= 0xffff) + return C_SCON; + if((instoffset & 0xffff) == 0) + return C_UCON; + return C_LCON; + */ + + case D_AUTO: + instoffset = autosize + a->offset; + if(instoffset >= -BIG && instoffset < BIG) + return C_SACON; + return C_LACON; + + case D_PARAM: + instoffset = autosize + a->offset + 8L; + if(instoffset >= -BIG && instoffset < BIG) + return C_SACON; + return C_LACON; + } + return C_GOK; + + case D_BRANCH: + return C_SBRA; + } + return C_GOK; +} + +Optab* +oplook(Prog *p) +{ + int a1, a2, a3, a4, r; + char *c1, *c3, *c4; + Optab *o, *e; + + a1 = p->optab; + if(a1) + return optab+(a1-1); + a1 = p->from.class; + if(a1 == 0) { + a1 = aclass(&p->from) + 1; + p->from.class = a1; + } + a1--; + a3 = p->from3.class; + if(a3 == 0) { + a3 = aclass(&p->from3) + 1; + p->from3.class = a3; + } + a3--; + a4 = p->to.class; + if(a4 == 0) { + a4 = aclass(&p->to) + 1; + p->to.class = a4; + } + a4--; + a2 = C_NONE; + if(p->reg != NREG) + a2 = C_REG; + 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(; oa2 == a2) + if(c1[o->a1]) + if(c3[o->a3]) + if(c4[o->a4]) { + p->optab = (o-optab)+1; + return o; + } + diag("illegal combination %A %R %R %R %R", + p->as, a1, a2, a3, a4); + if(1||!debug['a']) + prasm(p); + if(o == 0) + errorexit(); + return o; +} + +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; +} + +int +ocmp(void *a1, void *a2) +{ + 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; +} + +void +buildop(void) +{ + int i, n, r; + + for(i=0; i 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]; + 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: + break; + } + } +} + +enum{ + ABSD = 0, + ABSU = 1, + RELD = 2, + RELU = 3, +}; + +int modemap[8] = { 0, 1, -1, 2, 3, 4, 5, 6}; + +typedef struct Reloc Reloc; + +struct Reloc +{ + int n; + int t; + uchar *m; + ulong *a; +}; + +Reloc rels; + +static void +grow(Reloc *r) +{ + int t; + uchar *m, *nm; + ulong *a, *na; + + t = r->t; + r->t += 64; + m = r->m; + a = r->a; + r->m = nm = malloc(r->t*sizeof(uchar)); + r->a = na = malloc(r->t*sizeof(ulong)); + memmove(nm, m, t*sizeof(uchar)); + memmove(na, a, t*sizeof(ulong)); + free(m); + free(a); +} + +void +dynreloc(Sym *s, long v, int abs, int split, int sext) +{ + int i, k, n; + uchar *m; + ulong *a; + Reloc *r; + + if(v&3) + diag("bad relocation address"); + v >>= 2; + if(s->type == SUNDEF) + k = abs ? ABSU : RELU; + else + k = abs ? ABSD : RELD; + if(split) + k += 4; + if(sext) + k += 2; + /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */ + k = modemap[k]; + r = &rels; + n = r->n; + if(n >= r->t) + grow(r); + m = r->m; + a = r->a; + for(i = n; i > 0; i--){ + if(v < a[i-1]){ /* happens occasionally for data */ + m[i] = m[i-1]; + a[i] = a[i-1]; + } + else + break; + } + m[i] = k; + a[i] = v; + r->n++; +} + +static int +sput(char *s) +{ + char *p; + + p = s; + while(*s) + cput(*s++); + cput(0); + return s-p+1; +} + +void +asmdyn() +{ + int i, n, t, c; + Sym *s; + ulong la, ra, *a; + vlong off; + uchar *m; + Reloc *r; + + cflush(); + off = seek(cout, 0, 1); + lput(0); + t = 0; + lput(imports); + t += 4; + for(i = 0; i < NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + if(s->type == SUNDEF){ + lput(s->sig); + t += 4; + t += sput(s->name); + } + + la = 0; + r = &rels; + n = r->n; + m = r->m; + a = r->a; + lput(n); + t += 4; + for(i = 0; i < n; i++){ + ra = *a-la; + if(*a < la) + diag("bad relocation order"); + if(ra < 256) + c = 0; + else if(ra < 65536) + c = 1; + else + c = 2; + cput((c<<6)|*m++); + t++; + if(c == 0){ + cput(ra); + t++; + } + else if(c == 1){ + wput(ra); + t += 2; + } + else{ + lput(ra); + t += 4; + } + la = *a++; + } + + cflush(); + seek(cout, off, 0); + lput(t); + + if(debug['v']){ + Bprint(&bso, "import table entries = %d\n", imports); + Bprint(&bso, "export table entries = %d\n", exports); + } +} 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; slink; + 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<used.ireg |= 1<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<from.reg; + s->set.cr |= 1<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<set.ireg |= 1<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<set.ireg |= 1<used.ireg |= 1<set.ireg |= 1<used.ireg |= 1<to.reg; + else + s->set.ireg |= 1<to.reg; + break; + case C_FREG: + if(ar) + s->used.freg |= 1<to.reg; + else + s->set.freg |= 1<to.reg; + break; + case C_SAUTO: + case C_LAUTO: + s->used.ireg |= 1<set.ireg |= 1<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<set.ireg |= 1<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<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<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<used.ireg |= 1<used.ireg |= 1<from.reg; + break; + case C_FREG: + s->used.freg |= 1<from.reg; + break; + case C_SAUTO: + case C_LAUTO: + s->used.ireg |= 1<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<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<used.ireg |= 1<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<freg & (1<cr & (1<cc & (1<size); + break; + case E_MEMSB: + Bprint(&bso, " SB%d", s->size); + break; + case E_MEMSP: + Bprint(&bso, " SP%d", s->size); + break; + } +} -- cgit v1.2.1 From f2df9fb26fffce8bb9975d9f81a49dd1df22c839 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 23:43:36 -0400 Subject: [dev.power64] cmd/9g: add doc.go to prevent build failures. After CL 117670045, cmd/dist will expect to have a cmd/9g directory. LGTM=rsc, dave R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/126780043 --- src/cmd/9g/doc.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/cmd/9g/doc.go (limited to 'src') 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 -- cgit v1.2.1 From 8a1bf66795f0aa63adcd4cad3dcbca14067863da Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 23:59:14 -0400 Subject: [dev.power64] cmd/dist: power64/power64le support. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/117670045 --- src/cmd/dist/build.c | 43 +++++++++++++++++++++++++++++++++++++++---- src/cmd/dist/buildruntime.c | 7 +++++++ 2 files changed, 46 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index 2e0f5b636..1feeccf41 100644 --- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -347,6 +347,7 @@ static char *oldtool[] = { "5a", "5c", "5g", "5l", "6a", "6c", "6g", "6l", "8a", "8c", "8g", "8l", + "9a", "9c", "9g", "9l", "6cov", "6nm", "6prof", @@ -553,6 +554,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", @@ -577,6 +583,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/*", }}, @@ -586,6 +600,9 @@ static struct { {"cmd/8l", { "../ld/*", }}, + {"cmd/9l", { + "../ld/*", + }}, {"cmd/go", { "zdefaultcc.go", }}, @@ -1178,12 +1195,26 @@ shouldbuild(char *file, char *dir) // Check file name for GOOS or GOARCH. name = lastelem(file); - for(i=0; i Date: Thu, 7 Aug 2014 12:02:36 -0400 Subject: [dev.power64] liblink: move span and asmout related function from obj9.c to asm9.c To reduce delta for the upcoming liblink CL. Just code movement, no semantic changes. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/124830043 --- src/liblink/asm9.c | 852 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/liblink/obj9.c | 852 ----------------------------------------------------- 2 files changed, 852 insertions(+), 852 deletions(-) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index ea510df79..27ccb0a23 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -402,6 +402,843 @@ Optab optab[] = { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, }; +#include "l.h" + +void +span(void) +{ + Prog *p, *q; + Sym *setext; + Optab *o; + int m, bflag; + vlong c, otxt; + + if(debug['v']) + Bprint(&bso, "%5.2f span\n", cputime()); + Bflush(&bso); + + bflag = 0; + c = INITTEXT; + otxt = c; + for(p = firstp; p != P; p = p->link) { + p->pc = c; + o = oplook(p); + m = o->size; + if(m == 0) { + if(p->as == ATEXT) { + curtext = p; + autosize = p->to.offset + 8; + if(p->from3.type == D_CONST) { + if(p->from3.offset & 3) + diag("illegal origin\n%P", p); + if(c > p->from3.offset) + diag("passed origin (#%llux)\n%P", c, p); + else + c = p->from3.offset; + p->pc = c; + } + if(p->from.sym != S) + p->from.sym->value = c; + /* need passes to resolve branches? */ + if(c-otxt >= (1L<<15)) + bflag = c; + otxt = c; + continue; + } + if(p->as != ANOP) + diag("zero-width instruction\n%P", p); + continue; + } + c += m; + } + + /* + * 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. + */ + while(bflag) { + if(debug['v']) + Bprint(&bso, "%5.2f span1\n", cputime()); + bflag = 0; + c = INITTEXT; + for(p = firstp; p != P; p = p->link) { + p->pc = c; + o = oplook(p); + if((o->type == 16 || o->type == 17) && p->cond) { + otxt = p->cond->pc - c; + if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = p->cond; + p->cond = q; + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = q->link->link; + addnop(p->link); + addnop(p); + bflag = 1; + } + } + m = o->size; + if(m == 0) { + if(p->as == ATEXT) { + curtext = p; + autosize = p->to.offset + 8; + if(p->from.sym != S) + p->from.sym->value = c; + continue; + } + if(p->as != ANOP) + diag("zero-width instruction\n%P", p); + continue; + } + c += m; + } + } + + c = rnd(c, 8); + + setext = lookup("etext", 0); + if(setext != S) { + setext->value = c; + textsize = c - INITTEXT; + } + if(INITRND) + INITDAT = rnd(c, INITRND); + if(debug['v']) + Bprint(&bso, "tsize = %llux\n", textsize); + Bflush(&bso); +} + +void +xdefine(char *p, int t, vlong v) +{ + Sym *s; + + s = lookup(p, 0); + if(s->type == 0 || s->type == SXREF) { + s->type = t; + s->value = v; + } +} + +int +isint32(vlong v) +{ + long l; + + l = v; + return (vlong)l == v; +} + +int +isuint32(uvlong v) +{ + ulong l; + + l = v; + return (uvlong)l == v; +} + +int +aclass(Adr *a) +{ + Sym *s; + int t; + + 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 == S) + break; + t = a->sym->type; + if(t == 0 || t == SXREF) { + diag("undefined external: %s in %s", + a->sym->name, TNAME); + a->sym->type = SDATA; + } + if(dlm){ + instoffset = a->sym->value + a->offset; + switch(a->sym->type){ + case STEXT: + case SLEAF: + case SCONST: + case SUNDEF: + break; + default: + instoffset += INITDAT; + } + return C_ADDR; + } + instoffset = a->sym->value + a->offset - BIG; + if(instoffset >= -BIG && instoffset < BIG) + return C_SEXT; + return C_LEXT; + case D_AUTO: + instoffset = autosize + a->offset; + if(instoffset >= -BIG && instoffset < BIG) + return C_SAUTO; + return C_LAUTO; + case D_PARAM: + instoffset = autosize + a->offset + 8L; + if(instoffset >= -BIG && instoffset < BIG) + return C_SAUTO; + return C_LAUTO; + case D_NONE: + instoffset = a->offset; + if(instoffset == 0) + return C_ZOREG; + if(instoffset >= -BIG && instoffset < BIG) + return C_SOREG; + return C_LOREG; + } + return C_GOK; + + case D_OPT: + instoffset = a->offset & 31L; + if(a->name == D_NONE) + return C_SCON; + return C_GOK; + + case D_CONST: + switch(a->name) { + + case D_NONE: + instoffset = a->offset; + consize: + if(instoffset >= 0) { + if(instoffset == 0) + return C_ZCON; + if(instoffset <= 0x7fff) + return C_SCON; + if(instoffset <= 0xffff) + return C_ANDCON; + if((instoffset & 0xffff) == 0 && isuint32(instoffset)) /* && (instoffset & (1<<31)) == 0) */ + return C_UCON; + if(isint32(instoffset) || isuint32(instoffset)) + return C_LCON; + return C_DCON; + } + if(instoffset >= -0x8000) + return C_ADDCON; + if((instoffset & 0xffff) == 0 && isint32(instoffset)) + return C_UCON; + if(isint32(instoffset)) + return C_LCON; + return C_DCON; + + case D_EXTERN: + case D_STATIC: + s = a->sym; + if(s == S) + break; + t = s->type; + if(t == 0 || t == SXREF) { + diag("undefined external: %s in %s", + s->name, TNAME); + s->type = SDATA; + } + if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) { + instoffset = s->value + a->offset; + return C_LCON; + } + if(s->type == SCONST) { + instoffset = s->value + a->offset; + if(dlm) + return C_LCON; + goto consize; + } + if(!dlm){ + instoffset = s->value + a->offset - BIG; + if(instoffset >= -BIG && instoffset < BIG && instoffset != 0) + return C_SECON; + } + instoffset = s->value + a->offset + INITDAT; + if(dlm) + return C_LCON; + /* not sure why this barfs */ + return C_LCON; + /* + if(instoffset == 0) + return C_ZCON; + if(instoffset >= -0x8000 && instoffset <= 0xffff) + return C_SCON; + if((instoffset & 0xffff) == 0) + return C_UCON; + return C_LCON; + */ + + case D_AUTO: + instoffset = autosize + a->offset; + if(instoffset >= -BIG && instoffset < BIG) + return C_SACON; + return C_LACON; + + case D_PARAM: + instoffset = autosize + a->offset + 8L; + if(instoffset >= -BIG && instoffset < BIG) + return C_SACON; + return C_LACON; + } + return C_GOK; + + case D_BRANCH: + return C_SBRA; + } + return C_GOK; +} + +Optab* +oplook(Prog *p) +{ + int a1, a2, a3, a4, r; + char *c1, *c3, *c4; + Optab *o, *e; + + a1 = p->optab; + if(a1) + return optab+(a1-1); + a1 = p->from.class; + if(a1 == 0) { + a1 = aclass(&p->from) + 1; + p->from.class = a1; + } + a1--; + a3 = p->from3.class; + if(a3 == 0) { + a3 = aclass(&p->from3) + 1; + p->from3.class = a3; + } + a3--; + a4 = p->to.class; + if(a4 == 0) { + a4 = aclass(&p->to) + 1; + p->to.class = a4; + } + a4--; + a2 = C_NONE; + if(p->reg != NREG) + a2 = C_REG; + 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(; oa2 == a2) + if(c1[o->a1]) + if(c3[o->a3]) + if(c4[o->a4]) { + p->optab = (o-optab)+1; + return o; + } + diag("illegal combination %A %R %R %R %R", + p->as, a1, a2, a3, a4); + if(1||!debug['a']) + prasm(p); + if(o == 0) + errorexit(); + return o; +} + +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; +} + +int +ocmp(void *a1, void *a2) +{ + 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; +} + +void +buildop(void) +{ + int i, n, r; + + for(i=0; i 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]; + 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: + break; + } + } +} + #include "l.h" #define OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1)) @@ -1403,6 +2240,21 @@ asmout(Prog *p, Optab *o, int aflag) return 0; } +vlong +vregoff(Adr *a) +{ + + instoffset = 0; + aclass(a); + return instoffset; +} + +long +regoff(Adr *a) +{ + return vregoff(a); +} + long oprrr(int a) { diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index cf073ec36..0e869fb53 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -1220,858 +1220,6 @@ export(void) free(esyms); } -#include "l.h" - -void -span(void) -{ - Prog *p, *q; - Sym *setext; - Optab *o; - int m, bflag; - vlong c, otxt; - - if(debug['v']) - Bprint(&bso, "%5.2f span\n", cputime()); - Bflush(&bso); - - bflag = 0; - c = INITTEXT; - otxt = c; - for(p = firstp; p != P; p = p->link) { - p->pc = c; - o = oplook(p); - m = o->size; - if(m == 0) { - if(p->as == ATEXT) { - curtext = p; - autosize = p->to.offset + 8; - if(p->from3.type == D_CONST) { - if(p->from3.offset & 3) - diag("illegal origin\n%P", p); - if(c > p->from3.offset) - diag("passed origin (#%llux)\n%P", c, p); - else - c = p->from3.offset; - p->pc = c; - } - if(p->from.sym != S) - p->from.sym->value = c; - /* need passes to resolve branches? */ - if(c-otxt >= (1L<<15)) - bflag = c; - otxt = c; - continue; - } - if(p->as != ANOP) - diag("zero-width instruction\n%P", p); - continue; - } - c += m; - } - - /* - * 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. - */ - while(bflag) { - if(debug['v']) - Bprint(&bso, "%5.2f span1\n", cputime()); - bflag = 0; - c = INITTEXT; - for(p = firstp; p != P; p = p->link) { - p->pc = c; - o = oplook(p); - if((o->type == 16 || o->type == 17) && p->cond) { - otxt = p->cond->pc - c; - if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { - q = prg(); - q->link = p->link; - p->link = q; - q->as = ABR; - q->to.type = D_BRANCH; - q->cond = p->cond; - p->cond = q; - q = prg(); - q->link = p->link; - p->link = q; - q->as = ABR; - q->to.type = D_BRANCH; - q->cond = q->link->link; - addnop(p->link); - addnop(p); - bflag = 1; - } - } - m = o->size; - if(m == 0) { - if(p->as == ATEXT) { - curtext = p; - autosize = p->to.offset + 8; - if(p->from.sym != S) - p->from.sym->value = c; - continue; - } - if(p->as != ANOP) - diag("zero-width instruction\n%P", p); - continue; - } - c += m; - } - } - - c = rnd(c, 8); - - setext = lookup("etext", 0); - if(setext != S) { - setext->value = c; - textsize = c - INITTEXT; - } - if(INITRND) - INITDAT = rnd(c, INITRND); - if(debug['v']) - Bprint(&bso, "tsize = %llux\n", textsize); - Bflush(&bso); -} - -void -xdefine(char *p, int t, vlong v) -{ - Sym *s; - - s = lookup(p, 0); - if(s->type == 0 || s->type == SXREF) { - s->type = t; - s->value = v; - } -} - -vlong -vregoff(Adr *a) -{ - - instoffset = 0; - aclass(a); - return instoffset; -} - -long -regoff(Adr *a) -{ - return vregoff(a); -} - -int -isint32(vlong v) -{ - long l; - - l = v; - return (vlong)l == v; -} - -int -isuint32(uvlong v) -{ - ulong l; - - l = v; - return (uvlong)l == v; -} - -int -aclass(Adr *a) -{ - Sym *s; - int t; - - 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 == S) - break; - t = a->sym->type; - if(t == 0 || t == SXREF) { - diag("undefined external: %s in %s", - a->sym->name, TNAME); - a->sym->type = SDATA; - } - if(dlm){ - instoffset = a->sym->value + a->offset; - switch(a->sym->type){ - case STEXT: - case SLEAF: - case SCONST: - case SUNDEF: - break; - default: - instoffset += INITDAT; - } - return C_ADDR; - } - instoffset = a->sym->value + a->offset - BIG; - if(instoffset >= -BIG && instoffset < BIG) - return C_SEXT; - return C_LEXT; - case D_AUTO: - instoffset = autosize + a->offset; - if(instoffset >= -BIG && instoffset < BIG) - return C_SAUTO; - return C_LAUTO; - case D_PARAM: - instoffset = autosize + a->offset + 8L; - if(instoffset >= -BIG && instoffset < BIG) - return C_SAUTO; - return C_LAUTO; - case D_NONE: - instoffset = a->offset; - if(instoffset == 0) - return C_ZOREG; - if(instoffset >= -BIG && instoffset < BIG) - return C_SOREG; - return C_LOREG; - } - return C_GOK; - - case D_OPT: - instoffset = a->offset & 31L; - if(a->name == D_NONE) - return C_SCON; - return C_GOK; - - case D_CONST: - switch(a->name) { - - case D_NONE: - instoffset = a->offset; - consize: - if(instoffset >= 0) { - if(instoffset == 0) - return C_ZCON; - if(instoffset <= 0x7fff) - return C_SCON; - if(instoffset <= 0xffff) - return C_ANDCON; - if((instoffset & 0xffff) == 0 && isuint32(instoffset)) /* && (instoffset & (1<<31)) == 0) */ - return C_UCON; - if(isint32(instoffset) || isuint32(instoffset)) - return C_LCON; - return C_DCON; - } - if(instoffset >= -0x8000) - return C_ADDCON; - if((instoffset & 0xffff) == 0 && isint32(instoffset)) - return C_UCON; - if(isint32(instoffset)) - return C_LCON; - return C_DCON; - - case D_EXTERN: - case D_STATIC: - s = a->sym; - if(s == S) - break; - t = s->type; - if(t == 0 || t == SXREF) { - diag("undefined external: %s in %s", - s->name, TNAME); - s->type = SDATA; - } - if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) { - instoffset = s->value + a->offset; - return C_LCON; - } - if(s->type == SCONST) { - instoffset = s->value + a->offset; - if(dlm) - return C_LCON; - goto consize; - } - if(!dlm){ - instoffset = s->value + a->offset - BIG; - if(instoffset >= -BIG && instoffset < BIG && instoffset != 0) - return C_SECON; - } - instoffset = s->value + a->offset + INITDAT; - if(dlm) - return C_LCON; - /* not sure why this barfs */ - return C_LCON; - /* - if(instoffset == 0) - return C_ZCON; - if(instoffset >= -0x8000 && instoffset <= 0xffff) - return C_SCON; - if((instoffset & 0xffff) == 0) - return C_UCON; - return C_LCON; - */ - - case D_AUTO: - instoffset = autosize + a->offset; - if(instoffset >= -BIG && instoffset < BIG) - return C_SACON; - return C_LACON; - - case D_PARAM: - instoffset = autosize + a->offset + 8L; - if(instoffset >= -BIG && instoffset < BIG) - return C_SACON; - return C_LACON; - } - return C_GOK; - - case D_BRANCH: - return C_SBRA; - } - return C_GOK; -} - -Optab* -oplook(Prog *p) -{ - int a1, a2, a3, a4, r; - char *c1, *c3, *c4; - Optab *o, *e; - - a1 = p->optab; - if(a1) - return optab+(a1-1); - a1 = p->from.class; - if(a1 == 0) { - a1 = aclass(&p->from) + 1; - p->from.class = a1; - } - a1--; - a3 = p->from3.class; - if(a3 == 0) { - a3 = aclass(&p->from3) + 1; - p->from3.class = a3; - } - a3--; - a4 = p->to.class; - if(a4 == 0) { - a4 = aclass(&p->to) + 1; - p->to.class = a4; - } - a4--; - a2 = C_NONE; - if(p->reg != NREG) - a2 = C_REG; - 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(; oa2 == a2) - if(c1[o->a1]) - if(c3[o->a3]) - if(c4[o->a4]) { - p->optab = (o-optab)+1; - return o; - } - diag("illegal combination %A %R %R %R %R", - p->as, a1, a2, a3, a4); - if(1||!debug['a']) - prasm(p); - if(o == 0) - errorexit(); - return o; -} - -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; -} - -int -ocmp(void *a1, void *a2) -{ - 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; -} - -void -buildop(void) -{ - int i, n, r; - - for(i=0; i 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]; - 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: - break; - } - } -} - enum{ ABSD = 0, ABSU = 1, -- cgit v1.2.1 From fe70c5018f03ca22aaec913f5b5cfa5b89bdadd7 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:36:34 -0400 Subject: [dev.power64] cmd/9c: use liblink, use Go argument passing rules, support both endians LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/126800043 --- src/cmd/9c/cgen.c | 26 ++-- src/cmd/9c/doc.go | 17 +++ src/cmd/9c/gc.h | 167 ++++++++++-------------- src/cmd/9c/list.c | 225 +------------------------------- src/cmd/9c/machcap.c | 2 - src/cmd/9c/mul.c | 18 ++- src/cmd/9c/peep.c | 47 +++---- src/cmd/9c/reg.c | 84 ++++++------ src/cmd/9c/sgen.c | 16 ++- src/cmd/9c/swt.c | 361 +++++++-------------------------------------------- src/cmd/9c/txt.c | 132 +++++++++++++------ 11 files changed, 332 insertions(+), 763 deletions(-) create mode 100644 src/cmd/9c/doc.go (limited to 'src') diff --git a/src/cmd/9c/cgen.c b/src/cmd/9c/cgen.c index 93bb010aa..0d7a40294 100644 --- a/src/cmd/9c/cgen.c +++ b/src/cmd/9c/cgen.c @@ -27,9 +27,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" +#include "../../pkg/runtime/funcdata.h" void cgen(Node *n, Node *nn) @@ -38,7 +37,7 @@ cgen(Node *n, Node *nn) Prog *p1; Node nod, nod1, nod2, nod3, nod4; int o; - long v, curs; + int32 v, curs; if(debug['g']) { prtree(nn, "cgen lhs"); @@ -340,14 +339,17 @@ cgen(Node *n, Node *nn) return; } - o = reg[REGARG]; + if(REGARG >= 0) + o = reg[REGARG]; gargs(r, &nod, &nod1); + gpcdata(PCDATA_ArgSize, curarg); if(l->addable < INDEXED) { reglcgen(&nod, l, Z); gopcode(OFUNC, Z, Z, &nod); regfree(&nod); } else gopcode(OFUNC, Z, Z, l); + gpcdata(PCDATA_ArgSize, -1); if(REGARG>=0) if(o != reg[REGARG]) reg[REGARG]--; @@ -448,7 +450,7 @@ cgen(Node *n, Node *nn) diag(n, "DOT and no offset"); break; } - nod.xoffset += (long)r->vconst; + nod.xoffset += (int32)r->vconst; nod.type = n->type; cgen(&nod, nn); } @@ -564,7 +566,7 @@ void reglcgen(Node *t, Node *n, Node *nn) { Node *r; - long v; + int32 v; regialloc(t, n, nn); if(n->op == OIND) { @@ -653,7 +655,7 @@ boolgen(Node *n, int true, Node *nn) int o; Prog *p1, *p2; Node *l, *r, nod, nod1; - long curs; + int32 curs; if(debug['g']) { prtree(nn, "boolgen lhs"); @@ -805,12 +807,12 @@ boolgen(Node *n, int true, Node *nn) } void -sugen(Node *n, Node *nn, long w) +sugen(Node *n, Node *nn, int32 w) { Prog *p1; Node nod0, nod1, nod2, nod3, nod4, *l, *r; Type *t; - long pc1; + int32 pc1; int i, m, c; if(n == Z || n->type == T) @@ -844,12 +846,12 @@ sugen(Node *n, Node *nn, long w) reglcgen(&nod1, nn, Z); nn->type = t; - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ + 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)) /* isbigendian */ + if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */ gopcode(OAS, nod32const(n->vconst), Z, &nod1); else gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); @@ -870,7 +872,7 @@ sugen(Node *n, Node *nn, long w) diag(n, "DOT and no offset"); break; } - nod1.xoffset += (long)r->vconst; + nod1.xoffset += (int32)r->vconst; nod1.type = n->type; sugen(&nod1, nn, w); } 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 index 2b718b9f9..1c7d7837a 100644 --- a/src/cmd/9c/gc.h +++ b/src/cmd/9c/gc.h @@ -27,8 +27,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include #include "../cc/cc.h" -#include "../9c/9.out.h" +#include "../9l/9.out.h" /* * 9c/powerpc64 @@ -43,50 +44,23 @@ #define SZ_DOUBLE 8 #define FNX 100 -typedef struct Adr Adr; -typedef struct Prog Prog; typedef struct Case Case; typedef struct C1 C1; typedef struct Multab Multab; typedef struct Hintab Hintab; -typedef struct Var Var; typedef struct Reg Reg; typedef struct Rgn Rgn; -struct Adr -{ - union - { - vlong offset; - double dval; - char sval[NSNAME]; - }; - Sym* sym; - char type; - char reg; - char name; - char etype; -}; #define A ((Adr*)0) #define INDEXED 9 -struct Prog -{ - Adr from; - Adr from3; /* third argument for fmadd, fmsub, ... */ - Adr to; - Prog* link; - long lineno; - short as; - char reg; -}; #define P ((Prog*)0) struct Case { Case* link; vlong val; - long label; + int32 label; char def; char isv; }; @@ -95,12 +69,12 @@ struct Case struct C1 { vlong val; - long label; + int32 label; }; struct Multab { - long val; + int32 val; char code[20]; }; @@ -110,18 +84,10 @@ struct Hintab char hint[10]; }; -struct Var -{ - vlong offset; - Sym* sym; - char name; - char etype; -}; - struct Reg { - long pc; - long rpo; /* reverse post ordering */ + int32 pc; + int32 rpo; /* reverse post ordering */ Bits set; Bits use1; @@ -134,13 +100,13 @@ struct Reg Bits regdiff; Bits act; - long regu; - long loop; /* could be shorter */ + int32 regu; + int32 loop; /* could be shorter */ union { Reg* log5; - long active; + int32 active; }; Reg* p1; Reg* p2; @@ -161,28 +127,28 @@ struct Rgn short regno; }; -EXTERN long breakpc; -EXTERN long nbreak; +EXTERN int32 breakpc; +EXTERN int32 nbreak; EXTERN Case* cases; EXTERN Node constnode; EXTERN Node fconstnode; EXTERN Node vconstnode; -EXTERN long continpc; -EXTERN long curarg; -EXTERN long cursafe; -EXTERN Prog* firstp; +EXTERN int32 continpc; +EXTERN int32 curarg; +EXTERN int32 cursafe; EXTERN Prog* lastp; -EXTERN int hintabsize; -EXTERN long maxargsafe; +extern int hintabsize; +EXTERN int32 maxargsafe; EXTERN Multab multab[20]; EXTERN int mnstring; +EXTERN int retok; EXTERN Node* nodrat; EXTERN Node* nodret; EXTERN Node* nodsafe; -EXTERN long nrathole; -EXTERN long nstring; +EXTERN int32 nrathole; +EXTERN int32 nstring; EXTERN Prog* p; -EXTERN long pc; +EXTERN int32 pc; EXTERN Node regnode; EXTERN Node qregnode; EXTERN char string[NSNAME]; @@ -190,8 +156,8 @@ EXTERN Sym* symrathole; EXTERN Node znode; EXTERN Prog zprog; EXTERN int reg[NREG+NREG]; -EXTERN long exregoffset; -EXTERN long exfregoffset; +EXTERN int32 exregoffset; +EXTERN int32 exfregoffset; EXTERN uchar typechlpv[NTYPE]; #define BLOAD(r) band(bnot(r->refbehind), r->refahead) @@ -216,8 +182,8 @@ EXTERN Bits params; EXTERN Bits consts; EXTERN Bits addrs; -EXTERN long regbits; -EXTERN long exregbits; +EXTERN int32 regbits; +EXTERN int32 exregbits; EXTERN int change; EXTERN int suppress; @@ -227,9 +193,9 @@ EXTERN Reg* lastr; EXTERN Reg zreg; EXTERN Reg* freer; EXTERN Var var[NVAR]; -EXTERN long* idom; +EXTERN int32* idom; EXTERN Reg** rpo2r; -EXTERN long maxnr; +EXTERN int32 maxnr; #define R0ISZERO (debug['0']==0) @@ -245,6 +211,8 @@ void usedset(Node*, int); void noretval(int); void xcom(Node*); int bcomplex(Node*, Node*); +Prog* gtext(Sym*, int32); +vlong argsize(void); /* * cgen.c @@ -254,7 +222,7 @@ void reglcgen(Node*, Node*, Node*); void lcgen(Node*, Node*); void bcgen(Node*, int); void boolgen(Node*, int, Node*); -void sugen(Node*, Node*, long); +void sugen(Node*, Node*, int32); void layout(Node*, Node*, int, int, Node*); /* @@ -265,9 +233,10 @@ void gclean(void); void nextpc(void); void gargs(Node*, Node*, Node*); void garg1(Node*, Node*, Node*, int, Node**); -Node* nodconst(long); +Node* nodconst(int32); Node* nod32const(vlong); Node* nodfconst(double); +Node* nodgconst(vlong v, Type *t); void nodreg(Node*, Node*, int); void regret(Node*, Node*); void regalloc(Node*, Node*, Node*); @@ -279,36 +248,38 @@ void regaalloc(Node*, Node*); void regind(Node*, Node*); void gprep(Node*, Node*); void raddr(Node*, Prog*); -void naddr(Node*, Adr*); +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*, long); +void patch(Prog*, int32); int sconst(Node*); -int sval(long); +int sval(int32); int uconst(Node*); void gpseudo(int, Sym*, Node*); +void gprefetch(Node*); +void gpcdata(int, int); /* * swt.c */ -int swcmp(void*, void*); +int swcmp(const void*, const void*); void doswit(Node*); -void swit1(C1*, int, long, Node*); -void swit2(C1*, int, long, Node*, Node*); -void casf(void); +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*); -long outstring(char*, long); +int32 outstring(char*, int32); int mulcon(Node*, Node*); -Multab* mulcon0(Node*, long); -int mulcon1(Node*, long, Node*); +Multab* mulcon0(Node*, int32); +int mulcon1(Node*, int32, Node*); void nullwarn(Node*, Node*); -void sextern(Sym*, Node*, long, long); -void gextern(Sym*, Node*, long, long); +void sextern(Sym*, Node*, int32, int32); +void gextern(Sym*, Node*, int32, int32); void outcode(void); void ieeedtod(Ieee*, double); @@ -327,18 +298,18 @@ int Bconv(Fmt*); * reg.c */ Reg* rega(void); -int rcmp(void*, void*); +int rcmp(const void*, const void*); void regopt(Prog*); void addmove(Reg*, int, int, int); -Bits mkvar(Adr*, int); +Bits mkvar(Addr*, int); void prop(Reg*, Bits, Bits); -void loopit(Reg*, long); +void loopit(Reg*, int32); void synch(Reg*, Bits); -ulong allreg(ulong, Rgn*); +uint32 allreg(uint32, Rgn*); void paint1(Reg*, int); -ulong paint2(Reg*, int); -void paint3(Reg*, int, long, int); -void addreg(Adr*, int); +uint32 paint2(Reg*, int); +void paint3(Reg*, int, int32, int); +void addreg(Addr*, int); /* * peep.c @@ -347,24 +318,24 @@ void peep(void); void excise(Reg*); Reg* uniqp(Reg*); Reg* uniqs(Reg*); -int regtyp(Adr*); -int regzer(Adr*); -int anyvar(Adr*); +int regtyp(Addr*); +int regzer(Addr*); +int anyvar(Addr*); int subprop(Reg*); int copyprop(Reg*); -int copy1(Adr*, Adr*, Reg*, int); -int copyu(Prog*, Adr*, Adr*); +int copy1(Addr*, Addr*, Reg*, int); +int copyu(Prog*, Addr*, Addr*); -int copyas(Adr*, Adr*); -int copyau(Adr*, Adr*); -int copyau1(Prog*, Adr*); -int copysub(Adr*, Adr*, Adr*, int); -int copysub1(Prog*, Adr*, Adr*, int); +int copyas(Addr*, Addr*); +int copyau(Addr*, Addr*); +int copyau1(Prog*, Addr*); +int copysub(Addr*, Addr*, Addr*, int); +int copysub1(Prog*, Addr*, Addr*, int); -long RtoB(int); -long FtoB(int); -int BtoR(long); -int BtoF(long); +int32 RtoB(int); +int32 FtoB(int); +int BtoR(int32); +int BtoF(int32); /* * com64.c @@ -375,7 +346,7 @@ void bool64(Node*); #pragma varargck type "A" int #pragma varargck type "B" Bits -#pragma varargck type "D" Adr* -#pragma varargck type "N" Adr* +#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 index ed6213dba..5cfc442cb 100644 --- a/src/cmd/9c/list.c +++ b/src/cmd/9c/list.c @@ -27,234 +27,11 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #define EXTERN #include "gc.h" void listinit(void) { - - fmtinstall('A', Aconv); - fmtinstall('P', Pconv); - fmtinstall('S', Sconv); - fmtinstall('N', Nconv); - fmtinstall('D', Dconv); - fmtinstall('B', Bconv); -} - -int -Bconv(Fmt *fp) -{ - char str[STRINGSZ], ss[STRINGSZ], *s; - Bits bits; - int i; - - str[0] = 0; - bits = va_arg(fp->args, Bits); - while(bany(&bits)) { - i = bnum(bits); - if(str[0]) - strcat(str, " "); - if(var[i].sym == S) { - sprint(ss, "$%lld", var[i].offset); - s = ss; - } else - s = var[i].sym->name; - if(strlen(str) + strlen(s) + 1 >= STRINGSZ) - break; - strcat(str, s); - bits.b[i/32] &= ~(1L << (i%32)); - } - return fmtstrcpy(fp, str); -} - -int -Pconv(Fmt *fp) -{ - char str[STRINGSZ]; - Prog *p; - int a; - - p = va_arg(fp->args, Prog*); - a = p->as; - if(a == ADATA) - sprint(str, " %A %D/%d,%D", a, &p->from, p->reg, &p->to); - else - if(p->as == ATEXT) - sprint(str, " %A %D,%d,%D", a, &p->from, p->reg, &p->to); - else - if(p->reg == NREG) - sprint(str, " %A %D,%D", a, &p->from, &p->to); - else - if(p->from.type != D_FREG) - sprint(str, " %A %D,R%d,%D", a, &p->from, p->reg, &p->to); - else - sprint(str, " %A %D,F%d,%D", a, &p->from, p->reg, &p->to); - return fmtstrcpy(fp, str); -} - -int -Aconv(Fmt *fp) -{ - char *s; - int a; - - a = va_arg(fp->args, int); - s = "???"; - if(a >= AXXX && a <= ALAST) - s = anames[a]; - return fmtstrcpy(fp, s); -} - -int -Dconv(Fmt *fp) -{ - char str[STRINGSZ]; - Adr *a; - - a = va_arg(fp->args, Adr*); - 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 != S) - sprint(str, "%N(R%d)(NONE)", a, a->reg); - break; - - case D_CONST: - if(a->reg != NREG) - sprint(str, "$%N(R%d)", a, a->reg); - else - sprint(str, "$%N", a); - break; - - case D_OREG: - if(a->reg != NREG) - sprint(str, "%N(R%d)", a, a->reg); - else - sprint(str, "%N", a); - break; - - case D_REG: - sprint(str, "R%d", a->reg); - if(a->name != D_NONE || a->sym != S) - sprint(str, "%N(R%d)(REG)", a, a->reg); - break; - - case D_FREG: - sprint(str, "F%d", a->reg); - if(a->name != D_NONE || a->sym != S) - sprint(str, "%N(F%d)(REG)", a, a->reg); - break; - - case D_CREG: - sprint(str, "C%d", a->reg); - if(a->name != D_NONE || a->sym != S) - sprint(str, "%N(C%d)(REG)", a, a->reg); - break; - - case D_BRANCH: - sprint(str, "%lld(PC)", a->offset-pc); - break; - - case D_FCONST: - sprint(str, "$%.17e", a->dval); - break; - - case D_SCONST: - sprint(str, "$\"%S\"", a->sval); - break; - } - return fmtstrcpy(fp, str); -} - -int -Sconv(Fmt *fp) -{ - int i, c; - char str[STRINGSZ], *p, *a; - - a = va_arg(fp->args, char*); - p = str; - for(i=0; i= '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; - case '\r': - *p++ = 'r'; - continue; - case '\f': - *p++ = 'f'; - continue; - } - *p++ = (c>>6) + '0'; - *p++ = ((c>>3) & 7) + '0'; - *p++ = (c & 7) + '0'; - } - *p = 0; - return fmtstrcpy(fp, str); -} - -int -Nconv(Fmt *fp) -{ - char str[STRINGSZ]; - Adr *a; - Sym *s; - - a = va_arg(fp->args, Adr*); - s = a->sym; - if(s == S) { - sprint(str, "%lld", a->offset); - goto out; - } - switch(a->name) { - default: - sprint(str, "GOK-name(%d)", a->name); - break; - - case D_EXTERN: - sprint(str, "%s+%lld(SB)", s->name, a->offset); - break; - - case D_STATIC: - sprint(str, "%s<>+%lld(SB)", s->name, a->offset); - break; - - case D_AUTO: - sprint(str, "%s-%lld(SP)", s->name, -a->offset); - break; - - case D_PARAM: - sprint(str, "%s+%lld(FP)", s->name, a->offset); - break; - } -out: - return fmtstrcpy(fp, str); + listinit9(); } diff --git a/src/cmd/9c/machcap.c b/src/cmd/9c/machcap.c index 1d66146be..af44bc820 100644 --- a/src/cmd/9c/machcap.c +++ b/src/cmd/9c/machcap.c @@ -27,8 +27,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" int diff --git a/src/cmd/9c/mul.c b/src/cmd/9c/mul.c index fdbf0fcb2..353376f15 100644 --- a/src/cmd/9c/mul.c +++ b/src/cmd/9c/mul.c @@ -27,8 +27,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" /* @@ -42,15 +40,15 @@ */ static int multabp; -static long mulval; +static int32 mulval; static char* mulcp; -static long valmax; +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, long r1); -static int gen3(int len, long r0, long r1, int flag); +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 */ @@ -60,7 +58,7 @@ enum }; Multab* -mulcon0(Node *n, long v) +mulcon0(Node *n, int32 v) { int a1, a2, g; Multab *m, *m1; @@ -266,7 +264,7 @@ gen1(int len) } static int -gen2(int len, long r1) +gen2(int len, int32 r1) { int i; @@ -316,10 +314,10 @@ out: } static int -gen3(int len, long r0, long r1, int flag) +gen3(int len, int32 r0, int32 r1, int flag) { int i, f1, f2; - long x; + int32 x; if(r0 <= 0 || r0 >= r1 || diff --git a/src/cmd/9c/peep.c b/src/cmd/9c/peep.c index 6cb09dd42..2e8e2adcc 100644 --- a/src/cmd/9c/peep.c +++ b/src/cmd/9c/peep.c @@ -27,10 +27,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" +/* static Reg* rnops(Reg *r) { @@ -49,6 +48,7 @@ rnops(Reg *r) } return r; } +*/ void peep(void) @@ -389,11 +389,12 @@ uniqs(Reg *r) * if the system forces R0 to be zero, * convert references to $0 to references to R0. */ -regzer(Adr *a) +int +regzer(Addr *a) { if(R0ISZERO) { if(a->type == D_CONST) - if(a->sym == S) + if(a->sym == nil) if(a->offset == 0) return 1; if(a->type == D_REG) @@ -403,7 +404,8 @@ regzer(Adr *a) return 0; } -regtyp(Adr *a) +int +regtyp(Addr *a) { if(a->type == D_REG) { @@ -434,7 +436,7 @@ int subprop(Reg *r0) { Prog *p; - Adr *v1, *v2; + Addr *v1, *v2; Reg *r; int t; @@ -589,7 +591,7 @@ int copyprop(Reg *r0) { Prog *p; - Adr *v1, *v2; + Addr *v1, *v2; Reg *r; p = r0->prog; @@ -602,7 +604,8 @@ copyprop(Reg *r0) return copy1(v1, v2, r0->s1, 0); } -copy1(Adr *v1, Adr *v2, Reg *r, int f) +int +copy1(Addr *v1, Addr *v2, Reg *r, int f) { int t; Prog *p; @@ -624,7 +627,7 @@ copy1(Adr *v1, Adr *v2, Reg *r, int f) if(debug['P']) print("; merge; f=%d", f); } - t = copyu(p, v2, A); + t = copyu(p, v2, nil); switch(t) { case 2: /* rar, cant split */ if(debug['P']) @@ -662,7 +665,7 @@ copy1(Adr *v1, Adr *v2, Reg *r, int f) break; } if(!f) { - t = copyu(p, v1, A); + t = copyu(p, v1, nil); if(!f && (t == 2 || t == 3 || t == 4)) { f = 1; if(debug['P']) @@ -687,14 +690,14 @@ copy1(Adr *v1, Adr *v2, Reg *r, int f) * 0 otherwise (not touched) */ int -copyu(Prog *p, Adr *v, Adr *s) +copyu(Prog *p, Addr *v, Addr *s) { switch(p->as) { default: if(debug['P']) - print(" (???)"); + print(" (\?\?\?)"); return 2; @@ -725,7 +728,7 @@ copyu(Prog *p, Adr *v, Adr *s) case AFRSP: case AFNEG: case AFNEGCC: - if(s != A) { + if(s != nil) { if(copysub(&p->from, v, s, 1)) return 1; if(!copyas(&p->to, v)) @@ -796,7 +799,7 @@ copyu(Prog *p, Adr *v, Adr *s) case AFMUL: case AFDIVS: case AFDIV: - if(s != A) { + if(s != nil) { if(copysub(&p->from, v, s, 1)) return 1; if(copysub1(p, v, s, 1)) @@ -839,7 +842,7 @@ copyu(Prog *p, Adr *v, Adr *s) case ACMPWU: case AFCMPO: case AFCMPU: - if(s != A) { + if(s != nil) { if(copysub(&p->from, v, s, 1)) return 1; return copysub(&p->to, v, s, 1); @@ -851,7 +854,7 @@ copyu(Prog *p, Adr *v, Adr *s) break; case ABR: /* funny */ - if(s != A) { + if(s != nil) { if(copysub(&p->to, v, s, 1)) return 1; return 0; @@ -880,7 +883,7 @@ copyu(Prog *p, Adr *v, Adr *s) return 2; } - if(s != A) { + if(s != nil) { if(copysub(&p->to, v, s, 1)) return 1; return 0; @@ -1008,7 +1011,7 @@ a2type(Prog *p) * semantics */ int -copyas(Adr *a, Adr *v) +copyas(Addr *a, Addr *v) { if(regtyp(v)) @@ -1022,7 +1025,7 @@ copyas(Adr *a, Adr *v) * either direct or indirect */ int -copyau(Adr *a, Adr *v) +copyau(Addr *a, Addr *v) { if(copyas(a, v)) @@ -1035,7 +1038,7 @@ copyau(Adr *a, Adr *v) } int -copyau1(Prog *p, Adr *v) +copyau1(Prog *p, Addr *v) { if(regtyp(v)) @@ -1053,7 +1056,7 @@ copyau1(Prog *p, Adr *v) * return failure to substitute */ int -copysub(Adr *a, Adr *v, Adr *s, int f) +copysub(Addr *a, Addr *v, Addr *s, int f) { if(f) @@ -1063,7 +1066,7 @@ copysub(Adr *a, Adr *v, Adr *s, int f) } int -copysub1(Prog *p1, Adr *v, Adr *s, int f) +copysub1(Prog *p1, Addr *v, Addr *s, int f) { if(f) diff --git a/src/cmd/9c/reg.c b/src/cmd/9c/reg.c index ee48588c7..658fa3211 100644 --- a/src/cmd/9c/reg.c +++ b/src/cmd/9c/reg.c @@ -27,8 +27,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" Reg* @@ -47,9 +45,9 @@ rega(void) } int -rcmp(void *a1, void *a2) +rcmp(const void *a1, const void *a2) { - Rgn *p1, *p2; + const Rgn *p1, *p2; int c1, c2; p1 = a1; @@ -67,13 +65,13 @@ regopt(Prog *p) Reg *r, *r1, *r2; Prog *p1; int i, z; - long initpc, val, npc; - ulong vreg; + int32 initpc, val, npc; + uint32 vreg; Bits bit; struct { - long m; - long c; + int32 m; + int32 c; Reg* p; } log5[6], *lp; @@ -110,6 +108,7 @@ regopt(Prog *p) case AGLOBL: case ANAME: case ASIGNAME: + case AFUNCDATA: continue; } r = rega(); @@ -447,6 +446,7 @@ brk: case AGLOBL: case ANAME: case ASIGNAME: + case AFUNCDATA: break; } } @@ -463,8 +463,10 @@ brk: r1 = 0; /* set */ for(r = firstr; r != R; r = r->link) { p = r->prog; - if(p->to.type == D_BRANCH) + if(p->to.type == D_BRANCH) { p->to.offset = r->s2->pc; + p->to.u.branch = r->s2->prog; + } r1 = r; } @@ -491,7 +493,7 @@ void addmove(Reg *r, int bn, int rn, int f) { Prog *p, *p1; - Adr *a; + Addr *a; Var *v; p1 = alloc(sizeof(*p1)); @@ -510,7 +512,7 @@ addmove(Reg *r, int bn, int rn, int f) a->offset = v->offset; a->etype = v->etype; a->type = D_OREG; - if(a->etype == TARRAY || a->sym == S) + if(a->etype == TARRAY || a->sym == nil) a->type = D_CONST; p1->as = AMOVW; @@ -552,13 +554,13 @@ addmove(Reg *r, int bn, int rn, int f) } Bits -mkvar(Adr *a, int docon) +mkvar(Addr *a, int docon) { Var *v; int i, t, n, et, z; - long o; + int32 o; Bits bit; - Sym *s; + LSym *s; t = a->type; if(t == D_REG && a->reg != NREG) @@ -568,13 +570,13 @@ mkvar(Adr *a, int docon) s = a->sym; o = a->offset; et = a->etype; - if(s == S) { + if(s == nil) { if(t != D_CONST || !docon || a->reg != NREG) goto none; et = TLONG; } if(t == D_CONST) { - if(s == S && sval(o)) + if(s == nil && sval(o)) goto none; } n = a->name; @@ -615,7 +617,7 @@ out: for(z=0; z r) s = idom[s]; @@ -754,9 +756,9 @@ doms(long *idom, long r, long s) } int -loophead(long *idom, Reg *r) +loophead(int32 *idom, Reg *r) { - long src; + int32 src; src = r->rpo; if(r->p1 != R && doms(idom, src, r->p1->rpo)) @@ -768,7 +770,7 @@ loophead(long *idom, Reg *r) } void -loopmark(Reg **rpo2r, long head, Reg *r) +loopmark(Reg **rpo2r, int32 head, Reg *r) { if(r->rpo < head || r->active == head) return; @@ -781,14 +783,14 @@ loopmark(Reg **rpo2r, long head, Reg *r) } void -loopit(Reg *r, long nr) +loopit(Reg *r, int32 nr) { Reg *r1; - long i, d, me; + int32 i, d, me; if(nr > maxnr) { rpo2r = alloc(nr * sizeof(Reg*)); - idom = alloc(nr * sizeof(long)); + idom = alloc(nr * sizeof(int32)); maxnr = nr; } @@ -851,8 +853,8 @@ synch(Reg *r, Bits dif) } } -ulong -allreg(ulong b, Rgn *r) +uint32 +allreg(uint32 b, Rgn *r) { Var *v; int i; @@ -902,7 +904,7 @@ paint1(Reg *r, int bn) Reg *r1; Prog *p; int z; - ulong bb; + uint32 bb; z = bn/32; bb = 1L<<(bn%32); @@ -977,12 +979,12 @@ paint1(Reg *r, int bn) } } -ulong +uint32 paint2(Reg *r, int bn) { Reg *r1; int z; - ulong bb, vreg; + uint32 bb, vreg; z = bn/32; bb = 1L << (bn%32); @@ -1029,12 +1031,12 @@ paint2(Reg *r, int bn) } void -paint3(Reg *r, int bn, long rb, int rn) +paint3(Reg *r, int bn, int32 rb, int rn) { Reg *r1; Prog *p; int z; - ulong bb; + uint32 bb; z = bn/32; bb = 1L << (bn%32); @@ -1100,7 +1102,7 @@ paint3(Reg *r, int bn, long rb, int rn) } void -addreg(Adr *a, int rn) +addreg(Addr *a, int rn) { a->sym = 0; @@ -1121,7 +1123,7 @@ addreg(Adr *a, int rn) * ... ... * 21 R28 */ -long +int32 RtoB(int r) { @@ -1131,7 +1133,7 @@ RtoB(int r) } int -BtoR(long b) +BtoR(int32 b) { b &= 0x001fffffL; if(b == 0) @@ -1146,7 +1148,7 @@ BtoR(long b) * ... ... * 31 F26 */ -long +int32 FtoB(int f) { if(f < FREGMIN || f > FREGEXT) @@ -1155,7 +1157,7 @@ FtoB(int f) } int -BtoF(long b) +BtoF(int32 b) { b &= 0xffc00000L; diff --git a/src/cmd/9c/sgen.c b/src/cmd/9c/sgen.c index bad9a9c8a..25f0438e5 100644 --- a/src/cmd/9c/sgen.c +++ b/src/cmd/9c/sgen.c @@ -27,10 +27,22 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" +Prog* +gtext(Sym *s, int32 stkoff) +{ + vlong v; + + v = ((uvlong)argsize() << 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) { diff --git a/src/cmd/9c/swt.c b/src/cmd/9c/swt.c index d6f9833be..c912cd5ed 100644 --- a/src/cmd/9c/swt.c +++ b/src/cmd/9c/swt.c @@ -27,12 +27,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #include "gc.h" void -swit1(C1 *q, int nc, long def, Node *n) +swit1(C1 *q, int nc, int32 def, Node *n) { Node tn; @@ -42,7 +40,7 @@ swit1(C1 *q, int nc, long def, Node *n) } void -swit2(C1 *q, int nc, long def, Node *n, Node *tn) +swit2(C1 *q, int nc, int32 def, Node *n, Node *tn) { C1 *r; int i; @@ -86,7 +84,7 @@ void bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) { int sh; - long v; + int32 v; Node *l; /* @@ -124,7 +122,7 @@ bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) void bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) { - long v; + int32 v; Node nod, *l; int sh; @@ -154,10 +152,10 @@ bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) regfree(n3); } -long -outstring(char *s, long n) +int32 +outstring(char *s, int32 n) { - long r; + int32 r; if(suppress) return nstring; @@ -171,7 +169,7 @@ outstring(char *s, long n) p->from.offset += nstring - NSNAME; p->reg = NSNAME; p->to.type = D_SCONST; - memmove(p->to.sval, string, NSNAME); + memmove(p->to.u.sval, string, NSNAME); mnstring = 0; } n--; @@ -184,7 +182,7 @@ mulcon(Node *n, Node *nn) { Node *l, *r, nod1, nod2; Multab *m; - long v; + int32 v; int o; char code[sizeof(m->code)+2], *p; @@ -269,9 +267,9 @@ loop: } void -sextern(Sym *s, Node *a, long o, long w) +sextern(Sym *s, Node *a, int32 o, int32 w) { - long e, lw; + int32 e, lw; for(e=0; efrom.offset += o+e; p->reg = lw; p->to.type = D_SCONST; - memmove(p->to.sval, a->cstring+e, lw); + memmove(p->to.u.sval, a->cstring+e, lw); } } void -gextern(Sym *s, Node *a, long o, long w) +gextern(Sym *s, Node *a, int32 o, int32 w) { - if(a->op == OCONST && typev[a->type->etype]) { - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ - gpseudo(ADATA, s, nod32const(a->vconst>>32)); - else - gpseudo(ADATA, s, nod32const(a->vconst)); - p->from.offset += o; - p->reg = 4; - if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ - gpseudo(ADATA, s, nod32const(a->vconst)); - else - gpseudo(ADATA, s, nod32const(a->vconst>>32)); - p->from.offset += o + 4; - p->reg = 4; - return; - } gpseudo(ADATA, s, a); p->from.offset += o; p->reg = w; @@ -310,282 +293,28 @@ gextern(Sym *s, Node *a, long o, long w) p->to.type = D_CONST; } -void zname(Biobuf*, Sym*, int); -char* zaddr(char*, Adr*, int); -void zwrite(Biobuf*, Prog*, int, int); -void outhist(Biobuf*); - void outcode(void) { - struct { Sym *sym; short type; } h[NSYM]; - Prog *p; - Sym *s; - int sf, st, t, sym; - - if(debug['S']) { - for(p = firstp; p != P; p = p->link) - if(p->as != ADATA && p->as != AGLOBL) - pc--; - for(p = firstp; p != P; p = p->link) { - print("%P\n", p); - if(p->as != ADATA && p->as != AGLOBL) - pc++; - } - } - outhist(&outbuf); - for(sym=0; symlink) { - jackpot: - sf = 0; - s = p->from.sym; - while(s != S) { - sf = s->sym; - if(sf < 0 || sf >= NSYM) - sf = 0; - t = p->from.name; - if(h[sf].type == t) - if(h[sf].sym == s) - break; - s->sym = sym; - zname(&outbuf, s, t); - h[sym].sym = s; - h[sym].type = t; - sf = sym; - sym++; - if(sym >= NSYM) - sym = 1; - break; - } - st = 0; - s = p->to.sym; - while(s != S) { - st = s->sym; - if(st < 0 || st >= NSYM) - st = 0; - t = p->to.name; - if(h[st].type == t) - if(h[st].sym == s) - break; - s->sym = sym; - zname(&outbuf, s, t); - h[sym].sym = s; - h[sym].type = t; - st = sym; - sym++; - if(sym >= NSYM) - sym = 1; - if(st == sf) - goto jackpot; - break; - } - zwrite(&outbuf, p, sf, st); - } - firstp = P; - lastp = P; -} - -void -zwrite(Biobuf *b, Prog *p, int sf, int st) -{ - char bf[100], *bp; - long l; - - bf[0] = p->as; - bf[1] = p->as>>8; - bf[2] = p->reg; - l = p->lineno; - bf[3] = l; - bf[4] = l>>8; - bf[5] = l>>16; - bf[6] = l>>24; - bp = zaddr(bf+7, &p->from, sf); - bp = zaddr(bp, &p->to, st); - Bwrite(b, bf, bp-bf); -} - -void -outhist(Biobuf *b) -{ - Hist *h; - char *p, *q, *op, c; - Prog pg; - int n; - - pg = zprog; - pg.as = AHISTORY; - c = pathchar(); - for(h = hist; h != H; h = h->link) { - p = h->name; - op = 0; - /* on windows skip drive specifier in pathname */ - if(systemtype(Windows) && p && p[1] == ':'){ - p += 2; - c = *p; - } - if(p && p[0] != c && h->offset == 0 && pathname){ - /* on windows skip drive specifier in pathname */ - if(systemtype(Windows) && pathname[1] == ':') { - op = p; - p = pathname+2; - c = *p; - } else if(pathname[0] == c){ - op = p; - p = pathname; - } - } - while(p) { - q = utfrune(p, c); - if(q) { - n = q-p; - if(n == 0){ - n = 1; /* leading "/" */ - *p = '/'; /* don't emit "\" on windows */ - } - q++; - } else { - n = strlen(p); - q = 0; - } - if(n) { - Bputc(b, ANAME); - Bputc(b, ANAME>>8); - Bputc(b, D_FILE); - Bputc(b, 1); - Bputc(b, '<'); - Bwrite(b, p, n); - Bputc(b, 0); - } - p = q; - if(p == 0 && op) { - p = op; - op = 0; - } - } - pg.lineno = h->line; - pg.to.type = zprog.to.type; - pg.to.offset = h->offset; - if(h->offset) - pg.to.type = D_CONST; - - zwrite(b, &pg, 0, 0); - } -} - -void -zname(Biobuf *b, Sym *s, int t) -{ - char *n, bf[8]; - ulong sig; - - n = s->name; - if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ - sig = sign(s); - bf[0] = ASIGNAME; - bf[1] = ASIGNAME>>8; - bf[2] = sig; - bf[3] = sig>>8; - bf[4] = sig>>16; - bf[5] = sig>>24; - bf[6] = t; - bf[7] = s->sym; - Bwrite(b, bf, 8); - s->sig = SIGDONE; - } - else{ - bf[0] = ANAME; - bf[1] = ANAME>>8; - bf[2] = t; /* type */ - bf[3] = s->sym; /* sym */ - Bwrite(b, bf, 4); - } - Bwrite(b, n, strlen(n)+1); -} - -char* -zaddr(char *bp, Adr *a, int s) -{ - long l; - Ieee e; - - if(a->type == D_CONST){ - l = a->offset; - if((vlong)l != a->offset) - a->type = D_DCONST; + 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"); } - bp[0] = a->type; - bp[1] = a->reg; - bp[2] = s; - bp[3] = a->name; - bp += 4; - switch(a->type) { - default: - diag(Z, "unknown type %d in zaddr", a->type); - - case D_NONE: - case D_REG: - case D_FREG: - case D_CREG: - break; - - case D_OREG: - case D_CONST: - case D_BRANCH: - l = a->offset; - bp[0] = l; - bp[1] = l>>8; - bp[2] = l>>16; - bp[3] = l>>24; - bp += 4; - break; - - case D_DCONST: - l = a->offset; - bp[0] = l; - bp[1] = l>>8; - bp[2] = l>>16; - bp[3] = l>>24; - bp += 4; - l = a->offset>>32; - bp[0] = l; - bp[1] = l>>8; - bp[2] = l>>16; - bp[3] = l>>24; - bp += 4; - break; + Bprint(&outbuf, "!\n"); - case D_SCONST: - memmove(bp, a->sval, NSNAME); - bp += NSNAME; - break; - - case D_FCONST: - ieeedtod(&e, a->dval); - l = e.l; - bp[0] = l; - bp[1] = l>>8; - bp[2] = l>>16; - bp[3] = l>>24; - bp += 4; - l = e.h; - bp[0] = l; - bp[1] = l>>8; - bp[2] = l>>16; - bp[3] = l>>24; - bp += 4; - break; - } - return bp; + writeobj(ctxt, &outbuf); + lastp = nil; } -long -align(long i, Type *t, int op) +int32 +align(int32 i, Type *t, int op, int32 *maxalign) { - long o; + int32 o; Type *v; int w; @@ -597,7 +326,9 @@ align(long i, Type *t, int op) break; case Asu2: /* padding at end of a struct */ - w = SZ_VLONG; + w = *maxalign; + if(w < 1) + w = 1; if(packflg) w = packflg; break; @@ -605,9 +336,12 @@ align(long i, Type *t, int op) case Ael1: /* initial allign of struct element */ for(v=t; v->etype==TARRAY; v=v->link) ; - w = ewidth[v->etype]; - if(w <= 0 || w >= SZ_VLONG) - w = SZ_VLONG; + 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) w = packflg; break; @@ -618,8 +352,8 @@ align(long i, Type *t, int op) case Aarg0: /* initial passbyptr argument in arg list */ if(typesu[t->etype]) { - o = align(o, types[TIND], Aarg1); - o = align(o, types[TIND], Aarg2); + o = align(o, types[TIND], Aarg1, nil); + o = align(o, types[TIND], Aarg2, nil); } break; @@ -629,30 +363,33 @@ align(long i, Type *t, int op) w = SZ_VLONG; break; } - o += SZ_VLONG - w; /* big endian adjustment */ w = 1; break; case Aarg2: /* width of a parameter */ o += t->width; - w = SZ_VLONG; + w = t->width; + if(w > SZ_VLONG) + w = SZ_VLONG; break; case Aaut3: /* total align of automatic */ - o = align(o, t, Ael1); - o = align(o, t, Ael2); + o = align(o, t, Ael1, nil); + o = align(o, t, Ael2, nil); break; } - o = round(o, w); + 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; } -long -maxround(long max, long v) +int32 +maxround(int32 max, int32 v) { - v = round(v, SZ_VLONG); + 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 index 4cf23fc6a..345976cf2 100644 --- a/src/cmd/9c/txt.c +++ b/src/cmd/9c/txt.c @@ -27,21 +27,35 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #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; - thechar = '9'; - thestring = "power64"; + dodefine("_64BITREG"); + dodefine("_64BIT"); exregoffset = REGEXT; exfregoffset = FREGEXT; listinit(); @@ -52,12 +66,10 @@ ginit(void) breakpc = -1; continpc = -1; cases = C; - firstp = P; lastp = P; tfield = types[TLONG]; typeword = typechlvp; - typeswitch = typechlv; typecmplx = typesu; /* TO DO */ memmove(typechlpv, typechlp, sizeof(typechlpv)); @@ -70,6 +82,7 @@ ginit(void) 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; @@ -174,24 +187,25 @@ gclean(void) void nextpc(void) { + Plist *pl; p = alloc(sizeof(*p)); *p = zprog; p->lineno = nearln; + p->pc = pc; pc++; - if(firstp == P) { - firstp = p; - lastp = p; - return; - } - lastp->link = p; + if(lastp == P) { + pl = linknewplist(ctxt); + pl->firstpc = p; + } else + lastp->link = p; lastp = p; } void gargs(Node *n, Node *tn1, Node *tn2) { - long regs; + int32 regs; Node fnxargs[20], *fnxp; regs = cursafe; @@ -276,13 +290,13 @@ Node* nodgconst(vlong v, Type *t) { if(!typev[t->etype]) - return nodconst((long)v); + return nodconst((int32)v); vconstnode.vconst = v; return &vconstnode; } Node* -nodconst(long v) +nodconst(int32 v) { constnode.vconst = v; return &constnode; @@ -416,7 +430,7 @@ err: void regsalloc(Node *n, Node *nn) { - cursafe = align(cursafe, nn->type, Aaut3); + cursafe = align(cursafe, nn->type, Aaut3, nil); maxargsafe = maxround(maxargsafe, cursafe+curarg); *n = *nodsafe; n->xoffset = -(stkoff + cursafe); @@ -428,24 +442,26 @@ regsalloc(Node *n, Node *nn) void regaalloc1(Node *n, Node *nn) { + if(REGARG < 0) + return; nodreg(n, nn, REGARG); reg[REGARG]++; - curarg = align(curarg, nn->type, Aarg1); - curarg = align(curarg, nn->type, Aarg2); + 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); + 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); + curarg = align(curarg, nn->type, Aarg2, nil); maxargsafe = maxround(maxargsafe, cursafe+curarg); } @@ -464,7 +480,7 @@ regind(Node *n, Node *nn) void raddr(Node *n, Prog *p) { - Adr a; + Addr a; naddr(n, &a); if(R0ISZERO && a.type == D_CONST && a.offset == 0) { @@ -482,9 +498,9 @@ raddr(Node *n, Prog *p) } void -naddr(Node *n, Adr *a) +naddr(Node *n, Addr *a) { - long v; + int32 v; a->type = D_NONE; if(n == Z) @@ -492,12 +508,13 @@ naddr(Node *n, Adr *a) switch(n->op) { default: bad: - diag(n, "bad in naddr: %O", n->op); + prtree(n, "naddr"); + diag(n, "%L: !bad in naddr: %O", n->lineno, n->op); break; case OREGISTER: a->type = D_REG; - a->sym = S; + a->sym = nil; a->reg = n->reg; if(a->reg >= NREG) { a->type = D_FREG; @@ -519,7 +536,7 @@ naddr(Node *n, Adr *a) case OINDREG: a->type = D_OREG; - a->sym = S; + a->sym = nil; a->offset = n->xoffset; a->reg = n->reg; break; @@ -528,7 +545,7 @@ naddr(Node *n, Adr *a) a->etype = n->etype; a->type = D_OREG; a->name = D_STATIC; - a->sym = n->sym; + a->sym = linksym(n->sym); a->offset = n->xoffset; if(n->class == CSTATIC) break; @@ -547,11 +564,11 @@ naddr(Node *n, Adr *a) goto bad; case OCONST: - a->sym = S; + a->sym = nil; a->reg = NREG; if(typefd[n->type->etype]) { a->type = D_FCONST; - a->dval = n->fconst; + a->u.dval = n->fconst; } else { a->type = D_CONST; a->offset = n->vconst; @@ -786,7 +803,7 @@ gmove(Node *f, Node *t) case TUSHORT: case TCHAR: case TUCHAR: - /* BUG: not right for unsigned long */ + /* BUG: not right for unsigned int32 */ regalloc(&nod, f, Z); /* should be type float */ regsalloc(&fxrat, f); gins(AFCTIWZ, f, &nod); @@ -800,7 +817,7 @@ gmove(Node *f, Node *t) return; case TVLONG: case TUVLONG: - /* BUG: not right for unsigned long */ + /* BUG: not right for unsigned int32 */ regalloc(&nod, f, Z); /* should be type float */ regsalloc(&fxrat, f); gins(AFCTIDZ, f, &nod); @@ -1030,7 +1047,7 @@ void gopcode(int o, Node *f1, Node *f2, Node *t) { int a, et; - Adr ta; + Addr ta; int uns; uns = 0; @@ -1297,7 +1314,7 @@ gbranch(int o) } void -patch(Prog *op, long pc) +patch(Prog *op, int32 pc) { op->to.offset = pc; @@ -1311,9 +1328,18 @@ gpseudo(int a, Sym *s, Node *n) nextpc(); p->as = a; p->from.type = D_OREG; - p->from.sym = s; - if(a == ATEXT) - p->reg = (profileflg ? 0 : NOPROF); + 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; @@ -1323,7 +1349,7 @@ gpseudo(int a, Sym *s, Node *n) } int -sval(long v) +sval(int32 v) { if(v >= -(1<<15) && v < (1<<15)) @@ -1331,6 +1357,32 @@ sval(long v) 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) { @@ -1378,10 +1430,10 @@ immconst(Node *n) return 0; } -long +int32 exreg(Type *t) { - long o; + int32 o; if(typechlpv[t->etype]) { if(exregoffset <= 3) @@ -1423,7 +1475,7 @@ schar ewidth[NTYPE] = -1, /* [TUNION] */ SZ_INT, /* [TENUM] */ }; -long ncast[NTYPE] = +int32 ncast[NTYPE] = { 0, /* [TXXX] */ BCHAR|BUCHAR, /* [TCHAR] */ -- cgit v1.2.1 From 0178f2a25fe69bf71ea233df543f42267bc2e526 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:49:41 -0400 Subject: [dev.power64] cmd/9a: use liblink, add required additional instructions. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/127730043 --- src/cmd/9a/Makefile | 10 + src/cmd/9a/a.h | 126 +- src/cmd/9a/a.y | 80 +- src/cmd/9a/doc.go | 21 + src/cmd/9a/lex.c | 450 ++---- src/cmd/9a/y.tab.c | 3794 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/9a/y.tab.h | 192 +++ 7 files changed, 4234 insertions(+), 439 deletions(-) create mode 100644 src/cmd/9a/Makefile create mode 100644 src/cmd/9a/doc.go create mode 100644 src/cmd/9a/y.tab.c create mode 100644 src/cmd/9a/y.tab.h (limited to 'src') 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 index 2f5ff6d81..629543f13 100644 --- a/src/cmd/9a/a.h +++ b/src/cmd/9a/a.h @@ -27,19 +27,23 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include #include -#include "../9c/9.out.h" +#include +#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 Gen Gen; typedef struct Io Io; -typedef struct Hist Hist; #define MAXALIGN 7 #define FPCHIP 1 @@ -48,32 +52,15 @@ typedef struct Hist Hist; #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 -#define ALLOC(lhs, type)\ - while(nhunk < sizeof(type))\ - gethunk();\ - lhs = (type*)hunk;\ - nhunk -= sizeof(type);\ - hunk += sizeof(type); - -#define ALLOCN(lhs, len, n)\ - if(lhs+len != hunk || nhunk < n) {\ - while(nhunk <= len)\ - gethunk();\ - memmove(hunk, lhs, len);\ - lhs = hunk;\ - hunk += len;\ - nhunk -= len;\ - }\ - hunk += n;\ - nhunk -= n; - struct Sym { Sym* link; @@ -85,7 +72,7 @@ struct Sym }; #define S ((Sym*)0) -struct +EXTERN struct { char* p; int c; @@ -101,72 +88,47 @@ struct Io }; #define I ((Io*)0) -struct -{ - Sym* sym; - short type; -} h[NSYM]; - -struct Gen -{ - Sym* sym; - vlong offset; - short type; - short reg; - short xreg; - short name; - ushort mask; - double dval; - char sval[8]; -}; - -struct Hist -{ - Hist* link; - char* name; - long line; - vlong offset; -}; -#define H ((Hist*)0) - enum { CLAST, CMACARG, CMACRO, - CPREPROC + CPREPROC, }; -EXTERN char debug[256]; +EXTERN int debug[256]; EXTERN Sym* hash[NHASH]; -EXTERN char* Dlist[30]; +EXTERN char** Dlist; EXTERN int nDlist; -EXTERN Hist* ehist; EXTERN int newflag; -EXTERN Hist* hist; EXTERN char* hunk; -EXTERN char* include[NINCLUDE]; +EXTERN char** include; EXTERN Io* iofree; EXTERN Io* ionext; EXTERN Io* iostack; -EXTERN long lineno; +EXTERN int32 lineno; EXTERN int nerrors; -EXTERN long nhunk; +EXTERN int32 nhunk; EXTERN int nosched; EXTERN int ninclude; -EXTERN Gen nullgen; +EXTERN int32 nsymb; +EXTERN Addr nullgen; EXTERN char* outfile; EXTERN int pass; -EXTERN char* pathname; -EXTERN long pc; +EXTERN int32 pc; EXTERN int peekc; EXTERN int sym; -EXTERN char symb[NSYMB]; +EXTERN char* symb; EXTERN int thechar; EXTERN char* thestring; -EXTERN long thunk; +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); @@ -174,7 +136,7 @@ void newfile(char*, int); Sym* slookup(char*); Sym* lookup(void); void syminit(Sym*); -long yylex(void); +int32 yylex(void); int getc(void); int getnsc(void); void unget(int); @@ -182,11 +144,8 @@ int escchar(int); void cinit(void); void pinit(char*); void cclean(void); -void outcode(int, Gen*, int, Gen*); -void outgcode(int, Gen*, int, Gen*, Gen*); -void zname(char*, int, int); -void zaddr(Gen*, int); -void ieeedtod(Ieee*, double); +void outcode(int, Addr*, int, Addr*); +void outgcode(int, Addr*, int, Addr*, Addr*); int filbuf(void); Sym* getsym(void); void domacro(void); @@ -199,31 +158,10 @@ void maclin(void); void macif(int); void macend(void); void dodefine(char*); -void prfile(long); -void outhist(void); +void prfile(int32); void linehist(char*, int); void gethunk(void); void yyerror(char*, ...); int yyparse(void); void setinclude(char*); int assemble(char*); - -/* - * system-dependent stuff from ../cc/compat.c - */ -enum /* keep in synch with ../cc/cc.h */ -{ - Plan9 = 1<<0, - Unix = 1<<1, - Windows = 1<<2 -}; -int mywait(int*); -int mycreat(char*, int); -int systemtype(int); -int pathchar(void); -char* mygetwd(char*, int); -int myexec(char*, char*[]); -int mydup(int, int); -int myfork(void); -int mypipe(int*); -void* mysbrk(ulong); diff --git a/src/cmd/9a/a.y b/src/cmd/9a/a.y index e77d78c6d..2e0317e06 100644 --- a/src/cmd/9a/a.y +++ b/src/cmd/9a/a.y @@ -28,7 +28,11 @@ // THE SOFTWARE. %{ +#include +#include /* if we don't, bison will, and a.h re-#defines getc */ +#include #include "a.h" +#include "../../pkg/runtime/funcdata.h" %} %union { @@ -36,7 +40,7 @@ vlong lval; double dval; char sval[8]; - Gen gen; + Addr addr; } %left '|' %left '^' @@ -50,14 +54,14 @@ %token LCONST LSP LSB LFP LPC LCREG LFLUSH %token LREG LFREG LR LCR LF LFPSCR %token LLR LCTR LSPR LSPREG LSEG LMSR -%token LSCHED LXLD LXST LXOP LXMV +%token LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV %token LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA %token LFCONST %token LSCONST %token LNAME LLAB LVAR %type con expr pointer offset sreg -%type addr rreg regaddr name creg freg xlreg lr ctr -%type imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask +%type addr rreg regaddr name creg freg xlreg lr ctr +%type imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask %% prog: | prog line @@ -400,7 +404,7 @@ inst: } | LBRA con ',' con ',' rel { - Gen g; + Addr g; g = nullgen; g.type = D_CONST; g.offset = $2; @@ -408,7 +412,7 @@ inst: } | LBRA con ',' con ',' addr { - Gen g; + Addr g; g = nullgen; g.type = D_CONST; g.offset = $2; @@ -416,7 +420,7 @@ inst: } | LBRA con ',' con ',' '(' xlreg ')' { - Gen g; + Addr g; g = nullgen; g.type = D_CONST; g.offset = $2; @@ -572,21 +576,41 @@ inst: { 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 { - if($1 == ADWORD && $2.type == D_CONST) - $2.type = D_DCONST; outcode($1, &$2, NREG, &nullgen); } | LWORD ximm comma { - if($1 == ADWORD && $2.type == D_CONST) - $2.type = D_DCONST; 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 */ @@ -603,15 +627,15 @@ inst: } | LTEXT name ',' con ',' imm { + $6.offset &= 0xffffffffull; + $6.offset |= (vlong)ArgsSizeUnknown << 32; outcode($1, &$2, $4, &$6); } -| LTEXT name ',' imm ':' imm +| LTEXT name ',' con ',' imm '-' con { - outgcode($1, &$2, NREG, &$6, &$4); - } -| LTEXT name ',' con ',' imm ':' imm - { - outgcode($1, &$2, $4, &$8, &$6); + $6.offset &= 0xffffffffull; + $6.offset |= ($8 & 0xffffffffull) << 32; + outcode($1, &$2, $4, &$6); } /* * DATA @@ -649,14 +673,12 @@ rel: if(pass == 2) yyerror("undefined label: %s", $1->name); $$.type = D_BRANCH; - $$.sym = $1; $$.offset = $2; } | LLAB offset { $$ = nullgen; $$.type = D_BRANCH; - $$.sym = $1; $$.offset = $1->value + $2; } @@ -774,7 +796,7 @@ mask: con ',' con { int mb, me; - ulong v; + uint32 v; $$ = nullgen; $$.type = D_CONST; @@ -785,9 +807,9 @@ mask: mb = me = 0; } if(mb <= me) - v = ((ulong)~0L>>mb) & (~0L<<(31-me)); + v = ((uint32)~0L>>mb) & (~0L<<(31-me)); else - v = ~(((ulong)~0L>>(me+1)) & (~0L<<(31-(mb-1)))); + v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1)))); $$.offset = v; } @@ -801,7 +823,7 @@ ximm: { $$ = nullgen; $$.type = D_SCONST; - memcpy($$.sval, $2, sizeof($$.sval)); + memcpy($$.u.sval, $2, sizeof($$.u.sval)); } fimm: @@ -809,13 +831,13 @@ fimm: { $$ = nullgen; $$.type = D_FCONST; - $$.dval = $2; + $$.u.dval = $2; } | '$' '-' LFCONST { $$ = nullgen; $$.type = D_FCONST; - $$.dval = -$3; + $$.u.dval = -$3; } imm: '$' con @@ -847,7 +869,7 @@ regaddr: $$ = nullgen; $$.type = D_OREG; $$.reg = $2; - $$.xreg = $4; + $$.scale = $4; $$.offset = 0; } @@ -867,7 +889,7 @@ name: $$ = nullgen; $$.type = D_OREG; $$.name = $3; - $$.sym = S; + $$.sym = nil; $$.offset = $1; } | LNAME offset '(' pointer ')' @@ -875,7 +897,7 @@ name: $$ = nullgen; $$.type = D_OREG; $$.name = $4; - $$.sym = $1; + $$.sym = linklookup(ctxt, $1->name, 0); $$.offset = $2; } | LNAME '<' '>' offset '(' LSB ')' @@ -883,7 +905,7 @@ name: $$ = nullgen; $$.type = D_OREG; $$.name = D_STATIC; - $$.sym = $1; + $$.sym = linklookup(ctxt, $1->name, 0); $$.offset = $4; } 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 index a7dbc45fa..a9ad01eac 100644 --- a/src/cmd/9a/lex.c +++ b/src/cmd/9a/lex.c @@ -27,29 +27,68 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore - #define EXTERN +#include +#include #include "a.h" #include "y.tab.h" -#include + +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 +Lconv(Fmt *fp) +{ + return linklinefmt(ctxt, fp); +} + +int +pathchar(void) +{ + return '/'; +} void main(int argc, char *argv[]) { char *p; - int nout, nproc, status, i, c; + int c; thechar = '9'; - thestring = "power64"; + thestring = getgoarch(); + if(strcmp(thestring, "power64le") == 0) + ctxt = linknew(&linkpower64le); + else + ctxt = linknew(&linkpower64); + ctxt->diag = yyerror; + ctxt->bso = &bstdout; + Binit(&bstdout, 1, OWRITE); + listinit9(); + fmtinstall('L', Lconv); + + ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); cinit(); outfile = 0; - include[ninclude++] = "."; + setinclude("."); ARGBEGIN { default: c = ARGC(); - if(c >= 0 || c < sizeof(debug)) + if(c >= 0 && c < sizeof(debug)) debug[c] = 1; break; @@ -59,62 +98,31 @@ main(int argc, char *argv[]) case 'D': p = ARGF(); - if(p) + if(p) { + if (nDlist%8 == 0) + Dlist = allocn(Dlist, nDlist*sizeof(char *), + 8*sizeof(char *)); Dlist[nDlist++] = p; + } break; case 'I': p = ARGF(); setinclude(p); break; + + case 'S': + ctxt->debugasm++; + break; } ARGEND if(*argv == 0) { print("usage: %ca [-options] file.s\n", thechar); errorexit(); } - if(argc > 1 && systemtype(Windows)){ - print("can't assemble multiple files on windows\n"); + if(argc > 1){ + print("can't assemble multiple files\n"); errorexit(); } - if(argc > 1) { - nproc = 1; - if(p = getenv("NPROC")) - nproc = atol(p); - c = 0; - nout = 0; - for(;;) { - while(nout < nproc && argc > 0) { - i = myfork(); - if(i < 0) { - i = mywait(&status); - if(i < 0) - errorexit(); - if(status) - c++; - nout--; - continue; - } - if(i == 0) { - print("%s:\n", *argv); - if(assemble(*argv)) - errorexit(); - exits(0); - } - nout++; - argc--; - argv++; - } - i = mywait(&status); - if(i < 0) { - if(c) - errorexit(); - exits(0); - } - if(status) - c++; - nout--; - } - } if(assemble(argv[0])) errorexit(); exits(0); @@ -152,33 +160,30 @@ assemble(char *file) } } - of = mycreat(outfile, 0664); + 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(), thestring, getgoversion()); + Bprint(&obuf, "\n!\n"); pass = 1; - nosched = 0; - pinit(file); - for(i=0; itype = itab[i].type; s->value = itab[i].value; } - ALLOCN(pathname, 0, 100); - if(mygetwd(pathname, 99) == 0) { - ALLOCN(pathname, 100, 900); - if(mygetwd(pathname, 999) == 0) - strcpy(pathname, "/???"); - } } void @@ -644,263 +643,82 @@ cclean(void) { outcode(AEND, &nullgen, NREG, &nullgen); - Bflush(&obuf); -} - -void -zname(char *n, int t, int s) -{ - - Bputc(&obuf, ANAME); - Bputc(&obuf, ANAME>>8); - Bputc(&obuf, t); /* type */ - Bputc(&obuf, s); /* sym */ - while(*n) { - Bputc(&obuf, *n); - n++; - } - Bputc(&obuf, 0); -} - -void -zaddr(Gen *a, int s) -{ - long l; - int i; - char *n; - Ieee e; - - if(a->type == D_CONST){ - l = a->offset; - if((vlong)l != a->offset) - a->type = D_DCONST; - } - Bputc(&obuf, a->type); - Bputc(&obuf, a->reg); - Bputc(&obuf, s); - Bputc(&obuf, a->name); - switch(a->type) { - default: - print("unknown type %d\n", a->type); - exits("arg"); - - case D_NONE: - case D_REG: - case D_FREG: - case D_CREG: - case D_FPSCR: - case D_MSR: - case D_OPT: - break; - - case D_DCR: - case D_SPR: - case D_OREG: - case D_CONST: - case D_BRANCH: - l = a->offset; - Bputc(&obuf, l); - Bputc(&obuf, l>>8); - Bputc(&obuf, l>>16); - Bputc(&obuf, l>>24); - break; - - case D_DCONST: - l = a->offset; - Bputc(&obuf, l); - Bputc(&obuf, l>>8); - Bputc(&obuf, l>>16); - Bputc(&obuf, l>>24); - l = a->offset>>32; - Bputc(&obuf, l); - Bputc(&obuf, l>>8); - Bputc(&obuf, l>>16); - Bputc(&obuf, l>>24); - break; - - case D_SCONST: - n = a->sval; - for(i=0; idval); - Bputc(&obuf, e.l); - Bputc(&obuf, e.l>>8); - Bputc(&obuf, e.l>>16); - Bputc(&obuf, e.l>>24); - Bputc(&obuf, e.h); - Bputc(&obuf, e.h>>8); - Bputc(&obuf, e.h>>16); - Bputc(&obuf, e.h>>24); - break; - } } -int -outsim(Gen *g) -{ - Sym *s; - int sno, t; - - s = g->sym; - if(s == S) - return 0; - sno = s->sym; - if(sno < 0 || sno >= NSYM) - sno = 0; - t = g->name; - if(h[sno].type == t && h[sno].sym == s) - return sno; - zname(s->name, t, sym); - s->sym = sym; - h[sym].sym = s; - h[sym].type = t; - sno = sym; - sym++; - if(sym >= NSYM) - sym = 1; - return sno; -} +static Prog *lastpc; void -outcode(int a, Gen *g1, int reg, Gen *g2) +outcode(int a, Addr *g1, int reg, Addr *g2) { - int sf, st; + Prog *p; + Plist *pl; - if(a != AGLOBL && a != ADATA) - pc++; if(pass == 1) - return; - if(g1->xreg != NREG) { - if(reg != NREG || g2->xreg != NREG) + goto out; + + if(g1->scale != NREG) { + if(reg != NREG || g2->scale != NREG) yyerror("bad addressing modes"); - reg = g1->xreg; + reg = g1->scale; } else - if(g2->xreg != NREG) { + if(g2->scale != NREG) { if(reg != NREG) yyerror("bad addressing modes"); - reg = g2->xreg; + reg = g2->scale; } - do { - sf = outsim(g1); - st = outsim(g2); - } while(sf != 0 && st == sf); - Bputc(&obuf, a); - Bputc(&obuf, a>>8); - Bputc(&obuf, reg|nosched); - Bputc(&obuf, lineno); - Bputc(&obuf, lineno>>8); - Bputc(&obuf, lineno>>16); - Bputc(&obuf, lineno>>24); - zaddr(g1, sf); - zaddr(g2, st); -} - -void -outgcode(int a, Gen *g1, int reg, Gen *g2, Gen *g3) -{ - int s1, s2, s3, flag; + 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++; - if(pass == 1) - return; - do { - s1 = outsim(g1); - s2 = outsim(g2); - s3 = outsim(g3); - } while(s1 && (s2 && s1 == s2 || s3 && s1 == s3) || s2 && (s3 && s2 == s3)); - flag = 0; - if(g2->type != D_NONE) - flag = 0x40; /* flags extra operand */ - Bputc(&obuf, a); - Bputc(&obuf, a>>8); - Bputc(&obuf, reg | nosched | flag); - Bputc(&obuf, lineno); - Bputc(&obuf, lineno>>8); - Bputc(&obuf, lineno>>16); - Bputc(&obuf, lineno>>24); - zaddr(g1, s1); - if(flag) - zaddr(g2, s2); - zaddr(g3, s3); } void -outhist(void) +outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3) { - Gen g; - Hist *h; - char *p, *q, *op, c; - int n; - - g = nullgen; - c = pathchar(); - for(h = hist; h != H; h = h->link) { - p = h->name; - op = 0; - /* on windows skip drive specifier in pathname */ - if(systemtype(Windows) && p && p[1] == ':'){ - p += 2; - c = *p; - } - if(p && p[0] != c && h->offset == 0 && pathname){ - /* on windows skip drive specifier in pathname */ - if(systemtype(Windows) && pathname[1] == ':') { - op = p; - p = pathname+2; - c = *p; - } else if(pathname[0] == c){ - op = p; - p = pathname; - } - } - while(p) { - q = strchr(p, c); - if(q) { - n = q-p; - if(n == 0){ - n = 1; /* leading "/" */ - *p = '/'; /* don't emit "\" on windows */ - } - q++; - } else { - n = strlen(p); - q = 0; - } - if(n) { - Bputc(&obuf, ANAME); - Bputc(&obuf, ANAME>>8); - Bputc(&obuf, D_FILE); /* type */ - Bputc(&obuf, 1); /* sym */ - Bputc(&obuf, '<'); - Bwrite(&obuf, p, n); - Bputc(&obuf, 0); - } - p = q; - if(p == 0 && op) { - p = op; - op = 0; - } - } - g.offset = h->offset; - - Bputc(&obuf, AHISTORY); - Bputc(&obuf, AHISTORY>>8); - Bputc(&obuf, 0); - Bputc(&obuf, h->line); - Bputc(&obuf, h->line>>8); - Bputc(&obuf, h->line>>16); - Bputc(&obuf, h->line>>24); - zaddr(&nullgen, 0); - zaddr(&g, 0); - } + 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" -#include "../cc/compat" diff --git a/src/cmd/9a/y.tab.c b/src/cmd/9a/y.tab.c new file mode 100644 index 000000000..9a09cf932 --- /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 . */ + +/* 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 +#include /* if we don't, bison will, and a.h re-#defines getc */ +#include +#include "a.h" +#include "../../pkg/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 /* 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 /* 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 /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* 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 /* 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 /* 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 /* 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 + + 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 . */ + +/* 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; + + -- cgit v1.2.1 From d5f5813e711b9578d598b468f81898f4915fca81 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:56:59 -0400 Subject: [dev.power64] cmd/9l: update header files for liblink LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/128720044 --- src/cmd/9c/gc.h | 1 - src/cmd/9l/9.out.h | 96 ++++++++++++--- src/cmd/9l/l.h | 351 ++++++----------------------------------------------- 3 files changed, 113 insertions(+), 335 deletions(-) (limited to 'src') diff --git a/src/cmd/9c/gc.h b/src/cmd/9c/gc.h index 1c7d7837a..82204902b 100644 --- a/src/cmd/9c/gc.h +++ b/src/cmd/9c/gc.h @@ -281,7 +281,6 @@ void nullwarn(Node*, Node*); void sextern(Sym*, Node*, int32, int32); void gextern(Sym*, Node*, int32, int32); void outcode(void); -void ieeedtod(Ieee*, double); /* * list diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h index 8ad2f7d06..6e4f9ee1b 100644 --- a/src/cmd/9l/9.out.h +++ b/src/cmd/9l/9.out.h @@ -34,8 +34,7 @@ #define NSYM 50 #define NREG 32 -#define NOPROF (1<<0) -#define DUPOK (1<<1) +#include "../ld/textflag.h" enum { @@ -43,14 +42,16 @@ enum REGSP = 1, REGSB = 2, REGRET = 3, - REGARG = 3, + REGARG = -1, /* -1 disables passing the first argument in register */ REGMIN = 7, /* register variables allocated from here to REGMAX */ + REGENV = 11, /* environment variable for closures */ REGMAX = 27, REGEXT = 30, /* external registers allocated from here down */ 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 */ @@ -69,9 +70,66 @@ enum */ }; +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 = 0, + AXXX, AADD, AADDCC, AADDV, @@ -390,6 +448,17 @@ enum as /* more 64-bit operations */ AHRFID, + AUNDEF, + AUSEFIELD, + ATYPE, + AFUNCDATA, + APCDATA, + ACHECKNIL, + AVARDEF, + AVARKILL, + ADUFFCOPY, + ADUFFZERO, + ALAST }; @@ -422,6 +491,11 @@ enum 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, @@ -433,16 +507,4 @@ enum /* * this is the ranlib header */ -#define SYMDEF "__.SYMDEF" - -/* - * this is the simulated IEEE floating point - */ -typedef struct ieee Ieee; -struct ieee -{ - long l; /* contains ls-man 0xffffffff */ - long h; /* contains sign 0x80000000 - exp 0x7ff00000 - ms-man 0x000fffff */ -}; +#define SYMDEF "__.GOSYMDEF" diff --git a/src/cmd/9l/l.h b/src/cmd/9l/l.h index 0f2fd60a8..d787f1384 100644 --- a/src/cmd/9l/l.h +++ b/src/cmd/9l/l.h @@ -30,102 +30,29 @@ #include #include #include -#include "../9c/9.out.h" -#include "../8l/elf.h" +#include +#include "9.out.h" #ifndef EXTERN #define EXTERN extern #endif -#define LIBNAMELEN 300 - -typedef struct Adr Adr; -typedef struct Sym Sym; -typedef struct Autom Auto; -typedef struct Prog Prog; -typedef struct Optab Optab; - -#define P ((Prog*)0) -#define S ((Sym*)0) -#define TNAME (curtext&&curtext->from.sym?curtext->from.sym->name:noname) - -struct Adr +enum { - union - { - vlong u0offset; - char u0sval[NSNAME]; - Ieee u0ieee; - }u0; - Sym *sym; - Auto *autom; - char type; - uchar reg; - char name; - char class; + thechar = '9', + PtrSize = 8, + IntSize = 8, + RegSize = 8, + MaxAlign = 32, // max data alignment + FuncAlign = 8 }; -#define offset u0.u0offset -#define sval u0.u0sval -#define ieee u0.u0ieee - -struct Prog -{ - Adr from; - Adr from3; /* fma and rlwm */ - Adr to; - Prog *forwd; - Prog *cond; - Prog *link; - vlong pc; - long regused; - short line; - short mark; - short optab; /* could be uchar */ - short as; - char reg; -}; -struct Sym -{ - char *name; - short type; - short version; - short become; - short frame; - uchar subtype; - ushort file; - vlong value; - long sig; - Sym *link; -}; -struct Autom -{ - Sym *sym; - Auto *link; - vlong aoffset; - short type; -}; -struct Optab -{ - short as; - char a1; - char a2; - char a3; - char a4; - char type; - char size; - char param; -}; -struct -{ - Optab* start; - Optab* stop; -} oprange[ALAST]; +#define P ((Prog*)0) +#define S ((LSym*)0) enum { FPCHIP = 1, - BIG = 32768-8, STRINGSZ = 200, MAXIO = 8192, MAXHIST = 20, /* limit of path elements for history symbols */ @@ -135,250 +62,40 @@ enum MINSIZ = 64, NENT = 100, NSCHED = 20, - -/* 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, - - STEXT = 1, - SDATA, - SBSS, - SDATA1, - SXREF, - SLEAF, - SFILE, - SCONST, - SUNDEF, - - SIMPORT, - SEXPORT, - - C_NONE = 0, - 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, + MINLC = 4, Roffset = 22, /* no. bits for offset in relocation address */ Rindex = 10 /* no. bits for index in relocation address */ }; -EXTERN union -{ - struct - { - uchar obuf[MAXIO]; /* output buffer */ - uchar ibuf[MAXIO]; /* input buffer */ - } u; - char dbuf[1]; -} buf; - -#define cbuf u.obuf -#define xbuf u.ibuf - -EXTERN long HEADR; /* length of header */ -EXTERN int HEADTYPE; /* type of header */ -EXTERN vlong INITDAT; /* data location */ -EXTERN long INITRND; /* data round above text location */ -EXTERN vlong INITTEXT; /* text location */ -EXTERN long INITTEXTP; /* text location (physical) */ -EXTERN char* INITENTRY; /* entry point */ -EXTERN long autosize; -EXTERN Biobuf bso; -EXTERN long bsssize; -EXTERN int cbc; -EXTERN uchar* cbp; -EXTERN int cout; -EXTERN Auto* curauto; -EXTERN Auto* curhist; -EXTERN Prog* curp; -EXTERN Prog* curtext; -EXTERN Prog* datap; -EXTERN Prog* prog_movsw; -EXTERN Prog* prog_movdw; -EXTERN Prog* prog_movws; -EXTERN Prog* prog_movwd; -EXTERN vlong datsize; -EXTERN char debug[128]; -EXTERN Prog* firstp; -EXTERN uchar fnuxi8[8]; -EXTERN uchar fnuxi4[4]; -EXTERN Sym* hash[NHASH]; -EXTERN Sym* histfrog[MAXHIST]; -EXTERN int histfrogp; -EXTERN int histgen; -EXTERN char* library[50]; -EXTERN char* libraryobj[50]; -EXTERN int libraryp; -EXTERN int xrefresolv; -EXTERN char* hunk; -EXTERN uchar inuxi1[1]; -EXTERN uchar inuxi2[2]; -EXTERN uchar inuxi4[4]; -EXTERN uchar inuxi8[8]; -EXTERN Prog* lastp; -EXTERN long lcsize; +EXTERN int32 autosize; +EXTERN LSym* datap; +EXTERN int debug[128]; +EXTERN int32 lcsize; EXTERN char literal[32]; EXTERN int nerrors; -EXTERN long nhunk; -EXTERN char* noname; EXTERN vlong instoffset; -EXTERN char* outfile; +EXTERN char* rpath; EXTERN vlong pc; -EXTERN int r0iszero; -EXTERN long symsize; -EXTERN long staticgen; -EXTERN Prog* textp; +EXTERN int32 symsize; +EXTERN int32 staticgen; +EXTERN Prog* lastp; EXTERN vlong textsize; -EXTERN long tothunk; -EXTERN char xcmp[C_NCLASS][C_NCLASS]; -EXTERN int version; -EXTERN Prog zprg; -EXTERN int dtype; - -EXTERN int doexp, dlm; -EXTERN int imports, nimports; -EXTERN int exports, nexports, allexport; -EXTERN char* EXPTAB; -EXTERN Prog undefp; - -#define UP (&undefp) - -extern Optab optab[]; -extern char* anames[]; -extern char* cnames[]; -int Aconv(Fmt*); -int Dconv(Fmt*); -int Nconv(Fmt*); -int Pconv(Fmt*); -int Sconv(Fmt*); -int Rconv(Fmt*); -int aclass(Adr*); -void addhist(long, int); -void histtoauto(void); -void addlibpath(char*); -void addnop(Prog*); -void append(Prog*, Prog*); void asmb(void); -void asmdyn(void); -void asmlc(void); -int asmout(Prog*, Optab*, int); -void asmsym(void); -vlong atolwhex(char*); -Prog* brloop(Prog*); -void buildop(void); -void cflush(void); -void ckoff(Sym*, vlong); -int cmp(int, int); -void cput(long); -int compound(Prog*); -double cputime(void); -void datblk(long, long); -void diag(char*, ...); -void dodata(void); -void doprof1(void); -void doprof2(void); -void dynreloc(Sym*, long, int, int, int); -vlong entryvalue(void); -void errorexit(void); -void exchange(Prog*); -void export(void); -int fileexists(char*); -int find1(long, int); -char* findlib(char*); -void follow(void); -void gethunk(void); -double ieeedtod(Ieee*); -long ieeedtof(Ieee*); -void import(void); -int isint32(vlong); -int isuint32(uvlong); -int isnop(Prog*); -void ldobj(int, long, char*); -void loadlib(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); -void initmuldiv(void); -Sym* lookup(char*, int); -void llput(vlong); -void llputl(vlong); -void lput(long); -void lputl(long); -void mkfwd(void); -void* mysbrk(ulong); -void names(void); -void nocache(Prog*); -void noops(void); -void nopout(Prog*); -void nuxiinit(void); -void objfile(char*); -int ocmp(void*, void*); -long opcode(int); -Optab* oplook(Prog*); -void patch(void); -void prasm(Prog*); -void prepend(Prog*, Prog*); -Prog* prg(void); -int pseudo(Prog*); -void putsymb(char*, int, vlong, int); -void readundefs(char*, int); -long regoff(Adr*); -int relinv(int); -vlong rnd(vlong, long); -void sched(Prog*, Prog*); -void span(void); -void strnput(char*, int); -void undef(void); -void undefsym(Sym*); -vlong vregoff(Adr*); -void wput(long); -void wputl(long); -void xdefine(char*, int, vlong); -void xfol(Prog*); -void zerosig(char*); +vlong rnd(vlong, int32); -#pragma varargck type "D" Adr* -#pragma varargck type "N" Adr* -#pragma varargck type "P" Prog* -#pragma varargck type "R" int -#pragma varargck type "A" int -#pragma varargck type "S" char* -#pragma varargck argpos diag 1 +#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 +}; -- cgit v1.2.1 From 27d0dd420436a9a2dd9ed8170a5ac5bb4958bee9 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 15:13:25 -0400 Subject: [dev.power64] include/link.h, liblink: convert 9l functions to liblink This replaces CL 122990043. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123010043 --- src/liblink/asm9.c | 934 ++++++++++++++++++------------------ src/liblink/list9.c | 250 ++++++---- src/liblink/obj9.c | 1299 ++++++++++++++++----------------------------------- 3 files changed, 1034 insertions(+), 1449 deletions(-) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 27ccb0a23..647e6f178 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -27,12 +27,38 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore +// Instruction layout. -#include "l.h" +#include +#include +#include +#include +#include "../cmd/9l/9.out.h" +#include "../pkg/runtime/stack.h" -Optab optab[] = +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 }, @@ -268,6 +294,8 @@ Optab optab[] = { 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 }, @@ -308,6 +336,7 @@ Optab optab[] = { 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 }, @@ -399,58 +428,86 @@ Optab optab[] = { 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 }, + + { 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 }, }; -#include "l.h" +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 char xcmp[C_NCLASS][C_NCLASS]; + void -span(void) +span9(Link *ctxt, LSym *cursym) { - Prog *p, *q; - Sym *setext; + Prog *p; Optab *o; int m, bflag; - vlong c, otxt; + vlong c; + 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; + + if(oprange[AANDN].start == nil) + buildop(ctxt); - if(debug['v']) - Bprint(&bso, "%5.2f span\n", cputime()); - Bflush(&bso); + ctxt->cursym = cursym; bflag = 0; - c = INITTEXT; - otxt = c; - for(p = firstp; p != P; p = p->link) { + c = 0; + p->pc = c; + + for(p = p->link; p != nil; p = p->link) { + ctxt->curp = p; p->pc = c; - o = oplook(p); + o = oplook(ctxt, p); m = o->size; if(m == 0) { - if(p->as == ATEXT) { - curtext = p; - autosize = p->to.offset + 8; - if(p->from3.type == D_CONST) { - if(p->from3.offset & 3) - diag("illegal origin\n%P", p); - if(c > p->from3.offset) - diag("passed origin (#%llux)\n%P", c, p); - else - c = p->from3.offset; - p->pc = c; - } - if(p->from.sym != S) - p->from.sym->value = c; - /* need passes to resolve branches? */ - if(c-otxt >= (1L<<15)) - bflag = c; - otxt = c; - continue; - } - if(p->as != ANOP) - diag("zero-width instruction\n%P", p); + 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 @@ -459,100 +516,93 @@ span(void) * around jmps to fix. this is rare. */ while(bflag) { - if(debug['v']) - Bprint(&bso, "%5.2f span1\n", cputime()); + if(ctxt->debugvlog) + Bprint(ctxt->bso, "%5.2f span1\n", cputime()); bflag = 0; - c = INITTEXT; - for(p = firstp; p != P; p = p->link) { + c = 0; + for(p = cursym->text; p != nil; p = p->link) { p->pc = c; - o = oplook(p); - if((o->type == 16 || o->type == 17) && p->cond) { - otxt = p->cond->pc - c; + o = oplook(ctxt, p); + +/* very large branches + if((o->type == 16 || o->type == 17) && p->pcond) { + otxt = p->pcond->pc - c; if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { q = prg(); q->link = p->link; p->link = q; q->as = ABR; q->to.type = D_BRANCH; - q->cond = p->cond; - p->cond = q; + q->pcond = p->pcond; + p->pcond = q; q = prg(); q->link = p->link; p->link = q; q->as = ABR; q->to.type = D_BRANCH; - q->cond = q->link->link; + q->pcond = q->link->link; addnop(p->link); addnop(p); bflag = 1; } } +*/ m = o->size; if(m == 0) { - if(p->as == ATEXT) { - curtext = p; - autosize = p->to.offset + 8; - if(p->from.sym != S) - p->from.sym->value = c; - continue; - } - if(p->as != ANOP) - diag("zero-width instruction\n%P", p); + 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 = rnd(c, 8); - - setext = lookup("etext", 0); - if(setext != S) { - setext->value = c; - textsize = c - INITTEXT; - } - if(INITRND) - INITDAT = rnd(c, INITRND); - if(debug['v']) - Bprint(&bso, "tsize = %llux\n", textsize); - Bflush(&bso); -} - -void -xdefine(char *p, int t, vlong v) -{ - Sym *s; + c += -c&(FuncAlign-1); + cursym->size = c; - s = lookup(p, 0); - if(s->type == 0 || s->type == SXREF) { - s->type = t; - s->value = v; + /* + * lay out the code, emitting code and data relocations. + */ + if(ctxt->tlsg == nil) + ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0); + + p = cursym->text; + ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8; + symgrow(ctxt, cursym, cursym->size); + + bp = cursym->p; + for(p = p->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; isize/4; i++) { + cast = (uchar*)&out[i]; + for(j=0; j<4; j++) + *bp++ = cast[inuxi4[j]]; + } } } -int +static int isint32(vlong v) { - long l; - - l = v; - return (vlong)l == v; + return (int32)v == v; } -int +static int isuint32(uvlong v) { - ulong l; - - l = v; - return (uvlong)l == v; + return (uint32)v == v; } -int -aclass(Adr *a) +static int +aclass(Link *ctxt, Addr *a) { - Sym *s; - int t; + LSym *s; switch(a->type) { case D_NONE: @@ -589,134 +639,86 @@ aclass(Adr *a) switch(a->name) { case D_EXTERN: case D_STATIC: - if(a->sym == S) + if(a->sym == nil) break; - t = a->sym->type; - if(t == 0 || t == SXREF) { - diag("undefined external: %s in %s", - a->sym->name, TNAME); - a->sym->type = SDATA; - } - if(dlm){ - instoffset = a->sym->value + a->offset; - switch(a->sym->type){ - case STEXT: - case SLEAF: - case SCONST: - case SUNDEF: - break; - default: - instoffset += INITDAT; - } + ctxt->instoffset = a->offset; + if(a->sym != nil) // use relocation return C_ADDR; - } - instoffset = a->sym->value + a->offset - BIG; - if(instoffset >= -BIG && instoffset < BIG) - return C_SEXT; return C_LEXT; case D_AUTO: - instoffset = autosize + a->offset; - if(instoffset >= -BIG && instoffset < BIG) + ctxt->instoffset = ctxt->autosize + a->offset; + if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) return C_SAUTO; return C_LAUTO; case D_PARAM: - instoffset = autosize + a->offset + 8L; - if(instoffset >= -BIG && instoffset < BIG) + ctxt->instoffset = ctxt->autosize + a->offset + 8L; + if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) return C_SAUTO; return C_LAUTO; case D_NONE: - instoffset = a->offset; - if(instoffset == 0) + ctxt->instoffset = a->offset; + if(ctxt->instoffset == 0) return C_ZOREG; - if(instoffset >= -BIG && instoffset < BIG) + if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) return C_SOREG; return C_LOREG; } return C_GOK; case D_OPT: - instoffset = a->offset & 31L; + 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: - instoffset = a->offset; + ctxt->instoffset = a->offset; consize: - if(instoffset >= 0) { - if(instoffset == 0) + if(ctxt->instoffset >= 0) { + if(ctxt->instoffset == 0) return C_ZCON; - if(instoffset <= 0x7fff) + if(ctxt->instoffset <= 0x7fff) return C_SCON; - if(instoffset <= 0xffff) + if(ctxt->instoffset <= 0xffff) return C_ANDCON; - if((instoffset & 0xffff) == 0 && isuint32(instoffset)) /* && (instoffset & (1<<31)) == 0) */ + if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset)) /* && (instoffset & (1<<31)) == 0) */ return C_UCON; - if(isint32(instoffset) || isuint32(instoffset)) + if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset)) return C_LCON; return C_DCON; } - if(instoffset >= -0x8000) + if(ctxt->instoffset >= -0x8000) return C_ADDCON; - if((instoffset & 0xffff) == 0 && isint32(instoffset)) + if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset)) return C_UCON; - if(isint32(instoffset)) + if(isint32(ctxt->instoffset)) return C_LCON; return C_DCON; case D_EXTERN: case D_STATIC: s = a->sym; - if(s == S) + if(s == nil) break; - t = s->type; - if(t == 0 || t == SXREF) { - diag("undefined external: %s in %s", - s->name, TNAME); - s->type = SDATA; - } - if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) { - instoffset = s->value + a->offset; - return C_LCON; - } if(s->type == SCONST) { - instoffset = s->value + a->offset; - if(dlm) - return C_LCON; + ctxt->instoffset = s->value + a->offset; goto consize; } - if(!dlm){ - instoffset = s->value + a->offset - BIG; - if(instoffset >= -BIG && instoffset < BIG && instoffset != 0) - return C_SECON; - } - instoffset = s->value + a->offset + INITDAT; - if(dlm) - return C_LCON; + ctxt->instoffset = s->value + a->offset; /* not sure why this barfs */ return C_LCON; - /* - if(instoffset == 0) - return C_ZCON; - if(instoffset >= -0x8000 && instoffset <= 0xffff) - return C_SCON; - if((instoffset & 0xffff) == 0) - return C_UCON; - return C_LCON; - */ case D_AUTO: - instoffset = autosize + a->offset; - if(instoffset >= -BIG && instoffset < BIG) + ctxt->instoffset = ctxt->autosize + a->offset; + if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) return C_SACON; return C_LACON; case D_PARAM: - instoffset = autosize + a->offset + 8L; - if(instoffset >= -BIG && instoffset < BIG) + ctxt->instoffset = ctxt->autosize + a->offset + 8L; + if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) return C_SACON; return C_LACON; } @@ -728,8 +730,14 @@ aclass(Adr *a) return C_GOK; } -Optab* -oplook(Prog *p) +static void +prasm(Prog *p) +{ + print("%P\n", p); +} + +static Optab* +oplook(Link *ctxt, Prog *p) { int a1, a2, a3, a4, r; char *c1, *c3, *c4; @@ -740,19 +748,19 @@ oplook(Prog *p) return optab+(a1-1); a1 = p->from.class; if(a1 == 0) { - a1 = aclass(&p->from) + 1; + a1 = aclass(ctxt, &p->from) + 1; p->from.class = a1; } a1--; a3 = p->from3.class; if(a3 == 0) { - a3 = aclass(&p->from3) + 1; + a3 = aclass(ctxt, &p->from3) + 1; p->from3.class = a3; } a3--; a4 = p->to.class; if(a4 == 0) { - a4 = aclass(&p->to) + 1; + a4 = aclass(ctxt, &p->to) + 1; p->to.class = a4; } a4--; @@ -775,16 +783,15 @@ oplook(Prog *p) p->optab = (o-optab)+1; return o; } - diag("illegal combination %A %R %R %R %R", + ctxt->diag("illegal combination %A %^ %^ %^ %^", p->as, a1, a2, a3, a4); - if(1||!debug['a']) - prasm(p); + prasm(p); if(o == 0) - errorexit(); + o = optab; return o; } -int +static int cmp(int a, int b) { @@ -850,10 +857,10 @@ cmp(int a, int b) return 0; } -int -ocmp(void *a1, void *a2) +static int +ocmp(const void *a1, const void *a2) { - Optab *p1, *p2; + const Optab *p1, *p2; int n; p1 = a1; @@ -876,8 +883,8 @@ ocmp(void *a1, void *a2) return 0; } -void -buildop(void) +static void +buildop(Link *ctxt) { int i, n, r; @@ -898,8 +905,8 @@ buildop(void) switch(r) { default: - diag("unknown op in build: %A", r); - errorexit(); + 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]; @@ -910,6 +917,7 @@ buildop(void) 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]; @@ -1188,6 +1196,7 @@ buildop(void) break; case AECIWX: oprange[ALWAR] = oprange[r]; + oprange[ALDAR] = oprange[r]; break; case ASYSCALL: /* just the op; flow of control */ oprange[ARFI] = oprange[r]; @@ -1234,13 +1243,17 @@ buildop(void) case ADWORD: case ANOP: case ATEXT: + case AUNDEF: + case AUSEFIELD: + case AFUNCDATA: + case APCDATA: + case ADUFFZERO: + case ADUFFCOPY: break; } } } -#include "l.h" - #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) @@ -1293,18 +1306,30 @@ buildop(void) #define oclass(v) ((v).class-1) -long oprrr(int), opirr(int), opload(int), opstore(int), oploadx(int), opstorex(int); +// 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 */ -int -getmask(uchar *m, ulong v) +static int +getmask(uchar *m, uint32 v) { int i; m[0] = m[1] = 0; - if(v != ~0L && v & (1<<31) && v & 1){ /* MB > ME */ + 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; @@ -1325,17 +1350,17 @@ getmask(uchar *m, ulong v) return 0; } -void -maskgen(Prog *p, uchar *m, ulong v) +static void +maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v) { if(!getmask(m, v)) - diag("cannot generate mask #%lux\n%P", v, p); + ctxt->diag("cannot generate mask #%lux\n%P", v, p); } /* * 64-bit masks (rldic etc) */ -int +static int getmask64(uchar *m, uvlong v) { int i; @@ -1355,78 +1380,54 @@ getmask64(uchar *m, uvlong v) return 0; } -void -maskgen64(Prog *p, uchar *m, uvlong v) -{ - if(!getmask64(m, v)) - diag("cannot generate mask #%llux\n%P", v, p); -} - static void -reloc(Adr *a, long pc, int sext) +maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v) { - if(a->name == D_EXTERN || a->name == D_STATIC) - dynreloc(a->sym, pc, 1, 1, sext); + if(!getmask64(m, v)) + ctxt->diag("cannot generate mask #%llux\n%P", v, p); } -static ulong +static uint32 loadu32(int r, vlong d) { - long v; + int32 v; v = d>>16; if(isuint32(d)) return LOP_IRR(OP_ORIS, r, REGZERO, v); return AOP_IRR(OP_ADDIS, r, REGZERO, v); } - -int -asmout(Prog *p, Optab *o, int aflag) + +static void +asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) { - long o1, o2, o3, o4, o5, v, t; + int32 o1, o2, o3, o4, o5, v, t; vlong d; - Prog *ct; int r, a; uchar mask[2]; + Reloc *rel; o1 = 0; o2 = 0; o3 = 0; o4 = 0; o5 = 0; + switch(o->type) { default: - if(aflag) - return 0; - diag("unknown type %d", o->type); - if(!debug['a']) - prasm(p); + ctxt->diag("unknown type %d", o->type); + prasm(p); break; case 0: /* pseudo ops */ - if(aflag) { - if(p->link) { - if(p->as == ATEXT) { - ct = curtext; - o2 = autosize; - curtext = p; - autosize = p->to.offset + 8; - o1 = asmout(p->link, oplook(p->link), aflag); - curtext = ct; - autosize = o2; - } else - o1 = asmout(p->link, oplook(p->link), aflag); - } - return o1; - } break; case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */ if(p->to.reg == REGZERO && p->from.type == D_CONST) { - v = regoff(&p->from); + v = regoff(ctxt, &p->from); if(r0iszero && v != 0) { - nerrors--; - diag("literal operation on R0\n%P", p); + //nerrors--; + ctxt->diag("literal operation on R0\n%P", p); } o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v); break; @@ -1438,17 +1439,17 @@ asmout(Prog *p, Optab *o, int aflag) r = p->reg; if(r == NREG) r = p->to.reg; - o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, p->from.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(&p->from); + 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)) - diag("literal operation on R0\n%P", p); + ctxt->diag("literal operation on R0\n%P", p); a = OP_ADDI; if(o->a1 == C_UCON) { v >>= 16; @@ -1462,65 +1463,63 @@ asmout(Prog *p, Optab *o, int aflag) break; case 4: /* add/mul $scon,[r1],r2 */ - v = regoff(&p->from); + v = regoff(ctxt, &p->from); r = p->reg; if(r == NREG) r = p->to.reg; if(r0iszero && p->to.reg == 0) - diag("literal operation on R0\n%P", p); - o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v); + ctxt->diag("literal operation on R0\n%P", p); + o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); break; case 5: /* syscall */ - if(aflag) - return 0; - o1 = oprrr(p->as); + 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(p->as), p->to.reg, r, p->from.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(&p->to); + v = regoff(ctxt, &p->to); if(p->to.type == D_OREG && p->reg != NREG) { if(v) - diag("illegal indexed instruction\n%P", p); - o1 = AOP_RRR(opstorex(p->as), p->from.reg, p->reg, r); + ctxt->diag("illegal indexed instruction\n%P", p); + o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r); } else - o1 = AOP_IRR(opstore(p->as), p->from.reg, r, v); + 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(&p->from); + v = regoff(ctxt, &p->from); if(p->from.type == D_OREG && p->reg != NREG) { if(v) - diag("illegal indexed instruction\n%P", p); - o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r); + 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(p->as), p->to.reg, r, v); + 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(&p->from); + v = regoff(ctxt, &p->from); if(p->from.type == D_OREG && p->reg != NREG) { if(v) - diag("illegal indexed instruction\n%P", p); - o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r); + 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(p->as), p->to.reg, r, v); + 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; @@ -1528,36 +1527,37 @@ asmout(Prog *p, Optab *o, int aflag) r = p->reg; if(r == NREG) r = p->to.reg; - o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, r); + o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r); break; case 11: /* br/bl lbra */ - if(aflag) - return 0; v = 0; - if(p->cond == UP){ - if(p->to.sym->type != SUNDEF) - diag("bad branch sym type"); - v = (ulong)p->to.sym->value >> (Roffset-2); - dynreloc(p->to.sym, p->pc, 0, 0, 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); } - else if(p->cond) - v = p->cond->pc - p->pc; - if(v & 03) { - diag("odd branch target address\n%P", p); - v &= ~03; + 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; + rel->add = o1 | ((v & 0x03FFFFFC) >> 2); + rel->type = R_CALLPOWER; } - if(v < -(1L<<25) || v >= (1L<<24)) - diag("branch too far\n%P", p); - o1 = OP_BR(opirr(p->as), v, 0); break; case 12: /* movb r,r (extsb); movw r,r (extsw) */ if(p->to.reg == REGZERO && p->from.type == D_CONST) { - v = regoff(&p->from); + v = regoff(ctxt, &p->from); if(r0iszero && v != 0) { - nerrors--; - diag("literal operation on R0\n%P", p); + ctxt->diag("literal operation on R0\n%P", p); } o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v); break; @@ -1578,31 +1578,31 @@ asmout(Prog *p, Optab *o, int aflag) else if(p->as == AMOVWZ) o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5); /* MB=32 */ else - diag("internal: bad mov[bhw]z\n%P", p); + 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(&p->from3); - maskgen64(p, mask, d); + 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) - diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p); + 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) - diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p); + ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p); break; default: - diag("unexpected op in rldc case\n%P", p); + ctxt->diag("unexpected op in rldc case\n%P", p); a = 0; } - o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg); + 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 */ @@ -1610,31 +1610,27 @@ asmout(Prog *p, Optab *o, int aflag) case 17: /* bc bo,bi,lbra (same for now) */ case 16: /* bc bo,bi,sbra */ - if(aflag) - return 0; a = 0; if(p->from.type == D_CONST) - a = regoff(&p->from); + a = regoff(ctxt, &p->from); r = p->reg; if(r == NREG) r = 0; v = 0; - if(p->cond) - v = p->cond->pc - p->pc; + if(p->pcond) + v = p->pcond->pc - p->pc; if(v & 03) { - diag("odd branch target address\n%P", p); + ctxt->diag("odd branch target address\n%P", p); v &= ~03; } if(v < -(1L<<16) || v >= (1L<<15)) - diag("branch too far\n%P", p); - o1 = OP_BC(opirr(p->as), a, r, v, 0); + 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(aflag) - return 0; if(p->as == ABC || p->as == ABCL) - v = regoff(&p->to)&31L; + v = regoff(ctxt, &p->to)&31L; else v = 20; /* unconditional */ r = p->reg; @@ -1648,10 +1644,8 @@ asmout(Prog *p, Optab *o, int aflag) break; case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */ - if(aflag) - return 0; if(p->as == ABC || p->as == ABCL) - v = regoff(&p->from)&31L; + v = regoff(ctxt, &p->from)&31L; else v = 20; /* unconditional */ r = p->reg; @@ -1665,7 +1659,7 @@ asmout(Prog *p, Optab *o, int aflag) o1 = OPVCC(19, 16, 0, 0); break; default: - diag("bad optab entry (18): %d\n%P", p->to.class, p); + ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p); v = 0; } if(p->as == ABL || p->as == ABCL) @@ -1674,54 +1668,61 @@ asmout(Prog *p, Optab *o, int aflag) break; case 19: /* mov $lcon,r ==> cau+or */ - d = vregoff(&p->from); - o1 = loadu32(p->to.reg, d); - o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (long)d); - if(dlm) - reloc(&p->from, p->pc, 0); + 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, (d>>16)+(d&0x8000)?1:0); + 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(&p->from); + 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)) - diag("literal operation on R0\n%P", p); - o1 = AOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16); + 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) - diag("cant synthesize large constant\n%P", p); - d = vregoff(&p->from); + 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, (long)d); + o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d); r = p->reg; if(r == NREG) r = p->to.reg; - o3 = AOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r); - if(dlm) - reloc(&p->from, p->pc, 0); + 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) - diag("cant synthesize large constant\n%P", p); - d = vregoff(&p->from); + 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, (long)d); + o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d); r = p->reg; if(r == NREG) r = p->to.reg; - o3 = LOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r); - if(dlm) - reloc(&p->from, p->pc, 0); + 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(&p->from); + v = regoff(ctxt, &p->from); if(v < 0) v = 0; else if(v > 63) @@ -1740,7 +1741,7 @@ asmout(Prog *p, Optab *o, int aflag) o1 = OP_RLDICL; break; default: - diag("unexpected op in sldi case\n%P", p); + ctxt->diag("unexpected op in sldi case\n%P", p); a = 0; o1 = 0; } @@ -1756,8 +1757,8 @@ asmout(Prog *p, Optab *o, int aflag) case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */ if(p->to.reg == REGTMP) - diag("can't synthesize large constant\n%P", p); - v = regoff(&p->from); + ctxt->diag("can't synthesize large constant\n%P", p); + v = regoff(ctxt, &p->from); if(v & 0x8000L) v += 0x10000L; r = p->from.reg; @@ -1768,47 +1769,48 @@ asmout(Prog *p, Optab *o, int aflag) break; case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */ - v = regoff(&p->from3); + v = regoff(ctxt, &p->from3); r = p->from.reg; - o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v); + 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) - diag("can't synthesize large constant\n%P", p); - v = regoff(&p->from3); + 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(p->as), p->to.reg, p->from.reg, REGTMP); - if(dlm) - reloc(&p->from3, p->pc, 0); + 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(&p->from); - d = vregoff(&p->from3); - maskgen64(p, mask, d); + 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)) - diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); + 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) - diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); + 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) - diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); + ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); break; default: - diag("unexpected op in rldic case\n%P", p); + ctxt->diag("unexpected op in rldic case\n%P", p); a = 0; } - o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, (v&0x1F)); + o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F)); o1 |= (a&31L)<<6; if(v & 0x20) o1 |= 1<<1; @@ -1817,12 +1819,12 @@ asmout(Prog *p, Optab *o, int aflag) break; case 30: /* rldimi $sh,s,$mask,a */ - v = regoff(&p->from); - d = vregoff(&p->from3); - maskgen64(p, mask, d); + v = regoff(ctxt, &p->from); + d = vregoff(ctxt, &p->from3); + maskgen64(ctxt, p, mask, d); if(mask[1] != (63-v)) - diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); - o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, (v&0x1F)); + 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; @@ -1831,130 +1833,140 @@ asmout(Prog *p, Optab *o, int aflag) break; case 31: /* dword */ - if(aflag) - return 0; - d = vregoff(&p->from); - o1 = d>>32; - o2 = d; + 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(p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6); + 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(p->as), p->to.reg, 0, r); + 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(p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6); + 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(&p->to); + 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(p->as), p->from.reg, REGTMP, v); + 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(&p->from); + 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(p->as), p->to.reg, REGTMP, v); + 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(&p->from); + 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(p->as), p->to.reg, REGTMP, v); + 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 */ - if(aflag) - return 0; - o1 = regoff(&p->from); + o1 = regoff(ctxt, &p->from); break; case 41: /* stswi */ - o1 = AOP_RRR(opirr(p->as), p->from.reg, p->to.reg, 0) | ((regoff(&p->from3)&0x7F)<<11); + 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(p->as), p->to.reg, p->from.reg, 0) | ((regoff(&p->from3)&0x7F)<<11); + 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(p->as), 0, r, p->from.reg); + 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(p->as), p->from.reg, r, p->to.reg); + 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(p->as), p->to.reg, r, p->from.reg); + o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg); break; case 46: /* plain op */ - o1 = oprrr(p->as); + 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(p->as), p->to.reg, r, 0); + 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(p->as), p->to.reg, r, 0); + 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(&p->from) & 1; - o1 = AOP_RRR(oprrr(p->as), 0, 0, p->to.reg) | (v<<21); + 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(p->as), 0, 0, p->from.reg); + 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(p->as); + 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); @@ -1965,7 +1977,7 @@ asmout(Prog *p, Optab *o, int aflag) r = p->reg; if(r == NREG) r = p->to.reg; - v = oprrr(p->as); + 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); @@ -1973,8 +1985,8 @@ asmout(Prog *p, Optab *o, int aflag) break; case 52: /* mtfsbNx cr(n) */ - v = regoff(&p->from)&31L; - o1 = AOP_RRR(oprrr(p->as), v, 0, 0); + v = regoff(ctxt, &p->from)&31L; + o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0); break; case 53: /* mffsX ,fr1 */ @@ -1992,21 +2004,21 @@ asmout(Prog *p, Optab *o, int aflag) break; case 55: /* op Rb, Rd */ - o1 = AOP_RRR(oprrr(p->as), p->to.reg, 0, p->from.reg); + 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(&p->from); + v = regoff(ctxt, &p->from); r = p->reg; if(r == NREG) r = p->to.reg; - o1 = AOP_RRR(opirr(p->as), r, p->to.reg, v&31L); + 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(&p->from); + v = regoff(ctxt, &p->from); r = p->reg; if(r == NREG) r = p->to.reg; @@ -2015,7 +2027,7 @@ asmout(Prog *p, Optab *o, int aflag) * qc has already complained. * if(v < 0 || v > 31) - diag("illegal shift %ld\n%P", v, p); + ctxt->diag("illegal shift %ld\n%P", v, p); */ if(v < 0) v = 0; @@ -2035,48 +2047,48 @@ asmout(Prog *p, Optab *o, int aflag) break; case 58: /* logical $andcon,[s],a */ - v = regoff(&p->from); + v = regoff(ctxt, &p->from); r = p->reg; if(r == NREG) r = p->to.reg; - o1 = LOP_IRR(opirr(p->as), p->to.reg, r, v); + o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); break; case 59: /* or/and $ucon,,r */ - v = regoff(&p->from); + v = regoff(ctxt, &p->from); r = p->reg; if(r == NREG) r = p->to.reg; - o1 = LOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */ + 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(&p->from)&31L; - o1 = AOP_RRR(oprrr(p->as), r, p->reg, p->to.reg); + 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(&p->from)&31L; - v = regoff(&p->to); - o1 = AOP_IRR(opirr(p->as), r, p->reg, v); + 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(&p->from); - maskgen(p, mask, regoff(&p->from3)); - o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, v); + 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(p, mask, regoff(&p->from3)); - o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, p->from.reg); + 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(&p->from3)&255L; + v = regoff(ctxt, &p->from3)&255L; else v = 255; o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11); @@ -2084,8 +2096,8 @@ asmout(Prog *p, Optab *o, int aflag) case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */ if(p->to.reg == NREG) - diag("must specify FPSCR(n)\n%P", p); - o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(&p->from)&31L)<<12); + 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 */ @@ -2110,7 +2122,7 @@ asmout(Prog *p, Optab *o, int aflag) case 67: /* mcrf crfD,crfS */ if(p->from.type != D_CREG || p->from.reg == NREG || p->to.type != D_CREG || p->to.reg == NREG) - diag("illegal CR field number\n%P", p); + 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; @@ -2125,8 +2137,8 @@ asmout(Prog *p, Optab *o, int aflag) case 69: /* mtcrf CRM,rS */ if(p->from3.type != D_NONE) { if(p->to.reg != NREG) - diag("can't use both mask and CR(n)\n%P", p); - v = regoff(&p->from3) & 0xff; + 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 */ @@ -2141,7 +2153,7 @@ asmout(Prog *p, Optab *o, int aflag) r = 0; else r = (p->reg&7)<<2; - o1 = AOP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg); + o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg); break; case 71: /* cmp[l] r,i,cr*/ @@ -2149,50 +2161,77 @@ asmout(Prog *p, Optab *o, int aflag) r = 0; else r = (p->reg&7)<<2; - o1 = AOP_RRR(opirr(p->as), r, p->from.reg, 0) | (regoff(&p->to)&0xffff); + 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(p->as), p->from.reg, 0, p->to.reg); + 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) - diag("illegal FPSCR/CR field number\n%P", p); + 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(&p->to); - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); - o2 = AOP_IRR(opstore(p->as), p->from.reg, REGTMP, v); - if(dlm) - reloc(&p->to, p->pc, 1); + v = regoff(ctxt, &p->to); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, (v>>16)+(v&0x8000)?1:0); + 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(&p->from); - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); - o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v); - if(dlm) - reloc(&p->from, p->pc, 1); + v = regoff(ctxt, &p->from); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, (v>>16)+(v&0x8000)?1:0); + 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(&p->from); - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); - o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v); + v = regoff(ctxt, &p->from); + o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, (v>>16)+(v&0x8000)?1:0); + 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); + //if(dlm) reloc(&p->from, p->pc, 1); break; } - if(aflag) - return o1; + + out[0] = o1; + out[1] = o2; + out[2] = o3; + out[3] = o4; + out[4] = o5; + return; + +#if NOTDEF v = p->pc; switch(o->size) { default: @@ -2238,25 +2277,26 @@ asmout(Prog *p, Optab *o, int aflag) break; } return 0; +#endif } -vlong -vregoff(Adr *a) +static vlong +vregoff(Link *ctxt, Addr *a) { - instoffset = 0; - aclass(a); - return instoffset; + ctxt->instoffset = 0; + aclass(ctxt, a); + return ctxt->instoffset; } -long -regoff(Adr *a) +static int32 +regoff(Link *ctxt, Addr *a) { - return vregoff(a); + return vregoff(ctxt, a); } -long -oprrr(int a) +static int32 +oprrr(Link *ctxt, int a) { switch(a) { case AADD: return OPVCC(31,266,0,0); @@ -2531,12 +2571,12 @@ oprrr(int a) case AXOR: return OPVCC(31,316,0,0); case AXORCC: return OPVCC(31,316,0,1); } - diag("bad r/r opcode %A", a); + ctxt->diag("bad r/r opcode %A", a); return 0; } -long -opirr(int a) +static int32 +opirr(Link *ctxt, int a) { switch(a) { case AADD: return OPVCC(14,0,0,0); @@ -2602,15 +2642,15 @@ opirr(int a) case AXOR: return OPVCC(26,0,0,0); /* XORIL */ case AXOR+AEND: return OPVCC(27,0,0,0); /* XORIU */ } - diag("bad opcode i/r %A", a); + ctxt->diag("bad opcode i/r %A", a); return 0; } /* * load o(a),d */ -long -opload(int a) +static int32 +opload(Link *ctxt, int a) { switch(a) { case AMOVD: return OPVCC(58,0,0,0); /* ld */ @@ -2633,15 +2673,15 @@ opload(int a) case AMOVHZU: return OPVCC(41,0,0,0); case AMOVMW: return OPVCC(46,0,0,0); /* lmw */ } - diag("bad load opcode %A", a); + ctxt->diag("bad load opcode %A", a); return 0; } /* * indexed load a(b),d */ -long -oploadx(int a) +static int32 +oploadx(Link *ctxt, int a) { switch(a) { case AMOVWZ: return OPVCC(31,23,0,0); /* lwzx */ @@ -2664,19 +2704,20 @@ oploadx(int a) 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 */ } - diag("bad loadx opcode %A", a); + ctxt->diag("bad loadx opcode %A", a); return 0; } /* * store s,o(d) */ -long -opstore(int a) +static int32 +opstore(Link *ctxt, int a) { switch(a) { case AMOVB: @@ -2700,15 +2741,15 @@ opstore(int a) case AMOVD: return OPVCC(62,0,0,0); /* std */ case AMOVDU: return OPVCC(62,0,0,1); /* stdu */ } - diag("unknown store opcode %A", a); + ctxt->diag("unknown store opcode %A", a); return 0; } /* * indexed store s,a(b) */ -long -opstorex(int a) +static int32 +opstorex(Link *ctxt, int a) { switch(a) { case AMOVB: @@ -2736,6 +2777,7 @@ opstorex(int a) case AMOVD: return OPVCC(31,149,0,0); /* stdx */ case AMOVDU: return OPVCC(31,181,0,0); /* stdux */ } - diag("unknown storex opcode %A", a); + ctxt->diag("unknown storex opcode %A", a); return 0; } + diff --git a/src/liblink/list9.c b/src/liblink/list9.c index f9de2bf11..3299d269a 100644 --- a/src/liblink/list9.c +++ b/src/liblink/list9.c @@ -27,29 +27,61 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore +#include +#include +#include +#include +#include "../cmd/9l/9.out.h" -#include "l.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 -listinit(void) +listinit9(void) { - fmtinstall('A', Aconv); fmtinstall('D', Dconv); fmtinstall('P', Pconv); - fmtinstall('S', Sconv); - fmtinstall('N', Nconv); fmtinstall('R', Rconv); -} -void -prasm(Prog *p) -{ - print("%P\n", p); + // for liblink internal use + fmtinstall('^', DRconv); + + // for internal use + fmtinstall('$', DSconv); + fmtinstall('M', Mconv); } -int +static Prog* bigP; + +static int Pconv(Fmt *fp) { char str[STRINGSZ], *s; @@ -57,26 +89,36 @@ Pconv(Fmt *fp) int a; p = va_arg(fp->args, Prog*); - curp = p; + bigP = p; a = p->as; if(a == ADATA || a == AINIT || a == ADYNT) - sprint(str, "(%d) %A %D/%d,%D", p->line, a, &p->from, p->reg, &p->to); - else { + 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, "(%d) %A %D,%D", p->line, a, &p->from, &p->to); + sprint(s, "%.5lld (%d) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to); else if(a != ATEXT && p->from.type == D_OREG) { - sprint(s, "(%d) %A %lld(R%d+R%d),%D", p->line, a, + sprint(s, "%.5lld (%d) %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, "(%d) %A %D,%lld(R%d+R%d)", p->line, a, + sprint(s, "%.5lld (%d) %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, "(%d) %A %D", p->line, a, &p->from); + 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) @@ -87,7 +129,7 @@ Pconv(Fmt *fp) return fmtstrcpy(fp, str); } -int +static int Aconv(Fmt *fp) { char *s; @@ -96,55 +138,65 @@ Aconv(Fmt *fp) a = va_arg(fp->args, int); s = "???"; if(a >= AXXX && a < ALAST) - s = anames[a]; + s = anames9[a]; return fmtstrcpy(fp, s); } -int +static int Dconv(Fmt *fp) { char str[STRINGSZ]; - Adr *a; - long v; + Addr *a; + int32 v; - a = va_arg(fp->args, Adr*); - switch(a->type) { + 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 != S) - sprint(str, "%N(R%d)(NONE)", a, a->reg); + 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, "$%N(R%d)", a, a->reg); + sprint(str, "$%M(R%d)", a, a->reg); else - sprint(str, "$%N", a); + sprint(str, "$%M", a); break; case D_OREG: if(a->reg != NREG) - sprint(str, "%N(R%d)", a, a->reg); + sprint(str, "%M(R%d)", a, a->reg); else - sprint(str, "%N", a); + sprint(str, "%M", a); break; case D_REG: sprint(str, "R%d", a->reg); - if(a->name != D_NONE || a->sym != S) - sprint(str, "%N(R%d)(REG)", a, 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 != S) - sprint(str, "%N(F%d)(REG)", a, a->reg); + if(a->name != D_NONE || a->sym != nil) + sprint(str, "%M(F%d)(REG)", a, a->reg); break; case D_CREG: @@ -152,12 +204,12 @@ Dconv(Fmt *fp) strcpy(str, "CR"); else sprint(str, "CR%d", a->reg); - if(a->name != D_NONE || a->sym != S) - sprint(str, "%N(C%d)(REG)", a, 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 == S) { + 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; @@ -167,18 +219,18 @@ Dconv(Fmt *fp) break; } sprint(str, "SPR-GOK(%d)", a->reg); - if(a->name != D_NONE || a->sym != S) - sprint(str, "%N(SPR-GOK%d)(REG)", a, 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 == S) { + 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 != S) - sprint(str, "%N(DCR-GOK%d)(REG)", a, a->reg); + if(a->name != D_NONE || a->sym != nil) + sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg); break; case D_OPT: @@ -197,57 +249,71 @@ Dconv(Fmt *fp) break; case D_BRANCH: - if(curp->cond != P) { - v = curp->cond->pc; - if(v >= INITTEXT) - v -= INITTEXT-HEADR; - if(a->sym != S) + 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 != S) + 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, "$%lux-%lux", a->ieee.h, a->ieee.l); + sprint(str, "$%.17g", a->u.dval); break; case D_SCONST: - sprint(str, "$\"%S\"", a->sval); + sprint(str, "$\"%$\"", a->u.sval); break; } + +ret: return fmtstrcpy(fp, str); } -int -Nconv(Fmt *fp) +static int +Mconv(Fmt *fp) { char str[STRINGSZ]; - Adr *a; - Sym *s; - long l; + Addr *a; + LSym *s; + int32 l; - a = va_arg(fp->args, Adr*); + a = va_arg(fp->args, Addr*); s = a->sym; - if(s == S) { + //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); - goto out; - } - switch(a->name) { - default: - sprint(str, "GOK-name(%d)", a->name); break; case D_EXTERN: - sprint(str, "%s+%lld(SB)", s->name, a->offset); + 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: @@ -255,19 +321,36 @@ Nconv(Fmt *fp) break; case D_AUTO: - sprint(str, "%s-%lld(SP)", s->name, -a->offset); + if(s == nil) + sprint(str, "%lld(SP)", -a->offset); + else + sprint(str, "%s-%lld(SP)", s->name, -a->offset); break; case D_PARAM: - sprint(str, "%s+%lld(FP)", s->name, a->offset); + if(s == nil) + sprint(str, "%lld(FP)", a->offset); + else + sprint(str, "%s+%lld(FP)", s->name, a->offset); break; } -out: +//out: return fmtstrcpy(fp, str); } -int +static int Rconv(Fmt *fp) +{ + char str[STRINGSZ]; + int r; + + r = va_arg(fp->args, int); + sprint(str, "r%d", r); + return fmtstrcpy(fp, str); +} + +static int +DRconv(Fmt *fp) { char *s; int a; @@ -275,19 +358,19 @@ Rconv(Fmt *fp) a = va_arg(fp->args, int); s = "C_??"; if(a >= C_NONE && a <= C_NCLASS) - s = cnames[a]; + s = cnames9[a]; return fmtstrcpy(fp, s); } -int -Sconv(Fmt *fp) +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= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || @@ -319,24 +402,3 @@ Sconv(Fmt *fp) *p = 0; return fmtstrcpy(fp, str); } - -void -diag(char *fmt, ...) -{ - char buf[STRINGSZ], *tn; - va_list arg; - - tn = "??none??"; - if(curtext != P && curtext->from.sym != S) - tn = curtext->from.sym->name; - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - print("%s: %s\n", tn, buf); - - nerrors++; - if(nerrors > 10) { - print("too many errors\n"); - errorexit(); - } -} diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 0e869fb53..63f5b59b0 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -27,58 +27,222 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// +build ignore +#include +#include +#include +#include +#include "../cmd/9l/9.out.h" +#include "../pkg/runtime/stack.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; -#include "l.h" + 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; +} -void -noops(void) +static void +addstacksplit(Link *ctxt, LSym *cursym) { - Prog *p, *p1, *q, *q1; - int o, mov, aoffset, curframe, curbecome, maxbecome; + Prog *p, *q, *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 - * become sizes - * frame sizes * strip NOPs * expand RET * expand BECOME pseudo */ - if(debug['v']) - Bprint(&bso, "%5.2f noops\n", cputime()); - Bflush(&bso); - - curframe = 0; - curbecome = 0; - maxbecome = 0; - curtext = 0; - q = P; - for(p = firstp; p != P; p = p->link) { - - /* find out how much arg space is used in this TEXT */ - if(p->to.type == D_OREG && p->to.reg == REGSP) - if(p->to.offset > curframe) - curframe = p->to.offset; + 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: - if(curtext && curtext->from.sym) { - curtext->from.sym->frame = curframe; - curtext->from.sym->become = curbecome; - if(curbecome > maxbecome) - maxbecome = curbecome; - } - curframe = 0; - curbecome = 0; - q = p; p->mark |= LABEL|LEAF|SYNC; if(p->link) p->link->mark |= LABEL; - curtext = p; break; case ANOR: @@ -183,8 +347,9 @@ noops(void) case ABL: case ABCL: - if(curtext != P) - curtext->mark &= ~LEAF; + case ADUFFZERO: + case ADUFFCOPY: + cursym->text->mark &= ~LEAF; case ABC: case ABEQ: @@ -196,21 +361,20 @@ noops(void) case ABR: case ABVC: case ABVS: - p->mark |= BRANCH; q = p; - q1 = p->cond; - if(q1 != P) { + q1 = p->pcond; + if(q1 != nil) { while(q1->as == ANOP) { q1 = q1->link; - p->cond = q1; + p->pcond = q1; } if(!(q1->mark & LEAF)) q1->mark |= LABEL; } else p->mark |= LABEL; q1 = p->link; - if(q1 != P) + if(q1 != nil) q1->mark |= LABEL; continue; @@ -221,13 +385,8 @@ noops(void) continue; case ARETURN: - /* special form of RETURN is BECOME */ - if(p->from.type == D_CONST) - if(p->from.offset > curbecome) - curbecome = p->from.offset; - q = p; - if(p->link != P) + if(p->link != nil) p->link->mark |= LABEL; continue; @@ -242,106 +401,76 @@ noops(void) continue; } } - if(curtext && curtext->from.sym) { - curtext->from.sym->frame = curframe; - curtext->from.sym->become = curbecome; - if(curbecome > maxbecome) - maxbecome = curbecome; - } - - if(debug['b']) - print("max become = %d\n", maxbecome); - xdefine("ALEFbecome", STEXT, maxbecome); - - curtext = 0; - for(p = firstp; p != P; p = p->link) { - switch(p->as) { - case ATEXT: - curtext = p; - break; - - case ABL: /* ABCL? */ - if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { - o = maxbecome - curtext->from.sym->frame; - if(o <= 0) - break; - /* calling a become or calling a variable */ - if(p->to.sym == S || p->to.sym->become) { - curtext->to.offset += o; - if(debug['b']) { - curp = p; - print("%D calling %D increase %d\n", - &curtext->from, &p->to, o); - } - } - } - break; - } - } - curtext = P; - for(p = firstp; p != P; p = p->link) { + autosize = 0; + for(p = cursym->text; p != nil; p = p->link) { o = p->as; switch(o) { case ATEXT: mov = AMOVD; aoffset = 0; - curtext = p; - autosize = p->to.offset + 8; + autosize = textstksiz + 8; if((p->mark & LEAF) && autosize <= 8) autosize = 0; else if(autosize & 4) autosize += 4; - p->to.offset = autosize - 8; + p->to.offset = (p->to.offset & (0xffffffffull<<32)) | (uint32)(autosize-8); q = p; if(autosize) { /* use MOVDU to adjust R1 when saving R31, if autosize is small */ - if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) { + if(!(cursym->text->mark & LEAF) && autosize >= -BIG && autosize <= BIG) { mov = AMOVDU; aoffset = -autosize; } else { - q = prg(); + q = ctxt->arch->prg(); q->as = AADD; - q->line = p->line; + 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; } } else - if(!(curtext->mark & LEAF)) { - if(debug['v']) - Bprint(&bso, "save suppressed in: %s\n", - curtext->from.sym->name); - curtext->mark |= LEAF; + 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(curtext->mark & LEAF) { - if(curtext->from.sym) - curtext->from.sym->type = SLEAF; + if(cursym->text->mark & LEAF) { + cursym->leaf = 1; break; } - q1 = prg(); + if(!(p->reg & NOSPLIT)) + p = stacksplit(ctxt, p, autosize, !(cursym->text->reg&NEEDCTXT)); // emit split check + + q1 = ctxt->arch->prg(); q1->as = mov; - q1->line = p->line; + q1->lineno = p->lineno; q1->from.type = D_REG; q1->from.reg = REGTMP; q1->to.type = D_OREG; q1->to.offset = aoffset; q1->to.reg = REGSP; + if(q1->as == AMOVDU) + q1->spadj = -aoffset; q1->link = q->link; q->link = q1; - q1 = prg(); + q1 = ctxt->arch->prg(); q1->as = AMOVD; - q1->line = p->line; + q1->lineno = p->lineno; q1->from.type = D_SPR; q1->from.offset = D_LR; q1->to.type = D_REG; @@ -352,9 +481,11 @@ noops(void) break; case ARETURN: - if(p->from.type == D_CONST) - goto become; - if(curtext->mark & LEAF) { + if(p->from.type == D_CONST) { + ctxt->diag("using BECOME (%P) is not supported!", p); + break; + } + if(cursym->text->mark & LEAF) { if(!autosize) { p->as = ABR; p->from = zprg.from; @@ -369,13 +500,15 @@ noops(void) p->from.offset = autosize; p->to.type = D_REG; p->to.reg = REGSP; + p->spadj = -autosize; - q = prg(); + q = ctxt->arch->prg(); q->as = ABR; - q->line = p->line; + 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; @@ -389,9 +522,9 @@ noops(void) p->to.type = D_REG; p->to.reg = REGTMP; - q = prg(); + q = ctxt->arch->prg(); q->as = AMOVD; - q->line = p->line; + q->lineno = p->lineno; q->from.type = D_REG; q->from.reg = REGTMP; q->to.type = D_SPR; @@ -402,111 +535,50 @@ noops(void) p = q; if(autosize) { - q = prg(); + q = ctxt->arch->prg(); q->as = AADD; - q->line = p->line; + 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 = prg(); + q1 = ctxt->arch->prg(); q1->as = ABR; - q1->line = p->line; + 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; - become: - if(curtext->mark & LEAF) { - - q = prg(); - q->line = p->line; - q->as = ABR; - q->from = zprg.from; - q->to = p->to; - q->cond = p->cond; - q->link = p->link; - q->mark |= BRANCH; - p->link = q; - - p->as = AADD; - p->from = zprg.from; - p->from.type = D_CONST; - p->from.offset = autosize; - p->to = zprg.to; - p->to.type = D_REG; - p->to.reg = REGSP; - - break; - } - q = prg(); - q->line = p->line; - q->as = ABR; - q->from = zprg.from; - q->to = p->to; - q->cond = p->cond; - q->mark |= BRANCH; - q->link = p->link; - p->link = q; - - q = prg(); - q->line = p->line; - q->as = AADD; - q->from.type = D_CONST; - q->from.offset = autosize; - q->to.type = D_REG; - q->to.reg = REGSP; - q->link = p->link; - p->link = q; - - q = prg(); - q->line = p->line; - q->as = AMOVD; - q->line = p->line; - 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->as = AMOVD; - p->from = zprg.from; - p->from.type = D_OREG; - p->from.offset = 0; - p->from.reg = REGSP; - p->to = zprg.to; - p->to.type = D_REG; - p->to.reg = REGTMP; - - break; } } +#if 0 // instruction scheduling if(debug['Q'] == 0) return; - curtext = P; - q = P; /* p - 1 */ + curtext = nil; + q = nil; /* p - 1 */ q1 = firstp; /* top of block */ o = 0; /* count of instructions */ - for(p = firstp; p != P; p = p1) { + for(p = firstp; p != nil; p = p1) { p1 = p->link; o++; if(p->mark & NOSCHED){ if(q1 != p){ sched(q1, q); } - for(; p != P; p = p->link){ + for(; p != nil; p = p->link){ if(!(p->mark & NOSCHED)) break; q = p; @@ -534,236 +606,34 @@ noops(void) } q = p; } +#endif } -void -addnop(Prog *p) +static Prog* +stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) { - Prog *q; - - q = prg(); - q->as = AOR; - q->line = p->line; - q->from.type = D_REG; - q->from.reg = REGZERO; - q->to.type = D_REG; - q->to.reg = REGZERO; - - q->link = p->link; - p->link = q; + // TODO(minux): add stack split prologue + USED(ctxt); USED(p); USED(framesize); USED(noctxt); + return p; } -#include "l.h" +static void xfol(Link*, Prog*, Prog**); -void -dodata(void) +static void +follow(Link *ctxt, LSym *s) { - int i, t; - Sym *s; - Prog *p, *p1; - vlong orig, orig1, v; - - if(debug['v']) - Bprint(&bso, "%5.2f dodata\n", cputime()); - Bflush(&bso); - for(p = datap; p != P; p = p->link) { - s = p->from.sym; - if(p->as == ADYNT || p->as == AINIT) - s->value = dtype; - if(s->type == SBSS) - s->type = SDATA; - if(s->type != SDATA) - diag("initialize non-data (%d): %s\n%P", - s->type, s->name, p); - v = p->from.offset + p->reg; - if(v > s->value) - diag("initialize bounds (%lld): %s\n%P", - s->value, s->name, p); - } - - /* - * pass 1 - * assign 'small' variables to data segment - * (rational is that data segment is more easily - * addressed through offset on REGSB) - */ - orig = 0; - for(i=0; ilink) { - t = s->type; - if(t != SDATA && t != SBSS) - continue; - v = s->value; - if(v == 0) { - diag("%s: no size", s->name); - v = 1; - } - v = rnd(v, 4); - s->value = v; - if(v > MINSIZ) - continue; - if(v >= 8) - orig = rnd(orig, 8); - s->value = orig; - orig += v; - s->type = SDATA1; - } - orig1 = orig; - - /* - * pass 2 - * assign 'data' variables to data segment - */ - for(i=0; ilink) { - t = s->type; - if(t != SDATA) { - if(t == SDATA1) - s->type = SDATA; - continue; - } - v = s->value; - if(v >= 8) - orig = rnd(orig, 8); - s->value = orig; - orig += v; - s->type = SDATA1; - } - - if(orig) - orig = rnd(orig, 8); - datsize = orig; + Prog *firstp, *lastp; - /* - * pass 3 - * everything else to bss segment - */ - for(i=0; ilink) { - if(s->type != SBSS) - continue; - v = s->value; - if(v >= 8) - orig = rnd(orig, 8); - s->value = orig; - orig += v; - } - if(orig) - orig = rnd(orig, 8); - bsssize = orig-datsize; - - /* - * pass 4 - * add literals to all large values. - * at this time: - * small data is allocated DATA - * large data is allocated DATA1 - * large bss is allocated BSS - * the new literals are loaded between - * small data and large data. - */ - orig = 0; - for(p = firstp; p != P; p = p->link) { - if(p->as != AMOVW) - continue; - if(p->from.type != D_CONST) - continue; - if(s = p->from.sym) { - t = s->type; - if(t != SDATA && t != SDATA1 && t != SBSS) - continue; - t = p->from.name; - if(t != D_EXTERN && t != D_STATIC) - continue; - v = s->value + p->from.offset; - if(v >= 0 && v <= 0xffff) - continue; - if(!strcmp(s->name, "setSB")) - continue; - /* size should be 19 max */ - if(strlen(s->name) >= 10) /* has loader address */ - sprint(literal, "$%p.%llux", s, p->from.offset); - else - sprint(literal, "$%s.%d.%llux", s->name, s->version, p->from.offset); - } else { - if(p->from.name != D_NONE) - continue; - if(p->from.reg != NREG) - continue; - v = p->from.offset; - if(v >= -0x7fff-1 && v <= 0x7fff) - continue; - if(!(v & 0xffff)) - continue; - if(v) - continue; /* quicker to build it than load it */ - /* size should be 9 max */ - sprint(literal, "$%llux", v); - } - s = lookup(literal, 0); - if(s->type == 0) { - s->type = SDATA; - s->value = orig1+orig; - orig += 4; - p1 = prg(); - p1->as = ADATA; - p1->line = p->line; - p1->from.type = D_OREG; - p1->from.sym = s; - p1->from.name = D_EXTERN; - p1->reg = 4; - p1->to = p->from; - p1->link = datap; - datap = p1; - } - if(s->type != SDATA) - diag("literal not data: %s", s->name); - p->from.type = D_OREG; - p->from.sym = s; - p->from.name = D_EXTERN; - p->from.offset = 0; - continue; - } - while(orig & 7) - orig++; - /* - * pass 5 - * re-adjust offsets - */ - for(i=0; ilink) { - t = s->type; - if(t == SBSS) { - s->value += orig; - continue; - } - if(t == SDATA1) { - s->type = SDATA; - s->value += orig; - continue; - } - } - datsize += orig; - xdefine("setSB", SDATA, 0+BIG); - xdefine("bdata", SDATA, 0); - xdefine("edata", SDATA, datsize); - xdefine("end", SBSS, datsize+bsssize); - xdefine("etext", STEXT, 0); -} - -void -undef(void) -{ - int i; - Sym *s; + ctxt->cursym = s; - for(i=0; ilink) - if(s->type == SXREF) - diag("%s: not defined", s->name); + firstp = ctxt->arch->prg(); + lastp = firstp; + xfol(ctxt, s->text, &lastp); + lastp->link = nil; + s->text = firstp->link; } -int +static int relinv(int a) { @@ -783,49 +653,30 @@ relinv(int a) return 0; } -void -follow(void) -{ - - if(debug['v']) - Bprint(&bso, "%5.2f follow\n", cputime()); - Bflush(&bso); - - firstp = prg(); - lastp = firstp; - - xfol(textp); - - firstp = firstp->link; - lastp->link = P; -} - -void -xfol(Prog *p) +static void +xfol(Link *ctxt, Prog *p, Prog **last) { Prog *q, *r; int a, b, i; loop: - if(p == P) + if(p == nil) return; a = p->as; - if(a == ATEXT) - curtext = p; if(a == ABR) { - q = p->cond; + q = p->pcond; if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){ p->mark |= FOLL; - lastp->link = p; - lastp = p; + (*last)->link = p; + *last = p; p = p->link; - xfol(p); + xfol(ctxt, p, last); p = q; if(p && !(p->mark & FOLL)) goto loop; return; } - if(q != P) { + if(q != nil) { p->mark |= FOLL; p = q; if(!(p->mark & FOLL)) @@ -834,7 +685,7 @@ loop: } if(p->mark & FOLL) { for(i=0,q=p; i<4; i++,q=q->link) { - if(q == lastp || (q->mark&NOSCHED)) + if(q == *last || (q->mark&NOSCHED)) break; b = 0; /* set */ a = q->as; @@ -844,51 +695,51 @@ loop: } if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID) goto copy; - if(!q->cond || (q->cond->mark&FOLL)) + if(!q->pcond || (q->pcond->mark&FOLL)) continue; b = relinv(a); if(!b) continue; copy: for(;;) { - r = prg(); + r = ctxt->arch->prg(); *r = *p; if(!(r->mark&FOLL)) print("cant happen 1\n"); r->mark |= FOLL; if(p != q) { p = p->link; - lastp->link = r; - lastp = r; + (*last)->link = r; + *last = r; continue; } - lastp->link = r; - lastp = r; + (*last)->link = r; + *last = r; if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID) return; r->as = b; - r->cond = p->link; - r->link = p->cond; + r->pcond = p->link; + r->link = p->pcond; if(!(r->link->mark&FOLL)) - xfol(r->link); - if(!(r->cond->mark&FOLL)) + xfol(ctxt, r->link, last); + if(!(r->pcond->mark&FOLL)) print("cant happen 2\n"); return; } } a = ABR; - q = prg(); + q = ctxt->arch->prg(); q->as = a; - q->line = p->line; + q->lineno = p->lineno; q->to.type = D_BRANCH; q->to.offset = p->pc; - q->cond = p; + q->pcond = p; p = q; } p->mark |= FOLL; - lastp->link = p; - lastp = p; + (*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; @@ -896,11 +747,11 @@ loop: } return; } - if(p->cond != P) - if(a != ABL && p->link != P) { - xfol(p->link); - p = p->cond; - if(p == P || (p->mark&FOLL)) + 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; } @@ -908,474 +759,104 @@ loop: goto loop; } -void -patch(void) -{ - long c; - Prog *p, *q; - Sym *s; - int a; - vlong vexit; - - if(debug['v']) - Bprint(&bso, "%5.2f patch\n", cputime()); - Bflush(&bso); - mkfwd(); - s = lookup("exit", 0); - vexit = s->value; - for(p = firstp; p != P; p = p->link) { - a = p->as; - if(a == ATEXT) - curtext = p; - if((a == ABL || a == ARETURN) && p->to.sym != S) { - s = p->to.sym; - if(s->type != STEXT && s->type != SUNDEF) { - diag("undefined: %s\n%P", s->name, p); - s->type = STEXT; - s->value = vexit; - } - if(s->type == SUNDEF){ - p->to.offset = 0; - p->cond = UP; - } - else - p->to.offset = s->value; - p->to.type = D_BRANCH; - } - if(p->to.type != D_BRANCH || p->cond == UP) - continue; - c = p->to.offset; - for(q = firstp; q != P;) { - if(q->forwd != P) - if(c >= q->forwd->pc) { - q = q->forwd; - continue; - } - if(c == q->pc) - break; - q = q->link; - } - if(q == P) { - diag("branch out of range %ld\n%P", c, p); - p->to.type = D_NONE; - } - p->cond = q; - } - - for(p = firstp; p != P; p = p->link) { - if(p->as == ATEXT) - curtext = p; - p->mark = 0; /* initialization for follow */ - if(p->cond != P && p->cond != UP) { - p->cond = brloop(p->cond); - if(p->cond != P) - if(p->to.type == D_BRANCH) - p->to.offset = p->cond->pc; - } - } -} - -#define LOG 5 -void -mkfwd(void) -{ - Prog *p; - long dwn[LOG], cnt[LOG], i; - Prog *lst[LOG]; - - for(i=0; ilink) { - if(p->as == ATEXT) - curtext = p; - i--; - if(i < 0) - i = LOG-1; - p->forwd = P; - dwn[i]--; - if(dwn[i] <= 0) { - dwn[i] = cnt[i]; - if(lst[i] != P) - lst[i]->forwd = p; - lst[i] = p; - } - } -} - -Prog* -brloop(Prog *p) -{ - Prog *q; - int c; - - for(c=0; p!=P;) { - if(p->as != ABR || (p->mark&NOSCHED)) - return p; - q = p->cond; - if(q <= p) { - c++; - if(q == p || c > 5000) - break; - } - p = q; - } - return P; -} - -vlong -atolwhex(char *s) -{ - vlong n; - int f; - - n = 0; - f = 0; - while(*s == ' ' || *s == '\t') - s++; - if(*s == '-' || *s == '+') { - if(*s++ == '-') - f = 1; - while(*s == ' ' || *s == '\t') - s++; - } - if(s[0]=='0' && s[1]){ - if(s[1]=='x' || s[1]=='X'){ - s += 2; - for(;;){ - if(*s >= '0' && *s <= '9') - n = n*16 + *s++ - '0'; - else if(*s >= 'a' && *s <= 'f') - n = n*16 + *s++ - 'a' + 10; - else if(*s >= 'A' && *s <= 'F') - n = n*16 + *s++ - 'A' + 10; - else - break; - } - } else - while(*s >= '0' && *s <= '7') - n = n*8 + *s++ - '0'; - } else - while(*s >= '0' && *s <= '9') - n = n*10 + *s++ - '0'; - if(f) - n = -n; - return n; -} - -vlong -rnd(vlong v, long r) -{ - vlong c; - - if(r <= 0) - return v; - v += r - 1; - c = v % r; - if(c < 0) - c += r; - v -= c; - return v; -} - -void -import(void) -{ - int i; - Sym *s; - - for(i = 0; i < NHASH; i++) - for(s = hash[i]; s != S; s = s->link) - if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ - undefsym(s); - Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, s->value); - if(debug['S']) - s->sig = 0; - } -} - -void -ckoff(Sym *s, vlong v) -{ - if(v < 0 || v >= 1<name); -} - static Prog* -newdata(Sym *s, int o, int w, int t) +prg(void) { Prog *p; - p = prg(); - p->link = datap; - datap = p; - p->as = ADATA; - p->reg = w; - p->from.type = D_OREG; - p->from.name = t; - p->from.sym = s; - p->from.offset = o; - p->to.type = D_CONST; - p->to.name = D_NONE; + p = emallocz(sizeof(*p)); + *p = zprg; return p; } -void -export(void) -{ - int i, j, n, off, nb, sv, ne; - Sym *s, *et, *str, **esyms; - Prog *p; - char buf[NSNAME], *t; - - n = 0; - for(i = 0; i < NHASH; i++) - for(s = hash[i]; s != S; s = s->link) - if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport)) - n++; - esyms = malloc(n*sizeof(Sym*)); - ne = n; - n = 0; - for(i = 0; i < NHASH; i++) - for(s = hash[i]; s != S; s = s->link) - if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport)) - esyms[n++] = s; - for(i = 0; i < ne-1; i++) - for(j = i+1; j < ne; j++) - if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ - s = esyms[i]; - esyms[i] = esyms[j]; - esyms[j] = s; - } - - nb = 0; - off = 0; - et = lookup(EXPTAB, 0); - if(et->type != 0 && et->type != SXREF) - diag("%s already defined", EXPTAB); - et->type = SDATA; - str = lookup(".string", 0); - if(str->type == 0) - str->type = SDATA; - sv = str->value; - for(i = 0; i < ne; i++){ - s = esyms[i]; - Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); - - /* signature */ - p = newdata(et, off, sizeof(long), D_EXTERN); - off += sizeof(long); - p->to.offset = s->sig; - - /* address */ - p = newdata(et, off, sizeof(long), D_EXTERN); - off += sizeof(long); /* TO DO: bug */ - p->to.name = D_EXTERN; - p->to.sym = s; - - /* string */ - t = s->name; - n = strlen(t)+1; - for(;;){ - buf[nb++] = *t; - sv++; - if(nb >= NSNAME){ - p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); - p->to.type = D_SCONST; - memmove(p->to.sval, buf, NSNAME); - nb = 0; - } - if(*t++ == 0) - break; - } - - /* name */ - p = newdata(et, off, sizeof(long), D_EXTERN); - off += sizeof(long); - p->to.name = D_STATIC; - p->to.sym = str; - p->to.offset = sv-n; - } - - if(nb > 0){ - p = newdata(str, sv-nb, nb, D_STATIC); - p->to.type = D_SCONST; - memmove(p->to.sval, buf, nb); - } - - for(i = 0; i < 3; i++){ - newdata(et, off, sizeof(long), D_EXTERN); - off += sizeof(long); - } - et->value = off; - if(sv == 0) - sv = 1; - str->value = sv; - exports = ne; - free(esyms); -} - -enum{ - ABSD = 0, - ABSU = 1, - RELD = 2, - RELU = 3, +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, + + .ACALL = ABL, + .ADATA = ADATA, + .AEND = AEND, + .AFUNCDATA = AFUNCDATA, + .AGLOBL = AGLOBL, + .AJMP = ABR, + .ANOP = ANOP, + .APCDATA = APCDATA, + .ARET = ARETURN, + .ATEXT = ATEXT, + .ATYPE = ATYPE, + .AUSEFIELD = AUSEFIELD, }; -int modemap[8] = { 0, 1, -1, 2, 3, 4, 5, 6}; - -typedef struct Reloc Reloc; - -struct Reloc -{ - int n; - int t; - uchar *m; - ulong *a; +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, + + .ACALL = ABL, + .ADATA = ADATA, + .AEND = AEND, + .AFUNCDATA = AFUNCDATA, + .AGLOBL = AGLOBL, + .AJMP = ABR, + .ANOP = ANOP, + .APCDATA = APCDATA, + .ARET = ARETURN, + .ATEXT = ATEXT, + .ATYPE = ATYPE, + .AUSEFIELD = AUSEFIELD, }; - -Reloc rels; - -static void -grow(Reloc *r) -{ - int t; - uchar *m, *nm; - ulong *a, *na; - - t = r->t; - r->t += 64; - m = r->m; - a = r->a; - r->m = nm = malloc(r->t*sizeof(uchar)); - r->a = na = malloc(r->t*sizeof(ulong)); - memmove(nm, m, t*sizeof(uchar)); - memmove(na, a, t*sizeof(ulong)); - free(m); - free(a); -} - -void -dynreloc(Sym *s, long v, int abs, int split, int sext) -{ - int i, k, n; - uchar *m; - ulong *a; - Reloc *r; - - if(v&3) - diag("bad relocation address"); - v >>= 2; - if(s->type == SUNDEF) - k = abs ? ABSU : RELU; - else - k = abs ? ABSD : RELD; - if(split) - k += 4; - if(sext) - k += 2; - /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */ - k = modemap[k]; - r = &rels; - n = r->n; - if(n >= r->t) - grow(r); - m = r->m; - a = r->a; - for(i = n; i > 0; i--){ - if(v < a[i-1]){ /* happens occasionally for data */ - m[i] = m[i-1]; - a[i] = a[i-1]; - } - else - break; - } - m[i] = k; - a[i] = v; - r->n++; -} - -static int -sput(char *s) -{ - char *p; - - p = s; - while(*s) - cput(*s++); - cput(0); - return s-p+1; -} - -void -asmdyn() -{ - int i, n, t, c; - Sym *s; - ulong la, ra, *a; - vlong off; - uchar *m; - Reloc *r; - - cflush(); - off = seek(cout, 0, 1); - lput(0); - t = 0; - lput(imports); - t += 4; - for(i = 0; i < NHASH; i++) - for(s = hash[i]; s != S; s = s->link) - if(s->type == SUNDEF){ - lput(s->sig); - t += 4; - t += sput(s->name); - } - - la = 0; - r = &rels; - n = r->n; - m = r->m; - a = r->a; - lput(n); - t += 4; - for(i = 0; i < n; i++){ - ra = *a-la; - if(*a < la) - diag("bad relocation order"); - if(ra < 256) - c = 0; - else if(ra < 65536) - c = 1; - else - c = 2; - cput((c<<6)|*m++); - t++; - if(c == 0){ - cput(ra); - t++; - } - else if(c == 1){ - wput(ra); - t += 2; - } - else{ - lput(ra); - t += 4; - } - la = *a++; - } - - cflush(); - seek(cout, off, 0); - lput(t); - - if(debug['v']){ - Bprint(&bso, "import table entries = %d\n", imports); - Bprint(&bso, "export table entries = %d\n", exports); - } -} -- cgit v1.2.1 From 36631216a1103e4e017f8fa701419f7ff01c9727 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:34:25 -0400 Subject: [dev.power64] cmd/9c: fix switch bug The cmd/cc bundled with 9c has additional code compared to our cmd/cc, and without those code, 9c couldn't handle switch statement where the expression is not just a simple int32 or int64 variable (e.g. g->status or int8 variable). All credit goes to rsc. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125840043 --- src/cmd/9c/swt.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cmd/9c/swt.c b/src/cmd/9c/swt.c index c912cd5ed..83058e7ab 100644 --- a/src/cmd/9c/swt.c +++ b/src/cmd/9c/swt.c @@ -32,11 +32,19 @@ void swit1(C1 *q, int nc, int32 def, Node *n) { - Node tn; - + 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, ®node, Z); - swit2(q, nc, def, n, &tn); + swit2(q, nc, def, &nod, &tn); regfree(&tn); + regfree(&nod); } void -- cgit v1.2.1 From 5c2185b02484d16637a42e0ae86fa240f8db316c Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:36:42 -0400 Subject: [dev.power64] cmd/ld: update for power64 LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121380043 --- src/cmd/ld/data.c | 4 +++- src/cmd/ld/doc.go | 6 +++--- src/cmd/ld/dwarf.c | 4 ++-- src/cmd/ld/elf.c | 29 ++++++++++++++++++----------- src/cmd/ld/ldelf.c | 6 ++++++ src/cmd/ld/lib.c | 4 +++- src/cmd/ld/lib.h | 4 ---- src/cmd/ld/macho.c | 1 + src/cmd/ld/symtab.c | 1 + 9 files changed, 37 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 96eadd479..702f559a8 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -441,11 +441,11 @@ blk(LSym *start, int32 addr, int32 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; @@ -459,6 +459,8 @@ blk(LSym *start, int32 addr, int32 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 8135bd549..cea809715 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 3f93f5818..702d4dfcb 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -2179,7 +2179,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"); @@ -2234,7 +2234,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 38e414755..284f7b21d 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 0a5d8d99f..bdba21747 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -586,6 +586,7 @@ hostlink(void) argv[argc++] = "-m32"; break; case '6': + case '9': argv[argc++] = "-m64"; break; case '5': @@ -1146,6 +1147,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; @@ -1525,7 +1527,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/lib.h b/src/cmd/ld/lib.h index 4094dfa6b..6ce880ea9 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -33,10 +33,6 @@ // A section further describes the pieces of that block for // use in debuggers and such. -enum { - MAXIO = 8192, -}; - typedef struct Segment Segment; typedef struct Section Section; diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c index 61306bb7c..c645e6409 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 1805f97d3..8149a6716 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); -- cgit v1.2.1 From 4d0a2b27416e2cc87be30d198489d55db120d48b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:41:09 -0400 Subject: [dev.power64] liblink: handle $i64. symbols, add debug output for -S -v, show rel addend in hex for RISC arches LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/127770043 --- src/liblink/objfile.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c index 22c9199d5..3b78571b7 100644 --- a/src/liblink/objfile.c +++ b/src/liblink/objfile.c @@ -138,6 +138,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; @@ -322,7 +324,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); } } @@ -725,7 +730,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; -- cgit v1.2.1 From 8dfcec8baa67fd6c0027781289bcdc12a6c2cd63 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:41:37 -0400 Subject: [dev.power64] cmd/9c: add Makefile LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121370043 --- src/cmd/9c/Makefile | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/cmd/9c/Makefile (limited to 'src') 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 -- cgit v1.2.1 From 9a537c1ecfd5ff0bb25eac95c82a6a8c4c0dcc93 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:31:28 -0400 Subject: [dev.power64] cmd/ld: add MAXIO back in lib.h It was accidentally removed. LGTM=dave R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/124880043 --- src/cmd/ld/lib.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 6ce880ea9..4094dfa6b 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -33,6 +33,10 @@ // A section further describes the pieces of that block for // use in debuggers and such. +enum { + MAXIO = 8192, +}; + typedef struct Segment Segment; typedef struct Section Section; -- cgit v1.2.1 From 7ea73ff0a6fb3981622f592e199c8f43be8dd4c5 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:32:08 -0400 Subject: [dev.power64] runtime: rename traceback_arm.c to traceback_lr.c Also make it more portable by not hardcoding pointer sizes. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/127780043 --- src/pkg/runtime/traceback_arm.c | 363 --------------------------------------- src/pkg/runtime/traceback_lr.c | 365 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 365 insertions(+), 363 deletions(-) delete mode 100644 src/pkg/runtime/traceback_arm.c create mode 100644 src/pkg/runtime/traceback_lr.c (limited to 'src') diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c deleted file mode 100644 index 778d95a28..000000000 --- a/src/pkg/runtime/traceback_arm.c +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#include "runtime.h" -#include "arch_GOARCH.h" -#include "malloc.h" -#include "funcdata.h" - -void runtime·sigpanic(void); -void runtime·newproc(void); -void runtime·deferproc(void); - -int32 -runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, bool (*callback)(Stkframe*, void*), void *v, bool printall) -{ - int32 i, n, nprint, line, gotraceback; - uintptr x, tracepc, sparg; - bool waspanic, wasnewproc, printing; - Func *f, *flr; - Stkframe frame; - Stktop *stk; - String file; - Panic *panic; - Defer *defer; - - gotraceback = runtime·gotraceback(nil); - - if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp. - if(gp->syscallstack != (uintptr)nil) { - pc0 = gp->syscallpc; - sp0 = gp->syscallsp; - lr0 = 0; - } else { - pc0 = gp->sched.pc; - sp0 = gp->sched.sp; - lr0 = gp->sched.lr; - } - } - - nprint = 0; - runtime·memclr((byte*)&frame, sizeof frame); - frame.pc = pc0; - frame.lr = lr0; - frame.sp = sp0; - waspanic = false; - wasnewproc = false; - printing = pcbuf==nil && callback==nil; - - panic = gp->panic; - defer = gp->defer; - - while(defer != nil && defer->argp == NoArgs) - defer = defer->link; - while(panic != nil && panic->defer == nil) - panic = panic->link; - - // If the PC is zero, it's likely a nil function call. - // Start in the caller's frame. - if(frame.pc == 0) { - frame.pc = frame.lr; - frame.lr = 0; - } - - f = runtime·findfunc(frame.pc); - if(f == nil) { - if(callback != nil) { - runtime·printf("runtime: unknown pc %p\n", frame.pc); - runtime·throw("unknown pc"); - } - return 0; - } - frame.fn = f; - - n = 0; - stk = (Stktop*)gp->stackbase; - while(n < max) { - // Typically: - // pc is the PC of the running function. - // sp is the stack pointer at that program counter. - // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown. - // stk is the stack containing sp. - // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp. - - if(frame.pc == (uintptr)runtime·lessstack) { - // Hit top of stack segment. Unwind to next segment. - frame.pc = stk->gobuf.pc; - frame.sp = stk->gobuf.sp; - frame.lr = 0; - frame.fp = 0; - if(printing && runtime·showframe(nil, gp)) - runtime·printf("----- stack segment boundary -----\n"); - stk = (Stktop*)stk->stackbase; - - f = runtime·findfunc(frame.pc); - if(f == nil) { - runtime·printf("runtime: unknown pc %p after stack split\n", frame.pc); - if(callback != nil) - runtime·throw("unknown pc"); - } - frame.fn = f; - continue; - } - f = frame.fn; - - // Found an actual function. - // Derive frame pointer and link register. - if(frame.fp == 0) - frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc); - if(runtime·topofstack(f)) { - frame.lr = 0; - flr = nil; - } else if(f->entry == (uintptr)runtime·jmpdefer) { - // jmpdefer modifies SP/LR/PC non-atomically. - // If a profiling interrupt arrives during jmpdefer, - // the stack unwind may see a mismatched register set - // and get confused. Stop if we see PC within jmpdefer - // to avoid that confusion. - // See golang.org/issue/8153. - // This check can be deleted if jmpdefer is changed - // to restore all three atomically using pop. - if(callback != nil) - runtime·throw("traceback_arm: found jmpdefer when tracing with callback"); - frame.lr = 0; - flr = nil; - } else { - if((n == 0 && frame.sp < frame.fp) || frame.lr == 0) - frame.lr = *(uintptr*)frame.sp; - flr = runtime·findfunc(frame.lr); - if(flr == nil) { - // This happens if you get a profiling interrupt at just the wrong time. - // In that context it is okay to stop early. - // But if callback is set, we're doing a garbage collection and must - // get everything, so crash loudly. - if(callback != nil) { - runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr); - runtime·throw("unknown caller pc"); - } - } - } - - frame.varp = (byte*)frame.fp; - - // Derive size of arguments. - // Most functions have a fixed-size argument block, - // so we can use metadata about the function f. - // Not all, though: there are some variadic functions - // in package runtime and reflect, and for those we use call-specific - // metadata recorded by f's caller. - if(callback != nil || printing) { - frame.argp = (byte*)frame.fp + sizeof(uintptr); - if(f->args != ArgsSizeUnknown) - frame.arglen = f->args; - else if(flr == nil) - frame.arglen = 0; - else if(frame.lr == (uintptr)runtime·lessstack) - frame.arglen = stk->argsize; - else if((i = runtime·funcarglen(flr, frame.lr)) >= 0) - frame.arglen = i; - else { - runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n", - runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?"); - if(callback != nil) - runtime·throw("invalid stack"); - frame.arglen = 0; - } - } - - // Determine function SP where deferproc would find its arguments. - // On ARM that's just the standard bottom-of-stack plus 1 word for - // the saved LR. If the previous frame was a direct call to newproc/deferproc, - // however, the SP is three words lower than normal. - // If the function has no frame at all - perhaps it just started, or perhaps - // it is a leaf with no local variables - then we cannot possibly find its - // SP in a defer, and we might confuse its SP for its caller's SP, so - // set sparg=0 in that case. - sparg = 0; - if(frame.fp != frame.sp) { - sparg = frame.sp + sizeof(uintreg); - if(wasnewproc) - sparg += 3*sizeof(uintreg); - } - - // Determine frame's 'continuation PC', where it can continue. - // Normally this is the return address on the stack, but if sigpanic - // is immediately below this function on the stack, then the frame - // stopped executing due to a trap, and frame.pc is probably not - // a safe point for looking up liveness information. In this panicking case, - // the function either doesn't return at all (if it has no defers or if the - // defers do not recover) or it returns from one of the calls to - // deferproc a second time (if the corresponding deferred func recovers). - // It suffices to assume that the most recent deferproc is the one that - // returns; everything live at earlier deferprocs is still live at that one. - frame.continpc = frame.pc; - if(waspanic) { - if(panic != nil && panic->defer->argp == (byte*)sparg) - frame.continpc = (uintptr)panic->defer->pc; - else if(defer != nil && defer->argp == (byte*)sparg) - frame.continpc = (uintptr)defer->pc; - else - frame.continpc = 0; - } - - // Unwind our local panic & defer stacks past this frame. - while(panic != nil && (panic->defer == nil || panic->defer->argp == (byte*)sparg || panic->defer->argp == NoArgs)) - panic = panic->link; - while(defer != nil && (defer->argp == (byte*)sparg || defer->argp == NoArgs)) - defer = defer->link; - - if(skip > 0) { - skip--; - goto skipped; - } - - if(pcbuf != nil) - pcbuf[n] = frame.pc; - if(callback != nil) { - if(!callback(&frame, v)) - return n; - } - if(printing) { - if(printall || runtime·showframe(f, gp)) { - // Print during crash. - // main(0x1, 0x2, 0x3) - // /home/rsc/go/src/runtime/x.go:23 +0xf - tracepc = frame.pc; // back up to CALL instruction for funcline. - if(n > 0 && frame.pc > f->entry && !waspanic) - tracepc -= sizeof(uintptr); - runtime·printf("%s(", runtime·funcname(f)); - for(i = 0; i < frame.arglen/sizeof(uintptr); i++) { - if(i >= 10) { - runtime·prints(", ..."); - break; - } - if(i != 0) - runtime·prints(", "); - runtime·printhex_c(((uintptr*)frame.argp)[i]); - } - runtime·prints(")\n"); - line = runtime·funcline(f, tracepc, &file); - runtime·printf("\t%S:%d", file, line); - if(frame.pc > f->entry) - runtime·printf(" +%p", (uintptr)(frame.pc - f->entry)); - if(g->m->throwing > 0 && gp == g->m->curg || gotraceback >= 2) - runtime·printf(" fp=%p sp=%p", frame.fp, frame.sp); - runtime·printf("\n"); - nprint++; - } - } - n++; - - skipped: - waspanic = f->entry == (uintptr)runtime·sigpanic; - wasnewproc = f->entry == (uintptr)runtime·newproc || f->entry == (uintptr)runtime·deferproc; - - // Do not unwind past the bottom of the stack. - if(flr == nil) - break; - - // Unwind to next frame. - frame.pc = frame.lr; - frame.fn = flr; - frame.lr = 0; - frame.sp = frame.fp; - frame.fp = 0; - - // sighandler saves the lr on stack before faking a call to sigpanic - if(waspanic) { - x = *(uintptr*)frame.sp; - frame.sp += 4; - frame.fn = f = runtime·findfunc(frame.pc); - if(f == nil) - frame.pc = x; - else if(f->frame == 0) - frame.lr = x; - } - } - - if(pcbuf == nil && callback == nil) - n = nprint; - - // For rationale, see long comment in traceback_x86.c. - if(callback != nil && n < max && defer != nil) { - if(defer != nil) - runtime·printf("runtime: g%D: leftover defer argp=%p pc=%p\n", gp->goid, defer->argp, defer->pc); - if(panic != nil) - runtime·printf("runtime: g%D: leftover panic argp=%p pc=%p\n", gp->goid, panic->defer->argp, panic->defer->pc); - for(defer = gp->defer; defer != nil; defer = defer->link) - runtime·printf("\tdefer %p argp=%p pc=%p\n", defer, defer->argp, defer->pc); - for(panic = gp->panic; panic != nil; panic = panic->link) { - runtime·printf("\tpanic %p defer %p", panic, panic->defer); - if(panic->defer != nil) - runtime·printf(" argp=%p pc=%p", panic->defer->argp, panic->defer->pc); - runtime·printf("\n"); - } - runtime·throw("traceback has leftover defers or panics"); - } - - return n; -} - -void -runtime·printcreatedby(G *gp) -{ - int32 line; - uintptr pc, tracepc; - Func *f; - String file; - - // Show what created goroutine, except main goroutine (goid 1). - if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && - runtime·showframe(f, gp) && gp->goid != 1) { - runtime·printf("created by %s\n", runtime·funcname(f)); - tracepc = pc; // back up to CALL instruction for funcline. - if(pc > f->entry) - tracepc -= PCQuantum; - line = runtime·funcline(f, tracepc, &file); - runtime·printf("\t%S:%d", file, line); - if(pc > f->entry) - runtime·printf(" +%p", (uintptr)(pc - f->entry)); - runtime·printf("\n"); - } -} - -void -runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G *gp) -{ - int32 n; - - if(gp->status == Gsyscall) { - // Override signal registers if blocked in system call. - pc = gp->syscallpc; - sp = gp->syscallsp; - lr = 0; - } - - // Print traceback. By default, omits runtime frames. - // If that means we print nothing at all, repeat forcing all frames printed. - n = runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, false); - if(n == 0) - runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, true); - if(n == TracebackMaxFrames) - runtime·printf("...additional frames elided...\n"); - runtime·printcreatedby(gp); -} - -// func caller(n int) (pc uintptr, file string, line int, ok bool) -int32 -runtime·callers(int32 skip, uintptr *pcbuf, int32 m) -{ - uintptr pc, sp; - - sp = runtime·getcallersp(&skip); - pc = (uintptr)runtime·getcallerpc(&skip); - - return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, false); -} - -int32 -runtime·gcallers(G *gp, int32 skip, uintptr *pcbuf, int32 m) -{ - return runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, skip, pcbuf, m, nil, nil, false); -} diff --git a/src/pkg/runtime/traceback_lr.c b/src/pkg/runtime/traceback_lr.c new file mode 100644 index 000000000..d8fcddf68 --- /dev/null +++ b/src/pkg/runtime/traceback_lr.c @@ -0,0 +1,365 @@ +// 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 arm power64 power64le + +#include "runtime.h" +#include "arch_GOARCH.h" +#include "malloc.h" +#include "funcdata.h" + +void runtime·sigpanic(void); +void runtime·newproc(void); +void runtime·deferproc(void); + +int32 +runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, uintptr *pcbuf, int32 max, bool (*callback)(Stkframe*, void*), void *v, bool printall) +{ + int32 i, n, nprint, line, gotraceback; + uintptr x, tracepc, sparg; + bool waspanic, wasnewproc, printing; + Func *f, *flr; + Stkframe frame; + Stktop *stk; + String file; + Panic *panic; + Defer *defer; + + gotraceback = runtime·gotraceback(nil); + + if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp. + if(gp->syscallstack != (uintptr)nil) { + pc0 = gp->syscallpc; + sp0 = gp->syscallsp; + lr0 = 0; + } else { + pc0 = gp->sched.pc; + sp0 = gp->sched.sp; + lr0 = gp->sched.lr; + } + } + + nprint = 0; + runtime·memclr((byte*)&frame, sizeof frame); + frame.pc = pc0; + frame.lr = lr0; + frame.sp = sp0; + waspanic = false; + wasnewproc = false; + printing = pcbuf==nil && callback==nil; + + panic = gp->panic; + defer = gp->defer; + + while(defer != nil && defer->argp == NoArgs) + defer = defer->link; + while(panic != nil && panic->defer == nil) + panic = panic->link; + + // If the PC is zero, it's likely a nil function call. + // Start in the caller's frame. + if(frame.pc == 0) { + frame.pc = frame.lr; + frame.lr = 0; + } + + f = runtime·findfunc(frame.pc); + if(f == nil) { + if(callback != nil) { + runtime·printf("runtime: unknown pc %p\n", frame.pc); + runtime·throw("unknown pc"); + } + return 0; + } + frame.fn = f; + + n = 0; + stk = (Stktop*)gp->stackbase; + while(n < max) { + // Typically: + // pc is the PC of the running function. + // sp is the stack pointer at that program counter. + // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown. + // stk is the stack containing sp. + // The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp. + + if(frame.pc == (uintptr)runtime·lessstack) { + // Hit top of stack segment. Unwind to next segment. + frame.pc = stk->gobuf.pc; + frame.sp = stk->gobuf.sp; + frame.lr = 0; + frame.fp = 0; + if(printing && runtime·showframe(nil, gp)) + runtime·printf("----- stack segment boundary -----\n"); + stk = (Stktop*)stk->stackbase; + + f = runtime·findfunc(frame.pc); + if(f == nil) { + runtime·printf("runtime: unknown pc %p after stack split\n", frame.pc); + if(callback != nil) + runtime·throw("unknown pc"); + } + frame.fn = f; + continue; + } + f = frame.fn; + + // Found an actual function. + // Derive frame pointer and link register. + if(frame.fp == 0) + frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc); + if(runtime·topofstack(f)) { + frame.lr = 0; + flr = nil; + } else if(f->entry == (uintptr)runtime·jmpdefer) { + // jmpdefer modifies SP/LR/PC non-atomically. + // If a profiling interrupt arrives during jmpdefer, + // the stack unwind may see a mismatched register set + // and get confused. Stop if we see PC within jmpdefer + // to avoid that confusion. + // See golang.org/issue/8153. + // This check can be deleted if jmpdefer is changed + // to restore all three atomically using pop. + if(callback != nil) + runtime·throw("traceback_arm: found jmpdefer when tracing with callback"); + frame.lr = 0; + flr = nil; + } else { + if((n == 0 && frame.sp < frame.fp) || frame.lr == 0) + frame.lr = *(uintptr*)frame.sp; + flr = runtime·findfunc(frame.lr); + if(flr == nil) { + // This happens if you get a profiling interrupt at just the wrong time. + // In that context it is okay to stop early. + // But if callback is set, we're doing a garbage collection and must + // get everything, so crash loudly. + if(callback != nil) { + runtime·printf("runtime: unexpected return pc for %s called from %p\n", runtime·funcname(f), frame.lr); + runtime·throw("unknown caller pc"); + } + } + } + + frame.varp = (byte*)frame.fp; + + // Derive size of arguments. + // Most functions have a fixed-size argument block, + // so we can use metadata about the function f. + // Not all, though: there are some variadic functions + // in package runtime and reflect, and for those we use call-specific + // metadata recorded by f's caller. + if(callback != nil || printing) { + frame.argp = (byte*)frame.fp + sizeof(uintptr); + if(f->args != ArgsSizeUnknown) + frame.arglen = f->args; + else if(flr == nil) + frame.arglen = 0; + else if(frame.lr == (uintptr)runtime·lessstack) + frame.arglen = stk->argsize; + else if((i = runtime·funcarglen(flr, frame.lr)) >= 0) + frame.arglen = i; + else { + runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n", + runtime·funcname(f), frame.lr, flr ? runtime·funcname(flr) : "?"); + if(callback != nil) + runtime·throw("invalid stack"); + frame.arglen = 0; + } + } + + // Determine function SP where deferproc would find its arguments. + // On ARM that's just the standard bottom-of-stack plus 1 word for + // the saved LR. If the previous frame was a direct call to newproc/deferproc, + // however, the SP is three words lower than normal. + // If the function has no frame at all - perhaps it just started, or perhaps + // it is a leaf with no local variables - then we cannot possibly find its + // SP in a defer, and we might confuse its SP for its caller's SP, so + // set sparg=0 in that case. + sparg = 0; + if(frame.fp != frame.sp) { + sparg = frame.sp + sizeof(uintreg); + if(wasnewproc) + sparg += 3*sizeof(uintreg); + } + + // Determine frame's 'continuation PC', where it can continue. + // Normally this is the return address on the stack, but if sigpanic + // is immediately below this function on the stack, then the frame + // stopped executing due to a trap, and frame.pc is probably not + // a safe point for looking up liveness information. In this panicking case, + // the function either doesn't return at all (if it has no defers or if the + // defers do not recover) or it returns from one of the calls to + // deferproc a second time (if the corresponding deferred func recovers). + // It suffices to assume that the most recent deferproc is the one that + // returns; everything live at earlier deferprocs is still live at that one. + frame.continpc = frame.pc; + if(waspanic) { + if(panic != nil && panic->defer->argp == (byte*)sparg) + frame.continpc = (uintptr)panic->defer->pc; + else if(defer != nil && defer->argp == (byte*)sparg) + frame.continpc = (uintptr)defer->pc; + else + frame.continpc = 0; + } + + // Unwind our local panic & defer stacks past this frame. + while(panic != nil && (panic->defer == nil || panic->defer->argp == (byte*)sparg || panic->defer->argp == NoArgs)) + panic = panic->link; + while(defer != nil && (defer->argp == (byte*)sparg || defer->argp == NoArgs)) + defer = defer->link; + + if(skip > 0) { + skip--; + goto skipped; + } + + if(pcbuf != nil) + pcbuf[n] = frame.pc; + if(callback != nil) { + if(!callback(&frame, v)) + return n; + } + if(printing) { + if(printall || runtime·showframe(f, gp)) { + // Print during crash. + // main(0x1, 0x2, 0x3) + // /home/rsc/go/src/runtime/x.go:23 +0xf + tracepc = frame.pc; // back up to CALL instruction for funcline. + if(n > 0 && frame.pc > f->entry && !waspanic) + tracepc -= sizeof(uintptr); + runtime·printf("%s(", runtime·funcname(f)); + for(i = 0; i < frame.arglen/sizeof(uintptr); i++) { + if(i >= 10) { + runtime·prints(", ..."); + break; + } + if(i != 0) + runtime·prints(", "); + runtime·printhex_c(((uintptr*)frame.argp)[i]); + } + runtime·prints(")\n"); + line = runtime·funcline(f, tracepc, &file); + runtime·printf("\t%S:%d", file, line); + if(frame.pc > f->entry) + runtime·printf(" +%p", (uintptr)(frame.pc - f->entry)); + if(g->m->throwing > 0 && gp == g->m->curg || gotraceback >= 2) + runtime·printf(" fp=%p sp=%p", frame.fp, frame.sp); + runtime·printf("\n"); + nprint++; + } + } + n++; + + skipped: + waspanic = f->entry == (uintptr)runtime·sigpanic; + wasnewproc = f->entry == (uintptr)runtime·newproc || f->entry == (uintptr)runtime·deferproc; + + // Do not unwind past the bottom of the stack. + if(flr == nil) + break; + + // Unwind to next frame. + frame.pc = frame.lr; + frame.fn = flr; + frame.lr = 0; + frame.sp = frame.fp; + frame.fp = 0; + + // sighandler saves the lr on stack before faking a call to sigpanic + if(waspanic) { + x = *(uintptr*)frame.sp; + frame.sp += sizeof(uintptr); + frame.fn = f = runtime·findfunc(frame.pc); + if(f == nil) + frame.pc = x; + else if(f->frame == 0) + frame.lr = x; + } + } + + if(pcbuf == nil && callback == nil) + n = nprint; + + // For rationale, see long comment in traceback_x86.c. + if(callback != nil && n < max && defer != nil) { + if(defer != nil) + runtime·printf("runtime: g%D: leftover defer argp=%p pc=%p\n", gp->goid, defer->argp, defer->pc); + if(panic != nil) + runtime·printf("runtime: g%D: leftover panic argp=%p pc=%p\n", gp->goid, panic->defer->argp, panic->defer->pc); + for(defer = gp->defer; defer != nil; defer = defer->link) + runtime·printf("\tdefer %p argp=%p pc=%p\n", defer, defer->argp, defer->pc); + for(panic = gp->panic; panic != nil; panic = panic->link) { + runtime·printf("\tpanic %p defer %p", panic, panic->defer); + if(panic->defer != nil) + runtime·printf(" argp=%p pc=%p", panic->defer->argp, panic->defer->pc); + runtime·printf("\n"); + } + runtime·throw("traceback has leftover defers or panics"); + } + + return n; +} + +void +runtime·printcreatedby(G *gp) +{ + int32 line; + uintptr pc, tracepc; + Func *f; + String file; + + // Show what created goroutine, except main goroutine (goid 1). + if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil && + runtime·showframe(f, gp) && gp->goid != 1) { + runtime·printf("created by %s\n", runtime·funcname(f)); + tracepc = pc; // back up to CALL instruction for funcline. + if(pc > f->entry) + tracepc -= PCQuantum; + line = runtime·funcline(f, tracepc, &file); + runtime·printf("\t%S:%d", file, line); + if(pc > f->entry) + runtime·printf(" +%p", (uintptr)(pc - f->entry)); + runtime·printf("\n"); + } +} + +void +runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G *gp) +{ + int32 n; + + if(gp->status == Gsyscall) { + // Override signal registers if blocked in system call. + pc = gp->syscallpc; + sp = gp->syscallsp; + lr = 0; + } + + // Print traceback. By default, omits runtime frames. + // If that means we print nothing at all, repeat forcing all frames printed. + n = runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, false); + if(n == 0) + runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, true); + if(n == TracebackMaxFrames) + runtime·printf("...additional frames elided...\n"); + runtime·printcreatedby(gp); +} + +// func caller(n int) (pc uintptr, file string, line int, ok bool) +int32 +runtime·callers(int32 skip, uintptr *pcbuf, int32 m) +{ + uintptr pc, sp; + + sp = runtime·getcallersp(&skip); + pc = (uintptr)runtime·getcallerpc(&skip); + + return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, false); +} + +int32 +runtime·gcallers(G *gp, int32 skip, uintptr *pcbuf, int32 m) +{ + return runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, skip, pcbuf, m, nil, nil, false); +} -- cgit v1.2.1 From 03aa2547b60be7a357335d90377409760efa6f94 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:32:33 -0400 Subject: [dev.power64] runtime: ignore rt_sigaction error if it's for SIGRTMAX. Workaround a qemu linux user space emulation bug. ref: http://git.qemu.org/?p=qemu.git;a=blob;f=linux-user/signal.c;h=1141054be2170128d6f7a340b41484b49a255936;hb=HEAD#l82 LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/124900043 --- src/pkg/runtime/os_linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/runtime/os_linux.c b/src/pkg/runtime/os_linux.c index 77754f481..b9ac8c619 100644 --- a/src/pkg/runtime/os_linux.c +++ b/src/pkg/runtime/os_linux.c @@ -312,7 +312,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"); } -- cgit v1.2.1 From 1bb9d5fdf1ca14a7a9d75e886aefa2beee188dcc Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:43:15 -0400 Subject: [dev.power64] syscall: remove duplicated constants Without this CL, simply running mkall.sh for Linux will generate duplicated constants for termios. I verified that after this CL, mkall.sh will generate almost identical z* files for linux/amd64. LGTM=rsc R=rsc, iant, r CC=golang-codereviews https://codereview.appspot.com/124990043 --- src/pkg/syscall/types_linux.go | 104 ++--------------------------------------- 1 file changed, 5 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/pkg/syscall/types_linux.go b/src/pkg/syscall/types_linux.go index e8396a41f..8ea499246 100644 --- a/src/pkg/syscall/types_linux.go +++ b/src/pkg/syscall/types_linux.go @@ -382,103 +382,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 ) -- cgit v1.2.1 From a06382c48a19d92ffc7de1ca8ba2972e3fe1212a Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:43:34 -0400 Subject: [dev.power64] debug/elf: add power64 support along with relocation test LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125910043 --- src/pkg/debug/elf/elf.go | 178 +++++++++++++++++++++ src/pkg/debug/elf/file.go | 50 +++++- src/pkg/debug/elf/file_test.go | 6 + .../testdata/go-relocation-test-gcc482-ppc64le.obj | Bin 0 -> 3016 bytes 4 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 src/pkg/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj (limited to 'src') diff --git a/src/pkg/debug/elf/elf.go b/src/pkg/debug/elf/elf.go index d622dae2a..51319c0dd 100644 --- a/src/pkg/debug/elf/elf.go +++ b/src/pkg/debug/elf/elf.go @@ -1162,6 +1162,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/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go index 7be9deaa5..5e1c47a04 100644 --- a/src/pkg/debug/elf/file.go +++ b/src/pkg/debug/elf/file.go @@ -529,6 +529,9 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error { if f.Class == ELFCLASS32 && f.Machine == EM_386 { return f.applyRelocations386(dst, rels) } + if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 { + return f.applyRelocationsPPC64(dst, rels) + } return errors.New("not implemented") } @@ -615,6 +618,51 @@ func (f *File) applyRelocations386(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 @@ -637,7 +685,7 @@ func (f *File) DWARF() (*dwarf.Data, error) { // If there's a relocation table for .debug_info, we have to process it // now otherwise the data in .debug_info is invalid for x86-64 objects. rela := f.Section(".rela.debug_info") - if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 { + if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_PPC64) { data, err := rela.Data() if err != nil { return nil, err diff --git a/src/pkg/debug/elf/file_test.go b/src/pkg/debug/elf/file_test.go index 5e4ad5c10..db9a7476c 100644 --- a/src/pkg/debug/elf/file_test.go +++ b/src/pkg/debug/elf/file_test.go @@ -260,6 +260,12 @@ var relocationTests = []relocationTest{ {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, }, }, + { + "testdata/go-relocation-test-gcc482-ppc64le.obj", + []relocationTestEntry{ + {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, + }, + }, { "testdata/go-relocation-test-clang-x86.obj", []relocationTestEntry{ diff --git a/src/pkg/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj b/src/pkg/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj new file mode 100644 index 000000000..dad744548 Binary files /dev/null and b/src/pkg/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj differ -- cgit v1.2.1 From f25a6efb362f671d502410d3bc2091246eb4d0c0 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:43:51 -0400 Subject: [dev.power64] cmd/cgo: add {ppc,power}64{,le} to pointer and int size maps LGTM=rsc R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/119640043 --- src/cmd/cgo/main.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src') 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 -- cgit v1.2.1 From 56abc625d6b36223df13be518eb28803d6a22fec Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:44:23 -0400 Subject: [dev.power64] cmd/9l: introduce the power64 linker, based loosely on 5l LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123940043 --- src/cmd/9l/Makefile | 5 + src/cmd/9l/asm.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/9l/doc.go | 16 +++ src/cmd/9l/list.c | 40 +++++++ src/cmd/9l/obj.c | 108 +++++++++++++++++ 5 files changed, 507 insertions(+) create mode 100644 src/cmd/9l/Makefile create mode 100644 src/cmd/9l/asm.c create mode 100644 src/cmd/9l/doc.go create mode 100644 src/cmd/9l/list.c create mode 100644 src/cmd/9l/obj.c (limited to 'src') 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..5aeea1b6b --- /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 = HEADR+segtext.len+segdata.filelen; + break; + ElfSym: + symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(HEADR+segrodata.filelen, INITRND)+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/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..1ab18f491 --- /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 + +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 = 4096; + break; + case Hnacl: + elfinit(); + HEADR = 0x10000; + funcalign = 16; + if(INITTEXT == -1) + INITTEXT = 0x20000; + if(INITDAT == -1) + INITDAT = 0; + if(INITRND == -1) + INITRND = 0x10000; + break; + } + if(INITDAT != 0 && INITRND != 0) + print("warning: -D0x%ux is ignored because of -R0x%ux\n", + INITDAT, INITRND); +} -- cgit v1.2.1 From c813237eb1d26b6c60d6a56ed52179428f5de06b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:44:38 -0400 Subject: [dev.power64] cmd/9l/9.out.h: introduce NFREG, REGG, REGRT1 and REGRT2 LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125990043 --- src/cmd/9l/9.out.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h index 6e4f9ee1b..e494e90ca 100644 --- a/src/cmd/9l/9.out.h +++ b/src/cmd/9l/9.out.h @@ -32,7 +32,8 @@ */ #define NSNAME 8 #define NSYM 50 -#define NREG 32 +#define NREG 32 /* number of general registers */ +#define NFREG 32 /* number of floating point registers */ #include "../ld/textflag.h" @@ -43,17 +44,20 @@ enum 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 variable for closures */ + 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 */ + FREGCVI = 27, /* floating conversion constant */ FREGZERO = 28, /* both float and double */ FREGHALF = 29, /* double */ FREGONE = 30, /* double */ -- cgit v1.2.1 From bf14642e20bb60c882eb2b9856e9513fc7e616e0 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:44:55 -0400 Subject: [dev.power64] cmd/9g: first check point LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123170043 --- src/cmd/9g/cgen.c | 1742 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/9g/galign.c | 54 ++ src/cmd/9g/gg.h | 119 ++++ src/cmd/9g/ggen.c | 1028 ++++++++++++++++++++++++++++++ src/cmd/9g/gobj.c | 240 +++++++ src/cmd/9g/gsubr.c | 1708 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/9g/opt.h | 219 +++++++ src/cmd/9g/peep.c | 94 +++ src/cmd/9g/prog.c | 138 ++++ src/cmd/9g/reg.c | 161 +++++ 10 files changed, 5503 insertions(+) create mode 100644 src/cmd/9g/cgen.c create mode 100644 src/cmd/9g/galign.c create mode 100644 src/cmd/9g/gg.h create mode 100644 src/cmd/9g/ggen.c create mode 100644 src/cmd/9g/gobj.c create mode 100644 src/cmd/9g/gsubr.c create mode 100644 src/cmd/9g/opt.h create mode 100644 src/cmd/9g/peep.c create mode 100644 src/cmd/9g/prog.c create mode 100644 src/cmd/9g/reg.c (limited to 'src') diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c new file mode 100644 index 000000000..af87b3a07 --- /dev/null +++ b/src/cmd/9g/cgen.c @@ -0,0 +1,1742 @@ +// 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 +#include +#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 OADDPTR: + 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); + nodconst(&n2, types[TUINT64], v); + gins(optoas(OCMP, types[TUINT64]), &n4, &n2); + 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) { + nodconst(&n2, types[tptr], v*w); + gins(optoas(OADD, types[tptr]), &n2, &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; + } +} + +/* + * 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) { + ginscon(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) { + ginscon(optoas(OADD, types[tptr]), n->xoffset, res); + } + break; + + case ODOTPTR: + cgen(nl, res); + cgen_checknil(res); + if(n->xoffset != 0) { + ginscon(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); + + // TODO(minux): determine the reason for failed test/floatcmp.go. + // we might need to specially handle floating point comparisons. + /*if(isfloat[nr->type->etype] && (n->op == OEQ || n->op == ONE)) { + } 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; + int32 c, odst, osrc; + int dir, align, op; + Prog *p; + 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); + //if(c >= 4) { + // regalloc(&nend, types[tptr], N); + // p = gins(AMOVD, &src, &nend); + // p->from.type = D_CONST; + // if(dir < 0) + // p->from.offset = dir; + // else + // p->from.offset = w; + //} + + // move src and dest to the end of block if necessary + if(dir < 0) { + 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; + } + + // move + // TODO: enable loops and 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, N); + raddr(&nend, p); + + 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/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 +#include +#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..2b95dc7a6 --- /dev/null +++ b/src/cmd/9g/gg.h @@ -0,0 +1,119 @@ +// Copyright 2014 The Go 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*); +void clearslim(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*); +int samaddr(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 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 gargsize(vlong); +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..999b630fa --- /dev/null +++ b/src/cmd/9g/ggen.c @@ -0,0 +1,1028 @@ +// 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 +#include +#include "gg.h" +#include "opt.h" + +//static Prog *appendpp(Prog*, int, int, vlong, int, vlong); +static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax); + +void +defframe(Prog *ptxt) +{ + uint32 frame, r0; + 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; + r0 = 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, &r0); + + // set new range + hi = n->xoffset + n->type->width; + lo = n->xoffset; + } + // zero final range + zerorange(p, frame, lo, hi, &r0); +} + +static Prog* +zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0) +{ + vlong cnt/*, i*/; + + cnt = hi - lo; + if(cnt == 0) + return p; + fprint(2, "zerorange TODO: %P, frame:%lld, lo:%lld, hi:%lld, r0: %p (%d)\n", p, frame, lo, hi, r0, *r0); + return p; +} + +/*static*/ Prog* +appendpp(Prog *p, int as, int ftype, vlong foffset, int ttype, vlong toffset) +{ + Prog *q; + q = mal(sizeof(*q)); + clearp(q); + q->as = as; + q->lineno = p->lineno; + q->from.type = ftype; + q->from.offset = foffset; + q->to.type = ttype; + 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) +{ + int32 arg; + Prog *p; + Node reg, con, reg2; + Node r1; + + if(f->type != T) + setmaxarg(f->type); + + arg = -1; + // Most functions have a fixed-size argument block, so traceback uses that during unwind. + // Not all, though: there are some variadic functions in package runtime, + // and for those we emit call-specific metadata recorded by caller. + // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub), + // so we do this for all indirect calls as well. + if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) { + arg = f->type->argwid; + if(proc == 1 || proc == 2) + arg += 3*widthptr; + } + + if(arg != -1) + gargsize(arg); + + switch(proc) { + default: + fatal("ginscall: bad proc %d", proc); + 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(®, types[TINT], D_R0); + gins(AOR, ®, ®); + } + p = gins(ABL, N, f); + afunclit(&p->to, f); + if(proc == -1 || noreturn(p)) + gins(AUNDEF, N, N); + break; + } + nodreg(®, types[tptr], D_R0+REGENV); + nodreg(&r1, types[tptr], D_R0+3); + gmove(f, ®); + reg.op = OINDREG; + gmove(®, &r1); + reg.op = OREGISTER; + ginsBL(®, &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(®, types[TINT64], D_R0+3); + nodreg(®2, types[TINT64], D_R0+4); + gmove(f, ®); + + 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, ®2); + p = gins(AMOVW, ®2, N); + p->to.type = D_OREG; + p->to.reg = REGSP; + p->to.offset = 8; + + p = gins(AMOVD, ®, 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(®, types[TINT64], D_R0+3); + p = gins(ACMP, ®, N); + p->to.type = D_REG; + p->to.reg = D_R0; + p = gbranch(ABEQ, T, +1); + cgen_ret(N); + patch(p, pc); + } + break; + } + + if(arg != -1) + gargsize(-1); +} + +/* + * 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 ../../pkg/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 +#include +#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..bb70bb7fd --- /dev/null +++ b/src/cmd/9g/gsubr.c @@ -0,0 +1,1708 @@ +// 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 +#include +#include "gg.h" +#include "../../pkg/runtime/funcdata.h" + +// TODO(rsc): Can make this bigger if we move +// the text segment up higher in 6l for all GOOS. +// At the same time, can raise StackBig in ../../pkg/runtime/stack.h. +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 +gargsize(vlong size) +{ + Node n1, n2; + + nodconst(&n1, types[TINT32], PCDATA_ArgSize); + nodconst(&n2, types[TINT32], size); + gins(APCDATA, &n1, &n2); +} + +void +ggloblsym(Sym *s, int32 width, 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; ietype]; + + 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; iop == 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; iop == 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); +} + +#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: + return 1; + case OADDR: + //if(flag_largemodel) + return 1; + break; + } + 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; + + 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; +} + +int +samaddr(Node *f, Node *t) +{ + if(f->op != t->op) + return 0; + + switch(f->op) { + case OREGISTER: + if(f->val.u.reg != t->val.u.reg) + break; + return 1; + } + return 0; +} + +/* + * generate one instruction: + * as f, t + */ +Prog* +gins(int as, Node *f, Node *t) +{ + //int32 w; + Prog *p; + Addr af, at; + + switch(as) { + case AMOVW: + case AMOVD: + case AFMOVS: + case AFMOVD: + if(f != N && t != N && samaddr(f, t)) + return nil; + break; + } + + 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(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(OADDPTR, TPTR32): + case CASE(OADD, TINT64): + case CASE(OADD, TUINT64): + case CASE(OADD, TPTR64): + case CASE(OADDPTR, 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 +#include +#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 +#include +#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 +#include +#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; zset.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"); +// } + } +} -- cgit v1.2.1 From 6097e8ef3665cc89955ec9bf1946f33ec17bc653 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:48:49 -0400 Subject: [dev.power64] runtime: manually written parts for linux/power64 and linux/power64le, checkpoint LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/122430043 --- src/pkg/runtime/arch_power64.h | 14 + src/pkg/runtime/arch_power64le.h | 14 + src/pkg/runtime/asm_power64x.s | 997 +++++++++++++++++++++++++++++++ src/pkg/runtime/atomic_power64x.s | 37 ++ src/pkg/runtime/memclr_power64x.s | 20 + src/pkg/runtime/memmove_power64x.s | 40 ++ src/pkg/runtime/rt0_linux_power64.s | 17 + src/pkg/runtime/rt0_linux_power64le.s | 14 + src/pkg/runtime/signal_linux_power64.h | 49 ++ src/pkg/runtime/signal_linux_power64le.h | 49 ++ src/pkg/runtime/signal_power64x.c | 137 +++++ src/pkg/runtime/sys_linux_power64x.s | 369 ++++++++++++ src/pkg/runtime/sys_power64x.c | 38 ++ 13 files changed, 1795 insertions(+) create mode 100644 src/pkg/runtime/arch_power64.h create mode 100644 src/pkg/runtime/arch_power64le.h create mode 100644 src/pkg/runtime/asm_power64x.s create mode 100644 src/pkg/runtime/atomic_power64x.s create mode 100644 src/pkg/runtime/memclr_power64x.s create mode 100644 src/pkg/runtime/memmove_power64x.s create mode 100644 src/pkg/runtime/rt0_linux_power64.s create mode 100644 src/pkg/runtime/rt0_linux_power64le.s create mode 100644 src/pkg/runtime/signal_linux_power64.h create mode 100644 src/pkg/runtime/signal_linux_power64le.h create mode 100644 src/pkg/runtime/signal_power64x.c create mode 100644 src/pkg/runtime/sys_linux_power64x.s create mode 100644 src/pkg/runtime/sys_power64x.c (limited to 'src') diff --git a/src/pkg/runtime/arch_power64.h b/src/pkg/runtime/arch_power64.h new file mode 100644 index 000000000..3d5b4943c --- /dev/null +++ b/src/pkg/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 = 84, + PhysPageSize = 4096, + PCQuantum = 4, + Int64Align = 8 +}; + diff --git a/src/pkg/runtime/arch_power64le.h b/src/pkg/runtime/arch_power64le.h new file mode 100644 index 000000000..d9241da98 --- /dev/null +++ b/src/pkg/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 = 84, + PhysPageSize = 4096, + PCQuantum = 4, + Int64Align = 8 +}; + diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s new file mode 100644 index 000000000..52640f407 --- /dev/null +++ b/src/pkg/runtime/asm_power64x.s @@ -0,0 +1,997 @@ +// Copyright 2014 The Go 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) + +/* + * 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,$0-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,$0-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 + MOVD 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, $0-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), R31; \ + MOVD (R31), 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), R5; \ + MOVD R1, R6; \ + ADD $(8-1), R6; \ + ADD R5, R6; \ + ADD R5, R3; \ + SUB R5, R4; \ + CMP R4, $0; \ + BEQ 9(PC); \ + SUB $1, R3; \ + SUB $1, R6; \ + ADD R3, R4; \ + CMP R3, R4; \ + BEQ 4(PC); \ + MOVBZU 1(R3), R5; \ + MOVBZU R5, 1(R6); \ + 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 + MOVD R0, 17(R0) + +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 + SUB $1, R3 + MOVD R3, R6 // store base-1 for later + 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: + MOVW $-1, R3 + MOVW 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 + SUB $1, R3 + MOVD R3, R6 // store base-1 for later + 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: + MOVW $-1, R3 + MOVW 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/pkg/runtime/atomic_power64x.s b/src/pkg/runtime/atomic_power64x.s new file mode 100644 index 000000000..c08590ac9 --- /dev/null +++ b/src/pkg/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/pkg/runtime/memclr_power64x.s b/src/pkg/runtime/memclr_power64x.s new file mode 100644 index 000000000..4a2437c20 --- /dev/null +++ b/src/pkg/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/pkg/runtime/memmove_power64x.s b/src/pkg/runtime/memmove_power64x.s new file mode 100644 index 000000000..b618f0ad7 --- /dev/null +++ b/src/pkg/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/pkg/runtime/rt0_linux_power64.s b/src/pkg/runtime/rt0_linux_power64.s new file mode 100644 index 000000000..e944bcdbf --- /dev/null +++ b/src/pkg/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/pkg/runtime/rt0_linux_power64le.s b/src/pkg/runtime/rt0_linux_power64le.s new file mode 100644 index 000000000..051815dbc --- /dev/null +++ b/src/pkg/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/pkg/runtime/signal_linux_power64.h b/src/pkg/runtime/signal_linux_power64.h new file mode 100644 index 000000000..840648920 --- /dev/null +++ b/src/pkg/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/pkg/runtime/signal_linux_power64le.h b/src/pkg/runtime/signal_linux_power64le.h new file mode 100644 index 000000000..840648920 --- /dev/null +++ b/src/pkg/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/pkg/runtime/signal_power64x.c b/src/pkg/runtime/signal_power64x.c new file mode 100644 index 000000000..89c5c7848 --- /dev/null +++ b/src/pkg/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/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s new file mode 100644 index 000000000..c0c41efa9 --- /dev/null +++ b/src/pkg/runtime/sys_linux_power64x.s @@ -0,0 +1,369 @@ +// Copyright 2014 The Go 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 // ??? why not use SYS_getrlimit + RETURN + +TEXT runtime·usleep(SB),NOSPLIT,$-8-16 + MOVW usec+0(FP), R3 + MOVD R3, R5 + MOVW $1000000, R4 + DIVD R4, R3 + MOVD R3, 0(R1) + MULLD R3, R4 + SUB R4, R5 + MOVD R5, 8(R1) + + // select(0, 0, 0, 0, &tv) + MOVW $0, R3 + MOVW $0, R4 + MOVW $0, R5 + MOVW $0, R6 + MOVD 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 + MOVW 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 + BVC 2(PC) + NEG R3, R3 + 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/pkg/runtime/sys_power64x.c b/src/pkg/runtime/sys_power64x.c new file mode 100644 index 000000000..ed8900c45 --- /dev/null +++ b/src/pkg/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"); +} + -- cgit v1.2.1 From 066e15e707888a0c707e5e4ec9dfd0fc331ebfeb Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:03 -0400 Subject: [dev.power64] syscall: the manually written parts for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/129800043 --- src/pkg/syscall/asm_linux_power64x.s | 108 ++++++++++++++++++++++++++++++ src/pkg/syscall/syscall_linux_power64x.go | 97 +++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 src/pkg/syscall/asm_linux_power64x.s create mode 100644 src/pkg/syscall/syscall_linux_power64x.go (limited to 'src') diff --git a/src/pkg/syscall/asm_linux_power64x.s b/src/pkg/syscall/asm_linux_power64x.s new file mode 100644 index 000000000..1dd23ef30 --- /dev/null +++ b/src/pkg/syscall/asm_linux_power64x.s @@ -0,0 +1,108 @@ +// Copyright 2014 The Go 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 + NEG R3, R3 + 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 + NEG R3, R3 + 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 + NEG R3, R3 + 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 + NEG R3, R3 + 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/pkg/syscall/syscall_linux_power64x.go b/src/pkg/syscall/syscall_linux_power64x.go new file mode 100644 index 000000000..dbe37c44e --- /dev/null +++ b/src/pkg/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) +//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 4096 } + +//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) +} -- cgit v1.2.1 From 1ed2159b1da09b3e3a240b3e2961873bc8509d4f Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:18 -0400 Subject: [dev.power64] syscall: auto-generated source for linux/power64 and linux/power64le. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/127170043 --- src/pkg/syscall/zerrors_linux_power64.go | 1887 ++++++++++++++++++++++++++ src/pkg/syscall/zerrors_linux_power64le.go | 1911 ++++++++++++++++++++++++++ src/pkg/syscall/zsyscall_linux_power64.go | 1931 +++++++++++++++++++++++++++ src/pkg/syscall/zsyscall_linux_power64le.go | 1931 +++++++++++++++++++++++++++ src/pkg/syscall/zsysnum_linux_power64.go | 351 +++++ src/pkg/syscall/zsysnum_linux_power64le.go | 351 +++++ src/pkg/syscall/ztypes_linux_power64.go | 602 +++++++++ src/pkg/syscall/ztypes_linux_power64le.go | 602 +++++++++ 8 files changed, 9566 insertions(+) create mode 100644 src/pkg/syscall/zerrors_linux_power64.go create mode 100644 src/pkg/syscall/zerrors_linux_power64le.go create mode 100644 src/pkg/syscall/zsyscall_linux_power64.go create mode 100644 src/pkg/syscall/zsyscall_linux_power64le.go create mode 100644 src/pkg/syscall/zsysnum_linux_power64.go create mode 100644 src/pkg/syscall/zsysnum_linux_power64le.go create mode 100644 src/pkg/syscall/ztypes_linux_power64.go create mode 100644 src/pkg/syscall/ztypes_linux_power64le.go (limited to 'src') diff --git a/src/pkg/syscall/zerrors_linux_power64.go b/src/pkg/syscall/zerrors_linux_power64.go new file mode 100644 index 000000000..9409bdba3 --- /dev/null +++ b/src/pkg/syscall/zerrors_linux_power64.go @@ -0,0 +1,1887 @@ +// 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 = 0xc + 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 + MCAST_BLOCK_SOURCE = 0x2b + MCAST_EXCLUDE = 0x0 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x2a + MCAST_JOIN_SOURCE_GROUP = 0x2e + MCAST_LEAVE_GROUP = 0x2d + MCAST_LEAVE_SOURCE_GROUP = 0x2f + MCAST_MSFILTER = 0x30 + MCAST_UNBLOCK_SOURCE = 0x2c + 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/pkg/syscall/zerrors_linux_power64le.go b/src/pkg/syscall/zerrors_linux_power64le.go new file mode 100644 index 000000000..de3b442a1 --- /dev/null +++ b/src/pkg/syscall/zerrors_linux_power64le.go @@ -0,0 +1,1911 @@ +// 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 = 0xc + 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 + MCAST_BLOCK_SOURCE = 0x2b + MCAST_EXCLUDE = 0x0 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x2a + MCAST_JOIN_SOURCE_GROUP = 0x2e + MCAST_LEAVE_GROUP = 0x2d + MCAST_LEAVE_SOURCE_GROUP = 0x2f + MCAST_MSFILTER = 0x30 + MCAST_UNBLOCK_SOURCE = 0x2c + 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/pkg/syscall/zsyscall_linux_power64.go b/src/pkg/syscall/zsyscall_linux_power64.go new file mode 100644 index 000000000..5f8feccc5 --- /dev/null +++ b/src/pkg/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_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + uid = int(r0) + 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/pkg/syscall/zsyscall_linux_power64le.go b/src/pkg/syscall/zsyscall_linux_power64le.go new file mode 100644 index 000000000..5f8feccc5 --- /dev/null +++ b/src/pkg/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_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + uid = int(r0) + 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/pkg/syscall/zsysnum_linux_power64.go b/src/pkg/syscall/zsysnum_linux_power64.go new file mode 100644 index 000000000..0567fd0ea --- /dev/null +++ b/src/pkg/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/pkg/syscall/zsysnum_linux_power64le.go b/src/pkg/syscall/zsysnum_linux_power64le.go new file mode 100644 index 000000000..52c63e3d3 --- /dev/null +++ b/src/pkg/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/pkg/syscall/ztypes_linux_power64.go b/src/pkg/syscall/ztypes_linux_power64.go new file mode 100644 index 000000000..5a34068bc --- /dev/null +++ b/src/pkg/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 + Anon0 [8]byte + Anon1 [8]byte + Anon2 [8]byte + Anon3 [8]byte + Anon4 [8]byte + Anon5 [8]byte + Anon6 [8]byte + Anon7 [8]byte + Anon8 [8]byte + Anon9 [8]byte + Anon10 [8]byte + Anon11 [8]byte + Anon12 [8]byte + Anon13 [8]byte +} + +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/pkg/syscall/ztypes_linux_power64le.go b/src/pkg/syscall/ztypes_linux_power64le.go new file mode 100644 index 000000000..647755cb1 --- /dev/null +++ b/src/pkg/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 + Anon0 [8]byte + Anon1 [8]byte + Anon2 [8]byte + Anon3 [8]byte + Anon4 [8]byte + Anon5 [8]byte + Anon6 [8]byte + Anon7 [8]byte + Anon8 [8]byte + Anon9 [8]byte + Anon10 [8]byte + Anon11 [8]byte + Anon12 [8]byte + Anon13 [8]byte +} + +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 +) -- cgit v1.2.1 From 9997bca74c211b65cb2e27d3f1c624572767e566 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:31 -0400 Subject: [dev.power64] syscall: script changes for power64 LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123290043 --- src/pkg/syscall/mkall.sh | 19 +++++++++++++++++-- src/pkg/syscall/mkerrors.sh | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pkg/syscall/mkall.sh b/src/pkg/syscall/mkall.sh index 886db133c..ac1c20f03 100755 --- a/src/pkg/syscall/mkall.sh +++ b/src/pkg/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" @@ -244,7 +259,7 @@ esac case "$GOOS" in windows) echo "GOOS= GOARCH= go build mksyscall_windows.go" - echo "./mksyscall_windows syscall_windows.go security_windows.go syscall_$GOOSARCH.go |gofmt >zsyscall_$GOOSARCH.go" + echo "./mksyscall_windows syscall_windows.go security_windows.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go" echo "rm -f ./mksyscall_windows" ;; *) @@ -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/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh index cf0afe0bd..4711f307a 100755 --- a/src/pkg/syscall/mkerrors.sh +++ b/src/pkg/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} # contains ELF_ARCH, etc. $2 !~ /^ETH_/ && $2 !~ /^EPROC_/ && -- cgit v1.2.1 From c4a99d44b847065ae72e91a928faac139e92acea Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:41 -0400 Subject: [dev.power64] os/signal: support for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121580043 --- src/pkg/os/signal/sig.s | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/os/signal/sig.s b/src/pkg/os/signal/sig.s index f860924aa..c324fcda4 100644 --- a/src/pkg/os/signal/sig.s +++ b/src/pkg/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 "../../../cmd/ld/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) -- cgit v1.2.1 From 83f7928e7b90d6c414110ef580953a7da7f15894 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:52 -0400 Subject: [dev.power64] runtime: changes to the portable part for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121580044 --- src/pkg/runtime/cgocall.c | 8 ++++++++ src/pkg/runtime/panic.c | 6 +++--- src/pkg/runtime/proc.c | 4 ++-- src/pkg/runtime/stack.c | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c index aa4cf5ee5..2149d7c72 100644 --- a/src/pkg/runtime/cgocall.c +++ b/src/pkg/runtime/cgocall.c @@ -228,6 +228,14 @@ struct CallbackArgs #define CBARGS (CallbackArgs*)((byte*)g->m->g0->sched.sp+4*sizeof(void*)) #endif +// Unimplemented on power64 or power64le +#ifdef GOARCH_power64 +#define CBARGS (CallbackArgs*)(nil) +#endif +#ifdef GOARCH_power64le +#define CBARGS (CallbackArgs*)(nil) +#endif + void runtime·cgocallbackg1(void); #pragma textflag NOSPLIT diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c index af8bb1bc0..748c4174b 100644 --- a/src/pkg/runtime/panic.c +++ b/src/pkg/runtime/panic.c @@ -86,7 +86,7 @@ runtime·deferproc(int32 siz, FuncVal *fn, ...) d = newdefer(siz); d->fn = fn; d->pc = runtime·getcallerpc(&siz); - if(thechar == '5') + if(thechar == '5' || thechar == '9') d->argp = (byte*)(&fn+2); // skip caller's saved link register else d->argp = (byte*)(&fn+1); @@ -309,7 +309,7 @@ recovery(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); @@ -514,10 +514,10 @@ runtime·canpanic(G *gp) void runtime·throw(int8 *s) { + runtime·printf("fatal error: %s\n", s); if(g->m->throwing == 0) g->m->throwing = 1; runtime·startpanic(); - runtime·printf("fatal error: %s\n", s); runtime·dopanic(0); *(int32*)0 = 0; // not reached runtime·exit(1); // even more not reached diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index 26e687e3b..23513e1a7 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -1833,7 +1833,7 @@ runtime·newproc(int32 siz, FuncVal* fn, ...) { byte *argp; - if(thechar == '5') + if(thechar == '5' || thechar == '9') argp = (byte*)(&fn+2); // skip caller's saved LR else argp = (byte*)(&fn+1); @@ -1880,7 +1880,7 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp sp = (byte*)newg->stackbase; 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/pkg/runtime/stack.c b/src/pkg/runtime/stack.c index 0a806e8fa..49ecd6cc3 100644 --- a/src/pkg/runtime/stack.c +++ b/src/pkg/runtime/stack.c @@ -969,7 +969,7 @@ runtime·newstack(void) while(dst < dstend) *dst++ = *src++; } - if(thechar == '5') { + if(thechar == '5' || thechar == '9') { // caller would have saved its LR below args. sp -= sizeof(void*); *(void**)sp = nil; -- cgit v1.2.1 From f69f93cdae33776a956d7b3ce0048093b5a8845d Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:03 -0400 Subject: [dev.power64] runtime: move noasm_arm.goc to noasm.goc LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121590043 --- src/pkg/runtime/noasm.goc | 76 +++++++++++++++++++++++++++++++++++++++++++ src/pkg/runtime/noasm_arm.goc | 74 ----------------------------------------- 2 files changed, 76 insertions(+), 74 deletions(-) create mode 100644 src/pkg/runtime/noasm.goc delete mode 100644 src/pkg/runtime/noasm_arm.goc (limited to 'src') diff --git a/src/pkg/runtime/noasm.goc b/src/pkg/runtime/noasm.goc new file mode 100644 index 000000000..496667729 --- /dev/null +++ b/src/pkg/runtime/noasm.goc @@ -0,0 +1,76 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Routines that are implemented in assembly in asm_{amd64,386}.s +// but are implemented in C for arm. + +// +build arm power64 power64le + +package runtime +#include "runtime.h" +#include "../../cmd/ld/textflag.h" + +#pragma textflag NOSPLIT +func cmpstring(s1 String, s2 String) (v int) { + uintgo i, l; + byte c1, c2; + + l = s1.len; + if(s2.len < l) + l = s2.len; + for(i=0; i c2) { + v = +1; + goto done; + } + } + if(s1.len < s2.len) { + v = -1; + goto done; + } + if(s1.len > s2.len) { + v = +1; + goto done; + } + v = 0; + done:; +} + +#pragma textflag NOSPLIT +func bytes·Compare(s1 Slice, s2 Slice) (v int) { + uintgo i, l; + byte c1, c2; + + l = s1.len; + if(s2.len < l) + l = s2.len; + for(i=0; i c2) { + v = +1; + goto done; + } + } + if(s1.len < s2.len) { + v = -1; + goto done; + } + if(s1.len > s2.len) { + v = +1; + goto done; + } + v = 0; + done:; +} diff --git a/src/pkg/runtime/noasm_arm.goc b/src/pkg/runtime/noasm_arm.goc deleted file mode 100644 index fe3591e8a..000000000 --- a/src/pkg/runtime/noasm_arm.goc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Routines that are implemented in assembly in asm_{amd64,386}.s -// but are implemented in C for arm. - -package runtime -#include "runtime.h" -#include "../../cmd/ld/textflag.h" - -#pragma textflag NOSPLIT -func cmpstring(s1 String, s2 String) (v int) { - uintgo i, l; - byte c1, c2; - - l = s1.len; - if(s2.len < l) - l = s2.len; - for(i=0; i c2) { - v = +1; - goto done; - } - } - if(s1.len < s2.len) { - v = -1; - goto done; - } - if(s1.len > s2.len) { - v = +1; - goto done; - } - v = 0; - done:; -} - -#pragma textflag NOSPLIT -func bytes·Compare(s1 Slice, s2 Slice) (v int) { - uintgo i, l; - byte c1, c2; - - l = s1.len; - if(s2.len < l) - l = s2.len; - for(i=0; i c2) { - v = +1; - goto done; - } - } - if(s1.len < s2.len) { - v = -1; - goto done; - } - if(s1.len > s2.len) { - v = +1; - goto done; - } - v = 0; - done:; -} -- cgit v1.2.1 From 13b840a66623ed19c3e5c31cb928138258a489ba Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:18 -0400 Subject: [dev.power64] runtime: auto-generated headers for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123280043 --- src/pkg/runtime/defs_linux_power64.h | 211 +++++++++++++++++++++++++++++++++ src/pkg/runtime/defs_linux_power64le.h | 211 +++++++++++++++++++++++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 src/pkg/runtime/defs_linux_power64.h create mode 100644 src/pkg/runtime/defs_linux_power64le.h (limited to 'src') diff --git a/src/pkg/runtime/defs_linux_power64.h b/src/pkg/runtime/defs_linux_power64.h new file mode 100644 index 000000000..41db45ca1 --- /dev/null +++ b/src/pkg/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 Sigaltstack Sigaltstack; +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 Sigaltstack { + 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; + Sigaltstack uc_stack; + Usigset uc_sigmask; + Usigset __unused[15]; + Sigcontext uc_mcontext; +}; + + +#pragma pack off diff --git a/src/pkg/runtime/defs_linux_power64le.h b/src/pkg/runtime/defs_linux_power64le.h new file mode 100644 index 000000000..41db45ca1 --- /dev/null +++ b/src/pkg/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 Sigaltstack Sigaltstack; +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 Sigaltstack { + 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; + Sigaltstack uc_stack; + Usigset uc_sigmask; + Usigset __unused[15]; + Sigcontext uc_mcontext; +}; + + +#pragma pack off -- cgit v1.2.1 From 486ef78fc761b7695d648aed322d2d90bf9be3c0 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:30 -0400 Subject: [dev.power64] runtime: add defs3_linux.go to generate defs_linux_power64{,le}.h LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/128070043 --- src/pkg/runtime/defs1_linux.go | 6 ++++-- src/pkg/runtime/defs3_linux.go | 43 ++++++++++++++++++++++++++++++++++++++++++ src/pkg/runtime/defs_linux.go | 11 ++++++----- 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 src/pkg/runtime/defs3_linux.go (limited to 'src') diff --git a/src/pkg/runtime/defs1_linux.go b/src/pkg/runtime/defs1_linux.go index 451817a67..c0b510ac4 100644 --- a/src/pkg/runtime/defs1_linux.go +++ b/src/pkg/runtime/defs1_linux.go @@ -15,12 +15,14 @@ package runtime /* #include #include +#include */ 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/pkg/runtime/defs3_linux.go b/src/pkg/runtime/defs3_linux.go new file mode 100644 index 000000000..eb65f9d1e --- /dev/null +++ b/src/pkg/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 +#include +*/ +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 Sigaltstack 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/pkg/runtime/defs_linux.go b/src/pkg/runtime/defs_linux.go index 8657dbb0e..553366a50 100644 --- a/src/pkg/runtime/defs_linux.go +++ b/src/pkg/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 #define size_t __kernel_size_t #include @@ -28,7 +29,7 @@ package runtime #include #include #include -#undef size_t +#include */ 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 -- cgit v1.2.1 From b48228a2e045e5fbb48a8450d6d00695d9b1921e Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:40 -0400 Subject: [dev.power64] math: implement Abs, add power64/power64le forwarding assembly functions LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/119670043 --- src/pkg/math/abs_power64x.s | 14 +++++++ src/pkg/math/stubs_power64x.s | 91 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/pkg/math/abs_power64x.s create mode 100644 src/pkg/math/stubs_power64x.s (limited to 'src') diff --git a/src/pkg/math/abs_power64x.s b/src/pkg/math/abs_power64x.s new file mode 100644 index 000000000..8fd8020f9 --- /dev/null +++ b/src/pkg/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 "../../cmd/ld/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/pkg/math/stubs_power64x.s b/src/pkg/math/stubs_power64x.s new file mode 100644 index 000000000..0cb86144a --- /dev/null +++ b/src/pkg/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) -- cgit v1.2.1 From 2ba511778ddd2f026b998bce87a30db71b1bcdd2 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:51 -0400 Subject: [dev.power64] sync/atomic: implement for asm_power64x.s LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/124220043 --- src/pkg/sync/atomic/asm_power64x.s | 184 +++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/pkg/sync/atomic/asm_power64x.s (limited to 'src') diff --git a/src/pkg/sync/atomic/asm_power64x.s b/src/pkg/sync/atomic/asm_power64x.s new file mode 100644 index 000000000..bdb1dcff4 --- /dev/null +++ b/src/pkg/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) -- cgit v1.2.1 From 81f022f35e9234ce3b6945f029bb363c3e4b5b15 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:51:01 -0400 Subject: [dev.power64] cmd/9g: implement zerorange LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121540043 --- src/cmd/9g/ggen.c | 69 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c index 999b630fa..09f51536a 100644 --- a/src/cmd/9g/ggen.c +++ b/src/cmd/9g/ggen.c @@ -9,13 +9,13 @@ #include "gg.h" #include "opt.h" -//static Prog *appendpp(Prog*, int, int, vlong, int, vlong); -static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax); +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, r0; + uint32 frame; Prog *p; vlong hi, lo; NodeList *l; @@ -34,7 +34,6 @@ defframe(Prog *ptxt) // when it looks for pointers. p = ptxt; lo = hi = 0; - r0 = 0; // iterate through declarations - they are sorted in decreasing xoffset order. for(l=curfn->dcl; l != nil; l = l->next) { n = l->n; @@ -51,43 +50,69 @@ defframe(Prog *ptxt) continue; } // zero old range - p = zerorange(p, frame, lo, hi, &r0); + 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, &r0); + zerorange(p, frame, lo, hi); } static Prog* -zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0) +zerorange(Prog *p, vlong frame, vlong lo, vlong hi) { - vlong cnt/*, i*/; + vlong cnt, i; + Prog *p1; + Node *f; cnt = hi - lo; if(cnt == 0) return p; - fprint(2, "zerorange TODO: %P, frame:%lld, lo:%lld, hi:%lld, r0: %p (%d)\n", p, frame, lo, hi, r0, *r0); + 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, vlong foffset, int ttype, vlong toffset) +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.offset = foffset; - q->to.type = ttype; - q->to.offset = toffset; - q->link = p->link; - p->link = q; - return 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. -- cgit v1.2.1 From 92dd375ec14ba68e5856553f3d0042bf8267ec52 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:57:32 -0400 Subject: [dev.power64] cmd/gc: handle thechar=='9', disable nilopt() for now LGTM=rsc R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/121630043 --- src/cmd/gc/pgen.c | 4 ++-- src/cmd/gc/popt.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index cabba6824..5ac46e774 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -428,7 +428,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); @@ -485,7 +485,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(®, types[tptr], n); cgen(n, ®); gins(ACHECKNIL, ®, N); diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c index c8d60c5ad..4c75e6c26 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; -- cgit v1.2.1 From 066d5dbbec0cfbf73326128acd10198d60fbe4e3 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:57:45 -0400 Subject: [dev.power64] liblink: support stack split, long conditional branches LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123300043 --- src/liblink/asm9.c | 48 +++++++---- src/liblink/list9.c | 5 +- src/liblink/obj9.c | 236 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 243 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 647e6f178..886edf347 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -307,6 +307,7 @@ static Optab optab[] = { { 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 }, @@ -436,6 +437,8 @@ static Optab optab[] = { { 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 + { ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 }, + { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, }; @@ -475,10 +478,10 @@ static char xcmp[C_NCLASS][C_NCLASS]; void span9(Link *ctxt, LSym *cursym) { - Prog *p; + Prog *p, *q; Optab *o; int m, bflag; - vlong c; + vlong c, otxt; int32 out[6], i, j; uchar *bp, *cast; @@ -515,38 +518,39 @@ span9(Link *ctxt, LSym *cursym) * 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; p != nil; p = p->link) { + for(p = cursym->text->link; p != nil; p = p->link) { p->pc = c; o = oplook(ctxt, p); -/* very large branches + // very large conditional branches if((o->type == 16 || o->type == 17) && p->pcond) { otxt = p->pcond->pc - c; - if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { - q = prg(); + 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 = prg(); + 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); + //addnop(p->link); + //addnop(p); bflag = 1; } } -*/ + m = o->size; if(m == 0) { if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA) @@ -1398,6 +1402,14 @@ loadu32(int r, vlong d) 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) { @@ -1548,7 +1560,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) rel->siz = 4; rel->sym = p->to.sym; v += p->to.offset; - rel->add = o1 | ((v & 0x03FFFFFC) >> 2); + if(v & 03) { + ctxt->diag("odd branch target address\n%P", p); + v &= ~03; + } + rel->add = o1 | (v & 0x03FFFFFC); rel->type = R_CALLPOWER; } break; @@ -1673,7 +1689,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) 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, (d>>16)+(d&0x8000)?1:0); + 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); } @@ -2199,7 +2215,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) case 74: v = regoff(ctxt, &p->to); - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, (v>>16)+(v&0x8000)?1:0); + 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); @@ -2207,7 +2223,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) case 75: v = regoff(ctxt, &p->from); - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, (v>>16)+(v&0x8000)?1:0); + 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); @@ -2215,7 +2231,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) case 76: v = regoff(ctxt, &p->from); - o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, (v>>16)+(v&0x8000)?1:0); + 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); @@ -2589,6 +2605,8 @@ opirr(Link *ctxt, int a) 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; diff --git a/src/liblink/list9.c b/src/liblink/list9.c index 3299d269a..9700a1684 100644 --- a/src/liblink/list9.c +++ b/src/liblink/list9.c @@ -345,7 +345,10 @@ Rconv(Fmt *fp) int r; r = va_arg(fp->args, int); - sprint(str, "r%d", r); + if(r < NREG) + sprint(str, "r%d", r); + else + sprint(str, "f%d", r-NREG); return fmtstrcpy(fp, str); } diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 63f5b59b0..90145a46f 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -33,6 +33,7 @@ #include #include "../cmd/9l/9.out.h" #include "../pkg/runtime/stack.h" +#include "../pkg/runtime/funcdata.h" static Prog zprg = { .as = AGOK, @@ -417,6 +418,9 @@ addstacksplit(Link *ctxt, LSym *cursym) 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 */ @@ -424,7 +428,7 @@ addstacksplit(Link *ctxt, LSym *cursym) mov = AMOVDU; aoffset = -autosize; } else { - q = ctxt->arch->prg(); + q = appendp(ctxt, p); q->as = AADD; q->lineno = p->lineno; q->from.type = D_CONST; @@ -432,9 +436,6 @@ addstacksplit(Link *ctxt, LSym *cursym) q->to.type = D_REG; q->to.reg = REGSP; q->spadj = +autosize; - - q->link = p->link; - p->link = q; } } else if(!(cursym->text->mark & LEAF)) { @@ -451,33 +452,54 @@ addstacksplit(Link *ctxt, LSym *cursym) break; } - if(!(p->reg & NOSPLIT)) - p = stacksplit(ctxt, p, autosize, !(cursym->text->reg&NEEDCTXT)); // emit split check - - q1 = ctxt->arch->prg(); - q1->as = mov; - q1->lineno = p->lineno; - q1->from.type = D_REG; - q1->from.reg = REGTMP; - q1->to.type = D_OREG; - q1->to.offset = aoffset; - q1->to.reg = REGSP; - if(q1->as == AMOVDU) - q1->spadj = -aoffset; + 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; - q1->link = q->link; - q->link = q1; + 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) { + // g->panicwrap += autosize; + // MOVWZ panicwrap_offset(g), R3 + // ADD $autosize, R3 + // MOVWZ R3, panicwrap_offset(g) + p = appendp(ctxt, q); + p->as = AMOVWZ; + p->from.type = D_OREG; + p->from.reg = REGG; + p->from.offset = 2*ctxt->arch->ptrsize; + p->to.type = D_REG; + p->to.reg = 3; - q1 = ctxt->arch->prg(); - q1->as = AMOVD; - q1->lineno = p->lineno; - q1->from.type = D_SPR; - q1->from.offset = D_LR; - q1->to.type = D_REG; - q1->to.reg = REGTMP; + p = appendp(ctxt, p); + p->as = AADD; + p->from.type = D_CONST; + p->from.offset = autosize; + p->to.type = D_REG; + p->to.reg = 3; + + p = appendp(ctxt, p); + p->as = AMOVWZ; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_OREG; + p->to.reg = REGG; + p->to.offset = 2*ctxt->arch->ptrsize; + } - q1->link = q->link; - q->link = q1; break; case ARETURN: @@ -485,6 +507,11 @@ addstacksplit(Link *ctxt, LSym *cursym) 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; @@ -612,8 +639,157 @@ addstacksplit(Link *ctxt, LSym *cursym) static Prog* stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) { - // TODO(minux): add stack split prologue - USED(ctxt); USED(p); USED(framesize); USED(noctxt); + int32 arg; + Prog *q, *q1; + + // MOVD g_stackguard(g), R3 + p = appendp(ctxt, p); + p->as = AMOVD; + p->from.type = D_OREG; + p->from.reg = REGG; + p->to.type = D_REG; + p->to.reg = 3; + + q = nil; + if(framesize <= StackSmall) { + // small stack: SP < stackguard + // CMP stackguard, SP + p = appendp(ctxt, p); + p->as = ACMPU; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_REG; + p->to.reg = REGSP; + } else if(framesize <= StackBig) { + // large stack: SP-framesize < stackguard-StackSmall + // ADD $-framesize, SP, R4 + // CMP stackguard, R4 + p = appendp(ctxt, p); + p->as = AADD; + p->from.type = D_CONST; + p->from.offset = -framesize; + p->reg = REGSP; + p->to.type = D_REG; + p->to.reg = 4; + + p = appendp(ctxt, p); + p->as = ACMPU; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_REG; + p->to.reg = 4; + } else { + // Such a large stack we need to protect against wraparound. + // If SP is close to zero: + // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall) + // The +StackGuard on both sides is required to keep the left side positive: + // SP is allowed to be slightly below stackguard. See stack.h. + // + // Preemption sets stackguard to StackPreempt, a very large value. + // That breaks the math above, so we have to check for that explicitly. + // // stackguard is R3 + // CMP R3, $StackPreempt + // BEQ label-of-call-to-morestack + // ADD $StackGuard, SP, R4 + // SUB R3, R4 + // MOVD $(framesize+(StackGuard-StackSmall)), R31 + // CMP R4, R31 + p = appendp(ctxt, p); + p->as = ACMP; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_CONST; + p->to.offset = StackPreempt; + + q = p = appendp(ctxt, p); + p->as = ABEQ; + p->to.type = D_BRANCH; + + p = appendp(ctxt, p); + p->as = AADD; + p->from.type = D_CONST; + p->from.offset = StackGuard; + p->reg = REGSP; + p->to.type = D_REG; + p->to.reg = 4; + + p = appendp(ctxt, p); + p->as = ASUB; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_REG; + p->to.reg = 4; + + p = appendp(ctxt, p); + p->as = AMOVD; + p->from.type = D_CONST; + p->from.offset = framesize + StackGuard - StackSmall; + p->to.type = D_REG; + p->to.reg = REGTMP; + + p = appendp(ctxt, p); + p->as = ACMPU; + p->from.type = D_REG; + p->from.reg = 4; + p->to.type = D_REG; + p->to.reg = REGTMP; + } + + // q1: BLT done + q1 = p = appendp(ctxt, p); + p->as = ABLT; + p->to.type = D_BRANCH; + + // MOVD $framesize, R3 + p = appendp(ctxt, p); + p->as = AMOVD; + p->from.type = D_CONST; + p->from.offset = framesize; + p->to.type = D_REG; + p->to.reg = 3; + if(q) + q->pcond = p; + + // MOVD $args, R4 + p = appendp(ctxt, p); + p->as = AMOVD; + p->from.type = D_CONST; + arg = (ctxt->cursym->text->to.offset >> 32) & 0xffffffffull; + if(arg == 1) // special marker for known 0 + arg = 0; + else if(arg == ArgsSizeUnknown) + ctxt->diag("%s: arg size unknown, but split stack", ctxt->cursym->name); + if(arg&3) // ???? + ctxt->diag("misaligned argument size in stack split: %d", arg); + p->from.offset = arg; + p->to.type = D_REG; + p->to.reg = 4; + + // 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; + 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; } -- cgit v1.2.1 From 7bdf31242ed0e8125e3896669da76ed0d52589df Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:57:54 -0400 Subject: [dev.power64] cmd/9l: remove MAXIO (fix build) LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/124270043 --- src/cmd/9l/l.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/cmd/9l/l.h b/src/cmd/9l/l.h index d787f1384..dda741c56 100644 --- a/src/cmd/9l/l.h +++ b/src/cmd/9l/l.h @@ -54,7 +54,6 @@ enum { FPCHIP = 1, STRINGSZ = 200, - MAXIO = 8192, MAXHIST = 20, /* limit of path elements for history symbols */ DATBLK = 1024, NHASH = 10007, -- cgit v1.2.1 From aa440488c960620581115b2a708fb41105e596c2 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:58:05 -0400 Subject: [dev.power64] cmd/9c: fix endian issue in integer to floating point conversion LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/129850043 --- src/cmd/9c/txt.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cmd/9c/txt.c b/src/cmd/9c/txt.c index 345976cf2..84aeb4d8a 100644 --- a/src/cmd/9c/txt.c +++ b/src/cmd/9c/txt.c @@ -962,13 +962,22 @@ gmove(Node *f, Node *t) regsalloc(&fxrat, t); /* should be type float */ gins(AMOVW, nodconst(0x43300000L), &fxc0); gins(AMOVW, f, &fxc2); - gins(AMOVW, &fxc0, &fxrat); gins(AXOR, nodconst(0x80000000L), &fxc2); - fxc1 = fxrat; - fxc1.type = nodrat->type; - fxc1.etype = nodrat->etype; - fxc1.xoffset += SZ_LONG; - gins(AMOVW, &fxc2, &fxc1); + 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 */ -- cgit v1.2.1 From ee6a4ba096d22a0f44f636278e47eb62a6fb8821 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:22:27 -0400 Subject: [dev.power64] cmd/9g, cmd/gc, cmd/ld: fix build. 1. disable nonsplit stack overflow check 2. disable OLROT recognition 3. emit correct instructions for adding offsets to an address LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/123310043 --- src/cmd/9g/cgen.c | 18 +++++++++++++++--- src/cmd/gc/walk.c | 3 +++ src/cmd/ld/lib.c | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index af87b3a07..3644ebf8f 100644 --- a/src/cmd/9g/cgen.c +++ b/src/cmd/9g/cgen.c @@ -788,6 +788,18 @@ agenr(Node *n, Node *a, Node *res) } } +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; @@ -901,7 +913,7 @@ agen(Node *n, Node *res) } cgen(n->heapaddr, res); if(n->xoffset != 0) { - ginscon(optoas(OADD, types[tptr]), n->xoffset, res); + ginsadd(optoas(OADD, types[tptr]), n->xoffset, res); } break; @@ -913,7 +925,7 @@ agen(Node *n, Node *res) case ODOT: agen(nl, res); if(n->xoffset != 0) { - ginscon(optoas(OADD, types[tptr]), n->xoffset, res); + ginsadd(optoas(OADD, types[tptr]), n->xoffset, res); } break; @@ -921,7 +933,7 @@ agen(Node *n, Node *res) cgen(nl, res); cgen_checknil(res); if(n->xoffset != 0) { - ginscon(optoas(OADD, types[tptr]), n->xoffset, res); + ginsadd(optoas(OADD, types[tptr]), n->xoffset, res); } break; } diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index be929e99e..cb1873f85 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -3217,6 +3217,9 @@ walkrotate(Node **np) int w, sl, sr, s; Node *l, *r; Node *n; + + if(thechar == '9') + return; n = *np; diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index bdba21747..b4134da36 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -1045,6 +1045,9 @@ dostkcheck(void) { Chain ch; LSym *s; + + if(thechar == '9') + return; morestack = linklookup(ctxt, "runtime.morestack", 0); newstack = linklookup(ctxt, "runtime.newstack", 0); -- cgit v1.2.1 From 663439491633ff0aa013d32de4a67c97483ac926 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 12 Aug 2014 21:38:50 -0400 Subject: [dev.power64] hash/crc32: use portable castagnoli on power64 LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/128110044 --- src/pkg/hash/crc32/crc32_generic.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/hash/crc32/crc32_generic.go b/src/pkg/hash/crc32/crc32_generic.go index c3fdcd685..1c7f806c6 100644 --- a/src/pkg/hash/crc32/crc32_generic.go +++ b/src/pkg/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 -- cgit v1.2.1 From 83018e2fdd2eaf0f295a2575ba195abfaee2b69b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 12 Aug 2014 21:41:42 -0400 Subject: [dev.power64] cmd/9a: use new flag parser Copy main from 6a. Fixes various things, but the main thing is the use of the new flag parser. The go command expects to be able to use -trimpath and not have it be interpreted as -t rimpath. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/126100043 --- src/cmd/9a/lex.c | 129 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c index a9ad01eac..116618f25 100644 --- a/src/cmd/9a/lex.c +++ b/src/cmd/9a/lex.c @@ -50,30 +50,54 @@ systemtype(int sys) #endif } +int +pathchar(void) +{ + return '/'; +} + int Lconv(Fmt *fp) { return linklinefmt(ctxt, fp); } -int -pathchar(void) +void +dodef(char *p) { - return '/'; + 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; - int c; thechar = '9'; - thestring = getgoarch(); - if(strcmp(thestring, "power64le") == 0) - ctxt = linknew(&linkpower64le); - else - ctxt = linknew(&linkpower64); + 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; Binit(&bstdout, 1, OWRITE); @@ -85,79 +109,57 @@ main(int argc, char *argv[]) cinit(); outfile = 0; setinclude("."); - ARGBEGIN { - default: - c = ARGC(); - if(c >= 0 && c < sizeof(debug)) - debug[c] = 1; - break; - - case 'o': - outfile = ARGF(); - break; - - case 'D': - p = ARGF(); - if(p) { - if (nDlist%8 == 0) - Dlist = allocn(Dlist, nDlist*sizeof(char *), - 8*sizeof(char *)); - Dlist[nDlist++] = p; - } - break; - - case 'I': - p = ARGF(); - setinclude(p); - break; - - case 'S': - ctxt->debugasm++; - break; - } ARGEND - if(*argv == 0) { - print("usage: %ca [-options] file.s\n", thechar); - errorexit(); - } + + 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[100], incfile[20], *p; + char *ofile, *p; int i, of; + ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) strcpy(ofile, file); - if(p = strrchr(ofile, pathchar())) { + p = utfrrune(ofile, pathchar()); + if(p) { include[0] = ofile; *p++ = 0; } else p = ofile; if(outfile == 0) { outfile = p; - if(p = strrchr(outfile, '.')) - if(p[1] == 's' && p[2] == 0) - p[0] = 0; - p = strrchr(outfile, 0); - p[0] = '.'; - p[1] = thechar; - p[2] = 0; - } - p = getenv("INCLUDE"); - if(p) { - setinclude(p); - } else { - if(systemtype(Plan9)) { - sprint(incfile,"/%s/include", thestring); - setinclude(strdup(incfile)); - } + 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); @@ -166,10 +168,9 @@ assemble(char *file) errorexit(); } Binit(&obuf, of, OWRITE); - Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); - Bprint(&obuf, "\n!\n"); + Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); + Bprint(&obuf, "!\n"); - pass = 1; for(pass = 1; pass <= 2; pass++) { nosched = 0; pinit(file); -- cgit v1.2.1 From ff15480178aaa5a4802ade13e0aca7d931853d0e Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:43:31 -0400 Subject: [dev.power64] reflect: add assembly stubs LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/126090043 --- src/pkg/reflect/asm_power64x.s | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/pkg/reflect/asm_power64x.s (limited to 'src') diff --git a/src/pkg/reflect/asm_power64x.s b/src/pkg/reflect/asm_power64x.s new file mode 100644 index 000000000..78839075c --- /dev/null +++ b/src/pkg/reflect/asm_power64x.s @@ -0,0 +1,50 @@ +// Copyright 2012 The Go 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" + +// 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 + +// Stubs to give reflect package access to runtime services +// TODO: should probably be done another way. +TEXT ·makemap(SB),NOSPLIT,$0-0 + BR runtime·reflect_makemap(SB) +TEXT ·mapaccess(SB),NOSPLIT,$0-0 + BR runtime·reflect_mapaccess(SB) +TEXT ·mapassign(SB),NOSPLIT,$0-0 + BR runtime·reflect_mapassign(SB) +TEXT ·mapdelete(SB),NOSPLIT,$0-0 + BR runtime·reflect_mapdelete(SB) +TEXT ·mapiterinit(SB),NOSPLIT,$0-0 + BR runtime·reflect_mapiterinit(SB) +TEXT ·mapiterkey(SB),NOSPLIT,$0-0 + BR runtime·reflect_mapiterkey(SB) +TEXT ·mapiternext(SB),NOSPLIT,$0-0 + BR runtime·reflect_mapiternext(SB) +TEXT ·maplen(SB),NOSPLIT,$0-0 + BR runtime·reflect_maplen(SB) +TEXT ·ismapkey(SB),NOSPLIT,$0-0 + BR runtime·reflect_ismapkey(SB) -- cgit v1.2.1 From b76ce7b591921653a59633ef13b034b731f722d0 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:55:43 -0400 Subject: [dev.power64] runtime: implemnt runtime.switchtoM and runtime.onM LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/129860043 --- src/pkg/runtime/asm_power64x.s | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'src') diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 52640f407..5c67e1948 100644 --- a/src/pkg/runtime/asm_power64x.s +++ b/src/pkg/runtime/asm_power64x.s @@ -145,6 +145,57 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8 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 */ -- cgit v1.2.1 From 54f65304ca15c1a396f8faa03170803f0addc3bd Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:56:20 -0400 Subject: [dev.power64] liblink: disable stack split for now LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/122460043 --- src/liblink/obj9.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 90145a46f..321e2c9bf 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -639,6 +639,9 @@ addstacksplit(Link *ctxt, LSym *cursym) static Prog* stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) { + // TODO(minux) + return p; + int32 arg; Prog *q, *q1; -- cgit v1.2.1 From 42894150ca55302e19f0bc397d6516ae7a9611a8 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 22:07:15 -0400 Subject: [dev.power64] cmd/gc: disable magic multiply optimizations for now LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/126110043 --- src/cmd/gc/walk.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index cb1873f85..cf25a3eac 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -3345,6 +3345,10 @@ walkdiv(Node **np, NodeList **init) Type *twide; Magic m; + // TODO(minux) + if(thechar == '9') + return; + n = *np; if(n->right->op != OLITERAL) return; -- cgit v1.2.1 From 1eda87d02f57f6b454971e7b833f958d9a29cfe8 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 22:25:43 -0400 Subject: [dev.power64] cmd/9g: clear p->reg for ATEXT LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125150043 --- src/cmd/9g/gsubr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index bb70bb7fd..0e5df5c6d 100644 --- a/src/cmd/9g/gsubr.c +++ b/src/cmd/9g/gsubr.c @@ -1019,6 +1019,8 @@ gins(int as, Node *f, Node *t) p->from = af; if(t != N) p->to = at; + if(as == ATEXT) + p->reg = 0; if(debug['g']) print("%P\n", p); -- cgit v1.2.1 From 3aab706372cb36f844645c6401a111d3ffe63b9b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 22:28:25 -0400 Subject: [dev.power64] runtime: disable GC and use a larger default stack LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/128120043 --- src/pkg/runtime/malloc.go | 2 +- src/pkg/runtime/mgc0.c | 4 ++++ src/pkg/runtime/stack.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/malloc.go b/src/pkg/runtime/malloc.go index dedcea94a..68baa80d5 100644 --- a/src/pkg/runtime/malloc.go +++ b/src/pkg/runtime/malloc.go @@ -278,7 +278,7 @@ func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { // force = 1 - do GC regardless of current heap usage // force = 2 - go GC and eager sweep func gogc(force int32) { - if memstats.enablegc == 0 { + if GOARCH == "power64" || GOARCH == "power64le" || memstats.enablegc == 0 { return } diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index e7955151c..03622db28 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -1305,6 +1305,10 @@ runtime·gc(int32 force) if(!mstats.enablegc || g == g->m->g0 || g->m->locks > 0 || runtime·panicking) return; + if(thechar == '9') { + runtime·gcpercent = -1; + return; + } if(runtime·gcpercent == GcpercentUnknown) { // first time through runtime·lock(&runtime·mheap); if(runtime·gcpercent == GcpercentUnknown) diff --git a/src/pkg/runtime/stack.h b/src/pkg/runtime/stack.h index ee5fd351d..64d377754 100644 --- a/src/pkg/runtime/stack.h +++ b/src/pkg/runtime/stack.h @@ -76,7 +76,7 @@ enum { // The minimum stack segment size to allocate. // If the amount needed for the splitting frame + StackExtra // is less than this number, the stack will have this size instead. - StackMin = 8192, + StackMin = 65536, StackSystemRounded = StackSystem + (-StackSystem & (StackMin-1)), FixedStack = StackMin + StackSystemRounded, -- cgit v1.2.1 From 8f91b2a823ea44649049bff69cc38e09cf5c8fba Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 23:57:02 -0400 Subject: [dev.power64] cmd/9g: introduce ginscon2 for CMP/CMPU, use ginscon to ADD constants LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125170043 --- src/cmd/9g/cgen.c | 6 ++---- src/cmd/9g/gg.h | 1 + src/cmd/9g/gsubr.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index 3644ebf8f..f8078aece 100644 --- a/src/cmd/9g/cgen.c +++ b/src/cmd/9g/cgen.c @@ -690,8 +690,7 @@ agenr(Node *n, Node *a, Node *res) n1.xoffset = Array_nel; regalloc(&n4, n1.type, N); gmove(&n1, &n4); - nodconst(&n2, types[TUINT64], v); - gins(optoas(OCMP, types[TUINT64]), &n4, &n2); + ginscon2(optoas(OCMP, types[TUINT64]), &n4, v); regfree(&n4); p1 = gbranch(optoas(OGT, types[TUINT64]), T, +1); ginscall(panicindex, 0); @@ -706,8 +705,7 @@ agenr(Node *n, Node *a, Node *res) } if (v*w != 0) { - nodconst(&n2, types[tptr], v*w); - gins(optoas(OADD, types[tptr]), &n2, &n3); + ginscon(optoas(OADD, types[tptr]), v*w, &n3); } *a = n3; break; diff --git a/src/cmd/9g/gg.h b/src/cmd/9g/gg.h index 2b95dc7a6..319702200 100644 --- a/src/cmd/9g/gg.h +++ b/src/cmd/9g/gg.h @@ -87,6 +87,7 @@ 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*); diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index 0e5df5c6d..a5ce5f141 100644 --- a/src/cmd/9g/gsubr.c +++ b/src/cmd/9g/gsubr.c @@ -562,6 +562,40 @@ ginscon(int as, vlong c, Node *n2) 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); */ -- cgit v1.2.1 From 3d68d241e7b0f53ce80c5add6d122b2419025055 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 23:57:42 -0400 Subject: [dev.power64] runtime: fix morestack Must not save LR. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/129040044 --- src/pkg/runtime/asm_power64x.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 5c67e1948..2fbaf5a53 100644 --- a/src/pkg/runtime/asm_power64x.s +++ b/src/pkg/runtime/asm_power64x.s @@ -208,7 +208,7 @@ onm: // the top of a stack (for example, morestack calling newstack // calling the scheduler calling newm calling gc), so we must // record an argument size. For that purpose, it has no arguments. -TEXT runtime·morestack(SB),NOSPLIT,$0-0 +TEXT runtime·morestack(SB),NOSPLIT,$-8-0 // Cannot grow scheduler stack (m->g0). MOVD g_m(g), R7 MOVD m_g0(R7), R8 @@ -244,7 +244,7 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0 // is still in this function, and not the beginning of the next. UNDEF -TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0 +TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0 MOVD R0, R11 BR runtime·morestack(SB) @@ -306,7 +306,7 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $-8-20 BR (CTR) // Note: can't just "BR runtime·NAME(SB)" - bad inlining results. -TEXT reflect·call(SB), NOSPLIT, $0-24 +TEXT reflect·call(SB), NOSPLIT, $-8-24 MOVW argsize+16(FP), R3 DISPATCH(call16, 16) DISPATCH(call32, 32) -- cgit v1.2.1 From 1b1e379e4604e661b397476a7270134c764a2f04 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:22:21 -0400 Subject: [dev.power64] cmd/cc: round argsize to multiples of wordsize on power64 LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/121640043 --- src/cmd/cc/pgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c index 0ee13787f..c2cf0e101 100644 --- a/src/cmd/cc/pgen.c +++ b/src/cmd/cc/pgen.c @@ -89,7 +89,7 @@ argsize(void) } //print(" %d %T\n", s, t); } - if(thechar == '6') + if(thechar == '6' || thechar == '9') s = (s+7) & ~7; else s = (s+3) & ~3; -- cgit v1.2.1 From 5992aa313610a628c0134f8dc5aae50c5c70a0ae Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:22:34 -0400 Subject: [dev.power64] cmd/9g: use loops to do memmove in sgen() LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/128130044 --- src/cmd/9g/cgen.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index f8078aece..a8d628f43 100644 --- a/src/cmd/9g/cgen.c +++ b/src/cmd/9g/cgen.c @@ -1344,10 +1344,10 @@ stkof(Node *n) void sgen(Node *n, Node *ns, int64 w) { - Node dst, src, tmp; + Node dst, src, tmp, nend; int32 c, odst, osrc; int dir, align, op; - Prog *p; + Prog *p, *ploop; NodeList *l; Node *res = ns; @@ -1447,19 +1447,15 @@ sgen(Node *n, Node *ns, int64 w) regalloc(&tmp, types[tptr], N); // set up end marker - //memset(&nend, 0, sizeof nend); - //if(c >= 4) { - // regalloc(&nend, types[tptr], N); - // p = gins(AMOVD, &src, &nend); - // p->from.type = D_CONST; - // if(dir < 0) - // p->from.offset = dir; - // else - // p->from.offset = w; - //} + 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; @@ -1475,11 +1471,19 @@ sgen(Node *n, Node *ns, int64 w) 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 loops and duffcopy for larger copies. - /*if(c >= 4) { + // TODO: enable duffcopy for larger copies. + if(c >= 4) { p = gins(op, &src, &tmp); p->from.type = D_OREG; p->from.offset = dir; @@ -1489,12 +1493,11 @@ sgen(Node *n, Node *ns, int64 w) p->to.type = D_OREG; p->to.offset = dir; - p = gins(ACMP, &src, N); - raddr(&nend, p); + p = gins(ACMP, &src, &nend); patch(gbranch(ABNE, T, 0), ploop); regfree(&nend); - } else*/ { + } else { while(c-- > 0) { p = gins(op, &src, &tmp); p->from.type = D_OREG; -- cgit v1.2.1 From 47b1e82d6cab6de9ef3f404f49820c837915e365 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:22:47 -0400 Subject: [dev.power64] liblink: rewrite MOVD $con(Ra), Rb into ADD $con, Ra, Rb; fix stack split prologue LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/129050043 --- src/liblink/obj9.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 321e2c9bf..960083bf9 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -179,6 +179,15 @@ progedit(Link *ctxt, Prog *p) } break; } + + if(p->from.type == D_CONST && p->from.reg != NREG) { + if(p->as == AMOVD && p->to.type == D_REG) { + p->as = AADD; + p->reg = p->from.reg; + p->from.reg = NREG; + } else + ctxt->diag("invalid instruction: %P", p); + } } static Prog* stacksplit(Link*, Prog*, int32, int); @@ -639,9 +648,6 @@ addstacksplit(Link *ctxt, LSym *cursym) static Prog* stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) { - // TODO(minux) - return p; - int32 arg; Prog *q, *q1; @@ -696,7 +702,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) // ADD $StackGuard, SP, R4 // SUB R3, R4 // MOVD $(framesize+(StackGuard-StackSmall)), R31 - // CMP R4, R31 + // CMPU R31, R4 p = appendp(ctxt, p); p->as = ACMP; p->from.type = D_REG; @@ -733,9 +739,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p = appendp(ctxt, p); p->as = ACMPU; p->from.type = D_REG; - p->from.reg = 4; + p->from.reg = REGTMP; p->to.type = D_REG; - p->to.reg = REGTMP; + p->to.reg = 4; } // q1: BLT done @@ -762,7 +768,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) arg = 0; else if(arg == ArgsSizeUnknown) ctxt->diag("%s: arg size unknown, but split stack", ctxt->cursym->name); - if(arg&3) // ???? + if(arg&7) ctxt->diag("misaligned argument size in stack split: %d", arg); p->from.offset = arg; p->to.type = D_REG; -- cgit v1.2.1 From 04d3bcd72901222de30ba28a643a386da4a5c0a3 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:23:00 -0400 Subject: [dev.power64] runtime: switch back to old initial stack size, and disable debugging messages for rewindmorestack LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/129850044 --- src/pkg/runtime/stack.h | 2 +- src/pkg/runtime/sys_power64x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/stack.h b/src/pkg/runtime/stack.h index 64d377754..ee5fd351d 100644 --- a/src/pkg/runtime/stack.h +++ b/src/pkg/runtime/stack.h @@ -76,7 +76,7 @@ enum { // The minimum stack segment size to allocate. // If the amount needed for the splitting frame + StackExtra // is less than this number, the stack will have this size instead. - StackMin = 65536, + StackMin = 8192, StackSystemRounded = StackSystem + (-StackSystem & (StackMin-1)), FixedStack = StackMin + StackSystemRounded, diff --git a/src/pkg/runtime/sys_power64x.c b/src/pkg/runtime/sys_power64x.c index ed8900c45..79d976255 100644 --- a/src/pkg/runtime/sys_power64x.c +++ b/src/pkg/runtime/sys_power64x.c @@ -28,7 +28,7 @@ runtime·rewindmorestack(Gobuf *gobuf) 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)); + //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; } -- cgit v1.2.1 From 28b121f6edd0262b48d744a9127fd7d6c417d2e3 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 11:39:07 -0400 Subject: [dev.power64] cmd/9g: do not ignore move instructions even if from and to are samaddr() Those moves might be significant (e.g. narrowing or widening): on Power64, we don't distinguish between MOVWD and MOVW. This fixes divmode.go and bug447.go. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125200043 Committer: Russ Cox --- src/cmd/9g/gg.h | 1 - src/cmd/9g/gsubr.c | 25 ------------------------- 2 files changed, 26 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/gg.h b/src/cmd/9g/gg.h index 319702200..6aa00117f 100644 --- a/src/cmd/9g/gg.h +++ b/src/cmd/9g/gg.h @@ -62,7 +62,6 @@ vlong fieldoffset(Type*, Node*); void sgen(Node*, Node*, int64); void gmove(Node*, Node*); Prog* gins(int, Node*, Node*); -int samaddr(Node*, Node*); void naddr(Node*, Addr*, int); void cgen_aret(Node*, Node*); int componentgen(Node*, Node*); diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index a5ce5f141..d8842796a 100644 --- a/src/cmd/9g/gsubr.c +++ b/src/cmd/9g/gsubr.c @@ -1006,21 +1006,6 @@ hard: return; } -int -samaddr(Node *f, Node *t) -{ - if(f->op != t->op) - return 0; - - switch(f->op) { - case OREGISTER: - if(f->val.u.reg != t->val.u.reg) - break; - return 1; - } - return 0; -} - /* * generate one instruction: * as f, t @@ -1032,16 +1017,6 @@ gins(int as, Node *f, Node *t) Prog *p; Addr af, at; - switch(as) { - case AMOVW: - case AMOVD: - case AFMOVS: - case AFMOVD: - if(f != N && t != N && samaddr(f, t)) - return nil; - break; - } - memset(&af, 0, sizeof af); memset(&at, 0, sizeof at); if(f != N) -- cgit v1.2.1 From 8f975aa1bb06a0f93fd8abfe53123b3dfd808f03 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 14:36:29 -0400 Subject: [dev.power64] cmd/9l, math/big, runtime, syscall: fixes for power64 On the machine I'm using, the hardware page size seems to be 64 kB. Make ELF rounding and mmap quantum 64 kB to match. Error numbers returned from kernel are positive; do not negate. Implement stubs for math/big. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/124300043 --- src/cmd/9l/obj.c | 2 +- src/pkg/math/big/arith_power64x.s | 46 ++++++++++++++++++++++++++++++++++++ src/pkg/runtime/arch_power64.h | 2 +- src/pkg/runtime/asm_power64x.s | 12 +++++----- src/pkg/runtime/mem_linux.c | 16 ++++++++----- src/pkg/runtime/sys_linux_power64x.s | 1 - src/pkg/syscall/asm_linux_power64x.s | 4 ---- 7 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 src/pkg/math/big/arith_power64x.s (limited to 'src') diff --git a/src/cmd/9l/obj.c b/src/cmd/9l/obj.c index 1ab18f491..badb72a1a 100644 --- a/src/cmd/9l/obj.c +++ b/src/cmd/9l/obj.c @@ -88,7 +88,7 @@ archinit(void) if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) - INITRND = 4096; + INITRND = 0x10000; break; case Hnacl: elfinit(); diff --git a/src/pkg/math/big/arith_power64x.s b/src/pkg/math/big/arith_power64x.s new file mode 100644 index 000000000..502d40cb6 --- /dev/null +++ b/src/pkg/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 "../../../cmd/ld/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/pkg/runtime/arch_power64.h b/src/pkg/runtime/arch_power64.h index 3d5b4943c..1dcbbc226 100644 --- a/src/pkg/runtime/arch_power64.h +++ b/src/pkg/runtime/arch_power64.h @@ -7,7 +7,7 @@ enum { BigEndian = 1, CacheLineSize = 64, RuntimeGogoBytes = 84, - PhysPageSize = 4096, + PhysPageSize = 65536, PCQuantum = 4, Int64Align = 8 }; diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 2fbaf5a53..59c7a9eb5 100644 --- a/src/pkg/runtime/asm_power64x.s +++ b/src/pkg/runtime/asm_power64x.s @@ -782,8 +782,8 @@ 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 - MOVD R3, R6 // store base-1 for later ADD R3, R4 // end-1 _index_loop: @@ -798,16 +798,16 @@ _index_loop: RETURN _index_notfound: - MOVW $-1, R3 - MOVW R3, ret+32(FP) + 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 - MOVD R3, R6 // store base-1 for later ADD R3, R4 // end-1 _index2_loop: @@ -822,8 +822,8 @@ _index2_loop: RETURN _index2_notfound: - MOVW $-1, R3 - MOVW R3, ret+24(FP) + MOVD $-1, R3 + MOVD R3, ret+24(FP) RETURN diff --git a/src/pkg/runtime/mem_linux.c b/src/pkg/runtime/mem_linux.c index 635594c36..30594c528 100644 --- a/src/pkg/runtime/mem_linux.c +++ b/src/pkg/runtime/mem_linux.c @@ -10,7 +10,7 @@ enum { - _PAGE_SIZE = 4096, + _PAGE_SIZE = PhysPageSize, EACCES = 13, }; @@ -35,8 +35,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; } @@ -47,12 +48,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/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index c0c41efa9..f5149eaea 100644 --- a/src/pkg/runtime/sys_linux_power64x.s +++ b/src/pkg/runtime/sys_linux_power64x.s @@ -223,7 +223,6 @@ TEXT runtime·mmap(SB),NOSPLIT,$-8 SYSCALL $SYS_mmap BVC 2(PC) - NEG R3, R3 RETURN TEXT runtime·munmap(SB),NOSPLIT,$-8 diff --git a/src/pkg/syscall/asm_linux_power64x.s b/src/pkg/syscall/asm_linux_power64x.s index 1dd23ef30..c9b0fe320 100644 --- a/src/pkg/syscall/asm_linux_power64x.s +++ b/src/pkg/syscall/asm_linux_power64x.s @@ -24,7 +24,6 @@ TEXT ·Syscall(SB),NOSPLIT,$0-56 MOVD trap+0(FP), R9 // syscall entry SYSCALL R9 BVC ok - NEG R3, R3 MOVD $-1, R4 MOVD R4, r1+32(FP) // r1 MOVD R0, r2+40(FP) // r2 @@ -49,7 +48,6 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-80 MOVD trap+0(FP), R9 // syscall entry SYSCALL R9 BVC ok6 - NEG R3, R3 MOVD $-1, R4 MOVD R4, r1+56(FP) // r1 MOVD R0, r2+64(FP) // r2 @@ -73,7 +71,6 @@ TEXT ·RawSyscall(SB),NOSPLIT,$0-56 MOVD trap+0(FP), R9 // syscall entry SYSCALL R9 BVC ok1 - NEG R3, R3 MOVD $-1, R4 MOVD R4, r1+32(FP) // r1 MOVD R0, r2+40(FP) // r2 @@ -95,7 +92,6 @@ TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 MOVD trap+0(FP), R9 // syscall entry SYSCALL R9 BVC ok2 - NEG R3, R3 MOVD $-1, R4 MOVD R4, r1+56(FP) // r1 MOVD R0, r2+64(FP) // r2 -- cgit v1.2.1 From 3040edcab8d205b9de02da1b79732a2f817e5bbd Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 14:52:01 -0400 Subject: [dev.power64] runtime: fix newstackcall moreframesize is a uint32, not a uint64. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/124310043 --- src/pkg/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 59c7a9eb5..e530e704e 100644 --- a/src/pkg/runtime/asm_power64x.s +++ b/src/pkg/runtime/asm_power64x.s @@ -284,7 +284,7 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $-8-20 MOVD R8, m_moreargp(R5) MOVW R9, m_moreargsize(R5) MOVD $1, R10 - MOVD R10, m_moreframesize(R5) + MOVW R10, m_moreframesize(R5) // call newstack on m->g0's stack MOVD m_g0(R5), g -- cgit v1.2.1 From 14f6e326abdea8c34c42225aee0e42442071f48e Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 14:52:11 -0400 Subject: [dev.power64] runtime: fix build LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/128180044 Committer: Russ Cox --- src/pkg/runtime/sys_linux_power64x.s | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index f5149eaea..df808a83c 100644 --- a/src/pkg/runtime/sys_linux_power64x.s +++ b/src/pkg/runtime/sys_linux_power64x.s @@ -222,7 +222,6 @@ TEXT runtime·mmap(SB),NOSPLIT,$-8 MOVW 36(R1), R8 SYSCALL $SYS_mmap - BVC 2(PC) RETURN TEXT runtime·munmap(SB),NOSPLIT,$-8 -- cgit v1.2.1 From c0e9275f05847d76e747f0161d2ea11d0fb2e521 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 15:49:07 -0400 Subject: [dev.power64] cmd/9g: add missing break LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/125260043 Committer: Russ Cox --- src/cmd/9g/gsubr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index d8842796a..dfdff0587 100644 --- a/src/cmd/9g/gsubr.c +++ b/src/cmd/9g/gsubr.c @@ -772,6 +772,7 @@ gmove(Node *f, Node *t) case CASE(TINT64, TINT16): case CASE(TUINT64, TINT16): a = AMOVH; + break; case CASE(TINT16, TUINT16): // same size case CASE(TUINT16, TUINT16): -- cgit v1.2.1 From df0ee6bbcfb9b7cfb497347df464563ac8a3aefe Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 15:49:19 -0400 Subject: [dev.power64] cmd/9g: fix floating-point comparison for NaN LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/127300043 --- src/cmd/9g/cgen.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index a8d628f43..6bb44f547 100644 --- a/src/cmd/9g/cgen.c +++ b/src/cmd/9g/cgen.c @@ -1267,12 +1267,21 @@ bgen(Node *n, int true, int likely, Prog *to) l = &n1; r = &n2; gins(optoas(OCMP, nr->type), l, r); - - // TODO(minux): determine the reason for failed test/floatcmp.go. - // we might need to specially handle floating point comparisons. - /*if(isfloat[nr->type->etype] && (n->op == OEQ || n->op == ONE)) { - } else*/ + if(isfloat[nr->type->etype] && (n->op == OLE || n->op == OGE)) { + // To get NaN right, must rewrite x <= y into separate x < y or x = y. + switch(n->op) { + 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; -- cgit v1.2.1 From dbad4e57e9004e42066fd8b90f8b200a96d597df Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 15:50:06 -0400 Subject: [dev.power64] runtime: fix C prototype for cmallocgc LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/122520043 --- src/pkg/runtime/malloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/runtime/malloc.c b/src/pkg/runtime/malloc.c index d56d0dcf3..1e133168b 100644 --- a/src/pkg/runtime/malloc.c +++ b/src/pkg/runtime/malloc.c @@ -21,7 +21,7 @@ MHeap runtime·mheap; #pragma dataflag NOPTR MStats runtime·memstats; -void runtime·cmallocgc(uintptr size, Type *typ, uint32 flag, void **ret); +void runtime·cmallocgc(uintptr size, Type *typ, intgo flag, void **ret); void* runtime·mallocgc(uintptr size, Type *typ, uint32 flag) -- cgit v1.2.1 From 21fcf4f8d49df1546e6655b8228e779593df0945 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 16:26:43 -0400 Subject: [dev.power64] runtime: fix reflect.call The code to copy out the results was incorrect. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/122530043 --- src/pkg/runtime/asm_power64x.s | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index e530e704e..1a72b1b3c 100644 --- a/src/pkg/runtime/asm_power64x.s +++ b/src/pkg/runtime/asm_power64x.s @@ -368,29 +368,26 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \ MOVBZU R6, 1(R5); \ BR -4(PC); \ /* call function */ \ - MOVD f+0(FP), R31; \ - MOVD (R31), R31; \ + 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), R5; \ - MOVD R1, R6; \ - ADD $(8-1), R6; \ - ADD R5, R6; \ - ADD R5, R3; \ - SUB R5, R4; \ - CMP R4, $0; \ - BEQ 9(PC); \ + MOVW retoffset+20(FP), R6; \ + MOVD R1, R5; \ + ADD R6, R5; \ + ADD R6, R3; \ + SUB R6, R4; \ + ADD $(8-1), R5; \ SUB $1, R3; \ - SUB $1, R6; \ - ADD R3, R4; \ - CMP R3, R4; \ + ADD R5, R4; \ + CMP R5, R4; \ BEQ 4(PC); \ - MOVBZU 1(R3), R5; \ - MOVBZU R5, 1(R6); \ + MOVBZU 1(R5), R6; \ + MOVBZU R6, 1(R3); \ BR -4(PC); \ RETURN -- cgit v1.2.1 From f14ac88830638f1031ed0339d4db6e7e635385e6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 18:14:13 -0400 Subject: [dev.power64] liblink: fix handling of MOVD with large constants LGTM=minux R=golang-codereviews, minux CC=golang-codereviews https://codereview.appspot.com/122540043 Committer: Shenghou Ma --- src/liblink/asm9.c | 15 +++++++++------ src/liblink/obj9.c | 9 --------- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 886edf347..f1889a92c 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -488,12 +488,12 @@ span9(Link *ctxt, LSym *cursym) 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); - ctxt->cursym = cursym; - bflag = 0; c = 0; p->pc = c; @@ -571,12 +571,10 @@ span9(Link *ctxt, LSym *cursym) if(ctxt->tlsg == nil) ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0); - p = cursym->text; - ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8; symgrow(ctxt, cursym, cursym->size); bp = cursym->p; - for(p = p->link; p != nil; p = p->link) { + for(p = cursym->text->link; p != nil; p = p->link) { ctxt->pc = p->pc; ctxt->curp = p; o = oplook(ctxt, p); @@ -1464,12 +1462,17 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) 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; diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 960083bf9..3405fce47 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -179,15 +179,6 @@ progedit(Link *ctxt, Prog *p) } break; } - - if(p->from.type == D_CONST && p->from.reg != NREG) { - if(p->as == AMOVD && p->to.type == D_REG) { - p->as = AADD; - p->reg = p->from.reg; - p->from.reg = NREG; - } else - ctxt->diag("invalid instruction: %P", p); - } } static Prog* stacksplit(Link*, Prog*, int32, int); -- cgit v1.2.1 From e456ae86a6951a4c367019c2387cf4c9615f132a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 18:32:54 -0400 Subject: [dev.power64] liblink: fix handling of $nnn(reg) LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/126180043 --- src/liblink/asm9.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index f1889a92c..352fba915 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -677,6 +677,11 @@ aclass(Link *ctxt, Addr *a) 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) @@ -769,6 +774,7 @@ oplook(Link *ctxt, Prog *p) 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) @@ -1423,6 +1429,7 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) o4 = 0; o5 = 0; +//print("%P => case %d\n", p, o->type); switch(o->type) { default: ctxt->diag("unknown type %d", o->type); -- cgit v1.2.1 From a7d370d73398dc75e8191e7eccf7b9398b0dadf1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 11:57:10 -0400 Subject: [dev.power64] liblink: fix $large(SP) for floating point load/store Fixes test/cmplxdivide. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/128190045 --- src/liblink/asm9.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 352fba915..56582fe27 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -320,18 +320,18 @@ static Optab optab[] = { { 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, 8, 4, REGSB }, - { AFMOVD, C_LAUTO,C_NONE, C_NONE, C_FREG, 8, 4, REGSP }, - { AFMOVD, C_LOREG,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, 7, 4, REGSB }, - { AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 7, 4, REGSP }, - { AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 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 }, @@ -1491,6 +1491,8 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) 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; @@ -1514,8 +1516,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) if(v) ctxt->diag("illegal indexed instruction\n%P", p); o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r); - } else + } 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) */ @@ -1527,8 +1532,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) if(v) ctxt->diag("illegal indexed instruction\n%P", p); o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r); - } else + } 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 */ -- cgit v1.2.1 From 62cd30b6816b230629d1ed6075efb2a561491619 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 11:59:52 -0400 Subject: [dev.power64] reflect: now we find one big endian machine LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/124350043 Committer: Russ Cox --- src/pkg/reflect/value.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go index 2cbda3983..50f531596 100644 --- a/src/pkg/reflect/value.go +++ b/src/pkg/reflect/value.go @@ -11,7 +11,7 @@ import ( "unsafe" ) -const bigEndian = false // can be smarter if we find a big-endian machine +const bigEndian = runtime.GOARCH == "power64" // can be smarter if we find more big-endian machines const ptrSize = unsafe.Sizeof((*byte)(nil)) const cannotSet = "cannot set value obtained from unexported struct field" @@ -1620,6 +1620,7 @@ func (v Value) SetCap(n int) { // SetMapIndex sets the value associated with key in the map v to val. // It panics if v's Kind is not Map. // If val is the zero Value, SetMapIndex deletes the key from the map. +// Otherwise if v holds a nil map, SetMapIndex will panic. // As in Go, key's value must be assignable to the map's key type, // and val's value must be assignable to the map's value type. func (v Value) SetMapIndex(key, val Value) { -- cgit v1.2.1 From 6155cd4315080223580b41bf954a9aa29c007086 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 11:59:58 -0400 Subject: [dev.power64] runtime: fix time.now Was reading a uint64 field with a MOVW, which has endian issues. LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/122550043 Committer: Russ Cox --- src/pkg/runtime/sys_linux_power64x.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index df808a83c..1d985d1af 100644 --- a/src/pkg/runtime/sys_linux_power64x.s +++ b/src/pkg/runtime/sys_linux_power64x.s @@ -83,7 +83,7 @@ TEXT runtime·read(SB),NOSPLIT,$-8-24 TEXT runtime·getrlimit(SB),NOSPLIT,$-8-24 MOVW 8(R1), R3 MOVD 16(R1), R4 - SYSCALL $SYS_ugetrlimit // ??? why not use SYS_getrlimit + SYSCALL $SYS_ugetrlimit RETURN TEXT runtime·usleep(SB),NOSPLIT,$-8-16 @@ -132,7 +132,7 @@ TEXT time·now(SB),NOSPLIT,$16 MOVD $0, R4 SYSCALL $SYS_gettimeofday MOVD 0(R1), R3 // sec - MOVW 8(R1), R5 // usec + MOVD 8(R1), R5 // usec MOVD $1000, R4 MULLD R4, R5 MOVD R3, sec+0(FP) -- cgit v1.2.1 From 1d43cf04a69977d0629db143e0af7522ef55c1c3 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 12:01:14 -0400 Subject: [dev.power64] runtime: add power64/power64le as supported arch to gcinfo_test.go LGTM=rsc R=rsc, iant CC=golang-codereviews https://codereview.appspot.com/122560043 Committer: Russ Cox --- src/pkg/runtime/gcinfo_test.go | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/pkg/runtime/gcinfo_test.go b/src/pkg/runtime/gcinfo_test.go index 6afa9a4e2..5e5b7ec37 100644 --- a/src/pkg/runtime/gcinfo_test.go +++ b/src/pkg/runtime/gcinfo_test.go @@ -122,6 +122,12 @@ func infoComplex() []byte { BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsScalar, BitsMultiWord, BitsString, } + case "power64", "power64le": + return []byte{ + BitsPointer, BitsScalar, BitsScalar, BitsScalar, + BitsMultiWord, BitsSlice, BitsScalar, BitsScalar, + BitsScalar, BitsScalar, BitsMultiWord, BitsString, + } default: panic("unknown arch") } -- cgit v1.2.1 From c6a55543590d81f96dda0dc7a1f4bc34d0fec935 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 12:01:21 -0400 Subject: [dev.power64] syscall: re-generate using cgo compiled by gc, fix test failures LGTM=dave, rsc R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/127320043 Committer: Russ Cox --- src/pkg/syscall/syscall_linux_power64x.go | 2 +- src/pkg/syscall/types_linux.go | 6 ++++-- src/pkg/syscall/zerrors_linux_power64.go | 11 +--------- src/pkg/syscall/zerrors_linux_power64le.go | 11 +--------- src/pkg/syscall/zsyscall_linux_power64.go | 2 +- src/pkg/syscall/zsyscall_linux_power64le.go | 2 +- src/pkg/syscall/ztypes_linux_power64.go | 32 ++++++++++++++--------------- src/pkg/syscall/ztypes_linux_power64le.go | 32 ++++++++++++++--------------- 8 files changed, 41 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/pkg/syscall/syscall_linux_power64x.go b/src/pkg/syscall/syscall_linux_power64x.go index dbe37c44e..c0ea660d4 100644 --- a/src/pkg/syscall/syscall_linux_power64x.go +++ b/src/pkg/syscall/syscall_linux_power64x.go @@ -15,7 +15,7 @@ package syscall //sysnb Getegid() (egid int) //sysnb Geteuid() (euid int) //sysnb Getgid() (gid int) -//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) +//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) diff --git a/src/pkg/syscall/types_linux.go b/src/pkg/syscall/types_linux.go index 8ea499246..5e9f698cf 100644 --- a/src/pkg/syscall/types_linux.go +++ b/src/pkg/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 diff --git a/src/pkg/syscall/zerrors_linux_power64.go b/src/pkg/syscall/zerrors_linux_power64.go index 9409bdba3..15e0770c1 100644 --- a/src/pkg/syscall/zerrors_linux_power64.go +++ b/src/pkg/syscall/zerrors_linux_power64.go @@ -353,7 +353,7 @@ const ( F_GETFD = 0x1 F_GETFL = 0x3 F_GETLEASE = 0x401 - F_GETLK = 0xc + F_GETLK = 0x5 F_GETLK64 = 0xc F_GETOWN = 0x9 F_GETOWN_EX = 0x10 @@ -671,15 +671,6 @@ const ( MAP_SHARED = 0x1 MAP_STACK = 0x20000 MAP_TYPE = 0xf - MCAST_BLOCK_SOURCE = 0x2b - MCAST_EXCLUDE = 0x0 - MCAST_INCLUDE = 0x1 - MCAST_JOIN_GROUP = 0x2a - MCAST_JOIN_SOURCE_GROUP = 0x2e - MCAST_LEAVE_GROUP = 0x2d - MCAST_LEAVE_SOURCE_GROUP = 0x2f - MCAST_MSFILTER = 0x30 - MCAST_UNBLOCK_SOURCE = 0x2c MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MNT_DETACH = 0x2 diff --git a/src/pkg/syscall/zerrors_linux_power64le.go b/src/pkg/syscall/zerrors_linux_power64le.go index de3b442a1..fdecdf24d 100644 --- a/src/pkg/syscall/zerrors_linux_power64le.go +++ b/src/pkg/syscall/zerrors_linux_power64le.go @@ -353,7 +353,7 @@ const ( F_GETFD = 0x1 F_GETFL = 0x3 F_GETLEASE = 0x401 - F_GETLK = 0xc + F_GETLK = 0x5 F_GETLK64 = 0xc F_GETOWN = 0x9 F_GETOWN_EX = 0x10 @@ -675,15 +675,6 @@ const ( MAP_SHARED = 0x1 MAP_STACK = 0x20000 MAP_TYPE = 0xf - MCAST_BLOCK_SOURCE = 0x2b - MCAST_EXCLUDE = 0x0 - MCAST_INCLUDE = 0x1 - MCAST_JOIN_GROUP = 0x2a - MCAST_JOIN_SOURCE_GROUP = 0x2e - MCAST_LEAVE_GROUP = 0x2d - MCAST_LEAVE_SOURCE_GROUP = 0x2f - MCAST_MSFILTER = 0x30 - MCAST_UNBLOCK_SOURCE = 0x2c MCL_CURRENT = 0x2000 MCL_FUTURE = 0x4000 MNT_DETACH = 0x2 diff --git a/src/pkg/syscall/zsyscall_linux_power64.go b/src/pkg/syscall/zsyscall_linux_power64.go index 5f8feccc5..7808059cc 100644 --- a/src/pkg/syscall/zsyscall_linux_power64.go +++ b/src/pkg/syscall/zsyscall_linux_power64.go @@ -1431,7 +1431,7 @@ func Getgid() (gid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) + _, _, e1 := RawSyscall(SYS_UGETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) if e1 != 0 { err = e1 } diff --git a/src/pkg/syscall/zsyscall_linux_power64le.go b/src/pkg/syscall/zsyscall_linux_power64le.go index 5f8feccc5..7808059cc 100644 --- a/src/pkg/syscall/zsyscall_linux_power64le.go +++ b/src/pkg/syscall/zsyscall_linux_power64le.go @@ -1431,7 +1431,7 @@ func Getgid() (gid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) + _, _, e1 := RawSyscall(SYS_UGETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) if e1 != 0 { err = e1 } diff --git a/src/pkg/syscall/ztypes_linux_power64.go b/src/pkg/syscall/ztypes_linux_power64.go index 5a34068bc..204d80685 100644 --- a/src/pkg/syscall/ztypes_linux_power64.go +++ b/src/pkg/syscall/ztypes_linux_power64.go @@ -71,22 +71,22 @@ type Utimbuf struct { } type Rusage struct { - Utime Timeval - Stime Timeval - Anon0 [8]byte - Anon1 [8]byte - Anon2 [8]byte - Anon3 [8]byte - Anon4 [8]byte - Anon5 [8]byte - Anon6 [8]byte - Anon7 [8]byte - Anon8 [8]byte - Anon9 [8]byte - Anon10 [8]byte - Anon11 [8]byte - Anon12 [8]byte - Anon13 [8]byte + 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 { diff --git a/src/pkg/syscall/ztypes_linux_power64le.go b/src/pkg/syscall/ztypes_linux_power64le.go index 647755cb1..df481f5c7 100644 --- a/src/pkg/syscall/ztypes_linux_power64le.go +++ b/src/pkg/syscall/ztypes_linux_power64le.go @@ -71,22 +71,22 @@ type Utimbuf struct { } type Rusage struct { - Utime Timeval - Stime Timeval - Anon0 [8]byte - Anon1 [8]byte - Anon2 [8]byte - Anon3 [8]byte - Anon4 [8]byte - Anon5 [8]byte - Anon6 [8]byte - Anon7 [8]byte - Anon8 [8]byte - Anon9 [8]byte - Anon10 [8]byte - Anon11 [8]byte - Anon12 [8]byte - Anon13 [8]byte + 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 { -- cgit v1.2.1 From c143c548f010c131101a0e53401b60e6301b7031 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 12:01:27 -0400 Subject: [dev.power64] runtime: don't fault on runtime.procyield, just return LGTM=dave, rsc R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/128230044 Committer: Russ Cox --- src/pkg/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 1a72b1b3c..a0511de8e 100644 --- a/src/pkg/runtime/asm_power64x.s +++ b/src/pkg/runtime/asm_power64x.s @@ -547,7 +547,7 @@ TEXT runtime·xchgp(SB), NOSPLIT, $0-16 BR runtime·xchg64(SB) TEXT runtime·procyield(SB),NOSPLIT,$0-0 - MOVD R0, 17(R0) + RETURN TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16 BR runtime·atomicstore64(SB) -- cgit v1.2.1 From 74cc0ef0595c8290c34ca664a896d0c3b8ebfeee Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:34:14 -0400 Subject: [dev.power64] cmd/9c: fix constant truncation in optimizer This is what broke getpopcount, but that code had it coming. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/130000044 --- src/cmd/9c/reg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/9c/reg.c b/src/cmd/9c/reg.c index 658fa3211..38bb2e9de 100644 --- a/src/cmd/9c/reg.c +++ b/src/cmd/9c/reg.c @@ -558,7 +558,7 @@ mkvar(Addr *a, int docon) { Var *v; int i, t, n, et, z; - int32 o; + int64 o; Bits bit; LSym *s; @@ -617,6 +617,8 @@ out: for(z=0; zetype = TVLONG; if(s == nil) { for(z=0; z Date: Thu, 14 Aug 2014 14:34:25 -0400 Subject: [dev.power64] runtime: replace getproccount with simpler code This runs once. There is no need for inscrutable algorithms. Also it doesn't compile correctly with 9c. LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/130000043 --- src/pkg/runtime/os_linux.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/os_linux.c b/src/pkg/runtime/os_linux.c index b9ac8c619..1751ea83b 100644 --- a/src/pkg/runtime/os_linux.c +++ b/src/pkg/runtime/os_linux.c @@ -78,19 +78,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. -- cgit v1.2.1 From 81e54561e935e41fed0232a798a7f9264c8b93fb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:34:37 -0400 Subject: [dev.power64] cmd/9g: correct floating point comparison LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/129210043 --- src/cmd/9g/cgen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index 6bb44f547..86a56975a 100644 --- a/src/cmd/9g/cgen.c +++ b/src/cmd/9g/cgen.c @@ -1267,9 +1267,9 @@ bgen(Node *n, int true, int likely, Prog *to) l = &n1; r = &n2; gins(optoas(OCMP, nr->type), l, r); - if(isfloat[nr->type->etype] && (n->op == OLE || n->op == OGE)) { + 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(n->op) { + switch(a) { case OLE: a = OLT; break; -- cgit v1.2.1 From 5102f3d54ab1c432f3d037f6a0b9d435729a36f7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:34:48 -0400 Subject: [dev.power64] cmd/dist: tell goc2c that power64 is 64-bit system LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/125300043 --- src/cmd/dist/goc2c.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cmd/dist/goc2c.c b/src/cmd/dist/goc2c.c index 38627657e..72cbc1be6 100644 --- a/src/cmd/dist/goc2c.c +++ b/src/cmd/dist/goc2c.c @@ -786,7 +786,11 @@ goc2c(char *goc, char *c) // TODO: set gcc=1 when using gcc if(!gcc) { - if(streq(goarch, "amd64")) { + if(contains(goarch, "64p32")) { + type_table[Uintptr].size = 4; + type_table[Int].size = 4; + structround = 8; + } else if(contains(goarch, "64")) { type_table[Uintptr].size = 8; if(use64bitint) { type_table[Int].size = 8; @@ -794,10 +798,6 @@ goc2c(char *goc, char *c) type_table[Int].size = 4; } structround = 8; - } else if(streq(goarch, "amd64p32")) { - type_table[Uintptr].size = 4; - type_table[Int].size = 4; - structround = 8; } else { // NOTE: These are set in the initializer, // but they might have been changed by a -- cgit v1.2.1 From 2dba15cb8347c2832036294b389a6103c316f6fe Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:35:00 -0400 Subject: [dev.power64] reflect: fix test not to hang even if TrySend lies LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/124360043 --- src/pkg/reflect/all_test.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go index f12271173..50d223f92 100644 --- a/src/pkg/reflect/all_test.go +++ b/src/pkg/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) -- cgit v1.2.1 From 0d325017a5e61d732b4f42e79f14b780f3b882f1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 15:29:05 -0400 Subject: [dev.power64] syscall: fix power64 page size LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/128260043 --- src/pkg/syscall/syscall_linux_power64x.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/syscall/syscall_linux_power64x.go b/src/pkg/syscall/syscall_linux_power64x.go index c0ea660d4..fd043627a 100644 --- a/src/pkg/syscall/syscall_linux_power64x.go +++ b/src/pkg/syscall/syscall_linux_power64x.go @@ -58,7 +58,7 @@ package syscall //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 4096 } +func Getpagesize() int { return 65536 } //sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Time(t *Time_t) (tt Time_t, err error) -- cgit v1.2.1 From ba1d77eb933aeb8962ba1eb097ae7442e7ea6ecd Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 15:29:37 -0400 Subject: [dev.power64] cmd/ld, runtime: detect, fix nosplit overflows LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/121690043 --- src/cmd/ld/lib.c | 33 +++++++++++++++------------------ src/pkg/runtime/os_linux.c | 15 ++++++++++++++- src/pkg/runtime/string.go | 4 ---- 3 files changed, 29 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index b4134da36..5db41f9a7 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -1026,7 +1026,7 @@ static LSym *newstack; enum { - HasLinkRegister = (thechar == '5'), + HasLinkRegister = (thechar == '5' || thechar == '9'), }; // TODO: Record enough information in new object files to @@ -1035,7 +1035,7 @@ enum static int callsize(void) { - if(thechar == '5') + if(HasLinkRegister) return 0; return RegSize; } @@ -1046,9 +1046,6 @@ dostkcheck(void) Chain ch; LSym *s; - if(thechar == '9') - return; - morestack = linklookup(ctxt, "runtime.morestack", 0); newstack = linklookup(ctxt, "runtime.newstack", 0); @@ -1072,19 +1069,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) @@ -1102,7 +1099,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; } @@ -1161,8 +1158,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; @@ -1181,7 +1178,7 @@ stkcheck(Chain *up, int depth) break; } } - } + } return 0; } @@ -1210,7 +1207,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); } diff --git a/src/pkg/runtime/os_linux.c b/src/pkg/runtime/os_linux.c index 1751ea83b..8aadee721 100644 --- a/src/pkg/runtime/os_linux.c +++ b/src/pkg/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); } diff --git a/src/pkg/runtime/string.go b/src/pkg/runtime/string.go index c5b091748..69874e909 100644 --- a/src/pkg/runtime/string.go +++ b/src/pkg/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[:]) } -- cgit v1.2.1 From a3dada1c457e490fbb56d7d7fdab1b2321de411e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 16:34:28 -0400 Subject: [dev.power64] runtime: fix RuntimeGogoBytes on power64 LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/130030043 --- src/pkg/runtime/arch_power64.h | 2 +- src/pkg/runtime/arch_power64le.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/arch_power64.h b/src/pkg/runtime/arch_power64.h index 1dcbbc226..7cfb9da2f 100644 --- a/src/pkg/runtime/arch_power64.h +++ b/src/pkg/runtime/arch_power64.h @@ -6,7 +6,7 @@ enum { thechar = '9', BigEndian = 1, CacheLineSize = 64, - RuntimeGogoBytes = 84, + RuntimeGogoBytes = 64, PhysPageSize = 65536, PCQuantum = 4, Int64Align = 8 diff --git a/src/pkg/runtime/arch_power64le.h b/src/pkg/runtime/arch_power64le.h index d9241da98..3015e70aa 100644 --- a/src/pkg/runtime/arch_power64le.h +++ b/src/pkg/runtime/arch_power64le.h @@ -6,7 +6,7 @@ enum { thechar = '9', BigEndian = 0, CacheLineSize = 64, - RuntimeGogoBytes = 84, + RuntimeGogoBytes = 64, PhysPageSize = 4096, PCQuantum = 4, Int64Align = 8 -- cgit v1.2.1 From d34c536b6e9f2e3c883c91c9144cc821aa5f7c44 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Fri, 15 Aug 2014 13:15:24 +1000 Subject: [dev.power64] runtime: define page size on power64le systems to be 64k Fixes issue 8495. CL 128260043 updated the definition of syscall.GetPageSize to report 64k for power64 and power64le. This CL cleans up the last place where the page size was defined as 4k. LGTM=minux R=rsc, minux CC=golang-codereviews https://codereview.appspot.com/123520043 --- src/pkg/runtime/arch_power64le.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/pkg/runtime/arch_power64le.h b/src/pkg/runtime/arch_power64le.h index 3015e70aa..684ac9953 100644 --- a/src/pkg/runtime/arch_power64le.h +++ b/src/pkg/runtime/arch_power64le.h @@ -7,7 +7,7 @@ enum { BigEndian = 0, CacheLineSize = 64, RuntimeGogoBytes = 64, - PhysPageSize = 4096, + PhysPageSize = 65536, PCQuantum = 4, Int64Align = 8 }; -- cgit v1.2.1 From ac4f097bb640c032692354736617eeaddf33399a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 15 Aug 2014 15:22:33 -0400 Subject: [dev.power64] runtime: make all bitmaps arrays of bytes The "simpler faster garbage collector" is full of little-endian assumptions. Instead of trying to correct all the mistakes, just give in and make everything use bytes. LGTM=minux R=minux CC=dvyukov, golang-codereviews https://codereview.appspot.com/124400043 --- src/cmd/gc/plive.c | 6 +++++- src/pkg/runtime/heapdump.c | 14 ++++++------- src/pkg/runtime/malloc.go | 9 ++++---- src/pkg/runtime/malloc.h | 4 ++-- src/pkg/runtime/mgc0.c | 51 ++++++++++++++++++++++++++-------------------- src/pkg/runtime/mgc0.h | 7 +++++++ src/pkg/runtime/stack.c | 6 +++--- 7 files changed, 58 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c index e67b0af75..716cdd108 100644 --- a/src/cmd/gc/plive.c +++ b/src/cmd/gc/plive.c @@ -1939,7 +1939,11 @@ twobitwritesymbol(Array *arr, Sym *sym) break; for(j = 0; j < bv->n; j += 32) { word = bv->b[j/32]; - off = duint32(sym, off, word); + // Runtime reads the bitmaps as byte arrays. Oblige. + off = duint8(sym, off, word); + off = duint8(sym, off, word>>8); + off = duint8(sym, off, word>>16); + off = duint8(sym, off, word>>24); } } duint32(sym, 0, i); // number of bitmaps diff --git a/src/pkg/runtime/heapdump.c b/src/pkg/runtime/heapdump.c index eec34f2cb..f29cf0108 100644 --- a/src/pkg/runtime/heapdump.c +++ b/src/pkg/runtime/heapdump.c @@ -252,7 +252,7 @@ dumpbv(BitVector *bv, uintptr offset) uintptr i; for(i = 0; i < bv->n; i += BitsPerPointer) { - switch(bv->data[i/32] >> i%32 & 3) { + switch(bv->bytedata[i/8] >> i%8 & 3) { case BitsDead: case BitsScalar: break; @@ -261,7 +261,7 @@ dumpbv(BitVector *bv, uintptr offset) dumpint(offset + i / BitsPerPointer * PtrSize); break; case BitsMultiWord: - switch(bv->data[(i+BitsPerPointer)/32] >> (i+BitsPerPointer)%32 & 3) { + switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) { case BitsString: dumpint(FieldKindString); dumpint(offset + i / BitsPerPointer * PtrSize); @@ -497,13 +497,13 @@ dumproots(void) dumpint(TagData); dumpint((uintptr)data); dumpmemrange(data, edata - data); - dumpfields((BitVector){(edata - data)*8, (uint32*)gcdata}); + dumpfields((BitVector){(edata - data)*8, (byte*)gcdata}); /* WRONG! gcbss is not a bitmap */ // bss segment dumpint(TagBss); dumpint((uintptr)bss); dumpmemrange(bss, ebss - bss); - dumpfields((BitVector){(ebss - bss)*8, (uint32*)gcbss}); + dumpfields((BitVector){(ebss - bss)*8, (byte*)gcbss}); /* WRONG! gcbss is not a bitmap */ // MSpan.types allspans = runtime·mheap.allspans; @@ -795,9 +795,9 @@ dumpbvtypes(BitVector *bv, byte *base) uintptr i; for(i = 0; i < bv->n; i += BitsPerPointer) { - if((bv->data[i/32] >> i%32 & 3) != BitsMultiWord) + if((bv->bytedata[i/8] >> i%8 & 3) != BitsMultiWord) continue; - switch(bv->data[(i+BitsPerPointer)/32] >> (i+BitsPerPointer)%32 & 3) { + switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) { case BitsString: case BitsIface: i += BitsPerPointer; @@ -843,5 +843,5 @@ makeheapobjbv(byte *p, uintptr size) tmpbuf[i*BitsPerPointer/8] &= ~(3<<((i*BitsPerPointer)%8)); tmpbuf[i*BitsPerPointer/8] |= bits<<((i*BitsPerPointer)%8); } - return (BitVector){i*BitsPerPointer, (uint32*)tmpbuf}; + return (BitVector){i*BitsPerPointer, (byte*)tmpbuf}; } diff --git a/src/pkg/runtime/malloc.go b/src/pkg/runtime/malloc.go index 68baa80d5..df030794b 100644 --- a/src/pkg/runtime/malloc.go +++ b/src/pkg/runtime/malloc.go @@ -4,9 +4,7 @@ package runtime -import ( - "unsafe" -) +import "unsafe" const ( flagNoScan = 1 << 0 // GC doesn't have to scan object @@ -278,7 +276,10 @@ func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { // force = 1 - do GC regardless of current heap usage // force = 2 - go GC and eager sweep func gogc(force int32) { - if GOARCH == "power64" || GOARCH == "power64le" || memstats.enablegc == 0 { + if false && (GOARCH == "power64" || GOARCH == "power64le") { + return + } + if memstats.enablegc == 0 { return } diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h index 1e26509bd..41988415e 100644 --- a/src/pkg/runtime/malloc.h +++ b/src/pkg/runtime/malloc.h @@ -568,14 +568,14 @@ typedef struct BitVector BitVector; struct BitVector { int32 n; // # of bits - uint32 *data; + uint8 *bytedata; }; typedef struct StackMap StackMap; struct StackMap { int32 n; // number of bitmaps int32 nbit; // number of bits in each bitmap - uint32 data[]; + uint8 bytedata[]; }; // Returns pointer map data for the given stackmap index // (the index is encoded in PCDATA_StackMapIndex). diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 03622db28..b1a894311 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -64,7 +64,7 @@ enum { Debug = 0, - ConcurrentSweep = 1, + ConcurrentSweep = 0, PreciseScan = 1, WorkbufSize = 4*1024, @@ -75,6 +75,12 @@ enum { RootSpans = 3, RootFlushCaches = 4, RootCount = 5, + +#ifdef _64BIT + byteEndian = BigEndian*7, +#else + byteEndian = BigEndian*3, +#endif }; #define ScanConservatively ((byte*)1) @@ -669,7 +675,7 @@ runtime·stackmapdata(StackMap *stackmap, int32 n) { if(n < 0 || n >= stackmap->n) runtime·throw("stackmapdata: index out of range"); - return (BitVector){stackmap->nbit, stackmap->data + n*((stackmap->nbit+31)/32)}; + return (BitVector){stackmap->nbit, stackmap->bytedata + 4*n*((stackmap->nbit+31)/32)}; } // Scan a stack frame: local variables and function arguments/results. @@ -727,7 +733,7 @@ scanframe(Stkframe *frame, void *unused) } bv = runtime·stackmapdata(stackmap, pcdata); size = (bv.n * PtrSize) / BitsPerPointer; - scanblock(frame->varp - size, bv.n/BitsPerPointer*PtrSize, (byte*)bv.data); + scanblock(frame->varp - size, bv.n/BitsPerPointer*PtrSize, (byte*)bv.bytedata); } // Scan arguments. @@ -735,7 +741,7 @@ scanframe(Stkframe *frame, void *unused) stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps); if(stackmap != nil) { bv = runtime·stackmapdata(stackmap, pcdata); - scanblock(frame->argp, bv.n/BitsPerPointer*PtrSize, (byte*)bv.data); + scanblock(frame->argp, bv.n/BitsPerPointer*PtrSize, (byte*)bv.bytedata); } else { if(Debug > 2) runtime·printf("frame %s conservative args %p+%p\n", runtime·funcname(f), frame->argp, (uintptr)frame->arglen); @@ -1292,6 +1298,8 @@ runtime·gc(int32 force) struct gc_args a; int32 i; +//if(thechar == '9') return; + if(sizeof(Workbuf) != WorkbufSize) runtime·throw("runtime: size of Workbuf is suboptimal"); // The gc is turned off (via enablegc) until @@ -1305,10 +1313,6 @@ runtime·gc(int32 force) if(!mstats.enablegc || g == g->m->g0 || g->m->locks > 0 || runtime·panicking) return; - if(thechar == '9') { - runtime·gcpercent = -1; - return; - } if(runtime·gcpercent == GcpercentUnknown) { // first time through runtime·lock(&runtime·mheap); if(runtime·gcpercent == GcpercentUnknown) @@ -1777,8 +1781,8 @@ unrollgcprog1(byte *mask, byte *prog, uintptr *ppos, bool inplace, bool sparse) b = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; shift = (off % wordsPerBitmapWord) * gcBits; if((shift%8)==0) - ((byte*)b)[shift/8] = 0; - ((byte*)b)[shift/8] |= v<<((shift%8)+2); + ((byte*)b)[(shift/8)^byteEndian] = 0; + ((byte*)b)[(shift/8)^byteEndian] |= v<<((shift%8)+2); pos += PtrSize; } else if(sparse) { // 4-bits per word @@ -1873,7 +1877,7 @@ unrollgcprog(Type *typ) static Lock lock; byte *mask, *prog; uintptr pos; - uint32 x; + uintptr x; runtime·lock(&lock); mask = (byte*)typ->gc[0]; @@ -1888,9 +1892,11 @@ unrollgcprog(Type *typ) 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 = typ->gc[0]; + ((byte*)&x)[0] = 1; + runtime·atomicstorep((void**)mask, (void*)x); } runtime·unlock(&lock); } @@ -1898,7 +1904,7 @@ unrollgcprog(Type *typ) void runtime·markallocated(void *v, uintptr size, uintptr size0, Type *typ, bool scan) { - uintptr *b, off, shift, i, ti, te, nptr, masksize; + uintptr *b, off, shift, i, ti, te, nptr, masksize, maskword; byte *arena_start, x; bool *ptrmask; @@ -1907,7 +1913,7 @@ runtime·markallocated(void *v, uintptr size, uintptr size0, Type *typ, bool sca b = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; shift = (off % wordsPerBitmapWord) * gcBits; if(Debug && (((*b)>>shift)&bitMask) != bitBoundary) { - runtime·printf("runtime: bad bits in markallocated (%p) b=%p[%p]\n", v, b, *b); + runtime·printf("runtime: bad bits in markallocated (%p) b=%p[%p] off=%p shift=%d\n", v, b, *b, off, (int32)shift); runtime·throw("bad bits in markallocated"); } @@ -1916,7 +1922,7 @@ runtime·markallocated(void *v, uintptr size, uintptr size0, Type *typ, bool sca if(size == PtrSize) *b = (*b & ~((bitBoundary|bitPtrMask)<gc[0]; // check whether the program is already unrolled - if((runtime·atomicload((uint32*)ptrmask)&0xff) == 0) + maskword = (uintptr)runtime·atomicloadp((void*)&typ->gc[0]); + if(((byte*)&maskword)[0] == 0) unrollgcprog(typ); ptrmask++; // skip the unroll flag byte } else ptrmask = (byte*)&typ->gc[0]; // embed mask if(size == 2*PtrSize) { - ((byte*)b)[shift/8] = ptrmask[0] | bitAllocated; + ((byte*)b)[(shift/8)^byteEndian] = ptrmask[0] | bitAllocated; return; } te = typ->size/PtrSize; @@ -1959,7 +1966,7 @@ runtime·markallocated(void *v, uintptr size, uintptr size0, Type *typ, bool sca te /= 2; } if(size == 2*PtrSize) { - ((byte*)b)[shift/8] = (BitsPointer<<2) | (BitsPointer<<6) | bitAllocated; + ((byte*)b)[(shift/8)^byteEndian] = (BitsPointer<<2) | (BitsPointer<<6) | bitAllocated; return; } // Copy pointer bitmask into the bitmap. @@ -1977,14 +1984,14 @@ runtime·markallocated(void *v, uintptr size, uintptr size0, Type *typ, bool sca x |= bitAllocated; if(i+PtrSize == size0) x &= ~(bitPtrMask<<4); - ((byte*)b)[shift/8] = x; + ((byte*)b)[(shift/8)^byteEndian] = x; } if(size0 == i && size0 < size) { // mark the word after last object's word as BitsDead off = (uintptr*)((byte*)v + size0) - (uintptr*)arena_start; b = (uintptr*)arena_start - off/wordsPerBitmapWord - 1; shift = (off % wordsPerBitmapWord) * gcBits; - ((byte*)b)[shift/8] = 0; + ((byte*)b)[(shift/8)^byteEndian] = 0; } } @@ -2174,7 +2181,7 @@ runtime·getgcmask(byte *p, Type *t, byte **mask, uintptr *len) *mask = runtime·mallocgc(*len, nil, 0); for(i = 0; i < n; i += PtrSize) { off = (p+i-frame.varp+size)/PtrSize; - bits = (bv.data[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask; + bits = (bv.bytedata[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask; (*mask)[i/PtrSize] = bits; } } diff --git a/src/pkg/runtime/mgc0.h b/src/pkg/runtime/mgc0.h index 3b1c5ba8c..99271a532 100644 --- a/src/pkg/runtime/mgc0.h +++ b/src/pkg/runtime/mgc0.h @@ -7,6 +7,13 @@ enum { ScanStackByFrames = 1, + // TODO(rsc): Half the code in the garbage collector + // now accesses the bitmap as an array of bytes + // instead of as an array of uintptrs. + // This is tricky to do correctly in a portable fashion. + // (It breaks on big-endian systems.) + // Should we just make the bitmap a byte array? + // Four bits per word (see #defines below). wordsPerBitmapWord = sizeof(void*)*8/4, gcBits = 4, diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c index 49ecd6cc3..88f24408b 100644 --- a/src/pkg/runtime/stack.c +++ b/src/pkg/runtime/stack.c @@ -543,8 +543,8 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f) num = bv->n / BitsPerPointer; for(i = 0; i < num; i++) { if(StackDebug >= 4) - runtime·printf(" %p:%s:%p\n", &scanp[i], mapnames[bv->data[i / (32 / BitsPerPointer)] >> (i * BitsPerPointer & 31) & 3], scanp[i]); - switch(bv->data[i / (32 / BitsPerPointer)] >> (i * BitsPerPointer & 31) & 3) { + runtime·printf(" %p:%s:%p\n", &scanp[i], mapnames[bv->bytedata[i / (8 / BitsPerPointer)] >> (i * BitsPerPointer & 7) & 3], scanp[i]); + switch(bv->bytedata[i / (8 / BitsPerPointer)] >> (i * BitsPerPointer & 7) & 3) { case BitsDead: if(runtime·debug.gcdead) scanp[i] = (byte*)PoisonStack; @@ -567,7 +567,7 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f) } break; case BitsMultiWord: - switch(bv->data[(i+1) / (32 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 31) & 3) { + switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 7) & 3) { case BitsString: // string referents are never on the stack, never need to be adjusted i++; // skip len -- cgit v1.2.1 From 820abe2364e4469bee248143a379a63622091fbb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 15 Aug 2014 15:28:08 -0400 Subject: [dev.power64] runtime: fix usleep not to smash saved LR LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/130760043 --- src/pkg/runtime/sys_linux_power64x.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index 1d985d1af..fbd59a052 100644 --- a/src/pkg/runtime/sys_linux_power64x.s +++ b/src/pkg/runtime/sys_linux_power64x.s @@ -91,17 +91,17 @@ TEXT runtime·usleep(SB),NOSPLIT,$-8-16 MOVD R3, R5 MOVW $1000000, R4 DIVD R4, R3 - MOVD R3, 0(R1) + MOVD R3, 8(R1) MULLD R3, R4 SUB R4, R5 - MOVD R5, 8(R1) + MOVD R5, 16(R1) // select(0, 0, 0, 0, &tv) MOVW $0, R3 MOVW $0, R4 MOVW $0, R5 MOVW $0, R6 - MOVD R1, R7 + ADD $8, R1, R7 SYSCALL $SYS_newselect RETURN -- cgit v1.2.1 From a78e6cc8d5fffdc680350684a9c0d92d4eaf6328 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Fri, 15 Aug 2014 15:31:54 -0400 Subject: [dev.power64] liblink: fix g->panicwrap update code generation LGTM=rsc R=golang-codereviews, rsc CC=golang-codereviews https://codereview.appspot.com/123400043 --- src/liblink/obj9.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src') diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 3405fce47..28793676c 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -512,6 +512,36 @@ addstacksplit(Link *ctxt, LSym *cursym) p->to.type = D_BRANCH; break; } + if(cursym->text->reg & WRAPPER) { + // g->panicwrap -= autosize; + // MOVWZ panicwrap_offset(g), R3 + // ADD $-autosize, R3 + // MOVWZ R3, panicwrap_offset(g) + p->as = AMOVWZ; + p->from.type = D_OREG; + p->from.reg = REGG; + p->from.offset = 2*ctxt->arch->ptrsize; + p->to.type = D_REG; + p->to.reg = 3; + p = appendp(ctxt, p); + + p->as = AADD; + p->from.type = D_CONST; + p->from.offset = -autosize; + p->to.type = D_REG; + p->to.reg = 3; + p = appendp(ctxt, p); + + p->as = AMOVWZ; + p->from.type = D_REG; + p->from.reg = 3; + p->to.type = D_OREG; + p->to.reg = REGG; + p->to.offset = 2*ctxt->arch->ptrsize; + p = appendp(ctxt, p); + + p->as = ARETURN; + } if(cursym->text->mark & LEAF) { if(!autosize) { p->as = ABR; -- cgit v1.2.1 From ebe8a09fb603d9510cb982a6c11a3e1638f7f8fb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 18 Aug 2014 22:24:15 -0400 Subject: [dev.power64] liblink: recognize add instruction as adjusting SP LGTM=minux R=minux CC=golang-codereviews https://codereview.appspot.com/128360043 Committer: Shenghou Ma --- src/liblink/list9.c | 2 ++ src/liblink/obj9.c | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/liblink/list9.c b/src/liblink/list9.c index 9700a1684..9e205b7a9 100644 --- a/src/liblink/list9.c +++ b/src/liblink/list9.c @@ -125,6 +125,8 @@ Pconv(Fmt *fp) 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); } diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 28793676c..d0c14dfb5 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -617,6 +617,10 @@ addstacksplit(Link *ctxt, LSym *cursym) 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; } } -- cgit v1.2.1 From c17ee649b04ecdbe973d13f4b6ef087947ba80ea Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 1 Oct 2014 17:38:09 -0400 Subject: [dev.garbage] cmd/gc: never generate BitsMultiWord LGTM=rlh R=rlh, minux CC=golang-codereviews https://codereview.appspot.com/151940043 --- src/cmd/gc/reflect.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index 4892ab757..e229b3075 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -1506,11 +1506,9 @@ gengcprog1(ProgGen *g, Type *t, vlong *xoffset) *xoffset += t->width; break; case TINTER: - proggendata(g, BitsMultiWord); - if(isnilinter(t)) - proggendata(g, BitsEface); - else - proggendata(g, BitsIface); + // Assuming IfacePointerOnly=1. + proggendata(g, BitsPointer); + proggendata(g, BitsPointer); *xoffset += t->width; break; case TARRAY: -- cgit v1.2.1 From 59a42ca068d7cbe0b92f2f68768129599a6c42f8 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 2 Oct 2014 14:26:04 -0400 Subject: [dev.garbage] runtime: remove another BitsMultiWord Not found because it was not used by name. Add name in comments for what's left behind. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/148430043 --- src/cmd/gc/plive.c | 19 ++++++------------- src/runtime/gcinfo_test.go | 4 ++-- 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c index 0feb2c710..3bfa69b1f 100644 --- a/src/cmd/gc/plive.c +++ b/src/cmd/gc/plive.c @@ -1092,7 +1092,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) case TCOMPLEX64: case TCOMPLEX128: for(i = 0; i < t->width; i++) { - bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar + bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar (BitsScalar) } *xoffset += t->width; break; @@ -1105,7 +1105,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) case TMAP: if((*xoffset & (widthptr-1)) != 0) fatal("twobitwalktype1: invalid alignment, %T", t); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr (BitsPointer) *xoffset += t->width; break; @@ -1113,7 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) // struct { byte *str; intgo len; } if((*xoffset & (widthptr-1)) != 0) fatal("twobitwalktype1: invalid alignment, %T", t); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer) *xoffset += t->width; break; @@ -1123,15 +1123,8 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) // struct { Type *type; union { void *ptr, uintptr val } data; } if((*xoffset & (widthptr-1)) != 0) fatal("twobitwalktype1: invalid alignment, %T", t); - bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 0); - bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1); // 3 = multiword - // next word contains 2 = Iface, 3 = Eface - if(isnilinter(t)) { - bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 2); - bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3); - } else { - bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3); - } + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer) + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 3); // 2 = live ptr in second slot (BitsPointer) *xoffset += t->width; break; @@ -1144,7 +1137,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv) // struct { byte *array; uintgo len; uintgo cap; } if((*xoffset & (widthptr-1)) != 0) fatal("twobitwalktype1: invalid TARRAY alignment, %T", t); - bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot + bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer) *xoffset += t->width; } else for(i = 0; i < t->bound; i++) diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go index 88f6703f9..e74d8c2c0 100644 --- a/src/runtime/gcinfo_test.go +++ b/src/runtime/gcinfo_test.go @@ -188,6 +188,6 @@ var ( infoString = []byte{BitsPointer, BitsDead} infoSlice = []byte{BitsPointer, BitsDead, BitsDead} - infoEface = []byte{BitsMultiWord, BitsEface} - infoIface = []byte{BitsMultiWord, BitsIface} + infoEface = []byte{BitsPointer, BitsPointer} + infoIface = []byte{BitsPointer, BitsPointer} ) -- cgit v1.2.1 From 5fc8be8db6a4e7a0e43718e6b21d2b78e5aacf5f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 2 Oct 2014 16:49:11 -0400 Subject: [dev.garbage] runtime: make sure G.param and SudoG.elem do not hold stale pointers In old conservative Go, this could cause memory leaks. A new pickier collector might reasonably crash when it saw one of these. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/147480043 --- src/runtime/chan.go | 11 +++++++++-- src/runtime/proc.go | 13 +++++++++++++ src/runtime/select.go | 7 +++++++ src/runtime/sema.go | 1 + 4 files changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/runtime/chan.go b/src/runtime/chan.go index 48925b2e3..10503f4e1 100644 --- a/src/runtime/chan.go +++ b/src/runtime/chan.go @@ -140,10 +140,11 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin unlock(&c.lock) recvg := sg.g - recvg.param = unsafe.Pointer(sg) if sg.elem != nil { memmove(unsafe.Pointer(sg.elem), ep, uintptr(c.elemsize)) + sg.elem = nil } + recvg.param = unsafe.Pointer(sg) if sg.releasetime != 0 { sg.releasetime = cputicks() } @@ -179,6 +180,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin } panic("send on closed channel") } + gp.param = nil if mysg.releasetime > 0 { blockevent(int64(mysg.releasetime)-t0, 2) } @@ -278,6 +280,7 @@ func closechan(c *hchan) { break } gp := sg.g + sg.elem = nil gp.param = nil if sg.releasetime != 0 { sg.releasetime = cputicks() @@ -292,6 +295,7 @@ func closechan(c *hchan) { break } gp := sg.g + sg.elem = nil gp.param = nil if sg.releasetime != 0 { sg.releasetime = cputicks() @@ -372,6 +376,7 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r if ep != nil { memmove(ep, sg.elem, uintptr(c.elemsize)) } + sg.elem = nil gp := sg.g gp.param = unsafe.Pointer(sg) if sg.releasetime != 0 { @@ -409,9 +414,11 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r if mysg.releasetime > 0 { blockevent(mysg.releasetime-t0, 2) } + haveData := gp.param != nil + gp.param = nil releaseSudog(mysg) - if gp.param != nil { + if haveData { // a sender sent us some data. It already wrote to ep. selected = true received = true diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 9b9586859..eefe8239f 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -148,6 +148,9 @@ func acquireSudog() *sudog { c := gomcache() s := c.sudogcache if s != nil { + if s.elem != nil { + gothrow("acquireSudog: found s.elem != nil in cache") + } c.sudogcache = s.next return s } @@ -162,12 +165,22 @@ func acquireSudog() *sudog { // which keeps the garbage collector from being invoked. mp := acquirem() p := new(sudog) + if p.elem != nil { + gothrow("acquireSudog: found p.elem != nil after new") + } releasem(mp) return p } //go:nosplit func releaseSudog(s *sudog) { + if s.elem != nil { + gothrow("runtime: sudog with non-nil elem") + } + gp := getg() + if gp.param != nil { + gothrow("runtime: releaseSudog with non-nil gp.param") + } c := gomcache() s.next = c.sudogcache c.sudogcache = s diff --git a/src/runtime/select.go b/src/runtime/select.go index 7716d2d4b..1bcea8c4b 100644 --- a/src/runtime/select.go +++ b/src/runtime/select.go @@ -368,6 +368,7 @@ loop: // someone woke us up sellock(sel) sg = (*sudog)(gp.param) + gp.param = nil // pass 3 - dequeue from unsuccessful chans // otherwise they stack up on quiet channels @@ -376,6 +377,10 @@ loop: // iterating through the linked list they are in reverse order. cas = nil sglist = gp.waiting + // Clear all elem before unlinking from gp.waiting. + for sg1 := gp.waiting; sg1 != nil; sg1 = sg1.waitlink { + sg1.elem = nil + } gp.waiting = nil for i := int(sel.ncase) - 1; i >= 0; i-- { k = &scases[pollorder[i]] @@ -506,6 +511,7 @@ syncrecv: if cas.elem != nil { memmove(cas.elem, sg.elem, uintptr(c.elemsize)) } + sg.elem = nil gp = sg.g gp.param = unsafe.Pointer(sg) if sg.releasetime != 0 { @@ -541,6 +547,7 @@ syncsend: if sg.elem != nil { memmove(sg.elem, cas.elem, uintptr(c.elemsize)) } + sg.elem = nil gp = sg.g gp.param = unsafe.Pointer(sg) if sg.releasetime != 0 { diff --git a/src/runtime/sema.go b/src/runtime/sema.go index beacd6716..142d3082c 100644 --- a/src/runtime/sema.go +++ b/src/runtime/sema.go @@ -168,6 +168,7 @@ func (root *semaRoot) dequeue(s *sudog) { } else { root.head = s.next } + s.elem = nil s.next = nil s.prev = nil } -- cgit v1.2.1 From 4eb6792aa572c7e6d3448d4cf22223b61b65724f Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Fri, 3 Oct 2014 11:33:57 -0400 Subject: [dev.garbage] runtime: scan and mark phase refactoring Refactoring of the scan and mark phase so that concurrent GC, in particular the write barrier, can share a common infrastructure. Now that the scan and mark phases have been separated we will be able to scan stacks without blackening any objects. This in turn will allow us to delay installing expensive write barrier code. LGTM=rsc R=rsc, khr, dvyukov CC=golang-codereviews https://codereview.appspot.com/145640044 Committer: Russ Cox --- src/runtime/malloc.h | 10 +- src/runtime/mgc0.c | 627 ++++++++++++++++++++++++++++++-------------------- src/runtime/proc.c | 3 +- src/runtime/runtime.h | 27 ++- 4 files changed, 404 insertions(+), 263 deletions(-) (limited to 'src') diff --git a/src/runtime/malloc.h b/src/runtime/malloc.h index 3f1981f70..413870c9f 100644 --- a/src/runtime/malloc.h +++ b/src/runtime/malloc.h @@ -86,6 +86,7 @@ typedef struct MSpan MSpan; typedef struct MStats MStats; typedef struct MLink MLink; typedef struct GCStats GCStats; +typedef struct Workbuf Workbuf; enum { @@ -337,8 +338,11 @@ struct MCache StackFreeList stackcache[NumStackOrders]; SudoG* sudogcache; - - void* gcworkbuf; + // Cached P local buffer holding grey objects (marked by not yet scanned) + // Used by mutator for write barrier work. + // GC uses the mcache of the P it is running on for stack and global scanning + // work as well marking. + Workbuf* gcworkbuf; // Local allocator stats, flushed during GC. uintptr local_nlookup; // number of pointer lookups @@ -350,7 +354,7 @@ struct MCache MSpan* runtime·MCache_Refill(MCache *c, int32 sizeclass); void runtime·MCache_ReleaseAll(MCache *c); void runtime·stackcache_clear(MCache *c); -void runtime·gcworkbuffree(void *b); +void runtime·gcworkbuffree(Workbuf *b); enum { diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 7a3498ae1..b4cd3474d 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -66,7 +66,6 @@ enum { Debug = 0, ConcurrentSweep = 1, - WorkbufSize = 4*1024, FinBlockSize = 4*1024, RootData = 0, RootBss = 1, @@ -97,12 +96,12 @@ extern int32 runtime·gcpercent; // uint32 runtime·worldsema = 1; -typedef struct Workbuf Workbuf; -struct Workbuf -{ - LFNode node; // must be first - uintptr nobj; - byte* obj[(WorkbufSize-sizeof(LFNode)-sizeof(uintptr))/PtrSize]; +typedef struct Markbits Markbits; +struct Markbits { + byte *bitp; // pointer to the byte holding xbits + byte shift; // bits xbits needs to be shifted to get bits + byte xbits; // byte holding all the bits from *bitp + byte bits; // bits relevant to corresponding slot. }; extern byte runtime·data[]; @@ -127,15 +126,22 @@ BitVector runtime·gcbssmask; Mutex runtime·gclock; +static Workbuf* getpartial(void); +static void putpartial(Workbuf*); static Workbuf* getempty(Workbuf*); static Workbuf* getfull(Workbuf*); static void putempty(Workbuf*); static Workbuf* handoff(Workbuf*); static void gchelperstart(void); static void flushallmcaches(void); -static bool scanframe(Stkframe *frame, void *unused); -static void scanstack(G *gp); -static BitVector unrollglobgcprog(byte *prog, uintptr size); +static bool scanframe(Stkframe*, void*); +static void scanstack(G*); +static BitVector unrollglobgcprog(byte*, uintptr); +static void scanblock(byte*, uintptr, byte*); +static byte* objectstart(byte*, Markbits*); +static Workbuf* greyobject(byte*, Markbits*, Workbuf*); +static bool inheap(byte*); +static void slottombits(byte*, Markbits*); void runtime·bgsweep(void); static FuncVal bgsweepv = {runtime·bgsweep}; @@ -156,258 +162,279 @@ static struct { uint32 nspan; } work; -// scanblock scans a block of n bytes starting at pointer b for references -// to other objects, scanning any it finds recursively until there are no -// unscanned objects left. Instead of using an explicit recursion, it keeps -// a work list in the Workbuf* structures and loops in the main function -// body. Keeping an explicit work list is easier on the stack allocator and -// more efficient. +// Is address b in the known heap. If it doesn't have a valid gcmap +// returns false. For example pointers into stacks will return false. +static bool +inheap(byte *b) +{ + MSpan *s; + pageID k; + uintptr x; + + if(b == nil || b < runtime·mheap.arena_start || b >= runtime·mheap.arena_used) + return false; + // Not a beginning of a block, consult span table to find the block beginning. + k = (uintptr)b>>PageShift; + x = k; + x -= (uintptr)runtime·mheap.arena_start>>PageShift; + s = runtime·mheap.spans[x]; + if(s == nil || k < s->start || b >= s->limit || s->state != MSpanInUse) + return false; + return true; +} + +// Given an address in the heap return the relevant byte from the gcmap. This routine +// can be used on addresses to the start of an object or to the interior of the an object. static void -scanblock(byte *b, uintptr n, byte *ptrmask) +slottombits(byte *obj, Markbits *mbits) { - byte *obj, *p, *arena_start, *arena_used, **wp, *scanbuf[8], *ptrbitp, *bitp, bits, xbits, shift, cached; - uintptr i, nobj, size, idx, x, off, scanbufpos; - intptr ncached; - Workbuf *wbuf; - Iface *iface; - Eface *eface; - Type *typ; + uintptr off; + + off = (uintptr*)((uintptr)obj&~(PtrSize-1)) - (uintptr*)runtime·mheap.arena_start; + mbits->bitp = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1; + mbits->shift = (off % wordsPerBitmapByte) * gcBits; + mbits->xbits = *mbits->bitp; + mbits->bits = (mbits->xbits >> mbits->shift) & bitMask; +} + +// b is a pointer into the heap. +// Find the start of the object refered to by b. +// Set mbits to the associated bits from the bit map. +static byte* +objectstart(byte *b, Markbits *mbits) +{ + byte *obj, *p; MSpan *s; pageID k; - bool keepworking; + uintptr x, size, idx; - // Cache memory arena parameters in local vars. - arena_start = runtime·mheap.arena_start; - arena_used = runtime·mheap.arena_used; + obj = (byte*)((uintptr)b&~(PtrSize-1)); + for(;;) { + slottombits(obj, mbits); + if(mbits->bits&bitBoundary == bitBoundary) + break; + + // Not a beginning of a block, consult span table to find the block beginning. + k = (uintptr)obj>>PageShift; + x = k; + x -= (uintptr)runtime·mheap.arena_start>>PageShift; + s = runtime·mheap.spans[x]; + if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse){ + if(s->state == MSpanStack) + break; // This is legit. + + // The following is catching some bugs left over from + // us not being rigerous about what data structures are + // hold valid pointers and different parts of the system + // considering different structures as roots. For example + // if there is a pointer into a stack that is left in + // a global data structure but that part of the runtime knows that + // those structures will be reinitialized before they are + // reused. Unfortunately the GC believes these roots are valid. + // Typically a stack gets moved and only the structures that part of + // the system knows are alive are updated. The span is freed + // after the stack copy and the pointer is still alive. This + // check is catching that bug but for now we will not throw, + // instead we will simply break out of this routine and depend + // on the caller to recognize that this pointer is not a valid + // heap pointer. I leave the code that catches the bug so that once + // resolved we can turn this check back on and throw. + + //runtime·printf("Runtime: Span weird: obj=%p, k=%p", obj, k); + //if (s == nil) + // runtime·printf(" s=nil\n"); + //else + // runtime·printf(" s->start=%p s->limit=%p, s->state=%d\n", s->start*PageSize, s->limit, s->state); + //runtime·throw("Blowup on weird span"); + break; // We are not in a real block throw?? + } + p = (byte*)((uintptr)s->start<sizeclass != 0) { + size = s->elemsize; + idx = ((byte*)obj - p)/size; + p = p+idx*size; + } + if(p == obj) { + runtime·printf("runtime: failed to find block beginning for %p s=%p s->limit=%p\n", + p, s->start*PageSize, s->limit); + runtime·throw("failed to find block beginning"); + } + obj = p; + } + // if size(obj.firstfield) < PtrSize, the &obj.secondfield could map to the boundary bit + // Clear any low bits to get to the start of the object. + // greyobject depends on this. + return obj; +} - wbuf = getempty(nil); - nobj = wbuf->nobj; - wp = &wbuf->obj[nobj]; - keepworking = b == nil; - scanbufpos = 0; - for(i = 0; i < nelem(scanbuf); i++) - scanbuf[i] = nil; +// obj is the start of an object with mark mbits. +// If it isn't already marked, mark it and enqueue into workbuf. +// Return possibly new workbuf to use. +static Workbuf* +greyobject(byte *obj, Markbits *mbits, Workbuf *wbuf) +{ + // obj should be start of allocation, and so must be at least pointer-aligned. + if(((uintptr)obj & (PtrSize-1)) != 0) + runtime·throw("greyobject: obj not pointer-aligned"); + + // If marked we have nothing to do. + if((mbits->bits&bitMarked) != 0) + return wbuf; + + // Each byte of GC bitmap holds info for two words. + // If the current object is larger than two words, or if the object is one word + // but the object it shares the byte with is already marked, + // then all the possible concurrent updates are trying to set the same bit, + // so we can use a non-atomic update. + if((mbits->xbits&(bitMask|(bitMask<bitp = mbits->xbits | (bitMarked<shift); + else + runtime·atomicor8(mbits->bitp, bitMarked<shift); + + if(((mbits->xbits>>(mbits->shift+2))&BitsMask) == BitsDead) + return wbuf; // noscan object + + // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but + // seems like a nice optimization that can be added back in. + // There needs to be time between the PREFETCH and the use. + // Previously we put the obj in an 8 element buffer that is drained at a rate + // to give the PREFETCH time to do its work. + // Use of PREFETCHNTA might be more appropriate than PREFETCH + + // If workbuf is full, obtain an empty one. + if(wbuf->nobj >= nelem(wbuf->obj)) { + wbuf = getempty(wbuf); + } + + wbuf->obj[wbuf->nobj] = obj; + wbuf->nobj++; + return wbuf; +} +// Scan the object b of size n, adding pointers to wbuf. +// Return possibly new wbuf to use. +// If ptrmask != nil, it specifies where pointers are in b. +// If ptrmask == nil, the GC bitmap should be consulted. +// In this case, n may be an overestimate of the size; the GC bitmap +// must also be used to make sure the scan stops at the end of b. +static Workbuf* +scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf) +{ + byte *obj, *arena_start, *arena_used, *ptrbitp, bits, cshift, cached; + uintptr i; + intptr ncached; + Markbits mbits; + + arena_start = (byte*)runtime·mheap.arena_start; + arena_used = runtime·mheap.arena_used; ptrbitp = nil; cached = 0; ncached = 0; + // Find bits of the beginning of the object. + if(ptrmask == nil) { + b = objectstart(b, &mbits); + ptrbitp = mbits.bitp; //arena_start - off/wordsPerBitmapByte - 1; + cshift = mbits.shift; //(off % wordsPerBitmapByte) * gcBits; + cached = *ptrbitp >> cshift; + cached &= ~bitBoundary; + ncached = (8 - cshift)/gcBits; + } + for(i = 0; i < n; i += PtrSize) { + // Find bits for this word. + if(ptrmask != nil) { + // dense mask (stack or data) + bits = (ptrmask[(i/PtrSize)/4]>>(((i/PtrSize)%4)*BitsPerPointer))&BitsMask; + } else { + // Check if we have reached end of span. + if((((uintptr)b+i)%PageSize) == 0 && + runtime·mheap.spans[(b-arena_start)>>PageShift] != runtime·mheap.spans[(b+i-arena_start)>>PageShift]) + break; + // Consult GC bitmap. + if(ncached <= 0) { + // Refill cache. + cached = *--ptrbitp; + ncached = 2; + } + bits = cached; + cached >>= gcBits; + ncached--; + + if((bits&bitBoundary) != 0) + break; // reached beginning of the next object + bits = (bits>>2)&BitsMask; + if(bits == BitsDead) + break; // reached no-scan part of the object + } + + if(bits == BitsScalar || bits == BitsDead) + continue; + if(bits != BitsPointer) + runtime·throw("unexpected garbage collection bits"); + + obj = *(byte**)(b+i); + // At this point we have extracted the next potential pointer. + // Check if it points into heap. + if(obj == nil || obj < arena_start || obj >= arena_used) + continue; + // Mark the object. return some important bits. + // We we combine the following two rotines we don't have to pass mbits or obj around. + obj = objectstart(obj, &mbits); + wbuf = greyobject(obj, &mbits, wbuf); + } + return wbuf; +} + +// scanblock starts by scanning b as scanobject would. +// If the gcphase is GCscan, that's all scanblock does. +// Otherwise it traverses some fraction of the pointers it found in b, recursively. +// As a special case, scanblock(nil, 0, nil) means to scan previously queued work, +// stopping only when no work is left in the system. +static void +scanblock(byte *b, uintptr n, byte *ptrmask) +{ + Workbuf *wbuf; + bool keepworking; + + wbuf = getpartial(); + if(b != nil) { + wbuf = scanobject(b, n, ptrmask, wbuf); + if(runtime·gcphase == GCscan) { + putpartial(wbuf); + return; + } + } + + keepworking = b == nil; + // ptrmask can have 2 possible values: // 1. nil - obtain pointer mask from GC bitmap. // 2. pointer to a compact mask (for stacks and data). - if(b != nil) - goto scanobj; for(;;) { - if(nobj == 0) { - // Out of work in workbuf. - // First, see is there is any work in scanbuf. - for(i = 0; i < nelem(scanbuf); i++) { - b = scanbuf[scanbufpos]; - scanbuf[scanbufpos++] = nil; - if(scanbufpos == nelem(scanbuf)) - scanbufpos = 0; - if(b != nil) { - n = arena_used - b; // scan until bitBoundary or BitsDead - ptrmask = nil; // use GC bitmap for pointer info - goto scanobj; - } - } + if(wbuf->nobj == 0) { if(!keepworking) { putempty(wbuf); return; } // Refill workbuf from global queue. wbuf = getfull(wbuf); - if(wbuf == nil) + if(wbuf == nil) // nil means out of work barrier reached return; - nobj = wbuf->nobj; - wp = &wbuf->obj[nobj]; } // If another proc wants a pointer, give it some. - if(work.nwait > 0 && nobj > 4 && work.full == 0) { - wbuf->nobj = nobj; + if(work.nwait > 0 && wbuf->nobj > 4 && work.full == 0) { wbuf = handoff(wbuf); - nobj = wbuf->nobj; - wp = &wbuf->obj[nobj]; - } - - wp--; - nobj--; - b = *wp; - n = arena_used - b; // scan until next bitBoundary or BitsDead - ptrmask = nil; // use GC bitmap for pointer info - - scanobj: - // Find bits of the beginning of the object. - if(ptrmask == nil) { - off = (uintptr*)b - (uintptr*)arena_start; - ptrbitp = arena_start - off/wordsPerBitmapByte - 1; - shift = (off % wordsPerBitmapByte) * gcBits; - cached = *ptrbitp >> shift; - cached &= ~bitBoundary; - ncached = (8 - shift)/gcBits; - } - for(i = 0; i < n; i += PtrSize) { - obj = nil; - // Find bits for this word. - if(ptrmask == nil) { - // Check is we have reached end of span. - if((((uintptr)b+i)%PageSize) == 0 && - runtime·mheap.spans[(b-arena_start)>>PageShift] != runtime·mheap.spans[(b+i-arena_start)>>PageShift]) - break; - // Consult GC bitmap. - if(ncached <= 0) { - // Refill cache. - cached = *--ptrbitp; - ncached = 2; - } - bits = cached; - cached >>= gcBits; - ncached--; - if((bits&bitBoundary) != 0) - break; // reached beginning of the next object - bits = (bits>>2)&BitsMask; - if(bits == BitsDead) - break; // reached no-scan part of the object - } else // dense mask (stack or data) - bits = (ptrmask[(i/PtrSize)/4]>>(((i/PtrSize)%4)*BitsPerPointer))&BitsMask; - - if(bits == BitsScalar || bits == BitsDead) - continue; - if(bits == BitsPointer) { - obj = *(byte**)(b+i); - goto markobj; - } - - // With those three out of the way, must be multi-word. - if(bits != BitsMultiWord) - runtime·throw("unexpected garbage collection bits"); - // Find the next pair of bits. - if(ptrmask == nil) { - if(ncached <= 0) { - // Refill cache. - cached = *--ptrbitp; - ncached = 2; - } - bits = (cached>>2)&BitsMask; - } else - bits = (ptrmask[((i+PtrSize)/PtrSize)/4]>>((((i+PtrSize)/PtrSize)%4)*BitsPerPointer))&BitsMask; - - switch(bits) { - default: - runtime·throw("unexpected garbage collection bits"); - case BitsIface: - iface = (Iface*)(b+i); - if(iface->tab != nil) { - typ = iface->tab->type; - if(!(typ->kind&KindDirectIface) || !(typ->kind&KindNoPointers)) - obj = iface->data; - } - break; - case BitsEface: - eface = (Eface*)(b+i); - typ = eface->type; - if(typ != nil) { - if(!(typ->kind&KindDirectIface) || !(typ->kind&KindNoPointers)) - obj = eface->data; - } - break; - } - - i += PtrSize; - cached >>= gcBits; - ncached--; - - markobj: - // At this point we have extracted the next potential pointer. - // Check if it points into heap. - if(obj == nil || obj < arena_start || obj >= arena_used) - continue; - // Mark the object. - off = (uintptr*)obj - (uintptr*)arena_start; - bitp = arena_start - off/wordsPerBitmapByte - 1; - shift = (off % wordsPerBitmapByte) * gcBits; - xbits = *bitp; - bits = (xbits >> shift) & bitMask; - if((bits&bitBoundary) == 0) { - // Not a beginning of a block, consult span table to find the block beginning. - k = (uintptr)obj>>PageShift; - x = k; - x -= (uintptr)arena_start>>PageShift; - s = runtime·mheap.spans[x]; - if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse) - continue; - p = (byte*)((uintptr)s->start<sizeclass != 0) { - size = s->elemsize; - idx = ((byte*)obj - p)/size; - p = p+idx*size; - } - if(p == obj) { - runtime·printf("runtime: failed to find block beginning for %p s=%p s->limit=%p\n", - p, s->start*PageSize, s->limit); - runtime·throw("failed to find block beginning"); - } - obj = p; - goto markobj; - } - - // Now we have bits, bitp, and shift correct for - // obj pointing at the base of the object. - // Only care about not marked objects. - if((bits&bitMarked) != 0) - continue; - // If obj size is greater than 8, then each byte of GC bitmap - // contains info for at most one object. In such case we use - // non-atomic byte store to mark the object. This can lead - // to double enqueue of the object for scanning, but scanning - // is an idempotent operation, so it is OK. This cannot lead - // to bitmap corruption because the single marked bit is the - // only thing that can change in the byte. - // For 8-byte objects we use non-atomic store, if the other - // quadruple is already marked. Otherwise we resort to CAS - // loop for marking. - if((xbits&(bitMask|(bitMask<>(shift+2))&BitsMask) == BitsDead) - continue; // noscan object - - // Queue the obj for scanning. - PREFETCH(obj); - obj = (byte*)((uintptr)obj & ~(PtrSize-1)); - p = scanbuf[scanbufpos]; - scanbuf[scanbufpos++] = obj; - if(scanbufpos == nelem(scanbuf)) - scanbufpos = 0; - if(p == nil) - continue; - - // If workbuf is full, obtain an empty one. - if(nobj >= nelem(wbuf->obj)) { - wbuf->nobj = nobj; - wbuf = getempty(wbuf); - nobj = wbuf->nobj; - wp = &wbuf->obj[nobj]; - } - *wp = p; - wp++; - nobj++; } - if(Debug && ptrmask == nil) { - // For heap objects ensure that we did not overscan. - n = 0; - p = nil; - if(!runtime·mlookup(b, &p, &n, nil) || b != p || i > n) { - runtime·printf("runtime: scanned (%p,%p), heap object (%p,%p)\n", b, i, p, n); - runtime·throw("scanblock: scanned invalid object"); - } - } + // This might be a good place to add prefetch code... + // if(wbuf->nobj > 4) { + // PREFETCH(wbuf->obj[wbuf->nobj - 3]; + // } + --wbuf->nobj; + b = wbuf->obj[wbuf->nobj]; + wbuf = scanobject(b, runtime·mheap.arena_used - b, nil, wbuf); } } @@ -460,7 +487,8 @@ markroot(ParFor *desc, uint32 i) spf = (SpecialFinalizer*)sp; // A finalizer can be set for an inner byte of an object, find object beginning. p = (void*)((s->start << PageShift) + spf->special.offset/s->elemsize*s->elemsize); - scanblock(p, s->elemsize, nil); + if(runtime·gcphase != GCscan) + scanblock(p, s->elemsize, nil); // Scanned during mark phase scanblock((void*)&spf->fn, PtrSize, oneptr); } } @@ -477,7 +505,7 @@ markroot(ParFor *desc, uint32 i) gp = runtime·allg[i - RootCount]; // remember when we've first observed the G blocked // needed only to output in traceback - status = runtime·readgstatus(gp); + status = runtime·readgstatus(gp); // We are not in a scan state if((status == Gwaiting || status == Gsyscall) && gp->waitsince == 0) gp->waitsince = work.tstart; // Shrink a stack if not much of it is being used. @@ -487,7 +515,31 @@ markroot(ParFor *desc, uint32 i) else gp->gcworkdone = false; restart = runtime·stopg(gp); - scanstack(gp); + + // goroutine will scan its own stack when it stops running. + // Wait until it has. + while((status = runtime·readgstatus(gp)) == Grunning && !gp->gcworkdone) { + if(status == Gdead) { + // TBD you need to explain why Gdead without gp->gcworkdone + // being true. If there is a race then it needs to be + // explained here. + gp->gcworkdone = true; // scan is a noop + break; + //do nothing, scan not needed. + } + // try again + } + + // scanstack(gp); now done as part of gcphasework + // But to make sure we finished we need to make sure that + // the stack traps have all responded so drop into + // this while loop until they respond. + if(!gp->gcworkdone) + // For some reason a G has not completed its work. This is a bug that + // needs to be investigated. For now I'll just print this message in + // case the bug is benign. + runtime·printf("runtime:markroot: post stack scan work not done gp=%p has status %x\n", gp, status); + if(restart) runtime·restartg(gp); break; @@ -511,8 +563,12 @@ getempty(Workbuf *b) } if(b == nil) b = (Workbuf*)runtime·lfstackpop(&work.empty); - if(b == nil) + if(b == nil) { b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys); + b->nobj = 0; + } + if(b->nobj != 0) + runtime·throw("getempty: b->nobj not 0/n"); b->nobj = 0; return b; } @@ -522,6 +578,8 @@ putempty(Workbuf *b) { MCache *c; + if(b->nobj != 0) + runtime·throw("putempty: b->nobj=%D not 0\n"); c = g->m->mcache; if(c->gcworkbuf == nil) { c->gcworkbuf = b; @@ -530,21 +588,70 @@ putempty(Workbuf *b) runtime·lfstackpush(&work.empty, &b->node); } +// Get an partially empty work buffer from the mcache structure +// and if non is available get an empty one. +static Workbuf* +getpartial(void) +{ + MCache *c; + Workbuf *b; + + c = g->m->mcache; + if(c->gcworkbuf != nil) { + b = c->gcworkbuf; + c->gcworkbuf = nil; + } else { + b = getempty(nil); + } + return b; +} + +static void +putpartial(Workbuf *b) +{ + MCache *c; + + c = g->m->mcache; + if(c->gcworkbuf == nil) { + c->gcworkbuf = b; + return; + } + + runtime·throw("putpartial: c->gcworkbuf is not nil\n"); + + runtime·lfstackpush(&work.full, &b->node); +} + void -runtime·gcworkbuffree(void *b) +runtime·gcworkbuffree(Workbuf *b) { - if(b != nil) + if(b != nil) { + if(b->nobj != 0) + runtime·throw("gcworkbufferfree: b->nobj not 0\n"); putempty(b); + } } + // Get a full work buffer off the work.full list, or return nil. +// getfull acts as a barrier for work.nproc helpers. As long as one +// gchelper is actively marking objects it +// may create a workbuffer that the other helpers can work on. +// The for loop either exits when a work buffer is found +// or when _all_ of the work.nproc gc helpers are in the loop +// looking for work and thus not capable of creating new work. +// This is in fact the termination condition for the STW mark +// phase. static Workbuf* getfull(Workbuf *b) { int32 i; - if(b != nil) + if(b != nil) { + if(b->nobj != 0) + runtime·printf("runtime:getfull: b->nobj=%D not 0.", b->nobj); runtime·lfstackpush(&work.empty, &b->node); + } b = (Workbuf*)runtime·lfstackpop(&work.full); if(b != nil || work.nproc == 1) return b; @@ -674,7 +781,7 @@ scanframe(Stkframe *frame, void *unused) } bv = runtime·stackmapdata(stackmap, pcdata); } - scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata); + scanblock((byte*)frame->argp, bv.n/BitsPerPointer*PtrSize, bv.bytedata); } return true; } @@ -727,12 +834,23 @@ runtime·gcphasework(G *gp) case GCquiesce: case GCstw: case GCsweep: - // No work for now. + // No work. + break; + case GCscan: + // scan the stack, mark the objects, put pointers in work buffers + // hanging off the P where this is being run. + scanstack(gp); break; case GCmark: + case GCmarktermination: + // // Disabled until concurrent GC is implemented // but indicate the scan has been done. - // scanstack(gp); + scanstack(gp); + // scanstack will call shade which will populate + // the Workbuf. + // emptywbuf(gp) will empty it before returning + // break; } gp->gcworkdone = true; @@ -1108,6 +1226,7 @@ runtime·gosweepdone(void) return runtime·mheap.sweepdone; } + void runtime·gchelper(void) { @@ -1118,10 +1237,8 @@ runtime·gchelper(void) // parallel mark for over gc roots runtime·parfordo(work.markfor); - - // help other threads scan secondary blocks - scanblock(nil, 0, nil); - + if(runtime·gcphase != GCscan) + scanblock(nil, 0, nil); // blocks in getfull nproc = work.nproc; // work.nproc can change right after we increment work.ndone if(runtime·xadd(&work.ndone, +1) == nproc-1) runtime·notewakeup(&work.alldone); @@ -1288,6 +1405,7 @@ runtime·gcinit(void) runtime·gcbssmask = unrollglobgcprog(runtime·gcbss, runtime·ebss - runtime·bss); } +// Called from malloc.go using onM, stopping and starting the world handled in caller. void runtime·gc_m(void) { @@ -1311,7 +1429,8 @@ gc(struct gc_args *args) int64 t0, t1, t2, t3, t4; uint64 heap0, heap1, obj; GCStats stats; - + uint32 oldphase; + if(runtime·debug.allocfreetrace) runtime·tracegc(); @@ -1327,7 +1446,7 @@ gc(struct gc_args *args) while(runtime·sweepone() != -1) runtime·sweep.npausesweep++; - // Cache runtime.mheap.allspans in work.spans to avoid conflicts with + // Cache runtime·mheap.allspans in work.spans to avoid conflicts with // resizing/freeing allspans. // New spans can be created while GC progresses, but they are not garbage for // this round: @@ -1344,10 +1463,13 @@ gc(struct gc_args *args) work.spans = runtime·mheap.allspans; work.nspan = runtime·mheap.nspan; runtime·unlock(&runtime·mheap.lock); + oldphase = runtime·gcphase; work.nwait = 0; work.ndone = 0; - work.nproc = runtime·gcprocs(); + work.nproc = runtime·gcprocs(); + runtime·gcphase = GCmark; //^^ vv + runtime·parforsetup(work.markfor, work.nproc, RootCount + runtime·allglen, nil, false, markroot); if(work.nproc > 1) { runtime·noteclear(&work.alldone); @@ -1360,8 +1482,9 @@ gc(struct gc_args *args) gchelperstart(); runtime·parfordo(work.markfor); - scanblock(nil, 0, nil); + scanblock(nil, 0, nil); + runtime·gcphase = oldphase; //^^ vv t3 = 0; if(runtime·debug.gctrace) t3 = runtime·nanotime(); diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 25f916640..1f1044d1d 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -623,9 +623,10 @@ mquiesce(G *gpmaster) uint32 status; uint32 activeglen; - activeglen = runtime·allglen; // enqueue the calling goroutine. runtime·restartg(gpmaster); + + activeglen = runtime·allglen; for(i = 0; i < activeglen; i++) { gp = runtime·allg[i]; if(runtime·readgstatus(gp) == Gdead) diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index adc74cf41..74d7ba4f5 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -93,6 +93,7 @@ typedef struct PollDesc PollDesc; typedef struct DebugVars DebugVars; typedef struct ForceGCState ForceGCState; typedef struct Stack Stack; +typedef struct Workbuf Workbuf; /* * Per-CPU declaration. @@ -303,7 +304,7 @@ struct G bool paniconfault; // panic (instead of crash) on unexpected fault address bool preemptscan; // preempted g does scan for GC bool gcworkdone; // debug: cleared at begining of gc work phase cycle, set by gcphasework, tested at end of cycle - bool throwsplit; // must not split stack + bool throwsplit; // must not split stack int8 raceignore; // ignore race detection events M* m; // for debuggers, but offset not hard-coded M* lockedm; @@ -561,6 +562,16 @@ struct ParFor uint64 nsleep; }; +enum { + WorkbufSize = 4*1024, +}; +struct Workbuf +{ + LFNode node; // must be first + uintptr nobj; + byte* obj[(WorkbufSize-sizeof(LFNode)-sizeof(uintptr))/PtrSize]; +}; + // Track memory allocated by code not written in Go during a cgo call, // so that the garbage collector can see them. struct CgoMal @@ -583,12 +594,14 @@ struct DebugVars // Indicates to write barrier and sychronization task to preform. enum -{ // Synchronization Write barrier - GCoff, // stop and start nop - GCquiesce, // stop and start nop - GCstw, // stop the ps nop - GCmark, // scan the stacks and start no white to black - GCsweep, // stop and start nop +{ // Action WB installation + GCoff = 0, // stop and start no wb + GCquiesce, // stop and start no wb + GCstw, // stop the ps nop + GCscan, // scan the stacks prior to marking + GCmark, // mark use wbufs from GCscan and globals, scan the stacks, then go to GCtermination + GCmarktermination, // mark termination detection. Allocate black, Ps help out GC + GCsweep, // stop and start nop }; struct ForceGCState -- cgit v1.2.1 From af64ab79c0ad72decf083d78cf54257d009741b5 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Tue, 14 Oct 2014 09:51:46 -0400 Subject: [dev.garbage] runtime: Write barrier code. Comments lay out the concurrent GC algorithms. This CL implements parts of the algorithm. The acknowledgement code has been removed from this CL LGTM=rsc, dvyukov R=dvyukov, rsc CC=golang-codereviews https://codereview.appspot.com/151540043 --- src/runtime/mgc0.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 129 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 39fae9bbe..dabd38a60 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -4,22 +4,73 @@ // Garbage collector (GC). // -// GC is: -// - mark&sweep -// - mostly precise (with the exception of some C-allocated objects, assembly frames/arguments, etc) -// - parallel (up to MaxGcproc threads) -// - partially concurrent (mark is stop-the-world, while sweep is concurrent) -// - non-moving/non-compacting -// - full (non-partial) +// The GC runs concurrently with mutator threads, is type accurate (aka precise), allows multiple GC +// thread to run in parallel. It is a concurrent mark and sweep that uses a write barrier. It is +// non-generational and non-compacting. Allocation is done using size segregated per P allocation +// areas to minimize fragmentation while eliminating locks in the common case. // -// GC rate. -// Next GC is after we've allocated an extra amount of memory proportional to -// the amount already in use. The proportion is controlled by GOGC environment variable -// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M -// (this mark is tracked in next_gc variable). This keeps the GC cost in linear -// proportion to the allocation cost. Adjusting GOGC just changes the linear constant -// (and also the amount of extra memory used). +// The algorithm decomposes into several steps. +// This is a high level description of the algorithm being used. For an overview of GC a good +// place to start is Richard Jones' gchandbook.org. +// +// The algorithm's intellectual heritage includes Dijkstra's on-the-fly algorithm, see +// Edsger W. Dijkstra, Leslie Lamport, A. J. Martin, C. S. Scholten, and E. F. M. Steffens. 1978. +// On-the-fly garbage collection: an exercise in cooperation. Commun. ACM 21, 11 (November 1978), 966-975. +// For journal quality proofs that these steps are complete, correct, and terminate see +// Hudson, R., and Moss, J.E.B. Copying Garbage Collection without stopping the world. +// Concurrency and Computation: Practice and Experience 15(3-5), 2003. // +// 0. Set phase = GCscan from GCoff. +// 1. Wait for all P's to acknowledge phase change. +// At this point all goroutines have passed through a GC safepoint and +// know we are in the GCscan phase. +// 2. GC scans all goroutine stacks, mark and enqueues all encountered pointers +// (marking avoids most duplicate enqueuing but races may produce duplication which is benign). +// Preempted goroutines are scanned before P schedules next goroutine. +// 3. Set phase = GCmark. +// 4. Wait for all P's to acknowledge phase change. +// 5. Now write barrier marks and enqueues black or grey to white pointers. If a pointer is +// stored into a white slot, such pointer is not marked. +// Malloc still allocates white (non-marked) objects. +// 6. Meanwhile GC transitively walks the heap marking reachable objects. +// 7. When GC finishes marking heap, it preempts P's one-by-one and +// retakes partial wbufs (filled by write barrier or during a stack scan of the goroutine +// currently scheduled on the P). +// 8. Once the GC has exhausted all available marking work it sets phase = marktermination. +// 9. Wait for all P's to acknowledge phase change. +// 10. Malloc now allocates black objects, so number of unmarked reachable objects +// monotonically decreases. +// 11. GC preempts P's one-by-one taking partial wbufs and marks all unmarked yet reachable objects. +// 12. When GC completes a full cycle over P's and discovers no new grey +// objects, (which means all reachable objects are marked) set phase = GCsweep. +// 13. Wait for all P's to acknowledge phase change. +// 14. Now malloc allocates white (but sweeps spans before use). +// Write barrier becomes nop. +// 15. GC does background sweeping, see description below. +// 16. When sweeping is complete set phase to GCoff. +// 17. When sufficient allocation has taken place replay the sequence starting at 0 above, +// see discussion of GC rate below. + +// Changing phases. +// Phases are changed by setting the gcphase to the next phase and call ackgcphase. +// All phase action must be benign in the presence of a change. +// Starting with GCoff +// GCoff to GCscan +// GSscan scans stacks and globals greying them and never marks an object black. +// Once all the P's are aware of the new phase they will scan gs on preemption. +// This means that the scanning of preempted gs can't start until all the Ps +// have acknowledged. +// GCscan to GCmark +// GCMark turns on the write barrier which also only greys objects. No scanning +// of objects (making them black) can happen until all the Ps have acknowledged +// the phase change. +// GCmark to GCmarktermination +// The only change here is that we start allocating black so the Ps must acknowledge +// the change before we begin the termination algorithm +// GCmarktermination to GSsweep +// Object currently on the freelist must be marked black for this to work. +// Are things on the free lists black or white? How does the sweep phase work? + // Concurrent sweep. // The sweep phase proceeds concurrently with normal program execution. // The heap is swept span-by-span both lazily (when a goroutine needs another span) @@ -50,6 +101,14 @@ // The finalizer goroutine is kicked off only when all spans are swept. // When the next GC starts, it sweeps all not-yet-swept spans (if any). +// GC rate. +// Next GC is after we've allocated an extra amount of memory proportional to +// the amount already in use. The proportion is controlled by GOGC environment variable +// (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M +// (this mark is tracked in next_gc variable). This keeps the GC cost in linear +// proportion to the allocation cost. Adjusting GOGC just changes the linear constant +// (and also the amount of extra memory used). + #include "runtime.h" #include "arch_GOARCH.h" #include "malloc.h" @@ -141,6 +200,8 @@ static void scanblock(byte*, uintptr, byte*); static byte* objectstart(byte*, Markbits*); static Workbuf* greyobject(byte*, Markbits*, Workbuf*); static bool inheap(byte*); +static bool shaded(byte*); +static void shade(byte*); static void slottombits(byte*, Markbits*); void runtime·bgsweep(void); @@ -633,13 +694,12 @@ runtime·gcworkbuffree(Workbuf *b) } } - // Get a full work buffer off the work.full list, or return nil. // getfull acts as a barrier for work.nproc helpers. As long as one // gchelper is actively marking objects it // may create a workbuffer that the other helpers can work on. // The for loop either exits when a work buffer is found -// or when _all_ of the work.nproc gc helpers are in the loop +// or when _all_ of the work.nproc GC helpers are in the loop // looking for work and thus not capable of creating new work. // This is in fact the termination condition for the STW mark // phase. @@ -823,6 +883,59 @@ scanstack(G *gp) runtime·tracebackdefers(gp, &fn, nil); } +// If the slot is grey or black return true, if white return false. +// If the slot is not in the known heap and thus does not have a valid GC bitmap then +// it is considered grey. Globals and stacks can hold such slots. +// The slot is grey if its mark bit is set and it is enqueued to be scanned. +// The slot is black if it has already been scanned. +// It is white if it has a valid mark bit and the bit is not set. +static bool +shaded(byte *slot) +{ + Markbits mbits; + + if(!inheap(slot)) // non-heap slots considered grey + return true; + + objectstart(slot, &mbits); + return (mbits.bits&bitMarked) != 0; +} + +// Shade the object if it isn't already. +// The object is not nil and known to be in the heap. +static void +shade(byte *b) +{ + byte *obj; + Workbuf *wbuf; + Markbits mbits; + + if(!inheap(b)) + runtime·throw("shade: passed an address not in the heap"); + + wbuf = getpartial(); + // Mark the object, return some important bits. + // If we combine the following two rotines we don't have to pass mbits or obj around. + obj = objectstart(b, &mbits); + wbuf = greyobject(obj, &mbits, wbuf); // augments the wbuf + putpartial(wbuf); + return; +} + +// This is the Dijkstra barrier coarsened to shade grey to white whereas +// the original Dijkstra barrier only shaded black to white. +// +// Shade indicates that it has seen a white pointer by adding the referent +// to wbuf. +void +runtime·markwb(void **slot, void *ptr) +{ + // initial nil check avoids some needlesss loads + if(ptr != nil && inheap(ptr) && shaded((void*)slot)) + shade(ptr); + *slot = ptr; +} + // The gp has been moved to a gc safepoint. If there is gcphase specific // work it is done here. void -- cgit v1.2.1 From b8d4cd490ddd8ba298b5347d3e72316df768565c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 22 Oct 2014 14:02:04 -0400 Subject: [dev.power64] runtime: Fix broken merge of noasm.go The earlier dev.power64 merge missed the port of runtime/noasm.goc to runtime/noasm_arm.go. This CL fixes this by moving noasm_arm.go to noasm.go and adding a +build to share the file between arm and power64. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/158350043 --- src/runtime/noasm.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/runtime/noasm_arm.go | 54 ---------------------------------------------- 2 files changed, 56 insertions(+), 54 deletions(-) create mode 100644 src/runtime/noasm.go delete mode 100644 src/runtime/noasm_arm.go (limited to 'src') diff --git a/src/runtime/noasm.go b/src/runtime/noasm.go new file mode 100644 index 000000000..43c16860b --- /dev/null +++ b/src/runtime/noasm.go @@ -0,0 +1,56 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Routines that are implemented in assembly in asm_{amd64,386}.s +// but are implemented in Go for arm. + +// +build arm power64 power64le + +package runtime + +func cmpstring(s1, s2 string) int { + l := len(s1) + if len(s2) < l { + l = len(s2) + } + for i := 0; i < l; i++ { + c1, c2 := s1[i], s2[i] + if c1 < c2 { + return -1 + } + if c1 > c2 { + return +1 + } + } + if len(s1) < len(s2) { + return -1 + } + if len(s1) > len(s2) { + return +1 + } + return 0 +} + +func cmpbytes(s1, s2 []byte) int { + l := len(s1) + if len(s2) < l { + l = len(s2) + } + for i := 0; i < l; i++ { + c1, c2 := s1[i], s2[i] + if c1 < c2 { + return -1 + } + if c1 > c2 { + return +1 + } + } + if len(s1) < len(s2) { + return -1 + } + if len(s1) > len(s2) { + return +1 + } + return 0 +} diff --git a/src/runtime/noasm_arm.go b/src/runtime/noasm_arm.go deleted file mode 100644 index dd3ef8267..000000000 --- a/src/runtime/noasm_arm.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Routines that are implemented in assembly in asm_{amd64,386}.s -// but are implemented in Go for arm. - -package runtime - -func cmpstring(s1, s2 string) int { - l := len(s1) - if len(s2) < l { - l = len(s2) - } - for i := 0; i < l; i++ { - c1, c2 := s1[i], s2[i] - if c1 < c2 { - return -1 - } - if c1 > c2 { - return +1 - } - } - if len(s1) < len(s2) { - return -1 - } - if len(s1) > len(s2) { - return +1 - } - return 0 -} - -func cmpbytes(s1, s2 []byte) int { - l := len(s1) - if len(s2) < l { - l = len(s2) - } - for i := 0; i < l; i++ { - c1, c2 := s1[i], s2[i] - if c1 < c2 { - return -1 - } - if c1 > c2 { - return +1 - } - } - if len(s1) < len(s2) { - return -1 - } - if len(s1) > len(s2) { - return +1 - } - return 0 -} -- cgit v1.2.1 From 097998292f184b893daa9775d4997b0eb3e7f567 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 22 Oct 2014 16:39:31 -0400 Subject: [dev.power64] runtime: fix early GC of Defer objects go_bootstrap was panicking during runtime initialization (under runtime.main) because Defer objects were being prematurely GC'd. This happened because of an incorrect change to runtime?unrollgcprog_m to make it endian-agnostic during the conversion of runtime bitmaps to byte arrays. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/161960044 --- src/runtime/mgc0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index d376c1cf6..02f7eba12 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -1799,7 +1799,7 @@ runtime·unrollgcprog_m(void) } // atomic way to say mask[0] = 1 - x = typ->gc[0]; + x = *(uintptr*)mask; ((byte*)&x)[0] = 1; runtime·atomicstorep((void**)mask, (void*)x); } -- cgit v1.2.1 From cb7d300f93c28798b4a721d92655794d4dd2950e Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Thu, 23 Oct 2014 08:58:10 +1100 Subject: [dev.power64] runtime: fix SigaltstackT definition for power64le Also updated defs3_linux.go but had to manually edit defs_linux_power64le.h. Will regenerate the file when cgo is working natively on ppc64. LGTM=austin R=rsc, austin CC=golang-codereviews https://codereview.appspot.com/158360043 --- src/runtime/defs3_linux.go | 2 +- src/runtime/defs_linux_power64le.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/runtime/defs3_linux.go b/src/runtime/defs3_linux.go index eb65f9d1e..3551a4fa9 100644 --- a/src/runtime/defs3_linux.go +++ b/src/runtime/defs3_linux.go @@ -35,7 +35,7 @@ type Gregset C.elf_gregset_t type FPregset C.elf_fpregset_t type Vreg C.elf_vrreg_t -type Sigaltstack C.struct_sigaltstack +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 diff --git a/src/runtime/defs_linux_power64le.h b/src/runtime/defs_linux_power64le.h index 41db45ca1..64f145672 100644 --- a/src/runtime/defs_linux_power64le.h +++ b/src/runtime/defs_linux_power64le.h @@ -147,7 +147,7 @@ enum { //typedef struct Usigset Usigset; typedef struct Ptregs Ptregs; typedef struct Vreg Vreg; -typedef struct Sigaltstack Sigaltstack; +typedef struct SigaltstackT SigaltstackT; typedef struct Sigcontext Sigcontext; typedef struct Ucontext Ucontext; @@ -179,7 +179,7 @@ struct Vreg { uint32 u[4]; }; -struct Sigaltstack { +struct SigaltstackT { byte *ss_sp; int32 ss_flags; byte Pad_cgo_0[4]; @@ -201,7 +201,7 @@ struct Sigcontext { struct Ucontext { uint64 uc_flags; Ucontext *uc_link; - Sigaltstack uc_stack; + SigaltstackT uc_stack; Usigset uc_sigmask; Usigset __unused[15]; Sigcontext uc_mcontext; -- cgit v1.2.1 From 978c971bacf92ee97b8e24ce45b485afa1c31fad Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Thu, 23 Oct 2014 15:51:17 -0400 Subject: [dev.garbage] runtime: simplifiy lfstack.c due to undiagnosed buffer corruption. The changes got rid of the problems we were seeing. We suspect the pushcnt field has a race. LGTM=rsc R=dvyukov, rsc CC=golang-codereviews https://codereview.appspot.com/159330043 Committer: Russ Cox --- src/runtime/lfstack.c | 14 ++++++-------- src/runtime/runtime.h | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/runtime/lfstack.c b/src/runtime/lfstack.c index 57e0af282..0ced839c2 100644 --- a/src/runtime/lfstack.c +++ b/src/runtime/lfstack.c @@ -46,7 +46,7 @@ runtime·lfstackpush(uint64 *head, LFNode *node) new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<next = (LFNode*)(uintptr)(old&PTR_MASK); + node->next = old; if(runtime·cas64(head, old, new)) break; } @@ -55,19 +55,17 @@ runtime·lfstackpush(uint64 *head, LFNode *node) LFNode* runtime·lfstackpop(uint64 *head) { - LFNode *node, *node2; - uint64 old, new; + LFNode *node; + uint64 old, next; for(;;) { old = runtime·atomicload64(head); if(old == 0) return nil; node = (LFNode*)(uintptr)(old&PTR_MASK); - node2 = runtime·atomicloadp(&node->next); - new = 0; - if(node2 != nil) - new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<next); + + if(runtime·cas64(head, old, next)) return node; } } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index bea773799..37929c59c 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -573,7 +573,7 @@ enum { // Lock-free stack node. struct LFNode { - LFNode *next; + uint64 next; uintptr pushcnt; }; -- cgit v1.2.1 From 2c987a9ddefd9d256bf9e7e21396e2485a7d6514 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Fri, 24 Oct 2014 11:07:16 -0400 Subject: [dev.garbage] runtime: Concurrent scan code Routines and logic to preform a concurrent stack scan of go-routines. This CL excersizes most of the functionality needed. The major exception being that it does not scan running goroutines. After doing the scans it relies on a STW to finish the GC, including rescanning the stacks. It is intended to achieve correctness, performance will follow. LGTM=rsc R=golang-codereviews, rsc CC=dvyukov, golang-codereviews https://codereview.appspot.com/156580043 --- src/runtime/malloc.go | 8 ++ src/runtime/malloc.h | 5 - src/runtime/mcache.c | 2 +- src/runtime/mgc0.c | 308 ++++++++++++++++++++++++++++++++++---------------- src/runtime/proc.c | 19 ++-- src/runtime/runtime.h | 2 + src/runtime/stack.c | 35 +++--- src/runtime/stubs.go | 2 + 8 files changed, 254 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 9b4264f2b..c56e03886 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -438,7 +438,15 @@ func gogc(force int32) { mp = acquirem() mp.gcing = 1 releasem(mp) + onM(stoptheworld) + onM(finishsweep_m) // finish sweep before we start concurrent scan. + onM(starttheworld) + + // Do a concurrent heap scan before we stop the world. + onM(gcscan_m) + onM(stoptheworld) + if mp != acquirem() { gothrow("gogc: rescheduled") } diff --git a/src/runtime/malloc.h b/src/runtime/malloc.h index edcd0be77..e606b0c7a 100644 --- a/src/runtime/malloc.h +++ b/src/runtime/malloc.h @@ -343,11 +343,6 @@ struct MCache StackFreeList stackcache[NumStackOrders]; SudoG* sudogcache; - // Cached P local buffer holding grey objects (marked by not yet scanned) - // Used by mutator for write barrier work. - // GC uses the mcache of the P it is running on for stack and global scanning - // work as well marking. - Workbuf* gcworkbuf; // Local allocator stats, flushed during GC. uintptr local_nlookup; // number of pointer lookups diff --git a/src/runtime/mcache.c b/src/runtime/mcache.c index 5fdbe3266..95ddced3e 100644 --- a/src/runtime/mcache.c +++ b/src/runtime/mcache.c @@ -39,12 +39,12 @@ runtime·allocmcache(void) return c; } +// mheap.lock needs to be held to release the gcworkbuf. static void freemcache(MCache *c) { runtime·MCache_ReleaseAll(c); runtime·stackcache_clear(c); - runtime·gcworkbuffree(c->gcworkbuf); runtime·lock(&runtime·mheap.lock); runtime·purgecachedstats(c); runtime·FixAlloc_Free(&runtime·mheap.cachealloc, c); diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 8620f47af..c385d51cf 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -52,7 +52,7 @@ // see discussion of GC rate below. // Changing phases. -// Phases are changed by setting the gcphase to the next phase and call ackgcphase. +// Phases are changed by setting the gcphase to the next phase and possibly calling ackgcphase. // All phase action must be benign in the presence of a change. // Starting with GCoff // GCoff to GCscan @@ -137,7 +137,7 @@ enum { // ptrmask for an allocation containing a single pointer. static byte oneptr[] = {BitsPointer}; -// Initialized from $GOGC. GOGC=off means no gc. +// Initialized from $GOGC. GOGC=off means no GC. extern int32 runtime·gcpercent; // Holding worldsema grants an M the right to try to stop the world. @@ -185,11 +185,12 @@ BitVector runtime·gcbssmask; Mutex runtime·gclock; -static Workbuf* getpartial(void); +static Workbuf* getpartialorempty(void); static void putpartial(Workbuf*); static Workbuf* getempty(Workbuf*); static Workbuf* getfull(Workbuf*); static void putempty(Workbuf*); +static void putfull(Workbuf*); static Workbuf* handoff(Workbuf*); static void gchelperstart(void); static void flushallmcaches(void); @@ -205,12 +206,14 @@ static void shade(byte*); static void slottombits(byte*, Markbits*); void runtime·bgsweep(void); +void runtime·finishsweep_m(void); static FuncVal bgsweepv = {runtime·bgsweep}; typedef struct WorkData WorkData; struct WorkData { - uint64 full; // lock-free list of full blocks - uint64 empty; // lock-free list of empty blocks + uint64 full; // lock-free list of full blocks + uint64 empty; // lock-free list of empty blocks + uint64 partial; // lock-free list of partially filled blocks byte pad0[CacheLineSize]; // prevents false-sharing between full/empty and nproc/nwait uint32 nproc; int64 tstart; @@ -455,15 +458,22 @@ scanblock(byte *b, uintptr n, byte *ptrmask) Workbuf *wbuf; bool keepworking; - wbuf = getpartial(); + wbuf = getpartialorempty(); if(b != nil) { wbuf = scanobject(b, n, ptrmask, wbuf); if(runtime·gcphase == GCscan) { + if(inheap(b) && !ptrmask) + // b is in heap, we are in GCscan so there should be a ptrmask. + runtime·throw("scanblock: In GCscan phase and inheap is true."); + // GCscan only goes one level deep since mark wb not turned on. putpartial(wbuf); return; } } - + if(runtime·gcphase == GCscan) { + runtime·throw("scanblock: In GCscan phase but no b passed in."); + } + keepworking = b == nil; // ptrmask can have 2 possible values: @@ -479,6 +489,11 @@ scanblock(byte *b, uintptr n, byte *ptrmask) wbuf = getfull(wbuf); if(wbuf == nil) // nil means out of work barrier reached return; + + if(wbuf->nobj<=0) { + runtime·throw("runtime:scanblock getfull returns empty buffer"); + } + } // If another proc wants a pointer, give it some. @@ -506,7 +521,7 @@ markroot(ParFor *desc, uint32 i) void *p; uint32 status; bool restart; - + USED(&desc); // Note: if you add a case here, please also update heapdump.c:dumproots. switch(i) { @@ -553,7 +568,8 @@ markroot(ParFor *desc, uint32 i) break; case RootFlushCaches: - flushallmcaches(); + if (runtime·gcphase != GCscan) // Do not flush mcaches during GCscan phase. + flushallmcaches(); break; default: @@ -566,9 +582,10 @@ markroot(ParFor *desc, uint32 i) status = runtime·readgstatus(gp); // We are not in a scan state if((status == Gwaiting || status == Gsyscall) && gp->waitsince == 0) gp->waitsince = runtime·work.tstart; - // Shrink a stack if not much of it is being used. - runtime·shrinkstack(gp); - if(runtime·readgstatus(gp) == Gdead) + // Shrink a stack if not much of it is being used but not in the scan phase. + if (runtime·gcphase != GCscan) // Do not shrink during GCscan phase. + runtime·shrinkstack(gp); + if(runtime·readgstatus(gp) == Gdead) gp->gcworkdone = true; else gp->gcworkdone = false; @@ -576,121 +593,120 @@ markroot(ParFor *desc, uint32 i) // goroutine will scan its own stack when it stops running. // Wait until it has. - while((status = runtime·readgstatus(gp)) == Grunning && !gp->gcworkdone) { + while(runtime·readgstatus(gp) == Grunning && !gp->gcworkdone) { + } + + // scanstack(gp) is done as part of gcphasework + // But to make sure we finished we need to make sure that + // the stack traps have all responded so drop into + // this while loop until they respond. + while(!gp->gcworkdone){ + status = runtime·readgstatus(gp); if(status == Gdead) { - // TBD you need to explain why Gdead without gp->gcworkdone - // being true. If there is a race then it needs to be - // explained here. gp->gcworkdone = true; // scan is a noop break; //do nothing, scan not needed. } - // try again + if(status == Gwaiting || status == Grunnable) + restart = runtime·stopg(gp); } - - // scanstack(gp); now done as part of gcphasework - // But to make sure we finished we need to make sure that - // the stack traps have all responded so drop into - // this while loop until they respond. - if(!gp->gcworkdone) - // For some reason a G has not completed its work. This is a bug that - // needs to be investigated. For now I'll just print this message in - // case the bug is benign. - runtime·printf("runtime:markroot: post stack scan work not done gp=%p has status %x\n", gp, status); - if(restart) runtime·restartg(gp); break; } } +// wblock is used for creating new empty work buffer blocks. +static Mutex wblock; + // Get an empty work buffer off the work.empty list, // allocating new buffers as needed. static Workbuf* getempty(Workbuf *b) { - MCache *c; - - if(b != nil) - runtime·lfstackpush(&runtime·work.full, &b->node); - b = nil; - c = g->m->mcache; - if(c->gcworkbuf != nil) { - b = c->gcworkbuf; - c->gcworkbuf = nil; + if(b != nil) { + putfull(b); + b = nil; } - if(b == nil) + if(runtime·work.empty) b = (Workbuf*)runtime·lfstackpop(&runtime·work.empty); + + if(b && b->nobj != 0) { + runtime·printf("m%d: getempty: popped b=%p with non-zero b->nobj=%D\n", g->m->id, b, b->nobj); + runtime·throw("getempty: workbuffer not empty, b->nobj not 0"); + } if(b == nil) { + runtime·lock(&wblock); b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys); b->nobj = 0; + runtime·unlock(&wblock); } - if(b->nobj != 0) - runtime·throw("getempty: b->nobj not 0/n"); - b->nobj = 0; return b; } static void putempty(Workbuf *b) { - MCache *c; - - if(b->nobj != 0) - runtime·throw("putempty: b->nobj=%D not 0\n"); - c = g->m->mcache; - if(c->gcworkbuf == nil) { - c->gcworkbuf = b; - return; + if(b->nobj != 0) { + runtime·throw("putempty: b->nobj not 0\n"); } runtime·lfstackpush(&runtime·work.empty, &b->node); } -// Get an partially empty work buffer from the mcache structure -// and if non is available get an empty one. +// Put a full or partially full workbuf on the full list. +static void +putfull(Workbuf *b) +{ + if(b->nobj <= 0) { + runtime·throw("putfull: b->nobj <= 0\n"); + } + runtime·lfstackpush(&runtime·work.full, &b->node); +} + +// Get an partially empty work buffer +// if none are available get an empty one. static Workbuf* -getpartial(void) +getpartialorempty(void) { - MCache *c; Workbuf *b; - c = g->m->mcache; - if(c->gcworkbuf != nil) { - b = c->gcworkbuf; - c->gcworkbuf = nil; - } else { + b = (Workbuf*)runtime·lfstackpop(&runtime·work.partial); + if(b == nil) b = getempty(nil); - } return b; } static void putpartial(Workbuf *b) { - MCache *c; - c = g->m->mcache; - if(c->gcworkbuf == nil) { - c->gcworkbuf = b; - return; + if(b->nobj == 0) + runtime·lfstackpush(&runtime·work.empty, &b->node); + else if (b->nobj < nelem(b->obj)) + runtime·lfstackpush(&runtime·work.partial, &b->node); + else if (b->nobj == nelem(b->obj)) + runtime·lfstackpush(&runtime·work.full, &b->node); + else { + runtime·printf("b=%p, b->nobj=%D, nelem(b->obj)=%d\n", b, b->nobj, nelem(b->obj)); + runtime·throw("putpartial: bad Workbuf b->nobj"); } - - runtime·throw("putpartial: c->gcworkbuf is not nil\n"); - - runtime·lfstackpush(&runtime·work.full, &b->node); } void runtime·gcworkbuffree(Workbuf *b) { - if(b != nil) { - if(b->nobj != 0) - runtime·throw("gcworkbufferfree: b->nobj not 0\n"); + if(b == nil) + return; + if(b->nobj == 0) putempty(b); - } + else + putfull(b); } -// Get a full work buffer off the work.full list, or return nil. +// Get a full work buffer off the work.full or a partially +// filled one off the work.partial list. If nothing is available +// wait until all the other gc helpers have finished and then +// return nil. // getfull acts as a barrier for work.nproc helpers. As long as one // gchelper is actively marking objects it // may create a workbuffer that the other helpers can work on. @@ -704,12 +720,12 @@ getfull(Workbuf *b) { int32 i; - if(b != nil) { - if(b->nobj != 0) - runtime·printf("runtime:getfull: b->nobj=%D not 0.", b->nobj); - runtime·lfstackpush(&runtime·work.empty, &b->node); - } + if(b != nil) + putempty(b); + b = (Workbuf*)runtime·lfstackpop(&runtime·work.full); + if(b==nil) + b = (Workbuf*)runtime·lfstackpop(&runtime·work.partial); if(b != nil || runtime·work.nproc == 1) return b; @@ -718,7 +734,9 @@ getfull(Workbuf *b) if(runtime·work.full != 0) { runtime·xadd(&runtime·work.nwait, -1); b = (Workbuf*)runtime·lfstackpop(&runtime·work.full); - if(b != nil) + if(b==nil) + b = (Workbuf*)runtime·lfstackpop(&runtime·work.partial); + if(b != nil) return b; runtime·xadd(&runtime·work.nwait, +1); } @@ -861,8 +879,7 @@ scanstack(G *gp) case Gdead: return; case Grunning: - runtime·printf("runtime: gp=%p, goid=%D, gp->atomicstatus=%d\n", gp, gp->goid, runtime·readgstatus(gp)); - runtime·throw("mark - world not stopped"); + runtime·throw("scanstack: - goroutine not stopped"); case Grunnable: case Gsyscall: case Gwaiting: @@ -909,7 +926,7 @@ shade(byte *b) if(!inheap(b)) runtime·throw("shade: passed an address not in the heap"); - wbuf = getpartial(); + wbuf = getpartialorempty(); // Mark the object, return some important bits. // If we combine the following two rotines we don't have to pass mbits or obj around. obj = objectstart(b, &mbits); @@ -932,8 +949,8 @@ runtime·markwb(void **slot, void *ptr) *slot = ptr; } -// The gp has been moved to a gc safepoint. If there is gcphase specific -// work it is done here. +// The gp has been moved to a GC safepoint. GC phase specific +// work is done here. void runtime·gcphasework(G *gp) { @@ -953,14 +970,8 @@ runtime·gcphasework(G *gp) break; case GCmark: case GCmarktermination: - // - // Disabled until concurrent GC is implemented - // but indicate the scan has been done. scanstack(gp); - // scanstack will call shade which will populate - // the Workbuf. - // emptywbuf(gp) will empty it before returning - // + // All available mark work will be emptied before returning. break; } gp->gcworkdone = true; @@ -1050,6 +1061,7 @@ runtime·iterate_finq(void (*callback)(FuncVal*, byte*, uintptr, Type*, PtrType* } } +// Returns only when span s has been swept. void runtime·MSpan_EnsureSwept(MSpan *s) { @@ -1064,6 +1076,7 @@ runtime·MSpan_EnsureSwept(MSpan *s) sg = runtime·mheap.sweepgen; if(runtime·atomicload(&s->sweepgen) == sg) return; + // The caller must be sure that the span is a MSpanInUse span. if(runtime·cas(&s->sweepgen, sg-2, sg-1)) { runtime·MSpan_Sweep(s, false); return; @@ -1347,7 +1360,7 @@ runtime·gchelper(void) g->m->traceback = 2; gchelperstart(); - // parallel mark for over gc roots + // parallel mark for over GC roots runtime·parfordo(runtime·work.markfor); if(runtime·gcphase != GCscan) scanblock(nil, 0, nil); // blocks in getfull @@ -1531,10 +1544,93 @@ runtime·gc_m(void) a.start_time = (uint64)(g->m->scalararg[0]) | ((uint64)(g->m->scalararg[1]) << 32); a.eagersweep = g->m->scalararg[2]; gc(&a); - runtime·casgstatus(gp, Gwaiting, Grunning); } +void +runtime·finishsweep_m(void) +{ + uint32 i, sg; + MSpan *s; + + // The world is stopped so we should be able to complete the sweeps + // quickly. + while(runtime·sweepone() != -1) + runtime·sweep.npausesweep++; + + // There may be some other spans being swept concurrently that + // we need to wait for. If finishsweep_m is done with the world stopped + // this code is not required. + sg = runtime·mheap.sweepgen; + for(i=0; isweepgen == sg) { + continue; + } + if(s->state != MSpanInUse) // Span is not part of the GCed heap so no need to ensure it is swept. + continue; + runtime·MSpan_EnsureSwept(s); + } +} + +// Scan all of the stacks, greying (or graying if in America) the referents +// but not blackening them since the mark write barrier isn't installed. +void +runtime·gcscan_m(void) +{ + uint32 i, allglen, oldphase; + G *gp, *mastergp, **allg; + + // Grab the g that called us and potentially allow rescheduling. + // This allows it to be scanned like other goroutines. + mastergp = g->m->curg; + + runtime·casgstatus(mastergp, Grunning, Gwaiting); + mastergp->waitreason = runtime·gostringnocopy((byte*)"garbage collection scan"); + + // Span sweeping has been done by finishsweep_m. + // Long term we will want to make this goroutine runnable + // by placing it onto a scanenqueue state and then calling + // runtime·restartg(mastergp) to make it Grunnable. + // At the bottom we will want to return this p back to the scheduler. + + oldphase = runtime·gcphase; + + runtime·lock(&runtime·allglock); + allglen = runtime·allglen; + allg = runtime·allg; + // Prepare flag indicating that the scan has not been completed. + for(i = 0; i < allglen; i++) { + gp = allg[i]; + gp->gcworkdone = false; // set to true in gcphasework + } + runtime·unlock(&runtime·allglock); + + runtime·work.nwait = 0; + runtime·work.ndone = 0; + runtime·work.nproc = 1; // For now do not do this in parallel. + runtime·gcphase = GCscan; + // ackgcphase is not needed since we are not scanning running goroutines. + runtime·parforsetup(runtime·work.markfor, runtime·work.nproc, RootCount + allglen, nil, false, markroot); + runtime·parfordo(runtime·work.markfor); + + runtime·lock(&runtime·allglock); + + allg = runtime·allg; + // Check that gc work is done. + for(i = 0; i < allglen; i++) { + gp = allg[i]; + if(!gp->gcworkdone) { + runtime·throw("scan missed a g"); + } + } + runtime·unlock(&runtime·allglock); + + runtime·gcphase = oldphase; + runtime·casgstatus(mastergp, Gwaiting, Grunning); + // Let the g that called us continue to run. +} + static void gc(struct gc_args *args) { @@ -1542,7 +1638,9 @@ gc(struct gc_args *args) uint64 heap0, heap1, obj; GCStats stats; uint32 oldphase; - + uint32 i; + G *gp; + if(runtime·debug.allocfreetrace) runtime·tracegc(); @@ -1554,9 +1652,7 @@ gc(struct gc_args *args) if(runtime·debug.gctrace) t1 = runtime·nanotime(); - // Sweep what is not sweeped by bgsweep. - while(runtime·sweepone() != -1) - runtime·sweep.npausesweep++; + runtime·finishsweep_m(); // Cache runtime·mheap.allspans in work.spans to avoid conflicts with // resizing/freeing allspans. @@ -1580,7 +1676,13 @@ gc(struct gc_args *args) runtime·work.nwait = 0; runtime·work.ndone = 0; runtime·work.nproc = runtime·gcprocs(); - runtime·gcphase = GCmark; //^^ vv + runtime·gcphase = GCmark; + + // World is stopped so allglen will not change. + for(i = 0; i < runtime·allglen; i++) { + gp = runtime·allg[i]; + gp->gcworkdone = false; // set to true in gcphasework + } runtime·parforsetup(runtime·work.markfor, runtime·work.nproc, RootCount + runtime·allglen, nil, false, markroot); if(runtime·work.nproc > 1) { @@ -1596,7 +1698,13 @@ gc(struct gc_args *args) runtime·parfordo(runtime·work.markfor); scanblock(nil, 0, nil); - runtime·gcphase = oldphase; //^^ vv + + if(runtime·work.full) + runtime·throw("runtime·work.full != nil"); + if(runtime·work.partial) + runtime·throw("runtime·work.partial != nil"); + + runtime·gcphase = oldphase; t3 = 0; if(runtime·debug.gctrace) t3 = runtime·nanotime(); @@ -1735,7 +1843,7 @@ readgcstats_m(void) if(pauses->cap < nelem(mstats.pause_ns)+3) runtime·throw("runtime: short slice passed to readGCStats"); - // Pass back: pauses, last gc (absolute time), number of gc, total pause ns. + // Pass back: pauses, last GC (absolute time), number of GC, total pause ns. p = (uint64*)pauses->array; runtime·lock(&runtime·mheap.lock); n = mstats.numgc; diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 9643abcc6..b824f574d 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -423,13 +423,7 @@ runtime·casgstatus(G *gp, uint32 oldval, uint32 newval) // loop if gp->atomicstatus is in a scan state giving // GC time to finish and change the state to oldval. while(!runtime·cas(&gp->atomicstatus, oldval, newval)) { - // Help GC if needed. - if(gp->preemptscan && !gp->gcworkdone && (oldval == Grunning || oldval == Gsyscall)) { - gp->preemptscan = false; - g->m->ptrarg[0] = gp; - fn = helpcasgstatus; - runtime·onM(&fn); - } + } } @@ -504,6 +498,13 @@ runtime·stopg(G *gp) return false; case Grunning: + if(runtime·gcphase == GCscan) { + gp->gcworkdone = true; + return false; + // Running routines not scanned during + // GCscan phase, we only scan non-running routines. + } + // Claim goroutine, so we aren't racing with a status // transition away from Grunning. if(!runtime·castogscanstatus(gp, Grunning, Gscanrunning)) @@ -1918,6 +1919,7 @@ exitsyscallfast(void) // Freezetheworld sets stopwait but does not retake P's. if(runtime·sched.stopwait) { + g->m->mcache = nil; g->m->p = nil; return false; } @@ -1930,6 +1932,7 @@ exitsyscallfast(void) return true; } // Try to get any other idle P. + g->m->mcache = nil; g->m->p = nil; if(runtime·sched.pidle) { fn = exitsyscallfast_pidle; @@ -2617,6 +2620,8 @@ runtime·setcpuprofilerate_m(void) P *runtime·newP(void); // Change number of processors. The world is stopped, sched is locked. +// gcworkbufs are not being modified by either the GC or +// the write barrier code. static void procresize(int32 new) { diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 37929c59c..cbbf6b3fc 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -649,6 +649,7 @@ struct ForceGCState }; extern uint32 runtime·gcphase; +extern Mutex runtime·allglock; /* * defined macros @@ -677,6 +678,7 @@ enum { uint32 runtime·readgstatus(G*); void runtime·casgstatus(G*, uint32, uint32); +bool runtime·castogscanstatus(G*, uint32, uint32); void runtime·quiesce(G*); bool runtime·stopg(G*); void runtime·restartg(G*); diff --git a/src/runtime/stack.c b/src/runtime/stack.c index e402691f4..e06e48a93 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -587,13 +587,13 @@ adjustsudogs(G *gp, AdjustInfo *adjinfo) } // Copies gp's stack to a new stack of a different size. +// Caller must have changed gp status to Gcopystack. static void copystack(G *gp, uintptr newsize) { Stack old, new; uintptr used; AdjustInfo adjinfo; - uint32 oldstatus; bool (*cb)(Stkframe*, void*); byte *p, *ep; @@ -637,20 +637,11 @@ copystack(G *gp, uintptr newsize) } runtime·memmove((byte*)new.hi - used, (byte*)old.hi - used, used); - oldstatus = runtime·readgstatus(gp); - oldstatus &= ~Gscan; - if(oldstatus == Gwaiting || oldstatus == Grunnable) - runtime·casgstatus(gp, oldstatus, Gcopystack); // oldstatus is Gwaiting or Grunnable - else - runtime·throw("copystack: bad status, not Gwaiting or Grunnable"); - // Swap out old stack for new one gp->stack = new; gp->stackguard0 = new.lo + StackGuard; // NOTE: might clobber a preempt request gp->sched.sp = new.hi - used; - runtime·casgstatus(gp, Gcopystack, oldstatus); // oldstatus is Gwaiting or Grunnable - // free old stack if(StackPoisonCopy) { p = (byte*)old.lo; @@ -700,6 +691,7 @@ void runtime·newstack(void) { int32 oldsize, newsize; + uint32 oldstatus; uintptr sp; G *gp; Gobuf morebuf; @@ -789,12 +781,15 @@ runtime·newstack(void) runtime·throw("stack overflow"); } - // Note that the concurrent GC might be scanning the stack as we try to replace it. - // copystack takes care of the appropriate coordination with the stack scanner. + oldstatus = runtime·readgstatus(gp); + oldstatus &= ~Gscan; + runtime·casgstatus(gp, oldstatus, Gcopystack); // oldstatus is Gwaiting or Grunnable + // The concurrent GC will not scan the stack while we are doing the copy since + // the gp is in a Gcopystack status. copystack(gp, newsize); if(StackDebug >= 1) runtime·printf("stack grow done\n"); - runtime·casgstatus(gp, Gwaiting, Grunning); + runtime·casgstatus(gp, Gcopystack, Grunning); runtime·gogo(&gp->sched); } @@ -825,6 +820,7 @@ void runtime·shrinkstack(G *gp) { uintptr used, oldsize, newsize; + uint32 oldstatus; if(runtime·readgstatus(gp) == Gdead) { if(gp->stack.lo != 0) { @@ -858,8 +854,19 @@ runtime·shrinkstack(G *gp) #endif if(StackDebug > 0) runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uint64)newsize); + // This is being done in a Gscan state and was initiated by the GC so no need to move to + // the Gcopystate. + // The world is stopped, so the goroutine must be Gwaiting or Grunnable, + // and what it is is not changing underfoot. + + oldstatus = runtime·readgstatus(gp); + oldstatus &= ~Gscan; + if(oldstatus != Gwaiting && oldstatus != Grunnable) + runtime·throw("status is not Gwaiting or Grunnable"); + runtime·casgstatus(gp, oldstatus, Gcopystack); copystack(gp, newsize); -} + runtime·casgstatus(gp, Gcopystack, oldstatus); + } // Do any delayed stack freeing that was queued up during GC. void diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 6561094ff..32dfed7d3 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -106,6 +106,8 @@ func recovery_m(*g) func mcacheRefill_m() func largeAlloc_m() func gc_m() +func gcscan_m() +func finishsweep_m() func scavenge_m() func setFinalizer_m() func removeFinalizer_m() -- cgit v1.2.1 From 4045a260d6969f3715a117d905de6a1a50a183e0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 24 Oct 2014 11:39:01 -0400 Subject: [dev.power64] liblink: print line numbers in disassembly on power64 Matching other platforms. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/161320043 --- src/liblink/list9.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/liblink/list9.c b/src/liblink/list9.c index 9e205b7a9..041c6884f 100644 --- a/src/liblink/list9.c +++ b/src/liblink/list9.c @@ -108,14 +108,14 @@ Pconv(Fmt *fp) if(p->mark & NOSCHED) s += sprint(s, "*"); if(p->reg == NREG && p->from3.type == D_NONE) - sprint(s, "%.5lld (%d) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to); + 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 (%d) %A %lld(R%d+R%d),%D", p->pc, p->lineno, a, + 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 (%d) %A %D,%lld(R%d+R%d)", p->pc, p->lineno, a, + 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); -- cgit v1.2.1 From 93135bf586c4803e45f2fd709e895e249c250025 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 15:10:54 -0400 Subject: [dev.power64] cc: 8-byte align argument size on power64 LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/163370043 --- src/cmd/cc/pgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c index 2687e05a9..54cf0c5e1 100644 --- a/src/cmd/cc/pgen.c +++ b/src/cmd/cc/pgen.c @@ -72,7 +72,7 @@ argsize(int doret) 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; -- cgit v1.2.1 From fcceea1097e0f86dac0d71bd2fa0b37ab66d8143 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 15:25:40 -0400 Subject: [dev.power64] liblink: power64 fixes and ports of changes Ports of platform-specific changes that happened on default after dev.power64 forked (fixes for c2go, wrapper math fixes, moved stackguard field, stackguard1 support, precise stacks). Bug fixes (missing AMOVW in instruction table, correct unsigned 32-bit remainder). LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/164920044 --- src/liblink/asm9.c | 69 ++++++----------------- src/liblink/obj9.c | 159 ++++++++++++++++++++++++++++------------------------- 2 files changed, 102 insertions(+), 126 deletions(-) (limited to 'src') diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 47d515e05..c5a78e53c 100644 --- a/src/liblink/asm9.c +++ b/src/liblink/asm9.c @@ -232,6 +232,7 @@ static Optab optab[] = { { 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 }, @@ -349,8 +350,12 @@ static Optab optab[] = { { 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 }, @@ -433,12 +438,11 @@ static Optab optab[] = { { 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 - { ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 }, - { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, }; @@ -472,7 +476,7 @@ static struct Optab* stop; } oprange[ALAST]; -static char xcmp[C_NCLASS][C_NCLASS]; +static uchar xcmp[C_NCLASS][C_NCLASS]; void @@ -747,7 +751,7 @@ static Optab* oplook(Link *ctxt, Prog *p) { int a1, a2, a3, a4, r; - char *c1, *c3, *c4; + uchar *c1, *c3, *c4; Optab *o, *e; a1 = p->optab; @@ -931,6 +935,8 @@ buildop(Link *ctxt) 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]; @@ -940,6 +946,8 @@ buildop(Link *ctxt) 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]; @@ -2005,6 +2013,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) 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 */ @@ -2264,54 +2277,6 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) out[3] = o4; out[4] = o5; return; - -#if NOTDEF - v = p->pc; - switch(o->size) { - default: - if(debug['a']) - Bprint(&bso, " %.8lux:\t\t%P\n", v, p); - break; - case 4: - if(debug['a']) - Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); - lput(o1); - break; - case 8: - if(debug['a']) - Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); - lput(o1); - lput(o2); - break; - case 12: - if(debug['a']) - Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); - lput(o1); - lput(o2); - lput(o3); - break; - case 16: - if(debug['a']) - Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", - v, o1, o2, o3, o4, p); - lput(o1); - lput(o2); - lput(o3); - lput(o4); - break; - case 20: - if(debug['a']) - Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", - v, o1, o2, o3, o4, o5, p); - lput(o1); - lput(o2); - lput(o3); - lput(o4); - lput(o5); - break; - } - return 0; -#endif } static vlong diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 3906181a3..fa8af5f83 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -199,7 +199,7 @@ parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg) static void addstacksplit(Link *ctxt, LSym *cursym) { - Prog *p, *q, *q1; + Prog *p, *q, *p1, *p2, *q1; int o, mov, aoffset; vlong textstksiz, textarg; int32 autoffset, autosize; @@ -472,32 +472,92 @@ addstacksplit(Link *ctxt, LSym *cursym) q->spadj = -aoffset; if(cursym->text->reg & WRAPPER) { - // g->panicwrap += autosize; - // MOVWZ panicwrap_offset(g), R3 - // ADD $autosize, R3 - // MOVWZ R3, panicwrap_offset(g) - p = appendp(ctxt, q); - p->as = AMOVWZ; + // 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 = 2*ctxt->arch->ptrsize; + 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; + p->from.offset = autosize+8; + p->reg = REGSP; p->to.type = D_REG; - p->to.reg = 3; + p->to.reg = 5; p = appendp(ctxt, p); - p->as = AMOVWZ; + p->as = ACMP; p->from.type = D_REG; - p->from.reg = 3; + 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 = REGG; - p->to.offset = 2*ctxt->arch->ptrsize; + p->to.reg = 3; + p->to.offset = 0; // Panic.argp + + p = appendp(ctxt, p); + p->as = ANOP; + p1->pcond = p; + p2->pcond = p; } break; @@ -512,36 +572,6 @@ addstacksplit(Link *ctxt, LSym *cursym) p->to.type = D_BRANCH; break; } - if(cursym->text->reg & WRAPPER) { - // g->panicwrap -= autosize; - // MOVWZ panicwrap_offset(g), R3 - // ADD $-autosize, R3 - // MOVWZ R3, panicwrap_offset(g) - p->as = AMOVWZ; - p->from.type = D_OREG; - p->from.reg = REGG; - p->from.offset = 2*ctxt->arch->ptrsize; - p->to.type = D_REG; - p->to.reg = 3; - p = appendp(ctxt, p); - - p->as = AADD; - p->from.type = D_CONST; - p->from.offset = -autosize; - p->to.type = D_REG; - p->to.reg = 3; - p = appendp(ctxt, p); - - p->as = AMOVWZ; - p->from.type = D_REG; - p->from.reg = 3; - p->to.type = D_OREG; - p->to.reg = REGG; - p->to.offset = 2*ctxt->arch->ptrsize; - p = appendp(ctxt, p); - - p->as = ARETURN; - } if(cursym->text->mark & LEAF) { if(!autosize) { p->as = ABR; @@ -673,18 +703,19 @@ addstacksplit(Link *ctxt, LSym *cursym) static Prog* stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) { - int32 arg; - Prog *q, *q1; + 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; - q = nil; if(framesize <= StackSmall) { // small stack: SP < stackguard // CMP stackguard, SP @@ -735,7 +766,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p->to.type = D_CONST; p->to.offset = StackPreempt; - q = p = appendp(ctxt, p); + p = appendp(ctxt, p); p->as = ABEQ; p->to.type = D_BRANCH; @@ -774,31 +805,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p->as = ABLT; p->to.type = D_BRANCH; - // MOVD $framesize, R3 - p = appendp(ctxt, p); - p->as = AMOVD; - p->from.type = D_CONST; - p->from.offset = framesize; - p->to.type = D_REG; - p->to.reg = 3; - if(q) - q->pcond = p; - - // MOVD $args, R4 - p = appendp(ctxt, p); - p->as = AMOVD; - p->from.type = D_CONST; - arg = (ctxt->cursym->text->to.offset >> 32) & 0xffffffffull; - if(arg == 1) // special marker for known 0 - arg = 0; - else if(arg == ArgsSizeUnknown) - ctxt->diag("%s: arg size unknown, but split stack", ctxt->cursym->name); - if(arg&7) - ctxt->diag("misaligned argument size in stack split: %d", arg); - p->from.offset = arg; - p->to.type = D_REG; - p->to.reg = 4; - // MOVD LR, R5 p = appendp(ctxt, p); p->as = AMOVD; @@ -811,7 +817,10 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p = appendp(ctxt, p); p->as = ABL; p->to.type = D_BRANCH; - p->to.sym = ctxt->symmorestack[noctxt]; + if(ctxt->cursym->cfunc) + p->to.sym = linklookup(ctxt, "runtime.morestackc", 0); + else + p->to.sym = ctxt->symmorestack[noctxt]; // BR start p = appendp(ctxt, p); @@ -1010,6 +1019,7 @@ LinkArch linkpower64 = { .D_PARAM = D_PARAM, .D_SCONST = D_SCONST, .D_STATIC = D_STATIC, + .D_OREG = D_OREG, .ACALL = ABL, .ADATA = ADATA, @@ -1056,6 +1066,7 @@ LinkArch linkpower64le = { .D_PARAM = D_PARAM, .D_SCONST = D_SCONST, .D_STATIC = D_STATIC, + .D_OREG = D_OREG, .ACALL = ABL, .ADATA = ADATA, -- cgit v1.2.1 From 297ae6e1545a6982878a82114d5d2d40da373ca6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 27 Oct 2014 15:57:07 -0400 Subject: [dev.garbage] runtime: fix TestLFStack on 386 LGTM=rlh R=rlh, dvyukov CC=golang-codereviews https://codereview.appspot.com/157430044 --- src/runtime/export_test.go | 2 +- src/runtime/lfstack_test.go | 2 +- src/runtime/runtime.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index be352557f..65e918e84 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -26,7 +26,7 @@ var Exitsyscall = exitsyscall var LockedOSThread = lockedOSThread type LFNode struct { - Next *LFNode + Next uint64 Pushcnt uintptr } diff --git a/src/runtime/lfstack_test.go b/src/runtime/lfstack_test.go index e51877704..68f221d6e 100644 --- a/src/runtime/lfstack_test.go +++ b/src/runtime/lfstack_test.go @@ -121,7 +121,7 @@ func TestLFStackStress(t *testing.T) { } cnt++ sum2 += node.data - node.Next = nil + node.Next = 0 } } if cnt != K { diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index cbbf6b3fc..c1bba423a 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -571,6 +571,7 @@ enum { #endif // Lock-free stack node. +// Also known to export_test.go. struct LFNode { uint64 next; -- cgit v1.2.1 From 9232cbb6a6aaa8a4197b22819406128ff0f99265 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Mon, 27 Oct 2014 17:07:53 -0400 Subject: [dev.garbage] runtime: Fix 386 compiler warnings. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/163390043 --- src/runtime/mgc0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index c385d51cf..cc1f81123 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -632,7 +632,7 @@ getempty(Workbuf *b) b = (Workbuf*)runtime·lfstackpop(&runtime·work.empty); if(b && b->nobj != 0) { - runtime·printf("m%d: getempty: popped b=%p with non-zero b->nobj=%D\n", g->m->id, b, b->nobj); + runtime·printf("m%d: getempty: popped b=%p with non-zero b->nobj=%d\n", g->m->id, b, (uint32)b->nobj); runtime·throw("getempty: workbuffer not empty, b->nobj not 0"); } if(b == nil) { @@ -687,7 +687,7 @@ putpartial(Workbuf *b) else if (b->nobj == nelem(b->obj)) runtime·lfstackpush(&runtime·work.full, &b->node); else { - runtime·printf("b=%p, b->nobj=%D, nelem(b->obj)=%d\n", b, b->nobj, nelem(b->obj)); + runtime·printf("b=%p, b->nobj=%d, nelem(b->obj)=%d\n", b, b->nobj, (uint32)nelem(b->obj)); runtime·throw("putpartial: bad Workbuf b->nobj"); } } -- cgit v1.2.1 From 76b6806e2f08df32f2caa859d39cfc9ad812e22c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 17:19:41 -0400 Subject: [dev.power64] liblink: fix lost branch target A recent commit lost the branch target in the really-big-stack case of splitstack, causing an infinite loop stack preempt case. Revive the branch target. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/157790044 --- src/liblink/obj9.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index fa8af5f83..3db08c545 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -703,7 +703,7 @@ addstacksplit(Link *ctxt, LSym *cursym) static Prog* stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) { - Prog *q1; + Prog *q, *q1; // MOVD g_stackguard(g), R3 p = appendp(ctxt, p); @@ -716,6 +716,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p->to.type = D_REG; p->to.reg = 3; + q = nil; if(framesize <= StackSmall) { // small stack: SP < stackguard // CMP stackguard, SP @@ -766,7 +767,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p->to.type = D_CONST; p->to.offset = StackPreempt; - p = appendp(ctxt, p); + q = p = appendp(ctxt, p); p->as = ABEQ; p->to.type = D_BRANCH; @@ -812,6 +813,8 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) p->from.offset = D_LR; p->to.type = D_REG; p->to.reg = 5; + if(q) + q->pcond = p; // BL runtime.morestack(SB) p = appendp(ctxt, p); -- cgit v1.2.1 From d794c3a12eb8d762b119cf244bbbac8ee66b5a54 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 17:27:03 -0400 Subject: [dev.power64] runtime: power64 fixes and ports of changes Fix include paths that got moved in the great pkg/ rename. Add missing runtime/arch_* files for power64. Port changes that happened on default since branching to runtime/{asm,atomic,sys_linux}_power64x.s (precise stacks, calling convention change, various new and deleted functions. Port struct renaming and fix some bugs in runtime/defs_linux_power64.h. LGTM=rsc R=rsc, dave CC=golang-codereviews https://codereview.appspot.com/161450043 --- src/math/stubs_power64x.s | 2 +- src/runtime/arch_power64.go | 8 + src/runtime/arch_power64le.go | 8 + src/runtime/asm_power64x.s | 478 ++++++++++++++++---------------------- src/runtime/atomic_power64x.s | 11 +- src/runtime/debug/stubs.s | 6 + src/runtime/defs_linux_power64.h | 19 +- src/runtime/memclr_power64x.s | 2 +- src/runtime/memmove_power64x.s | 2 +- src/runtime/rt0_linux_power64.s | 6 +- src/runtime/rt0_linux_power64le.s | 6 +- src/runtime/sys_linux_power64x.s | 166 +++++++------ src/sync/atomic/asm_power64x.s | 2 +- src/syscall/asm.s | 7 + src/syscall/asm_linux_power64x.s | 2 +- 15 files changed, 342 insertions(+), 383 deletions(-) create mode 100644 src/runtime/arch_power64.go create mode 100644 src/runtime/arch_power64le.go (limited to 'src') diff --git a/src/math/stubs_power64x.s b/src/math/stubs_power64x.s index 0cb86144a..36b762554 100644 --- a/src/math/stubs_power64x.s +++ b/src/math/stubs_power64x.s @@ -4,7 +4,7 @@ // +build power64 power64le -#include "../../cmd/ld/textflag.h" +#include "textflag.h" TEXT ·Asin(SB),NOSPLIT,$0 BR ·asin(SB) diff --git a/src/runtime/arch_power64.go b/src/runtime/arch_power64.go new file mode 100644 index 000000000..270cd7b95 --- /dev/null +++ b/src/runtime/arch_power64.go @@ -0,0 +1,8 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +type uintreg uint64 +type intptr int64 // TODO(rsc): remove diff --git a/src/runtime/arch_power64le.go b/src/runtime/arch_power64le.go new file mode 100644 index 000000000..270cd7b95 --- /dev/null +++ b/src/runtime/arch_power64le.go @@ -0,0 +1,8 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +type uintreg uint64 +type intptr int64 // TODO(rsc): remove diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index a0511de8e..76bf42094 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -6,9 +6,9 @@ #include "zasm_GOOS_GOARCH.h" #include "funcdata.h" -#include "../../cmd/ld/textflag.h" +#include "textflag.h" -TEXT _rt0_go(SB),NOSPLIT,$0 +TEXT runtime·rt0_go(SB),NOSPLIT,$0 // initialize essential registers BL runtime·reginit(SB) @@ -21,9 +21,10 @@ TEXT _rt0_go(SB),NOSPLIT,$0 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) + MOVD R3, g_stackguard1(g) + MOVD R3, (g_stack+stack_lo)(g) + MOVD R1, (g_stack+stack_hi)(g) // TODO: if there is a _cgo_init, call it. // TODO: add TLS @@ -41,7 +42,6 @@ TEXT _rt0_go(SB),NOSPLIT,$0 // 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 @@ -49,9 +49,7 @@ TEXT _rt0_go(SB),NOSPLIT,$0 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 @@ -118,7 +116,7 @@ TEXT runtime·gogo(SB), NOSPLIT, $-8-8 MOVD R31, CTR BR (CTR) -// void mcall(void (*fn)(G*)) +// void mcall(fn func(*g)) // Switch to m->g0's stack, call fn(g). // Fn must never return. It should gogo(&g->sched) // to keep running g. @@ -137,9 +135,10 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8 CMP g, R3 BNE 2(PC) BR runtime·badmcall(SB) - MOVD fn+0(FP), R4 + MOVD fn+0(FP), R11 // context + MOVD 0(R11), R4 // code pointer MOVD R4, CTR - MOVD (g_sched+gobuf_sp)(g), R1 + MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp MOVDU R3, -8(R1) MOVDU R0, -8(R1) BL (CTR) @@ -150,23 +149,50 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8 // 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 +TEXT runtime·switchtoM(SB), NOSPLIT, $0-0 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. +// func onM_signalok(fn func()) +TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8 + MOVD g, R3 // R3 = g + MOVD g_m(R3), R4 // R4 = g->m + MOVD m_gsignal(R4), R4 // R4 = g->m->gsignal + MOVD fn+0(FP), R11 // context for call below + CMP R3, R4 + BEQ onsignal + MOVD R11, 8(R1) + BL runtime·onM(SB) + RETURN + +onsignal: + MOVD 0(R11), R3 // code pointer + MOVD R3, CTR + BL (CTR) + RETURN + +// void onM(fn func()) TEXT runtime·onM(SB), NOSPLIT, $0-8 MOVD fn+0(FP), R3 // R3 = fn - MOVD R3, CTR + MOVD R3, R11 // context MOVD g_m(g), R4 // R4 = m + MOVD m_g0(R4), R5 // R5 = g0 CMP g, R5 BEQ onm + MOVD m_curg(R4), R6 + CMP g, R6 + BEQ oncurg + + // Not g0, not curg. Must be gsignal, but that's not allowed. + // Hide call from linker nosplit analysis. + MOVD $runtime·badonm(SB), R3 + MOVD R3, CTR + BL (CTR) + +oncurg: // save our state in g->sched. Pretend to // be switchtoM if the G stack is scanned. MOVD $runtime·switchtoM(SB), R6 @@ -178,10 +204,16 @@ TEXT runtime·onM(SB), NOSPLIT, $0-8 // switch to g0 MOVD R5, g - MOVD (g_sched+gobuf_sp)(g), R1 + MOVD (g_sched+gobuf_sp)(g), R3 + // make it look like mstart called onM on g0, to stop traceback + SUB $8, R3 + MOVD $runtime·mstart(SB), R4 + MOVD R4, 0(R3) + MOVD R3, R1 // call target function - ARGSIZE(0) + MOVD 0(R11), R3 // code pointer + MOVD R3, CTR BL (CTR) // switch back to g @@ -193,6 +225,8 @@ TEXT runtime·onM(SB), NOSPLIT, $0-8 onm: // already on m stack, just call directly + MOVD 0(R11), R3 // code pointer + MOVD R3, CTR BL (CTR) RETURN @@ -216,8 +250,11 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0 BNE 2(PC) BL runtime·abort(SB) - MOVW R3, m_moreframesize(R7) - MOVW R4, m_moreargsize(R7) + // Cannot grow signal stack (m->gsignal). + MOVD m_gsignal(R7), R8 + CMP g, R8 + BNE 2(PC) + BL runtime·abort(SB) // Called from f. // Set g->sched to context in f. @@ -231,8 +268,6 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0 // 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. @@ -248,51 +283,8 @@ 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). +// reflectcall: call a function with the given argument list +// func call(f *FuncVal, arg *byte, argsize, retoffset uint32). // we don't have variable-sized frames, so we use a small number // of constant-sized-frame functions to encode a few bits of size in the pc. // Caution: ugly multiline assembly macros in your future! @@ -301,60 +293,47 @@ TEXT runtime·newstackcall(SB), NOSPLIT, $-8-20 MOVD $MAXSIZE, R31; \ CMP R3, R31; \ BGT 4(PC); \ - MOVD $runtime·NAME(SB), R31; \ + MOVD $NAME(SB), R31; \ MOVD R31, CTR; \ BR (CTR) +// Note: can't just "BR NAME(SB)" - bad inlining results. -// Note: can't just "BR runtime·NAME(SB)" - bad inlining results. -TEXT reflect·call(SB), NOSPLIT, $-8-24 +TEXT ·reflectcall(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) + DISPATCH(runtime·call16, 16) + DISPATCH(runtime·call32, 32) + DISPATCH(runtime·call64, 64) + DISPATCH(runtime·call128, 128) + DISPATCH(runtime·call256, 256) + DISPATCH(runtime·call512, 512) + DISPATCH(runtime·call1024, 1024) + DISPATCH(runtime·call2048, 2048) + DISPATCH(runtime·call4096, 4096) + DISPATCH(runtime·call8192, 8192) + DISPATCH(runtime·call16384, 16384) + DISPATCH(runtime·call32768, 32768) + DISPATCH(runtime·call65536, 65536) + DISPATCH(runtime·call131072, 131072) + DISPATCH(runtime·call262144, 262144) + DISPATCH(runtime·call524288, 524288) + DISPATCH(runtime·call1048576, 1048576) + DISPATCH(runtime·call2097152, 2097152) + DISPATCH(runtime·call4194304, 4194304) + DISPATCH(runtime·call8388608, 8388608) + DISPATCH(runtime·call16777216, 16777216) + DISPATCH(runtime·call33554432, 33554432) + DISPATCH(runtime·call67108864, 67108864) + DISPATCH(runtime·call134217728, 134217728) + DISPATCH(runtime·call268435456, 268435456) + DISPATCH(runtime·call536870912, 536870912) + DISPATCH(runtime·call1073741824, 1073741824) MOVD $runtime·badreflectcall(SB), R31 MOVD R31, CTR BR (CTR) -// Argument map for the callXX frames. Each has one -// stack map (for the single call) with 3 arguments. -DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap -DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args -DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4)) -GLOBL gcargs_reflectcall<>(SB),RODATA,$12 - -// callXX frames have no locals -DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap -DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals -GLOBL gclocals_reflectcall<>(SB),RODATA,$8 - #define CALLFN(NAME,MAXSIZE) \ -TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \ - FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \ - FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\ +TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ + NO_LOCAL_POINTERS; \ /* copy arguments to stack */ \ MOVD argptr+8(FP), R3; \ MOVW argsize+16(FP), R4; \ @@ -391,47 +370,33 @@ TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \ 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) +CALLFN(·call16, 16) +CALLFN(·call32, 32) +CALLFN(·call64, 64) +CALLFN(·call128, 128) +CALLFN(·call256, 256) +CALLFN(·call512, 512) +CALLFN(·call1024, 1024) +CALLFN(·call2048, 2048) +CALLFN(·call4096, 4096) +CALLFN(·call8192, 8192) +CALLFN(·call16384, 16384) +CALLFN(·call32768, 32768) +CALLFN(·call65536, 65536) +CALLFN(·call131072, 131072) +CALLFN(·call262144, 262144) +CALLFN(·call524288, 524288) +CALLFN(·call1048576, 1048576) +CALLFN(·call2097152, 2097152) +CALLFN(·call4194304, 4194304) +CALLFN(·call8388608, 8388608) +CALLFN(·call16777216, 16777216) +CALLFN(·call33554432, 33554432) +CALLFN(·call67108864, 67108864) +CALLFN(·call134217728, 134217728) +CALLFN(·call268435456, 268435456) +CALLFN(·call536870912, 536870912) +CALLFN(·call1073741824, 1073741824) // bool cas(int32 *val, int32 old, int32 new) // Atomically: @@ -440,22 +405,23 @@ TEXT runtime·lessstack(SB), NOSPLIT, $-8-0 // return 1; // } else // return 0; -TEXT runtime·cas(SB), NOSPLIT, $0-16 +TEXT runtime·cas(SB), NOSPLIT, $0-17 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) + BNE 8(PC) STWCCC R5, (R3) BNE -5(PC) MOVD $1, R3 SYNC ISYNC + MOVB R3, ret+16(FP) RETURN MOVD $0, R3 - BR -4(PC) + BR -5(PC) // bool runtime·cas64(uint64 *val, uint64 old, uint64 new) // Atomically: @@ -465,7 +431,7 @@ TEXT runtime·cas(SB), NOSPLIT, $0-16 // } else { // return 0; // } -TEXT runtime·cas64(SB), NOSPLIT, $0-24 +TEXT runtime·cas64(SB), NOSPLIT, $0-25 MOVD p+0(FP), R3 MOVD old+8(FP), R4 MOVD new+16(FP), R5 @@ -478,10 +444,23 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-24 MOVD $1, R3 SYNC ISYNC + MOVB R3, ret+24(FP) RETURN MOVD $0, R3 BR -4(PC) +TEXT runtime·casuintptr(SB), NOSPLIT, $0-25 + BR runtime·cas64(SB) + +TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16 + BR runtime·atomicload64(SB) + +TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16 + BR runtime·atomicload64(SB) + +TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16 + BR runtime·atomicstore64(SB) + // bool casp(void **val, void *old, void *new) // Atomically: // if(*val == old){ @@ -489,14 +468,14 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-24 // return 1; // } else // return 0; -TEXT runtime·casp(SB), NOSPLIT, $0-24 +TEXT runtime·casp(SB), NOSPLIT, $0-25 BR runtime·cas64(SB) // uint32 xadd(uint32 volatile *val, int32 delta) // Atomically: // *val += delta; // return *val; -TEXT runtime·xadd(SB), NOSPLIT, $0-12 +TEXT runtime·xadd(SB), NOSPLIT, $0-20 MOVD p+0(FP), R4 MOVW delta+8(FP), R5 SYNC @@ -506,10 +485,10 @@ TEXT runtime·xadd(SB), NOSPLIT, $0-12 BNE -4(PC) SYNC ISYNC - MOVW R3, R3 + MOVW R3, ret+16(FP) RETURN -TEXT runtime·xadd64(SB), NOSPLIT, $0-16 +TEXT runtime·xadd64(SB), NOSPLIT, $0-24 MOVD p+0(FP), R4 MOVD delta+8(FP), R5 SYNC @@ -519,9 +498,10 @@ TEXT runtime·xadd64(SB), NOSPLIT, $0-16 BNE -4(PC) SYNC ISYNC + MOVD R3, ret+16(FP) RETURN -TEXT runtime·xchg(SB), NOSPLIT, $0-12 +TEXT runtime·xchg(SB), NOSPLIT, $0-20 MOVD p+0(FP), R4 MOVW new+8(FP), R5 SYNC @@ -530,9 +510,10 @@ TEXT runtime·xchg(SB), NOSPLIT, $0-12 BNE -3(PC) SYNC ISYNC + MOVW R3, ret+16(FP) RETURN -TEXT runtime·xchg64(SB), NOSPLIT, $0-16 +TEXT runtime·xchg64(SB), NOSPLIT, $0-24 MOVD p+0(FP), R4 MOVD new+8(FP), R5 SYNC @@ -541,9 +522,13 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-16 BNE -3(PC) SYNC ISYNC + MOVD R3, ret+16(FP) RETURN -TEXT runtime·xchgp(SB), NOSPLIT, $0-16 +TEXT runtime·xchgp(SB), NOSPLIT, $0-24 + BR runtime·xchg64(SB) + +TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24 BR runtime·xchg64(SB) TEXT runtime·procyield(SB),NOSPLIT,$0-0 @@ -553,20 +538,33 @@ 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 + MOVD ptr+0(FP), R3 + MOVW val+8(FP), R4 SYNC MOVW R4, 0(R3) RETURN TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16 + MOVD ptr+0(FP), R3 + MOVD val+8(FP), R4 + SYNC + MOVD R4, 0(R3) + RETURN + +// void runtime·atomicor8(byte volatile*, byte); +TEXT runtime·atomicor8(SB), NOSPLIT, $0-9 MOVD 0(FP), R3 MOVD 8(FP), R4 SYNC - MOVD R4, 0(R3) + LWAR (R3), R5 + OR R4, R5 + STWCCC R5, (R3) + BNE -3(PC) + SYNC + ISYNC RETURN -// void jmpdefer(fn, sp); +// void jmpdefer(fv, sp); // called from deferreturn. // 1. grab stored LR for caller // 2. sub 4 bytes to get back to BL deferreturn @@ -576,7 +574,7 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16 SUB $4, R31 MOVD R31, LR - MOVD fn+0(FP), R11 + MOVD fv+0(FP), R11 MOVD argp+8(FP), R1 SUB $8, R1 MOVD 0(R11), R3 @@ -597,7 +595,7 @@ TEXT gosave<>(SB),NOSPLIT,$-8 // Call fn(arg) on the scheduler stack, // aligned appropriately for the gcc ABI. // See cgocall.c for more details. -TEXT runtime·asmcgocall(SB),NOSPLIT,$0-16 +TEXT ·asmcgocall(SB),NOSPLIT,$0-16 MOVD R0, 21(R0) // cgocallback(void (*fn)(void*), void *frame, uintptr framesize) @@ -608,19 +606,20 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$24-24 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize) // See cgocall.c for more details. -TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-24 +TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24 MOVD R0, 23(R0) // void setg(G*); set g. for use by needm. -TEXT runtime·setg(SB), NOSPLIT, $0-16 +TEXT runtime·setg(SB), NOSPLIT, $0-8 MOVD R0, 24(R0) // void setg_gcc(G*); set g called from gcc. TEXT setg_gcc<>(SB),NOSPLIT,$0 MOVD R0, 25(R0) -TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-8 +TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-16 MOVD 0(R1), R3 + MOVD R3, ret+8(FP) RETURN TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16 @@ -629,16 +628,24 @@ TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16 RETURN TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16 - MOVD x+8(FP),R3 // addr of first arg + MOVD pc+8(FP), R3 MOVD R3, 0(R1) // set calling pc RETURN -TEXT runtime·getcallersp(SB),NOSPLIT,$0-8 +TEXT runtime·getcallersp(SB),NOSPLIT,$0-16 MOVD sp+0(FP), R3 SUB $8, R3 + MOVD R3, ret+8(FP) RETURN -TEXT runtime·abort(SB),NOSPLIT,$-4-0 +// func gogetcallersp(p unsafe.Pointer) uintptr +TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16 + MOVD sp+0(FP), R3 + SUB $8, R3 + MOVD R3,ret+8(FP) + RETURN + +TEXT runtime·abort(SB),NOSPLIT,$-8-0 MOVW (R0), R0 UNDEF @@ -646,7 +653,7 @@ TEXT runtime·abort(SB),NOSPLIT,$-4-0 #define TBRU 269 /* Time base Upper/Lower */ // int64 runtime·cputicks(void) -TEXT runtime·cputicks(SB),NOSPLIT,$0-0 +TEXT runtime·cputicks(SB),NOSPLIT,$0-8 MOVW SPR(TBRU), R4 MOVW SPR(TBRL), R3 MOVW SPR(TBRU), R5 @@ -654,17 +661,9 @@ TEXT runtime·cputicks(SB),NOSPLIT,$0-0 BNE -4(PC) SLD $32, R5 OR R5, R3 + MOVD R3, ret+0(FP) 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 @@ -675,7 +674,7 @@ TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0 MOVW (R0), R1 -TEXT runtime·memeq(SB),NOSPLIT,$-8-24 +TEXT runtime·memeq(SB),NOSPLIT,$-8-25 MOVD a+0(FP), R3 MOVD b+8(FP), R4 MOVD count+16(FP), R5 @@ -683,26 +682,6 @@ TEXT runtime·memeq(SB),NOSPLIT,$-8-24 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 @@ -711,14 +690,14 @@ _next2: MOVBZU 1(R3), R6 MOVBZU 1(R4), R7 CMP R6, R7 - BEQ _next2 + BEQ _next MOVB R0, ret+24(FP) RETURN // eqstring tests whether two strings are equal. // See runtime_test.go:eqstring_generic for -// equivlaent Go code. +// equivalent Go code. TEXT runtime·eqstring(SB),NOSPLIT,$0-33 MOVD s1len+8(FP), R4 MOVD s2len+24(FP), R5 @@ -824,9 +803,6 @@ _index2_notfound: 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 @@ -966,80 +942,22 @@ TEXT runtime·duffzero(SB), NOSPLIT, $-8-0 MOVDU R0, 8(R3) RETURN -TEXT runtime·fastrand2(SB), NOSPLIT, $0-4 +TEXT runtime·fastrand1(SB), NOSPLIT, $0-4 MOVD g_m(g), R4 - MOVD m_fastrand(R4), R3 + MOVWZ 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) + MOVW R3, m_fastrand(R4) + MOVW 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) +TEXT runtime·return0(SB), NOSPLIT, $0 + MOVW $0, R3 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 +// Called from cgo wrappers, this function returns g->m->curg.stack.hi. +// Must obey the gcc calling convention. +TEXT _cgo_topofstack(SB),NOSPLIT,$0 + MOVD R0, 26(R0) diff --git a/src/runtime/atomic_power64x.s b/src/runtime/atomic_power64x.s index c08590ac9..e72871761 100644 --- a/src/runtime/atomic_power64x.s +++ b/src/runtime/atomic_power64x.s @@ -4,34 +4,37 @@ // +build power64 power64le -#include "../../cmd/ld/textflag.h" +#include "textflag.h" // uint32 runtime·atomicload(uint32 volatile* addr) -TEXT ·atomicload(SB),NOSPLIT,$-8-8 +TEXT ·atomicload(SB),NOSPLIT,$-8-12 MOVD 0(FP), R3 SYNC MOVWZ 0(R3), R3 CMPW R3, R3, CR7 BC 4, 30, 1(PC) // bne- cr7,0x4 ISYNC + MOVW R3, ret+8(FP) RETURN // uint64 runtime·atomicload64(uint64 volatile* addr) -TEXT ·atomicload64(SB),NOSPLIT,$-8-8 +TEXT ·atomicload64(SB),NOSPLIT,$-8-16 MOVD 0(FP), R3 SYNC MOVD 0(R3), R3 CMP R3, R3, CR7 BC 4, 30, 1(PC) // bne- cr7,0x4 ISYNC + MOVD R3, ret+8(FP) RETURN // void *runtime·atomicloadp(void *volatile *addr) -TEXT ·atomicloadp(SB),NOSPLIT,$-8-8 +TEXT ·atomicloadp(SB),NOSPLIT,$-8-16 MOVD 0(FP), R3 SYNC MOVD 0(R3), R3 CMP R3, R3, CR7 BC 4, 30, 1(PC) // bne- cr7,0x4 ISYNC + MOVD R3, ret+8(FP) RETURN diff --git a/src/runtime/debug/stubs.s b/src/runtime/debug/stubs.s index d56274f2d..1e883b72c 100644 --- a/src/runtime/debug/stubs.s +++ b/src/runtime/debug/stubs.s @@ -7,6 +7,12 @@ #ifdef GOARCH_arm #define JMP B #endif +#ifdef GOARCH_power64 +#define JMP BR +#endif +#ifdef GOARCH_power64le +#define JMP BR +#endif TEXT ·setMaxStack(SB),NOSPLIT,$0-0 JMP runtime·setMaxStack(SB) diff --git a/src/runtime/defs_linux_power64.h b/src/runtime/defs_linux_power64.h index 64f145672..93742fa34 100644 --- a/src/runtime/defs_linux_power64.h +++ b/src/runtime/defs_linux_power64.h @@ -88,11 +88,10 @@ enum { typedef struct Sigset Sigset; typedef struct Timespec Timespec; typedef struct Timeval Timeval; -typedef struct Sigaction Sigaction; +typedef struct SigactionT SigactionT; typedef struct Siginfo Siginfo; typedef struct Itimerval Itimerval; typedef struct EpollEvent EpollEvent; -typedef uint64 Usigset; #pragma pack on @@ -109,11 +108,11 @@ struct Timeval { int64 tv_sec; int64 tv_usec; }; -struct Sigaction { +struct SigactionT { void *sa_handler; uint64 sa_flags; void *sa_restorer; - Usigset sa_mask; + uint64 sa_mask; }; struct Siginfo { int32 si_signo; @@ -129,7 +128,7 @@ struct Itimerval { struct EpollEvent { uint32 events; byte Pad_cgo_0[4]; - uint64 data; + byte data[8]; // unaligned uintptr }; @@ -144,7 +143,6 @@ enum { SA_RESTORER = 0, }; -//typedef struct Usigset Usigset; typedef struct Ptregs Ptregs; typedef struct Vreg Vreg; typedef struct SigaltstackT SigaltstackT; @@ -153,11 +151,6 @@ typedef struct Ucontext Ucontext; #pragma pack on -//struct Usigset { -// uint64 sig[1]; -//}; -//typedef Sigset Usigset; - struct Ptregs { uint64 gpr[32]; uint64 nip; @@ -202,8 +195,8 @@ struct Ucontext { uint64 uc_flags; Ucontext *uc_link; SigaltstackT uc_stack; - Usigset uc_sigmask; - Usigset __unused[15]; + uint64 uc_sigmask; + uint64 __unused[15]; Sigcontext uc_mcontext; }; diff --git a/src/runtime/memclr_power64x.s b/src/runtime/memclr_power64x.s index 4a2437c20..dfad64b6f 100644 --- a/src/runtime/memclr_power64x.s +++ b/src/runtime/memclr_power64x.s @@ -4,7 +4,7 @@ // +build power64 power64le -#include "../../cmd/ld/textflag.h" +#include "textflag.h" // void runtime·memclr(void*, uintptr) TEXT runtime·memclr(SB),NOSPLIT,$0-16 diff --git a/src/runtime/memmove_power64x.s b/src/runtime/memmove_power64x.s index b618f0ad7..2b04d8319 100644 --- a/src/runtime/memmove_power64x.s +++ b/src/runtime/memmove_power64x.s @@ -4,7 +4,7 @@ // +build power64 power64le -#include "../../cmd/ld/textflag.h" +#include "textflag.h" // void runtime·memmove(void*, void*, uintptr) TEXT runtime·memmove(SB), NOSPLIT, $-8-24 diff --git a/src/runtime/rt0_linux_power64.s b/src/runtime/rt0_linux_power64.s index e944bcdbf..970b6a673 100644 --- a/src/runtime/rt0_linux_power64.s +++ b/src/runtime/rt0_linux_power64.s @@ -1,7 +1,7 @@ -#include "../../cmd/ld/textflag.h" +#include "textflag.h" // actually a function descriptor for _main<>(SB) -TEXT _rt0_power64_linux(SB),7,$0 +TEXT _rt0_power64_linux(SB),NOSPLIT,$0 DWORD $_main<>(SB) DWORD $0 DWORD $0 @@ -12,6 +12,6 @@ TEXT _main<>(SB),NOSPLIT,$-8 BR main(SB) TEXT main(SB),NOSPLIT,$-8 - MOVD $_rt0_go(SB), R31 + MOVD $runtime·rt0_go(SB), R31 MOVD R31, CTR BR (CTR) diff --git a/src/runtime/rt0_linux_power64le.s b/src/runtime/rt0_linux_power64le.s index 051815dbc..85ce84733 100644 --- a/src/runtime/rt0_linux_power64le.s +++ b/src/runtime/rt0_linux_power64le.s @@ -1,6 +1,6 @@ -#include "../../cmd/ld/textflag.h" +#include "textflag.h" -TEXT _rt0_power64le_linux(SB),7,$0 +TEXT _rt0_power64le_linux(SB),NOSPLIT,$0 BR _main<>(SB) TEXT _main<>(SB),NOSPLIT,$-8 @@ -9,6 +9,6 @@ TEXT _main<>(SB),NOSPLIT,$-8 BR main(SB) TEXT main(SB),NOSPLIT,$-8 - MOVD $_rt0_go(SB), R31 + MOVD $runtime·rt0_go(SB), R31 MOVD R31, CTR BR (CTR) diff --git a/src/runtime/sys_linux_power64x.s b/src/runtime/sys_linux_power64x.s index fbd59a052..fb24d3e79 100644 --- a/src/runtime/sys_linux_power64x.s +++ b/src/runtime/sys_linux_power64x.s @@ -10,7 +10,7 @@ // #include "zasm_GOOS_GOARCH.h" -#include "../../cmd/ld/textflag.h" +#include "textflag.h" #define SYS_exit 1 #define SYS_read 3 @@ -44,49 +44,54 @@ #define SYS_clock_gettime 246 #define SYS_epoll_create1 315 -TEXT runtime·exit(SB),NOSPLIT,$-8-8 - MOVW 8(R1), R3 +TEXT runtime·exit(SB),NOSPLIT,$-8-4 + MOVW code+0(FP), R3 SYSCALL $SYS_exit_group RETURN -TEXT runtime·exit1(SB),NOSPLIT,$-8-8 - MOVW 8(R1), R3 +TEXT runtime·exit1(SB),NOSPLIT,$-8-4 + MOVW code+0(FP), R3 SYSCALL $SYS_exit RETURN -TEXT runtime·open(SB),NOSPLIT,$-8-16 - MOVD 8(R1), R3 - MOVW 16(R1), R4 - MOVW 20(R1), R5 +TEXT runtime·open(SB),NOSPLIT,$-8-20 + MOVD name+0(FP), R3 + MOVW mode+8(FP), R4 + MOVW perm+12(FP), R5 SYSCALL $SYS_open + MOVW R3, ret+16(FP) RETURN -TEXT runtime·close(SB),NOSPLIT,$-8-16 - MOVW 8(R1), R3 +TEXT runtime·close(SB),NOSPLIT,$-8-12 + MOVW fd+0(FP), R3 SYSCALL $SYS_close + MOVW R3, ret+8(FP) RETURN -TEXT runtime·write(SB),NOSPLIT,$-8-24 - MOVD 8(R1), R3 - MOVD 16(R1), R4 - MOVW 24(R1), R5 +TEXT runtime·write(SB),NOSPLIT,$-8-28 + MOVD fd+0(FP), R3 + MOVD p+8(FP), R4 + MOVW n+16(FP), R5 SYSCALL $SYS_write + MOVW R3, ret+24(FP) RETURN -TEXT runtime·read(SB),NOSPLIT,$-8-24 - MOVW 8(R1), R3 - MOVD 16(R1), R4 - MOVW 24(R1), R5 +TEXT runtime·read(SB),NOSPLIT,$-8-28 + MOVW fd+0(FP), R3 + MOVD p+8(FP), R4 + MOVW n+16(FP), R5 SYSCALL $SYS_read + MOVW R3, ret+24(FP) RETURN -TEXT runtime·getrlimit(SB),NOSPLIT,$-8-24 - MOVW 8(R1), R3 - MOVD 16(R1), R4 +TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20 + MOVW kind+0(FP), R3 + MOVD limit+8(FP), R4 SYSCALL $SYS_ugetrlimit + MOVW R3, ret+16(FP) RETURN -TEXT runtime·usleep(SB),NOSPLIT,$-8-16 +TEXT runtime·usleep(SB),NOSPLIT,$16-4 MOVW usec+0(FP), R3 MOVD R3, R5 MOVW $1000000, R4 @@ -113,17 +118,18 @@ TEXT runtime·raise(SB),NOSPLIT,$-8 RETURN TEXT runtime·setitimer(SB),NOSPLIT,$-8-24 - MOVW 8(R1), R3 - MOVD 16(R1), R4 - MOVD 24(R1), R5 + MOVW mode+0(FP), R3 + MOVD new+8(FP), R4 + MOVD old+16(FP), R5 SYSCALL $SYS_setitimer RETURN -TEXT runtime·mincore(SB),NOSPLIT,$-8-24 - MOVD 8(R1), R3 - MOVD 16(R1), R4 - MOVD 24(R1), R5 +TEXT runtime·mincore(SB),NOSPLIT,$-8-28 + MOVD addr+0(FP), R3 + MOVD n+8(FP), R4 + MOVD dst+16(FP), R5 SYSCALL $SYS_mincore + MOVW R3, ret+24(FP) RETURN // func now() (sec int64, nsec int32) @@ -150,24 +156,26 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16 MOVD $1000000000, R4 MULLD R4, R3 ADD R5, R3 + MOVD R3, ret+0(FP) RETURN -TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-32 - MOVW 8(R1), R3 - MOVD 16(R1), R4 - MOVD 24(R1), R5 - MOVW 32(R1), R6 +TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28 + MOVW sig+0(FP), R3 + MOVD new+8(FP), R4 + MOVD old+16(FP), R5 + MOVW size+24(FP), R6 SYSCALL $SYS_rt_sigprocmask BVC 2(PC) MOVD R0, 0xf1(R0) // crash RETURN -TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-32 - MOVD 8(R1), R3 - MOVD 16(R1), R4 - MOVD 24(R1), R5 - MOVD 32(R1), R6 +TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36 + MOVD sig+0(FP), R3 + MOVD new+8(FP), R4 + MOVD old+16(FP), R5 + MOVD size+24(FP), R6 SYSCALL $SYS_rt_sigaction + MOVW R3, ret+32(FP) RETURN #ifdef GOARCH_power64le @@ -214,28 +222,29 @@ TEXT runtime·_sigtramp(SB),NOSPLIT,$64 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 + MOVD addr+0(FP), R3 + MOVD n+8(FP), R4 + MOVW prot+16(FP), R5 + MOVW flags+20(FP), R6 + MOVW fd+24(FP), R7 + MOVW off+28(FP), R8 SYSCALL $SYS_mmap + MOVD R3, ret+32(FP) RETURN TEXT runtime·munmap(SB),NOSPLIT,$-8 - MOVD 8(R1), R3 - MOVD 16(R1), R4 + MOVD addr+0(FP), R3 + MOVD n+8(FP), R4 SYSCALL $SYS_munmap BVC 2(PC) MOVD R0, 0xf3(R0) RETURN TEXT runtime·madvise(SB),NOSPLIT,$-8 - MOVD 8(R1), R3 - MOVD 16(R1), R4 - MOVD 24(R1), R5 + MOVD addr+0(FP), R3 + MOVD n+8(FP), R4 + MOVW flags+16(FP), R5 SYSCALL $SYS_madvise // ignore failure - maybe pages are locked RETURN @@ -243,19 +252,20 @@ TEXT runtime·madvise(SB),NOSPLIT,$-8 // 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 + MOVD addr+0(FP), R3 + MOVW op+8(FP), R4 + MOVW val+12(FP), R5 + MOVD ts+16(FP), R6 + MOVD addr2+24(FP), R7 + MOVW val3+32(FP), R8 SYSCALL $SYS_futex + MOVW R3, ret+40(FP) RETURN -// int64 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); +// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void)); TEXT runtime·clone(SB),NOSPLIT,$-8 MOVW flags+0(FP), R3 - MOVD stack+8(FP), R4 + MOVD stk+8(FP), R4 // Copy mp, gp, fn off parent stack for use by child. // Careful: Linux system call clobbers ???. @@ -273,7 +283,8 @@ TEXT runtime·clone(SB),NOSPLIT,$-8 // In parent, return. CMP R3, $0 - BEQ 2(PC) + BEQ 3(PC) + MOVW R3, ret+40(FP) RETURN // In child, on new stack. @@ -322,45 +333,50 @@ TEXT runtime·osyield(SB),NOSPLIT,$-8 RETURN TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8 - MOVD 8(R1), R3 - MOVD 16(R1), R4 - MOVD 24(R1), R5 + MOVD pid+0(FP), R3 + MOVD len+8(FP), R4 + MOVD buf+16(FP), R5 SYSCALL $SYS_sched_getaffinity + MOVW R3, ret+24(FP) RETURN // int32 runtime·epollcreate(int32 size); TEXT runtime·epollcreate(SB),NOSPLIT,$-8 - MOVW 8(R1), R3 + MOVW size+0(FP), R3 SYSCALL $SYS_epoll_create + MOVW R3, ret+8(FP) RETURN // int32 runtime·epollcreate1(int32 flags); TEXT runtime·epollcreate1(SB),NOSPLIT,$-8 - MOVW 8(R1), R3 + MOVW flags+0(FP), R3 SYSCALL $SYS_epoll_create1 + MOVW R3, ret+8(FP) RETURN -// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev); +// func epollctl(epfd, op, fd int32, ev *epollEvent) int TEXT runtime·epollctl(SB),NOSPLIT,$-8 - MOVW 8(R1), R3 - MOVW 12(R1), R4 - MOVW 16(R1), R5 - MOVD 24(R1), R6 + MOVW epfd+0(FP), R3 + MOVW op+4(FP), R4 + MOVW fd+8(FP), R5 + MOVD ev+16(FP), R6 SYSCALL $SYS_epoll_ctl + MOVW R3, ret+24(FP) RETURN // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); TEXT runtime·epollwait(SB),NOSPLIT,$-8 - MOVW 8(R1), R3 - MOVD 16(R1), R4 - MOVW 24(R1), R5 - MOVW 28(R1), R6 + MOVW epfd+0(FP), R3 + MOVD ev+8(FP), R4 + MOVW nev+16(FP), R5 + MOVW timeout+20(FP), R6 SYSCALL $SYS_epoll_wait + MOVW R3, ret+24(FP) RETURN // void runtime·closeonexec(int32 fd); TEXT runtime·closeonexec(SB),NOSPLIT,$-8 - MOVW 8(R1), R3 // fd + MOVW fd+0(FP), R3 // fd MOVD $2, R4 // F_SETFD MOVD $1, R5 // FD_CLOEXEC SYSCALL $SYS_fcntl diff --git a/src/sync/atomic/asm_power64x.s b/src/sync/atomic/asm_power64x.s index bdb1dcff4..1130d3c16 100644 --- a/src/sync/atomic/asm_power64x.s +++ b/src/sync/atomic/asm_power64x.s @@ -4,7 +4,7 @@ // +build power64 power64le -#include "../../../cmd/ld/textflag.h" +#include "textflag.h" TEXT ·SwapInt32(SB),NOSPLIT,$0-20 BR ·SwapUint32(SB) diff --git a/src/syscall/asm.s b/src/syscall/asm.s index d4ca868f1..43561e201 100644 --- a/src/syscall/asm.s +++ b/src/syscall/asm.s @@ -4,5 +4,12 @@ #include "textflag.h" +#ifdef GOARCH_power64 +#define RET RETURN +#endif +#ifdef GOARCH_power64le +#define RET RETURN +#endif + TEXT ·use(SB),NOSPLIT,$0 RET diff --git a/src/syscall/asm_linux_power64x.s b/src/syscall/asm_linux_power64x.s index c9b0fe320..be8518a45 100644 --- a/src/syscall/asm_linux_power64x.s +++ b/src/syscall/asm_linux_power64x.s @@ -5,7 +5,7 @@ // +build linux // +build power64 power64le -#include "../../cmd/ld/textflag.h" +#include "textflag.h" // // System calls for Power64, Linux -- cgit v1.2.1 From 8fd8d4fc3e77101d12b836ca0ff334d20cd2ea04 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 28 Oct 2014 09:56:33 +1100 Subject: [dev.power64] runtime: fix power64le build Brings defs_linux_power64le.h up to date with the big endian version. LGTM=rsc R=rsc, austin CC=golang-codereviews https://codereview.appspot.com/161470043 --- src/runtime/defs_linux_power64le.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/runtime/defs_linux_power64le.h b/src/runtime/defs_linux_power64le.h index 64f145672..93742fa34 100644 --- a/src/runtime/defs_linux_power64le.h +++ b/src/runtime/defs_linux_power64le.h @@ -88,11 +88,10 @@ enum { typedef struct Sigset Sigset; typedef struct Timespec Timespec; typedef struct Timeval Timeval; -typedef struct Sigaction Sigaction; +typedef struct SigactionT SigactionT; typedef struct Siginfo Siginfo; typedef struct Itimerval Itimerval; typedef struct EpollEvent EpollEvent; -typedef uint64 Usigset; #pragma pack on @@ -109,11 +108,11 @@ struct Timeval { int64 tv_sec; int64 tv_usec; }; -struct Sigaction { +struct SigactionT { void *sa_handler; uint64 sa_flags; void *sa_restorer; - Usigset sa_mask; + uint64 sa_mask; }; struct Siginfo { int32 si_signo; @@ -129,7 +128,7 @@ struct Itimerval { struct EpollEvent { uint32 events; byte Pad_cgo_0[4]; - uint64 data; + byte data[8]; // unaligned uintptr }; @@ -144,7 +143,6 @@ enum { SA_RESTORER = 0, }; -//typedef struct Usigset Usigset; typedef struct Ptregs Ptregs; typedef struct Vreg Vreg; typedef struct SigaltstackT SigaltstackT; @@ -153,11 +151,6 @@ typedef struct Ucontext Ucontext; #pragma pack on -//struct Usigset { -// uint64 sig[1]; -//}; -//typedef Sigset Usigset; - struct Ptregs { uint64 gpr[32]; uint64 nip; @@ -202,8 +195,8 @@ struct Ucontext { uint64 uc_flags; Ucontext *uc_link; SigaltstackT uc_stack; - Usigset uc_sigmask; - Usigset __unused[15]; + uint64 uc_sigmask; + uint64 __unused[15]; Sigcontext uc_mcontext; }; -- cgit v1.2.1 From c9d3f794a30d01abe9da84bfc2be7b5303421043 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 28 Oct 2014 11:15:48 +1100 Subject: [dev.power64] runtime: fix cas64 on power64x cas64 was jumping to the wrong offset. LGTM=minux, rsc R=rsc, austin, minux CC=golang-codereviews https://codereview.appspot.com/158710043 --- src/runtime/asm_power64x.s | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index 76bf42094..b489f6acc 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -409,17 +409,19 @@ TEXT runtime·cas(SB), NOSPLIT, $0-17 MOVD p+0(FP), R3 MOVW old+8(FP), R4 MOVW new+12(FP), R5 +cas_again: SYNC LWAR (R3), R6 CMPW R6, R4 - BNE 8(PC) + BNE cas_fail STWCCC R5, (R3) - BNE -5(PC) + BNE cas_again MOVD $1, R3 SYNC ISYNC MOVB R3, ret+16(FP) RETURN +cas_fail: MOVD $0, R3 BR -5(PC) @@ -435,19 +437,21 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25 MOVD p+0(FP), R3 MOVD old+8(FP), R4 MOVD new+16(FP), R5 +cas64_again: SYNC LDAR (R3), R6 CMP R6, R4 - BNE 7(PC) + BNE cas64_fail STDCCC R5, (R3) - BNE -5(PC) + BNE cas64_again MOVD $1, R3 SYNC ISYNC MOVB R3, ret+24(FP) RETURN +cas64_fail: MOVD $0, R3 - BR -4(PC) + BR -5(PC) TEXT runtime·casuintptr(SB), NOSPLIT, $0-25 BR runtime·cas64(SB) -- cgit v1.2.1 From 8777610f3b35969d2f52acc32056ea08549b0ba1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 28 Oct 2014 10:14:19 -0400 Subject: [dev.power64] liblink: emit wrapper code in correct place The wrapper code was being emitted before the stack reservation, rather than after. LGTM=rsc R=rsc, dave CC=golang-codereviews https://codereview.appspot.com/161540043 --- src/liblink/obj9.c | 126 ++++++++++++++++++++++++++--------------------------- 1 file changed, 63 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 3db08c545..0bae64d0b 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -490,74 +490,74 @@ addstacksplit(Link *ctxt, LSym *cursym) // 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; + q = appendp(ctxt, q); + q->as = AMOVD; + q->from.type = D_OREG; + q->from.reg = REGG; + q->from.offset = 4*ctxt->arch->ptrsize; // G.panic + q->to.type = D_REG; + q->to.reg = 3; - 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; + q = appendp(ctxt, q); + q->as = ACMP; + q->from.type = D_REG; + q->from.reg = 0; + q->to.type = D_REG; + q->to.reg = 3; + + q = appendp(ctxt, q); + q->as = ABEQ; + q->to.type = D_BRANCH; + p1 = q; + + q = appendp(ctxt, q); + q->as = AMOVD; + q->from.type = D_OREG; + q->from.reg = 3; + q->from.offset = 0; // Panic.argp + q->to.type = D_REG; + q->to.reg = 4; - 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; + q = appendp(ctxt, q); + q->as = AADD; + q->from.type = D_CONST; + q->from.offset = autosize+8; + q->reg = REGSP; + q->to.type = D_REG; + q->to.reg = 5; - 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; + q = appendp(ctxt, q); + q->as = ACMP; + q->from.type = D_REG; + q->from.reg = 4; + q->to.type = D_REG; + q->to.reg = 5; - p = appendp(ctxt, p); - p->as = ABNE; - p->to.type = D_BRANCH; - p2 = p; + q = appendp(ctxt, q); + q->as = ABNE; + q->to.type = D_BRANCH; + p2 = q; - 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; + q = appendp(ctxt, q); + q->as = AADD; + q->from.type = D_CONST; + q->from.offset = 8; + q->reg = REGSP; + q->to.type = D_REG; + q->to.reg = 6; + + q = appendp(ctxt, q); + q->as = AMOVD; + q->from.type = D_REG; + q->from.reg = 6; + q->to.type = D_OREG; + q->to.reg = 3; + q->to.offset = 0; // Panic.argp + + q = appendp(ctxt, q); + q->as = ANOP; + p1->pcond = q; + p2->pcond = q; } break; -- cgit v1.2.1 From ef12babfae569c89d7045b6daac218fa15c93312 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 28 Oct 2014 15:08:09 -0400 Subject: [dev.power64] 9a: correct generation of four argument ops The "to" field was the penultimate argument to outgcode, instead of the last argument, which swapped the third and fourth operands. The argument order was correct in a.y, so just swap the meaning of the arguments in outgcode. This hadn't come up because we hadn't used these more obscure operations in any hand-written assembly until now. LGTM=rsc, dave R=rsc, dave CC=golang-codereviews https://codereview.appspot.com/160690043 --- src/cmd/9a/lex.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c index bd38493d5..26f21f743 100644 --- a/src/cmd/9a/lex.c +++ b/src/cmd/9a/lex.c @@ -706,10 +706,9 @@ outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3) p->mark |= NOSCHED; p->from = *g1; p->reg = reg; - p->to = *g2; - p->from3 = *g3; + p->from3 = *g2; + p->to = *g3; p->pc = pc; - print("oc: %P\n", p); if(lastpc == nil) { pl = linknewplist(ctxt); -- cgit v1.2.1 From c9851bece1a56434cf60ad6b98694a027599d1f6 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 28 Oct 2014 15:57:33 -0400 Subject: [dev.power64] runtime: fix atomicor8 for power64x Power64 servers do not currently support sub-word size atomic memory access, so atomicor8 uses word size atomic access. However, previously atomicor8 made no attempt to align this access, resulting in errors. Fix this by aligning the pointer to a word boundary and shifting the value appropriately. Since atomicor8 is used in GC, add a test to runtime?check to make sure this doesn't break in the future. This also fixes an incorrect branch label, an incorrectly sized argument move, and adds argument names to help go vet. LGTM=rsc R=rsc, dave CC=golang-codereviews https://codereview.appspot.com/165820043 --- src/runtime/asm_power64x.s | 26 ++++++++++++++++++++------ src/runtime/runtime.c | 6 ++++++ 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index b489f6acc..21220e5cb 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -557,13 +557,27 @@ TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16 // void runtime·atomicor8(byte volatile*, byte); TEXT runtime·atomicor8(SB), NOSPLIT, $0-9 - MOVD 0(FP), R3 - MOVD 8(FP), R4 + MOVD ptr+0(FP), R3 + MOVBZ val+8(FP), R4 + // Align ptr down to 4 bytes so we can use 32-bit load/store. + // R5 = (R3 << 0) & ~3 + RLDCR $0, R3, $~3, R5 + // Compute val shift. +#ifdef GOARCH_power64 + // Big endian. ptr = ptr ^ 3 + XOR $3, R3 +#endif + // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8) + RLDC $3, R3, $(3*8), R6 + // Shift val for aligned ptr. R4 = val << R6 + SLD R6, R4, R4 + +atomicor8_again: SYNC - LWAR (R3), R5 - OR R4, R5 - STWCCC R5, (R3) - BNE -3(PC) + LWAR (R5), R6 + OR R4, R6 + STWCCC R6, (R5) + BNE atomicor8_again SYNC ISYNC RETURN diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index b3503fb90..d984983ce 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -185,6 +185,7 @@ runtime·check(void) float64 j, j1; byte *k, *k1; uint16* l; + byte m[4]; struct x1 { byte x; }; @@ -236,6 +237,11 @@ runtime·check(void) if(k != k1) runtime·throw("casp3"); + m[0] = m[1] = m[2] = m[3] = 0x1; + runtime·atomicor8(&m[1], 0xf0); + if (m[0] != 0x1 || m[1] != 0xf1 || m[2] != 0x1 || m[3] != 0x1) + runtime·throw("atomicor8"); + *(uint64*)&j = ~0ULL; if(j == j) runtime·throw("float64nan"); -- cgit v1.2.1 From 05d42f8a61328aa7ea55887f601286b597caf0da Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 28 Oct 2014 21:50:16 -0400 Subject: [dev.power64] cmd/5a, cmd/6a, cmd/8a, cmd/9a: make labels function-scoped I removed support for jumping between functions years ago, as part of doing the instruction layout for each function separately. Given that, it makes sense to treat labels as function-scoped. This lets each function have its own 'loop' label, for example. Makes the assembly much cleaner and removes the last reason anyone would reach for the 123(PC) form instead. Note that this is on the dev.power64 branch, but it changes all the assemblers. The change will ship in Go 1.5 (perhaps after being ported into the new assembler). Came up as part of CL 167730043. LGTM=r R=r CC=austin, dave, golang-codereviews, minux https://codereview.appspot.com/159670043 --- src/cmd/5a/a.h | 3 + src/cmd/5a/a.y | 26 +- src/cmd/5a/y.tab.c | 2049 ++++++++++++++---------------- src/cmd/5a/y.tab.h | 68 +- src/cmd/6a/a.h | 3 + src/cmd/6a/a.y | 25 +- src/cmd/6a/y.tab.c | 1054 ++++++++-------- src/cmd/8a/a.h | 3 + src/cmd/8a/a.y | 25 +- src/cmd/8a/y.tab.c | 1050 ++++++++-------- src/cmd/9a/a.h | 3 + src/cmd/9a/a.y | 26 +- src/cmd/9a/y.tab.c | 2602 +++++++++++++++++---------------------- src/cmd/9a/y.tab.h | 46 +- src/cmd/cc/lexbody | 25 + src/runtime/asm_386.s | 58 +- src/runtime/asm_amd64.s | 78 +- src/runtime/asm_amd64p32.s | 58 +- src/runtime/asm_arm.s | 24 +- src/runtime/asm_power64x.s | 40 +- src/runtime/memclr_386.s | 46 +- src/runtime/memclr_amd64.s | 44 +- src/runtime/memclr_plan9_386.s | 24 +- src/runtime/race_amd64.s | 18 +- src/runtime/sys_darwin_386.s | 4 +- src/runtime/sys_darwin_amd64.s | 4 +- src/runtime/sys_dragonfly_386.s | 4 +- src/runtime/sys_freebsd_386.s | 4 +- src/runtime/sys_linux_amd64.s | 8 +- src/runtime/sys_linux_arm.s | 8 +- src/runtime/sys_nacl_386.s | 4 +- src/runtime/sys_nacl_amd64p32.s | 1 - src/runtime/sys_nacl_arm.s | 1 - src/runtime/sys_openbsd_386.s | 4 +- src/runtime/sys_solaris_amd64.s | 12 +- src/runtime/sys_windows_386.s | 12 +- src/runtime/sys_windows_amd64.s | 12 +- 37 files changed, 3442 insertions(+), 4034 deletions(-) (limited to 'src') diff --git a/src/cmd/5a/a.h b/src/cmd/5a/a.h index bb60fe7de..df9838ad3 100644 --- a/src/cmd/5a/a.h +++ b/src/cmd/5a/a.h @@ -67,6 +67,7 @@ struct Sym int32 value; ushort type; char *name; + char* labelname; char sym; }; #define S ((Sym*)0) @@ -136,6 +137,8 @@ void newio(void); void newfile(char*, int); Sym* slookup(char*); Sym* lookup(void); +Sym* labellookup(Sym*); +void settext(LSym*); void syminit(Sym*); int32 yylex(void); int getc(void); diff --git a/src/cmd/5a/a.y b/src/cmd/5a/a.y index ad647606e..d365c7534 100644 --- a/src/cmd/5a/a.y +++ b/src/cmd/5a/a.y @@ -73,15 +73,11 @@ prog: line line: - LLAB ':' - { - if($1->value != pc) - yyerror("redeclaration of %s", $1->name); - $1->value = pc; - } - line -| LNAME ':' + LNAME ':' { + $1 = labellookup($1); + if($1->type == LLAB && $1->value != pc) + yyerror("redeclaration of %s", $1->labelname); $1->type = LLAB; $1->value = pc; } @@ -218,18 +214,21 @@ inst: */ | LTYPEB name ',' imm { + settext($2.sym); $4.type = D_CONST2; $4.offset2 = ArgsSizeUnknown; outcode($1, Always, &$2, 0, &$4); } | LTYPEB name ',' con ',' imm { + settext($2.sym); $6.type = D_CONST2; $6.offset2 = ArgsSizeUnknown; outcode($1, Always, &$2, $4, &$6); } | LTYPEB name ',' con ',' imm '-' con { + settext($2.sym); $6.type = D_CONST2; $6.offset2 = $8; outcode($1, Always, &$2, $4, &$6); @@ -373,15 +372,10 @@ rel: } | LNAME offset { + $1 = labellookup($1); $$ = nullgen; - if(pass == 2) - yyerror("undefined label: %s", $1->name); - $$.type = D_BRANCH; - $$.offset = $2; - } -| LLAB offset - { - $$ = nullgen; + if(pass == 2 && $1->type != LLAB) + yyerror("undefined label: %s", $1->labelname); $$.type = D_BRANCH; $$.offset = $1->value + $2; } diff --git a/src/cmd/5a/y.tab.c b/src/cmd/5a/y.tab.c index a6251b835..ace80c7e0 100644 --- a/src/cmd/5a/y.tab.c +++ b/src/cmd/5a/y.tab.c @@ -1,21 +1,24 @@ -/* A Bison parser, made by GNU Bison 2.7.12-4996. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - + the Free Software Foundation; either version 2, or (at your option) + any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -26,7 +29,7 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ @@ -44,7 +47,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.7.12-4996" +#define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -52,55 +55,10 @@ /* Pure parsers. */ #define YYPURE 0 -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* Copy the first part of user declarations. */ -/* Line 371 of yacc.c */ -#line 31 "a.y" - -#include -#include /* if we don't, bison will, and a.h re-#defines getc */ -#include -#include "a.h" -#include "../../runtime/funcdata.h" +/* Using locations. */ +#define YYLSP_NEEDED 0 -/* Line 371 of yacc.c */ -#line 76 "y.tab.c" -# ifndef YY_NULL -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULL nullptr -# else -# define YY_NULL 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* In a future release of Bison, this section will be replaced - by #include "y.tab.h". */ -#ifndef YY_YY_Y_TAB_H_INCLUDED -# define YY_YY_Y_TAB_H_INCLUDED -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif /* Tokens. */ #ifndef YYTOKENTYPE @@ -210,49 +168,60 @@ extern int yydebug; + +/* Copy the first part of user declarations. */ +#line 31 "a.y" + +#include +#include /* if we don't, bison will, and a.h re-#defines getc */ +#include +#include "a.h" +#include "../../runtime/funcdata.h" + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -{ -/* Line 387 of yacc.c */ #line 39 "a.y" - +{ Sym *sym; int32 lval; double dval; char sval[8]; Addr addr; - - -/* Line 387 of yacc.c */ -#line 228 "y.tab.c" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 +} +/* Line 193 of yacc.c. */ +#line 212 "y.tab.c" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif -extern YYSTYPE yylval; -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - -#endif /* !YY_YY_Y_TAB_H_INCLUDED */ /* Copy the second part of user declarations. */ -/* Line 390 of yacc.c */ -#line 256 "y.tab.c" + +/* Line 216 of yacc.c. */ +#line 225 "y.tab.c" #ifdef short # undef short @@ -305,45 +274,36 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if (! defined __GNUC__ || __GNUC__ < 2 \ - || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) -# define __attribute__(Spec) /* empty */ +# define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YYUSE(e) ((void) (e)) #else -# define YYUSE(E) /* empty */ +# define YYUSE(e) /* empty */ #endif - /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(N) (N) +# define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int -YYID (int yyi) +YYID (int i) #else static int -YYID (yyi) - int yyi; +YYID (i) + int i; #endif { - return yyi; + return i; } #endif @@ -364,12 +324,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # endif @@ -392,24 +351,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ +# if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -425,9 +384,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; + yytype_int16 yyss; + YYSTYPE yyvs; + }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -438,19 +397,35 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -# define YYCOPY_NEEDED 1 +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ +# define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ @@ -458,39 +433,19 @@ union yyalloc #endif -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 609 +#define YYLAST 640 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 71 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 35 +#define YYNNTS 34 /* YYNRULES -- Number of rules. */ -#define YYNRULES 133 +#define YYNRULES 130 /* YYNRULES -- Number of states. */ -#define YYNSTATES 339 +#define YYNSTATES 333 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -540,101 +495,100 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint16 yyprhs[] = { - 0, 0, 3, 4, 5, 9, 10, 15, 16, 21, - 26, 31, 33, 36, 39, 47, 54, 60, 66, 72, - 77, 82, 86, 90, 95, 102, 110, 118, 126, 133, - 140, 144, 149, 156, 165, 172, 177, 181, 187, 193, - 201, 208, 221, 229, 239, 242, 247, 252, 255, 256, - 259, 262, 263, 266, 271, 274, 277, 280, 283, 288, - 291, 293, 296, 300, 302, 306, 310, 312, 314, 316, - 321, 323, 325, 327, 329, 331, 333, 335, 339, 341, - 346, 348, 353, 355, 357, 359, 361, 364, 366, 372, - 377, 382, 387, 392, 394, 396, 398, 400, 405, 407, - 409, 411, 416, 418, 420, 422, 427, 432, 438, 446, - 447, 450, 453, 455, 457, 459, 461, 463, 466, 469, - 472, 476, 477, 480, 482, 486, 490, 494, 498, 502, - 507, 512, 516, 520 + 0, 0, 3, 4, 5, 9, 10, 15, 20, 25, + 27, 30, 33, 41, 48, 54, 60, 66, 71, 76, + 80, 84, 89, 96, 104, 112, 120, 127, 134, 138, + 143, 150, 159, 166, 171, 175, 181, 187, 195, 202, + 215, 223, 233, 236, 241, 246, 249, 250, 253, 256, + 257, 260, 265, 268, 271, 274, 279, 282, 284, 287, + 291, 293, 297, 301, 303, 305, 307, 312, 314, 316, + 318, 320, 322, 324, 326, 330, 332, 337, 339, 344, + 346, 348, 350, 352, 355, 357, 363, 368, 373, 378, + 383, 385, 387, 389, 391, 396, 398, 400, 402, 407, + 409, 411, 413, 418, 423, 429, 437, 438, 441, 444, + 446, 448, 450, 452, 454, 457, 460, 463, 467, 468, + 471, 473, 477, 481, 485, 489, 493, 498, 503, 507, + 511 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 72, 0, -1, -1, -1, 72, 73, 74, -1, -1, - 59, 61, 75, 74, -1, -1, 58, 61, 76, 74, - -1, 58, 62, 105, 63, -1, 60, 62, 105, 63, - -1, 63, -1, 77, 63, -1, 1, 63, -1, 13, - 78, 89, 64, 96, 64, 91, -1, 13, 78, 89, - 64, 96, 64, -1, 13, 78, 89, 64, 91, -1, - 14, 78, 89, 64, 91, -1, 15, 78, 84, 64, - 84, -1, 16, 78, 79, 80, -1, 16, 78, 79, - 85, -1, 35, 79, 86, -1, 17, 79, 80, -1, - 18, 78, 79, 84, -1, 19, 78, 89, 64, 96, - 79, -1, 20, 78, 87, 64, 65, 83, 66, -1, - 20, 78, 65, 83, 66, 64, 87, -1, 21, 78, - 91, 64, 86, 64, 91, -1, 21, 78, 91, 64, - 86, 79, -1, 21, 78, 79, 86, 64, 91, -1, - 22, 78, 79, -1, 23, 100, 64, 90, -1, 23, - 100, 64, 103, 64, 90, -1, 23, 100, 64, 103, - 64, 90, 9, 103, -1, 24, 100, 11, 103, 64, - 81, -1, 25, 78, 91, 79, -1, 28, 79, 81, - -1, 29, 78, 99, 64, 99, -1, 31, 78, 98, - 64, 99, -1, 31, 78, 98, 64, 48, 64, 99, - -1, 32, 78, 99, 64, 99, 79, -1, 30, 78, - 103, 64, 105, 64, 96, 64, 97, 64, 97, 104, - -1, 33, 78, 91, 64, 91, 64, 92, -1, 34, - 78, 91, 64, 91, 64, 91, 64, 96, -1, 36, - 88, -1, 43, 84, 64, 84, -1, 44, 84, 64, - 84, -1, 26, 79, -1, -1, 78, 53, -1, 78, - 54, -1, -1, 64, 79, -1, 103, 67, 41, 68, - -1, 58, 101, -1, 59, 101, -1, 69, 103, -1, - 69, 88, -1, 69, 10, 69, 88, -1, 69, 57, - -1, 82, -1, 69, 56, -1, 69, 9, 56, -1, - 96, -1, 96, 9, 96, -1, 96, 79, 83, -1, - 91, -1, 81, -1, 93, -1, 93, 67, 96, 68, - -1, 51, -1, 52, -1, 103, -1, 88, -1, 99, - -1, 86, -1, 100, -1, 67, 96, 68, -1, 86, - -1, 103, 67, 95, 68, -1, 100, -1, 100, 67, - 95, 68, -1, 87, -1, 91, -1, 90, -1, 93, - -1, 69, 103, -1, 96, -1, 67, 96, 64, 96, - 68, -1, 96, 6, 6, 94, -1, 96, 7, 7, - 94, -1, 96, 9, 7, 94, -1, 96, 55, 7, - 94, -1, 96, -1, 103, -1, 46, -1, 41, -1, - 45, 67, 105, 68, -1, 95, -1, 38, -1, 50, - -1, 49, 67, 105, 68, -1, 99, -1, 82, -1, - 48, -1, 47, 67, 103, 68, -1, 103, 67, 102, - 68, -1, 58, 101, 67, 102, 68, -1, 58, 6, - 7, 101, 67, 39, 68, -1, -1, 8, 103, -1, - 9, 103, -1, 39, -1, 38, -1, 40, -1, 37, - -1, 60, -1, 9, 103, -1, 8, 103, -1, 70, - 103, -1, 67, 105, 68, -1, -1, 64, 105, -1, - 103, -1, 105, 8, 105, -1, 105, 9, 105, -1, - 105, 10, 105, -1, 105, 11, 105, -1, 105, 12, - 105, -1, 105, 6, 6, 105, -1, 105, 7, 7, - 105, -1, 105, 5, 105, -1, 105, 4, 105, -1, - 105, 3, 105, -1 + 58, 61, 75, 74, -1, 58, 62, 104, 63, -1, + 60, 62, 104, 63, -1, 63, -1, 76, 63, -1, + 1, 63, -1, 13, 77, 88, 64, 95, 64, 90, + -1, 13, 77, 88, 64, 95, 64, -1, 13, 77, + 88, 64, 90, -1, 14, 77, 88, 64, 90, -1, + 15, 77, 83, 64, 83, -1, 16, 77, 78, 79, + -1, 16, 77, 78, 84, -1, 35, 78, 85, -1, + 17, 78, 79, -1, 18, 77, 78, 83, -1, 19, + 77, 88, 64, 95, 78, -1, 20, 77, 86, 64, + 65, 82, 66, -1, 20, 77, 65, 82, 66, 64, + 86, -1, 21, 77, 90, 64, 85, 64, 90, -1, + 21, 77, 90, 64, 85, 78, -1, 21, 77, 78, + 85, 64, 90, -1, 22, 77, 78, -1, 23, 99, + 64, 89, -1, 23, 99, 64, 102, 64, 89, -1, + 23, 99, 64, 102, 64, 89, 9, 102, -1, 24, + 99, 11, 102, 64, 80, -1, 25, 77, 90, 78, + -1, 28, 78, 80, -1, 29, 77, 98, 64, 98, + -1, 31, 77, 97, 64, 98, -1, 31, 77, 97, + 64, 48, 64, 98, -1, 32, 77, 98, 64, 98, + 78, -1, 30, 77, 102, 64, 104, 64, 95, 64, + 96, 64, 96, 103, -1, 33, 77, 90, 64, 90, + 64, 91, -1, 34, 77, 90, 64, 90, 64, 90, + 64, 95, -1, 36, 87, -1, 43, 83, 64, 83, + -1, 44, 83, 64, 83, -1, 26, 78, -1, -1, + 77, 53, -1, 77, 54, -1, -1, 64, 78, -1, + 102, 67, 41, 68, -1, 58, 100, -1, 69, 102, + -1, 69, 87, -1, 69, 10, 69, 87, -1, 69, + 57, -1, 81, -1, 69, 56, -1, 69, 9, 56, + -1, 95, -1, 95, 9, 95, -1, 95, 78, 82, + -1, 90, -1, 80, -1, 92, -1, 92, 67, 95, + 68, -1, 51, -1, 52, -1, 102, -1, 87, -1, + 98, -1, 85, -1, 99, -1, 67, 95, 68, -1, + 85, -1, 102, 67, 94, 68, -1, 99, -1, 99, + 67, 94, 68, -1, 86, -1, 90, -1, 89, -1, + 92, -1, 69, 102, -1, 95, -1, 67, 95, 64, + 95, 68, -1, 95, 6, 6, 93, -1, 95, 7, + 7, 93, -1, 95, 9, 7, 93, -1, 95, 55, + 7, 93, -1, 95, -1, 102, -1, 46, -1, 41, + -1, 45, 67, 104, 68, -1, 94, -1, 38, -1, + 50, -1, 49, 67, 104, 68, -1, 98, -1, 81, + -1, 48, -1, 47, 67, 102, 68, -1, 102, 67, + 101, 68, -1, 58, 100, 67, 101, 68, -1, 58, + 6, 7, 100, 67, 39, 68, -1, -1, 8, 102, + -1, 9, 102, -1, 39, -1, 38, -1, 40, -1, + 37, -1, 60, -1, 9, 102, -1, 8, 102, -1, + 70, 102, -1, 67, 104, 68, -1, -1, 64, 104, + -1, 102, -1, 104, 8, 104, -1, 104, 9, 104, + -1, 104, 10, 104, -1, 104, 11, 104, -1, 104, + 12, 104, -1, 104, 6, 6, 104, -1, 104, 7, + 7, 104, -1, 104, 5, 104, -1, 104, 4, 104, + -1, 104, 3, 104, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 68, 68, 70, 69, 77, 76, 84, 83, 89, - 94, 100, 101, 102, 108, 112, 116, 123, 130, 137, - 141, 148, 155, 162, 169, 176, 185, 197, 201, 205, - 212, 219, 225, 231, 240, 247, 254, 261, 265, 269, - 273, 280, 302, 310, 319, 326, 335, 346, 352, 355, - 359, 364, 365, 368, 374, 382, 389, 395, 400, 405, - 411, 414, 420, 428, 432, 441, 447, 448, 449, 450, - 455, 461, 467, 473, 474, 477, 478, 486, 495, 496, - 505, 506, 512, 515, 516, 517, 519, 527, 535, 544, - 550, 556, 562, 570, 576, 584, 585, 589, 597, 598, - 604, 605, 613, 614, 617, 623, 631, 639, 647, 657, - 660, 664, 670, 671, 672, 675, 676, 680, 684, 688, - 692, 698, 701, 707, 708, 712, 716, 720, 724, 728, - 732, 736, 740, 744 + 0, 68, 68, 70, 69, 77, 76, 85, 90, 96, + 97, 98, 104, 108, 112, 119, 126, 133, 137, 144, + 151, 158, 165, 172, 181, 193, 197, 201, 208, 215, + 222, 229, 239, 246, 253, 260, 264, 268, 272, 279, + 301, 309, 318, 325, 334, 345, 351, 354, 358, 363, + 364, 367, 373, 383, 389, 394, 399, 405, 408, 414, + 422, 426, 435, 441, 442, 443, 444, 449, 455, 461, + 467, 468, 471, 472, 480, 489, 490, 499, 500, 506, + 509, 510, 511, 513, 521, 529, 538, 544, 550, 556, + 564, 570, 578, 579, 583, 591, 592, 598, 599, 607, + 608, 611, 617, 625, 633, 641, 651, 654, 658, 664, + 665, 666, 669, 670, 674, 678, 682, 686, 692, 695, + 701, 702, 706, 710, 714, 718, 722, 726, 730, 734, + 738 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || 0 +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -647,11 +601,11 @@ static const char *const yytname[] = "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LTYPEPC", "LTYPEF", "LR", "LREG", "LF", "LFREG", "LC", "LCREG", "LPSR", "LFCR", "LCOND", "LS", "LAT", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='", "';'", - "','", "'['", "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog", - "$@1", "line", "$@2", "$@3", "inst", "cond", "comma", "rel", "ximm", - "fcon", "reglist", "gen", "nireg", "ireg", "ioreg", "oreg", "imsr", - "imm", "reg", "regreg", "shift", "rcon", "sreg", "spreg", "creg", - "frcon", "freg", "name", "offset", "pointer", "con", "oexpr", "expr", YY_NULL + "','", "'['", "']'", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1", + "line", "@2", "inst", "cond", "comma", "rel", "ximm", "fcon", "reglist", + "gen", "nireg", "ireg", "ioreg", "oreg", "imsr", "imm", "reg", "regreg", + "shift", "rcon", "sreg", "spreg", "creg", "frcon", "freg", "name", + "offset", "pointer", "con", "oexpr", "expr", 0 }; #endif @@ -674,279 +628,282 @@ static const yytype_uint16 yytoknum[] = /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 71, 72, 73, 72, 75, 74, 76, 74, 74, - 74, 74, 74, 74, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, - 78, 79, 79, 80, 80, 80, 81, 81, 81, 81, - 81, 82, 82, 83, 83, 83, 84, 84, 84, 84, - 84, 84, 84, 84, 84, 85, 85, 86, 87, 87, - 88, 88, 88, 89, 89, 89, 90, 91, 92, 93, - 93, 93, 93, 94, 94, 95, 95, 95, 96, 96, - 97, 97, 98, 98, 99, 99, 100, 100, 100, 101, - 101, 101, 102, 102, 102, 103, 103, 103, 103, 103, - 103, 104, 104, 105, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 105 + 0, 71, 72, 73, 72, 75, 74, 74, 74, 74, + 74, 74, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 77, 77, 77, 78, + 78, 79, 79, 80, 80, 80, 80, 80, 81, 81, + 82, 82, 82, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 84, 84, 85, 86, 86, 87, 87, 87, + 88, 88, 88, 89, 90, 91, 92, 92, 92, 92, + 93, 93, 94, 94, 94, 95, 95, 96, 96, 97, + 97, 98, 98, 99, 99, 99, 100, 100, 100, 101, + 101, 101, 102, 102, 102, 102, 102, 102, 103, 103, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 0, 0, 3, 0, 4, 0, 4, 4, - 4, 1, 2, 2, 7, 6, 5, 5, 5, 4, - 4, 3, 3, 4, 6, 7, 7, 7, 6, 6, - 3, 4, 6, 8, 6, 4, 3, 5, 5, 7, - 6, 12, 7, 9, 2, 4, 4, 2, 0, 2, - 2, 0, 2, 4, 2, 2, 2, 2, 4, 2, - 1, 2, 3, 1, 3, 3, 1, 1, 1, 4, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, - 1, 4, 1, 1, 1, 1, 2, 1, 5, 4, - 4, 4, 4, 1, 1, 1, 1, 4, 1, 1, - 1, 4, 1, 1, 1, 4, 4, 5, 7, 0, - 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, - 3, 0, 2, 1, 3, 3, 3, 3, 3, 4, - 4, 3, 3, 3 + 0, 2, 0, 0, 3, 0, 4, 4, 4, 1, + 2, 2, 7, 6, 5, 5, 5, 4, 4, 3, + 3, 4, 6, 7, 7, 7, 6, 6, 3, 4, + 6, 8, 6, 4, 3, 5, 5, 7, 6, 12, + 7, 9, 2, 4, 4, 2, 0, 2, 2, 0, + 2, 4, 2, 2, 2, 4, 2, 1, 2, 3, + 1, 3, 3, 1, 1, 1, 4, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 4, 1, 4, 1, + 1, 1, 1, 2, 1, 5, 4, 4, 4, 4, + 1, 1, 1, 1, 4, 1, 1, 1, 4, 1, + 1, 1, 4, 4, 5, 7, 0, 2, 2, 1, + 1, 1, 1, 1, 2, 2, 2, 3, 0, 2, + 1, 3, 3, 3, 3, 3, 4, 4, 3, 3, + 3 }; -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 3, 1, 0, 0, 48, 48, 48, 48, 51, - 48, 48, 48, 48, 48, 0, 0, 48, 51, 51, - 48, 48, 48, 48, 48, 48, 51, 0, 0, 0, - 0, 0, 0, 11, 4, 0, 13, 0, 0, 0, - 51, 51, 0, 51, 0, 0, 51, 51, 0, 0, - 115, 109, 116, 0, 0, 0, 0, 0, 0, 47, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, - 82, 44, 80, 0, 99, 96, 0, 95, 0, 104, - 70, 71, 0, 67, 60, 0, 73, 66, 68, 98, - 87, 74, 72, 0, 7, 0, 5, 0, 12, 49, - 50, 0, 0, 84, 83, 85, 0, 0, 0, 52, - 109, 109, 22, 0, 0, 0, 0, 0, 0, 0, - 0, 87, 30, 118, 117, 0, 0, 0, 0, 123, - 0, 119, 0, 0, 0, 51, 36, 0, 0, 0, - 103, 0, 102, 0, 0, 0, 0, 21, 0, 0, - 0, 0, 0, 0, 0, 61, 59, 57, 56, 0, + 2, 3, 1, 0, 0, 46, 46, 46, 46, 49, + 46, 46, 46, 46, 46, 0, 0, 46, 49, 49, + 46, 46, 46, 46, 46, 46, 49, 0, 0, 0, + 0, 0, 9, 4, 0, 11, 0, 0, 0, 49, + 49, 0, 49, 0, 0, 49, 49, 0, 0, 112, + 106, 113, 0, 0, 0, 0, 0, 0, 45, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 75, 79, + 42, 77, 0, 96, 93, 0, 92, 0, 101, 67, + 68, 0, 64, 57, 0, 70, 63, 65, 95, 84, + 71, 69, 0, 5, 0, 0, 10, 47, 48, 0, + 0, 81, 80, 82, 0, 0, 0, 50, 106, 20, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 28, + 115, 114, 0, 0, 0, 0, 120, 0, 116, 0, + 0, 0, 49, 34, 0, 0, 0, 100, 0, 99, + 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, + 0, 0, 58, 56, 54, 53, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 83, 0, 0, 0, + 106, 17, 18, 72, 73, 0, 52, 0, 21, 0, + 0, 49, 0, 0, 0, 0, 106, 107, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 86, 0, 0, 0, 109, 19, 20, 75, 76, 0, - 54, 55, 0, 23, 0, 0, 51, 0, 0, 0, - 0, 109, 110, 111, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 120, 31, 0, 113, 112, - 114, 0, 0, 35, 0, 0, 0, 0, 0, 0, - 0, 77, 0, 0, 0, 0, 62, 0, 45, 0, - 0, 0, 0, 0, 46, 8, 9, 6, 10, 16, - 87, 17, 18, 54, 0, 0, 51, 0, 0, 0, - 0, 0, 51, 0, 0, 133, 132, 131, 0, 0, - 124, 125, 126, 127, 128, 0, 106, 0, 37, 0, - 104, 38, 51, 0, 0, 81, 79, 97, 105, 58, - 69, 89, 93, 94, 90, 91, 92, 15, 53, 24, - 0, 64, 65, 0, 29, 51, 28, 0, 107, 129, - 130, 32, 34, 0, 0, 40, 0, 0, 14, 26, - 25, 27, 0, 0, 0, 39, 0, 42, 0, 108, - 33, 0, 0, 0, 0, 100, 0, 0, 43, 0, - 0, 0, 0, 121, 88, 101, 0, 41, 122 + 117, 29, 0, 110, 109, 111, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, + 0, 59, 0, 43, 0, 0, 0, 0, 0, 44, + 6, 7, 8, 14, 84, 15, 16, 52, 0, 0, + 49, 0, 0, 0, 0, 0, 49, 0, 0, 130, + 129, 128, 0, 0, 121, 122, 123, 124, 125, 0, + 103, 0, 35, 0, 101, 36, 49, 0, 0, 78, + 76, 94, 102, 55, 66, 86, 90, 91, 87, 88, + 89, 13, 51, 22, 0, 61, 62, 0, 27, 49, + 26, 0, 104, 126, 127, 30, 32, 0, 0, 38, + 0, 0, 12, 24, 23, 25, 0, 0, 0, 37, + 0, 40, 0, 105, 31, 0, 0, 0, 0, 97, + 0, 0, 41, 0, 0, 0, 0, 118, 85, 98, + 0, 39, 119 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 3, 34, 168, 166, 35, 37, 109, 112, - 83, 84, 185, 85, 176, 69, 70, 86, 102, 103, - 87, 317, 88, 281, 89, 121, 326, 141, 91, 72, - 128, 211, 129, 337, 130 + -1, 1, 3, 33, 163, 34, 36, 107, 109, 82, + 83, 180, 84, 172, 68, 69, 85, 100, 101, 86, + 311, 87, 275, 88, 118, 320, 138, 90, 71, 125, + 206, 126, 331, 127 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -128 +#define YYPACT_NINF -125 static const yytype_int16 yypact[] = { - -128, 4, -128, 315, -35, -128, -128, -128, -128, -10, - -128, -128, -128, -128, -128, 44, 44, -128, -10, -10, - -128, -128, -128, -128, -128, -128, -10, 416, 371, 371, - -49, 9, 32, -128, -128, 38, -128, 487, 487, 344, - 69, -10, 391, 69, 487, 209, 489, 69, 317, 317, - -128, 49, -128, 317, 317, 42, 48, 106, 67, -128, - 61, 191, 25, 93, 191, 67, 67, 68, 170, -128, - -128, -128, 72, 84, -128, -128, 86, -128, 109, -128, - -128, -128, 233, -128, -128, 80, -128, -128, 115, -128, - 426, -128, 84, 120, -128, 317, -128, 317, -128, -128, - -128, 317, 137, -128, -128, -128, 148, 155, 397, -128, - 74, 74, -128, 164, 371, 204, 240, 207, 206, 68, - 223, -128, -128, -128, -128, 270, 317, 317, 227, -128, - 183, -128, 90, 160, 317, -10, -128, 234, 237, 16, - -128, 254, -128, 255, 256, 257, 240, -128, 212, 168, - 548, 317, 317, 428, 258, -128, -128, -128, 84, 371, - 240, 318, 316, 335, 348, 371, 315, 502, 315, 512, - -128, 240, 240, 371, 49, -128, -128, -128, -128, 289, - -128, -128, 330, -128, 240, 291, 11, 307, 168, 312, - 68, 74, -128, -128, 160, 317, 317, 317, 377, 379, - 317, 317, 317, 317, 317, -128, -128, 324, -128, -128, - -128, 325, 337, -128, 77, 317, 338, 126, 77, 240, - 240, -128, 339, 342, 249, 347, -128, 416, -128, 352, - 170, 170, 170, 170, -128, -128, -128, -128, -128, -128, - 362, -128, -128, 227, -2, 359, -10, 366, 240, 240, - 240, 240, 375, 336, 384, 562, 590, 597, 317, 317, - 213, 213, -128, -128, -128, 385, -128, 61, -128, 357, - 395, -128, -10, 396, 398, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -128, -128, -128, 240, -128, -128, - 434, -128, -128, 400, -128, 432, -128, 424, -128, 436, - 436, 459, -128, 240, 77, -128, 402, 240, -128, -128, - -128, -128, 404, 317, 411, -128, 240, -128, 415, -128, - -128, 216, 418, 240, 413, -128, 421, 240, -128, 317, - 216, 419, 302, 425, -128, -128, 317, -128, 573 + -125, 7, -125, 308, -41, -125, -125, -125, -125, -19, + -125, -125, -125, -125, -125, 80, 80, -125, -19, -19, + -125, -125, -125, -125, -125, -125, -19, 405, 364, 364, + -31, -15, -125, -125, -2, -125, 528, 528, 337, -18, + -19, 409, -18, 528, 230, 187, -18, 448, 448, -125, + 257, -125, 448, 448, -6, 15, 94, 309, -125, 49, + 19, 44, 95, 19, 309, 309, 63, 391, -125, -125, + -125, 90, 137, -125, -125, 145, -125, 146, -125, -125, + -125, 66, -125, -125, 52, -125, -125, 150, -125, 147, + -125, 137, 57, -125, 448, 448, -125, -125, -125, 448, + 167, -125, -125, -125, 184, 200, 431, -125, 47, -125, + 201, 364, 217, 189, 223, 221, 63, 228, -125, -125, + -125, -125, 289, 448, 448, 231, -125, 181, -125, 411, + 54, 448, -19, -125, 237, 238, 12, -125, 240, -125, + 241, 244, 246, 189, -125, 245, 114, 319, 448, 448, + 417, 243, -125, -125, -125, 137, 364, 189, 293, 312, + 313, 341, 364, 308, 542, 552, -125, 189, 189, 364, + 257, -125, -125, -125, -125, 282, -125, 315, -125, 189, + 287, 42, 296, 114, 303, 63, 47, -125, -125, 54, + 448, 448, 448, 363, 369, 448, 448, 448, 448, 448, + -125, -125, 306, -125, -125, -125, 311, 316, -125, 53, + 448, 321, 65, 53, 189, 189, -125, 318, 324, 250, + 325, -125, 405, -125, 326, 391, 391, 391, 391, -125, + -125, -125, -125, -125, 317, -125, -125, 231, 130, 328, + -19, 323, 189, 189, 189, 189, 334, 336, 340, 602, + 621, 628, 448, 448, 197, 197, -125, -125, -125, 352, + -125, 49, -125, 516, 359, -125, -19, 366, 371, -125, + -125, -125, -125, -125, -125, -125, -125, -125, -125, -125, + -125, 189, -125, -125, 474, -125, -125, 361, -125, 165, + -125, 399, -125, 235, 235, 432, -125, 189, 53, -125, + 376, 189, -125, -125, -125, -125, 377, 448, 380, -125, + 189, -125, 383, -125, -125, 112, 385, 189, 386, -125, + 388, 189, -125, 448, 112, 382, 267, 395, -125, -125, + 448, -125, 613 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -128, -128, -128, -77, -128, -128, -128, 538, 50, 382, - -57, 429, 33, -7, -128, -48, -43, -21, 36, -127, - -23, -128, 29, 17, -101, -28, 161, -128, -37, -8, - -65, 299, 2, -128, -32 + -125, -125, -125, 292, -125, -125, 578, 45, 354, -56, + 400, -48, -25, -125, -7, -42, -21, -5, -124, 5, + -125, -10, 89, -118, -28, 140, -125, -46, 4, -90, + 277, -4, -125, -16 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -64 + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -61 static const yytype_int16 yytable[] = { - 90, 90, 117, 136, 2, 206, 71, 55, 57, 90, - 90, 90, 94, 95, 104, 104, 90, 56, 56, 147, - 248, 104, 93, 120, 137, 216, 142, 143, 36, 73, - 92, 92, 107, 48, 49, 135, 208, 209, 210, 245, - 148, 92, 144, 145, 113, 180, 181, 118, 222, 223, - 123, 124, 48, 49, 41, 125, 131, 126, 127, 42, - 177, 157, 50, 167, 138, 169, 105, 105, 59, 60, - 96, 189, 155, 105, 106, 41, 67, -63, 99, 100, - 115, 50, 126, 127, 158, 52, 90, 223, 186, 235, - 108, 237, 53, 114, 97, 54, 119, 122, 48, 49, - 178, 98, 51, 170, 52, 74, 132, 183, 75, 243, - 179, 53, 76, 77, 54, 133, 92, 134, 148, 224, - 99, 100, 99, 100, 78, 79, 253, 50, 192, 193, - 82, 90, 229, 41, 207, 146, 212, 90, 301, 149, - 78, 79, 252, 240, 159, 90, 99, 100, 239, 241, - 52, 150, 228, 151, 225, 124, 246, 53, 234, 101, - 54, 92, 139, 255, 256, 257, 242, 92, 260, 261, - 262, 263, 264, 78, 270, 92, 152, 268, 48, 49, - 271, 272, 160, 269, 165, 213, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 273, 274, 208, 209, - 210, 171, 282, 282, 282, 282, 279, 50, 74, 75, - 302, 75, 172, 76, 77, 76, 77, 48, 49, 173, - 291, 186, 186, 202, 203, 204, 299, 300, 294, 73, - 52, 182, 283, 283, 283, 283, 249, 53, 78, 79, - 54, 48, 153, 154, 99, 100, 50, 309, 284, 285, - 286, 205, 195, 196, 197, 198, 199, 200, 201, 202, - 203, 204, 99, 100, 308, 324, 325, 315, 184, 52, - 50, 187, 311, 188, 116, 314, 68, 191, 74, 54, - 221, 75, 292, 293, 318, 76, 77, 190, 322, 155, - 156, 51, 118, 52, 194, 328, 289, 332, 214, 331, - 68, 215, 296, 54, 338, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 320, 4, 277, 217, 218, - 219, 220, 305, 231, 230, 48, 49, 227, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 232, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 48, 49, 50, 233, 244, 247, 28, 29, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 335, 245, 250, 30, 31, 32, 251, 52, 33, 48, - 49, 50, 74, 258, 53, 75, 259, 54, 265, 76, - 77, 78, 79, 266, 226, 80, 81, 99, 100, 48, - 49, 267, 51, 297, 52, 48, 49, 275, 50, 74, - 276, 68, 75, 82, 54, 278, 76, 77, 78, 79, - 280, 303, 80, 81, 48, 49, 287, 288, 50, 51, - 290, 52, 161, 162, 50, 163, 48, 49, 68, 295, - 82, 54, 48, 49, 200, 201, 202, 203, 204, 110, - 111, 52, 298, 50, 101, 174, 111, 52, 53, 304, - 306, 54, 307, 312, 68, 50, 310, 54, 313, 316, - 74, 50, 319, 75, 51, 321, 52, 76, 77, 323, - 329, 164, 327, 68, 226, 330, 54, 334, 52, 336, - 175, 333, 140, 254, 52, 53, 41, 0, 54, 0, - 0, 68, 0, 0, 54, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 74, 0, 74, 75, 0, - 75, 0, 76, 77, 76, 77, 0, 0, 0, 0, - 99, 100, 99, 100, 38, 39, 40, 0, 43, 44, - 45, 46, 47, 41, 0, 58, 101, 0, 61, 62, - 63, 64, 65, 66, 0, 236, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 238, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 208, 209, 210, 75, - 0, 0, 0, 76, 77, 197, 198, 199, 200, 201, - 202, 203, 204, 198, 199, 200, 201, 202, 203, 204 + 89, 89, 114, 133, 92, 201, 70, 2, 89, 89, + 89, 55, 55, 105, 134, 89, 139, 140, 176, 54, + 56, 211, 35, 72, 91, 91, 103, 103, 217, 218, + 93, 94, 104, 103, 91, 97, 98, 110, 112, 145, + 115, 102, 102, 120, 121, 40, 40, 95, 102, 128, + 117, 242, 47, 48, 41, 123, 124, 135, 129, 144, + 154, 96, 132, 58, 59, 218, 77, 78, 152, 141, + 142, 66, 97, 98, 47, 150, 151, 155, 164, 165, + 237, 49, 130, 89, 106, 181, 178, 111, 47, 48, + 116, 119, 203, 204, 205, 166, 247, 97, 98, 173, + 77, 78, 175, 49, 51, 131, 40, 91, -60, 184, + 174, 52, 77, 264, 53, 145, 156, 49, 81, 187, + 188, 162, 152, 153, 50, 202, 51, 207, 89, 224, + 143, 223, 219, 67, 89, 295, 53, 229, 50, 234, + 51, 89, 77, 78, 236, 220, 121, 52, 97, 98, + 53, 240, 91, 158, 159, 74, 160, 146, 91, 75, + 76, 318, 319, 262, 136, 91, 265, 266, 203, 204, + 205, 239, 233, 235, 249, 250, 251, 208, 246, 254, + 255, 256, 257, 258, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 263, 286, 287, 276, 276, 276, + 276, 273, 161, 73, 147, 296, 74, 197, 198, 199, + 75, 76, 148, 149, 285, 181, 181, 157, 72, 267, + 268, 277, 277, 277, 277, 73, 243, 73, 74, 40, + 74, 167, 75, 76, 75, 76, 293, 294, 47, 48, + 97, 98, 303, 195, 196, 197, 198, 199, 168, 200, + 288, 40, 309, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 122, 169, 123, 124, 49, 177, 308, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 115, 179, 316, 97, 98, 283, 302, 182, 183, 322, + 51, 290, 185, 325, 305, 113, 186, 67, 189, 225, + 53, 209, 210, 314, 212, 213, 312, 326, 214, 4, + 215, 299, 222, 216, 332, 278, 279, 280, 271, 226, + 227, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 329, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 47, 48, 73, 228, 238, + 74, 28, 29, 241, 75, 76, 239, 203, 204, 205, + 74, 244, 97, 98, 75, 76, 30, 245, 31, 252, + 259, 32, 47, 48, 49, 73, 253, 221, 74, 260, + 261, 281, 75, 76, 77, 78, 269, 284, 79, 80, + 97, 98, 270, 272, 274, 50, 282, 51, 289, 47, + 48, 49, 73, 291, 67, 74, 81, 53, 292, 75, + 76, 77, 78, 47, 48, 79, 80, 47, 48, 47, + 48, 99, 50, 298, 51, 47, 48, 304, 49, 73, + 300, 67, 74, 81, 53, 301, 75, 76, 306, 47, + 48, 307, 49, 310, 315, 313, 49, 317, 49, 321, + 328, 51, 324, 323, 49, 230, 47, 48, 52, 330, + 171, 53, 137, 50, 327, 51, 248, 108, 49, 51, + 0, 51, 67, 221, 0, 53, 52, 51, 52, 53, + 99, 53, 47, 48, 52, 49, 0, 53, 0, 170, + 0, 51, 0, 0, 0, 0, 0, 0, 67, 0, + 0, 53, 0, 0, 0, 0, 0, 0, 51, 0, + 0, 49, 0, 0, 0, 52, 0, 0, 53, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 0, + 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, + 0, 67, 0, 0, 53, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 0, 73, 0, 0, 74, + 0, 0, 0, 75, 76, 0, 0, 0, 0, 0, + 297, 97, 98, 0, 37, 38, 39, 0, 42, 43, + 44, 45, 46, 0, 0, 57, 0, 99, 60, 61, + 62, 63, 64, 65, 0, 231, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 232, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 192, 193, 194, 195, + 196, 197, 198, 199, 193, 194, 195, 196, 197, 198, + 199 }; -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-128))) - -#define yytable_value_is_error(Yytable_value) \ - YYID (0) - static const yytype_int16 yycheck[] = { - 28, 29, 45, 60, 0, 132, 27, 15, 16, 37, - 38, 39, 61, 62, 37, 38, 44, 15, 16, 67, - 9, 44, 29, 46, 61, 9, 63, 64, 63, 27, - 28, 29, 39, 8, 9, 58, 38, 39, 40, 41, - 68, 39, 65, 66, 42, 110, 111, 45, 149, 150, - 48, 49, 8, 9, 64, 6, 54, 8, 9, 9, - 108, 82, 37, 95, 62, 97, 37, 38, 18, 19, - 61, 119, 56, 44, 38, 64, 26, 66, 53, 54, - 44, 37, 8, 9, 82, 60, 114, 188, 116, 166, - 40, 168, 67, 43, 62, 70, 46, 47, 8, 9, - 108, 63, 58, 101, 60, 38, 64, 114, 41, 174, - 108, 67, 45, 46, 70, 67, 114, 11, 146, 151, - 53, 54, 53, 54, 47, 48, 191, 37, 126, 127, - 69, 159, 160, 64, 132, 67, 134, 165, 265, 67, - 47, 48, 190, 171, 64, 173, 53, 54, 171, 172, - 60, 67, 159, 67, 152, 153, 184, 67, 165, 69, - 70, 159, 69, 195, 196, 197, 173, 165, 200, 201, - 202, 203, 204, 47, 48, 173, 67, 214, 8, 9, - 217, 218, 67, 215, 64, 135, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 219, 220, 38, 39, - 40, 64, 230, 231, 232, 233, 227, 37, 38, 41, - 267, 41, 64, 45, 46, 45, 46, 8, 9, 64, - 248, 249, 250, 10, 11, 12, 258, 259, 251, 227, - 60, 67, 230, 231, 232, 233, 186, 67, 47, 48, - 70, 8, 9, 10, 53, 54, 37, 290, 231, 232, - 233, 68, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 53, 54, 287, 49, 50, 304, 64, 60, - 37, 64, 295, 67, 65, 303, 67, 7, 38, 70, - 68, 41, 249, 250, 307, 45, 46, 64, 316, 56, - 57, 58, 290, 60, 67, 323, 246, 329, 64, 327, - 67, 64, 252, 70, 336, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 313, 1, 68, 64, 64, - 64, 64, 272, 7, 6, 8, 9, 69, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 7, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 8, 9, 37, 7, 67, 66, 43, 44, + 28, 29, 44, 59, 29, 129, 27, 0, 36, 37, + 38, 15, 16, 38, 60, 43, 62, 63, 108, 15, + 16, 9, 63, 27, 28, 29, 36, 37, 146, 147, + 61, 62, 37, 43, 38, 53, 54, 41, 43, 67, + 44, 36, 37, 47, 48, 64, 64, 62, 43, 53, + 45, 9, 8, 9, 9, 8, 9, 61, 64, 66, + 81, 63, 57, 18, 19, 183, 47, 48, 56, 64, + 65, 26, 53, 54, 8, 9, 10, 81, 94, 95, + 170, 37, 67, 111, 39, 113, 111, 42, 8, 9, + 45, 46, 38, 39, 40, 99, 186, 53, 54, 106, + 47, 48, 106, 37, 60, 11, 64, 111, 66, 116, + 106, 67, 47, 48, 70, 143, 64, 37, 69, 123, + 124, 64, 56, 57, 58, 129, 60, 131, 156, 157, + 67, 156, 148, 67, 162, 259, 70, 162, 58, 167, + 60, 169, 47, 48, 169, 149, 150, 67, 53, 54, + 70, 179, 156, 6, 7, 41, 9, 67, 162, 45, + 46, 49, 50, 209, 69, 169, 212, 213, 38, 39, + 40, 41, 167, 168, 190, 191, 192, 132, 185, 195, + 196, 197, 198, 199, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 210, 243, 244, 225, 226, 227, + 228, 222, 55, 38, 67, 261, 41, 10, 11, 12, + 45, 46, 67, 67, 242, 243, 244, 67, 222, 214, + 215, 225, 226, 227, 228, 38, 181, 38, 41, 64, + 41, 64, 45, 46, 45, 46, 252, 253, 8, 9, + 53, 54, 284, 8, 9, 10, 11, 12, 64, 68, + 245, 64, 298, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 6, 64, 8, 9, 37, 67, 297, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 68, 41, 65, 58, 59, 60, 64, 60, 63, 8, - 9, 37, 38, 6, 67, 41, 7, 70, 64, 45, - 46, 47, 48, 68, 56, 51, 52, 53, 54, 8, - 9, 64, 58, 67, 60, 8, 9, 68, 37, 38, - 68, 67, 41, 69, 70, 68, 45, 46, 47, 48, - 68, 64, 51, 52, 8, 9, 64, 68, 37, 58, - 64, 60, 6, 7, 37, 9, 8, 9, 67, 64, - 69, 70, 8, 9, 8, 9, 10, 11, 12, 58, - 59, 60, 68, 37, 69, 58, 59, 60, 67, 64, - 64, 70, 64, 39, 67, 37, 66, 70, 9, 67, - 38, 37, 68, 41, 58, 64, 60, 45, 46, 64, - 67, 55, 64, 67, 56, 64, 70, 68, 60, 64, - 108, 330, 63, 194, 60, 67, 64, -1, 70, -1, + 284, 64, 310, 53, 54, 240, 281, 64, 67, 317, + 60, 246, 64, 321, 289, 65, 7, 67, 67, 6, + 70, 64, 64, 307, 64, 64, 301, 323, 64, 1, + 64, 266, 69, 68, 330, 226, 227, 228, 68, 7, + 7, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 68, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 8, 9, 38, 7, 67, + 41, 43, 44, 66, 45, 46, 41, 38, 39, 40, + 41, 65, 53, 54, 45, 46, 58, 64, 60, 6, + 64, 63, 8, 9, 37, 38, 7, 56, 41, 68, + 64, 64, 45, 46, 47, 48, 68, 64, 51, 52, + 53, 54, 68, 68, 68, 58, 68, 60, 64, 8, + 9, 37, 38, 67, 67, 41, 69, 70, 68, 45, + 46, 47, 48, 8, 9, 51, 52, 8, 9, 8, + 9, 69, 58, 64, 60, 8, 9, 66, 37, 38, + 64, 67, 41, 69, 70, 64, 45, 46, 39, 8, + 9, 9, 37, 67, 64, 68, 37, 64, 37, 64, + 68, 60, 64, 67, 37, 163, 8, 9, 67, 64, + 106, 70, 62, 58, 324, 60, 189, 58, 37, 60, + -1, 60, 67, 56, -1, 70, 67, 60, 67, 70, + 69, 70, 8, 9, 67, 37, -1, 70, -1, 58, + -1, 60, -1, -1, -1, -1, -1, -1, 67, -1, + -1, 70, -1, -1, -1, -1, -1, -1, 60, -1, + -1, 37, -1, -1, -1, 67, -1, -1, 70, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, + -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, 67, -1, -1, 70, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 38, -1, 38, 41, -1, - 41, -1, 45, 46, 45, 46, -1, -1, -1, -1, - 53, 54, 53, 54, 6, 7, 8, -1, 10, 11, - 12, 13, 14, 64, -1, 17, 69, -1, 20, 21, + 8, 9, 10, 11, 12, -1, 38, -1, -1, 41, + -1, -1, -1, 45, 46, -1, -1, -1, -1, -1, + 64, 53, 54, -1, 6, 7, 8, -1, 10, 11, + 12, 13, 14, -1, -1, 17, -1, 69, 20, 21, 22, 23, 24, 25, -1, 63, 4, 5, 6, 7, 8, 9, 10, 11, 12, 63, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 38, 39, 40, 41, - -1, -1, -1, 45, 46, 5, 6, 7, 8, 9, - 10, 11, 12, 6, 7, 8, 9, 10, 11, 12 + 7, 8, 9, 10, 11, 12, 5, 6, 7, 8, + 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, + 12 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -956,37 +913,37 @@ static const yytype_uint8 yystos[] = 0, 72, 0, 73, 1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 43, 44, - 58, 59, 60, 63, 74, 77, 63, 78, 78, 78, - 78, 64, 79, 78, 78, 78, 78, 78, 8, 9, - 37, 58, 60, 67, 70, 100, 103, 100, 78, 79, - 79, 78, 78, 78, 78, 78, 78, 79, 67, 86, - 87, 88, 100, 103, 38, 41, 45, 46, 47, 48, - 51, 52, 69, 81, 82, 84, 88, 91, 93, 95, - 96, 99, 103, 84, 61, 62, 61, 62, 63, 53, - 54, 69, 89, 90, 91, 93, 89, 84, 79, 79, - 58, 59, 80, 103, 79, 89, 65, 87, 103, 79, - 91, 96, 79, 103, 103, 6, 8, 9, 101, 103, - 105, 103, 64, 67, 11, 91, 81, 99, 103, 69, - 82, 98, 99, 99, 91, 91, 67, 86, 96, 67, - 67, 67, 67, 9, 10, 56, 57, 88, 103, 64, - 67, 6, 7, 9, 55, 64, 76, 105, 75, 105, - 103, 64, 64, 64, 58, 80, 85, 86, 100, 103, - 101, 101, 67, 84, 64, 83, 96, 64, 67, 86, - 64, 7, 103, 103, 67, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 68, 90, 103, 38, 39, - 40, 102, 103, 79, 64, 64, 9, 64, 64, 64, - 64, 68, 95, 95, 105, 103, 56, 69, 84, 96, - 6, 7, 7, 7, 84, 74, 63, 74, 63, 91, - 96, 91, 84, 101, 67, 41, 96, 66, 9, 79, - 65, 64, 86, 101, 102, 105, 105, 105, 6, 7, - 105, 105, 105, 105, 105, 64, 68, 64, 99, 105, - 48, 99, 99, 91, 91, 68, 68, 68, 68, 88, - 68, 94, 96, 103, 94, 94, 94, 64, 68, 79, - 64, 96, 83, 83, 91, 64, 79, 67, 68, 105, - 105, 90, 81, 64, 64, 79, 64, 64, 91, 87, - 66, 91, 39, 9, 96, 99, 67, 92, 91, 68, - 103, 64, 96, 64, 49, 50, 97, 64, 96, 67, - 64, 96, 105, 97, 68, 68, 64, 104, 105 + 58, 60, 63, 74, 76, 63, 77, 77, 77, 77, + 64, 78, 77, 77, 77, 77, 77, 8, 9, 37, + 58, 60, 67, 70, 99, 102, 99, 77, 78, 78, + 77, 77, 77, 77, 77, 77, 78, 67, 85, 86, + 87, 99, 102, 38, 41, 45, 46, 47, 48, 51, + 52, 69, 80, 81, 83, 87, 90, 92, 94, 95, + 98, 102, 83, 61, 62, 62, 63, 53, 54, 69, + 88, 89, 90, 92, 88, 83, 78, 78, 58, 79, + 102, 78, 88, 65, 86, 102, 78, 90, 95, 78, + 102, 102, 6, 8, 9, 100, 102, 104, 102, 64, + 67, 11, 90, 80, 98, 102, 69, 81, 97, 98, + 98, 90, 90, 67, 85, 95, 67, 67, 67, 67, + 9, 10, 56, 57, 87, 102, 64, 67, 6, 7, + 9, 55, 64, 75, 104, 104, 102, 64, 64, 64, + 58, 79, 84, 85, 99, 102, 100, 67, 83, 64, + 82, 95, 64, 67, 85, 64, 7, 102, 102, 67, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 68, 89, 102, 38, 39, 40, 101, 102, 78, 64, + 64, 9, 64, 64, 64, 64, 68, 94, 94, 104, + 102, 56, 69, 83, 95, 6, 7, 7, 7, 83, + 74, 63, 63, 90, 95, 90, 83, 100, 67, 41, + 95, 66, 9, 78, 65, 64, 85, 100, 101, 104, + 104, 104, 6, 7, 104, 104, 104, 104, 104, 64, + 68, 64, 98, 104, 48, 98, 98, 90, 90, 68, + 68, 68, 68, 87, 68, 93, 95, 102, 93, 93, + 93, 64, 68, 78, 64, 95, 82, 82, 90, 64, + 78, 67, 68, 104, 104, 89, 80, 64, 64, 78, + 64, 64, 90, 86, 66, 90, 39, 9, 95, 98, + 67, 91, 90, 68, 102, 64, 95, 64, 49, 50, + 96, 64, 95, 67, 64, 95, 104, 96, 68, 68, + 64, 103, 104 }; #define yyerrok (yyerrstatus = 0) @@ -1001,50 +958,78 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ + Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) -/* Error token number */ + #define YYTERROR 1 #define YYERRCODE 256 -/* This macro is provided for backward compatibility. */ +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + #ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ + #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else @@ -1094,8 +1079,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) YYSTYPE const * const yyvaluep; #endif { - FILE *yyo = yyoutput; - YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT @@ -1104,7 +1087,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) # else YYUSE (yyoutput); # endif - YYUSE (yytype); + switch (yytype) + { + default: + break; + } } @@ -1141,20 +1128,17 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } @@ -1188,11 +1172,11 @@ yy_reduce_print (yyvsp, yyrule) /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - YYFPRINTF (stderr, " $%d = ", yyi + 1); + fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); - YYFPRINTF (stderr, "\n"); + fprintf (stderr, "\n"); } } @@ -1229,6 +1213,7 @@ int yydebug; # define YYMAXDEPTH 10000 #endif + #if YYERROR_VERBOSE @@ -1331,145 +1316,115 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULL; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - Assume YYFAIL is not used. It's too flawed to consider. See - - for details. YYERROR is fine as it does not invoke this - function. - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } + int yyn = yypact[yystate]; - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } + if (yysize_overflow) + return YYSIZE_MAXIMUM; - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } } #endif /* YYERROR_VERBOSE */ + /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1494,31 +1449,44 @@ yydestruct (yymsg, yytype, yyvaluep) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - YYUSE (yytype); -} + switch (yytype) + { + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ -/* The lookahead symbol. */ -int yychar; -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif +/* The look-ahead symbol. */ +int yychar; -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; + /*----------. | yyparse. | `----------*/ @@ -1545,37 +1513,14 @@ yyparse () #endif #endif { - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - + + int yystate; int yyn; int yyresult; - /* Lookahead token as an internal (translated) token number. */ + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; @@ -1583,22 +1528,54 @@ yyparse () YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yystacksize = YYINITDEPTH; - YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + goto yysetstate; /*------------------------------------------------------------. @@ -1625,6 +1602,7 @@ yyparse () YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; + /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might @@ -1632,6 +1610,7 @@ yyparse () yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); yyss = yyss1; @@ -1654,8 +1633,9 @@ yyparse () (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1666,6 +1646,7 @@ yyparse () yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; + YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1675,9 +1656,6 @@ yyparse () YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) - YYACCEPT; - goto yybackup; /*-----------. @@ -1686,16 +1664,16 @@ yyparse () yybackup: /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ + look-ahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to lookahead token. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) + if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -1721,27 +1699,29 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yytable_value_is_error (yyn)) - goto yyerrlab; + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; yyn = -yyn; goto yyreduce; } + if (yyn == YYFINAL) + YYACCEPT; + /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the lookahead token. */ + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token. */ - yychar = YYEMPTY; + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1778,7 +1758,6 @@ yyreduce: switch (yyn) { case 3: -/* Line 1787 of yacc.c */ #line 70 "a.y" { stmtline = lineno; @@ -1786,36 +1765,26 @@ yyreduce: break; case 5: -/* Line 1787 of yacc.c */ #line 77 "a.y" { - if((yyvsp[(1) - (2)].sym)->value != pc) - yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name); - (yyvsp[(1) - (2)].sym)->value = pc; - } - break; - - case 7: -/* Line 1787 of yacc.c */ -#line 84 "a.y" - { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); + if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc) + yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname); (yyvsp[(1) - (2)].sym)->type = LLAB; (yyvsp[(1) - (2)].sym)->value = pc; } break; - case 9: -/* Line 1787 of yacc.c */ -#line 90 "a.y" + case 7: +#line 86 "a.y" { (yyvsp[(1) - (4)].sym)->type = LVAR; (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval); } break; - case 10: -/* Line 1787 of yacc.c */ -#line 95 "a.y" + case 8: +#line 91 "a.y" { if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval)) yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name); @@ -1823,97 +1792,85 @@ yyreduce: } break; - case 14: -/* Line 1787 of yacc.c */ -#line 109 "a.y" + case 12: +#line 105 "a.y" { outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr)); } break; - case 15: -/* Line 1787 of yacc.c */ -#line 113 "a.y" + case 13: +#line 109 "a.y" { outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].lval), &nullgen); } break; - case 16: -/* Line 1787 of yacc.c */ -#line 117 "a.y" + case 14: +#line 113 "a.y" { outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr)); } break; - case 17: -/* Line 1787 of yacc.c */ -#line 124 "a.y" + case 15: +#line 120 "a.y" { outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr)); } break; - case 18: -/* Line 1787 of yacc.c */ -#line 131 "a.y" + case 16: +#line 127 "a.y" { outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr)); } break; - case 19: -/* Line 1787 of yacc.c */ -#line 138 "a.y" + case 17: +#line 134 "a.y" { outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 20: -/* Line 1787 of yacc.c */ -#line 142 "a.y" + case 18: +#line 138 "a.y" { outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 21: -/* Line 1787 of yacc.c */ -#line 149 "a.y" + case 19: +#line 145 "a.y" { outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 22: -/* Line 1787 of yacc.c */ -#line 156 "a.y" + case 20: +#line 152 "a.y" { outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 23: -/* Line 1787 of yacc.c */ -#line 163 "a.y" + case 21: +#line 159 "a.y" { outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 24: -/* Line 1787 of yacc.c */ -#line 170 "a.y" + case 22: +#line 166 "a.y" { outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].lval), &nullgen); } break; - case 25: -/* Line 1787 of yacc.c */ -#line 177 "a.y" + case 23: +#line 173 "a.y" { Addr g; @@ -1924,9 +1881,8 @@ yyreduce: } break; - case 26: -/* Line 1787 of yacc.c */ -#line 186 "a.y" + case 24: +#line 182 "a.y" { Addr g; @@ -1937,127 +1893,115 @@ yyreduce: } break; - case 27: -/* Line 1787 of yacc.c */ -#line 198 "a.y" + case 25: +#line 194 "a.y" { outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(5) - (7)].addr), (yyvsp[(3) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr)); } break; - case 28: -/* Line 1787 of yacc.c */ -#line 202 "a.y" + case 26: +#line 198 "a.y" { outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr), (yyvsp[(3) - (6)].addr).reg, &(yyvsp[(3) - (6)].addr)); } break; - case 29: -/* Line 1787 of yacc.c */ -#line 206 "a.y" + case 27: +#line 202 "a.y" { outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(4) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr)); } break; - case 30: -/* Line 1787 of yacc.c */ -#line 213 "a.y" + case 28: +#line 209 "a.y" { outcode((yyvsp[(1) - (3)].lval), (yyvsp[(2) - (3)].lval), &nullgen, NREG, &nullgen); } break; - case 31: -/* Line 1787 of yacc.c */ -#line 220 "a.y" + case 29: +#line 216 "a.y" { + settext((yyvsp[(2) - (4)].addr).sym); (yyvsp[(4) - (4)].addr).type = D_CONST2; (yyvsp[(4) - (4)].addr).offset2 = ArgsSizeUnknown; outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr)); } break; - case 32: -/* Line 1787 of yacc.c */ -#line 226 "a.y" + case 30: +#line 223 "a.y" { + settext((yyvsp[(2) - (6)].addr).sym); (yyvsp[(6) - (6)].addr).type = D_CONST2; (yyvsp[(6) - (6)].addr).offset2 = ArgsSizeUnknown; outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 33: -/* Line 1787 of yacc.c */ -#line 232 "a.y" + case 31: +#line 230 "a.y" { + settext((yyvsp[(2) - (8)].addr).sym); (yyvsp[(6) - (8)].addr).type = D_CONST2; (yyvsp[(6) - (8)].addr).offset2 = (yyvsp[(8) - (8)].lval); outcode((yyvsp[(1) - (8)].lval), Always, &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr)); } break; - case 34: -/* Line 1787 of yacc.c */ -#line 241 "a.y" + case 32: +#line 240 "a.y" { outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 35: -/* Line 1787 of yacc.c */ -#line 248 "a.y" + case 33: +#line 247 "a.y" { outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &(yyvsp[(3) - (4)].addr), NREG, &nullgen); } break; - case 36: -/* Line 1787 of yacc.c */ -#line 255 "a.y" + case 34: +#line 254 "a.y" { outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 37: -/* Line 1787 of yacc.c */ -#line 262 "a.y" + case 35: +#line 261 "a.y" { outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr)); } break; - case 38: -/* Line 1787 of yacc.c */ -#line 266 "a.y" + case 36: +#line 265 "a.y" { outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr)); } break; - case 39: -/* Line 1787 of yacc.c */ -#line 270 "a.y" + case 37: +#line 269 "a.y" { outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr)); } break; - case 40: -/* Line 1787 of yacc.c */ -#line 274 "a.y" + case 38: +#line 273 "a.y" { outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr).reg, &nullgen); } break; - case 41: -/* Line 1787 of yacc.c */ -#line 281 "a.y" + case 39: +#line 280 "a.y" { Addr g; @@ -2078,17 +2022,15 @@ yyreduce: } break; - case 42: -/* Line 1787 of yacc.c */ -#line 303 "a.y" + case 40: +#line 302 "a.y" { outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr)); } break; - case 43: -/* Line 1787 of yacc.c */ -#line 311 "a.y" + case 41: +#line 310 "a.y" { (yyvsp[(7) - (9)].addr).type = D_REGREG2; (yyvsp[(7) - (9)].addr).offset = (yyvsp[(9) - (9)].lval); @@ -2096,17 +2038,15 @@ yyreduce: } break; - case 44: -/* Line 1787 of yacc.c */ -#line 320 "a.y" + case 42: +#line 319 "a.y" { outcode((yyvsp[(1) - (2)].lval), Always, &(yyvsp[(2) - (2)].addr), NREG, &nullgen); } break; - case 45: -/* Line 1787 of yacc.c */ -#line 327 "a.y" + case 43: +#line 326 "a.y" { if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST) yyerror("arguments to PCDATA must be integer constants"); @@ -2114,9 +2054,8 @@ yyreduce: } break; - case 46: -/* Line 1787 of yacc.c */ -#line 336 "a.y" + case 44: +#line 335 "a.y" { if((yyvsp[(2) - (4)].addr).type != D_CONST) yyerror("index for FUNCDATA must be integer constant"); @@ -2126,41 +2065,36 @@ yyreduce: } break; - case 47: -/* Line 1787 of yacc.c */ -#line 347 "a.y" + case 45: +#line 346 "a.y" { outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, NREG, &nullgen); } break; - case 48: -/* Line 1787 of yacc.c */ -#line 352 "a.y" + case 46: +#line 351 "a.y" { (yyval.lval) = Always; } break; - case 49: -/* Line 1787 of yacc.c */ -#line 356 "a.y" + case 47: +#line 355 "a.y" { (yyval.lval) = ((yyvsp[(1) - (2)].lval) & ~C_SCOND) | (yyvsp[(2) - (2)].lval); } break; - case 50: -/* Line 1787 of yacc.c */ -#line 360 "a.y" + case 48: +#line 359 "a.y" { (yyval.lval) = (yyvsp[(1) - (2)].lval) | (yyvsp[(2) - (2)].lval); } break; - case 53: -/* Line 1787 of yacc.c */ -#line 369 "a.y" + case 51: +#line 368 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_BRANCH; @@ -2168,31 +2102,20 @@ yyreduce: } break; - case 54: -/* Line 1787 of yacc.c */ -#line 375 "a.y" - { - (yyval.addr) = nullgen; - if(pass == 2) - yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name); - (yyval.addr).type = D_BRANCH; - (yyval.addr).offset = (yyvsp[(2) - (2)].lval); - } - break; - - case 55: -/* Line 1787 of yacc.c */ -#line 383 "a.y" + case 52: +#line 374 "a.y" { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); (yyval.addr) = nullgen; + if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB) + yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname); (yyval.addr).type = D_BRANCH; (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval); } break; - case 56: -/* Line 1787 of yacc.c */ -#line 390 "a.y" + case 53: +#line 384 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST; @@ -2200,27 +2123,24 @@ yyreduce: } break; - case 57: -/* Line 1787 of yacc.c */ -#line 396 "a.y" + case 54: +#line 390 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); (yyval.addr).type = D_CONST; } break; - case 58: -/* Line 1787 of yacc.c */ -#line 401 "a.y" + case 55: +#line 395 "a.y" { (yyval.addr) = (yyvsp[(4) - (4)].addr); (yyval.addr).type = D_OCONST; } break; - case 59: -/* Line 1787 of yacc.c */ -#line 406 "a.y" + case 56: +#line 400 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SCONST; @@ -2228,9 +2148,8 @@ yyreduce: } break; - case 61: -/* Line 1787 of yacc.c */ -#line 415 "a.y" + case 58: +#line 409 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2238,9 +2157,8 @@ yyreduce: } break; - case 62: -/* Line 1787 of yacc.c */ -#line 421 "a.y" + case 59: +#line 415 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2248,17 +2166,15 @@ yyreduce: } break; - case 63: -/* Line 1787 of yacc.c */ -#line 429 "a.y" + case 60: +#line 423 "a.y" { (yyval.lval) = 1 << (yyvsp[(1) - (1)].lval); } break; - case 64: -/* Line 1787 of yacc.c */ -#line 433 "a.y" + case 61: +#line 427 "a.y" { int i; (yyval.lval)=0; @@ -2269,26 +2185,23 @@ yyreduce: } break; - case 65: -/* Line 1787 of yacc.c */ -#line 442 "a.y" + case 62: +#line 436 "a.y" { (yyval.lval) = (1<<(yyvsp[(1) - (3)].lval)) | (yyvsp[(3) - (3)].lval); } break; - case 69: -/* Line 1787 of yacc.c */ -#line 451 "a.y" + case 66: +#line 445 "a.y" { (yyval.addr) = (yyvsp[(1) - (4)].addr); (yyval.addr).reg = (yyvsp[(3) - (4)].lval); } break; - case 70: -/* Line 1787 of yacc.c */ -#line 456 "a.y" + case 67: +#line 450 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_PSR; @@ -2296,9 +2209,8 @@ yyreduce: } break; - case 71: -/* Line 1787 of yacc.c */ -#line 462 "a.y" + case 68: +#line 456 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FPCR; @@ -2306,9 +2218,8 @@ yyreduce: } break; - case 72: -/* Line 1787 of yacc.c */ -#line 468 "a.y" + case 69: +#line 462 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -2316,9 +2227,8 @@ yyreduce: } break; - case 76: -/* Line 1787 of yacc.c */ -#line 479 "a.y" + case 73: +#line 473 "a.y" { (yyval.addr) = (yyvsp[(1) - (1)].addr); if((yyvsp[(1) - (1)].addr).name != D_EXTERN && (yyvsp[(1) - (1)].addr).name != D_STATIC) { @@ -2326,9 +2236,8 @@ yyreduce: } break; - case 77: -/* Line 1787 of yacc.c */ -#line 487 "a.y" + case 74: +#line 481 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -2337,9 +2246,8 @@ yyreduce: } break; - case 79: -/* Line 1787 of yacc.c */ -#line 497 "a.y" + case 76: +#line 491 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -2348,9 +2256,8 @@ yyreduce: } break; - case 81: -/* Line 1787 of yacc.c */ -#line 507 "a.y" + case 78: +#line 501 "a.y" { (yyval.addr) = (yyvsp[(1) - (4)].addr); (yyval.addr).type = D_OREG; @@ -2358,9 +2265,8 @@ yyreduce: } break; - case 86: -/* Line 1787 of yacc.c */ -#line 520 "a.y" + case 83: +#line 514 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST; @@ -2368,9 +2274,8 @@ yyreduce: } break; - case 87: -/* Line 1787 of yacc.c */ -#line 528 "a.y" + case 84: +#line 522 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_REG; @@ -2378,9 +2283,8 @@ yyreduce: } break; - case 88: -/* Line 1787 of yacc.c */ -#line 536 "a.y" + case 85: +#line 530 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_REGREG; @@ -2389,9 +2293,8 @@ yyreduce: } break; - case 89: -/* Line 1787 of yacc.c */ -#line 545 "a.y" + case 86: +#line 539 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SHIFT; @@ -2399,9 +2302,8 @@ yyreduce: } break; - case 90: -/* Line 1787 of yacc.c */ -#line 551 "a.y" + case 87: +#line 545 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SHIFT; @@ -2409,9 +2311,8 @@ yyreduce: } break; - case 91: -/* Line 1787 of yacc.c */ -#line 557 "a.y" + case 88: +#line 551 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SHIFT; @@ -2419,9 +2320,8 @@ yyreduce: } break; - case 92: -/* Line 1787 of yacc.c */ -#line 563 "a.y" + case 89: +#line 557 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SHIFT; @@ -2429,9 +2329,8 @@ yyreduce: } break; - case 93: -/* Line 1787 of yacc.c */ -#line 571 "a.y" + case 90: +#line 565 "a.y" { if((yyval.lval) < 0 || (yyval.lval) >= 16) print("register value out of range\n"); @@ -2439,9 +2338,8 @@ yyreduce: } break; - case 94: -/* Line 1787 of yacc.c */ -#line 577 "a.y" + case 91: +#line 571 "a.y" { if((yyval.lval) < 0 || (yyval.lval) >= 32) print("shift value out of range\n"); @@ -2449,17 +2347,15 @@ yyreduce: } break; - case 96: -/* Line 1787 of yacc.c */ -#line 586 "a.y" + case 93: +#line 580 "a.y" { (yyval.lval) = REGPC; } break; - case 97: -/* Line 1787 of yacc.c */ -#line 590 "a.y" + case 94: +#line 584 "a.y" { if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG) print("register value out of range\n"); @@ -2467,17 +2363,15 @@ yyreduce: } break; - case 99: -/* Line 1787 of yacc.c */ -#line 599 "a.y" + case 96: +#line 593 "a.y" { (yyval.lval) = REGSP; } break; - case 101: -/* Line 1787 of yacc.c */ -#line 606 "a.y" + case 98: +#line 600 "a.y" { if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG) print("register value out of range\n"); @@ -2485,9 +2379,8 @@ yyreduce: } break; - case 104: -/* Line 1787 of yacc.c */ -#line 618 "a.y" + case 101: +#line 612 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FREG; @@ -2495,9 +2388,8 @@ yyreduce: } break; - case 105: -/* Line 1787 of yacc.c */ -#line 624 "a.y" + case 102: +#line 618 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FREG; @@ -2505,9 +2397,8 @@ yyreduce: } break; - case 106: -/* Line 1787 of yacc.c */ -#line 632 "a.y" + case 103: +#line 626 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -2517,9 +2408,8 @@ yyreduce: } break; - case 107: -/* Line 1787 of yacc.c */ -#line 640 "a.y" + case 104: +#line 634 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -2529,9 +2419,8 @@ yyreduce: } break; - case 108: -/* Line 1787 of yacc.c */ -#line 648 "a.y" + case 105: +#line 642 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -2541,182 +2430,151 @@ yyreduce: } break; - case 109: -/* Line 1787 of yacc.c */ -#line 657 "a.y" + case 106: +#line 651 "a.y" { (yyval.lval) = 0; } break; - case 110: -/* Line 1787 of yacc.c */ -#line 661 "a.y" + case 107: +#line 655 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 111: -/* Line 1787 of yacc.c */ -#line 665 "a.y" + case 108: +#line 659 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 116: -/* Line 1787 of yacc.c */ -#line 677 "a.y" + case 113: +#line 671 "a.y" { (yyval.lval) = (yyvsp[(1) - (1)].sym)->value; } break; - case 117: -/* Line 1787 of yacc.c */ -#line 681 "a.y" + case 114: +#line 675 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 118: -/* Line 1787 of yacc.c */ -#line 685 "a.y" + case 115: +#line 679 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 119: -/* Line 1787 of yacc.c */ -#line 689 "a.y" + case 116: +#line 683 "a.y" { (yyval.lval) = ~(yyvsp[(2) - (2)].lval); } break; - case 120: -/* Line 1787 of yacc.c */ -#line 693 "a.y" + case 117: +#line 687 "a.y" { (yyval.lval) = (yyvsp[(2) - (3)].lval); } break; - case 121: -/* Line 1787 of yacc.c */ -#line 698 "a.y" + case 118: +#line 692 "a.y" { (yyval.lval) = 0; } break; - case 122: -/* Line 1787 of yacc.c */ -#line 702 "a.y" + case 119: +#line 696 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 124: -/* Line 1787 of yacc.c */ -#line 709 "a.y" + case 121: +#line 703 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval); } break; - case 125: -/* Line 1787 of yacc.c */ -#line 713 "a.y" + case 122: +#line 707 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval); } break; - case 126: -/* Line 1787 of yacc.c */ -#line 717 "a.y" + case 123: +#line 711 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval); } break; - case 127: -/* Line 1787 of yacc.c */ -#line 721 "a.y" + case 124: +#line 715 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval); } break; - case 128: -/* Line 1787 of yacc.c */ -#line 725 "a.y" + case 125: +#line 719 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval); } break; - case 129: -/* Line 1787 of yacc.c */ -#line 729 "a.y" + case 126: +#line 723 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval); } break; - case 130: -/* Line 1787 of yacc.c */ -#line 733 "a.y" + case 127: +#line 727 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval); } break; - case 131: -/* Line 1787 of yacc.c */ -#line 737 "a.y" + case 128: +#line 731 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval); } break; - case 132: -/* Line 1787 of yacc.c */ -#line 741 "a.y" + case 129: +#line 735 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval); } break; - case 133: -/* Line 1787 of yacc.c */ -#line 745 "a.y" + case 130: +#line 739 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval); } break; -/* Line 1787 of yacc.c */ -#line 2707 "y.tab.c" +/* Line 1267 of yacc.c. */ +#line 2576 "y.tab.c" default: break; } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -2725,6 +2583,7 @@ yyreduce: *++yyvsp = yyval; + /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -2744,10 +2603,6 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -2755,36 +2610,37 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } } -# undef YYSYNTAX_ERROR #endif } @@ -2792,7 +2648,7 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an + /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) @@ -2809,7 +2665,7 @@ yyerrlab: } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; @@ -2843,7 +2699,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) + if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -2866,9 +2722,10 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + if (yyn == YYFINAL) + YYACCEPT; + *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -2892,7 +2749,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined yyoverflow || YYERROR_VERBOSE +#ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -2903,14 +2760,9 @@ yyexhaustedlab: #endif yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2934,3 +2786,4 @@ yyreturn: } + diff --git a/src/cmd/5a/y.tab.h b/src/cmd/5a/y.tab.h index f11fb85c6..f75cb22a7 100644 --- a/src/cmd/5a/y.tab.h +++ b/src/cmd/5a/y.tab.h @@ -1,21 +1,24 @@ -/* A Bison parser, made by GNU Bison 2.7.12-4996. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - + the Free Software Foundation; either version 2, or (at your option) + any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -26,20 +29,10 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -#ifndef YY_YY_Y_TAB_H_INCLUDED -# define YY_YY_Y_TAB_H_INCLUDED -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE @@ -148,41 +141,24 @@ extern int yydebug; + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -{ -/* Line 2053 of yacc.c */ #line 39 "a.y" - +{ Sym *sym; int32 lval; double dval; char sval[8]; Addr addr; - - -/* Line 2053 of yacc.c */ -#line 166 "y.tab.h" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 +} +/* Line 1529 of yacc.c. */ +#line 157 "y.tab.h" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - -#endif /* !YY_YY_Y_TAB_H_INCLUDED */ diff --git a/src/cmd/6a/a.h b/src/cmd/6a/a.h index b3fb0bb19..e1927b6d4 100644 --- a/src/cmd/6a/a.h +++ b/src/cmd/6a/a.h @@ -70,6 +70,7 @@ struct Sym vlong value; ushort type; char *name; + char* labelname; char sym; }; #define S ((Sym*)0) @@ -148,6 +149,8 @@ void newio(void); void newfile(char*, int); Sym* slookup(char*); Sym* lookup(void); +Sym* labellookup(Sym*); +void settext(LSym*); void syminit(Sym*); int32 yylex(void); int getc(void); diff --git a/src/cmd/6a/a.y b/src/cmd/6a/a.y index 1089d4061..29011c7ff 100644 --- a/src/cmd/6a/a.y +++ b/src/cmd/6a/a.y @@ -71,15 +71,11 @@ prog: line line: - LLAB ':' - { - if($1->value != pc) - yyerror("redeclaration of %s", $1->name); - $1->value = pc; - } - line -| LNAME ':' + LNAME ':' { + $1 = labellookup($1); + if($1->type == LLAB && $1->value != pc) + yyerror("redeclaration of %s (%s)", $1->labelname, $1->name); $1->type = LLAB; $1->value = pc; } @@ -197,11 +193,13 @@ spec1: /* DATA */ spec2: /* TEXT */ mem ',' imm2 { + settext($1.sym); $$.from = $1; $$.to = $3; } | mem ',' con ',' imm2 { + settext($1.sym); $$.from = $1; $$.from.scale = $3; $$.to = $5; @@ -363,15 +361,10 @@ rel: } | LNAME offset { + $1 = labellookup($1); $$ = nullgen; - if(pass == 2) - yyerror("undefined label: %s", $1->name); - $$.type = D_BRANCH; - $$.offset = $2; - } -| LLAB offset - { - $$ = nullgen; + if(pass == 2 && $1->type != LLAB) + yyerror("undefined label: %s", $1->labelname); $$.type = D_BRANCH; $$.offset = $1->value + $2; } diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c index b69fd95b5..a698079d2 100644 --- a/src/cmd/6a/y.tab.c +++ b/src/cmd/6a/y.tab.c @@ -411,16 +411,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 560 +#define YYLAST 549 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 56 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 42 +#define YYNNTS 41 /* YYNRULES -- Number of rules. */ -#define YYNRULES 137 +#define YYNRULES 134 /* YYNRULES -- Number of states. */ -#define YYNSTATES 277 +#define YYNSTATES 271 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -469,91 +469,91 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint16 yyprhs[] = { - 0, 0, 3, 4, 5, 9, 10, 15, 16, 21, - 23, 26, 29, 33, 37, 40, 43, 46, 49, 52, + 0, 0, 3, 4, 5, 9, 10, 15, 17, 20, + 23, 27, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, - 85, 88, 91, 94, 95, 97, 101, 105, 108, 110, - 113, 115, 118, 120, 124, 130, 134, 140, 143, 145, - 147, 149, 153, 159, 163, 169, 172, 174, 178, 184, - 190, 191, 193, 197, 203, 207, 211, 213, 215, 217, - 219, 222, 225, 227, 229, 231, 233, 238, 241, 244, - 246, 248, 250, 252, 254, 256, 258, 261, 264, 267, - 270, 273, 278, 284, 288, 290, 292, 294, 299, 304, - 309, 316, 326, 336, 340, 344, 350, 359, 361, 368, - 374, 382, 383, 386, 389, 391, 393, 395, 397, 399, - 402, 405, 408, 412, 414, 417, 421, 426, 428, 432, - 436, 440, 444, 448, 453, 458, 462, 466 + 85, 88, 89, 91, 95, 99, 102, 104, 107, 109, + 112, 114, 118, 124, 128, 134, 137, 139, 141, 143, + 147, 153, 157, 163, 166, 168, 172, 178, 184, 185, + 187, 191, 197, 201, 205, 207, 209, 211, 213, 216, + 219, 221, 223, 225, 227, 232, 235, 237, 239, 241, + 243, 245, 247, 249, 252, 255, 258, 261, 264, 269, + 275, 279, 281, 283, 285, 290, 295, 300, 307, 317, + 327, 331, 335, 341, 350, 352, 359, 365, 373, 374, + 377, 380, 382, 384, 386, 388, 390, 393, 396, 399, + 403, 405, 408, 412, 417, 419, 423, 427, 431, 435, + 439, 444, 449, 453, 457 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 57, 0, -1, -1, -1, 57, 58, 59, -1, -1, - 46, 48, 60, 59, -1, -1, 45, 48, 61, 59, - -1, 49, -1, 62, 49, -1, 1, 49, -1, 45, - 50, 97, -1, 47, 50, 97, -1, 13, 63, -1, - 14, 67, -1, 15, 66, -1, 16, 64, -1, 17, - 65, -1, 21, 68, -1, 19, 69, -1, 22, 70, - -1, 18, 71, -1, 20, 72, -1, 25, 73, -1, - 26, 74, -1, 27, 75, -1, 28, 76, -1, 29, - 77, -1, 30, 78, -1, 23, 79, -1, 24, 80, - -1, 31, 81, -1, -1, 51, -1, 84, 51, 82, - -1, 82, 51, 84, -1, 84, 51, -1, 84, -1, - 51, 82, -1, 82, -1, 51, 85, -1, 85, -1, - 88, 51, 85, -1, 92, 11, 95, 51, 88, -1, - 89, 51, 87, -1, 89, 51, 95, 51, 87, -1, - 51, 83, -1, 83, -1, 63, -1, 67, -1, 84, - 51, 82, -1, 84, 51, 82, 48, 37, -1, 84, - 51, 82, -1, 84, 51, 82, 48, 38, -1, 84, - 51, -1, 84, -1, 84, 51, 82, -1, 86, 51, - 82, 51, 95, -1, 88, 51, 82, 51, 86, -1, - -1, 88, -1, 89, 51, 88, -1, 89, 51, 95, - 51, 88, -1, 84, 51, 84, -1, 84, 51, 84, - -1, 86, -1, 89, -1, 85, -1, 91, -1, 10, - 86, -1, 10, 90, -1, 86, -1, 90, -1, 82, - -1, 88, -1, 95, 52, 34, 53, -1, 45, 93, - -1, 46, 93, -1, 36, -1, 39, -1, 37, -1, - 40, -1, 44, -1, 38, -1, 41, -1, 54, 96, - -1, 54, 95, -1, 54, 92, -1, 54, 43, -1, - 54, 42, -1, 54, 52, 42, 53, -1, 54, 52, - 9, 42, 53, -1, 54, 9, 42, -1, 90, -1, - 91, -1, 95, -1, 95, 52, 37, 53, -1, 95, - 52, 44, 53, -1, 95, 52, 38, 53, -1, 95, - 52, 37, 10, 95, 53, -1, 95, 52, 37, 53, - 52, 37, 10, 95, 53, -1, 95, 52, 37, 53, - 52, 38, 10, 95, 53, -1, 52, 37, 53, -1, - 52, 44, 53, -1, 52, 37, 10, 95, 53, -1, - 52, 37, 53, 52, 37, 10, 95, 53, -1, 92, - -1, 92, 52, 37, 10, 95, 53, -1, 45, 93, - 52, 94, 53, -1, 45, 6, 7, 93, 52, 35, - 53, -1, -1, 8, 95, -1, 9, 95, -1, 35, - -1, 44, -1, 33, -1, 32, -1, 47, -1, 9, - 95, -1, 8, 95, -1, 55, 95, -1, 52, 97, - 53, -1, 32, -1, 9, 32, -1, 32, 9, 32, - -1, 9, 32, 9, 32, -1, 95, -1, 97, 8, - 97, -1, 97, 9, 97, -1, 97, 10, 97, -1, - 97, 11, 97, -1, 97, 12, 97, -1, 97, 6, - 6, 97, -1, 97, 7, 7, 97, -1, 97, 5, - 97, -1, 97, 4, 97, -1, 97, 3, 97, -1 + 45, 48, 60, 59, -1, 49, -1, 61, 49, -1, + 1, 49, -1, 45, 50, 96, -1, 47, 50, 96, + -1, 13, 62, -1, 14, 66, -1, 15, 65, -1, + 16, 63, -1, 17, 64, -1, 21, 67, -1, 19, + 68, -1, 22, 69, -1, 18, 70, -1, 20, 71, + -1, 25, 72, -1, 26, 73, -1, 27, 74, -1, + 28, 75, -1, 29, 76, -1, 30, 77, -1, 23, + 78, -1, 24, 79, -1, 31, 80, -1, -1, 51, + -1, 83, 51, 81, -1, 81, 51, 83, -1, 83, + 51, -1, 83, -1, 51, 81, -1, 81, -1, 51, + 84, -1, 84, -1, 87, 51, 84, -1, 91, 11, + 94, 51, 87, -1, 88, 51, 86, -1, 88, 51, + 94, 51, 86, -1, 51, 82, -1, 82, -1, 62, + -1, 66, -1, 83, 51, 81, -1, 83, 51, 81, + 48, 37, -1, 83, 51, 81, -1, 83, 51, 81, + 48, 38, -1, 83, 51, -1, 83, -1, 83, 51, + 81, -1, 85, 51, 81, 51, 94, -1, 87, 51, + 81, 51, 85, -1, -1, 87, -1, 88, 51, 87, + -1, 88, 51, 94, 51, 87, -1, 83, 51, 83, + -1, 83, 51, 83, -1, 85, -1, 88, -1, 84, + -1, 90, -1, 10, 85, -1, 10, 89, -1, 85, + -1, 89, -1, 81, -1, 87, -1, 94, 52, 34, + 53, -1, 45, 92, -1, 36, -1, 39, -1, 37, + -1, 40, -1, 44, -1, 38, -1, 41, -1, 54, + 95, -1, 54, 94, -1, 54, 91, -1, 54, 43, + -1, 54, 42, -1, 54, 52, 42, 53, -1, 54, + 52, 9, 42, 53, -1, 54, 9, 42, -1, 89, + -1, 90, -1, 94, -1, 94, 52, 37, 53, -1, + 94, 52, 44, 53, -1, 94, 52, 38, 53, -1, + 94, 52, 37, 10, 94, 53, -1, 94, 52, 37, + 53, 52, 37, 10, 94, 53, -1, 94, 52, 37, + 53, 52, 38, 10, 94, 53, -1, 52, 37, 53, + -1, 52, 44, 53, -1, 52, 37, 10, 94, 53, + -1, 52, 37, 53, 52, 37, 10, 94, 53, -1, + 91, -1, 91, 52, 37, 10, 94, 53, -1, 45, + 92, 52, 93, 53, -1, 45, 6, 7, 92, 52, + 35, 53, -1, -1, 8, 94, -1, 9, 94, -1, + 35, -1, 44, -1, 33, -1, 32, -1, 47, -1, + 9, 94, -1, 8, 94, -1, 55, 94, -1, 52, + 96, 53, -1, 32, -1, 9, 32, -1, 32, 9, + 32, -1, 9, 32, 9, 32, -1, 94, -1, 96, + 8, 96, -1, 96, 9, 96, -1, 96, 10, 96, + -1, 96, 11, 96, -1, 96, 12, 96, -1, 96, + 6, 6, 96, -1, 96, 7, 7, 96, -1, 96, + 5, 96, -1, 96, 4, 96, -1, 96, 3, 96, + -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 66, 66, 68, 67, 75, 74, 82, 81, 87, - 88, 89, 92, 97, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 124, 128, 135, 142, 149, 154, 161, - 166, 173, 178, 183, 190, 198, 203, 211, 216, 223, - 224, 227, 232, 242, 247, 257, 262, 267, 274, 282, - 292, 296, 303, 308, 316, 325, 336, 337, 340, 341, - 342, 346, 350, 351, 354, 355, 358, 364, 372, 380, - 385, 390, 395, 400, 405, 410, 416, 424, 430, 441, - 447, 453, 459, 465, 473, 474, 477, 483, 489, 495, - 501, 510, 519, 528, 533, 538, 546, 556, 560, 569, - 576, 585, 588, 592, 598, 599, 603, 606, 607, 611, - 615, 619, 623, 629, 634, 639, 644, 651, 652, 656, - 660, 664, 668, 672, 676, 680, 684, 688 + 0, 66, 66, 68, 67, 75, 74, 83, 84, 85, + 88, 93, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 120, 124, 131, 138, 145, 150, 157, 162, 169, + 174, 179, 186, 194, 200, 209, 214, 221, 222, 225, + 230, 240, 245, 255, 260, 265, 272, 280, 290, 294, + 301, 306, 314, 323, 334, 335, 338, 339, 340, 344, + 348, 349, 352, 353, 356, 362, 373, 378, 383, 388, + 393, 398, 403, 409, 417, 423, 434, 440, 446, 452, + 458, 466, 467, 470, 476, 482, 488, 494, 503, 512, + 521, 526, 531, 539, 549, 553, 562, 569, 578, 581, + 585, 591, 592, 596, 599, 600, 604, 608, 612, 616, + 622, 627, 632, 637, 644, 645, 649, 653, 657, 661, + 665, 669, 673, 677, 681 }; #endif @@ -569,7 +569,7 @@ static const char *const yytname[] = "LTYPEF", "LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG", "LMREG", "LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'", "'~'", - "$accept", "prog", "@1", "line", "@2", "@3", "inst", "nonnon", "rimrem", + "$accept", "prog", "@1", "line", "@2", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "spec10", "spec11", "spec12", "spec13", "rem", "rom", "rim", "rel", "reg", "imm2", "imm", @@ -594,39 +594,39 @@ static const yytype_uint16 yytoknum[] = /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 56, 57, 58, 57, 60, 59, 61, 59, 59, - 59, 59, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 63, 63, 64, 65, 66, 66, 67, - 67, 68, 68, 68, 69, 70, 70, 71, 71, 72, - 72, 73, 73, 74, 74, 75, 75, 75, 76, 77, - 78, 78, 79, 79, 80, 81, 82, 82, 83, 83, - 83, 83, 83, 83, 84, 84, 85, 85, 85, 86, - 86, 86, 86, 86, 86, 86, 87, 88, 88, 88, - 88, 88, 88, 88, 89, 89, 90, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 90, 91, 91, 92, - 92, 93, 93, 93, 94, 94, 94, 95, 95, 95, - 95, 95, 95, 96, 96, 96, 96, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97 + 0, 56, 57, 58, 57, 60, 59, 59, 59, 59, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 62, 62, 63, 64, 65, 65, 66, 66, 67, + 67, 67, 68, 69, 69, 70, 70, 71, 71, 72, + 72, 73, 73, 74, 74, 74, 75, 76, 77, 77, + 78, 78, 79, 80, 81, 81, 82, 82, 82, 82, + 82, 82, 83, 83, 84, 84, 85, 85, 85, 85, + 85, 85, 85, 86, 87, 87, 87, 87, 87, 87, + 87, 88, 88, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 90, 90, 91, 91, 92, 92, + 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, + 95, 95, 95, 95, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 0, 0, 3, 0, 4, 0, 4, 1, - 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, + 0, 2, 0, 0, 3, 0, 4, 1, 2, 2, + 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 0, 1, 3, 3, 2, 1, 2, - 1, 2, 1, 3, 5, 3, 5, 2, 1, 1, - 1, 3, 5, 3, 5, 2, 1, 3, 5, 5, - 0, 1, 3, 5, 3, 3, 1, 1, 1, 1, - 2, 2, 1, 1, 1, 1, 4, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, - 2, 4, 5, 3, 1, 1, 1, 4, 4, 4, - 6, 9, 9, 3, 3, 5, 8, 1, 6, 5, - 7, 0, 2, 2, 1, 1, 1, 1, 1, 2, - 2, 2, 3, 1, 2, 3, 4, 1, 3, 3, - 3, 3, 3, 4, 4, 3, 3, 3 + 2, 0, 1, 3, 3, 2, 1, 2, 1, 2, + 1, 3, 5, 3, 5, 2, 1, 1, 1, 3, + 5, 3, 5, 2, 1, 3, 5, 5, 0, 1, + 3, 5, 3, 3, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 1, 4, 2, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 4, 5, + 3, 1, 1, 1, 4, 4, 4, 6, 9, 9, + 3, 3, 5, 8, 1, 6, 5, 7, 0, 2, + 2, 1, 1, 1, 1, 1, 2, 2, 2, 3, + 1, 2, 3, 4, 1, 3, 3, 3, 3, 3, + 4, 4, 3, 3, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -634,89 +634,89 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 3, 1, 0, 0, 33, 0, 0, 0, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 60, 0, 0, 0, 0, 9, 4, 0, - 11, 34, 14, 0, 0, 117, 79, 81, 84, 80, - 82, 85, 83, 111, 118, 0, 0, 0, 15, 40, - 66, 67, 94, 95, 107, 96, 0, 16, 74, 38, - 75, 17, 0, 18, 0, 0, 111, 111, 0, 22, - 48, 68, 72, 73, 69, 96, 20, 0, 34, 49, - 50, 23, 111, 0, 0, 19, 42, 0, 0, 21, - 0, 30, 0, 31, 0, 24, 0, 25, 0, 26, - 56, 27, 0, 28, 0, 29, 61, 32, 0, 7, - 0, 5, 0, 10, 120, 119, 0, 0, 0, 0, - 39, 0, 0, 127, 0, 121, 0, 0, 0, 90, - 89, 0, 88, 87, 37, 0, 0, 70, 71, 77, - 78, 47, 0, 0, 77, 41, 0, 0, 0, 0, - 0, 0, 0, 55, 0, 0, 0, 0, 12, 0, - 13, 111, 112, 113, 0, 0, 103, 104, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, - 0, 0, 0, 93, 0, 0, 35, 36, 0, 0, - 43, 0, 45, 0, 62, 0, 64, 51, 53, 57, - 0, 0, 65, 8, 6, 0, 116, 114, 115, 0, - 0, 0, 137, 136, 135, 0, 0, 128, 129, 130, - 131, 132, 0, 0, 97, 99, 98, 0, 91, 76, - 0, 0, 123, 86, 0, 0, 0, 0, 0, 0, - 0, 109, 105, 0, 133, 134, 0, 0, 0, 92, - 44, 124, 0, 46, 63, 52, 54, 58, 59, 0, - 0, 108, 100, 0, 0, 0, 125, 110, 0, 0, - 0, 126, 106, 0, 0, 101, 102 + 2, 3, 1, 0, 0, 31, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 58, 0, 0, 0, 7, 4, 0, 9, + 32, 12, 0, 0, 114, 76, 78, 81, 77, 79, + 82, 80, 108, 115, 0, 0, 0, 13, 38, 64, + 65, 91, 92, 104, 93, 0, 14, 72, 36, 73, + 15, 0, 16, 0, 0, 108, 0, 20, 46, 66, + 70, 71, 67, 93, 18, 0, 32, 47, 48, 21, + 108, 0, 0, 17, 40, 0, 0, 19, 0, 28, + 0, 29, 0, 22, 0, 23, 0, 24, 54, 25, + 0, 26, 0, 27, 59, 30, 0, 5, 0, 0, + 8, 117, 116, 0, 0, 0, 0, 37, 0, 0, + 124, 0, 118, 0, 0, 0, 87, 86, 0, 85, + 84, 35, 0, 0, 68, 69, 75, 45, 0, 0, + 75, 39, 0, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 0, 0, 10, 11, 108, 109, 110, 0, + 0, 100, 101, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 119, 0, 0, 0, 0, 90, 0, + 0, 33, 34, 0, 0, 41, 0, 43, 0, 60, + 0, 62, 49, 51, 55, 0, 0, 63, 6, 0, + 113, 111, 112, 0, 0, 0, 134, 133, 132, 0, + 0, 125, 126, 127, 128, 129, 0, 0, 94, 96, + 95, 0, 88, 74, 0, 0, 120, 83, 0, 0, + 0, 0, 0, 0, 0, 106, 102, 0, 130, 131, + 0, 0, 0, 89, 42, 121, 0, 44, 61, 50, + 52, 56, 57, 0, 0, 105, 97, 0, 0, 0, + 122, 107, 0, 0, 0, 123, 103, 0, 0, 98, + 99 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 3, 28, 159, 157, 29, 32, 61, 63, - 57, 48, 85, 76, 89, 69, 81, 95, 97, 99, - 101, 103, 105, 91, 93, 107, 58, 70, 59, 71, - 50, 192, 60, 51, 52, 53, 54, 119, 209, 55, - 233, 124 + -1, 1, 3, 27, 153, 28, 31, 60, 62, 56, + 47, 83, 74, 87, 67, 79, 93, 95, 97, 99, + 101, 103, 89, 91, 105, 57, 68, 58, 69, 49, + 187, 59, 50, 51, 52, 53, 116, 203, 54, 227, + 121 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -94 +#define YYPACT_NINF -89 static const yytype_int16 yypact[] = { - -94, 15, -94, 218, -28, -25, 264, 285, 285, 340, - 163, 2, 319, 97, 415, 415, 285, 285, 285, 285, - 306, -24, -24, 285, -17, -14, 4, -94, -94, 48, - -94, -94, -94, 481, 481, -94, -94, -94, -94, -94, - -94, -94, -94, 19, -94, 340, 399, 481, -94, -94, - -94, -94, -94, -94, 46, 47, 385, -94, -94, 52, - -94, -94, 59, -94, 60, 374, 19, 56, 243, -94, - -94, -94, -94, -94, -94, 63, -94, 106, 340, -94, - -94, -94, 56, 138, 481, -94, -94, 69, 72, -94, - 74, -94, 76, -94, 77, -94, 79, -94, 80, -94, - 81, -94, 83, -94, 89, -94, -94, -94, 94, -94, - 481, -94, 481, -94, -94, -94, 119, 481, 481, 98, - -94, -1, 100, -94, 84, -94, 117, 23, 426, -94, - -94, 433, -94, -94, -94, 340, 285, -94, -94, 98, - -94, -94, 75, 481, -94, -94, 138, 122, 440, 444, - 285, 340, 340, 340, 340, 340, 285, 218, 393, 218, - 393, 56, -94, -94, -15, 481, 105, -94, 481, 481, - 481, 156, 162, 481, 481, 481, 481, 481, -94, 165, - 0, 123, 133, -94, 474, 134, -94, -94, 136, 140, - -94, 7, -94, 141, -94, 143, -94, 148, 149, -94, - 147, 160, -94, -94, -94, 164, -94, -94, -94, 167, - 168, 180, 533, 541, 548, 481, 481, 58, 58, -94, - -94, -94, 481, 481, 171, -94, -94, 172, -94, -94, - -24, 192, 217, -94, 175, -24, 219, 216, 481, 306, - 220, -94, -94, 247, 33, 33, 205, 208, 41, -94, - -94, 253, 234, -94, -94, -94, -94, -94, -94, 215, - 481, -94, -94, 259, 260, 239, -94, -94, 221, 481, - 481, -94, -94, 223, 224, -94, -94 + -89, 18, -89, 163, -5, -13, 219, 253, 253, 335, + 194, 16, 274, 369, 418, 418, 253, 253, 253, 253, + 240, 0, 0, 253, -17, 19, -89, -89, 24, -89, + -89, -89, 479, 479, -89, -89, -89, -89, -89, -89, + -89, -89, 111, -89, 335, 397, 479, -89, -89, -89, + -89, -89, -89, 33, 51, 390, -89, -89, 65, -89, + -89, 72, -89, 73, 356, 111, 314, -89, -89, -89, + -89, -89, -89, 74, -89, 30, 335, -89, -89, -89, + 70, 422, 479, -89, -89, 82, 86, -89, 88, -89, + 89, -89, 90, -89, 91, -89, 92, -89, 101, -89, + 105, -89, 114, -89, -89, -89, 116, -89, 479, 479, + -89, -89, -89, 118, 479, 479, 120, -89, 5, 115, + -89, 83, -89, 133, -12, 404, -89, -89, 439, -89, + -89, -89, 335, 253, -89, -89, 120, -89, 9, 479, + -89, -89, 422, 141, 119, 452, 253, 335, 335, 335, + 335, 335, 253, 163, 327, 327, 70, -89, -89, 4, + 479, 143, -89, 479, 479, 479, 190, 191, 479, 479, + 479, 479, 479, -89, 187, 6, 148, 152, -89, 470, + 156, -89, -89, 158, 162, -89, 8, -89, 164, -89, + 166, -89, 170, 171, -89, 169, 172, -89, -89, 173, + -89, -89, -89, 161, 176, 199, 102, 530, 537, 479, + 479, 39, 39, -89, -89, -89, 479, 479, 185, -89, + -89, 189, -89, -89, 0, 208, 234, -89, 193, 0, + 211, 212, 479, 240, 217, -89, -89, 255, 55, 55, + 214, 215, 59, -89, -89, 260, 241, -89, -89, -89, + -89, -89, -89, 222, 479, -89, -89, 262, 276, 256, + -89, -89, 242, 479, 479, -89, -89, 243, 246, -89, + -89 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -94, -94, -94, -43, -94, -94, -94, 266, -94, -94, - -94, 273, -94, -94, -94, -94, -94, -94, -94, -94, - -94, -94, -94, -94, -94, -94, 26, 229, 32, -11, - -9, 57, -8, 71, -2, -6, 1, -60, -94, -10, - -94, -93 + -89, -89, -89, 134, -89, -89, 289, -89, -89, -89, + 290, -89, -89, -89, -89, -89, -89, -89, -89, -89, + -89, -89, -89, -89, -89, -2, 237, 11, -11, -9, + 76, -8, 87, -4, 2, -3, -56, -89, -10, -89, + -88 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -726,124 +726,120 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint16 yytable[] = { - 75, 72, 86, 88, 74, 87, 139, 140, 73, 165, - 223, 102, 77, 104, 106, 2, 231, 158, 206, 160, - 207, 30, 144, 114, 115, 116, 31, 117, 118, 208, - 56, 109, 49, 110, 111, 64, 123, 125, 49, 232, - 62, 173, 174, 175, 176, 177, 133, 43, 94, 96, - 98, 100, 166, 224, 112, 108, 137, 132, 75, 72, - 180, 181, 74, 138, 117, 118, 73, 182, 175, 176, - 177, 120, 145, 88, 123, 212, 213, 214, 263, 264, - 217, 218, 219, 220, 221, 90, 92, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 113, 126, 127, - 123, 205, 123, 134, 120, 33, 34, 162, 163, 188, - 135, 136, 180, 181, 203, 142, 204, 143, 115, 182, - 146, 123, 244, 245, 147, 148, 161, 149, 150, 35, - 151, 152, 153, 189, 154, 190, 88, 178, 193, 195, - 155, 194, 82, 67, 44, 156, 33, 34, 83, 84, - 164, 56, 47, 167, 179, 210, 188, 211, 123, 123, - 123, 186, 215, 123, 123, 123, 123, 123, 187, 216, - 35, 33, 34, 65, 115, 222, 225, 197, 198, 199, - 200, 201, 196, 82, 67, 44, 226, 228, 202, 229, - 84, 230, 234, 47, 235, 35, 236, 237, 238, 36, - 37, 38, 39, 40, 41, 123, 123, 42, 66, 67, - 44, 239, 246, 247, 68, 46, 240, 243, 47, 4, - 241, 242, 250, 248, 251, 249, 252, 254, 257, 191, - 258, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 268, 33, 34, 65, 256, 259, 255, 260, 261, 273, - 274, 262, 265, 24, 25, 26, 266, 27, 267, 269, - 270, 271, 33, 34, 272, 35, 275, 276, 79, 36, - 37, 38, 39, 40, 41, 80, 0, 42, 66, 67, - 44, 253, 0, 33, 34, 46, 35, 141, 47, 0, - 36, 37, 38, 39, 40, 41, 0, 0, 42, 43, - 0, 44, 0, 0, 0, 45, 46, 35, 0, 47, - 0, 36, 37, 38, 39, 40, 41, 33, 34, 42, - 43, 0, 44, 0, 0, 0, 0, 46, 0, 56, - 47, 0, 36, 37, 38, 39, 40, 41, 33, 34, - 42, 35, 0, 0, 0, 36, 37, 38, 39, 40, - 41, 0, 0, 42, 43, 0, 44, 0, 0, 0, - 78, 46, 35, 0, 47, 0, 36, 37, 38, 39, - 40, 41, 33, 34, 42, 43, 0, 44, 0, 0, - 0, 0, 46, 33, 128, 47, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 35, 33, 34, 0, - 36, 37, 38, 39, 40, 41, 0, 35, 42, 0, - 0, 44, 0, 33, 34, 0, 46, 129, 130, 47, - 43, 35, 44, 0, 33, 34, 121, 131, 0, 0, - 47, 33, 184, 122, 0, 0, 44, 35, 33, 34, - 0, 84, 33, 34, 47, 0, 0, 0, 35, 0, - 43, 0, 44, 0, 0, 35, 0, 46, 183, 0, - 47, 0, 35, 44, 0, 185, 35, 0, 84, 0, - 44, 47, 33, 34, 0, 84, 0, 44, 47, 33, - 34, 44, 84, 0, 191, 47, 84, 0, 56, 47, - 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, - 0, 0, 0, 35, 0, 0, 227, 0, 0, 0, - 0, 44, 0, 0, 0, 0, 84, 0, 44, 47, - 0, 0, 0, 84, 0, 0, 47, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 170, 171, 172, 173, - 174, 175, 176, 177, 171, 172, 173, 174, 175, 176, - 177 + 73, 70, 84, 86, 48, 85, 71, 63, 75, 136, + 48, 100, 72, 102, 104, 160, 217, 225, 2, 61, + 154, 155, 111, 112, 140, 175, 176, 92, 94, 96, + 98, 107, 177, 108, 106, 120, 122, 200, 30, 201, + 226, 139, 117, 183, 29, 130, 175, 176, 202, 170, + 171, 172, 129, 177, 55, 134, 73, 70, 161, 218, + 135, 42, 71, 168, 169, 170, 171, 172, 72, 109, + 141, 86, 120, 110, 117, 206, 207, 208, 114, 115, + 211, 212, 213, 214, 215, 123, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 257, 258, 120, 120, + 199, 88, 90, 124, 157, 158, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 112, 131, 113, 120, 114, + 115, 238, 239, 132, 133, 156, 138, 32, 33, 184, + 181, 185, 86, 142, 188, 190, 173, 189, 143, 144, + 145, 146, 147, 148, 182, 192, 193, 194, 195, 196, + 204, 34, 149, 120, 120, 120, 150, 191, 120, 120, + 120, 120, 120, 197, 4, 151, 43, 152, 162, 112, + 174, 82, 159, 186, 46, 183, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 205, 209, 216, 210, 120, + 120, 219, 32, 33, 64, 220, 240, 241, 24, 222, + 25, 223, 26, 224, 235, 228, 244, 229, 230, 231, + 232, 248, 251, 233, 252, 234, 34, 32, 33, 236, + 35, 36, 37, 38, 39, 40, 237, 242, 41, 65, + 245, 43, 243, 246, 262, 66, 45, 186, 249, 46, + 250, 34, 253, 267, 268, 35, 36, 37, 38, 39, + 40, 32, 33, 41, 42, 254, 43, 255, 256, 259, + 44, 45, 263, 260, 46, 261, 35, 36, 37, 38, + 39, 40, 32, 33, 41, 34, 264, 198, 265, 35, + 36, 37, 38, 39, 40, 266, 269, 41, 42, 270, + 43, 77, 78, 137, 247, 45, 34, 55, 46, 0, + 35, 36, 37, 38, 39, 40, 0, 0, 41, 42, + 0, 43, 32, 33, 64, 76, 45, 0, 0, 46, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 0, 0, 0, 32, 33, 0, 34, 0, 0, 0, + 35, 36, 37, 38, 39, 40, 0, 0, 41, 65, + 0, 43, 0, 0, 32, 33, 45, 34, 0, 46, + 0, 35, 36, 37, 38, 39, 40, 32, 33, 41, + 42, 0, 43, 0, 0, 0, 0, 45, 34, 0, + 46, 0, 35, 36, 37, 38, 39, 40, 32, 125, + 41, 34, 0, 43, 0, 32, 33, 0, 45, 0, + 0, 46, 32, 33, 80, 0, 43, 0, 0, 0, + 81, 82, 34, 55, 46, 0, 32, 33, 0, 34, + 32, 33, 126, 127, 118, 42, 34, 43, 0, 0, + 0, 119, 128, 0, 43, 46, 178, 32, 179, 82, + 34, 43, 46, 0, 34, 0, 82, 0, 0, 46, + 32, 33, 0, 42, 0, 43, 0, 80, 0, 43, + 45, 34, 0, 46, 82, 0, 0, 46, 32, 33, + 0, 180, 0, 0, 34, 0, 43, 32, 33, 0, + 0, 82, 0, 0, 46, 0, 0, 0, 0, 43, + 0, 0, 34, 0, 82, 0, 55, 46, 0, 0, + 0, 34, 221, 0, 0, 0, 0, 43, 0, 0, + 0, 0, 82, 0, 0, 46, 43, 0, 0, 0, + 0, 82, 0, 0, 46, 165, 166, 167, 168, 169, + 170, 171, 172, 166, 167, 168, 169, 170, 171, 172 }; static const yytype_int16 yycheck[] = { - 10, 10, 13, 13, 10, 13, 66, 67, 10, 10, - 10, 20, 11, 21, 22, 0, 9, 110, 33, 112, - 35, 49, 82, 33, 34, 6, 51, 8, 9, 44, - 54, 48, 6, 50, 48, 9, 46, 47, 12, 32, - 8, 8, 9, 10, 11, 12, 56, 45, 16, 17, - 18, 19, 53, 53, 50, 23, 65, 56, 68, 68, - 37, 38, 68, 65, 8, 9, 68, 44, 10, 11, - 12, 45, 83, 83, 84, 168, 169, 170, 37, 38, - 173, 174, 175, 176, 177, 14, 15, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 49, 52, 52, - 110, 161, 112, 51, 78, 8, 9, 117, 118, 34, - 51, 51, 37, 38, 157, 52, 159, 11, 128, 44, - 51, 131, 215, 216, 52, 51, 7, 51, 51, 32, - 51, 51, 51, 143, 51, 146, 146, 53, 148, 149, - 51, 149, 45, 46, 47, 51, 8, 9, 51, 52, - 52, 54, 55, 53, 37, 165, 34, 52, 168, 169, - 170, 135, 6, 173, 174, 175, 176, 177, 136, 7, - 32, 8, 9, 10, 184, 10, 53, 151, 152, 153, - 154, 155, 150, 45, 46, 47, 53, 53, 156, 53, - 52, 51, 51, 55, 51, 32, 48, 48, 51, 36, - 37, 38, 39, 40, 41, 215, 216, 44, 45, 46, - 47, 51, 222, 223, 51, 52, 52, 37, 55, 1, - 53, 53, 230, 52, 32, 53, 9, 235, 238, 54, - 239, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 260, 8, 9, 10, 38, 35, 37, 10, 53, 269, - 270, 53, 9, 45, 46, 47, 32, 49, 53, 10, - 10, 32, 8, 9, 53, 32, 53, 53, 12, 36, - 37, 38, 39, 40, 41, 12, -1, 44, 45, 46, - 47, 234, -1, 8, 9, 52, 32, 68, 55, -1, + 10, 10, 13, 13, 6, 13, 10, 9, 11, 65, + 12, 20, 10, 21, 22, 10, 10, 9, 0, 8, + 108, 109, 32, 33, 80, 37, 38, 16, 17, 18, + 19, 48, 44, 50, 23, 45, 46, 33, 51, 35, + 32, 11, 44, 34, 49, 55, 37, 38, 44, 10, + 11, 12, 55, 44, 54, 64, 66, 66, 53, 53, + 64, 45, 66, 8, 9, 10, 11, 12, 66, 50, + 81, 81, 82, 49, 76, 163, 164, 165, 8, 9, + 168, 169, 170, 171, 172, 52, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 37, 38, 108, 109, + 156, 14, 15, 52, 114, 115, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 125, 51, 6, 128, 8, + 9, 209, 210, 51, 51, 7, 52, 8, 9, 139, + 132, 142, 142, 51, 144, 145, 53, 145, 52, 51, + 51, 51, 51, 51, 133, 147, 148, 149, 150, 151, + 160, 32, 51, 163, 164, 165, 51, 146, 168, 169, + 170, 171, 172, 152, 1, 51, 47, 51, 53, 179, + 37, 52, 52, 54, 55, 34, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 52, 6, 10, 7, 209, + 210, 53, 8, 9, 10, 53, 216, 217, 45, 53, + 47, 53, 49, 51, 53, 51, 224, 51, 48, 48, + 51, 229, 232, 51, 233, 52, 32, 8, 9, 53, + 36, 37, 38, 39, 40, 41, 37, 52, 44, 45, + 32, 47, 53, 9, 254, 51, 52, 54, 37, 55, + 38, 32, 35, 263, 264, 36, 37, 38, 39, 40, + 41, 8, 9, 44, 45, 10, 47, 53, 53, 9, + 51, 52, 10, 32, 55, 53, 36, 37, 38, 39, + 40, 41, 8, 9, 44, 32, 10, 153, 32, 36, + 37, 38, 39, 40, 41, 53, 53, 44, 45, 53, + 47, 12, 12, 66, 228, 52, 32, 54, 55, -1, 36, 37, 38, 39, 40, 41, -1, -1, 44, 45, - -1, 47, -1, -1, -1, 51, 52, 32, -1, 55, + -1, 47, 8, 9, 10, 51, 52, -1, -1, 55, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + -1, -1, -1, 8, 9, -1, 32, -1, -1, -1, + 36, 37, 38, 39, 40, 41, -1, -1, 44, 45, + -1, 47, -1, -1, 8, 9, 52, 32, -1, 55, -1, 36, 37, 38, 39, 40, 41, 8, 9, 44, - 45, -1, 47, -1, -1, -1, -1, 52, -1, 54, + 45, -1, 47, -1, -1, -1, -1, 52, 32, -1, 55, -1, 36, 37, 38, 39, 40, 41, 8, 9, - 44, 32, -1, -1, -1, 36, 37, 38, 39, 40, - 41, -1, -1, 44, 45, -1, 47, -1, -1, -1, - 51, 52, 32, -1, 55, -1, 36, 37, 38, 39, - 40, 41, 8, 9, 44, 45, -1, 47, -1, -1, - -1, -1, 52, 8, 9, 55, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 32, 8, 9, -1, - 36, 37, 38, 39, 40, 41, -1, 32, 44, -1, - -1, 47, -1, 8, 9, -1, 52, 42, 43, 55, - 45, 32, 47, -1, 8, 9, 37, 52, -1, -1, - 55, 8, 9, 44, -1, -1, 47, 32, 8, 9, - -1, 52, 8, 9, 55, -1, -1, -1, 32, -1, - 45, -1, 47, -1, -1, 32, -1, 52, 42, -1, - 55, -1, 32, 47, -1, 42, 32, -1, 52, -1, - 47, 55, 8, 9, -1, 52, -1, 47, 55, 8, - 9, 47, 52, -1, 54, 55, 52, -1, 54, 55, - -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, - -1, -1, -1, 32, -1, -1, 42, -1, -1, -1, - -1, 47, -1, -1, -1, -1, 52, -1, 47, 55, - -1, -1, -1, 52, -1, -1, 55, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 5, 6, 7, 8, - 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, - 12 + 44, 32, -1, 47, -1, 8, 9, -1, 52, -1, + -1, 55, 8, 9, 45, -1, 47, -1, -1, -1, + 51, 52, 32, 54, 55, -1, 8, 9, -1, 32, + 8, 9, 42, 43, 37, 45, 32, 47, -1, -1, + -1, 44, 52, -1, 47, 55, 42, 8, 9, 52, + 32, 47, 55, -1, 32, -1, 52, -1, -1, 55, + 8, 9, -1, 45, -1, 47, -1, 45, -1, 47, + 52, 32, -1, 55, 52, -1, -1, 55, 8, 9, + -1, 42, -1, -1, 32, -1, 47, 8, 9, -1, + -1, 52, -1, -1, 55, -1, -1, -1, -1, 47, + -1, -1, 32, -1, 52, -1, 54, 55, -1, -1, + -1, 32, 42, -1, -1, -1, -1, 47, -1, -1, + -1, -1, 52, -1, -1, 55, 47, -1, -1, -1, + -1, 52, -1, -1, 55, 5, 6, 7, 8, 9, + 10, 11, 12, 6, 7, 8, 9, 10, 11, 12 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -852,32 +848,32 @@ static const yytype_uint8 yystos[] = { 0, 57, 0, 58, 1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 45, 46, 47, 49, 59, 62, - 49, 51, 63, 8, 9, 32, 36, 37, 38, 39, - 40, 41, 44, 45, 47, 51, 52, 55, 67, 82, - 86, 89, 90, 91, 92, 95, 54, 66, 82, 84, - 88, 64, 84, 65, 82, 10, 45, 46, 51, 71, - 83, 85, 86, 90, 91, 95, 69, 92, 51, 63, - 67, 72, 45, 51, 52, 68, 85, 88, 95, 70, - 89, 79, 89, 80, 84, 73, 84, 74, 84, 75, - 84, 76, 86, 77, 88, 78, 88, 81, 84, 48, - 50, 48, 50, 49, 95, 95, 6, 8, 9, 93, - 82, 37, 44, 95, 97, 95, 52, 52, 9, 42, - 43, 52, 92, 95, 51, 51, 51, 86, 90, 93, - 93, 83, 52, 11, 93, 85, 51, 52, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 61, 97, 60, - 97, 7, 95, 95, 52, 10, 53, 53, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 53, 37, - 37, 38, 44, 42, 9, 42, 82, 84, 34, 95, - 85, 54, 87, 95, 88, 95, 84, 82, 82, 82, - 82, 82, 84, 59, 59, 93, 33, 35, 44, 94, - 95, 52, 97, 97, 97, 6, 7, 97, 97, 97, - 97, 97, 10, 10, 53, 53, 53, 42, 53, 53, - 51, 9, 32, 96, 51, 51, 48, 48, 51, 51, - 52, 53, 53, 37, 97, 97, 95, 95, 52, 53, - 88, 32, 9, 87, 88, 37, 38, 95, 86, 35, - 10, 53, 53, 37, 38, 9, 32, 53, 95, 10, - 10, 32, 53, 95, 95, 53, 53 + 28, 29, 30, 31, 45, 47, 49, 59, 61, 49, + 51, 62, 8, 9, 32, 36, 37, 38, 39, 40, + 41, 44, 45, 47, 51, 52, 55, 66, 81, 85, + 88, 89, 90, 91, 94, 54, 65, 81, 83, 87, + 63, 83, 64, 81, 10, 45, 51, 70, 82, 84, + 85, 89, 90, 94, 68, 91, 51, 62, 66, 71, + 45, 51, 52, 67, 84, 87, 94, 69, 88, 78, + 88, 79, 83, 72, 83, 73, 83, 74, 83, 75, + 85, 76, 87, 77, 87, 80, 83, 48, 50, 50, + 49, 94, 94, 6, 8, 9, 92, 81, 37, 44, + 94, 96, 94, 52, 52, 9, 42, 43, 52, 91, + 94, 51, 51, 51, 85, 89, 92, 82, 52, 11, + 92, 84, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 60, 96, 96, 7, 94, 94, 52, + 10, 53, 53, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 53, 37, 37, 38, 44, 42, 9, + 42, 81, 83, 34, 94, 84, 54, 86, 94, 87, + 94, 83, 81, 81, 81, 81, 81, 83, 59, 92, + 33, 35, 44, 93, 94, 52, 96, 96, 96, 6, + 7, 96, 96, 96, 96, 96, 10, 10, 53, 53, + 53, 42, 53, 53, 51, 9, 32, 95, 51, 51, + 48, 48, 51, 51, 52, 53, 53, 37, 96, 96, + 94, 94, 52, 53, 87, 32, 9, 86, 87, 37, + 38, 94, 85, 35, 10, 53, 53, 37, 38, 9, + 32, 53, 94, 10, 10, 32, 53, 94, 94, 53, + 53 }; #define yyerrok (yyerrstatus = 0) @@ -1701,30 +1697,24 @@ yyreduce: case 5: #line 75 "a.y" { - if((yyvsp[(1) - (2)].sym)->value != pc) - yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name); - (yyvsp[(1) - (2)].sym)->value = pc; - } - break; - - case 7: -#line 82 "a.y" - { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); + if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc) + yyerror("redeclaration of %s (%s)", (yyvsp[(1) - (2)].sym)->labelname, (yyvsp[(1) - (2)].sym)->name); (yyvsp[(1) - (2)].sym)->type = LLAB; (yyvsp[(1) - (2)].sym)->value = pc; } break; - case 12: -#line 93 "a.y" + case 10: +#line 89 "a.y" { (yyvsp[(1) - (3)].sym)->type = LVAR; (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval); } break; - case 13: -#line 98 "a.y" + case 11: +#line 94 "a.y" { if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval)) yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name); @@ -1732,191 +1722,191 @@ yyreduce: } break; + case 12: +#line 99 "a.y" + { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } + break; + + case 13: +#line 100 "a.y" + { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } + break; + case 14: -#line 103 "a.y" +#line 101 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 15: -#line 104 "a.y" +#line 102 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 16: -#line 105 "a.y" +#line 103 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 17: -#line 106 "a.y" +#line 104 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 18: -#line 107 "a.y" +#line 105 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 19: -#line 108 "a.y" +#line 106 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 20: -#line 109 "a.y" +#line 107 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 21: -#line 110 "a.y" +#line 108 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 22: -#line 111 "a.y" +#line 109 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 23: -#line 112 "a.y" +#line 110 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 24: -#line 113 "a.y" +#line 111 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 25: -#line 114 "a.y" +#line 112 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 26: -#line 115 "a.y" +#line 113 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 27: -#line 116 "a.y" +#line 114 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 28: -#line 117 "a.y" +#line 115 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 29: -#line 118 "a.y" +#line 116 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 30: -#line 119 "a.y" +#line 117 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 31: #line 120 "a.y" - { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } - break; - - case 32: -#line 121 "a.y" - { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } - break; - - case 33: -#line 124 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = nullgen; } break; - case 34: -#line 129 "a.y" + case 32: +#line 125 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = nullgen; } break; - case 35: -#line 136 "a.y" + case 33: +#line 132 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 36: -#line 143 "a.y" + case 34: +#line 139 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 37: -#line 150 "a.y" + case 35: +#line 146 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (2)].addr); (yyval.addr2).to = nullgen; } break; - case 38: -#line 155 "a.y" + case 36: +#line 151 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (1)].addr); (yyval.addr2).to = nullgen; } break; - case 39: -#line 162 "a.y" + case 37: +#line 158 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); } break; - case 40: -#line 167 "a.y" + case 38: +#line 163 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); } break; - case 41: -#line 174 "a.y" + case 39: +#line 170 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); } break; - case 42: -#line 179 "a.y" + case 40: +#line 175 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); } break; - case 43: -#line 184 "a.y" + case 41: +#line 180 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 44: -#line 191 "a.y" + case 42: +#line 187 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval); @@ -1924,49 +1914,51 @@ yyreduce: } break; - case 45: -#line 199 "a.y" + case 43: +#line 195 "a.y" { + settext((yyvsp[(1) - (3)].addr).sym); (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 46: -#line 204 "a.y" + case 44: +#line 201 "a.y" { + settext((yyvsp[(1) - (5)].addr).sym); (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval); (yyval.addr2).to = (yyvsp[(5) - (5)].addr); } break; - case 47: -#line 212 "a.y" + case 45: +#line 210 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); } break; - case 48: -#line 217 "a.y" + case 46: +#line 215 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); } break; - case 51: -#line 228 "a.y" + case 49: +#line 226 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 52: -#line 233 "a.y" + case 50: +#line 231 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).to = (yyvsp[(3) - (5)].addr); @@ -1976,16 +1968,16 @@ yyreduce: } break; - case 53: -#line 243 "a.y" + case 51: +#line 241 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 54: -#line 248 "a.y" + case 52: +#line 246 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).to = (yyvsp[(3) - (5)].addr); @@ -1995,32 +1987,32 @@ yyreduce: } break; - case 55: -#line 258 "a.y" + case 53: +#line 256 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (2)].addr); (yyval.addr2).to = nullgen; } break; - case 56: -#line 263 "a.y" + case 54: +#line 261 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (1)].addr); (yyval.addr2).to = nullgen; } break; - case 57: -#line 268 "a.y" + case 55: +#line 266 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 58: -#line 275 "a.y" + case 56: +#line 273 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).to = (yyvsp[(3) - (5)].addr); @@ -2028,8 +2020,8 @@ yyreduce: } break; - case 59: -#line 283 "a.y" + case 57: +#line 281 "a.y" { (yyval.addr2).from = (yyvsp[(3) - (5)].addr); (yyval.addr2).to = (yyvsp[(5) - (5)].addr); @@ -2039,32 +2031,32 @@ yyreduce: } break; - case 60: -#line 292 "a.y" + case 58: +#line 290 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = nullgen; } break; - case 61: -#line 297 "a.y" + case 59: +#line 295 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (1)].addr); (yyval.addr2).to = nullgen; } break; - case 62: -#line 304 "a.y" + case 60: +#line 302 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 63: -#line 309 "a.y" + case 61: +#line 307 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval); @@ -2072,8 +2064,8 @@ yyreduce: } break; - case 64: -#line 317 "a.y" + case 62: +#line 315 "a.y" { if((yyvsp[(1) - (3)].addr).type != D_CONST || (yyvsp[(3) - (3)].addr).type != D_CONST) yyerror("arguments to PCDATA must be integer constants"); @@ -2082,8 +2074,8 @@ yyreduce: } break; - case 65: -#line 326 "a.y" + case 63: +#line 324 "a.y" { if((yyvsp[(1) - (3)].addr).type != D_CONST) yyerror("index for FUNCDATA must be integer constant"); @@ -2094,22 +2086,22 @@ yyreduce: } break; - case 70: -#line 343 "a.y" + case 68: +#line 341 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); } break; - case 71: -#line 347 "a.y" + case 69: +#line 345 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); } break; - case 76: -#line 359 "a.y" + case 74: +#line 357 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_BRANCH; @@ -2117,84 +2109,76 @@ yyreduce: } break; - case 77: -#line 365 "a.y" - { - (yyval.addr) = nullgen; - if(pass == 2) - yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name); - (yyval.addr).type = D_BRANCH; - (yyval.addr).offset = (yyvsp[(2) - (2)].lval); - } - break; - - case 78: -#line 373 "a.y" + case 75: +#line 363 "a.y" { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); (yyval.addr) = nullgen; + if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB) + yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname); (yyval.addr).type = D_BRANCH; (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval); } break; - case 79: -#line 381 "a.y" + case 76: +#line 374 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 80: -#line 386 "a.y" + case 77: +#line 379 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 81: -#line 391 "a.y" + case 78: +#line 384 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 82: -#line 396 "a.y" + case 79: +#line 389 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 83: -#line 401 "a.y" + case 80: +#line 394 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SP; } break; - case 84: -#line 406 "a.y" + case 81: +#line 399 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 85: -#line 411 "a.y" + case 82: +#line 404 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 86: -#line 417 "a.y" + case 83: +#line 410 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST; @@ -2202,8 +2186,8 @@ yyreduce: } break; - case 87: -#line 425 "a.y" + case 84: +#line 418 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST; @@ -2211,8 +2195,8 @@ yyreduce: } break; - case 88: -#line 431 "a.y" + case 85: +#line 424 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); (yyval.addr).index = (yyvsp[(2) - (2)].addr).type; @@ -2225,8 +2209,8 @@ yyreduce: } break; - case 89: -#line 442 "a.y" + case 86: +#line 435 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SCONST; @@ -2234,8 +2218,8 @@ yyreduce: } break; - case 90: -#line 448 "a.y" + case 87: +#line 441 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2243,8 +2227,8 @@ yyreduce: } break; - case 91: -#line 454 "a.y" + case 88: +#line 447 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2252,8 +2236,8 @@ yyreduce: } break; - case 92: -#line 460 "a.y" + case 89: +#line 453 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2261,8 +2245,8 @@ yyreduce: } break; - case 93: -#line 466 "a.y" + case 90: +#line 459 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2270,8 +2254,8 @@ yyreduce: } break; - case 96: -#line 478 "a.y" + case 93: +#line 471 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_NONE; @@ -2279,8 +2263,8 @@ yyreduce: } break; - case 97: -#line 484 "a.y" + case 94: +#line 477 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval); @@ -2288,8 +2272,8 @@ yyreduce: } break; - case 98: -#line 490 "a.y" + case 95: +#line 483 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_SP; @@ -2297,8 +2281,8 @@ yyreduce: } break; - case 99: -#line 496 "a.y" + case 96: +#line 489 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval); @@ -2306,8 +2290,8 @@ yyreduce: } break; - case 100: -#line 502 "a.y" + case 97: +#line 495 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_NONE; @@ -2318,8 +2302,8 @@ yyreduce: } break; - case 101: -#line 511 "a.y" + case 98: +#line 504 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval); @@ -2330,8 +2314,8 @@ yyreduce: } break; - case 102: -#line 520 "a.y" + case 99: +#line 513 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval); @@ -2342,24 +2326,24 @@ yyreduce: } break; - case 103: -#line 529 "a.y" + case 100: +#line 522 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(2) - (3)].lval); } break; - case 104: -#line 534 "a.y" + case 101: +#line 527 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_SP; } break; - case 105: -#line 539 "a.y" + case 102: +#line 532 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_NONE; @@ -2369,8 +2353,8 @@ yyreduce: } break; - case 106: -#line 547 "a.y" + case 103: +#line 540 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(2) - (8)].lval); @@ -2380,15 +2364,15 @@ yyreduce: } break; - case 107: -#line 557 "a.y" + case 104: +#line 550 "a.y" { (yyval.addr) = (yyvsp[(1) - (1)].addr); } break; - case 108: -#line 561 "a.y" + case 105: +#line 554 "a.y" { (yyval.addr) = (yyvsp[(1) - (6)].addr); (yyval.addr).index = (yyvsp[(3) - (6)].lval); @@ -2397,8 +2381,8 @@ yyreduce: } break; - case 109: -#line 570 "a.y" + case 106: +#line 563 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(4) - (5)].lval); @@ -2407,8 +2391,8 @@ yyreduce: } break; - case 110: -#line 577 "a.y" + case 107: +#line 570 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_STATIC; @@ -2417,166 +2401,166 @@ yyreduce: } break; - case 111: -#line 585 "a.y" + case 108: +#line 578 "a.y" { (yyval.lval) = 0; } break; - case 112: -#line 589 "a.y" + case 109: +#line 582 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 113: -#line 593 "a.y" + case 110: +#line 586 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 115: -#line 600 "a.y" + case 112: +#line 593 "a.y" { (yyval.lval) = D_AUTO; } break; - case 118: -#line 608 "a.y" + case 115: +#line 601 "a.y" { (yyval.lval) = (yyvsp[(1) - (1)].sym)->value; } break; - case 119: -#line 612 "a.y" + case 116: +#line 605 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 120: -#line 616 "a.y" + case 117: +#line 609 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 121: -#line 620 "a.y" + case 118: +#line 613 "a.y" { (yyval.lval) = ~(yyvsp[(2) - (2)].lval); } break; - case 122: -#line 624 "a.y" + case 119: +#line 617 "a.y" { (yyval.lval) = (yyvsp[(2) - (3)].lval); } break; - case 123: -#line 630 "a.y" + case 120: +#line 623 "a.y" { (yyval.lval) = ((yyvsp[(1) - (1)].lval) & 0xffffffffLL) + ((vlong)ArgsSizeUnknown << 32); } break; - case 124: -#line 635 "a.y" + case 121: +#line 628 "a.y" { (yyval.lval) = (-(yyvsp[(2) - (2)].lval) & 0xffffffffLL) + ((vlong)ArgsSizeUnknown << 32); } break; - case 125: -#line 640 "a.y" + case 122: +#line 633 "a.y" { (yyval.lval) = ((yyvsp[(1) - (3)].lval) & 0xffffffffLL) + (((yyvsp[(3) - (3)].lval) & 0xffffLL) << 32); } break; - case 126: -#line 645 "a.y" + case 123: +#line 638 "a.y" { (yyval.lval) = (-(yyvsp[(2) - (4)].lval) & 0xffffffffLL) + (((yyvsp[(4) - (4)].lval) & 0xffffLL) << 32); } break; - case 128: -#line 653 "a.y" + case 125: +#line 646 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval); } break; - case 129: -#line 657 "a.y" + case 126: +#line 650 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval); } break; - case 130: -#line 661 "a.y" + case 127: +#line 654 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval); } break; - case 131: -#line 665 "a.y" + case 128: +#line 658 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval); } break; - case 132: -#line 669 "a.y" + case 129: +#line 662 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval); } break; - case 133: -#line 673 "a.y" + case 130: +#line 666 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval); } break; - case 134: -#line 677 "a.y" + case 131: +#line 670 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval); } break; - case 135: -#line 681 "a.y" + case 132: +#line 674 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval); } break; - case 136: -#line 685 "a.y" + case 133: +#line 678 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval); } break; - case 137: -#line 689 "a.y" + case 134: +#line 682 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval); } @@ -2584,7 +2568,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 2588 "y.tab.c" +#line 2572 "y.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); diff --git a/src/cmd/8a/a.h b/src/cmd/8a/a.h index adc388ca9..a1aca07ae 100644 --- a/src/cmd/8a/a.h +++ b/src/cmd/8a/a.h @@ -70,6 +70,7 @@ struct Sym int32 value; ushort type; char *name; + char* labelname; char sym; }; #define S ((Sym*)0) @@ -148,6 +149,8 @@ void newio(void); void newfile(char*, int); Sym* slookup(char*); Sym* lookup(void); +Sym* labellookup(Sym*); +void settext(LSym*); void syminit(Sym*); int32 yylex(void); int getc(void); diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y index 6bcf1313b..c810d3857 100644 --- a/src/cmd/8a/a.y +++ b/src/cmd/8a/a.y @@ -74,15 +74,11 @@ prog: line line: - LLAB ':' - { - if($1->value != pc) - yyerror("redeclaration of %s", $1->name); - $1->value = pc; - } - line -| LNAME ':' + LNAME ':' { + $1 = labellookup($1); + if($1->type == LLAB && $1->value != pc) + yyerror("redeclaration of %s", $1->labelname); $1->type = LLAB; $1->value = pc; } @@ -199,11 +195,13 @@ spec1: /* DATA */ spec2: /* TEXT */ mem ',' imm2 { + settext($1.sym); $$.from = $1; $$.to = $3; } | mem ',' con ',' imm2 { + settext($1.sym); $$.from = $1; $$.from.scale = $3; $$.to = $5; @@ -362,15 +360,10 @@ rel: } | LNAME offset { + $1 = labellookup($1); $$ = nullgen; - if(pass == 2) - yyerror("undefined label: %s", $1->name); - $$.type = D_BRANCH; - $$.offset = $2; - } -| LLAB offset - { - $$ = nullgen; + if(pass == 2 && $1->type != LLAB) + yyerror("undefined label: %s", $1->labelname); $$.type = D_BRANCH; $$.offset = $1->value + $2; } diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c index 85279c21f..f284d8ea2 100644 --- a/src/cmd/8a/y.tab.c +++ b/src/cmd/8a/y.tab.c @@ -411,16 +411,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 546 +#define YYLAST 561 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 54 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 41 +#define YYNNTS 40 /* YYNRULES -- Number of rules. */ -#define YYNRULES 135 +#define YYNRULES 132 /* YYNRULES -- Number of states. */ -#define YYNSTATES 276 +#define YYNSTATES 270 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -469,91 +469,90 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint16 yyprhs[] = { - 0, 0, 3, 4, 5, 9, 10, 15, 16, 21, - 23, 26, 29, 33, 37, 40, 43, 46, 49, 52, + 0, 0, 3, 4, 5, 9, 10, 15, 17, 20, + 23, 27, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, - 85, 88, 91, 92, 94, 98, 102, 105, 107, 110, - 112, 115, 117, 121, 127, 131, 137, 140, 142, 145, - 147, 149, 153, 159, 163, 169, 172, 174, 178, 182, - 188, 194, 200, 204, 208, 210, 212, 214, 216, 219, - 222, 224, 226, 228, 230, 232, 237, 240, 243, 245, - 247, 249, 251, 253, 255, 258, 261, 264, 267, 272, - 278, 282, 285, 287, 290, 294, 299, 301, 303, 305, - 310, 315, 322, 332, 342, 346, 350, 355, 361, 370, - 372, 379, 385, 393, 394, 397, 400, 402, 404, 406, - 408, 410, 413, 416, 419, 423, 425, 429, 433, 437, - 441, 445, 450, 455, 459, 463 + 85, 86, 88, 92, 96, 99, 101, 104, 106, 109, + 111, 115, 121, 125, 131, 134, 136, 139, 141, 143, + 147, 153, 157, 163, 166, 168, 172, 176, 182, 188, + 194, 198, 202, 204, 206, 208, 210, 213, 216, 218, + 220, 222, 224, 226, 231, 234, 236, 238, 240, 242, + 244, 246, 249, 252, 255, 258, 263, 269, 273, 276, + 278, 281, 285, 290, 292, 294, 296, 301, 306, 313, + 323, 333, 337, 341, 346, 352, 361, 363, 370, 376, + 384, 385, 388, 391, 393, 395, 397, 399, 401, 404, + 407, 410, 414, 416, 420, 424, 428, 432, 436, 441, + 446, 450, 454 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 55, 0, -1, -1, -1, 55, 56, 57, -1, -1, - 44, 46, 58, 57, -1, -1, 43, 46, 59, 57, - -1, 47, -1, 60, 47, -1, 1, 47, -1, 43, - 48, 94, -1, 45, 48, 94, -1, 13, 61, -1, - 14, 65, -1, 15, 64, -1, 16, 62, -1, 17, - 63, -1, 21, 66, -1, 19, 67, -1, 22, 68, - -1, 18, 69, -1, 20, 70, -1, 23, 71, -1, - 24, 72, -1, 25, 73, -1, 26, 74, -1, 27, - 75, -1, 28, 76, -1, 29, 77, -1, 30, 78, - -1, -1, 49, -1, 81, 49, 79, -1, 79, 49, - 81, -1, 81, 49, -1, 81, -1, 49, 79, -1, - 79, -1, 49, 82, -1, 82, -1, 84, 49, 82, - -1, 90, 11, 93, 49, 84, -1, 87, 49, 85, - -1, 87, 49, 93, 49, 85, -1, 49, 80, -1, - 80, -1, 10, 90, -1, 61, -1, 65, -1, 81, - 49, 79, -1, 81, 49, 79, 46, 36, -1, 81, - 49, 79, -1, 81, 49, 79, 46, 37, -1, 81, - 49, -1, 81, -1, 81, 49, 79, -1, 87, 49, - 84, -1, 87, 49, 93, 49, 84, -1, 83, 49, - 79, 49, 93, -1, 84, 49, 79, 49, 83, -1, - 81, 49, 81, -1, 81, 49, 81, -1, 83, -1, - 87, -1, 82, -1, 89, -1, 10, 83, -1, 10, - 88, -1, 83, -1, 88, -1, 84, -1, 79, -1, - 84, -1, 93, 50, 33, 51, -1, 43, 91, -1, - 44, 91, -1, 35, -1, 38, -1, 36, -1, 39, - -1, 42, -1, 37, -1, 52, 93, -1, 52, 90, - -1, 52, 41, -1, 52, 40, -1, 52, 50, 40, - 51, -1, 52, 50, 9, 40, 51, -1, 52, 9, - 40, -1, 52, 86, -1, 31, -1, 9, 31, -1, - 31, 9, 31, -1, 9, 31, 9, 31, -1, 88, - -1, 89, -1, 93, -1, 93, 50, 36, 51, -1, - 93, 50, 42, 51, -1, 93, 50, 36, 10, 93, - 51, -1, 93, 50, 36, 51, 50, 36, 10, 93, - 51, -1, 93, 50, 36, 51, 50, 37, 10, 93, - 51, -1, 50, 36, 51, -1, 50, 42, 51, -1, - 93, 50, 37, 51, -1, 50, 36, 10, 93, 51, - -1, 50, 36, 51, 50, 36, 10, 93, 51, -1, - 90, -1, 90, 50, 36, 10, 93, 51, -1, 43, - 91, 50, 92, 51, -1, 43, 6, 7, 91, 50, - 34, 51, -1, -1, 8, 93, -1, 9, 93, -1, - 34, -1, 42, -1, 32, -1, 31, -1, 45, -1, - 9, 93, -1, 8, 93, -1, 53, 93, -1, 50, - 94, 51, -1, 93, -1, 94, 8, 94, -1, 94, - 9, 94, -1, 94, 10, 94, -1, 94, 11, 94, - -1, 94, 12, 94, -1, 94, 6, 6, 94, -1, - 94, 7, 7, 94, -1, 94, 5, 94, -1, 94, - 4, 94, -1, 94, 3, 94, -1 + 43, 46, 58, 57, -1, 47, -1, 59, 47, -1, + 1, 47, -1, 43, 48, 93, -1, 45, 48, 93, + -1, 13, 60, -1, 14, 64, -1, 15, 63, -1, + 16, 61, -1, 17, 62, -1, 21, 65, -1, 19, + 66, -1, 22, 67, -1, 18, 68, -1, 20, 69, + -1, 23, 70, -1, 24, 71, -1, 25, 72, -1, + 26, 73, -1, 27, 74, -1, 28, 75, -1, 29, + 76, -1, 30, 77, -1, -1, 49, -1, 80, 49, + 78, -1, 78, 49, 80, -1, 80, 49, -1, 80, + -1, 49, 78, -1, 78, -1, 49, 81, -1, 81, + -1, 83, 49, 81, -1, 89, 11, 92, 49, 83, + -1, 86, 49, 84, -1, 86, 49, 92, 49, 84, + -1, 49, 79, -1, 79, -1, 10, 89, -1, 60, + -1, 64, -1, 80, 49, 78, -1, 80, 49, 78, + 46, 36, -1, 80, 49, 78, -1, 80, 49, 78, + 46, 37, -1, 80, 49, -1, 80, -1, 80, 49, + 78, -1, 86, 49, 83, -1, 86, 49, 92, 49, + 83, -1, 82, 49, 78, 49, 92, -1, 83, 49, + 78, 49, 82, -1, 80, 49, 80, -1, 80, 49, + 80, -1, 82, -1, 86, -1, 81, -1, 88, -1, + 10, 82, -1, 10, 87, -1, 82, -1, 87, -1, + 83, -1, 78, -1, 83, -1, 92, 50, 33, 51, + -1, 43, 90, -1, 35, -1, 38, -1, 36, -1, + 39, -1, 42, -1, 37, -1, 52, 92, -1, 52, + 89, -1, 52, 41, -1, 52, 40, -1, 52, 50, + 40, 51, -1, 52, 50, 9, 40, 51, -1, 52, + 9, 40, -1, 52, 85, -1, 31, -1, 9, 31, + -1, 31, 9, 31, -1, 9, 31, 9, 31, -1, + 87, -1, 88, -1, 92, -1, 92, 50, 36, 51, + -1, 92, 50, 42, 51, -1, 92, 50, 36, 10, + 92, 51, -1, 92, 50, 36, 51, 50, 36, 10, + 92, 51, -1, 92, 50, 36, 51, 50, 37, 10, + 92, 51, -1, 50, 36, 51, -1, 50, 42, 51, + -1, 92, 50, 37, 51, -1, 50, 36, 10, 92, + 51, -1, 50, 36, 51, 50, 36, 10, 92, 51, + -1, 89, -1, 89, 50, 36, 10, 92, 51, -1, + 43, 90, 50, 91, 51, -1, 43, 6, 7, 90, + 50, 34, 51, -1, -1, 8, 92, -1, 9, 92, + -1, 34, -1, 42, -1, 32, -1, 31, -1, 45, + -1, 9, 92, -1, 8, 92, -1, 53, 92, -1, + 50, 93, 51, -1, 92, -1, 93, 8, 93, -1, + 93, 9, 93, -1, 93, 10, 93, -1, 93, 11, + 93, -1, 93, 12, 93, -1, 93, 6, 6, 93, + -1, 93, 7, 7, 93, -1, 93, 5, 93, -1, + 93, 4, 93, -1, 93, 3, 93, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 69, 69, 71, 70, 78, 77, 85, 84, 90, - 91, 92, 95, 100, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 126, 130, 137, 144, 151, 156, 163, 168, - 175, 180, 185, 192, 200, 205, 213, 218, 223, 232, - 233, 236, 241, 251, 256, 266, 271, 276, 283, 288, - 296, 304, 314, 323, 334, 335, 338, 339, 340, 344, - 348, 349, 350, 353, 354, 357, 363, 371, 379, 384, - 389, 394, 399, 404, 411, 417, 428, 434, 440, 446, - 452, 460, 469, 474, 479, 484, 491, 492, 495, 501, - 507, 513, 522, 531, 540, 545, 550, 556, 564, 574, - 578, 587, 594, 603, 606, 610, 616, 617, 621, 624, - 625, 629, 633, 637, 641, 647, 648, 652, 656, 660, - 664, 668, 672, 676, 680, 684 + 0, 69, 69, 71, 70, 78, 77, 86, 87, 88, + 91, 96, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 122, 126, 133, 140, 147, 152, 159, 164, 171, 176, + 181, 188, 196, 202, 211, 216, 221, 230, 231, 234, + 239, 249, 254, 264, 269, 274, 281, 286, 294, 302, + 312, 321, 332, 333, 336, 337, 338, 342, 346, 347, + 348, 351, 352, 355, 361, 372, 377, 382, 387, 392, + 397, 404, 410, 421, 427, 433, 439, 445, 453, 462, + 467, 472, 477, 484, 485, 488, 494, 500, 506, 515, + 524, 533, 538, 543, 549, 557, 567, 571, 580, 587, + 596, 599, 603, 609, 610, 614, 617, 618, 622, 626, + 630, 634, 640, 641, 645, 649, 653, 657, 661, 665, + 669, 673, 677 }; #endif @@ -569,10 +568,10 @@ static const char *const yytname[] = "LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1", - "line", "@2", "@3", "inst", "nonnon", "rimrem", "remrim", "rimnon", - "nonrem", "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", - "spec7", "spec8", "spec9", "spec10", "spec11", "spec12", "rem", "rom", - "rim", "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem", "nam", + "line", "@2", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem", + "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7", + "spec8", "spec9", "spec10", "spec11", "spec12", "rem", "rom", "rim", + "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem", "nam", "offset", "pointer", "con", "expr", 0 }; #endif @@ -594,39 +593,39 @@ static const yytype_uint16 yytoknum[] = /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 54, 55, 56, 55, 58, 57, 59, 57, 57, - 57, 57, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 61, 61, 62, 63, 64, 64, 65, 65, - 66, 66, 66, 67, 68, 68, 69, 69, 69, 70, - 70, 71, 71, 72, 72, 73, 73, 73, 74, 74, - 75, 76, 77, 78, 79, 79, 80, 80, 80, 80, - 80, 80, 80, 81, 81, 82, 82, 82, 83, 83, - 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, - 84, 85, 86, 86, 86, 86, 87, 87, 88, 88, - 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, - 89, 90, 90, 91, 91, 91, 92, 92, 92, 93, - 93, 93, 93, 93, 93, 94, 94, 94, 94, 94, - 94, 94, 94, 94, 94, 94 + 0, 54, 55, 56, 55, 58, 57, 57, 57, 57, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 60, 60, 61, 62, 63, 63, 64, 64, 65, 65, + 65, 66, 67, 67, 68, 68, 68, 69, 69, 70, + 70, 71, 71, 72, 72, 72, 73, 73, 74, 75, + 76, 77, 78, 78, 79, 79, 79, 79, 79, 79, + 79, 80, 80, 81, 81, 82, 82, 82, 82, 82, + 82, 83, 83, 83, 83, 83, 83, 83, 84, 85, + 85, 85, 85, 86, 86, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 88, 88, 89, 89, + 90, 90, 90, 91, 91, 91, 92, 92, 92, 92, + 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 0, 0, 3, 0, 4, 0, 4, 1, - 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, + 0, 2, 0, 0, 3, 0, 4, 1, 2, 2, + 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 0, 1, 3, 3, 2, 1, 2, 1, - 2, 1, 3, 5, 3, 5, 2, 1, 2, 1, - 1, 3, 5, 3, 5, 2, 1, 3, 3, 5, - 5, 5, 3, 3, 1, 1, 1, 1, 2, 2, - 1, 1, 1, 1, 1, 4, 2, 2, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 2, 4, 5, - 3, 2, 1, 2, 3, 4, 1, 1, 1, 4, - 4, 6, 9, 9, 3, 3, 4, 5, 8, 1, - 6, 5, 7, 0, 2, 2, 1, 1, 1, 1, - 1, 2, 2, 2, 3, 1, 3, 3, 3, 3, - 3, 4, 4, 3, 3, 3 + 0, 1, 3, 3, 2, 1, 2, 1, 2, 1, + 3, 5, 3, 5, 2, 1, 2, 1, 1, 3, + 5, 3, 5, 2, 1, 3, 3, 5, 5, 5, + 3, 3, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 1, 4, 2, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 4, 5, 3, 2, 1, + 2, 3, 4, 1, 1, 1, 4, 4, 6, 9, + 9, 3, 3, 4, 5, 8, 1, 6, 5, 7, + 0, 2, 2, 1, 1, 1, 1, 1, 2, 2, + 2, 3, 1, 3, 3, 3, 3, 3, 4, 4, + 3, 3, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -634,89 +633,85 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 3, 1, 0, 0, 32, 0, 0, 0, 0, - 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9, 4, 0, 11, - 33, 14, 0, 0, 119, 78, 80, 83, 79, 81, - 82, 113, 120, 0, 0, 0, 15, 39, 64, 65, - 96, 97, 109, 98, 0, 16, 73, 37, 74, 17, - 0, 18, 0, 0, 113, 113, 0, 22, 47, 66, - 70, 72, 71, 67, 98, 20, 0, 33, 49, 50, - 23, 113, 0, 0, 19, 41, 0, 0, 21, 0, - 24, 0, 25, 0, 26, 56, 27, 0, 28, 0, - 29, 0, 30, 0, 31, 0, 7, 0, 5, 0, - 10, 122, 121, 0, 0, 0, 0, 38, 0, 0, - 125, 0, 123, 0, 0, 0, 87, 86, 0, 85, - 84, 36, 0, 0, 68, 69, 48, 76, 77, 0, - 46, 0, 0, 76, 40, 0, 0, 0, 0, 0, - 55, 0, 0, 0, 0, 0, 0, 12, 0, 13, - 113, 114, 115, 0, 0, 104, 105, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, - 0, 0, 90, 0, 0, 34, 35, 0, 0, 42, - 0, 44, 0, 51, 53, 57, 58, 0, 0, 0, - 62, 63, 8, 6, 0, 118, 116, 117, 0, 0, - 0, 135, 134, 133, 0, 0, 126, 127, 128, 129, - 130, 0, 0, 99, 106, 100, 0, 88, 75, 0, - 0, 92, 91, 0, 0, 0, 0, 0, 0, 0, - 111, 107, 0, 131, 132, 0, 0, 0, 89, 43, - 93, 0, 45, 52, 54, 59, 60, 61, 0, 0, - 110, 101, 0, 0, 0, 94, 112, 0, 0, 0, - 95, 108, 0, 0, 102, 103 + 2, 3, 1, 0, 0, 30, 0, 0, 0, 0, + 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 4, 0, 9, 31, + 12, 0, 0, 116, 75, 77, 80, 76, 78, 79, + 110, 117, 0, 0, 0, 13, 37, 62, 63, 93, + 94, 106, 95, 0, 14, 71, 35, 72, 15, 0, + 16, 0, 0, 110, 0, 20, 45, 64, 68, 70, + 69, 65, 95, 18, 0, 31, 47, 48, 21, 110, + 0, 0, 17, 39, 0, 0, 19, 0, 22, 0, + 23, 0, 24, 54, 25, 0, 26, 0, 27, 0, + 28, 0, 29, 0, 5, 0, 0, 8, 119, 118, + 0, 0, 0, 0, 36, 0, 0, 122, 0, 120, + 0, 0, 0, 84, 83, 0, 82, 81, 34, 0, + 0, 66, 67, 46, 74, 0, 44, 0, 0, 74, + 38, 0, 0, 0, 0, 0, 53, 0, 0, 0, + 0, 0, 0, 10, 11, 110, 111, 112, 0, 0, + 101, 102, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 121, 0, 0, 0, 0, 87, 0, 0, + 32, 33, 0, 0, 40, 0, 42, 0, 49, 51, + 55, 56, 0, 0, 0, 60, 61, 6, 0, 115, + 113, 114, 0, 0, 0, 132, 131, 130, 0, 0, + 123, 124, 125, 126, 127, 0, 0, 96, 103, 97, + 0, 85, 73, 0, 0, 89, 88, 0, 0, 0, + 0, 0, 0, 0, 108, 104, 0, 128, 129, 0, + 0, 0, 86, 41, 90, 0, 43, 50, 52, 57, + 58, 59, 0, 0, 107, 98, 0, 0, 0, 91, + 109, 0, 0, 0, 92, 105, 0, 0, 99, 100 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 3, 27, 158, 156, 28, 31, 59, 61, - 55, 46, 84, 75, 88, 67, 80, 90, 92, 94, - 96, 98, 100, 102, 104, 56, 68, 57, 69, 48, - 58, 191, 232, 49, 50, 51, 52, 116, 208, 53, - 121 + -1, 1, 3, 26, 152, 27, 30, 58, 60, 54, + 45, 82, 73, 86, 65, 78, 88, 90, 92, 94, + 96, 98, 100, 102, 55, 66, 56, 67, 47, 57, + 186, 226, 48, 49, 50, 51, 113, 202, 52, 118 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -104 +#define YYPACT_NINF -89 static const yytype_int16 yypact[] = { - -104, 4, -104, 173, -26, -25, 277, 297, 297, 349, - 225, -14, 329, 396, 18, 297, 297, 297, 18, 171, - -20, 297, 297, 2, -4, 26, -104, -104, 43, -104, - -104, -104, 478, 478, -104, -104, -104, -104, -104, -104, - -104, 111, -104, 349, 402, 478, -104, -104, -104, -104, - -104, -104, -12, -5, 83, -104, -104, 44, -104, -104, - 46, -104, 49, 349, 111, 113, 245, -104, -104, -104, - -104, -104, -104, -104, 50, -104, 100, 349, -104, -104, - -104, 113, 420, 478, -104, -104, 64, 66, -104, 78, - -104, 80, -104, 85, -104, 89, -104, 93, -104, 98, - -104, 101, -104, 112, -104, 121, -104, 478, -104, 478, - -104, -104, -104, 153, 478, 478, 135, -104, 8, 163, - -104, 74, -104, 179, 52, 427, -104, -104, 445, -104, - -104, -104, 349, 297, -104, -104, -104, 135, -104, 381, - -104, 33, 478, -104, -104, 420, 186, 451, 349, 349, - 349, 460, 349, 349, 297, 297, 173, 172, 173, 172, - 113, -104, -104, 5, 478, 180, -104, 478, 478, 478, - 226, 224, 478, 478, 478, 478, 478, -104, 235, 36, - 195, 196, -104, 466, 197, -104, -104, 199, 202, -104, - 21, -104, 203, 211, 219, -104, -104, 217, 222, 223, - -104, -104, -104, -104, 229, -104, -104, -104, 240, 241, - 237, 232, 527, 534, 478, 478, 134, 134, -104, -104, - -104, 478, 478, 243, -104, -104, 248, -104, -104, -20, - 263, 287, -104, 249, 264, 265, -20, 478, 171, 269, - -104, -104, 294, 214, 214, 256, 258, 119, -104, -104, - 301, 280, -104, -104, -104, -104, -104, -104, 266, 478, - -104, -104, 308, 311, 292, -104, -104, 273, 478, 478, - -104, -104, 274, 278, -104, -104 + -89, 8, -89, 211, -33, -23, 288, 308, 308, 360, + 236, -11, 340, 54, 41, 308, 308, 308, 41, 106, + -13, 308, 308, 62, -4, -89, -89, 45, -89, -89, + -89, 484, 484, -89, -89, -89, -89, -89, -89, -89, + 81, -89, 360, 413, 484, -89, -89, -89, -89, -89, + -89, 38, 48, 407, -89, -89, -2, -89, -89, 64, + -89, 78, 360, 81, 256, -89, -89, -89, -89, -89, + -89, -89, 61, -89, 107, 360, -89, -89, -89, 59, + 431, 484, -89, -89, 86, 79, -89, 87, -89, 89, + -89, 91, -89, 97, -89, 102, -89, 116, -89, 120, + -89, 148, -89, 151, -89, 484, 484, -89, -89, -89, + 123, 484, 484, 105, -89, 1, 150, -89, 169, -89, + 166, 9, 69, -89, -89, 456, -89, -89, -89, 360, + 308, -89, -89, -89, 105, 392, -89, -17, 484, -89, + -89, 431, 170, 460, 360, 360, 360, 469, 360, 360, + 308, 308, 211, 179, 179, 59, -89, -89, 6, 484, + 154, -89, 484, 484, 484, 201, 149, 484, 484, 484, + 484, 484, -89, 198, 13, 158, 159, -89, 480, 160, + -89, -89, 162, 165, -89, 0, -89, 167, 171, 172, + -89, -89, 193, 199, 200, -89, -89, -89, 197, -89, + -89, -89, 168, 204, 214, 534, 542, 549, 484, 484, + 113, 113, -89, -89, -89, 484, 484, 207, -89, -89, + 208, -89, -89, -13, 220, 251, -89, 209, 226, 231, + -13, 484, 106, 229, -89, -89, 259, 184, 184, 219, + 225, 80, -89, -89, 268, 249, -89, -89, -89, -89, + -89, -89, 232, 484, -89, -89, 272, 274, 269, -89, + -89, 239, 484, 484, -89, -89, 252, 253, -89, -89 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -104, -104, -104, -103, -104, -104, -104, 319, -104, -104, - -104, 331, -104, -104, -104, -104, -104, -104, -104, -104, - -104, -104, -104, -104, -104, 19, 275, -2, -6, -9, - -8, 115, -104, 22, 1, -1, -3, -48, -104, -10, - -66 + -89, -89, -89, 153, -89, -89, 290, -89, -89, -89, + 295, -89, -89, -89, -89, -89, -89, -89, -89, -89, + -89, -89, -89, -89, 18, 246, 20, -7, -9, -8, + 84, -89, 51, -3, -6, 4, -50, -89, -10, -88 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -726,120 +721,124 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint16 yytable[] = { - 74, 70, 71, 87, 2, 86, 60, 85, 76, 73, - 99, 72, 101, 91, 93, 95, 137, 138, 164, 103, - 105, 29, 111, 112, 30, 47, 32, 33, 62, 41, - 230, 47, 54, 143, 120, 122, 89, 205, 123, 206, - 97, 157, 108, 159, 130, 124, 222, 207, 106, 34, - 107, 129, 231, 202, 134, 203, 74, 70, 71, 165, - 136, 41, 117, 42, 135, 73, 187, 72, 44, 179, - 180, 45, 87, 120, 109, 181, 144, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 223, 179, 180, - 110, 32, 125, 131, 181, 132, 117, 120, 133, 120, - 141, 211, 212, 213, 161, 162, 216, 217, 218, 219, - 220, 142, 204, 145, 34, 112, 146, 113, 120, 114, - 115, 114, 115, 126, 127, 177, 41, 147, 42, 148, - 134, 186, 188, 128, 149, 87, 45, 192, 150, 189, - 135, 197, 151, 196, 174, 175, 176, 152, 243, 244, - 153, 185, 200, 201, 209, 262, 263, 120, 120, 120, - 160, 154, 120, 120, 120, 120, 120, 193, 194, 195, - 155, 198, 199, 112, 4, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 163, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 120, 120, 35, 36, 37, 38, - 39, 245, 246, 40, 166, 178, 23, 24, 25, 187, - 26, 249, 172, 173, 174, 175, 176, 256, 255, 257, - 210, 215, 214, 32, 33, 63, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 221, 224, 225, 227, 267, - 228, 229, 233, 32, 33, 139, 34, 234, 272, 273, - 35, 36, 37, 38, 39, 235, 236, 40, 64, 65, - 42, 237, 238, 242, 66, 44, 34, 54, 45, 239, - 35, 36, 37, 38, 39, 32, 33, 40, 64, 65, - 42, 240, 241, 247, 250, 44, 251, 54, 45, 248, - 253, 190, 254, 258, 259, 32, 33, 260, 34, 261, - 264, 265, 35, 36, 37, 38, 39, 266, 268, 40, - 41, 269, 42, 270, 271, 274, 43, 44, 34, 275, - 45, 78, 35, 36, 37, 38, 39, 32, 33, 40, - 41, 140, 42, 79, 0, 0, 0, 44, 252, 54, - 45, 0, 0, 0, 0, 0, 0, 32, 33, 0, - 34, 0, 0, 0, 35, 36, 37, 38, 39, 0, - 0, 40, 41, 0, 42, 0, 0, 0, 77, 44, - 34, 0, 45, 0, 35, 36, 37, 38, 39, 32, - 33, 40, 41, 0, 42, 0, 0, 0, 0, 44, - 0, 0, 45, 0, 32, 33, 0, 0, 0, 0, - 32, 33, 34, 0, 0, 0, 35, 36, 37, 38, - 39, 0, 0, 40, 0, 0, 42, 34, 32, 33, - 0, 44, 0, 34, 45, 32, 33, 0, 118, 81, - 65, 42, 0, 0, 119, 82, 83, 42, 54, 45, - 0, 34, 83, 32, 183, 45, 0, 0, 34, 32, - 33, 0, 0, 81, 65, 42, 0, 182, 32, 33, - 83, 0, 42, 45, 32, 33, 34, 83, 0, 0, - 45, 0, 34, 0, 0, 184, 32, 33, 0, 0, - 42, 34, 0, 0, 0, 83, 42, 34, 45, 0, - 0, 83, 0, 190, 45, 42, 226, 0, 0, 34, - 83, 42, 54, 45, 0, 0, 83, 0, 0, 45, - 0, 0, 0, 42, 0, 0, 0, 0, 83, 0, - 0, 45, 169, 170, 171, 172, 173, 174, 175, 176, - 170, 171, 172, 173, 174, 175, 176 + 72, 68, 69, 85, 71, 84, 83, 70, 2, 224, + 97, 159, 99, 134, 28, 74, 182, 153, 154, 174, + 175, 108, 109, 216, 46, 176, 29, 61, 59, 139, + 46, 225, 40, 117, 119, 89, 91, 93, 199, 53, + 200, 101, 103, 127, 106, 174, 175, 128, 201, 31, + 32, 176, 160, 131, 72, 68, 69, 126, 71, 132, + 114, 70, 31, 32, 217, 87, 133, 111, 112, 95, + 85, 117, 33, 140, 205, 206, 207, 31, 32, 210, + 211, 212, 213, 214, 40, 33, 41, 110, 120, 111, + 112, 43, 107, 114, 44, 117, 117, 79, 121, 41, + 33, 156, 157, 80, 81, 198, 53, 44, 104, 177, + 105, 137, 109, 129, 41, 117, 256, 257, 138, 81, + 237, 238, 44, 169, 170, 171, 131, 130, 183, 142, + 155, 85, 132, 187, 184, 141, 143, 192, 144, 191, + 145, 34, 35, 36, 37, 38, 146, 180, 39, 203, + 181, 147, 117, 117, 117, 158, 209, 117, 117, 117, + 117, 117, 188, 189, 190, 148, 193, 194, 109, 149, + 195, 196, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 167, 168, 169, 170, 171, 150, 117, 117, + 151, 161, 173, 182, 204, 239, 240, 208, 215, 218, + 219, 221, 4, 222, 223, 243, 227, 228, 229, 234, + 172, 250, 249, 251, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 230, 261, 31, 32, 62, 233, 231, 232, + 236, 244, 266, 267, 23, 235, 24, 241, 25, 242, + 245, 185, 247, 252, 31, 32, 135, 33, 248, 253, + 254, 34, 35, 36, 37, 38, 255, 258, 39, 63, + 259, 41, 262, 260, 263, 64, 43, 33, 53, 44, + 265, 34, 35, 36, 37, 38, 31, 32, 39, 63, + 264, 41, 76, 268, 269, 197, 43, 77, 53, 44, + 136, 246, 0, 0, 0, 0, 31, 32, 0, 33, + 0, 0, 0, 34, 35, 36, 37, 38, 0, 0, + 39, 40, 0, 41, 0, 0, 0, 42, 43, 33, + 0, 44, 0, 34, 35, 36, 37, 38, 31, 32, + 39, 40, 0, 41, 0, 0, 0, 0, 43, 0, + 53, 44, 0, 0, 0, 0, 0, 0, 31, 32, + 0, 33, 0, 0, 0, 34, 35, 36, 37, 38, + 0, 0, 39, 40, 0, 41, 0, 0, 0, 75, + 43, 33, 0, 44, 0, 34, 35, 36, 37, 38, + 31, 32, 39, 40, 0, 41, 0, 0, 0, 0, + 43, 0, 0, 44, 0, 31, 122, 0, 0, 0, + 0, 31, 32, 33, 0, 0, 0, 34, 35, 36, + 37, 38, 0, 0, 39, 0, 0, 41, 33, 31, + 32, 0, 43, 0, 33, 44, 0, 123, 124, 115, + 40, 0, 41, 0, 0, 116, 0, 125, 41, 0, + 44, 0, 33, 81, 31, 178, 44, 0, 31, 32, + 0, 0, 0, 0, 79, 0, 41, 31, 32, 0, + 0, 81, 0, 0, 44, 0, 0, 33, 31, 32, + 0, 33, 31, 32, 0, 0, 179, 0, 0, 0, + 33, 41, 0, 0, 0, 41, 81, 0, 0, 44, + 81, 33, 185, 44, 41, 33, 0, 0, 0, 81, + 220, 53, 44, 0, 0, 41, 0, 0, 0, 41, + 81, 0, 0, 44, 81, 0, 0, 44, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 164, 165, 166, + 167, 168, 169, 170, 171, 165, 166, 167, 168, 169, + 170, 171 }; static const yytype_int16 yycheck[] = { - 10, 10, 10, 13, 0, 13, 8, 13, 11, 10, - 19, 10, 20, 15, 16, 17, 64, 65, 10, 21, - 22, 47, 32, 33, 49, 6, 8, 9, 9, 43, - 9, 12, 52, 81, 44, 45, 14, 32, 50, 34, - 18, 107, 46, 109, 54, 50, 10, 42, 46, 31, - 48, 54, 31, 156, 63, 158, 66, 66, 66, 51, - 63, 43, 43, 45, 63, 66, 33, 66, 50, 36, - 37, 53, 82, 83, 48, 42, 82, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 51, 36, 37, - 47, 8, 9, 49, 42, 49, 77, 107, 49, 109, - 50, 167, 168, 169, 114, 115, 172, 173, 174, 175, - 176, 11, 160, 49, 31, 125, 50, 6, 128, 8, - 9, 8, 9, 40, 41, 51, 43, 49, 45, 49, - 139, 133, 142, 50, 49, 145, 53, 147, 49, 145, - 139, 151, 49, 151, 10, 11, 12, 49, 214, 215, - 49, 132, 154, 155, 164, 36, 37, 167, 168, 169, - 7, 49, 172, 173, 174, 175, 176, 148, 149, 150, - 49, 152, 153, 183, 1, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 50, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 214, 215, 35, 36, 37, 38, - 39, 221, 222, 42, 51, 36, 43, 44, 45, 33, - 47, 229, 8, 9, 10, 11, 12, 237, 236, 238, - 50, 7, 6, 8, 9, 10, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 10, 51, 51, 51, 259, - 51, 49, 49, 8, 9, 10, 31, 46, 268, 269, - 35, 36, 37, 38, 39, 46, 49, 42, 43, 44, - 45, 49, 49, 36, 49, 50, 31, 52, 53, 50, - 35, 36, 37, 38, 39, 8, 9, 42, 43, 44, - 45, 51, 51, 50, 31, 50, 9, 52, 53, 51, - 36, 52, 37, 34, 10, 8, 9, 51, 31, 51, - 9, 31, 35, 36, 37, 38, 39, 51, 10, 42, - 43, 10, 45, 31, 51, 51, 49, 50, 31, 51, - 53, 12, 35, 36, 37, 38, 39, 8, 9, 42, - 43, 66, 45, 12, -1, -1, -1, 50, 233, 52, - 53, -1, -1, -1, -1, -1, -1, 8, 9, -1, - 31, -1, -1, -1, 35, 36, 37, 38, 39, -1, - -1, 42, 43, -1, 45, -1, -1, -1, 49, 50, - 31, -1, 53, -1, 35, 36, 37, 38, 39, 8, - 9, 42, 43, -1, 45, -1, -1, -1, -1, 50, - -1, -1, 53, -1, 8, 9, -1, -1, -1, -1, - 8, 9, 31, -1, -1, -1, 35, 36, 37, 38, - 39, -1, -1, 42, -1, -1, 45, 31, 8, 9, - -1, 50, -1, 31, 53, 8, 9, -1, 36, 43, - 44, 45, -1, -1, 42, 49, 50, 45, 52, 53, - -1, 31, 50, 8, 9, 53, -1, -1, 31, 8, - 9, -1, -1, 43, 44, 45, -1, 40, 8, 9, - 50, -1, 45, 53, 8, 9, 31, 50, -1, -1, - 53, -1, 31, -1, -1, 40, 8, 9, -1, -1, - 45, 31, -1, -1, -1, 50, 45, 31, 53, -1, - -1, 50, -1, 52, 53, 45, 40, -1, -1, 31, - 50, 45, 52, 53, -1, -1, 50, -1, -1, 53, - -1, -1, -1, 45, -1, -1, -1, -1, 50, -1, - -1, 53, 5, 6, 7, 8, 9, 10, 11, 12, - 6, 7, 8, 9, 10, 11, 12 + 10, 10, 10, 13, 10, 13, 13, 10, 0, 9, + 19, 10, 20, 63, 47, 11, 33, 105, 106, 36, + 37, 31, 32, 10, 6, 42, 49, 9, 8, 79, + 12, 31, 43, 43, 44, 15, 16, 17, 32, 52, + 34, 21, 22, 53, 48, 36, 37, 49, 42, 8, + 9, 42, 51, 62, 64, 64, 64, 53, 64, 62, + 42, 64, 8, 9, 51, 14, 62, 8, 9, 18, + 80, 81, 31, 80, 162, 163, 164, 8, 9, 167, + 168, 169, 170, 171, 43, 31, 45, 6, 50, 8, + 9, 50, 47, 75, 53, 105, 106, 43, 50, 45, + 31, 111, 112, 49, 50, 155, 52, 53, 46, 40, + 48, 50, 122, 49, 45, 125, 36, 37, 11, 50, + 208, 209, 53, 10, 11, 12, 135, 49, 138, 50, + 7, 141, 135, 143, 141, 49, 49, 147, 49, 147, + 49, 35, 36, 37, 38, 39, 49, 129, 42, 159, + 130, 49, 162, 163, 164, 50, 7, 167, 168, 169, + 170, 171, 144, 145, 146, 49, 148, 149, 178, 49, + 150, 151, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 8, 9, 10, 11, 12, 49, 208, 209, + 49, 51, 36, 33, 50, 215, 216, 6, 10, 51, + 51, 51, 1, 51, 49, 223, 49, 46, 46, 51, + 51, 231, 230, 232, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 49, 253, 8, 9, 10, 50, 49, 49, + 36, 31, 262, 263, 43, 51, 45, 50, 47, 51, + 9, 52, 36, 34, 8, 9, 10, 31, 37, 10, + 51, 35, 36, 37, 38, 39, 51, 9, 42, 43, + 31, 45, 10, 51, 10, 49, 50, 31, 52, 53, + 51, 35, 36, 37, 38, 39, 8, 9, 42, 43, + 31, 45, 12, 51, 51, 152, 50, 12, 52, 53, + 64, 227, -1, -1, -1, -1, 8, 9, -1, 31, + -1, -1, -1, 35, 36, 37, 38, 39, -1, -1, + 42, 43, -1, 45, -1, -1, -1, 49, 50, 31, + -1, 53, -1, 35, 36, 37, 38, 39, 8, 9, + 42, 43, -1, 45, -1, -1, -1, -1, 50, -1, + 52, 53, -1, -1, -1, -1, -1, -1, 8, 9, + -1, 31, -1, -1, -1, 35, 36, 37, 38, 39, + -1, -1, 42, 43, -1, 45, -1, -1, -1, 49, + 50, 31, -1, 53, -1, 35, 36, 37, 38, 39, + 8, 9, 42, 43, -1, 45, -1, -1, -1, -1, + 50, -1, -1, 53, -1, 8, 9, -1, -1, -1, + -1, 8, 9, 31, -1, -1, -1, 35, 36, 37, + 38, 39, -1, -1, 42, -1, -1, 45, 31, 8, + 9, -1, 50, -1, 31, 53, -1, 40, 41, 36, + 43, -1, 45, -1, -1, 42, -1, 50, 45, -1, + 53, -1, 31, 50, 8, 9, 53, -1, 8, 9, + -1, -1, -1, -1, 43, -1, 45, 8, 9, -1, + -1, 50, -1, -1, 53, -1, -1, 31, 8, 9, + -1, 31, 8, 9, -1, -1, 40, -1, -1, -1, + 31, 45, -1, -1, -1, 45, 50, -1, -1, 53, + 50, 31, 52, 53, 45, 31, -1, -1, -1, 50, + 40, 52, 53, -1, -1, 45, -1, -1, -1, 45, + 50, -1, -1, 53, 50, -1, -1, 53, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 5, 6, 7, + 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, + 11, 12 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -848,32 +847,31 @@ static const yytype_uint8 yystos[] = { 0, 55, 0, 56, 1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 43, 44, 45, 47, 57, 60, 47, - 49, 61, 8, 9, 31, 35, 36, 37, 38, 39, - 42, 43, 45, 49, 50, 53, 65, 79, 83, 87, - 88, 89, 90, 93, 52, 64, 79, 81, 84, 62, - 81, 63, 79, 10, 43, 44, 49, 69, 80, 82, - 83, 84, 88, 89, 93, 67, 90, 49, 61, 65, - 70, 43, 49, 50, 66, 82, 84, 93, 68, 87, - 71, 81, 72, 81, 73, 81, 74, 87, 75, 83, - 76, 84, 77, 81, 78, 81, 46, 48, 46, 48, - 47, 93, 93, 6, 8, 9, 91, 79, 36, 42, - 93, 94, 93, 50, 50, 9, 40, 41, 50, 90, - 93, 49, 49, 49, 83, 88, 90, 91, 91, 10, - 80, 50, 11, 91, 82, 49, 50, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 59, 94, 58, 94, - 7, 93, 93, 50, 10, 51, 51, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 51, 36, 36, - 37, 42, 40, 9, 40, 79, 81, 33, 93, 82, - 52, 85, 93, 79, 79, 79, 84, 93, 79, 79, - 81, 81, 57, 57, 91, 32, 34, 42, 92, 93, - 50, 94, 94, 94, 6, 7, 94, 94, 94, 94, - 94, 10, 10, 51, 51, 51, 40, 51, 51, 49, - 9, 31, 86, 49, 46, 46, 49, 49, 49, 50, - 51, 51, 36, 94, 94, 93, 93, 50, 51, 84, - 31, 9, 85, 36, 37, 84, 93, 83, 34, 10, - 51, 51, 36, 37, 9, 31, 51, 93, 10, 10, - 31, 51, 93, 93, 51, 51 + 28, 29, 30, 43, 45, 47, 57, 59, 47, 49, + 60, 8, 9, 31, 35, 36, 37, 38, 39, 42, + 43, 45, 49, 50, 53, 64, 78, 82, 86, 87, + 88, 89, 92, 52, 63, 78, 80, 83, 61, 80, + 62, 78, 10, 43, 49, 68, 79, 81, 82, 83, + 87, 88, 92, 66, 89, 49, 60, 64, 69, 43, + 49, 50, 65, 81, 83, 92, 67, 86, 70, 80, + 71, 80, 72, 80, 73, 86, 74, 82, 75, 83, + 76, 80, 77, 80, 46, 48, 48, 47, 92, 92, + 6, 8, 9, 90, 78, 36, 42, 92, 93, 92, + 50, 50, 9, 40, 41, 50, 89, 92, 49, 49, + 49, 82, 87, 89, 90, 10, 79, 50, 11, 90, + 81, 49, 50, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 58, 93, 93, 7, 92, 92, 50, 10, + 51, 51, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 51, 36, 36, 37, 42, 40, 9, 40, + 78, 80, 33, 92, 81, 52, 84, 92, 78, 78, + 78, 83, 92, 78, 78, 80, 80, 57, 90, 32, + 34, 42, 91, 92, 50, 93, 93, 93, 6, 7, + 93, 93, 93, 93, 93, 10, 10, 51, 51, 51, + 40, 51, 51, 49, 9, 31, 85, 49, 46, 46, + 49, 49, 49, 50, 51, 51, 36, 93, 93, 92, + 92, 50, 51, 83, 31, 9, 84, 36, 37, 83, + 92, 82, 34, 10, 51, 51, 36, 37, 9, 31, + 51, 92, 10, 10, 31, 51, 92, 92, 51, 51 }; #define yyerrok (yyerrstatus = 0) @@ -1697,30 +1695,24 @@ yyreduce: case 5: #line 78 "a.y" { - if((yyvsp[(1) - (2)].sym)->value != pc) - yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->name); - (yyvsp[(1) - (2)].sym)->value = pc; - } - break; - - case 7: -#line 85 "a.y" - { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); + if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc) + yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname); (yyvsp[(1) - (2)].sym)->type = LLAB; (yyvsp[(1) - (2)].sym)->value = pc; } break; - case 12: -#line 96 "a.y" + case 10: +#line 92 "a.y" { (yyvsp[(1) - (3)].sym)->type = LVAR; (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval); } break; - case 13: -#line 101 "a.y" + case 11: +#line 97 "a.y" { if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval)) yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name); @@ -1728,186 +1720,186 @@ yyreduce: } break; + case 12: +#line 102 "a.y" + { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } + break; + + case 13: +#line 103 "a.y" + { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } + break; + case 14: -#line 106 "a.y" +#line 104 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 15: -#line 107 "a.y" +#line 105 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 16: -#line 108 "a.y" +#line 106 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 17: -#line 109 "a.y" +#line 107 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 18: -#line 110 "a.y" +#line 108 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 19: -#line 111 "a.y" +#line 109 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 20: -#line 112 "a.y" +#line 110 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 21: -#line 113 "a.y" +#line 111 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 22: -#line 114 "a.y" +#line 112 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 23: -#line 115 "a.y" +#line 113 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 24: -#line 116 "a.y" +#line 114 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 25: -#line 117 "a.y" +#line 115 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 26: -#line 118 "a.y" +#line 116 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 27: -#line 119 "a.y" +#line 117 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 28: -#line 120 "a.y" +#line 118 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 29: -#line 121 "a.y" +#line 119 "a.y" { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } break; case 30: #line 122 "a.y" - { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } - break; - - case 31: -#line 123 "a.y" - { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); } - break; - - case 32: -#line 126 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = nullgen; } break; - case 33: -#line 131 "a.y" + case 31: +#line 127 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = nullgen; } break; - case 34: -#line 138 "a.y" + case 32: +#line 134 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 35: -#line 145 "a.y" + case 33: +#line 141 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 36: -#line 152 "a.y" + case 34: +#line 148 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (2)].addr); (yyval.addr2).to = nullgen; } break; - case 37: -#line 157 "a.y" + case 35: +#line 153 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (1)].addr); (yyval.addr2).to = nullgen; } break; - case 38: -#line 164 "a.y" + case 36: +#line 160 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); } break; - case 39: -#line 169 "a.y" + case 37: +#line 165 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); } break; - case 40: -#line 176 "a.y" + case 38: +#line 172 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); } break; - case 41: -#line 181 "a.y" + case 39: +#line 177 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); } break; - case 42: -#line 186 "a.y" + case 40: +#line 182 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 43: -#line 193 "a.y" + case 41: +#line 189 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval); @@ -1915,41 +1907,43 @@ yyreduce: } break; - case 44: -#line 201 "a.y" + case 42: +#line 197 "a.y" { + settext((yyvsp[(1) - (3)].addr).sym); (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 45: -#line 206 "a.y" + case 43: +#line 203 "a.y" { + settext((yyvsp[(1) - (5)].addr).sym); (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval); (yyval.addr2).to = (yyvsp[(5) - (5)].addr); } break; - case 46: -#line 214 "a.y" + case 44: +#line 212 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); } break; - case 47: -#line 219 "a.y" + case 45: +#line 217 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); } break; - case 48: -#line 224 "a.y" + case 46: +#line 222 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); @@ -1958,16 +1952,16 @@ yyreduce: } break; - case 51: -#line 237 "a.y" + case 49: +#line 235 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 52: -#line 242 "a.y" + case 50: +#line 240 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).to = (yyvsp[(3) - (5)].addr); @@ -1977,16 +1971,16 @@ yyreduce: } break; - case 53: -#line 252 "a.y" + case 51: +#line 250 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 54: -#line 257 "a.y" + case 52: +#line 255 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).to = (yyvsp[(3) - (5)].addr); @@ -1996,40 +1990,40 @@ yyreduce: } break; - case 55: -#line 267 "a.y" + case 53: +#line 265 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (2)].addr); (yyval.addr2).to = nullgen; } break; - case 56: -#line 272 "a.y" + case 54: +#line 270 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (1)].addr); (yyval.addr2).to = nullgen; } break; - case 57: -#line 277 "a.y" + case 55: +#line 275 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 58: -#line 284 "a.y" + case 56: +#line 282 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (3)].addr); (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; - case 59: -#line 289 "a.y" + case 57: +#line 287 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).from.scale = (yyvsp[(3) - (5)].lval); @@ -2037,8 +2031,8 @@ yyreduce: } break; - case 60: -#line 297 "a.y" + case 58: +#line 295 "a.y" { (yyval.addr2).from = (yyvsp[(1) - (5)].addr); (yyval.addr2).to = (yyvsp[(3) - (5)].addr); @@ -2046,8 +2040,8 @@ yyreduce: } break; - case 61: -#line 305 "a.y" + case 59: +#line 303 "a.y" { (yyval.addr2).from = (yyvsp[(3) - (5)].addr); (yyval.addr2).to = (yyvsp[(5) - (5)].addr); @@ -2057,8 +2051,8 @@ yyreduce: } break; - case 62: -#line 315 "a.y" + case 60: +#line 313 "a.y" { if((yyvsp[(1) - (3)].addr).type != D_CONST || (yyvsp[(3) - (3)].addr).type != D_CONST) yyerror("arguments to PCDATA must be integer constants"); @@ -2067,8 +2061,8 @@ yyreduce: } break; - case 63: -#line 324 "a.y" + case 61: +#line 322 "a.y" { if((yyvsp[(1) - (3)].addr).type != D_CONST) yyerror("index for FUNCDATA must be integer constant"); @@ -2079,22 +2073,22 @@ yyreduce: } break; - case 68: -#line 341 "a.y" + case 66: +#line 339 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); } break; - case 69: -#line 345 "a.y" + case 67: +#line 343 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); } break; - case 75: -#line 358 "a.y" + case 73: +#line 356 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_BRANCH; @@ -2102,76 +2096,68 @@ yyreduce: } break; - case 76: -#line 364 "a.y" - { - (yyval.addr) = nullgen; - if(pass == 2) - yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->name); - (yyval.addr).type = D_BRANCH; - (yyval.addr).offset = (yyvsp[(2) - (2)].lval); - } - break; - - case 77: -#line 372 "a.y" + case 74: +#line 362 "a.y" { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); (yyval.addr) = nullgen; + if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB) + yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname); (yyval.addr).type = D_BRANCH; (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval); } break; - case 78: -#line 380 "a.y" + case 75: +#line 373 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 79: -#line 385 "a.y" + case 76: +#line 378 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 80: -#line 390 "a.y" + case 77: +#line 383 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 81: -#line 395 "a.y" + case 78: +#line 388 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 82: -#line 400 "a.y" + case 79: +#line 393 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SP; } break; - case 83: -#line 405 "a.y" + case 80: +#line 398 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); } break; - case 84: -#line 412 "a.y" + case 81: +#line 405 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST; @@ -2179,8 +2165,8 @@ yyreduce: } break; - case 85: -#line 418 "a.y" + case 82: +#line 411 "a.y" { (yyval.addr) = (yyvsp[(2) - (2)].addr); (yyval.addr).index = (yyvsp[(2) - (2)].addr).type; @@ -2193,8 +2179,8 @@ yyreduce: } break; - case 86: -#line 429 "a.y" + case 83: +#line 422 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SCONST; @@ -2202,8 +2188,8 @@ yyreduce: } break; - case 87: -#line 435 "a.y" + case 84: +#line 428 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2211,8 +2197,8 @@ yyreduce: } break; - case 88: -#line 441 "a.y" + case 85: +#line 434 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2220,8 +2206,8 @@ yyreduce: } break; - case 89: -#line 447 "a.y" + case 86: +#line 440 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2229,8 +2215,8 @@ yyreduce: } break; - case 90: -#line 453 "a.y" + case 87: +#line 446 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -2238,8 +2224,8 @@ yyreduce: } break; - case 91: -#line 461 "a.y" + case 88: +#line 454 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST2; @@ -2248,40 +2234,40 @@ yyreduce: } break; - case 92: -#line 470 "a.y" + case 89: +#line 463 "a.y" { (yyval.con2).v1 = (yyvsp[(1) - (1)].lval); (yyval.con2).v2 = ArgsSizeUnknown; } break; - case 93: -#line 475 "a.y" + case 90: +#line 468 "a.y" { (yyval.con2).v1 = -(yyvsp[(2) - (2)].lval); (yyval.con2).v2 = ArgsSizeUnknown; } break; - case 94: -#line 480 "a.y" + case 91: +#line 473 "a.y" { (yyval.con2).v1 = (yyvsp[(1) - (3)].lval); (yyval.con2).v2 = (yyvsp[(3) - (3)].lval); } break; - case 95: -#line 485 "a.y" + case 92: +#line 478 "a.y" { (yyval.con2).v1 = -(yyvsp[(2) - (4)].lval); (yyval.con2).v2 = (yyvsp[(4) - (4)].lval); } break; - case 98: -#line 496 "a.y" + case 95: +#line 489 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_NONE; @@ -2289,8 +2275,8 @@ yyreduce: } break; - case 99: -#line 502 "a.y" + case 96: +#line 495 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval); @@ -2298,8 +2284,8 @@ yyreduce: } break; - case 100: -#line 508 "a.y" + case 97: +#line 501 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_SP; @@ -2307,8 +2293,8 @@ yyreduce: } break; - case 101: -#line 514 "a.y" + case 98: +#line 507 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_NONE; @@ -2319,8 +2305,8 @@ yyreduce: } break; - case 102: -#line 523 "a.y" + case 99: +#line 516 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval); @@ -2331,8 +2317,8 @@ yyreduce: } break; - case 103: -#line 532 "a.y" + case 100: +#line 525 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (9)].lval); @@ -2343,24 +2329,24 @@ yyreduce: } break; - case 104: -#line 541 "a.y" + case 101: +#line 534 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(2) - (3)].lval); } break; - case 105: -#line 546 "a.y" + case 102: +#line 539 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_SP; } break; - case 106: -#line 551 "a.y" + case 103: +#line 544 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(3) - (4)].lval); @@ -2368,8 +2354,8 @@ yyreduce: } break; - case 107: -#line 557 "a.y" + case 104: +#line 550 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+D_NONE; @@ -2379,8 +2365,8 @@ yyreduce: } break; - case 108: -#line 565 "a.y" + case 105: +#line 558 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_INDIR+(yyvsp[(2) - (8)].lval); @@ -2390,15 +2376,15 @@ yyreduce: } break; - case 109: -#line 575 "a.y" + case 106: +#line 568 "a.y" { (yyval.addr) = (yyvsp[(1) - (1)].addr); } break; - case 110: -#line 579 "a.y" + case 107: +#line 572 "a.y" { (yyval.addr) = (yyvsp[(1) - (6)].addr); (yyval.addr).index = (yyvsp[(3) - (6)].lval); @@ -2407,8 +2393,8 @@ yyreduce: } break; - case 111: -#line 588 "a.y" + case 108: +#line 581 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(4) - (5)].lval); @@ -2417,8 +2403,8 @@ yyreduce: } break; - case 112: -#line 595 "a.y" + case 109: +#line 588 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_STATIC; @@ -2427,134 +2413,134 @@ yyreduce: } break; - case 113: -#line 603 "a.y" + case 110: +#line 596 "a.y" { (yyval.lval) = 0; } break; - case 114: -#line 607 "a.y" + case 111: +#line 600 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 115: -#line 611 "a.y" + case 112: +#line 604 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 117: -#line 618 "a.y" + case 114: +#line 611 "a.y" { (yyval.lval) = D_AUTO; } break; - case 120: -#line 626 "a.y" + case 117: +#line 619 "a.y" { (yyval.lval) = (yyvsp[(1) - (1)].sym)->value; } break; - case 121: -#line 630 "a.y" + case 118: +#line 623 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 122: -#line 634 "a.y" + case 119: +#line 627 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 123: -#line 638 "a.y" + case 120: +#line 631 "a.y" { (yyval.lval) = ~(yyvsp[(2) - (2)].lval); } break; - case 124: -#line 642 "a.y" + case 121: +#line 635 "a.y" { (yyval.lval) = (yyvsp[(2) - (3)].lval); } break; - case 126: -#line 649 "a.y" + case 123: +#line 642 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval); } break; - case 127: -#line 653 "a.y" + case 124: +#line 646 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval); } break; - case 128: -#line 657 "a.y" + case 125: +#line 650 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval); } break; - case 129: -#line 661 "a.y" + case 126: +#line 654 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval); } break; - case 130: -#line 665 "a.y" + case 127: +#line 658 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval); } break; - case 131: -#line 669 "a.y" + case 128: +#line 662 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval); } break; - case 132: -#line 673 "a.y" + case 129: +#line 666 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval); } break; - case 133: -#line 677 "a.y" + case 130: +#line 670 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval); } break; - case 134: -#line 681 "a.y" + case 131: +#line 674 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval); } break; - case 135: -#line 685 "a.y" + case 132: +#line 678 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval); } @@ -2562,7 +2548,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 2566 "y.tab.c" +#line 2552 "y.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); diff --git a/src/cmd/9a/a.h b/src/cmd/9a/a.h index 629543f13..7a01fc947 100644 --- a/src/cmd/9a/a.h +++ b/src/cmd/9a/a.h @@ -68,6 +68,7 @@ struct Sym vlong value; ushort type; char *name; + char* labelname; char sym; }; #define S ((Sym*)0) @@ -135,6 +136,8 @@ void newio(void); void newfile(char*, int); Sym* slookup(char*); Sym* lookup(void); +Sym* labellookup(Sym*); +void settext(LSym*); void syminit(Sym*); int32 yylex(void); int getc(void); diff --git a/src/cmd/9a/a.y b/src/cmd/9a/a.y index 41776fd3c..b36614615 100644 --- a/src/cmd/9a/a.y +++ b/src/cmd/9a/a.y @@ -67,15 +67,11 @@ prog: | prog line line: - LLAB ':' - { - if($1->value != pc) - yyerror("redeclaration of %s", $1->name); - $1->value = pc; - } - line -| LNAME ':' + LNAME ':' { + $1 = labellookup($1); + if($1->type == LLAB && $1->value != pc) + yyerror("redeclaration of %s", $1->labelname); $1->type = LLAB; $1->value = pc; } @@ -623,16 +619,19 @@ inst: */ | LTEXT name ',' imm { + settext($2.sym); outcode($1, &$2, NREG, &$4); } | LTEXT name ',' con ',' imm { + settext($2.sym); $6.offset &= 0xffffffffull; $6.offset |= (vlong)ArgsSizeUnknown << 32; outcode($1, &$2, $4, &$6); } | LTEXT name ',' con ',' imm '-' con { + settext($2.sym); $6.offset &= 0xffffffffull; $6.offset |= ($8 & 0xffffffffull) << 32; outcode($1, &$2, $4, &$6); @@ -669,15 +668,10 @@ rel: } | LNAME offset { + $1 = labellookup($1); $$ = nullgen; - if(pass == 2) - yyerror("undefined label: %s", $1->name); - $$.type = D_BRANCH; - $$.offset = $2; - } -| LLAB offset - { - $$ = nullgen; + if(pass == 2 && $1->type != LLAB) + yyerror("undefined label: %s", $1->labelname); $$.type = D_BRANCH; $$.offset = $1->value + $2; } diff --git a/src/cmd/9a/y.tab.c b/src/cmd/9a/y.tab.c index e81db9924..6025a2402 100644 --- a/src/cmd/9a/y.tab.c +++ b/src/cmd/9a/y.tab.c @@ -1,21 +1,24 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - + the Free Software Foundation; either version 2, or (at your option) + any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -26,7 +29,7 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ @@ -44,7 +47,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -52,51 +55,11 @@ /* Pure parsers. */ #define YYPURE 0 -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - /* Using locations. */ #define YYLSP_NEEDED 0 -/* Copy the first part of user declarations. */ - -/* Line 268 of yacc.c */ -#line 30 "a.y" - -#include -#include /* if we don't, bison will, and a.h re-#defines getc */ -#include -#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 @@ -230,35 +193,59 @@ +/* Copy the first part of user declarations. */ +#line 30 "a.y" + +#include +#include /* if we don't, bison will, and a.h re-#defines getc */ +#include +#include "a.h" +#include "../../runtime/funcdata.h" + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -{ - -/* Line 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 +} +/* Line 193 of yacc.c. */ +#line 236 "y.tab.c" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif + /* Copy the second part of user declarations. */ -/* Line 343 of yacc.c */ -#line 262 "y.tab.c" +/* Line 216 of yacc.c. */ +#line 249 "y.tab.c" #ifdef short # undef short @@ -333,14 +320,14 @@ typedef short int yytype_int16; #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int -YYID (int yyi) +YYID (int i) #else static int -YYID (yyi) - int yyi; +YYID (i) + int i; #endif { - return yyi; + return i; } #endif @@ -361,11 +348,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # endif @@ -388,24 +375,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ +# if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 +# ifndef _STDLIB_H +# define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -421,9 +408,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; + yytype_int16 yyss; + YYSTYPE yyvs; + }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -434,27 +421,6 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY @@ -472,21 +438,38 @@ union yyalloc while (YYID (0)) # endif # endif -#endif /* !YYCOPY_NEEDED */ + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 836 +#define YYLAST 862 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 81 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 32 +#define YYNNTS 31 /* YYNRULES -- Number of rules. */ -#define YYNRULES 186 +#define YYNRULES 183 /* YYNRULES -- Number of states. */ -#define YYNSTATES 459 +#define YYNSTATES 453 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -537,140 +520,139 @@ static const yytype_uint8 yytranslate[] = 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 + 0, 0, 3, 4, 7, 8, 13, 18, 23, 26, + 28, 31, 34, 39, 44, 49, 54, 59, 64, 69, + 74, 79, 84, 89, 94, 99, 104, 109, 114, 119, + 124, 129, 134, 141, 146, 151, 156, 163, 168, 173, + 180, 187, 194, 199, 204, 211, 216, 223, 228, 235, + 240, 245, 248, 255, 260, 265, 270, 277, 282, 287, + 292, 297, 302, 307, 312, 317, 320, 323, 328, 332, + 336, 342, 347, 352, 359, 364, 369, 376, 383, 390, + 399, 404, 409, 413, 416, 421, 426, 433, 442, 447, + 454, 459, 464, 471, 478, 487, 496, 505, 514, 519, + 524, 529, 536, 541, 548, 553, 558, 561, 564, 568, + 572, 576, 580, 583, 587, 591, 596, 601, 604, 609, + 616, 625, 632, 639, 646, 649, 654, 657, 659, 661, + 663, 665, 667, 669, 671, 673, 678, 680, 682, 687, + 689, 694, 696, 701, 703, 707, 710, 713, 716, 720, + 723, 725, 730, 734, 740, 742, 747, 752, 758, 766, + 767, 769, 770, 773, 776, 778, 780, 782, 784, 786, + 789, 792, 795, 799, 801, 805, 809, 813, 817, 821, + 826, 831, 835, 839 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 82, 0, -1, -1, 82, 83, -1, -1, 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 + 82, 0, -1, -1, 82, 83, -1, -1, 70, 73, + 84, 83, -1, 70, 74, 111, 75, -1, 72, 74, + 111, 75, -1, 57, 75, -1, 75, -1, 85, 75, + -1, 1, 75, -1, 13, 87, 76, 87, -1, 13, + 105, 76, 87, -1, 13, 104, 76, 87, -1, 14, + 87, 76, 87, -1, 14, 105, 76, 87, -1, 14, + 104, 76, 87, -1, 22, 105, 76, 96, -1, 22, + 104, 76, 96, -1, 22, 101, 76, 96, -1, 22, + 96, 76, 96, -1, 22, 96, 76, 105, -1, 22, + 96, 76, 104, -1, 13, 87, 76, 105, -1, 13, + 87, 76, 104, -1, 14, 87, 76, 105, -1, 14, + 87, 76, 104, -1, 13, 96, 76, 105, -1, 13, + 96, 76, 104, -1, 13, 94, 76, 96, -1, 13, + 96, 76, 94, -1, 13, 96, 76, 102, 76, 94, + -1, 13, 94, 76, 97, -1, 13, 102, 76, 95, + -1, 66, 102, 76, 110, -1, 13, 87, 76, 102, + 76, 90, -1, 13, 87, 76, 97, -1, 13, 87, + 76, 90, -1, 18, 87, 76, 103, 76, 87, -1, + 18, 102, 76, 103, 76, 87, -1, 18, 87, 76, + 102, 76, 87, -1, 18, 87, 76, 87, -1, 18, + 102, 76, 87, -1, 16, 87, 76, 103, 76, 87, + -1, 16, 87, 76, 87, -1, 17, 87, 76, 103, + 76, 87, -1, 17, 87, 76, 87, -1, 17, 102, + 76, 103, 76, 87, -1, 17, 102, 76, 87, -1, + 15, 87, 76, 87, -1, 15, 87, -1, 67, 87, + 76, 103, 76, 87, -1, 13, 102, 76, 87, -1, + 13, 100, 76, 87, -1, 20, 98, 76, 98, -1, + 20, 98, 76, 110, 76, 98, -1, 13, 97, 76, + 97, -1, 13, 93, 76, 97, -1, 13, 90, 76, + 87, -1, 13, 93, 76, 87, -1, 13, 88, 76, + 87, -1, 13, 87, 76, 88, -1, 13, 97, 76, + 93, -1, 13, 87, 76, 93, -1, 21, 86, -1, + 21, 105, -1, 21, 77, 88, 78, -1, 21, 76, + 86, -1, 21, 76, 105, -1, 21, 76, 77, 88, + 78, -1, 21, 97, 76, 86, -1, 21, 97, 76, + 105, -1, 21, 97, 76, 77, 88, 78, -1, 21, + 110, 76, 86, -1, 21, 110, 76, 105, -1, 21, + 110, 76, 77, 88, 78, -1, 21, 110, 76, 110, + 76, 86, -1, 21, 110, 76, 110, 76, 105, -1, + 21, 110, 76, 110, 76, 77, 88, 78, -1, 27, + 87, 76, 103, -1, 27, 102, 76, 103, -1, 27, + 87, 107, -1, 27, 107, -1, 23, 96, 76, 96, + -1, 25, 96, 76, 96, -1, 25, 96, 76, 96, + 76, 96, -1, 26, 96, 76, 96, 76, 96, 76, + 96, -1, 24, 96, 76, 96, -1, 24, 96, 76, + 96, 76, 97, -1, 19, 87, 76, 87, -1, 19, + 87, 76, 102, -1, 19, 87, 76, 87, 76, 97, + -1, 19, 87, 76, 102, 76, 97, -1, 62, 102, + 76, 87, 76, 102, 76, 87, -1, 62, 102, 76, + 87, 76, 99, 76, 87, -1, 62, 87, 76, 87, + 76, 102, 76, 87, -1, 62, 87, 76, 87, 76, + 99, 76, 87, -1, 63, 105, 76, 87, -1, 63, + 87, 76, 105, -1, 58, 104, 76, 87, -1, 58, + 104, 76, 102, 76, 87, -1, 59, 87, 76, 104, + -1, 59, 87, 76, 102, 76, 104, -1, 61, 104, + 76, 87, -1, 61, 87, 76, 104, -1, 60, 104, + -1, 29, 107, -1, 29, 87, 107, -1, 29, 96, + 107, -1, 29, 76, 87, -1, 29, 76, 96, -1, + 29, 102, -1, 32, 102, 107, -1, 32, 100, 107, + -1, 55, 102, 76, 102, -1, 56, 102, 76, 105, + -1, 30, 107, -1, 33, 106, 76, 102, -1, 33, + 106, 76, 110, 76, 102, -1, 33, 106, 76, 110, + 76, 102, 9, 110, -1, 34, 106, 11, 110, 76, + 102, -1, 34, 106, 11, 110, 76, 100, -1, 34, + 106, 11, 110, 76, 101, -1, 35, 107, -1, 110, + 77, 40, 78, -1, 70, 108, -1, 103, -1, 89, + -1, 91, -1, 49, -1, 46, -1, 50, -1, 54, + -1, 52, -1, 51, 77, 110, 78, -1, 92, -1, + 48, -1, 48, 77, 110, 78, -1, 44, -1, 47, + 77, 110, 78, -1, 41, -1, 46, 77, 110, 78, + -1, 110, -1, 110, 76, 110, -1, 79, 105, -1, + 79, 69, -1, 79, 68, -1, 79, 9, 68, -1, + 79, 110, -1, 43, -1, 45, 77, 110, 78, -1, + 77, 103, 78, -1, 77, 103, 8, 103, 78, -1, + 106, -1, 110, 77, 103, 78, -1, 110, 77, 109, + 78, -1, 70, 108, 77, 109, 78, -1, 70, 6, + 7, 108, 77, 38, 78, -1, -1, 76, -1, -1, + 8, 110, -1, 9, 110, -1, 38, -1, 37, -1, + 39, -1, 36, -1, 72, -1, 9, 110, -1, 8, + 110, -1, 80, 110, -1, 77, 111, 78, -1, 110, + -1, 111, 8, 111, -1, 111, 9, 111, -1, 111, + 10, 111, -1, 111, 11, 111, -1, 111, 12, 111, + -1, 111, 6, 6, 111, -1, 111, 7, 7, 111, + -1, 111, 5, 111, -1, 111, 4, 111, -1, 111, + 3, 111, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 66, 66, 67, 71, 70, 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 + 0, 66, 66, 67, 71, 70, 79, 84, 90, 94, + 95, 96, 102, 106, 110, 114, 118, 122, 129, 133, + 137, 141, 145, 149, 156, 160, 164, 168, 175, 179, + 186, 190, 194, 198, 202, 206, 213, 217, 221, 231, + 235, 239, 243, 247, 251, 255, 259, 263, 267, 271, + 275, 279, 286, 293, 297, 304, 308, 316, 320, 324, + 328, 332, 336, 340, 344, 353, 357, 361, 365, 369, + 373, 377, 381, 385, 389, 393, 397, 401, 409, 417, + 428, 432, 436, 440, 447, 451, 455, 459, 463, 467, + 474, 478, 482, 486, 493, 497, 501, 505, 512, 516, + 524, 528, 532, 536, 540, 544, 548, 555, 559, 563, + 567, 571, 575, 582, 586, 593, 602, 613, 620, 625, + 632, 642, 646, 650, 657, 663, 669, 680, 688, 689, + 692, 700, 708, 716, 723, 729, 735, 738, 746, 754, + 760, 768, 774, 782, 790, 811, 816, 824, 830, 837, + 845, 846, 854, 861, 871, 872, 881, 889, 897, 906, + 907, 910, 913, 917, 923, 924, 925, 928, 929, 933, + 937, 941, 945, 951, 952, 956, 960, 964, 968, 972, + 976, 980, 984, 988 }; #endif @@ -689,10 +671,10 @@ static const char *const yytname[] = "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 + "@1", "inst", "rel", "rreg", "xlreg", "lr", "lcr", "ctr", "msr", "psr", + "fpscr", "fpscrf", "freg", "creg", "cbit", "mask", "ximm", "fimm", "imm", + "sreg", "regaddr", "addr", "name", "comma", "offset", "pointer", "con", + "expr", 0 }; #endif @@ -716,359 +698,360 @@ static const yytype_uint16 yytoknum[] = /* 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 + 0, 81, 82, 82, 84, 83, 83, 83, 83, 83, + 83, 83, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 86, 86, 87, 88, 88, + 89, 90, 91, 92, 93, 93, 93, 94, 95, 96, + 96, 97, 97, 98, 99, 100, 100, 101, 101, 102, + 103, 103, 104, 104, 105, 105, 106, 106, 106, 107, + 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, + 110, 110, 110, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 0, 2, 0, 4, 0, 4, 4, 4, - 2, 1, 2, 2, 4, 4, 4, 4, 4, 4, + 0, 2, 0, 2, 0, 4, 4, 4, 2, 1, + 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 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 + 4, 4, 6, 4, 4, 4, 6, 4, 4, 6, + 6, 6, 4, 4, 6, 4, 6, 4, 6, 4, + 4, 2, 6, 4, 4, 4, 6, 4, 4, 4, + 4, 4, 4, 4, 4, 2, 2, 4, 3, 3, + 5, 4, 4, 6, 4, 4, 6, 6, 6, 8, + 4, 4, 3, 2, 4, 4, 6, 8, 4, 6, + 4, 4, 6, 6, 8, 8, 8, 8, 4, 4, + 4, 6, 4, 6, 4, 4, 2, 2, 3, 3, + 3, 3, 2, 3, 3, 4, 4, 2, 4, 6, + 8, 6, 6, 6, 2, 4, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 4, 1, 1, 4, 1, + 4, 1, 4, 1, 3, 2, 2, 2, 3, 2, + 1, 4, 3, 5, 1, 4, 4, 5, 7, 0, + 1, 0, 2, 2, 1, 1, 1, 1, 1, 2, + 2, 2, 3, 1, 3, 3, 3, 3, 3, 4, + 4, 3, 3, 3 }; -/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 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, 159, 159, + 159, 0, 0, 0, 159, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 3, + 0, 11, 0, 0, 167, 141, 150, 139, 0, 131, + 0, 137, 130, 132, 0, 134, 133, 161, 168, 0, + 0, 0, 0, 0, 128, 0, 129, 136, 0, 0, + 0, 0, 0, 0, 127, 0, 0, 154, 0, 0, + 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 143, 0, 161, 0, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 160, 159, 0, 83, 160, 159, 159, 112, 107, 117, + 159, 159, 0, 0, 0, 124, 0, 0, 8, 0, + 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 10, 170, 169, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 173, 0, 146, 145, + 149, 171, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, + 0, 0, 0, 0, 0, 0, 126, 0, 68, 69, + 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 160, 82, 0, 110, 111, + 108, 109, 114, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 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 + 0, 0, 0, 0, 0, 0, 161, 162, 163, 0, + 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 172, 12, 62, 38, 64, 37, 0, 25, + 24, 61, 59, 60, 58, 30, 33, 31, 0, 29, + 28, 63, 57, 54, 0, 53, 34, 14, 13, 165, + 164, 166, 0, 0, 15, 27, 26, 17, 16, 50, + 45, 127, 47, 127, 49, 127, 42, 0, 127, 43, + 127, 90, 91, 55, 143, 0, 67, 0, 71, 72, + 0, 74, 75, 0, 0, 148, 21, 23, 22, 20, + 19, 18, 84, 88, 85, 0, 80, 81, 118, 0, + 0, 115, 116, 100, 0, 0, 102, 105, 104, 0, + 0, 99, 98, 35, 0, 5, 6, 7, 151, 142, + 140, 135, 0, 0, 0, 183, 182, 181, 0, 0, + 174, 175, 176, 177, 178, 0, 0, 0, 155, 156, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, + 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 157, 153, 179, 180, 131, + 36, 32, 0, 44, 46, 48, 41, 39, 40, 92, + 93, 56, 73, 76, 0, 77, 78, 89, 86, 0, + 119, 0, 122, 123, 121, 101, 103, 0, 0, 0, + 0, 0, 52, 0, 138, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 158, 79, 87, 120, 97, 96, + 144, 95, 94 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 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 + -1, 1, 39, 229, 40, 97, 62, 63, 64, 65, + 66, 67, 68, 69, 276, 70, 71, 91, 427, 72, + 103, 73, 74, 75, 159, 77, 113, 154, 283, 156, + 157 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -178 +#define YYPACT_NINF -176 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 + -176, 464, -176, -63, 560, 637, 97, 97, -24, -24, + 97, 556, 317, 618, 12, 12, 12, 12, -27, 47, + -47, -29, 725, 725, -47, -26, -26, -43, -17, 97, + -17, -23, -24, 658, -26, 97, 51, -11, -176, -176, + -2, -176, 556, 556, -176, -176, -176, -176, -1, 2, + 11, -176, -176, -176, 24, -176, -176, 91, -176, 26, + 716, 556, 57, 65, -176, 85, -176, -176, 92, 98, + 104, 110, 119, 134, -176, 155, 160, -176, 69, 162, + 165, 170, 172, 176, 556, 179, 180, 182, 183, 185, + 556, 187, -176, 2, 91, 736, 326, -176, 196, -176, + 52, 6, 197, 198, 202, 203, 215, 216, 217, 222, + -176, 223, 235, -176, 73, -47, -47, -176, -176, -176, + -47, -47, 239, 79, 178, -176, 240, 246, -176, 97, + 247, 248, -176, 252, 253, 255, 262, 263, 266, 267, + 268, -176, 556, 556, -176, -176, -176, 556, 556, 556, + 556, 193, 556, 556, 166, 9, -176, 278, -176, -176, + 69, -176, 607, 97, 97, 109, 20, 683, 61, 97, + 27, 97, 97, 340, 637, 97, 97, 97, 97, -176, + 97, 97, -24, 97, -24, 556, 166, 326, -176, -176, + 199, 152, 742, 762, 153, 283, -176, 696, 12, 12, + 12, 12, 12, 12, 12, 97, -176, 97, -176, -176, + -176, -176, -176, -176, 382, 4, 556, -26, 725, -24, + 72, -17, 97, 97, 97, 725, 97, 556, 97, 527, + 436, 567, 274, 276, 277, 279, 154, -176, -176, 4, + 97, -176, 556, 556, 556, 353, 339, 556, 556, 556, + 556, 556, -176, -176, -176, -176, -176, -176, 284, -176, + -176, -176, -176, -176, -176, -176, -176, -176, 295, -176, + -176, -176, -176, -176, 303, -176, -176, -176, -176, -176, + -176, -176, 304, 308, -176, -176, -176, -176, -176, -176, + -176, 305, -176, 316, -176, 323, -176, 325, 333, -176, + 334, 335, 336, -176, 343, 342, -176, 326, -176, -176, + 326, -176, -176, 139, 344, -176, -176, -176, -176, -176, + -176, -176, -176, 345, 348, 349, -176, -176, -176, 354, + 355, -176, -176, -176, 356, 357, -176, -176, -176, 360, + 373, -176, -176, -176, 374, -176, -176, -176, -176, -176, + -176, -176, 327, 377, 379, 298, 612, 506, 556, 556, + 125, 125, -176, -176, -176, 405, 410, 556, -176, -176, + 97, 97, 97, 97, 97, 97, -8, -8, 556, -176, + 385, 388, 782, -176, -8, 12, 12, -26, 381, 97, + -17, 382, 382, 97, 429, -176, -176, 498, 498, -176, + -176, -176, 390, -176, -176, -176, -176, -176, -176, -176, + -176, -176, -176, -176, 326, -176, -176, -176, -176, 393, + 462, 712, -176, -176, -176, -176, -176, 398, 399, 416, + 419, 426, -176, 451, -176, 454, 12, 556, 328, 97, + 97, 556, 97, 97, -176, -176, -176, -176, -176, -176, + -176, -176, -176 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -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 + -176, -176, 306, -176, -176, -88, -5, -73, -176, -154, + -176, -176, -137, -158, -176, 67, 39, -175, 141, -15, + 149, 113, 167, 80, 32, 200, 124, -83, 299, 35, + 70 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If YYTABLE_NINF, syntax error. */ + number is the opposite. If zero, do what YYDEFACT says. + 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, + 79, 82, 83, 85, 87, 89, 120, 188, 255, 267, + 303, 186, 41, 111, 115, 195, 46, 240, 48, 46, + 46, 48, 48, 191, 131, 256, 133, 135, 137, 110, + 140, 271, 128, 45, 42, 43, 76, 81, 93, 78, + 78, 279, 280, 281, 99, 105, 92, 100, 78, 110, + 60, 98, 84, 84, 129, 84, 47, 123, 123, 50, + 129, 45, 44, 143, 47, 138, 93, 50, 78, 46, + 46, 48, 48, 144, 196, 274, 147, 145, 146, 148, + 102, 106, 107, 108, 109, 80, 116, 241, 149, 254, + 46, 47, 48, 104, 50, 160, 161, 151, 58, 152, + 153, 150, 45, 90, 308, 311, 61, 93, 130, 208, + 132, 134, 54, 55, 305, 56, 46, 47, 48, 179, + 50, 86, 88, 114, 141, 142, 84, 189, 193, 194, + 190, 112, 117, 162, 121, 249, 250, 251, 126, 127, + 46, 163, 48, 118, 119, 136, 173, 139, 125, 129, + 45, 84, 46, 352, 48, 93, 215, 253, 261, 262, + 263, 164, 152, 153, 273, 275, 277, 278, 165, 284, + 287, 288, 289, 290, 166, 292, 294, 296, 299, 301, + 167, 209, 232, 233, 234, 235, 168, 237, 238, 216, + 279, 280, 281, 314, 260, 169, 46, 78, 48, 270, + 236, 257, 78, 411, 264, 266, 286, 272, 401, 78, + 170, 400, 230, 231, 333, 382, 194, 338, 339, 340, + 304, 342, 122, 124, 309, 312, 155, 190, 313, 318, + 306, 171, 78, 265, 380, 206, 172, 381, 174, 210, + 211, 175, 259, 239, 212, 213, 176, 269, 177, 329, + 332, 330, 178, 78, 285, 180, 181, 341, 182, 183, + 78, 184, 343, 185, 316, 319, 320, 321, 322, 323, + 324, 325, 192, 197, 198, 258, 194, 317, 199, 200, + 268, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 201, 202, 203, 415, 297, 155, 302, 204, 205, + 336, 337, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 207, 355, 356, 357, 214, 217, 360, 361, 362, + 363, 364, 218, 219, 220, 42, 43, 328, 221, 222, + 331, 223, 334, 335, 42, 43, 42, 43, 224, 225, + 282, 435, 226, 227, 228, 291, 359, 293, 295, 298, + 300, 315, 348, 44, 349, 350, 252, 351, 45, 358, + 365, 282, 44, 93, 44, 403, 404, 405, 406, 407, + 408, 366, 326, 422, 327, 52, 53, 279, 280, 281, + 367, 370, 368, 46, 425, 48, 369, 94, 432, 58, + 42, 43, 371, 95, 96, 344, 315, 61, 58, 372, + 58, 373, 402, 90, 394, 90, 61, 354, 61, 374, + 375, 376, 377, 92, 416, 409, 410, 190, 44, 378, + 379, 384, 383, 417, 385, 386, 429, 429, 397, 398, + 387, 388, 389, 390, 448, 449, 391, 451, 452, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 392, + 393, 399, 418, 419, 58, 395, 160, 396, 51, 90, + 421, 84, 61, 412, 2, 3, 413, 433, 434, 436, + 426, 437, 447, 146, 439, 440, 450, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 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 + 17, 18, 441, 19, 20, 442, 21, 22, 23, 24, + 420, 424, 443, 446, 428, 431, 247, 248, 249, 250, + 251, 346, 245, 246, 247, 248, 249, 250, 251, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 3, 444, + 34, 35, 445, 430, 36, 345, 37, 423, 353, 38, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 0, 19, 20, 0, 21, + 22, 23, 24, 0, 42, 43, 0, 0, 42, 43, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 0, 0, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 0, 44, 34, 35, 0, 44, 36, 0, 37, + 0, 45, 38, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 0, 56, 42, 43, 244, 245, 246, + 247, 248, 249, 250, 251, 0, 42, 43, 58, 0, + 57, 0, 58, 90, 0, 0, 61, 59, 0, 60, + 61, 0, 347, 44, 0, 42, 43, 0, 45, 0, + 46, 0, 48, 49, 44, 0, 52, 53, 54, 55, + 0, 56, 47, 0, 0, 50, 42, 43, 0, 0, + 0, 0, 0, 44, 0, 0, 0, 57, 0, 58, + 46, 0, 48, 0, 59, 0, 84, 61, 57, 0, + 58, 42, 43, 0, 44, 59, 0, 101, 61, 0, + 0, 46, 0, 48, 42, 43, 0, 57, 0, 58, + 0, 0, 0, 0, 59, 0, 0, 61, 0, 44, + 42, 438, 0, 0, 42, 43, 0, 0, 57, 0, + 58, 51, 44, 42, 43, 90, 0, 0, 61, 0, + 47, 0, 0, 50, 42, 43, 0, 0, 44, 0, + 42, 43, 44, 57, 0, 58, 0, 0, 0, 0, + 59, 44, 84, 61, 0, 0, 57, 0, 58, 0, + 42, 43, 44, 59, 0, 0, 61, 0, 44, 0, + 196, 158, 57, 0, 58, 158, 57, 0, 58, 90, + 42, 43, 61, 90, 0, 57, 61, 58, 44, 0, + 0, 0, 90, 0, 0, 61, 94, 0, 58, 0, + 0, 0, 94, 187, 58, 0, 61, 0, 44, 307, + 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 94, 0, 58, 0, 0, 0, 0, 310, + 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 94, 0, 58, 0, 0, 0, 0, 414, + 0, 0, 61 }; -#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, + 5, 6, 7, 8, 9, 10, 21, 95, 162, 167, + 185, 94, 75, 18, 19, 9, 43, 8, 45, 43, + 43, 45, 45, 96, 29, 162, 31, 32, 33, 76, + 35, 168, 75, 41, 8, 9, 4, 5, 46, 4, + 5, 37, 38, 39, 12, 13, 11, 12, 13, 76, + 79, 12, 79, 79, 77, 79, 44, 22, 23, 47, + 77, 41, 36, 74, 44, 33, 46, 47, 33, 43, + 43, 45, 45, 75, 68, 48, 77, 42, 43, 77, + 13, 14, 15, 16, 17, 5, 19, 78, 77, 162, + 43, 44, 45, 13, 47, 60, 61, 6, 72, 8, + 9, 77, 41, 77, 192, 193, 80, 46, 28, 114, + 30, 31, 51, 52, 187, 54, 43, 44, 45, 84, + 47, 8, 9, 76, 73, 74, 79, 95, 76, 77, + 95, 18, 19, 76, 21, 10, 11, 12, 25, 26, + 43, 76, 45, 19, 20, 32, 77, 34, 24, 77, + 41, 79, 43, 236, 45, 46, 77, 162, 163, 164, + 165, 76, 8, 9, 169, 170, 171, 172, 76, 174, + 175, 176, 177, 178, 76, 180, 181, 182, 183, 184, + 76, 114, 147, 148, 149, 150, 76, 152, 153, 11, + 37, 38, 39, 40, 162, 76, 43, 162, 45, 167, + 7, 162, 167, 378, 165, 166, 174, 168, 366, 174, + 76, 365, 142, 143, 219, 76, 77, 222, 223, 224, + 185, 226, 22, 23, 192, 193, 59, 192, 193, 197, + 78, 76, 197, 166, 307, 111, 76, 310, 76, 115, + 116, 76, 162, 77, 120, 121, 76, 167, 76, 214, + 218, 216, 76, 218, 174, 76, 76, 225, 76, 76, + 225, 76, 227, 76, 197, 198, 199, 200, 201, 202, + 203, 204, 76, 76, 76, 162, 77, 197, 76, 76, + 167, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 76, 76, 76, 382, 182, 129, 184, 76, 76, + 220, 221, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 76, 242, 243, 244, 76, 76, 247, 248, 249, + 250, 251, 76, 76, 76, 8, 9, 214, 76, 76, + 217, 76, 219, 220, 8, 9, 8, 9, 76, 76, + 173, 414, 76, 76, 76, 178, 7, 180, 181, 182, + 183, 68, 78, 36, 78, 78, 78, 78, 41, 6, + 76, 194, 36, 46, 36, 370, 371, 372, 373, 374, + 375, 76, 205, 388, 207, 49, 50, 37, 38, 39, + 77, 76, 78, 43, 389, 45, 78, 70, 393, 72, + 8, 9, 76, 76, 77, 228, 68, 80, 72, 76, + 72, 76, 367, 77, 77, 77, 80, 240, 80, 76, + 76, 76, 76, 378, 382, 376, 377, 382, 36, 76, + 78, 76, 78, 384, 76, 76, 391, 392, 358, 359, + 76, 76, 76, 76, 439, 440, 76, 442, 443, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 76, + 76, 46, 385, 386, 72, 78, 421, 78, 48, 77, + 79, 79, 80, 78, 0, 1, 78, 38, 78, 76, + 390, 9, 437, 438, 76, 76, 441, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 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 + 26, 27, 76, 29, 30, 76, 32, 33, 34, 35, + 387, 388, 76, 436, 391, 392, 8, 9, 10, 11, + 12, 75, 6, 7, 8, 9, 10, 11, 12, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 1, 78, + 66, 67, 78, 392, 70, 229, 72, 388, 239, 75, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, -1, 29, 30, -1, 32, + 33, 34, 35, -1, 8, 9, -1, -1, 8, 9, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + -1, -1, 55, 56, 57, 58, 59, 60, 61, 62, + 63, -1, 36, 66, 67, -1, 36, 70, -1, 72, + -1, 41, 75, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, -1, 54, 8, 9, 5, 6, 7, + 8, 9, 10, 11, 12, -1, 8, 9, 72, -1, + 70, -1, 72, 77, -1, -1, 80, 77, -1, 79, + 80, -1, 75, 36, -1, 8, 9, -1, 41, -1, + 43, -1, 45, 46, 36, -1, 49, 50, 51, 52, + -1, 54, 44, -1, -1, 47, 8, 9, -1, -1, + -1, -1, -1, 36, -1, -1, -1, 70, -1, 72, + 43, -1, 45, -1, 77, -1, 79, 80, 70, -1, + 72, 8, 9, -1, 36, 77, -1, 79, 80, -1, + -1, 43, -1, 45, 8, 9, -1, 70, -1, 72, + -1, -1, -1, -1, 77, -1, -1, 80, -1, 36, + 8, 9, -1, -1, 8, 9, -1, -1, 70, -1, + 72, 48, 36, 8, 9, 77, -1, -1, 80, -1, + 44, -1, -1, 47, 8, 9, -1, -1, 36, -1, + 8, 9, 36, 70, -1, 72, -1, -1, -1, -1, + 77, 36, 79, 80, -1, -1, 70, -1, 72, -1, + 8, 9, 36, 77, -1, -1, 80, -1, 36, -1, + 68, 69, 70, -1, 72, 69, 70, -1, 72, 77, + 8, 9, 80, 77, -1, 70, 80, 72, 36, -1, + -1, -1, 77, -1, -1, 80, 70, -1, 72, -1, + -1, -1, 70, 77, 72, -1, 80, -1, 36, 77, + -1, -1, 80, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 70, -1, 72, -1, -1, -1, -1, 77, + -1, -1, 80, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 70, -1, 72, -1, -1, -1, -1, 77, + -1, -1, 80 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1078,49 +1061,49 @@ 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 + 60, 61, 62, 63, 66, 67, 70, 72, 75, 83, + 85, 75, 8, 9, 36, 41, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 54, 70, 72, 77, + 79, 80, 87, 88, 89, 90, 91, 92, 93, 94, + 96, 97, 100, 102, 103, 104, 105, 106, 110, 87, + 104, 105, 87, 87, 79, 87, 102, 87, 102, 87, + 77, 98, 110, 46, 70, 76, 77, 86, 97, 105, + 110, 79, 96, 101, 104, 105, 96, 96, 96, 96, + 76, 87, 102, 107, 76, 87, 96, 102, 107, 107, + 100, 102, 106, 110, 106, 107, 102, 102, 75, 77, + 104, 87, 104, 87, 104, 87, 102, 87, 105, 102, + 87, 73, 74, 74, 75, 110, 110, 77, 77, 77, + 77, 6, 8, 9, 108, 103, 110, 111, 69, 105, + 110, 110, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 77, 76, 76, 76, 76, 76, 110, + 76, 76, 76, 76, 76, 76, 108, 77, 86, 105, + 110, 88, 76, 76, 77, 9, 68, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 107, 76, 87, 96, + 107, 107, 107, 107, 76, 77, 11, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 84, + 111, 111, 110, 110, 110, 110, 7, 110, 110, 77, + 8, 78, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 78, 87, 88, 90, 93, 97, 102, 104, + 105, 87, 87, 87, 97, 96, 97, 94, 102, 104, + 105, 93, 97, 87, 48, 87, 95, 87, 87, 37, + 38, 39, 103, 109, 87, 104, 105, 87, 87, 87, + 87, 103, 87, 103, 87, 103, 87, 102, 103, 87, + 103, 87, 102, 98, 110, 88, 78, 77, 86, 105, + 77, 86, 105, 110, 40, 68, 96, 104, 105, 96, + 96, 96, 96, 96, 96, 96, 103, 103, 102, 110, + 110, 102, 105, 87, 102, 102, 104, 104, 87, 87, + 87, 105, 87, 110, 103, 83, 75, 75, 78, 78, + 78, 78, 108, 109, 103, 111, 111, 111, 6, 7, + 111, 111, 111, 111, 111, 76, 76, 77, 78, 78, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 78, + 88, 88, 76, 78, 76, 76, 76, 76, 76, 76, + 76, 76, 76, 76, 77, 78, 78, 111, 111, 46, + 90, 94, 110, 87, 87, 87, 87, 87, 87, 97, + 97, 98, 78, 78, 77, 86, 105, 97, 96, 96, + 102, 79, 100, 101, 102, 87, 104, 99, 102, 110, + 99, 102, 87, 38, 78, 88, 76, 9, 9, 76, + 76, 76, 76, 76, 78, 78, 96, 110, 87, 87, + 110, 87, 87 }; #define yyerrok (yyerrstatus = 0) @@ -1135,18 +1118,9 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ + Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif #define YYRECOVERING() (!!yyerrstatus) @@ -1156,6 +1130,7 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -1197,10 +1172,19 @@ while (YYID (0)) #endif -/* This macro is provided for backward compatibility. */ +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif #endif @@ -1304,20 +1288,17 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } @@ -1351,11 +1332,11 @@ yy_reduce_print (yyvsp, yyrule) /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - YYFPRINTF (stderr, " $%d = ", yyi + 1); + fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); - YYFPRINTF (stderr, "\n"); + fprintf (stderr, "\n"); } } @@ -1392,6 +1373,7 @@ int yydebug; # define YYMAXDEPTH 10000 #endif + #if YYERROR_VERBOSE @@ -1494,142 +1476,115 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = 0; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - Assume YYFAIL is not used. It's too flawed to consider. See - - for details. YYERROR is fine as it does not invoke this - function. - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } + int yyn = yypact[yystate]; - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } - yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } + if (yysize_overflow) + return YYSIZE_MAXIMUM; - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } } #endif /* YYERROR_VERBOSE */ + /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1661,9 +1616,10 @@ yydestruct (yymsg, yytype, yyvaluep) break; } } - + /* Prevent warnings from -Wmissing-prototypes. */ + #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); @@ -1679,16 +1635,18 @@ int yyparse (); #endif /* ! YYPARSE_PARAM */ -/* The lookahead symbol. */ + +/* The look-ahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ +/* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; + /*----------. | yyparse. | `----------*/ @@ -1715,37 +1673,14 @@ yyparse () #endif #endif { - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks 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 yystate; int yyn; int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; @@ -1753,28 +1688,51 @@ yyparse () YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; - yystacksize = YYINITDEPTH; - YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ + yyssp = yyss; yyvsp = yyvs; @@ -1804,6 +1762,7 @@ yyparse () YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; + /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might @@ -1811,6 +1770,7 @@ yyparse () yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); yyss = yyss1; @@ -1833,8 +1793,9 @@ yyparse () (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1845,6 +1806,7 @@ yyparse () yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; + YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1854,9 +1816,6 @@ yyparse () YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - if (yystate == YYFINAL) - YYACCEPT; - goto yybackup; /*-----------. @@ -1865,16 +1824,16 @@ yyparse () yybackup: /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ + look-ahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to lookahead token. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) + if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -1900,22 +1859,26 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yytable_value_is_error (yyn)) - goto yyerrlab; + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; yyn = -yyn; goto yyreduce; } + if (yyn == YYFINAL) + YYACCEPT; + /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the lookahead token. */ + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token. */ - yychar = YYEMPTY; + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; @@ -1955,40 +1918,26 @@ yyreduce: 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) = labellookup((yyvsp[(1) - (2)].sym)); + if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc) + yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname); (yyvsp[(1) - (2)].sym)->type = LLAB; (yyvsp[(1) - (2)].sym)->value = pc; } break; - case 8: - -/* Line 1806 of yacc.c */ -#line 84 "a.y" + case 6: +#line 80 "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" + case 7: +#line 85 "a.y" { if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval)) yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name); @@ -1996,604 +1945,470 @@ yyreduce: } break; - case 10: - -/* Line 1806 of yacc.c */ -#line 95 "a.y" + case 8: +#line 91 "a.y" { nosched = (yyvsp[(1) - (2)].lval); } break; - case 14: + case 12: +#line 103 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 13: #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 */ + case 14: #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 */ + case 15: #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 */ + case 16: #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 */ + case 17: #line 123 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 19: + case 18: +#line 130 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ -#line 127 "a.y" + case 19: +#line 134 "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" +#line 138 "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" +#line 142 "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" +#line 146 "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" +#line 150 "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" +#line 157 "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" +#line 161 "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" +#line 165 "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" +#line 169 "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" +#line 176 "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" +#line 180 "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" +#line 187 "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" +#line 191 "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" +#line 195 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); } break; case 33: - -/* Line 1806 of yacc.c */ -#line 195 "a.y" +#line 199 "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" +#line 203 "a.y" { - outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 35: - -/* Line 1806 of yacc.c */ -#line 203 "a.y" +#line 207 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen); } break; case 36: - -/* Line 1806 of yacc.c */ -#line 207 "a.y" +#line 214 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); } break; case 37: - -/* Line 1806 of yacc.c */ -#line 211 "a.y" +#line 218 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 38: - -/* Line 1806 of yacc.c */ -#line 218 "a.y" +#line 222 "a.y" { - outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 39: - -/* Line 1806 of yacc.c */ -#line 222 "a.y" +#line 232 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 40: - -/* Line 1806 of yacc.c */ -#line 226 "a.y" +#line 236 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 41: - -/* Line 1806 of yacc.c */ -#line 236 "a.y" +#line 240 "a.y" { - outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); } break; case 42: - -/* Line 1806 of yacc.c */ -#line 240 "a.y" +#line 244 "a.y" { - outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 43: - -/* Line 1806 of yacc.c */ -#line 244 "a.y" +#line 248 "a.y" { - outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 44: - -/* Line 1806 of yacc.c */ -#line 248 "a.y" +#line 252 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 45: - -/* Line 1806 of yacc.c */ -#line 252 "a.y" +#line 256 "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" +#line 260 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 47: - -/* Line 1806 of yacc.c */ -#line 260 "a.y" +#line 264 "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" +#line 268 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 49: - -/* Line 1806 of yacc.c */ -#line 268 "a.y" +#line 272 "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" +#line 276 "a.y" { - outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 51: - -/* Line 1806 of yacc.c */ -#line 276 "a.y" +#line 280 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &(yyvsp[(2) - (2)].addr)); } break; case 52: - -/* Line 1806 of yacc.c */ -#line 280 "a.y" +#line 287 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 53: - -/* Line 1806 of yacc.c */ -#line 284 "a.y" +#line 294 "a.y" { - outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &(yyvsp[(2) - (2)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 54: - -/* Line 1806 of yacc.c */ -#line 291 "a.y" +#line 298 "a.y" { - outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 55: - -/* Line 1806 of yacc.c */ -#line 298 "a.y" +#line 305 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr)); } break; case 56: - -/* Line 1806 of yacc.c */ -#line 302 "a.y" +#line 309 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 57: - -/* Line 1806 of yacc.c */ -#line 309 "a.y" +#line 317 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(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 */ + case 59: #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 */ + case 60: #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 */ + case 61: #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 */ + case 62: #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 */ + case 63: #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 */ + case 64: #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" + case 65: +#line 354 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr)); } break; - case 67: - -/* Line 1806 of yacc.c */ + case 66: #line 358 "a.y" { outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr)); } break; - case 68: - -/* Line 1806 of yacc.c */ + case 67: #line 362 "a.y" { - outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &(yyvsp[(2) - (2)].addr)); + outcode((yyvsp[(1) - (4)].lval), &nullgen, NREG, &(yyvsp[(3) - (4)].addr)); } break; - case 69: - -/* Line 1806 of yacc.c */ + case 68: #line 366 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &nullgen, NREG, &(yyvsp[(3) - (4)].addr)); + outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 70: - -/* Line 1806 of yacc.c */ + case 69: #line 370 "a.y" { outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 71: - -/* Line 1806 of yacc.c */ + case 70: #line 374 "a.y" { - outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); + outcode((yyvsp[(1) - (5)].lval), &nullgen, NREG, &(yyvsp[(4) - (5)].addr)); } break; - case 72: - -/* Line 1806 of yacc.c */ + case 71: #line 378 "a.y" { - outcode((yyvsp[(1) - (5)].lval), &nullgen, NREG, &(yyvsp[(4) - (5)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 73: - -/* Line 1806 of yacc.c */ + case 72: #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 */ + case 73: #line 386 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(5) - (6)].addr)); } break; - case 75: - -/* Line 1806 of yacc.c */ + case 74: #line 390 "a.y" { - outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(5) - (6)].addr)); + outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr)); } break; - case 76: - -/* Line 1806 of yacc.c */ + case 75: #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 */ + case 76: #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" + case 77: +#line 402 "a.y" { Addr g; g = nullgen; @@ -2603,10 +2418,8 @@ yyreduce: } break; - case 80: - -/* Line 1806 of yacc.c */ -#line 414 "a.y" + case 78: +#line 410 "a.y" { Addr g; g = nullgen; @@ -2616,10 +2429,8 @@ yyreduce: } break; - case 81: - -/* Line 1806 of yacc.c */ -#line 422 "a.y" + case 79: +#line 418 "a.y" { Addr g; g = nullgen; @@ -2629,325 +2440,253 @@ yyreduce: } break; - case 82: - -/* Line 1806 of yacc.c */ -#line 433 "a.y" + case 80: +#line 429 "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" + case 81: +#line 433 "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" + case 82: +#line 437 "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" + case 83: +#line 441 "a.y" { outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); } break; - case 86: - -/* Line 1806 of yacc.c */ -#line 452 "a.y" + case 84: +#line 448 "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" + case 85: +#line 452 "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" + case 86: +#line 456 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr)); } break; - case 89: - -/* Line 1806 of yacc.c */ -#line 464 "a.y" + case 87: +#line 460 "a.y" { outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; - case 90: - -/* Line 1806 of yacc.c */ -#line 468 "a.y" + case 88: +#line 464 "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" + case 89: +#line 468 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr)); } break; - case 92: + case 90: +#line 475 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 91: #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 */ + case 92: #line 483 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr)); } break; - case 94: - -/* Line 1806 of yacc.c */ + case 93: #line 487 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr)); } break; - case 95: + case 94: +#line 494 "a.y" + { + outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); + } + break; -/* Line 1806 of yacc.c */ -#line 491 "a.y" + case 95: +#line 498 "a.y" { - outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr)); + outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; case 96: - -/* Line 1806 of yacc.c */ -#line 498 "a.y" +#line 502 "a.y" { outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; case 97: - -/* Line 1806 of yacc.c */ -#line 502 "a.y" +#line 506 "a.y" { outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; case 98: - -/* Line 1806 of yacc.c */ -#line 506 "a.y" +#line 513 "a.y" { - outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 99: - -/* Line 1806 of yacc.c */ -#line 510 "a.y" +#line 517 "a.y" { - outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 100: - -/* Line 1806 of yacc.c */ -#line 517 "a.y" +#line 525 "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" +#line 529 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); } break; case 102: - -/* Line 1806 of yacc.c */ -#line 529 "a.y" +#line 533 "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" +#line 537 "a.y" { outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); } break; case 104: - -/* Line 1806 of yacc.c */ -#line 537 "a.y" +#line 541 "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 */ + case 106: #line 549 "a.y" { - outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen); } break; - case 108: - -/* Line 1806 of yacc.c */ -#line 553 "a.y" + case 107: +#line 556 "a.y" { - outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), NREG, &nullgen); + outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); } break; - case 109: - -/* Line 1806 of yacc.c */ + case 108: #line 560 "a.y" { - outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); + outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen); } break; - case 110: - -/* Line 1806 of yacc.c */ + case 109: #line 564 "a.y" { outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen); } break; - case 111: - -/* Line 1806 of yacc.c */ + case 110: #line 568 "a.y" { - outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen); + outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 112: - -/* Line 1806 of yacc.c */ + case 111: #line 572 "a.y" { outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; - case 113: - -/* Line 1806 of yacc.c */ + case 112: #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" + case 113: +#line 583 "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" + case 114: +#line 587 "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" + case 115: +#line 594 "a.y" { if((yyvsp[(2) - (4)].addr).type != D_CONST || (yyvsp[(4) - (4)].addr).type != D_CONST) yyerror("arguments to PCDATA must be integer constants"); @@ -2955,10 +2694,8 @@ yyreduce: } break; - case 118: - -/* Line 1806 of yacc.c */ -#line 607 "a.y" + case 116: +#line 603 "a.y" { if((yyvsp[(2) - (4)].addr).type != D_CONST) yyerror("index for FUNCDATA must be integer constant"); @@ -2968,86 +2705,71 @@ yyreduce: } break; - case 119: - -/* Line 1806 of yacc.c */ -#line 618 "a.y" + case 117: +#line 614 "a.y" { outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); } break; - case 120: - -/* Line 1806 of yacc.c */ -#line 625 "a.y" + case 118: +#line 621 "a.y" { + settext((yyvsp[(2) - (4)].addr).sym); outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 121: - -/* Line 1806 of yacc.c */ -#line 629 "a.y" + case 119: +#line 626 "a.y" { + settext((yyvsp[(2) - (6)].addr).sym); (yyvsp[(6) - (6)].addr).offset &= 0xffffffffull; (yyvsp[(6) - (6)].addr).offset |= (vlong)ArgsSizeUnknown << 32; outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 122: - -/* Line 1806 of yacc.c */ -#line 635 "a.y" + case 120: +#line 633 "a.y" { + settext((yyvsp[(2) - (8)].addr).sym); (yyvsp[(6) - (8)].addr).offset &= 0xffffffffull; (yyvsp[(6) - (8)].addr).offset |= ((yyvsp[(8) - (8)].lval) & 0xffffffffull) << 32; outcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].lval), &(yyvsp[(6) - (8)].addr)); } break; - case 123: - -/* Line 1806 of yacc.c */ -#line 644 "a.y" + case 121: +#line 643 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 124: - -/* Line 1806 of yacc.c */ -#line 648 "a.y" + case 122: +#line 647 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 125: - -/* Line 1806 of yacc.c */ -#line 652 "a.y" + case 123: +#line 651 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 126: - -/* Line 1806 of yacc.c */ -#line 659 "a.y" + case 124: +#line 658 "a.y" { outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); } break; - case 127: - -/* Line 1806 of yacc.c */ -#line 665 "a.y" + case 125: +#line 664 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_BRANCH; @@ -3055,34 +2777,20 @@ yyreduce: } 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" + case 126: +#line 670 "a.y" { + (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym)); (yyval.addr) = nullgen; + if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB) + yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname); (yyval.addr).type = D_BRANCH; (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval); } break; - case 130: - -/* Line 1806 of yacc.c */ -#line 687 "a.y" + case 127: +#line 681 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_REG; @@ -3090,10 +2798,8 @@ yyreduce: } break; - case 133: - -/* Line 1806 of yacc.c */ -#line 699 "a.y" + case 130: +#line 693 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SPR; @@ -3101,10 +2807,8 @@ yyreduce: } break; - case 134: - -/* Line 1806 of yacc.c */ -#line 707 "a.y" + case 131: +#line 701 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CREG; @@ -3112,10 +2816,8 @@ yyreduce: } break; - case 135: - -/* Line 1806 of yacc.c */ -#line 715 "a.y" + case 132: +#line 709 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SPR; @@ -3123,20 +2825,16 @@ yyreduce: } break; - case 136: - -/* Line 1806 of yacc.c */ -#line 723 "a.y" + case 133: +#line 717 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_MSR; } break; - case 137: - -/* Line 1806 of yacc.c */ -#line 730 "a.y" + case 134: +#line 724 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SPR; @@ -3144,10 +2842,8 @@ yyreduce: } break; - case 138: - -/* Line 1806 of yacc.c */ -#line 736 "a.y" + case 135: +#line 730 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (4)].lval); @@ -3155,10 +2851,8 @@ yyreduce: } break; - case 140: - -/* Line 1806 of yacc.c */ -#line 745 "a.y" + case 137: +#line 739 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FPSCR; @@ -3166,10 +2860,8 @@ yyreduce: } break; - case 141: - -/* Line 1806 of yacc.c */ -#line 753 "a.y" + case 138: +#line 747 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FPSCR; @@ -3177,10 +2869,8 @@ yyreduce: } break; - case 142: - -/* Line 1806 of yacc.c */ -#line 761 "a.y" + case 139: +#line 755 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FREG; @@ -3188,10 +2878,8 @@ yyreduce: } break; - case 143: - -/* Line 1806 of yacc.c */ -#line 767 "a.y" + case 140: +#line 761 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FREG; @@ -3199,10 +2887,8 @@ yyreduce: } break; - case 144: - -/* Line 1806 of yacc.c */ -#line 775 "a.y" + case 141: +#line 769 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CREG; @@ -3210,10 +2896,8 @@ yyreduce: } break; - case 145: - -/* Line 1806 of yacc.c */ -#line 781 "a.y" + case 142: +#line 775 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CREG; @@ -3221,10 +2905,8 @@ yyreduce: } break; - case 146: - -/* Line 1806 of yacc.c */ -#line 789 "a.y" + case 143: +#line 783 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_REG; @@ -3232,10 +2914,8 @@ yyreduce: } break; - case 147: - -/* Line 1806 of yacc.c */ -#line 797 "a.y" + case 144: +#line 791 "a.y" { int mb, me; uint32 v; @@ -3256,20 +2936,16 @@ yyreduce: } break; - case 148: - -/* Line 1806 of yacc.c */ -#line 818 "a.y" + case 145: +#line 812 "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" + case 146: +#line 817 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_SCONST; @@ -3277,10 +2953,8 @@ yyreduce: } break; - case 150: - -/* Line 1806 of yacc.c */ -#line 831 "a.y" + case 147: +#line 825 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -3288,10 +2962,8 @@ yyreduce: } break; - case 151: - -/* Line 1806 of yacc.c */ -#line 837 "a.y" + case 148: +#line 831 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_FCONST; @@ -3299,10 +2971,8 @@ yyreduce: } break; - case 152: - -/* Line 1806 of yacc.c */ -#line 844 "a.y" + case 149: +#line 838 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_CONST; @@ -3310,10 +2980,8 @@ yyreduce: } break; - case 154: - -/* Line 1806 of yacc.c */ -#line 853 "a.y" + case 151: +#line 847 "a.y" { if((yyval.lval) < 0 || (yyval.lval) >= NREG) print("register value out of range\n"); @@ -3321,10 +2989,8 @@ yyreduce: } break; - case 155: - -/* Line 1806 of yacc.c */ -#line 861 "a.y" + case 152: +#line 855 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -3333,10 +2999,8 @@ yyreduce: } break; - case 156: - -/* Line 1806 of yacc.c */ -#line 868 "a.y" + case 153: +#line 862 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -3346,10 +3010,8 @@ yyreduce: } break; - case 158: - -/* Line 1806 of yacc.c */ -#line 879 "a.y" + case 155: +#line 873 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -3358,10 +3020,8 @@ yyreduce: } break; - case 159: - -/* Line 1806 of yacc.c */ -#line 888 "a.y" + case 156: +#line 882 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -3371,10 +3031,8 @@ yyreduce: } break; - case 160: - -/* Line 1806 of yacc.c */ -#line 896 "a.y" + case 157: +#line 890 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -3384,10 +3042,8 @@ yyreduce: } break; - case 161: - -/* Line 1806 of yacc.c */ -#line 904 "a.y" + case 158: +#line 898 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = D_OREG; @@ -3397,185 +3053,137 @@ yyreduce: } break; - case 164: - -/* Line 1806 of yacc.c */ -#line 916 "a.y" + case 161: +#line 910 "a.y" { (yyval.lval) = 0; } break; - case 165: - -/* Line 1806 of yacc.c */ -#line 920 "a.y" + case 162: +#line 914 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 166: - -/* Line 1806 of yacc.c */ -#line 924 "a.y" + case 163: +#line 918 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 171: - -/* Line 1806 of yacc.c */ -#line 936 "a.y" + case 168: +#line 930 "a.y" { (yyval.lval) = (yyvsp[(1) - (1)].sym)->value; } break; - case 172: - -/* Line 1806 of yacc.c */ -#line 940 "a.y" + case 169: +#line 934 "a.y" { (yyval.lval) = -(yyvsp[(2) - (2)].lval); } break; - case 173: - -/* Line 1806 of yacc.c */ -#line 944 "a.y" + case 170: +#line 938 "a.y" { (yyval.lval) = (yyvsp[(2) - (2)].lval); } break; - case 174: - -/* Line 1806 of yacc.c */ -#line 948 "a.y" + case 171: +#line 942 "a.y" { (yyval.lval) = ~(yyvsp[(2) - (2)].lval); } break; - case 175: - -/* Line 1806 of yacc.c */ -#line 952 "a.y" + case 172: +#line 946 "a.y" { (yyval.lval) = (yyvsp[(2) - (3)].lval); } break; - case 177: - -/* Line 1806 of yacc.c */ -#line 959 "a.y" + case 174: +#line 953 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval); } break; - case 178: - -/* Line 1806 of yacc.c */ -#line 963 "a.y" + case 175: +#line 957 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval); } break; - case 179: - -/* Line 1806 of yacc.c */ -#line 967 "a.y" + case 176: +#line 961 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval); } break; - case 180: - -/* Line 1806 of yacc.c */ -#line 971 "a.y" + case 177: +#line 965 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval); } break; - case 181: - -/* Line 1806 of yacc.c */ -#line 975 "a.y" + case 178: +#line 969 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval); } break; - case 182: - -/* Line 1806 of yacc.c */ -#line 979 "a.y" + case 179: +#line 973 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval); } break; - case 183: - -/* Line 1806 of yacc.c */ -#line 983 "a.y" + case 180: +#line 977 "a.y" { (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval); } break; - case 184: - -/* Line 1806 of yacc.c */ -#line 987 "a.y" + case 181: +#line 981 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval); } break; - case 185: - -/* Line 1806 of yacc.c */ -#line 991 "a.y" + case 182: +#line 985 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval); } break; - case 186: - -/* Line 1806 of yacc.c */ -#line 995 "a.y" + case 183: +#line 989 "a.y" { (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval); } break; - -/* Line 1806 of yacc.c */ -#line 3566 "y.tab.c" +/* Line 1267 of yacc.c. */ +#line 3185 "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); @@ -3584,6 +3192,7 @@ yyreduce: *++yyvsp = yyval; + /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -3603,10 +3212,6 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -3614,36 +3219,37 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } } -# undef YYSYNTAX_ERROR #endif } @@ -3651,7 +3257,7 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an + /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) @@ -3668,7 +3274,7 @@ yyerrlab: } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; @@ -3702,7 +3308,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) + if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -3725,6 +3331,9 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } + if (yyn == YYFINAL) + YYACCEPT; + *++yyvsp = yylval; @@ -3749,7 +3358,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -3760,14 +3369,9 @@ yyexhaustedlab: #endif yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); diff --git a/src/cmd/9a/y.tab.h b/src/cmd/9a/y.tab.h index f1b4a7223..e6b93a2ec 100644 --- a/src/cmd/9a/y.tab.h +++ b/src/cmd/9a/y.tab.h @@ -1,21 +1,24 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - + the Free Software Foundation; either version 2, or (at your option) + any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License - along with this program. If not, see . */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -26,11 +29,10 @@ special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. - + This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ - /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE @@ -166,27 +168,21 @@ #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 +} +/* Line 1529 of yacc.c. */ +#line 181 "y.tab.h" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; - diff --git a/src/cmd/cc/lexbody b/src/cmd/cc/lexbody index e24db1bc0..f586aaa20 100644 --- a/src/cmd/cc/lexbody +++ b/src/cmd/cc/lexbody @@ -220,6 +220,31 @@ slookup(char *s) return lookup(); } +LSym *thetext; + +void +settext(LSym *s) +{ + thetext = s; +} + +Sym* +labellookup(Sym *s) +{ + char *p; + Sym *lab; + + if(thetext == nil) { + s->labelname = s->name; + return s; + } + p = smprint("%s.%s", thetext->name, s->name); + lab = slookup(p); + free(p); + lab->labelname = s->name; + return lab; +} + Sym* lookup(void) { diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 20d3c47c9..d0b3969bd 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -486,11 +486,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-21 MOVL new_hi+16(FP), CX LOCK CMPXCHG8B 0(BP) - JNZ cas64_fail + JNZ fail MOVL $1, AX MOVB AX, ret+20(FP) RET -cas64_fail: +fail: MOVL $0, AX MOVB AX, ret+20(FP) RET @@ -1342,29 +1342,29 @@ TEXT strings·IndexByte(SB),NOSPLIT,$0 // AX = 1/0/-1 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0 CMPL SI, DI - JEQ cmp_allsame + JEQ allsame CMPL BX, DX MOVL DX, BP CMOVLLT BX, BP // BP = min(alen, blen) CMPL BP, $4 - JB cmp_small + JB small TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2 - JE cmp_mediumloop -cmp_largeloop: + JE mediumloop +largeloop: CMPL BP, $16 - JB cmp_mediumloop + JB mediumloop MOVOU (SI), X0 MOVOU (DI), X1 PCMPEQB X0, X1 PMOVMSKB X1, AX XORL $0xffff, AX // convert EQ to NE - JNE cmp_diff16 // branch if at least one byte is not equal + JNE diff16 // branch if at least one byte is not equal ADDL $16, SI ADDL $16, DI SUBL $16, BP - JMP cmp_largeloop + JMP largeloop -cmp_diff16: +diff16: BSFL AX, BX // index of first byte that differs XORL AX, AX MOVB (SI)(BX*1), CX @@ -1373,25 +1373,25 @@ cmp_diff16: LEAL -1(AX*2), AX // convert 1/0 to +1/-1 RET -cmp_mediumloop: +mediumloop: CMPL BP, $4 - JBE cmp_0through4 + JBE _0through4 MOVL (SI), AX MOVL (DI), CX CMPL AX, CX - JNE cmp_diff4 + JNE diff4 ADDL $4, SI ADDL $4, DI SUBL $4, BP - JMP cmp_mediumloop + JMP mediumloop -cmp_0through4: +_0through4: MOVL -4(SI)(BP*1), AX MOVL -4(DI)(BP*1), CX CMPL AX, CX - JEQ cmp_allsame + JEQ allsame -cmp_diff4: +diff4: BSWAPL AX // reverse order of bytes BSWAPL CX XORL AX, CX // find bit differences @@ -1402,37 +1402,37 @@ cmp_diff4: RET // 0-3 bytes in common -cmp_small: +small: LEAL (BP*8), CX NEGL CX - JEQ cmp_allsame + JEQ allsame // load si CMPB SI, $0xfc - JA cmp_si_high + JA si_high MOVL (SI), SI - JMP cmp_si_finish -cmp_si_high: + JMP si_finish +si_high: MOVL -4(SI)(BP*1), SI SHRL CX, SI -cmp_si_finish: +si_finish: SHLL CX, SI // same for di CMPB DI, $0xfc - JA cmp_di_high + JA di_high MOVL (DI), DI - JMP cmp_di_finish -cmp_di_high: + JMP di_finish +di_high: MOVL -4(DI)(BP*1), DI SHRL CX, DI -cmp_di_finish: +di_finish: SHLL CX, DI BSWAPL SI // reverse order of bytes BSWAPL DI XORL SI, DI // find bit differences - JEQ cmp_allsame + JEQ allsame BSRL DI, CX // index of highest bit difference SHRL CX, SI // move a's bit to bottom ANDL $1, SI // mask bit @@ -1441,7 +1441,7 @@ cmp_di_finish: // all the bytes in common are the same, so we just need // to compare the lengths. -cmp_allsame: +allsame: XORL AX, AX XORL CX, CX CMPL BX, DX diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 709834180..7a0fdfa73 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -461,11 +461,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25 MOVQ new+16(FP), CX LOCK CMPXCHGQ CX, 0(BX) - JNZ cas64_fail + JNZ fail MOVL $1, AX MOVB AX, ret+24(FP) RET -cas64_fail: +fail: MOVL $0, AX MOVB AX, ret+24(FP) RET @@ -876,24 +876,24 @@ TEXT runtime·aeshashbody(SB),NOSPLIT,$0-32 MOVO runtime·aeskeysched+0(SB), X2 MOVO runtime·aeskeysched+16(SB), X3 CMPQ CX, $16 - JB aessmall -aesloop: + JB small +loop: CMPQ CX, $16 - JBE aesloopend + JBE loopend MOVOU (AX), X1 AESENC X2, X0 AESENC X1, X0 SUBQ $16, CX ADDQ $16, AX - JMP aesloop + JMP loop // 1-16 bytes remaining -aesloopend: +loopend: // This load may overlap with the previous load above. // We'll hash some bytes twice, but that's ok. MOVOU -16(AX)(CX*1), X1 JMP partial // 0-15 bytes -aessmall: +small: TESTQ CX, CX JE finalize // 0 bytes @@ -1036,18 +1036,18 @@ TEXT runtime·eqstring(SB),NOSPLIT,$0-33 MOVQ s1len+8(FP), AX MOVQ s2len+24(FP), BX CMPQ AX, BX - JNE different + JNE noteq MOVQ s1str+0(FP), SI MOVQ s2str+16(FP), DI CMPQ SI, DI - JEQ same + JEQ eq CALL runtime·memeqbody(SB) MOVB AX, v+32(FP) RET -same: +eq: MOVB $1, v+32(FP) RET -different: +noteq: MOVB $0, v+32(FP) RET @@ -1170,29 +1170,29 @@ TEXT runtime·cmpbytes(SB),NOSPLIT,$0-56 // AX = 1/0/-1 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0 CMPQ SI, DI - JEQ cmp_allsame + JEQ allsame CMPQ BX, DX MOVQ DX, BP CMOVQLT BX, BP // BP = min(alen, blen) = # of bytes to compare CMPQ BP, $8 - JB cmp_small + JB small -cmp_loop: +loop: CMPQ BP, $16 - JBE cmp_0through16 + JBE _0through16 MOVOU (SI), X0 MOVOU (DI), X1 PCMPEQB X0, X1 PMOVMSKB X1, AX XORQ $0xffff, AX // convert EQ to NE - JNE cmp_diff16 // branch if at least one byte is not equal + JNE diff16 // branch if at least one byte is not equal ADDQ $16, SI ADDQ $16, DI SUBQ $16, BP - JMP cmp_loop + JMP loop // AX = bit mask of differences -cmp_diff16: +diff16: BSFQ AX, BX // index of first byte that differs XORQ AX, AX MOVB (SI)(BX*1), CX @@ -1202,21 +1202,21 @@ cmp_diff16: RET // 0 through 16 bytes left, alen>=8, blen>=8 -cmp_0through16: +_0through16: CMPQ BP, $8 - JBE cmp_0through8 + JBE _0through8 MOVQ (SI), AX MOVQ (DI), CX CMPQ AX, CX - JNE cmp_diff8 -cmp_0through8: + JNE diff8 +_0through8: MOVQ -8(SI)(BP*1), AX MOVQ -8(DI)(BP*1), CX CMPQ AX, CX - JEQ cmp_allsame + JEQ allsame // AX and CX contain parts of a and b that differ. -cmp_diff8: +diff8: BSWAPQ AX // reverse order of bytes BSWAPQ CX XORQ AX, CX @@ -1227,44 +1227,44 @@ cmp_diff8: RET // 0-7 bytes in common -cmp_small: +small: LEAQ (BP*8), CX // bytes left -> bits left NEGQ CX // - bits lift (== 64 - bits left mod 64) - JEQ cmp_allsame + JEQ allsame // load bytes of a into high bytes of AX CMPB SI, $0xf8 - JA cmp_si_high + JA si_high MOVQ (SI), SI - JMP cmp_si_finish -cmp_si_high: + JMP si_finish +si_high: MOVQ -8(SI)(BP*1), SI SHRQ CX, SI -cmp_si_finish: +si_finish: SHLQ CX, SI // load bytes of b in to high bytes of BX CMPB DI, $0xf8 - JA cmp_di_high + JA di_high MOVQ (DI), DI - JMP cmp_di_finish -cmp_di_high: + JMP di_finish +di_high: MOVQ -8(DI)(BP*1), DI SHRQ CX, DI -cmp_di_finish: +di_finish: SHLQ CX, DI BSWAPQ SI // reverse order of bytes BSWAPQ DI XORQ SI, DI // find bit differences - JEQ cmp_allsame + JEQ allsame BSRQ DI, CX // index of highest bit difference SHRQ CX, SI // move a's bit to bottom ANDQ $1, SI // mask bit LEAQ -1(SI*2), AX // 1/0 => +1/-1 RET -cmp_allsame: +allsame: XORQ AX, AX XORQ CX, CX CMPQ BX, DX @@ -1299,7 +1299,7 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0 MOVQ SI, DI CMPQ BX, $16 - JLT indexbyte_small + JLT small // round up to first 16-byte boundary TESTQ $15, SI @@ -1357,7 +1357,7 @@ failure: RET // handle for lengths < 16 -indexbyte_small: +small: MOVQ BX, CX REPN; SCASB JZ success diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s index 28875bc55..de3ef3a23 100644 --- a/src/runtime/asm_amd64p32.s +++ b/src/runtime/asm_amd64p32.s @@ -444,11 +444,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25 MOVQ new+16(FP), CX LOCK CMPXCHGQ CX, 0(BX) - JNZ cas64_fail + JNZ fail MOVL $1, AX MOVB AX, ret+24(FP) RET -cas64_fail: +fail: MOVL $0, AX MOVB AX, ret+24(FP) RET @@ -834,29 +834,29 @@ TEXT runtime·cmpbytes(SB),NOSPLIT,$0-28 // AX = 1/0/-1 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0 CMPQ SI, DI - JEQ cmp_allsame + JEQ allsame CMPQ BX, DX MOVQ DX, R8 CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare CMPQ R8, $8 - JB cmp_small + JB small -cmp_loop: +loop: CMPQ R8, $16 - JBE cmp_0through16 + JBE _0through16 MOVOU (SI), X0 MOVOU (DI), X1 PCMPEQB X0, X1 PMOVMSKB X1, AX XORQ $0xffff, AX // convert EQ to NE - JNE cmp_diff16 // branch if at least one byte is not equal + JNE diff16 // branch if at least one byte is not equal ADDQ $16, SI ADDQ $16, DI SUBQ $16, R8 - JMP cmp_loop + JMP loop // AX = bit mask of differences -cmp_diff16: +diff16: BSFQ AX, BX // index of first byte that differs XORQ AX, AX ADDQ BX, SI @@ -868,23 +868,23 @@ cmp_diff16: RET // 0 through 16 bytes left, alen>=8, blen>=8 -cmp_0through16: +_0through16: CMPQ R8, $8 - JBE cmp_0through8 + JBE _0through8 MOVQ (SI), AX MOVQ (DI), CX CMPQ AX, CX - JNE cmp_diff8 -cmp_0through8: + JNE diff8 +_0through8: ADDQ R8, SI ADDQ R8, DI MOVQ -8(SI), AX MOVQ -8(DI), CX CMPQ AX, CX - JEQ cmp_allsame + JEQ allsame // AX and CX contain parts of a and b that differ. -cmp_diff8: +diff8: BSWAPQ AX // reverse order of bytes BSWAPQ CX XORQ AX, CX @@ -895,46 +895,46 @@ cmp_diff8: RET // 0-7 bytes in common -cmp_small: +small: LEAQ (R8*8), CX // bytes left -> bits left NEGQ CX // - bits lift (== 64 - bits left mod 64) - JEQ cmp_allsame + JEQ allsame // load bytes of a into high bytes of AX CMPB SI, $0xf8 - JA cmp_si_high + JA si_high MOVQ (SI), SI - JMP cmp_si_finish -cmp_si_high: + JMP si_finish +si_high: ADDQ R8, SI MOVQ -8(SI), SI SHRQ CX, SI -cmp_si_finish: +si_finish: SHLQ CX, SI // load bytes of b in to high bytes of BX CMPB DI, $0xf8 - JA cmp_di_high + JA di_high MOVQ (DI), DI - JMP cmp_di_finish -cmp_di_high: + JMP di_finish +di_high: ADDQ R8, DI MOVQ -8(DI), DI SHRQ CX, DI -cmp_di_finish: +di_finish: SHLQ CX, DI BSWAPQ SI // reverse order of bytes BSWAPQ DI XORQ SI, DI // find bit differences - JEQ cmp_allsame + JEQ allsame BSRQ DI, CX // index of highest bit difference SHRQ CX, SI // move a's bit to bottom ANDQ $1, SI // mask bit LEAQ -1(SI*2), AX // 1/0 => +1/-1 RET -cmp_allsame: +allsame: XORQ AX, AX XORQ CX, CX CMPQ BX, DX @@ -969,7 +969,7 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0 MOVL SI, DI CMPL BX, $16 - JLT indexbyte_small + JLT small // round up to first 16-byte boundary TESTL $15, SI @@ -1027,7 +1027,7 @@ failure: RET // handle for lengths < 16 -indexbyte_small: +small: MOVL BX, CX REPN; SCASB JZ success diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index 621d13187..8942b11ac 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -492,7 +492,7 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0 MOVW g_m(g), R8 MOVW m_g0(R8), R3 CMP R3, g - BEQ asmcgocall_g0 + BEQ g0 BL gosave<>(SB) MOVW R0, R5 MOVW R3, R0 @@ -501,7 +501,7 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0 MOVW (g_sched+gobuf_sp)(g), R13 // Now on a scheduling stack (a pthread-created stack). -asmcgocall_g0: +g0: SUB $24, R13 BIC $0x7, R13 // alignment for gcc ABI MOVW R4, 20(R13) // save old g @@ -736,13 +736,13 @@ TEXT runtime·memeq(SB),NOSPLIT,$-4-13 ADD R1, R3, R6 MOVW $1, R0 MOVB R0, ret+12(FP) -_next2: +loop: CMP R1, R6 RET.EQ MOVBU.P 1(R1), R4 MOVBU.P 1(R2), R5 CMP R4, R5 - BEQ _next2 + BEQ loop MOVW $0, R0 MOVB R0, ret+12(FP) @@ -765,13 +765,13 @@ TEXT runtime·eqstring(SB),NOSPLIT,$-4-17 CMP R2, R3 RET.EQ ADD R2, R0, R6 -_eqnext: +loop: CMP R2, R6 RET.EQ MOVBU.P 1(R2), R4 MOVBU.P 1(R3), R5 CMP R4, R5 - BEQ _eqnext + BEQ loop MOVB R7, v+16(FP) RET @@ -786,26 +786,26 @@ TEXT bytes·Equal(SB),NOSPLIT,$0 MOVW b_len+16(FP), R3 CMP R1, R3 // unequal lengths are not equal - B.NE _notequal + B.NE notequal MOVW a+0(FP), R0 MOVW b+12(FP), R2 ADD R0, R1 // end -_byteseq_next: +loop: CMP R0, R1 - B.EQ _equal // reached the end + B.EQ equal // reached the end MOVBU.P 1(R0), R4 MOVBU.P 1(R2), R5 CMP R4, R5 - B.EQ _byteseq_next + B.EQ loop -_notequal: +notequal: MOVW $0, R0 MOVBU R0, ret+24(FP) RET -_equal: +equal: MOVW $1, R0 MOVBU R0, ret+24(FP) RET diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index 21220e5cb..f77658032 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -699,7 +699,7 @@ TEXT runtime·memeq(SB),NOSPLIT,$-8-25 SUB $1, R3 SUB $1, R4 ADD R3, R5, R8 -_next: +loop: CMP R3, R8 BNE 4(PC) MOVD $1, R3 @@ -708,7 +708,7 @@ _next: MOVBZU 1(R3), R6 MOVBZU 1(R4), R7 CMP R6, R7 - BEQ _next + BEQ loop MOVB R0, ret+24(FP) RETURN @@ -720,14 +720,14 @@ TEXT runtime·eqstring(SB),NOSPLIT,$0-33 MOVD s1len+8(FP), R4 MOVD s2len+24(FP), R5 CMP R4, R5 - BNE str_noteq + BNE noteq MOVD s1str+0(FP), R3 MOVD s2str+16(FP), R4 SUB $1, R3 SUB $1, R4 ADD R3, R5, R8 -eq_next: +loop: CMP R3, R8 BNE 4(PC) MOVD $1, R3 @@ -736,8 +736,8 @@ eq_next: MOVBZU 1(R3), R6 MOVBZU 1(R4), R7 CMP R6, R7 - BEQ eq_next -str_noteq: + BEQ loop +noteq: MOVB R0, ret+32(FP) RETURN @@ -747,7 +747,7 @@ TEXT bytes·Equal(SB),NOSPLIT,$0-49 MOVD b_len+32(FP), R4 CMP R3, R4 // unequal lengths are not equal - BNE _notequal + BNE noteq MOVD a+0(FP), R5 MOVD b+24(FP), R6 @@ -755,19 +755,19 @@ TEXT bytes·Equal(SB),NOSPLIT,$0-49 SUB $1, R6 ADD R5, R3 // end-1 -_byteseq_next: +loop: CMP R5, R3 - BEQ _equal // reached the end + BEQ equal // reached the end MOVBZU 1(R5), R4 MOVBZU 1(R6), R7 CMP R4, R7 - BEQ _byteseq_next + BEQ loop -_notequal: +noteq: MOVBZ R0, ret+48(FP) RETURN -_equal: +equal: MOVD $1, R3 MOVBZ R3, ret+48(FP) RETURN @@ -780,18 +780,18 @@ TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 SUB $1, R3 ADD R3, R4 // end-1 -_index_loop: +loop: CMP R3, R4 - BEQ _index_notfound + BEQ notfound MOVBZU 1(R3), R7 CMP R7, R5 - BNE _index_loop + BNE loop SUB R6, R3 // remove base MOVD R3, ret+32(FP) RETURN -_index_notfound: +notfound: MOVD $-1, R3 MOVD R3, ret+32(FP) RETURN @@ -804,18 +804,18 @@ TEXT strings·IndexByte(SB),NOSPLIT,$0 SUB $1, R3 ADD R3, R4 // end-1 -_index2_loop: +loop: CMP R3, R4 - BEQ _index2_notfound + BEQ notfound MOVBZU 1(R3), R7 CMP R7, R5 - BNE _index2_loop + BNE loop SUB R6, R3 // remove base MOVD R3, ret+24(FP) RETURN -_index2_notfound: +notfound: MOVD $-1, R3 MOVD R3, ret+24(FP) RETURN diff --git a/src/runtime/memclr_386.s b/src/runtime/memclr_386.s index 1520aea2e..3f20b69c8 100644 --- a/src/runtime/memclr_386.s +++ b/src/runtime/memclr_386.s @@ -15,31 +15,31 @@ TEXT runtime·memclr(SB), NOSPLIT, $0-8 XORL AX, AX // MOVOU seems always faster than REP STOSL. -clr_tail: +tail: TESTL BX, BX - JEQ clr_0 + JEQ _0 CMPL BX, $2 - JBE clr_1or2 + JBE _1or2 CMPL BX, $4 - JBE clr_3or4 + JBE _3or4 CMPL BX, $8 - JBE clr_5through8 + JBE _5through8 CMPL BX, $16 - JBE clr_9through16 + JBE _9through16 TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2 JEQ nosse2 PXOR X0, X0 CMPL BX, $32 - JBE clr_17through32 + JBE _17through32 CMPL BX, $64 - JBE clr_33through64 + JBE _33through64 CMPL BX, $128 - JBE clr_65through128 + JBE _65through128 CMPL BX, $256 - JBE clr_129through256 + JBE _129through256 // TODO: use branch table and BSR to make this just a single dispatch -clr_loop: +loop: MOVOU X0, 0(DI) MOVOU X0, 16(DI) MOVOU X0, 32(DI) @@ -59,40 +59,40 @@ clr_loop: SUBL $256, BX ADDL $256, DI CMPL BX, $256 - JAE clr_loop - JMP clr_tail + JAE loop + JMP tail -clr_1or2: +_1or2: MOVB AX, (DI) MOVB AX, -1(DI)(BX*1) RET -clr_0: +_0: RET -clr_3or4: +_3or4: MOVW AX, (DI) MOVW AX, -2(DI)(BX*1) RET -clr_5through8: +_5through8: MOVL AX, (DI) MOVL AX, -4(DI)(BX*1) RET -clr_9through16: +_9through16: MOVL AX, (DI) MOVL AX, 4(DI) MOVL AX, -8(DI)(BX*1) MOVL AX, -4(DI)(BX*1) RET -clr_17through32: +_17through32: MOVOU X0, (DI) MOVOU X0, -16(DI)(BX*1) RET -clr_33through64: +_33through64: MOVOU X0, (DI) MOVOU X0, 16(DI) MOVOU X0, -32(DI)(BX*1) MOVOU X0, -16(DI)(BX*1) RET -clr_65through128: +_65through128: MOVOU X0, (DI) MOVOU X0, 16(DI) MOVOU X0, 32(DI) @@ -102,7 +102,7 @@ clr_65through128: MOVOU X0, -32(DI)(BX*1) MOVOU X0, -16(DI)(BX*1) RET -clr_129through256: +_129through256: MOVOU X0, (DI) MOVOU X0, 16(DI) MOVOU X0, 32(DI) @@ -126,5 +126,5 @@ nosse2: REP STOSL ANDL $3, BX - JNE clr_tail + JNE tail RET diff --git a/src/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s index 94a2c7f23..ec24f1db2 100644 --- a/src/runtime/memclr_amd64.s +++ b/src/runtime/memclr_amd64.s @@ -15,30 +15,30 @@ TEXT runtime·memclr(SB), NOSPLIT, $0-16 XORQ AX, AX // MOVOU seems always faster than REP STOSQ. -clr_tail: +tail: TESTQ BX, BX - JEQ clr_0 + JEQ _0 CMPQ BX, $2 - JBE clr_1or2 + JBE _1or2 CMPQ BX, $4 - JBE clr_3or4 + JBE _3or4 CMPQ BX, $8 - JBE clr_5through8 + JBE _5through8 CMPQ BX, $16 - JBE clr_9through16 + JBE _9through16 PXOR X0, X0 CMPQ BX, $32 - JBE clr_17through32 + JBE _17through32 CMPQ BX, $64 - JBE clr_33through64 + JBE _33through64 CMPQ BX, $128 - JBE clr_65through128 + JBE _65through128 CMPQ BX, $256 - JBE clr_129through256 + JBE _129through256 // TODO: use branch table and BSR to make this just a single dispatch // TODO: for really big clears, use MOVNTDQ. -clr_loop: +loop: MOVOU X0, 0(DI) MOVOU X0, 16(DI) MOVOU X0, 32(DI) @@ -58,38 +58,38 @@ clr_loop: SUBQ $256, BX ADDQ $256, DI CMPQ BX, $256 - JAE clr_loop - JMP clr_tail + JAE loop + JMP tail -clr_1or2: +_1or2: MOVB AX, (DI) MOVB AX, -1(DI)(BX*1) RET -clr_0: +_0: RET -clr_3or4: +_3or4: MOVW AX, (DI) MOVW AX, -2(DI)(BX*1) RET -clr_5through8: +_5through8: MOVL AX, (DI) MOVL AX, -4(DI)(BX*1) RET -clr_9through16: +_9through16: MOVQ AX, (DI) MOVQ AX, -8(DI)(BX*1) RET -clr_17through32: +_17through32: MOVOU X0, (DI) MOVOU X0, -16(DI)(BX*1) RET -clr_33through64: +_33through64: MOVOU X0, (DI) MOVOU X0, 16(DI) MOVOU X0, -32(DI)(BX*1) MOVOU X0, -16(DI)(BX*1) RET -clr_65through128: +_65through128: MOVOU X0, (DI) MOVOU X0, 16(DI) MOVOU X0, 32(DI) @@ -99,7 +99,7 @@ clr_65through128: MOVOU X0, -32(DI)(BX*1) MOVOU X0, -16(DI)(BX*1) RET -clr_129through256: +_129through256: MOVOU X0, (DI) MOVOU X0, 16(DI) MOVOU X0, 32(DI) diff --git a/src/runtime/memclr_plan9_386.s b/src/runtime/memclr_plan9_386.s index b4b671f77..50f327b4e 100644 --- a/src/runtime/memclr_plan9_386.s +++ b/src/runtime/memclr_plan9_386.s @@ -10,40 +10,40 @@ TEXT runtime·memclr(SB), NOSPLIT, $0-8 MOVL n+4(FP), BX XORL AX, AX -clr_tail: +tail: TESTL BX, BX - JEQ clr_0 + JEQ _0 CMPL BX, $2 - JBE clr_1or2 + JBE _1or2 CMPL BX, $4 - JBE clr_3or4 + JBE _3or4 CMPL BX, $8 - JBE clr_5through8 + JBE _5through8 CMPL BX, $16 - JBE clr_9through16 + JBE _9through16 MOVL BX, CX SHRL $2, CX REP STOSL ANDL $3, BX - JNE clr_tail + JNE tail RET -clr_1or2: +_1or2: MOVB AX, (DI) MOVB AX, -1(DI)(BX*1) RET -clr_0: +_0: RET -clr_3or4: +_3or4: MOVW AX, (DI) MOVW AX, -2(DI)(BX*1) RET -clr_5through8: +_5through8: MOVL AX, (DI) MOVL AX, -4(DI)(BX*1) RET -clr_9through16: +_9through16: MOVL AX, (DI) MOVL AX, 4(DI) MOVL AX, -8(DI)(BX*1) diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index bdea28c7c..15b18ff8f 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -140,20 +140,20 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0 MOVQ g_racectx(R14), RARG0 // goroutine context // Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss). CMPQ RARG1, runtime·racearenastart(SB) - JB racecalladdr_data + JB data CMPQ RARG1, runtime·racearenaend(SB) - JB racecalladdr_call -racecalladdr_data: + JB call +data: MOVQ $runtime·noptrdata(SB), R13 CMPQ RARG1, R13 - JB racecalladdr_ret + JB ret MOVQ $runtime·enoptrbss(SB), R13 CMPQ RARG1, R13 - JAE racecalladdr_ret -racecalladdr_call: + JAE ret +call: MOVQ AX, AX // w/o this 6a miscompiles this function JMP racecall<>(SB) -racecalladdr_ret: +ret: RET // func runtime·racefuncenter(pc uintptr) @@ -335,9 +335,9 @@ TEXT racecall<>(SB), NOSPLIT, $0-0 MOVQ SP, R12 // callee-saved, preserved across the CALL MOVQ m_g0(R13), R10 CMPQ R10, R14 - JE racecall_cont // already on g0 + JE call // already on g0 MOVQ (g_sched+gobuf_sp)(R10), SP -racecall_cont: +call: ANDQ $~15, SP // alignment for gcc ABI CALL AX MOVQ R12, SP diff --git a/src/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s index a961c71a8..3bf8b1d41 100644 --- a/src/runtime/sys_darwin_386.s +++ b/src/runtime/sys_darwin_386.s @@ -248,7 +248,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$40 MOVL BX, 0(SP) MOVL $runtime·badsignal(SB), AX CALL AX - JMP sigtramp_ret + JMP ret // save g MOVL DI, 20(SP) @@ -275,7 +275,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$40 MOVL 20(SP), DI MOVL DI, g(CX) -sigtramp_ret: +ret: // call sigreturn MOVL context+16(FP), CX MOVL style+4(FP), BX diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index bd397d72a..8a8928e06 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -211,7 +211,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64 MOVL DX, 0(SP) MOVQ $runtime·badsignal(SB), AX CALL AX - JMP sigtramp_ret + JMP ret // save g MOVQ R10, 48(SP) @@ -233,7 +233,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64 MOVQ 48(SP), R10 MOVQ R10, g(BX) -sigtramp_ret: +ret: // call sigreturn MOVL $(0x2000000+184), AX // sigreturn(ucontext, infostyle) MOVQ 32(SP), DI // saved ucontext diff --git a/src/runtime/sys_dragonfly_386.s b/src/runtime/sys_dragonfly_386.s index 161eaec19..71ece9ecb 100644 --- a/src/runtime/sys_dragonfly_386.s +++ b/src/runtime/sys_dragonfly_386.s @@ -217,7 +217,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44 MOVL BX, 0(SP) MOVL $runtime·badsignal(SB), AX CALL AX - JMP sigtramp_ret + JMP ret // save g MOVL DI, 20(SP) @@ -243,7 +243,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44 MOVL 20(SP), BX MOVL BX, g(CX) -sigtramp_ret: +ret: // call sigreturn MOVL context+8(FP), AX MOVL $0, 0(SP) // syscall gap diff --git a/src/runtime/sys_freebsd_386.s b/src/runtime/sys_freebsd_386.s index 2c40fc433..66d03c27d 100644 --- a/src/runtime/sys_freebsd_386.s +++ b/src/runtime/sys_freebsd_386.s @@ -197,7 +197,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44 MOVL BX, 0(SP) MOVL $runtime·badsignal(SB), AX CALL AX - JMP sigtramp_ret + JMP ret // save g MOVL DI, 20(SP) @@ -223,7 +223,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44 MOVL 20(SP), BX MOVL BX, g(CX) -sigtramp_ret: +ret: // call sigreturn MOVL context+8(FP), AX MOVL $0, 0(SP) // syscall gap diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 33b91e872..d8d86ffad 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -115,7 +115,7 @@ TEXT time·now(SB),NOSPLIT,$16 // That leaves 104 for the gettime code to use. Hope that's enough! MOVQ runtime·__vdso_clock_gettime_sym(SB), AX CMPQ AX, $0 - JEQ fallback_gtod + JEQ fallback MOVL $0, DI // CLOCK_REALTIME LEAQ 0(SP), SI CALL AX @@ -124,7 +124,7 @@ TEXT time·now(SB),NOSPLIT,$16 MOVQ AX, sec+0(FP) MOVL DX, nsec+8(FP) RET -fallback_gtod: +fallback: LEAQ 0(SP), DI MOVQ $0, SI MOVQ runtime·__vdso_gettimeofday_sym(SB), AX @@ -141,7 +141,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16 // See comment above in time.now. MOVQ runtime·__vdso_clock_gettime_sym(SB), AX CMPQ AX, $0 - JEQ fallback_gtod_nt + JEQ fallback MOVL $1, DI // CLOCK_MONOTONIC LEAQ 0(SP), SI CALL AX @@ -153,7 +153,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16 ADDQ DX, AX MOVQ AX, ret+0(FP) RET -fallback_gtod_nt: +fallback: LEAQ 0(SP), DI MOVQ $0, SI MOVQ runtime·__vdso_gettimeofday_sym(SB), AX diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index bd285f399..033a03642 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -373,20 +373,20 @@ TEXT cas<>(SB),NOSPLIT,$0 TEXT runtime·cas(SB),NOSPLIT,$0 MOVW ptr+0(FP), R2 MOVW old+4(FP), R0 -casagain: +loop: MOVW new+8(FP), R1 BL cas<>(SB) - BCC cascheck + BCC check MOVW $1, R0 MOVB R0, ret+12(FP) RET -cascheck: +check: // Kernel lies; double-check. MOVW ptr+0(FP), R2 MOVW old+4(FP), R0 MOVW 0(R2), R3 CMP R0, R3 - BEQ casagain + BEQ loop MOVW $0, R0 MOVB R0, ret+12(FP) RET diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s index 47985f31f..16cd721d9 100644 --- a/src/runtime/sys_nacl_386.s +++ b/src/runtime/sys_nacl_386.s @@ -293,7 +293,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0 MOVL $0, 0(SP) MOVL $runtime·badsignal(SB), AX CALL AX - JMP sigtramp_ret + JMP ret // save g MOVL DI, 20(SP) @@ -317,7 +317,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0 MOVL 20(SP), BX MOVL BX, g(CX) -sigtramp_ret: +ret: // Enable exceptions again. NACL_SYSCALL(SYS_exception_clear_flag) diff --git a/src/runtime/sys_nacl_amd64p32.s b/src/runtime/sys_nacl_amd64p32.s index c30c2a893..06a0dc5dd 100644 --- a/src/runtime/sys_nacl_amd64p32.s +++ b/src/runtime/sys_nacl_amd64p32.s @@ -338,7 +338,6 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80 MOVL 20(SP), BX MOVL BX, g(CX) -sigtramp_ret: // Enable exceptions again. NACL_SYSCALL(SYS_exception_clear_flag) diff --git a/src/runtime/sys_nacl_arm.s b/src/runtime/sys_nacl_arm.s index d354ab483..432deadf4 100644 --- a/src/runtime/sys_nacl_arm.s +++ b/src/runtime/sys_nacl_arm.s @@ -269,7 +269,6 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80 // restore g MOVW 20(R13), g -sigtramp_ret: // Enable exceptions again. NACL_SYSCALL(SYS_exception_clear_flag) diff --git a/src/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s index 5cda7768a..b1ae5ecee 100644 --- a/src/runtime/sys_openbsd_386.s +++ b/src/runtime/sys_openbsd_386.s @@ -186,7 +186,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44 MOVL BX, 0(SP) MOVL $runtime·badsignal(SB), AX CALL AX - JMP sigtramp_ret + JMP ret // save g MOVL DI, 20(SP) @@ -212,7 +212,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$44 MOVL 20(SP), BX MOVL BX, g(CX) -sigtramp_ret: +ret: // call sigreturn MOVL context+8(FP), AX MOVL $0, 0(SP) // syscall gap diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s index 0ebdab6ee..3981893b0 100644 --- a/src/runtime/sys_solaris_amd64.s +++ b/src/runtime/sys_solaris_amd64.s @@ -287,24 +287,24 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0 // Execute call on m->g0. get_tls(R15) CMPQ R15, $0 - JE usleep1_noswitch + JE noswitch MOVQ g(R15), R13 CMPQ R13, $0 - JE usleep1_noswitch + JE noswitch MOVQ g_m(R13), R13 CMPQ R13, $0 - JE usleep1_noswitch + JE noswitch // TODO(aram): do something about the cpu profiler here. MOVQ m_g0(R13), R14 CMPQ g(R15), R14 - JNE usleep1_switch + JNE switch // executing on m->g0 already CALL AX RET -usleep1_switch: +switch: // Switch to m->g0 stack and back. MOVQ (g_sched+gobuf_sp)(R14), R14 MOVQ SP, -8(R14) @@ -313,7 +313,7 @@ usleep1_switch: MOVQ 0(SP), SP RET -usleep1_noswitch: +noswitch: // Not a Go-managed thread. Do not switch stack. CALL AX RET diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s index 932fe9dd2..13fb5bdc9 100644 --- a/src/runtime/sys_windows_386.s +++ b/src/runtime/sys_windows_386.s @@ -106,7 +106,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 MOVL g_m(DX), BX MOVL m_g0(BX), BX CMPL DX, BX - JEQ sigtramp_g0 + JEQ g0 // switch to the g0 stack get_tls(BP) @@ -123,7 +123,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 MOVL SP, 36(DI) MOVL DI, SP -sigtramp_g0: +g0: MOVL 0(CX), BX // ExceptionRecord* MOVL 4(CX), CX // Context* MOVL BX, 0(SP) @@ -383,12 +383,12 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0 MOVL m_g0(BP), SI CMPL g(CX), SI - JNE usleep1_switch + JNE switch // executing on m->g0 already CALL AX - JMP usleep1_ret + JMP ret -usleep1_switch: +switch: // Switch to m->g0 stack and back. MOVL (g_sched+gobuf_sp)(SI), SI MOVL SP, -4(SI) @@ -396,7 +396,7 @@ usleep1_switch: CALL AX MOVL 0(SP), SP -usleep1_ret: +ret: get_tls(CX) MOVL g(CX), BP MOVL g_m(BP), BP diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index e6190ce68..8b95f6d6c 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -138,7 +138,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 MOVQ g_m(DX), BX MOVQ m_g0(BX), BX CMPQ DX, BX - JEQ sigtramp_g0 + JEQ g0 // switch to g0 stack get_tls(BP) @@ -157,7 +157,7 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 MOVQ SP, 104(DI) MOVQ DI, SP -sigtramp_g0: +g0: MOVQ 0(CX), BX // ExceptionRecord* MOVQ 8(CX), CX // Context* MOVQ BX, 0(SP) @@ -407,12 +407,12 @@ TEXT runtime·usleep1(SB),NOSPLIT,$0 MOVQ m_g0(R13), R14 CMPQ g(R15), R14 - JNE usleep1_switch + JNE switch // executing on m->g0 already CALL AX - JMP usleep1_ret + JMP ret -usleep1_switch: +switch: // Switch to m->g0 stack and back. MOVQ (g_sched+gobuf_sp)(R14), R14 MOVQ SP, -8(R14) @@ -420,7 +420,7 @@ usleep1_switch: CALL AX MOVQ 0(SP), SP -usleep1_ret: +ret: MOVQ $0, m_libcallsp(R13) RET -- cgit v1.2.1 From f65bb028c5ceb4fb213b103f24a85f17cf67ac39 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 30 Oct 2014 10:16:03 -0400 Subject: [dev.garbage] cmd/gc, runtime: implement write barriers in terms of writebarrierptr This CL implements the many multiword write barriers by calling writebarrierptr, so that only writebarrierptr needs the actual barrier. In lieu of an actual barrier, writebarrierptr checks that the value being copied is not a small non-zero integer. This is enough to shake out bugs where the barrier is being called when it should not (for non-pointer values). It also found a few tests in sync/atomic that were being too clever. This CL adds a write barrier for the memory moved during the builtin copy function, which I forgot when inserting barriers for Go 1.4. This CL re-enables some write barriers that were disabled for Go 1.4. Those were disabled because it is possible to change the generated code so that they are unnecessary most of the time, but we have not changed the generated code yet. For safety they must be enabled. None of this is terribly efficient. We are aiming for correct first. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/168770043 --- src/cmd/api/goapi.go | 1 + src/cmd/gc/builtin.c | 29 ++++++- src/cmd/gc/runtime.go | 31 ++++++- src/cmd/gc/typecheck.c | 6 +- src/cmd/gc/walk.c | 46 +++++++--- src/run.bash | 3 +- src/runtime/malloc.go | 33 +++++++ src/runtime/mgc0.go | 104 +++++++++++++++++----- src/runtime/mgc0.h | 2 +- src/runtime/wbfat.go | 190 +++++++++++++++++++++++++++++++++++++++++ src/runtime/wbfat_gen.go | 41 +++++++++ src/sync/atomic/atomic_test.go | 8 +- 12 files changed, 447 insertions(+), 47 deletions(-) create mode 100644 src/runtime/wbfat.go create mode 100644 src/runtime/wbfat_gen.go (limited to 'src') diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 5a8c87603..e49ba33bb 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -405,6 +405,7 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) { " note struct{};" + " p struct{};" + " parfor struct{};" + + " slice struct{};" + " slicetype struct{};" + " stkframe struct{};" + " sudog struct{};" + diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c index fbca4ee5f..bd3fca167 100644 --- a/src/cmd/gc/builtin.c +++ b/src/cmd/gc/builtin.c @@ -86,10 +86,33 @@ char *runtimeimport = "func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n" "func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n" - "func @\"\".writebarrierfat2 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" - "func @\"\".writebarrierfat3 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" - "func @\"\".writebarrierfat4 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat01 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat10 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat11 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat0111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1000 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" + "func @\"\".writebarrierfat1111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n" "func @\"\".writebarrierfat (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n" + "func @\"\".writebarriercopy (@\"\".typ·2 *byte, @\"\".dst·3 any, @\"\".src·4 any) (? int)\n" "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n" "func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n" "func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n" diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index 0fb15c265..38bf6abb6 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -115,10 +115,35 @@ func writebarrieriface(dst *any, src any) // The unused *byte argument makes sure that src is 2-pointer-aligned, // which is the maximum alignment on NaCl amd64p32 // (and possibly on 32-bit systems if we start 64-bit aligning uint64s). -func writebarrierfat2(dst *any, _ *byte, src any) -func writebarrierfat3(dst *any, _ *byte, src any) -func writebarrierfat4(dst *any, _ *byte, src any) +// The bitmap in the name tells which words being copied are pointers. +func writebarrierfat01(dst *any, _ *byte, src any) +func writebarrierfat10(dst *any, _ *byte, src any) +func writebarrierfat11(dst *any, _ *byte, src any) +func writebarrierfat001(dst *any, _ *byte, src any) +func writebarrierfat010(dst *any, _ *byte, src any) +func writebarrierfat011(dst *any, _ *byte, src any) +func writebarrierfat100(dst *any, _ *byte, src any) +func writebarrierfat101(dst *any, _ *byte, src any) +func writebarrierfat110(dst *any, _ *byte, src any) +func writebarrierfat111(dst *any, _ *byte, src any) +func writebarrierfat0001(dst *any, _ *byte, src any) +func writebarrierfat0010(dst *any, _ *byte, src any) +func writebarrierfat0011(dst *any, _ *byte, src any) +func writebarrierfat0100(dst *any, _ *byte, src any) +func writebarrierfat0101(dst *any, _ *byte, src any) +func writebarrierfat0110(dst *any, _ *byte, src any) +func writebarrierfat0111(dst *any, _ *byte, src any) +func writebarrierfat1000(dst *any, _ *byte, src any) +func writebarrierfat1001(dst *any, _ *byte, src any) +func writebarrierfat1010(dst *any, _ *byte, src any) +func writebarrierfat1011(dst *any, _ *byte, src any) +func writebarrierfat1100(dst *any, _ *byte, src any) +func writebarrierfat1101(dst *any, _ *byte, src any) +func writebarrierfat1110(dst *any, _ *byte, src any) +func writebarrierfat1111(dst *any, _ *byte, src any) + func writebarrierfat(typ *byte, dst *any, src *any) +func writebarriercopy(typ *byte, dst any, src any) int func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 714c66268..f05d8022d 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -2891,7 +2891,8 @@ typecheckas(Node *n) case OSLICE3: case OSLICESTR: // For x = x[0:y], x can be updated in place, without touching pointer. - if(samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left))) + // TODO(rsc): Reenable once it is actually updated in place without touching the pointer. + if(0 && samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left))) n->right->reslice = 1; break; @@ -2899,7 +2900,8 @@ typecheckas(Node *n) // For x = append(x, ...), x can be updated in place when there is capacity, // without touching the pointer; otherwise the emitted code to growslice // can take care of updating the pointer, and only in that case. - if(n->right->list != nil && samesafeexpr(n->left, n->right->list->n)) + // TODO(rsc): Reenable once the emitted code does update the pointer. + if(0 && n->right->list != nil && samesafeexpr(n->left, n->right->list->n)) n->right->reslice = 1; break; } diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index d4d0f449c..7b502eb60 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -6,6 +6,7 @@ #include #include "go.h" #include "../ld/textflag.h" +#include "../../runtime/mgc0.h" static Node* walkprint(Node*, NodeList**); static Node* writebarrierfn(char*, Type*, Type*); @@ -1988,14 +1989,15 @@ applywritebarrier(Node *n, NodeList **init) { Node *l, *r; Type *t; + vlong x; + static Bvec *bv; + char name[32]; if(n->left && n->right && needwritebarrier(n->left, n->right)) { t = n->left->type; l = nod(OADDR, n->left, N); l->etype = 1; // addr does not escape if(t->width == widthptr) { - n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init, - l, n->right); } else if(t->etype == TSTRING) { n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init, l, n->right); @@ -2005,14 +2007,33 @@ applywritebarrier(Node *n, NodeList **init) } else if(isinter(t)) { n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init, l, n->right); - } else if(t->width == 2*widthptr) { - n = mkcall1(writebarrierfn("writebarrierfat2", t, n->right->type), T, init, - l, nodnil(), n->right); - } else if(t->width == 3*widthptr) { - n = mkcall1(writebarrierfn("writebarrierfat3", t, n->right->type), T, init, - l, nodnil(), n->right); - } else if(t->width == 4*widthptr) { - n = mkcall1(writebarrierfn("writebarrierfat4", t, n->right->type), T, init, + } else if(t->width <= 4*widthptr) { + x = 0; + if(bv == nil) + bv = bvalloc(BitsPerPointer*4); + bvresetall(bv); + twobitwalktype1(t, &x, bv); + // The bvgets are looking for BitsPointer in successive slots. + enum { + PtrBit = 1, + }; + if(BitsPointer != (1<width/widthptr) { + case 2: + snprint(name, sizeof name, "writebarrierfat%d%d", + bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit)); + break; + case 3: + snprint(name, sizeof name, "writebarrierfat%d%d%d", + bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit)); + break; + case 4: + snprint(name, sizeof name, "writebarrierfat%d%d%d%d", + bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit), bvget(bv, 3*BitsPerPointer+PtrBit)); + break; + } + n = mkcall1(writebarrierfn(name, t, n->right->type), T, init, l, nodnil(), n->right); } else { r = n->right; @@ -2874,6 +2895,11 @@ copyany(Node *n, NodeList **init, int runtimecall) { Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn; NodeList *l; + + if(haspointers(n->left->type->type)) { + fn = writebarrierfn("writebarriercopy", n->left->type, n->right->type); + return mkcall1(fn, n->type, init, typename(n->left->type->type), n->left, n->right); + } if(runtimecall) { if(n->right->type->etype == TSTRING) diff --git a/src/run.bash b/src/run.bash index 3c9430c87..91f12a174 100755 --- a/src/run.bash +++ b/src/run.bash @@ -66,7 +66,8 @@ go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10 # Race detector only supported on Linux, FreeBSD and OS X, # and only on amd64, and only when cgo is enabled. -case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in +# DISABLED until we get garbage collection working. +case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED-XXX-DISABLED" in linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1) echo echo '# Testing race detector.' diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 020f87a7a..56f4f7cd7 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -245,6 +245,8 @@ func mallocgc(size uintptr, typ *_type, flags int) unsafe.Pointer { masksize = masksize * pointersPerByte / 8 // 4 bits per word masksize++ // unroll flag in the beginning if masksize > maxGCMask && typ.gc[1] != 0 { + // write barriers have not been updated to deal with this case yet. + gothrow("maxGCMask too small for now") // If the mask is too large, unroll the program directly // into the GC bitmap. It's 7 times slower than copying // from the pre-unrolled mask, but saves 1/16 of type size @@ -344,6 +346,37 @@ marked: return x } +func loadPtrMask(typ *_type) []uint8 { + var ptrmask *uint8 + nptr := (uintptr(typ.size) + ptrSize - 1) / ptrSize + if typ.kind&kindGCProg != 0 { + masksize := nptr + if masksize%2 != 0 { + masksize *= 2 // repeated + } + masksize = masksize * pointersPerByte / 8 // 4 bits per word + masksize++ // unroll flag in the beginning + if masksize > maxGCMask && typ.gc[1] != 0 { + // write barriers have not been updated to deal with this case yet. + gothrow("maxGCMask too small for now") + } + ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0]))) + // Check whether the program is already unrolled + // by checking if the unroll flag byte is set + maskword := uintptr(atomicloadp(unsafe.Pointer(ptrmask))) + if *(*uint8)(unsafe.Pointer(&maskword)) == 0 { + mp := acquirem() + mp.ptrarg[0] = unsafe.Pointer(typ) + onM(unrollgcprog_m) + releasem(mp) + } + ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte + } else { + ptrmask = (*uint8)(unsafe.Pointer(typ.gc[0])) // pointer to unrolled mask + } + return (*[1 << 30]byte)(unsafe.Pointer(ptrmask))[:(nptr+1)/2] +} + // implementation of new builtin func newobject(typ *_type) unsafe.Pointer { flags := 0 diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index 3a7204b54..75678c522 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -83,54 +83,112 @@ func bgsweep() { } } +const ( + _PoisonGC = 0xf969696969696969 & ^uintptr(0) + _PoisonStack = 0x6868686868686868 & ^uintptr(0) +) + // NOTE: Really dst *unsafe.Pointer, src unsafe.Pointer, // but if we do that, Go inserts a write barrier on *dst = src. //go:nosplit func writebarrierptr(dst *uintptr, src uintptr) { + if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) { + onM(func() { gothrow("bad pointer in write barrier") }) + } *dst = src } //go:nosplit func writebarrierstring(dst *[2]uintptr, src [2]uintptr) { - dst[0] = src[0] + writebarrierptr(&dst[0], src[0]) dst[1] = src[1] } //go:nosplit func writebarrierslice(dst *[3]uintptr, src [3]uintptr) { - dst[0] = src[0] + writebarrierptr(&dst[0], src[0]) dst[1] = src[1] dst[2] = src[2] } //go:nosplit func writebarrieriface(dst *[2]uintptr, src [2]uintptr) { - dst[0] = src[0] - dst[1] = src[1] + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) } -//go:nosplit -func writebarrierfat2(dst *[2]uintptr, _ *byte, src [2]uintptr) { - dst[0] = src[0] - dst[1] = src[1] -} +//go:generate go run wbfat_gen.go -- wbfat.go +// +// The above line generates multiword write barriers for +// all the combinations of ptr+scalar up to four words. +// The implementations are written to wbfat.go. //go:nosplit -func writebarrierfat3(dst *[3]uintptr, _ *byte, src [3]uintptr) { - dst[0] = src[0] - dst[1] = src[1] - dst[2] = src[2] -} - -//go:nosplit -func writebarrierfat4(dst *[4]uintptr, _ *byte, src [4]uintptr) { - dst[0] = src[0] - dst[1] = src[1] - dst[2] = src[2] - dst[3] = src[3] +func writebarrierfat(typ *_type, dst, src unsafe.Pointer) { + mask := loadPtrMask(typ) + nptr := typ.size / ptrSize + for i := uintptr(0); i < nptr; i += 2 { + bits := mask[i/2] + if (bits>>2)&_BitsMask == _BitsPointer { + writebarrierptr((*uintptr)(dst), *(*uintptr)(src)) + } else { + *(*uintptr)(dst) = *(*uintptr)(src) + } + dst = add(dst, ptrSize) + src = add(src, ptrSize) + if i+1 == nptr { + break + } + bits >>= 4 + if (bits>>2)&_BitsMask == _BitsPointer { + writebarrierptr((*uintptr)(dst), *(*uintptr)(src)) + } else { + *(*uintptr)(dst) = *(*uintptr)(src) + } + dst = add(dst, ptrSize) + src = add(src, ptrSize) + } } //go:nosplit -func writebarrierfat(typ *_type, dst, src unsafe.Pointer) { - memmove(dst, src, typ.size) +func writebarriercopy(typ *_type, dst, src slice) int { + n := dst.len + if n > src.len { + n = src.len + } + if n == 0 { + return 0 + } + dstp := unsafe.Pointer(dst.array) + srcp := unsafe.Pointer(src.array) + + if uintptr(srcp) < uintptr(dstp) && uintptr(srcp)+uintptr(n)*typ.size > uintptr(dstp) { + // Overlap with src before dst. + // Copy backward, being careful not to move dstp/srcp + // out of the array they point into. + dstp = add(dstp, uintptr(n-1)*typ.size) + srcp = add(srcp, uintptr(n-1)*typ.size) + i := uint(0) + for { + writebarrierfat(typ, dstp, srcp) + if i++; i >= n { + break + } + dstp = add(dstp, -typ.size) + srcp = add(srcp, -typ.size) + } + } else { + // Copy forward, being careful not to move dstp/srcp + // out of the array they point into. + i := uint(0) + for { + writebarrierfat(typ, dstp, srcp) + if i++; i >= n { + break + } + dstp = add(dstp, typ.size) + srcp = add(srcp, typ.size) + } + } + return int(n) } diff --git a/src/runtime/mgc0.h b/src/runtime/mgc0.h index 64f818914..16fbe4665 100644 --- a/src/runtime/mgc0.h +++ b/src/runtime/mgc0.h @@ -56,7 +56,7 @@ enum { BitsEface = 3, // 64 bytes cover objects of size 1024/512 on 64/32 bits, respectively. - MaxGCMask = 64, + MaxGCMask = 65536, // TODO(rsc): change back to 64 }; // Bits in per-word bitmap. diff --git a/src/runtime/wbfat.go b/src/runtime/wbfat.go new file mode 100644 index 000000000..75c58b26b --- /dev/null +++ b/src/runtime/wbfat.go @@ -0,0 +1,190 @@ +// generated by wbfat_gen.go; use go generate + +package runtime + +//go:nosplit +func writebarrierfat01(dst *[2]uintptr, _ *byte, src [2]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) +} + +//go:nosplit +func writebarrierfat10(dst *[2]uintptr, _ *byte, src [2]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] +} + +//go:nosplit +func writebarrierfat11(dst *[2]uintptr, _ *byte, src [2]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) +} + +//go:nosplit +func writebarrierfat001(dst *[3]uintptr, _ *byte, src [3]uintptr) { + dst[0] = src[0] + dst[1] = src[1] + writebarrierptr(&dst[2], src[2]) +} + +//go:nosplit +func writebarrierfat010(dst *[3]uintptr, _ *byte, src [3]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) + dst[2] = src[2] +} + +//go:nosplit +func writebarrierfat011(dst *[3]uintptr, _ *byte, src [3]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) + writebarrierptr(&dst[2], src[2]) +} + +//go:nosplit +func writebarrierfat100(dst *[3]uintptr, _ *byte, src [3]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] + dst[2] = src[2] +} + +//go:nosplit +func writebarrierfat101(dst *[3]uintptr, _ *byte, src [3]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] + writebarrierptr(&dst[2], src[2]) +} + +//go:nosplit +func writebarrierfat110(dst *[3]uintptr, _ *byte, src [3]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) + dst[2] = src[2] +} + +//go:nosplit +func writebarrierfat111(dst *[3]uintptr, _ *byte, src [3]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) + writebarrierptr(&dst[2], src[2]) +} + +//go:nosplit +func writebarrierfat0001(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + dst[1] = src[1] + dst[2] = src[2] + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat0010(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + dst[1] = src[1] + writebarrierptr(&dst[2], src[2]) + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat0011(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + dst[1] = src[1] + writebarrierptr(&dst[2], src[2]) + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat0100(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) + dst[2] = src[2] + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat0101(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) + dst[2] = src[2] + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat0110(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) + writebarrierptr(&dst[2], src[2]) + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat0111(dst *[4]uintptr, _ *byte, src [4]uintptr) { + dst[0] = src[0] + writebarrierptr(&dst[1], src[1]) + writebarrierptr(&dst[2], src[2]) + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat1000(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] + dst[2] = src[2] + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat1001(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] + dst[2] = src[2] + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat1010(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] + writebarrierptr(&dst[2], src[2]) + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat1011(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + dst[1] = src[1] + writebarrierptr(&dst[2], src[2]) + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat1100(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) + dst[2] = src[2] + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat1101(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) + dst[2] = src[2] + writebarrierptr(&dst[3], src[3]) +} + +//go:nosplit +func writebarrierfat1110(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) + writebarrierptr(&dst[2], src[2]) + dst[3] = src[3] +} + +//go:nosplit +func writebarrierfat1111(dst *[4]uintptr, _ *byte, src [4]uintptr) { + writebarrierptr(&dst[0], src[0]) + writebarrierptr(&dst[1], src[1]) + writebarrierptr(&dst[2], src[2]) + writebarrierptr(&dst[3], src[3]) +} diff --git a/src/runtime/wbfat_gen.go b/src/runtime/wbfat_gen.go new file mode 100644 index 000000000..78d5b6271 --- /dev/null +++ b/src/runtime/wbfat_gen.go @@ -0,0 +1,41 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +package main + +import ( + "flag" + "fmt" + "log" + "os" +) + +func main() { + flag.Parse() + if flag.NArg() > 0 { + f, err := os.Create(flag.Arg(0)) + if err != nil { + log.Fatal(err) + } + os.Stdout = f + } + fmt.Printf("// generated by wbfat_gen.go; use go generate\n\n") + fmt.Printf("package runtime\n") + for i := uint(2); i <= 4; i++ { + for j := 1; j < 1< delta; delta += delta { + for delta := uintptr(1 << 16); delta+delta > delta; delta += delta { k := SwapPointer(&x.i, unsafe.Pointer(delta)) if uintptr(x.i) != delta || uintptr(k) != j { t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) @@ -456,7 +456,7 @@ func TestCompareAndSwapPointer(t *testing.T) { magicptr := uintptr(m) x.before = magicptr x.after = magicptr - for val := uintptr(1); val+val > val; val += val { + for val := uintptr(1 << 16); val+val > val; val += val { x.i = unsafe.Pointer(val) if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) { t.Fatalf("should have swapped %#x %#x", val, val+1) @@ -595,7 +595,7 @@ func TestLoadPointer(t *testing.T) { magicptr := uintptr(m) x.before = magicptr x.after = magicptr - for delta := uintptr(1); delta+delta > delta; delta += delta { + for delta := uintptr(1 << 16); delta+delta > delta; delta += delta { k := LoadPointer(&x.i) if k != x.i { t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) @@ -731,7 +731,7 @@ func TestStorePointer(t *testing.T) { x.before = magicptr x.after = magicptr v := unsafe.Pointer(uintptr(0)) - for delta := uintptr(1); delta+delta > delta; delta += delta { + for delta := uintptr(1 << 16); delta+delta > delta; delta += delta { StorePointer(&x.i, unsafe.Pointer(v)) if x.i != v { t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) -- cgit v1.2.1 From 9155768e48e7de0fd0d6297eaa932d4c489e3f38 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Tue, 4 Nov 2014 13:31:34 -0500 Subject: [dev.garbage] runtime: Add gc mark verification pass. This adds an independent mark phase to the GC that can be used to verify the the default concurrent mark phase has found all reachable objects. It uses the upper 2 bits of the boundary nibble to encode the mark leaving the lower bits to encode the boundary and the normal mark bit. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/167130043 --- src/runtime/heapdump.c | 15 +- src/runtime/malloc.go | 28 +++- src/runtime/mgc0.c | 428 +++++++++++++++++++++++++++++++++++++++---------- src/runtime/mgc0.h | 8 +- src/runtime/stack.c | 40 +---- src/runtime/stubs.go | 6 + 6 files changed, 382 insertions(+), 143 deletions(-) (limited to 'src') diff --git a/src/runtime/heapdump.c b/src/runtime/heapdump.c index 71da419f1..5ac37803b 100644 --- a/src/runtime/heapdump.c +++ b/src/runtime/heapdump.c @@ -259,20 +259,7 @@ dumpbv(BitVector *bv, uintptr offset) dumpint(offset + i / BitsPerPointer * PtrSize); break; case BitsMultiWord: - switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) { - default: - runtime·throw("unexpected garbage collection bits"); - case BitsIface: - dumpint(FieldKindIface); - dumpint(offset + i / BitsPerPointer * PtrSize); - i += BitsPerPointer; - break; - case BitsEface: - dumpint(FieldKindEface); - dumpint(offset + i / BitsPerPointer * PtrSize); - i += BitsPerPointer; - break; - } + runtime·throw("bumpbv unexpected garbage collection bits"); } } } diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 56f4f7cd7..274bae9a3 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -306,6 +306,18 @@ func mallocgc(size uintptr, typ *_type, flags int) unsafe.Pointer { } } marked: + + // GCmarkterminate allocates black + // All slots hold nil so no scanning is needed. + // This may be racing with GC so do it atomically if there can be + // a race marking the bit. + if gcphase == _GCmarktermination { + mp := acquirem() + mp.ptrarg[0] = x + onM(gcmarknewobject_m) + releasem(mp) + } + if raceenabled { racemalloc(x, size) } @@ -478,8 +490,12 @@ func gogc(force int32) { // Do a concurrent heap scan before we stop the world. onM(gcscan_m) + onM(gcinstallmarkwb_m) onM(stoptheworld) - + // onM(starttheworld) + // mark from roots scanned in gcscan_m. startthework when write barrier works + onM(gcmark_m) + // onM(stoptheworld) if mp != acquirem() { gothrow("gogc: rescheduled") } @@ -510,6 +526,8 @@ func gogc(force int32) { onM(gc_m) } + onM(gccheckmark_m) + // all done mp.gcing = 0 semrelease(&worldsema) @@ -524,6 +542,14 @@ func gogc(force int32) { } } +func GCcheckmarkenable() { + onM(gccheckmarkenable_m) +} + +func GCcheckmarkdisable() { + onM(gccheckmarkdisable_m) +} + // GC runs a garbage collection. func GC() { gogc(2) diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index f76d7c05c..e283f6ee8 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -155,12 +155,16 @@ extern int32 runtime·gcpercent; // uint32 runtime·worldsema = 1; +// It is a bug if bits does not have bitBoundary set but +// there are still some cases where this happens related +// to stack spans. typedef struct Markbits Markbits; struct Markbits { byte *bitp; // pointer to the byte holding xbits byte shift; // bits xbits needs to be shifted to get bits byte xbits; // byte holding all the bits from *bitp - byte bits; // bits relevant to corresponding slot. + byte bits; // mark and boundary bits relevant to corresponding slot. + byte tbits; // pointer||scalar bits relevant to corresponding slot. }; extern byte runtime·data[]; @@ -204,6 +208,11 @@ static bool inheap(byte*); static bool shaded(byte*); static void shade(byte*); static void slottombits(byte*, Markbits*); +static void atomicxor8(byte*, byte); +static bool ischeckmarked(Markbits*); +static bool ismarked(Markbits*); +static void clearcheckmarkbits(void); +static void clearcheckmarkbitsspan(MSpan*); void runtime·bgsweep(void); void runtime·finishsweep_m(void); @@ -228,6 +237,28 @@ struct WorkData { }; WorkData runtime·work; +// To help debug the concurrent GC we remark with the world +// stopped ensuring that any object encountered has their normal +// mark bit set. To do this we use an orthogonal bit +// pattern to indicate the object is marked. The following pattern +// uses the upper two bits in the object's bounday nibble. +// 01: scalar not marked +// 10: pointer not marked +// 11: pointer marked +// 00: scalar marked +// Xoring with 01 will flip the pattern from marked to unmarked and vica versa. +// The higher bit is 1 for pointers and 0 for scalars, whether the object +// is marked or not. +// The first nibble no longer holds the bitsDead pattern indicating that the +// there are no more pointers in the object. This information is held +// in the second nibble. + +// When marking an object if the bool checkmark is true one uses the above +// encoding, otherwise one uses the bitMarked bit in the lower two bits +// of the nibble. +static bool checkmark = false; +static bool gccheckmarkenable = false; + // Is address b in the known heap. If it doesn't have a valid gcmap // returns false. For example pointers into stacks will return false. static bool @@ -261,11 +292,14 @@ slottombits(byte *obj, Markbits *mbits) mbits->shift = (off % wordsPerBitmapByte) * gcBits; mbits->xbits = *mbits->bitp; mbits->bits = (mbits->xbits >> mbits->shift) & bitMask; + mbits->tbits = (mbits->xbits >> mbits->shift) & bitPtrMask; } // b is a pointer into the heap. // Find the start of the object refered to by b. // Set mbits to the associated bits from the bit map. +// If b is not a valid heap object return nil and +// undefined values in mbits. static byte* objectstart(byte *b, Markbits *mbits) { @@ -277,42 +311,27 @@ objectstart(byte *b, Markbits *mbits) obj = (byte*)((uintptr)b&~(PtrSize-1)); for(;;) { slottombits(obj, mbits); - if(mbits->bits&bitBoundary == bitBoundary) + if((mbits->bits&bitBoundary) == bitBoundary) break; - + // Not a beginning of a block, consult span table to find the block beginning. k = (uintptr)obj>>PageShift; x = k; x -= (uintptr)runtime·mheap.arena_start>>PageShift; s = runtime·mheap.spans[x]; if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse){ - if(s->state == MSpanStack) - break; // This is legit. - - // The following is catching some bugs left over from - // us not being rigerous about what data structures are - // hold valid pointers and different parts of the system - // considering different structures as roots. For example - // if there is a pointer into a stack that is left in - // a global data structure but that part of the runtime knows that - // those structures will be reinitialized before they are - // reused. Unfortunately the GC believes these roots are valid. - // Typically a stack gets moved and only the structures that part of - // the system knows are alive are updated. The span is freed - // after the stack copy and the pointer is still alive. This - // check is catching that bug but for now we will not throw, - // instead we will simply break out of this routine and depend - // on the caller to recognize that this pointer is not a valid - // heap pointer. I leave the code that catches the bug so that once - // resolved we can turn this check back on and throw. - - //runtime·printf("Runtime: Span weird: obj=%p, k=%p", obj, k); - //if (s == nil) - // runtime·printf(" s=nil\n"); - //else - // runtime·printf(" s->start=%p s->limit=%p, s->state=%d\n", s->start*PageSize, s->limit, s->state); - //runtime·throw("Blowup on weird span"); - break; // We are not in a real block throw?? + if(s != nil && s->state == MSpanStack) { + return nil; // This is legit. + } + + // The following ensures that we are rigorous about what data + // structures hold valid pointers + runtime·printf("runtime:objectstart Span weird: obj=%p, k=%p", obj, k); + if (s == nil) + runtime·printf(" s=nil\n"); + else + runtime·printf(" s->start=%p s->limit=%p, s->state=%d\n", s->start*PageSize, s->limit, s->state); + runtime·throw("objectstart: bad span"); } p = (byte*)((uintptr)s->start<sizeclass != 0) { @@ -333,6 +352,75 @@ objectstart(byte *b, Markbits *mbits) return obj; } +// Slow for now as we serialize this, since this is on a debug path +// speed is not critical at this point. +static Mutex xorlock; +static void +atomicxor8(byte *src, byte val) +{ + runtime·lock(&xorlock); + *src = *src^val; + runtime·unlock(&xorlock); +} + +// Mark using the checkmark scheme. +void +docheckmark(Markbits *mbits) +{ + // xor 01 moves 01(scalar unmarked) to 00(scalar marked) + // and 10(pointer unmarked) to 11(pointer marked) + atomicxor8(mbits->bitp, BitsCheckMarkXor<shift<<2); + return; +} + +// In the default scheme does mbits refer to a marked object. +static bool +ismarked(Markbits *mbits) +{ + if((mbits->bits&bitBoundary) != bitBoundary) + runtime·throw("ismarked: bits should have boundary bit set"); + return (mbits->bits&bitMarked) == bitMarked; +} + +// In the checkmark scheme does mbits refer to a marked object. +static bool +ischeckmarked(Markbits *mbits) +{ + if((mbits->bits&bitBoundary) != bitBoundary) + runtime·printf("runtime:ischeckmarked: bits should have boundary bit set\n"); + return mbits->tbits==BitsScalarMarked || mbits->tbits==BitsPointerMarked; +} + +// When in GCmarkterminate phase we allocate black. +void +runtime·gcmarknewobject_m(void) +{ + Markbits mbits; + byte *obj; + + if(runtime·gcphase != GCmarktermination) + runtime·throw("marking new object while not in mark termination phase"); + if(checkmark) // The world should be stopped so this should not happen. + runtime·throw("gcmarknewobject called while doing checkmark"); + + obj = g->m->ptrarg[0]; + slottombits((byte*)((uintptr)obj & (PtrSize-1)), &mbits); + + if((mbits.bits&bitMarked) != 0) + return; + + // Each byte of GC bitmap holds info for two words. + // If the current object is larger than two words, or if the object is one word + // but the object it shares the byte with is already marked, + // then all the possible concurrent updates are trying to set the same bit, + // so we can use a non-atomic update. + if((mbits.xbits&(bitMask|(bitMask<bits&bitMarked) != 0) - return wbuf; + if(checkmark) { + if(!ismarked(mbits)) { + runtime·printf("runtime:greyobject: checkmarks finds unexpected unmarked object obj=%p, mbits->bits=%x, *mbits->bitp=%x\n", obj, mbits->bits, *mbits->bitp); + } + if(ischeckmarked(mbits)) + return wbuf; + docheckmark(mbits); + } else { + // If marked we have nothing to do. + if((mbits->bits&bitMarked) != 0) + return wbuf; + + // Each byte of GC bitmap holds info for two words. + // If the current object is larger than two words, or if the object is one word + // but the object it shares the byte with is already marked, + // then all the possible concurrent updates are trying to set the same bit, + // so we can use a non-atomic update. + if((mbits->xbits&(bitMask|(bitMask<bitp = mbits->xbits | (bitMarked<shift); + else + runtime·atomicor8(mbits->bitp, bitMarked<shift); + } - // Each byte of GC bitmap holds info for two words. - // If the current object is larger than two words, or if the object is one word - // but the object it shares the byte with is already marked, - // then all the possible concurrent updates are trying to set the same bit, - // so we can use a non-atomic update. - if((mbits->xbits&(bitMask|(bitMask<bitp = mbits->xbits | (bitMarked<shift); - else - runtime·atomicor8(mbits->bitp, bitMarked<shift); - - if(((mbits->xbits>>(mbits->shift+2))&BitsMask) == BitsDead) + if (!checkmark && (((mbits->xbits>>(mbits->shift+2))&BitsMask) == BitsDead)) return wbuf; // noscan object // Queue the obj for scanning. The PREFETCH(obj) logic has been removed but @@ -398,6 +495,8 @@ scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf) // Find bits of the beginning of the object. if(ptrmask == nil) { b = objectstart(b, &mbits); + if(b == nil) + return wbuf; ptrbitp = mbits.bitp; //arena_start - off/wordsPerBitmapByte - 1; } for(i = 0; i < n; i += PtrSize) { @@ -407,6 +506,7 @@ scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf) bits = (ptrmask[(i/PtrSize)/4]>>(((i/PtrSize)%4)*BitsPerPointer))&BitsMask; } else { // Check if we have reached end of span. + // n is an overestimate of the size of the object. if((((uintptr)b+i)%PageSize) == 0 && runtime·mheap.spans[(b-arena_start)>>PageShift] != runtime·mheap.spans[(b+i-arena_start)>>PageShift]) break; @@ -414,7 +514,7 @@ scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf) bits = *ptrbitp; if(wordsPerBitmapByte != 2) runtime·throw("alg doesn't work for wordsPerBitmapByte != 2"); - j = ((uintptr)b+i)/PtrSize & 1; + j = ((uintptr)b+i)/PtrSize & 1; // j indicates upper nibble or lower nibble bits >>= gcBits*j; if(i == 0) bits &= ~bitBoundary; @@ -422,15 +522,19 @@ scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf) if((bits&bitBoundary) != 0 && i != 0) break; // reached beginning of the next object - bits = (bits>>2)&BitsMask; - if(bits == BitsDead) + bits = (bits&bitPtrMask)>>2; // bits refer to the type bits. + + if(i != 0 && bits == BitsDead) // BitsDead in first nibble not valid during checkmark break; // reached no-scan part of the object - } + } - if(bits <= BitsScalar) // Bits Scalar || BitsDead - continue; - if(bits != BitsPointer) { - runtime·printf("gc bits=%x\n", bits); + if(bits <= BitsScalar) // Bits Scalar || + // BitsDead || // default encoding + // BitsScalarMarked // checkmark encoding + continue; + + if((bits&BitsPointer) != BitsPointer) { + runtime·printf("gc checkmark=%d, b=%p ptrmask=%p, mbits.bitp=%p, mbits.xbits=%x, bits=%x\n", checkmark, b, ptrmask, mbits.bitp, mbits.xbits, bits); runtime·throw("unexpected garbage collection bits"); } @@ -442,6 +546,11 @@ scanobject(byte *b, uintptr n, byte *ptrmask, Workbuf *wbuf) // Mark the object. return some important bits. // We we combine the following two rotines we don't have to pass mbits or obj around. obj = objectstart(obj, &mbits); + // In the case of the span being MSpan_Stack mbits is useless and will not have + // the boundary bit set. It does not need to be greyed since it will be + // scanned using the scan stack mechanism. + if(obj == nil) + continue; wbuf = greyobject(obj, &mbits, wbuf); } return wbuf; @@ -548,7 +657,8 @@ markroot(ParFor *desc, uint32 i) s = runtime·work.spans[spanidx]; if(s->state != MSpanInUse) continue; - if(s->sweepgen != sg) { + if(!checkmark && s->sweepgen != sg) { + // sweepgen was updated (+2) during non-checkmark GC pass runtime·printf("sweep %d %d\n", s->sweepgen, sg); runtime·throw("gc: unswept span"); } @@ -616,9 +726,6 @@ markroot(ParFor *desc, uint32 i) } } -// wblock is used for creating new empty work buffer blocks. -static Mutex wblock; - // Get an empty work buffer off the work.empty list, // allocating new buffers as needed. static Workbuf* @@ -636,10 +743,8 @@ getempty(Workbuf *b) runtime·throw("getempty: workbuffer not empty, b->nobj not 0"); } if(b == nil) { - runtime·lock(&wblock); b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys); b->nobj = 0; - runtime·unlock(&wblock); } return b; } @@ -692,17 +797,6 @@ putpartial(Workbuf *b) } } -void -runtime·gcworkbuffree(Workbuf *b) -{ - if(b == nil) - return; - if(b->nobj == 0) - putempty(b); - else - putfull(b); -} - // Get a full work buffer off the work.full or a partially // filled one off the work.partial list. If nothing is available // wait until all the other gc helpers have finished and then @@ -906,11 +1000,18 @@ static bool shaded(byte *slot) { Markbits mbits; + byte *valid; if(!inheap(slot)) // non-heap slots considered grey return true; - objectstart(slot, &mbits); + valid = objectstart(slot, &mbits); + if(valid == nil) + return true; + + if(checkmark) + return ischeckmarked(&mbits); + return (mbits.bits&bitMarked) != 0; } @@ -930,7 +1031,9 @@ shade(byte *b) // Mark the object, return some important bits. // If we combine the following two rotines we don't have to pass mbits or obj around. obj = objectstart(b, &mbits); - wbuf = greyobject(obj, &mbits, wbuf); // augments the wbuf + if(obj != nil) + wbuf = greyobject(obj, &mbits, wbuf); // augments the wbuf + putpartial(wbuf); return; } @@ -969,6 +1072,7 @@ runtime·gcphasework(G *gp) scanstack(gp); break; case GCmark: + break; case GCmarktermination: scanstack(gp); // All available mark work will be emptied before returning. @@ -1104,6 +1208,9 @@ runtime·MSpan_Sweep(MSpan *s, bool preserve) Special *special, **specialp, *y; bool res, sweepgenset; + if(checkmark) + runtime·throw("MSpan_Sweep: checkmark only runs in STW and after the sweep."); + // It's critical that we enter this function with preemption disabled, // GC must not start while we are in the middle of this function. if(g->m->locks == 0 && g->m->mallocing == 0 && g != g->m->g0) @@ -1547,6 +1654,134 @@ runtime·gc_m(void) runtime·casgstatus(gp, Gwaiting, Grunning); } +// Similar to clearcheckmarkbits but works on a single span. +// It preforms two tasks. +// 1. When used before the checkmark phase it converts BitsDead (00) to bitsScalar (01) +// for nibbles with the BoundaryBit set. +// 2. When used after the checkmark phase it converts BitsPointerMark (11) to BitsPointer 10 and +// BitsScalarMark (00) to BitsScalar (01), thus clearing the checkmark mark encoding. +// For the second case it is possible to restore the BitsDead pattern but since +// clearmark is a debug tool performance has a lower priority than simplicity. +// The span is MSpanInUse and the world is stopped. +static void +clearcheckmarkbitsspan(MSpan *s) +{ + int32 cl, n, npages, i; + uintptr size, off, step; + byte *p, *bitp, *arena_start, b; + + if(!checkmark) + runtime·throw("clearcheckmarkbitsspan: checkmark not set."); + + if(s->state != MSpanInUse) { + runtime·printf("runtime:clearcheckmarkbitsspan: state=%d\n", + s->state); + runtime·throw("clearcheckmarkbitsspan: bad span state"); + } + arena_start = runtime·mheap.arena_start; + cl = s->sizeclass; + size = s->elemsize; + if(cl == 0) { + n = 1; + } else { + // Chunk full of small blocks. + npages = runtime·class_to_allocnpages[cl]; + n = (npages << PageShift) / size; + } + + // MSpan_Sweep has similar code but instead of overloading and + // complicating that routine we do a simpler walk here. + // Sweep through n objects of given size starting at p. + // This thread owns the span now, so it can manipulate + // the block bitmap without atomic operations. + p = (byte*)(s->start << PageShift); + // Find bits for the beginning of the span. + off = (uintptr*)p - (uintptr*)arena_start; + bitp = arena_start - off/wordsPerBitmapByte - 1; + step = size/(PtrSize*wordsPerBitmapByte); + + if(step == 0) { + // updating top and bottom nibbles, all boundaries + for(i=0; i>2; + if(b == BitsScalarMarked || b == BitsPointerMarked) + *bitp ^= BitsCheckMarkXor<<2; + + if(((*bitp>>gcBits) & bitBoundary) != bitBoundary) + runtime·throw("missing bitBoundary"); + b = ((*bitp>>gcBits) & bitPtrMask)>>2; + if(b == BitsScalarMarked || b == BitsPointerMarked) + *bitp ^= BitsCheckMarkXor<<(2+gcBits); + } + } else { + // updating bottom nibble for first word of each object + for(i=0; i>2; + if(b == BitsScalarMarked || b == BitsPointerMarked) + *bitp ^= BitsCheckMarkXor<<2; + } + } +} + +// clearcheckmarkbits preforms two tasks. +// 1. When used before the checkmark phase it converts BitsDead (00) to bitsScalar (01) +// for nibbles with the BoundaryBit set. +// 2. When used after the checkmark phase it converts BitsPointerMark (11) to BitsPointer 10 and +// BitsScalarMark (00) to BitsScalar (01), thus clearing the checkmark mark encoding. +// This is a bit expensive but preserves the BitsDead encoding during the normal marking. +// BitsDead remains valid for every nibble except the ones with BitsBoundary set. +static void +clearcheckmarkbits(void) +{ + uint32 idx; + MSpan *s; + for(idx=0; idxstate == MSpanInUse) { + clearcheckmarkbitsspan(s); + } + } +} + +// Called from malloc.go using onM. +// The world is stopped. Rerun the scan and mark phases +// using the bitMarkedCheck bit instead of the +// bitMarked bit. If the marking encounters an +// bitMarked bit that is not set then we throw. +void +runtime·gccheckmark_m(void) +{ + if(!gccheckmarkenable) + return; + + if(checkmark) + runtime·throw("gccheckmark_m, entered with checkmark already true."); + + checkmark = true; + clearcheckmarkbits(); // Converts BitsDead to BitsScalar. + runtime·gc_m(); + // Work done, fixed up the GC bitmap to remove the checkmark bits. + clearcheckmarkbits(); + checkmark = false; +} + +// checkmarkenable is initially false +void +runtime·gccheckmarkenable_m(void) +{ + gccheckmarkenable = true; +} + +void +runtime·gccheckmarkdisable_m(void) +{ + gccheckmarkenable = false; +} + void runtime·finishsweep_m(void) { @@ -1631,6 +1866,21 @@ runtime·gcscan_m(void) // Let the g that called us continue to run. } +// Mark all objects that are known about. +void +runtime·gcmark_m(void) +{ + scanblock(nil, 0, nil); +} + +// For now this must be followed by a stoptheworld and a starttheworld to ensure +// all go routines see the new barrier. +void +runtime·gcinstallmarkwb_m(void) +{ + runtime·gcphase = GCmark; +} + static void gc(struct gc_args *args) { @@ -1652,7 +1902,8 @@ gc(struct gc_args *args) if(runtime·debug.gctrace) t1 = runtime·nanotime(); - runtime·finishsweep_m(); + if(!checkmark) + runtime·finishsweep_m(); // skip during checkmark debug phase. // Cache runtime·mheap.allspans in work.spans to avoid conflicts with // resizing/freeing allspans. @@ -1676,7 +1927,7 @@ gc(struct gc_args *args) runtime·work.nwait = 0; runtime·work.ndone = 0; runtime·work.nproc = runtime·gcprocs(); - runtime·gcphase = GCmark; + runtime·gcphase = GCmarktermination; // World is stopped so allglen will not change. for(i = 0; i < runtime·allglen; i++) { @@ -1774,21 +2025,24 @@ gc(struct gc_args *args) runtime·sweep.spanidx = 0; runtime·unlock(&runtime·mheap.lock); - if(ConcurrentSweep && !args->eagersweep) { - runtime·lock(&runtime·gclock); - if(runtime·sweep.g == nil) - runtime·sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, gc); - else if(runtime·sweep.parked) { - runtime·sweep.parked = false; - runtime·ready(runtime·sweep.g); + // Start the sweep after the checkmark phase if there is one. + if(!gccheckmarkenable || checkmark) { + if(ConcurrentSweep && !args->eagersweep) { + runtime·lock(&runtime·gclock); + if(runtime·sweep.g == nil) + runtime·sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, gc); + else if(runtime·sweep.parked) { + runtime·sweep.parked = false; + runtime·ready(runtime·sweep.g); + } + runtime·unlock(&runtime·gclock); + } else { + // Sweep all spans eagerly. + while(runtime·sweepone() != -1) + runtime·sweep.npausesweep++; + // Do an additional mProf_GC, because all 'free' events are now real as well. + runtime·mProf_GC(); } - runtime·unlock(&runtime·gclock); - } else { - // Sweep all spans eagerly. - while(runtime·sweepone() != -1) - runtime·sweep.npausesweep++; - // Do an additional mProf_GC, because all 'free' events are now real as well. - runtime·mProf_GC(); } runtime·mProf_GC(); diff --git a/src/runtime/mgc0.h b/src/runtime/mgc0.h index 16fbe4665..519d7206e 100644 --- a/src/runtime/mgc0.h +++ b/src/runtime/mgc0.h @@ -45,8 +45,12 @@ enum { // If you change these, also change scanblock. // scanblock does "if(bits == BitsScalar || bits == BitsDead)" as "if(bits <= BitsScalar)". BitsDead = 0, - BitsScalar = 1, - BitsPointer = 2, + BitsScalar = 1, // 01 + BitsPointer = 2, // 10 + BitsCheckMarkXor = 1, // 10 + BitsScalarMarked = BitsScalar ^ BitsCheckMarkXor, // 00 + BitsPointerMarked = BitsPointer ^ BitsCheckMarkXor, // 11 + BitsMultiWord = 3, // BitsMultiWord will be set for the first word of a multi-word item. // When it is set, one of the following will be set for the second word. diff --git a/src/runtime/stack.c b/src/runtime/stack.c index f18171ea5..fb23cc1c3 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -382,8 +382,6 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f) uintptr delta; int32 num, i; byte *p, *minp, *maxp; - Type *t; - Itab *tab; minp = (byte*)adjinfo->old.lo; maxp = (byte*)adjinfo->old.hi; @@ -415,43 +413,7 @@ adjustpointers(byte **scanp, BitVector *bv, AdjustInfo *adjinfo, Func *f) } break; case BitsMultiWord: - switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i+1) * BitsPerPointer & 7) & 3) { - default: - runtime·throw("unexpected garbage collection bits"); - case BitsEface: - t = (Type*)scanp[i]; - if(t != nil && ((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0)) { - p = scanp[i+1]; - if(minp <= p && p < maxp) { - if(StackDebug >= 3) - runtime·printf("adjust eface %p\n", p); - if(t->size > PtrSize) // currently we always allocate such objects on the heap - runtime·throw("large interface value found on stack"); - scanp[i+1] = p + delta; - } - } - i++; - break; - case BitsIface: - tab = (Itab*)scanp[i]; - if(tab != nil) { - t = tab->type; - //runtime·printf(" type=%p\n", t); - if((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0) { - p = scanp[i+1]; - if(minp <= p && p < maxp) { - if(StackDebug >= 3) - runtime·printf("adjust iface %p\n", p); - if(t->size > PtrSize) // currently we always allocate such objects on the heap - runtime·throw("large interface value found on stack"); - scanp[i+1] = p + delta; - } - } - } - i++; - break; - } - break; + runtime·throw("adjustpointers: unexpected garbage collection bits"); } } } diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 2d5e41c1c..68f464f57 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -107,6 +107,12 @@ func mcacheRefill_m() func largeAlloc_m() func gc_m() func gcscan_m() +func gcmark_m() +func gccheckmark_m() +func gccheckmarkenable_m() +func gccheckmarkdisable_m() +func gcinstallmarkwb_m() +func gcmarknewobject_m() func finishsweep_m() func scavenge_m() func setFinalizer_m() -- cgit v1.2.1 From 494d936b2c70f1f8a1fa51efe419619c05f624e5 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 5 Nov 2014 11:09:08 -0500 Subject: [dev.garbage] runtime: fix 32-bit build TBR=crawshaw R=crawshaw CC=golang-codereviews https://codereview.appspot.com/168860046 --- src/runtime/mgc0.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index 75678c522..22e88494a 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -84,8 +84,8 @@ func bgsweep() { } const ( - _PoisonGC = 0xf969696969696969 & ^uintptr(0) - _PoisonStack = 0x6868686868686868 & ^uintptr(0) + _PoisonGC = 0xf969696969696969 & (1<<(8*ptrSize) - 1) + _PoisonStack = 0x6868686868686868 & (1<<(8*ptrSize) - 1) ) // NOTE: Really dst *unsafe.Pointer, src unsafe.Pointer, -- cgit v1.2.1 From c4bde225a28b8ce8e0b2075c912f7726b3756300 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 5 Nov 2014 13:37:34 -0500 Subject: [dev.garbage] runtime: fix a few checkmark bugs - Some sequencing issues with stopping the first gc_m round at the right place to set up correctly for the second round. - atomicxor8 is not idempotent; avoid xor. - Maintain BitsDead type bits correctly; see long comment added. - Enable checkmark phase by default for now. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/171090043 --- src/runtime/mgc0.c | 146 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index e283f6ee8..77a6c9377 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -257,7 +257,7 @@ WorkData runtime·work; // encoding, otherwise one uses the bitMarked bit in the lower two bits // of the nibble. static bool checkmark = false; -static bool gccheckmarkenable = false; +static bool gccheckmarkenable = true; // Is address b in the known heap. If it doesn't have a valid gcmap // returns false. For example pointers into stacks will return false. @@ -292,7 +292,7 @@ slottombits(byte *obj, Markbits *mbits) mbits->shift = (off % wordsPerBitmapByte) * gcBits; mbits->xbits = *mbits->bitp; mbits->bits = (mbits->xbits >> mbits->shift) & bitMask; - mbits->tbits = (mbits->xbits >> mbits->shift) & bitPtrMask; + mbits->tbits = ((mbits->xbits >> mbits->shift) & bitPtrMask) >> 2; } // b is a pointer into the heap. @@ -354,13 +354,13 @@ objectstart(byte *b, Markbits *mbits) // Slow for now as we serialize this, since this is on a debug path // speed is not critical at this point. -static Mutex xorlock; +static Mutex andlock; static void -atomicxor8(byte *src, byte val) +atomicand8(byte *src, byte val) { - runtime·lock(&xorlock); - *src = *src^val; - runtime·unlock(&xorlock); + runtime·lock(&andlock); + *src = *src&val; + runtime·unlock(&andlock); } // Mark using the checkmark scheme. @@ -369,7 +369,16 @@ docheckmark(Markbits *mbits) { // xor 01 moves 01(scalar unmarked) to 00(scalar marked) // and 10(pointer unmarked) to 11(pointer marked) - atomicxor8(mbits->bitp, BitsCheckMarkXor<shift<<2); + if(mbits->tbits == BitsScalar) + atomicand8(mbits->bitp, ~(byte)(BitsCheckMarkXor<shift<<2)); + else if(mbits->tbits == BitsPointer) + runtime·atomicor8(mbits->bitp, BitsCheckMarkXor<shift<<2); + + // reload bits for ischeckmarked + mbits->xbits = *mbits->bitp; + mbits->bits = (mbits->xbits >> mbits->shift) & bitMask; + mbits->tbits = ((mbits->xbits >> mbits->shift) & bitPtrMask) >> 2; + return; } @@ -434,10 +443,15 @@ greyobject(byte *obj, Markbits *mbits, Workbuf *wbuf) if(checkmark) { if(!ismarked(mbits)) { runtime·printf("runtime:greyobject: checkmarks finds unexpected unmarked object obj=%p, mbits->bits=%x, *mbits->bitp=%x\n", obj, mbits->bits, *mbits->bitp); + runtime·throw("checkmark found unmarked object"); } if(ischeckmarked(mbits)) return wbuf; docheckmark(mbits); + if(!ischeckmarked(mbits)) { + runtime·printf("mbits xbits=%x bits=%x tbits=%x shift=%d\n", mbits->xbits, mbits->bits, mbits->tbits, mbits->shift); + runtime·throw("docheckmark and ischeckmarked disagree"); + } } else { // If marked we have nothing to do. if((mbits->bits&bitMarked) != 0) @@ -1670,9 +1684,6 @@ clearcheckmarkbitsspan(MSpan *s) uintptr size, off, step; byte *p, *bitp, *arena_start, b; - if(!checkmark) - runtime·throw("clearcheckmarkbitsspan: checkmark not set."); - if(s->state != MSpanInUse) { runtime·printf("runtime:clearcheckmarkbitsspan: state=%d\n", s->state); @@ -1700,19 +1711,65 @@ clearcheckmarkbitsspan(MSpan *s) bitp = arena_start - off/wordsPerBitmapByte - 1; step = size/(PtrSize*wordsPerBitmapByte); + // The type bit values are: + // 00 - BitsDead, for us BitsScalarMarked + // 01 - BitsScalar + // 10 - BitsPointer + // 11 - unused, for us BitsPointerMarked + // + // When called to prepare for the checkmark phase (checkmark==1), + // we change BitsDead to BitsScalar, so that there are no BitsScalarMarked + // type bits anywhere. + // + // The checkmark phase marks by changing BitsScalar to BitsScalarMarked + // and BitsPointer to BitsPointerMarked. + // + // When called to clean up after the checkmark phase (checkmark==0), + // we unmark by changing BitsScalarMarked back to BitsScalar and + // BitsPointerMarked back to BitsPointer. + // + // There are two problems with the scheme as just described. + // First, the setup rewrites BitsDead to BitsScalar, but the type bits + // following a BitsDead are uninitialized and must not be used. + // Second, objects that are free are expected to have their type + // bits zeroed (BitsDead), so in the cleanup we need to restore + // any BitsDeads that were there originally. + // + // In a one-word object (8-byte allocation on 64-bit system), + // there is no difference between BitsScalar and BitsDead, because + // neither is a pointer and there are no more words in the object, + // so using BitsScalar during the checkmark is safe and mapping + // both back to BitsDead during cleanup is also safe. + // + // In a larger object, we need to be more careful. During setup, + // if the type of the first word is BitsDead, we change it to BitsScalar + // (as we must) but also initialize the type of the second + // word to BitsDead, so that a scan during the checkmark phase + // will still stop before seeing the uninitialized type bits in the + // rest of the object. The sequence 'BitsScalar BitsDead' never + // happens in real type bitmaps - BitsDead is always as early + // as possible, so immediately after the last BitsPointer. + // During cleanup, if we see a BitsScalar, we can check to see if it + // is followed by BitsDead. If so, it was originally BitsDead and + // we can change it back. + if(step == 0) { // updating top and bottom nibbles, all boundaries for(i=0; i>2; - if(b == BitsScalarMarked || b == BitsPointerMarked) + if(!checkmark && (b == BitsScalar || b == BitsScalarMarked)) + *bitp &= ~0x0c; // convert to BitsDead + else if(b == BitsScalarMarked || b == BitsPointerMarked) *bitp ^= BitsCheckMarkXor<<2; - + if(((*bitp>>gcBits) & bitBoundary) != bitBoundary) runtime·throw("missing bitBoundary"); b = ((*bitp>>gcBits) & bitPtrMask)>>2; - if(b == BitsScalarMarked || b == BitsPointerMarked) + if(!checkmark && (b == BitsScalar || b == BitsScalarMarked)) + *bitp &= ~0xc0; // convert to BitsDead + else if(b == BitsScalarMarked || b == BitsPointerMarked) *bitp ^= BitsCheckMarkXor<<(2+gcBits); } } else { @@ -1721,7 +1778,19 @@ clearcheckmarkbitsspan(MSpan *s) if((*bitp & bitBoundary) != bitBoundary) runtime·throw("missing bitBoundary"); b = (*bitp & bitPtrMask)>>2; - if(b == BitsScalarMarked || b == BitsPointerMarked) + + if(checkmark && b == BitsDead) { + // move BitsDead into second word. + // set bits to BitsScalar in preparation for checkmark phase. + *bitp &= ~0xc0; + *bitp |= BitsScalar<<2; + } else if(!checkmark && (b == BitsScalar || b == BitsScalarMarked) && (*bitp & 0xc0) == 0) { + // Cleaning up after checkmark phase. + // First word is scalar or dead (we forgot) + // and second word is dead. + // First word might as well be dead too. + *bitp &= ~0x0c; + } else if(b == BitsScalarMarked || b == BitsPointerMarked) *bitp ^= BitsCheckMarkXor<<2; } } @@ -1763,10 +1832,9 @@ runtime·gccheckmark_m(void) checkmark = true; clearcheckmarkbits(); // Converts BitsDead to BitsScalar. - runtime·gc_m(); + runtime·gc_m(); // turns off checkmark // Work done, fixed up the GC bitmap to remove the checkmark bits. clearcheckmarkbits(); - checkmark = false; } // checkmarkenable is initially false @@ -2016,6 +2084,16 @@ gc(struct gc_args *args) // Free the old cached mark array if necessary. if(runtime·work.spans != nil && runtime·work.spans != runtime·mheap.allspans) runtime·SysFree(runtime·work.spans, runtime·work.nspan*sizeof(runtime·work.spans[0]), &mstats.other_sys); + + if(gccheckmarkenable) { + if(!checkmark) { + // first half of two-pass; don't set up sweep + runtime·unlock(&runtime·mheap.lock); + return; + } + checkmark = false; // done checking marks + } + // Cache the current array for sweeping. runtime·mheap.gcspans = runtime·mheap.allspans; runtime·mheap.sweepgen += 2; @@ -2025,24 +2103,22 @@ gc(struct gc_args *args) runtime·sweep.spanidx = 0; runtime·unlock(&runtime·mheap.lock); - // Start the sweep after the checkmark phase if there is one. - if(!gccheckmarkenable || checkmark) { - if(ConcurrentSweep && !args->eagersweep) { - runtime·lock(&runtime·gclock); - if(runtime·sweep.g == nil) - runtime·sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, gc); - else if(runtime·sweep.parked) { - runtime·sweep.parked = false; - runtime·ready(runtime·sweep.g); - } - runtime·unlock(&runtime·gclock); - } else { - // Sweep all spans eagerly. - while(runtime·sweepone() != -1) - runtime·sweep.npausesweep++; - // Do an additional mProf_GC, because all 'free' events are now real as well. - runtime·mProf_GC(); + + if(ConcurrentSweep && !args->eagersweep) { + runtime·lock(&runtime·gclock); + if(runtime·sweep.g == nil) + runtime·sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, gc); + else if(runtime·sweep.parked) { + runtime·sweep.parked = false; + runtime·ready(runtime·sweep.g); } + runtime·unlock(&runtime·gclock); + } else { + // Sweep all spans eagerly. + while(runtime·sweepone() != -1) + runtime·sweep.npausesweep++; + // Do an additional mProf_GC, because all 'free' events are now real as well. + runtime·mProf_GC(); } runtime·mProf_GC(); -- cgit v1.2.1 From 6d5e8c9c938b45ddcc62470a790408642a26218b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 5 Nov 2014 14:42:24 -0500 Subject: [dev.garbage] runtime: ignore objects in dead spans We still don't know why this is happening. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/169990043 --- src/runtime/mgc0.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 77a6c9377..3ebaf005f 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -326,12 +326,16 @@ objectstart(byte *b, Markbits *mbits) // The following ensures that we are rigorous about what data // structures hold valid pointers - runtime·printf("runtime:objectstart Span weird: obj=%p, k=%p", obj, k); - if (s == nil) - runtime·printf(" s=nil\n"); - else - runtime·printf(" s->start=%p s->limit=%p, s->state=%d\n", s->start*PageSize, s->limit, s->state); - runtime·throw("objectstart: bad span"); + if(0) { + // Still happens sometimes. We don't know why. + runtime·printf("runtime:objectstart Span weird: obj=%p, k=%p", obj, k); + if (s == nil) + runtime·printf(" s=nil\n"); + else + runtime·printf(" s->start=%p s->limit=%p, s->state=%d\n", s->start*PageSize, s->limit, s->state); + runtime·throw("objectstart: bad pointer in unexpected span"); + } + return nil; } p = (byte*)((uintptr)s->start<sizeclass != 0) { -- cgit v1.2.1 From aefaeb75f3eff323f212c5309d8ae65768ad9809 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 5 Nov 2014 14:42:54 -0500 Subject: [dev.garbage] cmd/gc, runtime: add locks around print statements Now each C printf, Go print, or Go println is guaranteed not to be interleaved with other calls of those functions. This should help when debugging concurrent failures. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/169120043 --- src/cmd/gc/builtin.c | 2 ++ src/cmd/gc/go.h | 1 + src/cmd/gc/runtime.go | 2 ++ src/cmd/gc/walk.c | 17 +++++++++++++++++ src/runtime/print1.go | 30 +++++++++++++++++++++++++++--- src/runtime/runtime.h | 1 + 6 files changed, 50 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c index bd3fca167..aeeadedca 100644 --- a/src/cmd/gc/builtin.c +++ b/src/cmd/gc/builtin.c @@ -24,6 +24,8 @@ char *runtimeimport = "func @\"\".printslice (? any)\n" "func @\"\".printnl ()\n" "func @\"\".printsp ()\n" + "func @\"\".printlock ()\n" + "func @\"\".printunlock ()\n" "func @\"\".concatstring2 (? string, ? string) (? string)\n" "func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n" "func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n" diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 965a0550d..cc590416b 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -1464,6 +1464,7 @@ void walk(Node *fn); void walkexpr(Node **np, NodeList **init); void walkexprlist(NodeList *l, NodeList **init); void walkexprlistsafe(NodeList *l, NodeList **init); +void walkexprlistcheap(NodeList *l, NodeList **init); void walkstmt(Node **np); void walkstmtlist(NodeList *l); Node* conv(Node*, Type*); diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index 38bf6abb6..c6007714c 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -36,6 +36,8 @@ func printeface(any) func printslice(any) func printnl() func printsp() +func printlock() +func printunlock() func concatstring2(string, string) string func concatstring3(string, string, string) string diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 7b502eb60..38bed1e22 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -363,6 +363,15 @@ walkexprlistsafe(NodeList *l, NodeList **init) } } +void +walkexprlistcheap(NodeList *l, NodeList **init) +{ + for(; l; l=l->next) { + l->n = cheapexpr(l->n, init); + walkexpr(&l->n, init); + } +} + void walkexpr(Node **np, NodeList **init) { @@ -1773,6 +1782,11 @@ walkprint(Node *nn, NodeList **init) calls = nil; notfirst = 0; + // Hoist all the argument evaluation up before the lock. + walkexprlistcheap(all, init); + + calls = list(calls, mkcall("printlock", T, init)); + for(l=all; l; l=l->next) { if(notfirst) { calls = list(calls, mkcall("printsp", T, init)); @@ -1853,6 +1867,9 @@ walkprint(Node *nn, NodeList **init) if(op == OPRINTN) calls = list(calls, mkcall("printnl", T, nil)); + + calls = list(calls, mkcall("printunlock", T, init)); + typechecklist(calls, Etop); walkexprlist(calls, init); diff --git a/src/runtime/print1.go b/src/runtime/print1.go index 8f8268873..3d812bd04 100644 --- a/src/runtime/print1.go +++ b/src/runtime/print1.go @@ -41,7 +41,31 @@ func snprintf(dst *byte, n int32, s *byte) { gp.writebuf = nil } -//var debuglock mutex +var debuglock mutex + +// The compiler emits calls to printlock and printunlock around +// the multiple calls that implement a single Go print or println +// statement. Some of the print helpers (printsp, for example) +// call print recursively. There is also the problem of a crash +// happening during the print routines and needing to acquire +// the print lock to print information about the crash. +// For both these reasons, let a thread acquire the printlock 'recursively'. + +func printlock() { + mp := getg().m + mp.printlock++ + if mp.printlock == 1 { + lock(&debuglock) + } +} + +func printunlock() { + mp := getg().m + mp.printlock-- + if mp.printlock == 0 { + unlock(&debuglock) + } +} // write to goroutine-local buffer if diverting output, // or else standard error. @@ -80,7 +104,7 @@ func printnl() { // Very simple printf. Only for debugging prints. // Do not add to this without checking with Rob. func vprintf(str string, arg unsafe.Pointer) { - //lock(&debuglock); + printlock() s := bytes(str) start := 0 @@ -160,7 +184,7 @@ func vprintf(str string, arg unsafe.Pointer) { gwrite(s[start:i]) } - //unlock(&debuglock); + printunlock() } func printpc(p unsafe.Pointer) { diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 6a02ef1d3..ee86f2d17 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -345,6 +345,7 @@ struct M int32 helpgc; bool spinning; // M is out of work and is actively looking for work bool blocked; // M is blocked on a Note + int8 printlock; uint32 fastrand; uint64 ncgocall; // number of cgo calls in total int32 ncgo; // number of cgo calls currently in progress -- cgit v1.2.1 From c3f533c86a28f6990b8d35a7ed9c30a6f620e853 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 5 Nov 2014 15:43:41 -0500 Subject: [dev.garbage] cmd/gc: emit pointer write barriers This got lost in the change that added the writebarrierfat variants. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/165510043 --- src/cmd/gc/walk.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 38bed1e22..37bd62dea 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -2015,6 +2015,8 @@ applywritebarrier(Node *n, NodeList **init) l = nod(OADDR, n->left, N); l->etype = 1; // addr does not escape if(t->width == widthptr) { + n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init, + l, n->right); } else if(t->etype == TSTRING) { n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init, l, n->right); @@ -2037,6 +2039,8 @@ applywritebarrier(Node *n, NodeList **init) if(BitsPointer != (1<width/widthptr) { + default: + fatal("found writebarrierfat for %d-byte object of type %T", (int)t->width, t); case 2: snprint(name, sizeof name, "writebarrierfat%d%d", bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit)); -- cgit v1.2.1 From cb223591339d2e03283e21144057b30d5e9667dd Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Mon, 10 Nov 2014 13:42:34 -0500 Subject: [dev.garbage] runtime: Code to implement write barriers To turn concurrent gc on alter the if false in func gogc currently at line 489 in malloc.go LGTM=rsc R=rsc CC=golang-codereviews, rlh https://codereview.appspot.com/172190043 Committer: Russ Cox --- src/runtime/malloc.go | 21 +++++++++++---------- src/runtime/mgc0.c | 39 ++++++++++++++++++++++++++++++++++----- src/runtime/mgc0.go | 19 ++++++++++++++++++- src/runtime/runtime.h | 1 + src/runtime/stubs.go | 2 ++ 5 files changed, 66 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 274bae9a3..a18e77421 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -486,16 +486,17 @@ func gogc(force int32) { onM(stoptheworld) onM(finishsweep_m) // finish sweep before we start concurrent scan. - onM(starttheworld) - - // Do a concurrent heap scan before we stop the world. - onM(gcscan_m) - onM(gcinstallmarkwb_m) - onM(stoptheworld) - // onM(starttheworld) - // mark from roots scanned in gcscan_m. startthework when write barrier works - onM(gcmark_m) - // onM(stoptheworld) + if false { // To turn on concurrent scan and mark set to true... + onM(starttheworld) + // Do a concurrent heap scan before we stop the world. + onM(gcscan_m) + onM(stoptheworld) + onM(gcinstallmarkwb_m) + onM(starttheworld) + onM(gcmark_m) + onM(stoptheworld) + onM(gcinstalloffwb_m) + } if mp != acquirem() { gothrow("gogc: rescheduled") } diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 3ebaf005f..5300f554b 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -1061,13 +1061,34 @@ shade(byte *b) // // Shade indicates that it has seen a white pointer by adding the referent // to wbuf. +// slot is the destination (dst) in go code +// ptr is the value that goes into the slot (src) in the go code void -runtime·markwb(void **slot, void *ptr) +runtime·gcmarkwb_m() { - // initial nil check avoids some needlesss loads - if(ptr != nil && inheap(ptr) && shaded((void*)slot)) - shade(ptr); + byte **slot, *ptr; + slot = (byte**)g->m->scalararg[0]; + ptr = (byte*)g->m->scalararg[1]; + *slot = ptr; + switch(runtime·gcphase) { + default: + runtime·throw("gcphasework in bad gcphase"); + case GCoff: + case GCquiesce: + case GCstw: + case GCsweep: + case GCscan: + break; + case GCmark: + if(ptr != nil && inheap(ptr) && shaded((byte*)slot)) + shade(ptr); + break; + case GCmarktermination: + if(ptr != nil && inheap(ptr) && shaded((byte*)slot)) + shade(ptr); + break; + } } // The gp has been moved to a GC safepoint. GC phase specific @@ -1945,7 +1966,7 @@ runtime·gcmark_m(void) scanblock(nil, 0, nil); } -// For now this must be followed by a stoptheworld and a starttheworld to ensure +// For now this must be bracketed with a stoptheworld and a starttheworld to ensure // all go routines see the new barrier. void runtime·gcinstallmarkwb_m(void) @@ -1953,6 +1974,14 @@ runtime·gcinstallmarkwb_m(void) runtime·gcphase = GCmark; } +// For now this must be bracketed with a stoptheworld and a starttheworld to ensure +// all go routines see the new barrier. +void +runtime·gcinstalloffwb_m(void) +{ + runtime·gcphase = GCoff; +} + static void gc(struct gc_args *args) { diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index 22e88494a..ce5c290ef 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -95,7 +95,24 @@ func writebarrierptr(dst *uintptr, src uintptr) { if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) { onM(func() { gothrow("bad pointer in write barrier") }) } - *dst = src + + mp := acquirem() + if mp.inwb { + *dst = src + releasem(mp) + return + } + mp.inwb = true + oldscalar0 := mp.scalararg[0] + oldscalar1 := mp.scalararg[1] + mp.scalararg[0] = uintptr(unsafe.Pointer(dst)) + mp.scalararg[1] = src + onM_signalok(gcmarkwb_m) + mp.scalararg[0] = oldscalar0 + mp.scalararg[1] = oldscalar1 + mp.inwb = false + releasem(mp) + // *dst = src is done inside of the write barrier. } //go:nosplit diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index ee86f2d17..a0f1acc05 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -345,6 +345,7 @@ struct M int32 helpgc; bool spinning; // M is out of work and is actively looking for work bool blocked; // M is blocked on a Note + bool inwb; // M is executing a write barrier int8 printlock; uint32 fastrand; uint64 ncgocall; // number of cgo calls in total diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 68f464f57..852f4ddbb 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -112,7 +112,9 @@ func gccheckmark_m() func gccheckmarkenable_m() func gccheckmarkdisable_m() func gcinstallmarkwb_m() +func gcinstalloffwb_m() func gcmarknewobject_m() +func gcmarkwb_m() func finishsweep_m() func scavenge_m() func setFinalizer_m() -- cgit v1.2.1 From 11c9da27d8b3d09835a611edea424885af1ec650 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Mon, 10 Nov 2014 14:32:02 -0500 Subject: [dev.garbage] runtime: Coarsen the write barrier to always grey the destination. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/174820043 --- src/runtime/mgc0.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 5300f554b..3f6cce5c0 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -1056,13 +1056,41 @@ shade(byte *b) return; } -// This is the Dijkstra barrier coarsened to shade grey to white whereas -// the original Dijkstra barrier only shaded black to white. +// This is the Dijkstra barrier coarsened to always shade the ptr (dst) object. +// The original Dijkstra barrier only shaded ptrs being placed in black slots. // // Shade indicates that it has seen a white pointer by adding the referent -// to wbuf. +// to wbuf as well as marking it. +// // slot is the destination (dst) in go code // ptr is the value that goes into the slot (src) in the go code +// +// Dijkstra pointed out that maintaining the no black to white +// pointers means that white to white pointers not need +// to be noted by the write barrier. Furthermore if either +// white object dies before it is reached by the +// GC then the object can be collected during this GC cycle +// instead of waiting for the next cycle. Unfortunately the cost of +// ensure that the object holding the slot doesn't concurrently +// change to black without the mutator noticing seems prohibitive. +// +// Consider the following example where the mutator writes into +// a slot and then loads the slot's mark bit while the GC thread +// writes to the slot's mark bit and then as part of scanning reads +// the slot. +// +// Initially both [slot] and [slotmark] are 0 (nil) +// Mutator thread GC thread +// st [slot], ptr st [slotmark], 1 +// +// ld r1, [slotmark] ld r2, [slot] +// +// This is a classic example of independent reads of independent writes, +// aka IRIW. The question is if r1==r2==0 is allowed and for most HW the +// answer is yes without inserting a memory barriers between the st and the ld. +// These barriers are expensive so we have decided that we will +// always grey the ptr object regardless of the slot's color. +// void runtime·gcmarkwb_m() { @@ -1081,11 +1109,11 @@ runtime·gcmarkwb_m() case GCscan: break; case GCmark: - if(ptr != nil && inheap(ptr) && shaded((byte*)slot)) + if(ptr != nil && inheap(ptr)) shade(ptr); break; case GCmarktermination: - if(ptr != nil && inheap(ptr) && shaded((byte*)slot)) + if(ptr != nil && inheap(ptr)) shade(ptr); break; } -- cgit v1.2.1 From f4d66a3a39bd302d7fd96fc98c086813cfdaf755 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 10 Nov 2014 14:59:36 -0500 Subject: [dev.garbage] runtime: add write barrier to casp Also rewrite some casp that don't use real pointers to use casuintptr instead. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/166440044 --- src/runtime/asm_386.s | 6 +++--- src/runtime/asm_amd64.s | 6 +++--- src/runtime/asm_amd64p32.s | 6 +++--- src/runtime/asm_power64x.s | 6 +++--- src/runtime/atomic.go | 38 ++++++++++++++++++++++++++++++++++---- src/runtime/mgc0.c | 1 - src/runtime/mgc0.go | 14 ++++++++++++-- src/runtime/proc.c | 14 +++++++------- src/runtime/runtime.h | 1 + src/runtime/string.c | 2 +- src/runtime/stubs.go | 3 --- 11 files changed, 67 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 2d102b273..d456e6bca 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -502,7 +502,7 @@ fail: // return 1; // }else // return 0; -TEXT runtime·casp(SB), NOSPLIT, $0-13 +TEXT runtime·casp1(SB), NOSPLIT, $0-13 MOVL ptr+0(FP), BX MOVL old+4(FP), AX MOVL new+8(FP), CX @@ -537,7 +537,7 @@ TEXT runtime·xchg(SB), NOSPLIT, $0-12 MOVL AX, ret+8(FP) RET -TEXT runtime·xchgp(SB), NOSPLIT, $0-12 +TEXT runtime·xchgp1(SB), NOSPLIT, $0-12 MOVL ptr+0(FP), BX MOVL new+4(FP), AX XCHGL AX, 0(BX) @@ -555,7 +555,7 @@ again: JNZ again RET -TEXT runtime·atomicstorep(SB), NOSPLIT, $0-8 +TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8 MOVL ptr+0(FP), BX MOVL val+4(FP), AX XCHGL AX, 0(BX) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index ac9c58cf3..5d176575c 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -489,7 +489,7 @@ TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16 // return 1; // } else // return 0; -TEXT runtime·casp(SB), NOSPLIT, $0-25 +TEXT runtime·casp1(SB), NOSPLIT, $0-25 MOVQ ptr+0(FP), BX MOVQ old+8(FP), AX MOVQ new+16(FP), CX @@ -541,7 +541,7 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24 MOVQ AX, ret+16(FP) RET -TEXT runtime·xchgp(SB), NOSPLIT, $0-24 +TEXT runtime·xchgp1(SB), NOSPLIT, $0-24 MOVQ ptr+0(FP), BX MOVQ new+8(FP), AX XCHGQ AX, 0(BX) @@ -559,7 +559,7 @@ again: JNZ again RET -TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16 +TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16 MOVQ ptr+0(FP), BX MOVQ val+8(FP), AX XCHGQ AX, 0(BX) diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s index de3ef3a23..2b2155753 100644 --- a/src/runtime/asm_amd64p32.s +++ b/src/runtime/asm_amd64p32.s @@ -460,7 +460,7 @@ fail: // return 1; // } else // return 0; -TEXT runtime·casp(SB), NOSPLIT, $0-17 +TEXT runtime·casp1(SB), NOSPLIT, $0-17 MOVL ptr+0(FP), BX MOVL old+4(FP), AX MOVL new+8(FP), CX @@ -512,7 +512,7 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24 MOVQ AX, ret+16(FP) RET -TEXT runtime·xchgp(SB), NOSPLIT, $0-12 +TEXT runtime·xchgp1(SB), NOSPLIT, $0-12 MOVL ptr+0(FP), BX MOVL new+4(FP), AX XCHGL AX, 0(BX) @@ -530,7 +530,7 @@ again: JNZ again RET -TEXT runtime·atomicstorep(SB), NOSPLIT, $0-8 +TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8 MOVL ptr+0(FP), BX MOVL val+4(FP), AX XCHGL AX, 0(BX) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index f77658032..fd0c6be16 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -472,7 +472,7 @@ TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16 // return 1; // } else // return 0; -TEXT runtime·casp(SB), NOSPLIT, $0-25 +TEXT runtime·casp1(SB), NOSPLIT, $0-25 BR runtime·cas64(SB) // uint32 xadd(uint32 volatile *val, int32 delta) @@ -529,7 +529,7 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24 MOVD R3, ret+16(FP) RETURN -TEXT runtime·xchgp(SB), NOSPLIT, $0-24 +TEXT runtime·xchgp1(SB), NOSPLIT, $0-24 BR runtime·xchg64(SB) TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24 @@ -538,7 +538,7 @@ TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24 TEXT runtime·procyield(SB),NOSPLIT,$0-0 RETURN -TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16 +TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16 BR runtime·atomicstore64(SB) TEXT runtime·atomicstore(SB), NOSPLIT, $0-12 diff --git a/src/runtime/atomic.go b/src/runtime/atomic.go index 7e9d9b3aa..a0e4d84e9 100644 --- a/src/runtime/atomic.go +++ b/src/runtime/atomic.go @@ -20,8 +20,16 @@ func xchg(ptr *uint32, new uint32) uint32 //go:noescape func xchg64(ptr *uint64, new uint64) uint64 -//go:noescape -func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer +// Cannot use noescape here: ptr does not but new does escape. +// Instead use noescape(ptr) in wrapper below. +func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer + +//go:nosplit +func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer { + old := xchgp1(noescape(ptr), new) + writebarrierptr_nostore((*uintptr)(ptr), uintptr(new)) + return old +} //go:noescape func xchguintptr(ptr *uintptr, new uintptr) uintptr @@ -47,5 +55,27 @@ func atomicstore(ptr *uint32, val uint32) //go:noescape func atomicstore64(ptr *uint64, val uint64) -//go:noescape -func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer) +// Cannot use noescape here: ptr does not but val does escape. +// Instead use noescape(ptr) in wrapper below. +func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer) + +//go:nosplit +func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer) { + atomicstorep1(noescape(ptr), val) + // TODO(rsc): Why does the compiler think writebarrierptr_nostore's dst argument escapes? + writebarrierptr_nostore((*uintptr)(noescape(ptr)), uintptr(val)) +} + +// Cannot use noescape here: ptr does not but new does escape. +// Instead use noescape(ptr) in wrapper below. +func casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool + +//go:nosplit +func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { + ok := casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), old, new) + if !ok { + return false + } + writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) + return true +} diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 3f6cce5c0..8d87107c7 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -1098,7 +1098,6 @@ runtime·gcmarkwb_m() slot = (byte**)g->m->scalararg[0]; ptr = (byte*)g->m->scalararg[1]; - *slot = ptr; switch(runtime·gcphase) { default: runtime·throw("gcphasework in bad gcphase"); diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index ce5c290ef..760d2a545 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -92,13 +92,24 @@ const ( // but if we do that, Go inserts a write barrier on *dst = src. //go:nosplit func writebarrierptr(dst *uintptr, src uintptr) { + *dst = src + writebarrierptr_nostore(dst, src) +} + +// Like writebarrierptr, but the store has already been applied. +// Do not reapply. +//go:nosplit +func writebarrierptr_nostore(dst *uintptr, src uintptr) { + if getg() == nil { // very low-level startup + return + } + if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) { onM(func() { gothrow("bad pointer in write barrier") }) } mp := acquirem() if mp.inwb { - *dst = src releasem(mp) return } @@ -112,7 +123,6 @@ func writebarrierptr(dst *uintptr, src uintptr) { mp.scalararg[1] = oldscalar1 mp.inwb = false releasem(mp) - // *dst = src is done inside of the write barrier. } //go:nosplit diff --git a/src/runtime/proc.c b/src/runtime/proc.c index 9626bd101..e5e2df2e4 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -1060,7 +1060,7 @@ runtime·dropm(void) unlockextra(mp); } -#define MLOCKED ((M*)1) +#define MLOCKED 1 // lockextra locks the extra list and returns the list head. // The caller must unlock the list by storing a new list head @@ -1071,28 +1071,28 @@ runtime·dropm(void) static M* lockextra(bool nilokay) { - M *mp; + uintptr mpx; void (*yield)(void); for(;;) { - mp = runtime·atomicloadp(&runtime·extram); - if(mp == MLOCKED) { + mpx = runtime·atomicloaduintptr((uintptr*)&runtime·extram); + if(mpx == MLOCKED) { yield = runtime·osyield; yield(); continue; } - if(mp == nil && !nilokay) { + if(mpx == 0 && !nilokay) { runtime·usleep(1); continue; } - if(!runtime·casp(&runtime·extram, mp, MLOCKED)) { + if(!runtime·casuintptr((uintptr*)&runtime·extram, mpx, MLOCKED)) { yield = runtime·osyield; yield(); continue; } break; } - return mp; + return (M*)mpx; } #pragma textflag NOSPLIT diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index a0f1acc05..a4186f450 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -894,6 +894,7 @@ int32 runtime·round2(int32 x); // round x up to a power of 2. bool runtime·cas(uint32*, uint32, uint32); bool runtime·cas64(uint64*, uint64, uint64); bool runtime·casp(void**, void*, void*); +bool runtime·casuintptr(uintptr*, uintptr, uintptr); // Don't confuse with XADD x86 instruction, // this one is actually 'addx', that is, add-and-fetch. uint32 runtime·xadd(uint32 volatile*, int32); diff --git a/src/runtime/string.c b/src/runtime/string.c index ed5debc33..475ea2de6 100644 --- a/src/runtime/string.c +++ b/src/runtime/string.c @@ -48,7 +48,7 @@ runtime·gostringnocopy(byte *str) s.len = runtime·findnull(str); while(true) { ms = runtime·maxstring; - if(s.len <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)s.len)) + if(s.len <= ms || runtime·casuintptr(&runtime·maxstring, ms, s.len)) return s; } } diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 852f4ddbb..421ab04e5 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -213,9 +213,6 @@ func write(fd uintptr, p unsafe.Pointer, n int32) int32 //go:noescape func cas(ptr *uint32, old, new uint32) bool -//go:noescape -func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool - //go:noescape func casuintptr(ptr *uintptr, old, new uintptr) bool -- cgit v1.2.1 From fc350a0d75c2df2eea560e66483dbb6f04d00e35 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 11 Nov 2014 16:54:50 -0500 Subject: [dev.garbage] runtime: concurrent mark fixes Add missing write barrier when initializing state for newly created goroutine. Add write barrier for same slot when preempting a goroutine. Disable write barrier during goroutine death, because dopanic does pointer writes. With concurrent mark enabled (not in this CL), all.bash passed once. The second time, TestGoexitCrash-2 failed. LGTM=rlh R=rlh CC=golang-codereviews https://codereview.appspot.com/167610043 --- src/runtime/mgc0.c | 3 +-- src/runtime/mgc0.go | 2 +- src/runtime/runtime.h | 2 ++ src/runtime/stack.c | 8 ++++++++ src/runtime/sys_x86.c | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 8d87107c7..3c4d1afa5 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -1094,8 +1094,7 @@ shade(byte *b) void runtime·gcmarkwb_m() { - byte **slot, *ptr; - slot = (byte**)g->m->scalararg[0]; + byte *ptr; ptr = (byte*)g->m->scalararg[1]; switch(runtime·gcphase) { diff --git a/src/runtime/mgc0.go b/src/runtime/mgc0.go index 760d2a545..dc4eec519 100644 --- a/src/runtime/mgc0.go +++ b/src/runtime/mgc0.go @@ -109,7 +109,7 @@ func writebarrierptr_nostore(dst *uintptr, src uintptr) { } mp := acquirem() - if mp.inwb { + if mp.inwb || mp.dying > 0 { releasem(mp) return } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index a4186f450..fec224390 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -1121,6 +1121,8 @@ void runtime·osyield(void); void runtime·lockOSThread(void); void runtime·unlockOSThread(void); +void runtime·writebarrierptr_nostore(void*, void*); + bool runtime·showframe(Func*, G*); void runtime·printcreatedby(G*); diff --git a/src/runtime/stack.c b/src/runtime/stack.c index fb23cc1c3..a4947a53b 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -706,6 +706,14 @@ runtime·newstack(void) runtime·printf("runtime: split stack overflow: %p < %p\n", sp, gp->stack.lo); runtime·throw("runtime: split stack overflow"); } + + if(gp->sched.ctxt != nil) { + // morestack wrote sched.ctxt on its way in here, + // without a write barrier. Run the write barrier now. + // It is not possible to be preempted between then + // and now, so it's okay. + runtime·writebarrierptr_nostore(&gp->sched.ctxt, gp->sched.ctxt); + } if(gp->stackguard0 == (uintptr)StackPreempt) { if(gp == g->m->g0) diff --git a/src/runtime/sys_x86.c b/src/runtime/sys_x86.c index a450b3e58..edbe47ff4 100644 --- a/src/runtime/sys_x86.c +++ b/src/runtime/sys_x86.c @@ -20,6 +20,7 @@ runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt) gobuf->sp = (uintptr)sp; gobuf->pc = (uintptr)fn; gobuf->ctxt = ctxt; + runtime·writebarrierptr_nostore(&gobuf->ctxt, ctxt); } // Called to rewind context saved during morestack back to beginning of function. -- cgit v1.2.1 From 4664f7441b495d8fa8aa5001755cb5f85e790b19 Mon Sep 17 00:00:00 2001 From: Rick Hudson Date: Wed, 12 Nov 2014 14:20:53 -0500 Subject: [dev.garbage] runtime: Add write barriers to c code Also improve missing GC mark diagnostics. LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/169450043 --- src/runtime/mgc0.c | 21 +++++++++++++++++++-- src/runtime/os_darwin.c | 3 +++ src/runtime/os_dragonfly.c | 3 +++ src/runtime/os_freebsd.c | 3 +++ src/runtime/os_linux.c | 3 +++ src/runtime/os_nacl.c | 3 +++ src/runtime/os_netbsd.c | 3 +++ src/runtime/os_openbsd.c | 3 +++ src/runtime/os_plan9.c | 6 ++++++ src/runtime/os_solaris.c | 3 +++ src/runtime/proc.c | 2 ++ 11 files changed, 51 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index 3c4d1afa5..214b9ebc2 100644 --- a/src/runtime/mgc0.c +++ b/src/runtime/mgc0.c @@ -29,8 +29,7 @@ // Preempted goroutines are scanned before P schedules next goroutine. // 3. Set phase = GCmark. // 4. Wait for all P's to acknowledge phase change. -// 5. Now write barrier marks and enqueues black or grey to white pointers. If a pointer is -// stored into a white slot, such pointer is not marked. +// 5. Now write barrier marks and enqueues black, grey, or white to white pointers. // Malloc still allocates white (non-marked) objects. // 6. Meanwhile GC transitively walks the heap marking reachable objects. // 7. When GC finishes marking heap, it preempts P's one-by-one and @@ -446,7 +445,25 @@ greyobject(byte *obj, Markbits *mbits, Workbuf *wbuf) if(checkmark) { if(!ismarked(mbits)) { + MSpan *s; + pageID k; + uintptr x, i; + runtime·printf("runtime:greyobject: checkmarks finds unexpected unmarked object obj=%p, mbits->bits=%x, *mbits->bitp=%x\n", obj, mbits->bits, *mbits->bitp); + + k = (uintptr)obj>>PageShift; + x = k; + x -= (uintptr)runtime·mheap.arena_start>>PageShift; + s = runtime·mheap.spans[x]; + runtime·printf("runtime:greyobject Span: obj=%p, k=%p", obj, k); + if (s == nil) { + runtime·printf(" s=nil\n"); + } else { + runtime·printf(" s->start=%p s->limit=%p, s->state=%d, s->sizeclass=%d, s->elemsize=%D \n", s->start*PageSize, s->limit, s->state, s->sizeclass, s->elemsize); + for(i=0; isizeclass; i++) { + runtime·printf(" ((uintptr*)obj)[%D]=%p\n", i, ((uintptr*)obj)[i]); + } + } runtime·throw("checkmark found unmarked object"); } if(ischeckmarked(mbits)) diff --git a/src/runtime/os_darwin.c b/src/runtime/os_darwin.c index bbd29282b..b866863d0 100644 --- a/src/runtime/os_darwin.c +++ b/src/runtime/os_darwin.c @@ -135,7 +135,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_dragonfly.c b/src/runtime/os_dragonfly.c index e372205ec..051192ad3 100644 --- a/src/runtime/os_dragonfly.c +++ b/src/runtime/os_dragonfly.c @@ -195,7 +195,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_freebsd.c b/src/runtime/os_freebsd.c index a513cb604..1c126547a 100644 --- a/src/runtime/os_freebsd.c +++ b/src/runtime/os_freebsd.c @@ -203,7 +203,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_linux.c b/src/runtime/os_linux.c index 9bd123d59..cc23774e3 100644 --- a/src/runtime/os_linux.c +++ b/src/runtime/os_linux.c @@ -233,7 +233,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_nacl.c b/src/runtime/os_nacl.c index 14b558303..ad72cc7c6 100644 --- a/src/runtime/os_nacl.c +++ b/src/runtime/os_nacl.c @@ -20,7 +20,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_netbsd.c b/src/runtime/os_netbsd.c index 58e5bedf2..28929ea57 100644 --- a/src/runtime/os_netbsd.c +++ b/src/runtime/os_netbsd.c @@ -271,7 +271,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_openbsd.c b/src/runtime/os_openbsd.c index eebaa13ee..960aaffff 100644 --- a/src/runtime/os_openbsd.c +++ b/src/runtime/os_openbsd.c @@ -217,7 +217,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_plan9.c b/src/runtime/os_plan9.c index f8c543f6f..18460fc12 100644 --- a/src/runtime/os_plan9.c +++ b/src/runtime/os_plan9.c @@ -20,12 +20,18 @@ runtime·mpreinit(M *mp) { // Initialize stack and goroutine for note handling. mp->gsignal = runtime·malg(32*1024); + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); + mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan); + runtime·writebarrierptr_nostore(&mp->notesig, mp->notesig); // Initialize stack for handling strings from the // errstr system call, as used in package syscall. mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan); + runtime·writebarrierptr_nostore(&mp->errstr, mp->errstr); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/os_solaris.c b/src/runtime/os_solaris.c index e16b8e637..bee91d8e6 100644 --- a/src/runtime/os_solaris.c +++ b/src/runtime/os_solaris.c @@ -176,7 +176,10 @@ void runtime·mpreinit(M *mp) { mp->gsignal = runtime·malg(32*1024); + runtime·writebarrierptr_nostore(&mp->gsignal, mp->gsignal); + mp->gsignal->m = mp; + runtime·writebarrierptr_nostore(&mp->gsignal->m, mp->gsignal->m); } // Called to initialize a new m (including the bootstrap m). diff --git a/src/runtime/proc.c b/src/runtime/proc.c index e5e2df2e4..c1df40d02 100644 --- a/src/runtime/proc.c +++ b/src/runtime/proc.c @@ -876,7 +876,9 @@ runtime·allocm(P *p) mp->g0 = runtime·malg(-1); else mp->g0 = runtime·malg(8192); + runtime·writebarrierptr_nostore(&mp->g0, mp->g0); mp->g0->m = mp; + runtime·writebarrierptr_nostore(&mp->g0->m, mp->g0->m); if(p == g->m->p) releasep(); -- cgit v1.2.1