From dc2bb6d0615067c5f0a0d6193f1774768f01f7e4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 Aug 2014 14:56:58 -0400 Subject: [PATCH 001/128] [dev.power64] create dev branch --- dev.power64 | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dev.power64 diff --git a/dev.power64 b/dev.power64 new file mode 100644 index 0000000000..e69de29bb2 From 8ad746d226b7a45060834c1e112e7777de8faa9e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 Aug 2014 14:57:34 -0400 Subject: [PATCH 002/128] [dev.power64] remove dummy file --- dev.power64 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dev.power64 diff --git a/dev.power64 b/dev.power64 deleted file mode 100644 index e69de29bb2..0000000000 From ccd880f290699a4227dd7f3dc3a83a89da3ca579 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 Aug 2014 14:58:17 -0400 Subject: [PATCH 003/128] cmd/dist, go/build: add power64, power64le to known GOARCH lists LGTM=dave, minux, aram R=minux, dave, bradfitz, aram CC=golang-codereviews https://golang.org/cl/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(-) diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index a994367351..70b7fb1056 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 09730d6351..e8bfc4a61e 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 965f873dfb..2ab53bb9cc 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 " From bd69b4479ad47d8e0de50928faa684ecdde20004 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 6 Aug 2014 15:12:08 -0400 Subject: [PATCH 004/128] cmd/dist: generate anames9.c LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/120690043 --- src/cmd/dist/build.c | 2 ++ src/cmd/dist/buildgc.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index 70b7fb1056..2e0f5b6360 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 66adf6857c..1c33297587 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 From 9512e470e10df9304ca54989015e76b46db4f540 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 16:16:28 -0400 Subject: [PATCH 005/128] [dev.power64] cmd/dist: recognize power64 and power64le as GOHOSTARCH LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/125760043 --- src/cmd/dist/unix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c index 8b943a2d95..668b189cac 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); } From 117b1d468527a2da8cf7686026d6ea23f23b0549 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 23:41:29 -0400 Subject: [PATCH 006/128] [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://golang.org/cl/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 diff --git a/src/cmd/9a/a.h b/src/cmd/9a/a.h new file mode 100644 index 0000000000..2f5ff6d819 --- /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 0000000000..e77d78c6df --- /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 0000000000..a7dbc45fa4 --- /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 0000000000..92dd9deb3a --- /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 0000000000..93bb010aa7 --- /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 0000000000..2b718b9f9d --- /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 0000000000..ed6213dbaa --- /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 0000000000..1d66146be1 --- /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 0000000000..fdbf0fcb28 --- /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 0000000000..6cb09dd423 --- /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 0000000000..ee48588c77 --- /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 0000000000..bad9a9c8a7 --- /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 0000000000..d6f9833beb --- /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 0000000000..4cf23fc6ad --- /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 0000000000..8ad2f7d06d --- /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 0000000000..0f2fd60a82 --- /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 0000000000..ea510df795 --- /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 0000000000..f9de2bf119 --- /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 0000000000..cf073ec36c --- /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 0000000000..a9083df9b4 --- /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; + } +} From 7582ecc996cd2009f0dbe97fe91c226b88ee12fd Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 23:43:36 -0400 Subject: [PATCH 007/128] [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://golang.org/cl/126780043 --- src/cmd/9g/doc.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/cmd/9g/doc.go diff --git a/src/cmd/9g/doc.go b/src/cmd/9g/doc.go new file mode 100644 index 0000000000..200be2eda2 --- /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 From c689eb9b21b97b888ef74b6ddccf9c08fd9d5c75 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 6 Aug 2014 23:59:14 -0400 Subject: [PATCH 008/128] [dev.power64] cmd/dist: power64/power64le support. LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/117670045 --- src/cmd/dist/build.c | 43 +++++++++++++++++++++++++++++++++---- src/cmd/dist/buildruntime.c | 7 ++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c index 2e0f5b6360..1feeccf417 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: [PATCH 009/128] [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://golang.org/cl/124830043 --- src/liblink/asm9.c | 852 +++++++++++++++++++++++++++++++++++++++++++++ src/liblink/obj9.c | 852 --------------------------------------------- 2 files changed, 852 insertions(+), 852 deletions(-) diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index ea510df795..27ccb0a237 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 cf073ec36c..0e869fb53f 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, From 83f6aadf16cde7a602b4f40a59038e2f8c4d11c8 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:36:34 -0400 Subject: [PATCH 010/128] [dev.power64] cmd/9c: use liblink, use Go argument passing rules, support both endians LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 | 363 ++++++------------------------------------- src/cmd/9c/txt.c | 132 +++++++++++----- 11 files changed, 333 insertions(+), 764 deletions(-) create mode 100644 src/cmd/9c/doc.go diff --git a/src/cmd/9c/cgen.c b/src/cmd/9c/cgen.c index 93bb010aa7..0d7a402945 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 0000000000..6c9b4762d8 --- /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 2b718b9f9d..1c7d7837a0 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 ed6213dbaa..5cfc442cb9 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 1d66146be1..af44bc8204 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 fdbf0fcb28..353376f15d 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 6cb09dd423..2e8e2adcc9 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 ee48588c77..658fa3211e 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 bad9a9c8a7..25f0438e58 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 d6f9833beb..c912cd5ed8 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; + Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); + if(pragcgobuf.to > pragcgobuf.start) { + Bprint(&outbuf, "\n"); + Bprint(&outbuf, "$$ // exports\n\n"); + Bprint(&outbuf, "$$ // local types\n\n"); + Bprint(&outbuf, "$$ // cgo\n"); + Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf)); + Bprint(&outbuf, "\n$$\n\n"); + } + Bprint(&outbuf, "!\n"); - 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; + writeobj(ctxt, &outbuf); + lastp = nil; } -void -zwrite(Biobuf *b, Prog *p, int sf, int st) +int32 +align(int32 i, Type *t, int op, int32 *maxalign) { - 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; + 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 4cf23fc6ad..345976cf20 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] */ From fcb842c6452516fd186cb54cc545c8922f7ff9c8 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:37:00 -0400 Subject: [PATCH 011/128] [dev.power64] .hgignore: update for the 9 toolchain LGTM=dave, rsc R=rsc, iant, dave CC=golang-codereviews https://golang.org/cl/124840043 --- .hgignore | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.hgignore b/.hgignore index 72d82910d9..5b90728d44 100644 --- a/.hgignore +++ b/.hgignore @@ -2,13 +2,13 @@ syntax:glob .DS_Store .git .gitignore -*.[568ao] -*.a[568o] +*.[5689ao] +*.a[5689o] *.so *.pyc ._* .nfs.* -[568a].out +[5689a].out *~ *.orig *.rej From bcf7f61f83dbade702b5f5c10ccd04e07d411c63 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:49:41 -0400 Subject: [PATCH 012/128] [dev.power64] cmd/9a: use liblink, add required additional instructions. LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 | 446 ++--- src/cmd/9a/y.tab.c | 3794 +++++++++++++++++++++++++++++++++++++++++++ src/cmd/9a/y.tab.h | 192 +++ 7 files changed, 4232 insertions(+), 437 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 diff --git a/src/cmd/9a/Makefile b/src/cmd/9a/Makefile new file mode 100644 index 0000000000..27290ddd71 --- /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 2f5ff6d819..629543f13f 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 e77d78c6df..2e0317e061 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 0000000000..44bf89dc00 --- /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 a7dbc45fa4..a9ad01eac0 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); } +static Prog *lastpc; + void -zname(char *n, int t, int s) +outcode(int a, Addr *g1, int reg, Addr *g2) { + Prog *p; + Plist *pl; - 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) + 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; + Prog *p; + Plist *pl; - 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; + if(pass == 1) + goto out; - 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); - } + 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 0000000000..9a09cf932f --- /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 0000000000..f1b4a72236 --- /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; + + From 7c33e5078f5c98fb1e973c65471c6a647927036c Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 14:56:59 -0400 Subject: [PATCH 013/128] [dev.power64] cmd/9l: update header files for liblink LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/128720044 --- src/cmd/9c/gc.h | 1 - src/cmd/9l/9.out.h | 96 +++++++++--- src/cmd/9l/l.h | 353 +++++---------------------------------------- 3 files changed, 114 insertions(+), 336 deletions(-) diff --git a/src/cmd/9c/gc.h b/src/cmd/9c/gc.h index 1c7d7837a0..82204902b7 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 8ad2f7d06d..6e4f9ee1b6 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 0f2fd60a82..d787f13844 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; +enum +{ + thechar = '9', + PtrSize = 8, + IntSize = 8, + RegSize = 8, + MaxAlign = 32, // max data alignment + FuncAlign = 8 +}; #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]; +#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 +}; From 4be75c8f26aaa2715505807a3dd3b0d9d8ce3f59 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 15:13:25 -0400 Subject: [PATCH 014/128] [dev.power64] include/link.h, liblink: convert 9l functions to liblink This replaces CL 122990043. LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/123010043 --- include/link.h | 27 +- src/liblink/asm9.c | 932 ++++++++++++++++--------------- src/liblink/list9.c | 254 +++++---- src/liblink/obj9.c | 1287 +++++++++++++------------------------------ 4 files changed, 1048 insertions(+), 1452 deletions(-) diff --git a/include/link.h b/include/link.h index 2b4de789d5..298b048e7c 100644 --- a/include/link.h +++ b/include/link.h @@ -62,9 +62,9 @@ struct Addr short type; uint8 index; int8 scale; - int8 reg; // for 5l - int8 name; // for 5l - int8 class; // for 5l + int8 reg; // for 5l, 9l + int8 name; // for 5l, 9l + int8 class; // for 5l, 9l uint8 etype; // for 5g, 6g, 8g int32 offset2; // for 5l, 8l struct Node* node; // for 5g, 6g, 8g @@ -89,9 +89,10 @@ struct Prog int32 lineno; Prog* link; short as; - uchar reg; // arm only + uchar reg; // arm, power64 only uchar scond; // arm only Addr from; + Addr from3; // power64 only, fma and rlwm Addr to; // for 5g, 6g, 8g internal use @@ -103,11 +104,11 @@ struct Prog Prog* comefrom; // 6l, 8l Prog* pcrel; // 5l int32 spadj; - uchar mark; + uint16 mark; + uint16 optab; // 5l, 9l uchar back; // 6l, 8l uchar ft; /* 6l, 8l oclass cache */ uchar tt; // 6l, 8l - uint16 optab; // 5l uchar isize; // 6l, 8l char width; /* fake for DATA */ @@ -232,10 +233,12 @@ enum enum { R_ADDR = 1, + R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power R_SIZE, R_CALL, // relocation for direct PC-relative call R_CALLARM, // relocation for ARM direct call R_CALLIND, // marker for indirect call (no actual relocating necessary) + R_CALLPOWER, // relocation for Power direct call R_CONST, R_PCREL, R_TLS, @@ -526,6 +529,9 @@ void span6(Link *ctxt, LSym *s); // asm8.c void span8(Link *ctxt, LSym *s); +// asm9.c +void span9(Link *ctxt, LSym *s); + // data.c vlong addaddr(Link *ctxt, LSym *s, LSym *t); vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add); @@ -572,10 +578,11 @@ Prog* copyp(Link*, Prog*); Prog* appendp(Link*, Prog*); vlong atolwhex(char*); -// list[568].c +// list[5689].c void listinit5(void); void listinit6(void); void listinit8(void); +void listinit9(void); // obj.c int linklinefmt(Link *ctxt, Fmt *fp); @@ -607,20 +614,24 @@ char* headstr(int); extern char* anames5[]; extern char* anames6[]; extern char* anames8[]; +extern char* anames9[]; extern char* cnames5[]; +extern char* cnames9[]; extern LinkArch link386; extern LinkArch linkamd64; extern LinkArch linkamd64p32; extern LinkArch linkarm; +extern LinkArch linkpower64; +extern LinkArch linkpower64le; #pragma varargck type "A" int #pragma varargck type "D" Addr* #pragma varargck type "lD" Addr* #pragma varargck type "P" Prog* #pragma varargck type "R" int -#pragma varargck type "^" int +#pragma varargck type "^" int // for 5l/9l, C_* classes (liblink internal) // TODO(ality): remove this workaround. // It's here because Pconv in liblink/list?.c references %L. diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 27ccb0a237..647e6f178e 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; - if(debug['v']) - Bprint(&bso, "%5.2f span\n", cputime()); - Bflush(&bso); + p = cursym->text; + if(p == nil || p->link == nil) // handle external functions and ELF section symbols + return; + + if(oprange[AANDN].start == nil) + buildop(ctxt); + + 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); + c += -c&(FuncAlign-1); + cursym->size = c; - 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; + /* + * lay out the code, emitting code and data relocations. + */ + if(ctxt->tlsg == nil) + ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0); - s = lookup(p, 0); - if(s->type == 0 || s->type == SXREF) { - s->type = t; - s->value = v; + 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) +static void +maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v) { if(!getmask64(m, v)) - diag("cannot generate mask #%llux\n%P", v, p); + ctxt->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 +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 f9de2bf119..3299d269a3 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); + + // for liblink internal use + fmtinstall('^', DRconv); + + // for internal use + fmtinstall('$', DSconv); + fmtinstall('M', Mconv); } -void -prasm(Prog *p) -{ - print("%P\n", p); -} +static Prog* bigP; -int +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, 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; + } - 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); + 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) { - l = a->offset; - if((vlong)l != a->offset) - sprint(str, "0x%llux", a->offset); - else - sprint(str, "%lld", a->offset); - goto out; - } + //if(s == nil) { + // l = a->offset; + // if((vlong)l != a->offset) + // sprint(str, "0x%llux", a->offset); + // else + // sprint(str, "%lld", a->offset); + // goto out; + //} switch(a->name) { default: sprint(str, "GOK-name(%d)", a->name); break; + case D_NONE: + l = a->offset; + if((vlong)l != a->offset) + sprint(str, "0x%llux", a->offset); + else + sprint(str, "%lld", a->offset); + break; + case D_EXTERN: - 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 0e869fb53f..63f5b59b01 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" -#include "l.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, + }, +}; -void -noops(void) +static int +symtype(Addr *a) { - Prog *p, *p1, *q, *q1; - int o, mov, aoffset, curframe, curbecome, maxbecome; + return a->name; +} + +static int +isdata(Prog *p) +{ + return p->as == ADATA || p->as == AGLOBL; +} + +static int +iscall(Prog *p) +{ + return p->as == ABL; +} + +static int +datasize(Prog *p) +{ + return p->reg; +} + +static int +textflag(Prog *p) +{ + return p->reg; +} + +static void +settextflag(Prog *p, int f) +{ + p->reg = f; +} + +static void +progedit(Link *ctxt, Prog *p) +{ + char literal[64]; + LSym *s; + + USED(ctxt); + + p->from.class = 0; + p->to.class = 0; + + // Rewrite BR/BL to symbol as D_BRANCH. + switch(p->as) { + case ABR: + case ABL: + case ARETURN: + case ADUFFZERO: + case ADUFFCOPY: + if(p->to.sym != nil) + p->to.type = D_BRANCH; + break; + } + + // Rewrite float constants to values stored in memory. + switch(p->as) { + case AFMOVS: + if(p->from.type == D_FCONST) { + int32 i32; + float32 f32; + f32 = p->from.u.dval; + memmove(&i32, &f32, 4); + sprint(literal, "$f32.%08ux", (uint32)i32); + s = linklookup(ctxt, literal, 0); + s->size = 4; + p->from.type = D_OREG; + p->from.sym = s; + p->from.name = D_EXTERN; + p->from.offset = 0; + } + break; + case AFMOVD: + if(p->from.type == D_FCONST) { + int64 i64; + memmove(&i64, &p->from.u.dval, 8); + sprint(literal, "$f64.%016llux", (uvlong)i64); + s = linklookup(ctxt, literal, 0); + s->size = 8; + p->from.type = D_OREG; + p->from.sym = s; + p->from.name = D_EXTERN; + p->from.offset = 0; + } + break; + case AMOVD: + if(p->from.type == D_CONST && p->from.name == D_NONE && (int64)(uint32)p->from.offset != p->from.offset) { + sprint(literal, "$i64.%016llux", (uvlong)p->from.offset); + s = linklookup(ctxt, literal, 0); + s->size = 8; + p->from.type = D_OREG; + p->from.sym = s; + p->from.name = D_EXTERN; + p->from.offset = 0; + } + } + + // Rewrite SUB constants into ADD. + switch(p->as) { + case ASUBC: + if(p->from.type == D_CONST) { + p->from.offset = -p->from.offset; + p->as = AADDC; + } + break; + + case ASUBCCC: + if(p->from.type == D_CONST) { + p->from.offset = -p->from.offset; + p->as = AADDCCC; + } + break; + + case ASUB: + if(p->from.type == D_CONST) { + p->from.offset = -p->from.offset; + p->as = AADD; + } + break; + } +} + +static Prog* stacksplit(Link*, Prog*, int32, int); + +static void +parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg) +{ + *textstksiz = arg & 0xffffffffLL; + if(*textstksiz & 0x80000000LL) + *textstksiz = -(-*textstksiz & 0xffffffffLL); + + *textarg = (arg >> 32) & 0xffffffffLL; + if(*textarg & 0x80000000LL) + *textarg = 0; + *textarg = (*textarg+7) & ~7LL; +} + +static void +addstacksplit(Link *ctxt, LSym *cursym) +{ + Prog *p, *q, *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; + Prog *firstp, *lastp; - 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); - } + ctxt->cursym = s; - /* - * 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); + firstp = ctxt->arch->prg(); + lastp = firstp; + xfol(ctxt, s->text, &lastp); + lastp->link = nil; + s->text = firstp->link; } -void -undef(void) -{ - int i; - Sym *s; - - for(i=0; ilink) - if(s->type == SXREF) - diag("%s: not defined", s->name); -} - -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; +LinkArch linkpower64 = { + .name = "power64", + .thechar = '9', + .endian = BigEndian, - 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; - } + .addstacksplit = addstacksplit, + .assemble = span9, + .datasize = datasize, + .follow = follow, + .iscall = iscall, + .isdata = isdata, + .prg = prg, + .progedit = progedit, + .settextflag = settextflag, + .symtype = symtype, + .textflag = textflag, - 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); + .minlc = 4, + .ptrsize = 8, + .regsize = 8, - /* signature */ - p = newdata(et, off, sizeof(long), D_EXTERN); - off += sizeof(long); - p->to.offset = s->sig; + .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, - /* 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, + .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}; +LinkArch linkpower64le = { + .name = "power64le", + .thechar = '9', + .endian = LittleEndian, -typedef struct Reloc Reloc; + .addstacksplit = addstacksplit, + .assemble = span9, + .datasize = datasize, + .follow = follow, + .iscall = iscall, + .isdata = isdata, + .prg = prg, + .progedit = progedit, + .settextflag = settextflag, + .symtype = symtype, + .textflag = textflag, -struct Reloc -{ - int n; - int t; - uchar *m; - ulong *a; + .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); - } -} From 95e8a3a1da2ba736c685424ecd9f23f6e78f27aa Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:34:25 -0400 Subject: [PATCH 015/128] [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://golang.org/cl/125840043 --- src/cmd/9c/swt.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/cmd/9c/swt.c b/src/cmd/9c/swt.c index c912cd5ed8..83058e7ab9 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 From 6e02e1cfc2a75380477a5a1f6f1e55a76b72f412 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:36:42 -0400 Subject: [PATCH 016/128] [dev.power64] cmd/ld: update for power64 LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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(-) diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 96eadd479a..702f559a88 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 8135bd549c..cea809715d 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 3f93f58184..702d4dfcbb 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 3196961f35..6ac6b6ee82 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 38e4147556..284f7b21d6 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 0a5d8d99f2..bdba217478 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 4094dfa6b1..6ce880ea9e 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 61306bb7ca..c645e64097 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 1805f97d3a..8149a67167 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); From 5b0ac5f76eca0f96b926c7f80d094b159b2fbcc5 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:41:09 -0400 Subject: [PATCH 017/128] [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://golang.org/cl/127770043 --- src/liblink/objfile.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c index 22c9199d5e..3b78571b74 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; From 05d72029db988c691bf951340215b8b7e98fd594 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 7 Aug 2014 18:41:37 -0400 Subject: [PATCH 018/128] [dev.power64] cmd/9c: add Makefile LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/121370043 --- src/cmd/9c/Makefile | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/cmd/9c/Makefile diff --git a/src/cmd/9c/Makefile b/src/cmd/9c/Makefile new file mode 100644 index 0000000000..3f528d7517 --- /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 From 40d7a6d58254933f941950b1c4714127a1a8a13b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:31:28 -0400 Subject: [PATCH 019/128] [dev.power64] cmd/ld: add MAXIO back in lib.h It was accidentally removed. LGTM=dave R=rsc, iant, dave CC=golang-codereviews https://golang.org/cl/124880043 --- src/cmd/ld/lib.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 6ce880ea9e..4094dfa6b1 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; From 26c9bbf736f97d8f72c20ed3853352484a77c72f Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:32:08 -0400 Subject: [PATCH 020/128] [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://golang.org/cl/127780043 --- src/pkg/runtime/{traceback_arm.c => traceback_lr.c} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename src/pkg/runtime/{traceback_arm.c => traceback_lr.c} (99%) diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_lr.c similarity index 99% rename from src/pkg/runtime/traceback_arm.c rename to src/pkg/runtime/traceback_lr.c index 778d95a28b..d8fcddf68b 100644 --- a/src/pkg/runtime/traceback_arm.c +++ b/src/pkg/runtime/traceback_lr.c @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build arm power64 power64le + #include "runtime.h" #include "arch_GOARCH.h" #include "malloc.h" @@ -267,7 +269,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, // sighandler saves the lr on stack before faking a call to sigpanic if(waspanic) { x = *(uintptr*)frame.sp; - frame.sp += 4; + frame.sp += sizeof(uintptr); frame.fn = f = runtime·findfunc(frame.pc); if(f == nil) frame.pc = x; From 8881e032d43470bdeaabc9b93b5a948094264d2c Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:32:33 -0400 Subject: [PATCH 021/128] [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://golang.org/cl/124900043 --- src/pkg/runtime/os_linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkg/runtime/os_linux.c b/src/pkg/runtime/os_linux.c index 77754f481c..b9ac8c619c 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"); } From 5cb7da754773de4fcc104d0263efb0661fb7574d Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:43:15 -0400 Subject: [PATCH 022/128] [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://golang.org/cl/124990043 --- src/pkg/syscall/types_linux.go | 104 ++------------------------------- 1 file changed, 5 insertions(+), 99 deletions(-) diff --git a/src/pkg/syscall/types_linux.go b/src/pkg/syscall/types_linux.go index e8396a41f3..8ea499246f 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 ) From 059d089fc0a02c2580b67d271baa269de6c0894c Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:43:34 -0400 Subject: [PATCH 023/128] [dev.power64] debug/elf: add power64 support along with relocation test LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/125910043 --- src/pkg/debug/elf/elf.go | 178 ++++++++++++++++++ src/pkg/debug/elf/file.go | 50 ++++- src/pkg/debug/elf/file_test.go | 6 + .../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 diff --git a/src/pkg/debug/elf/elf.go b/src/pkg/debug/elf/elf.go index d622dae2af..51319c0ddc 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 7be9deaa5f..5e1c47a04c 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 5e4ad5c100..db9a7476c3 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 0000000000000000000000000000000000000000..dad7445486e8897ad351ec2c8fad09f0d8ee494d GIT binary patch literal 3016 zcmbtWy>HV{5I@JIw4@FF013oED)B9B(o)e-K>ZR_NC+V$SQx-@olw!(sr?M8ghV!w z7+8>Cg8>ExR>XqDzre)I%mNz{L%FlxrOz)$AUG+xyWjop?!EJSP9B`UbfI7vz+%8| z*zy=ujTOKvFud zeiEjyf>8%$JzX4dS;nYwuryvYOZ!Tr#+WhEk8~U6hRlK4;+Y~r^Zm~jhm@QFX%}D} z*ycE56}CsZyeAd54|K70rDAFxMH4_?GY@VKrQLx;kaGTJEXoHP3d_a)W6{bd0lweys5~nah{2m6yuXcGaFLTMN-f zB)sOiwN*cEZ@IC*s(7s+BDWcNZX9}6YfYddV&6O03hsGf6+O2Vr_M~-YOLII!n%dk z>ydEWJ60R*QWRrwg$rPsfQnc{Bw8=s|3v7|_>V7&1T~ zB>Rh{$_ry*ct3Fxv7?QqaB5&jB24vdwuILfV6QmB0lOAOV2i*78)xmI9x7|=1|ewGQh zq-LdaDXwG0osnRL97S~Q4UFaO|4K1U;(XfwAb#}y3&ixAl-ZErb#fHZxdF!V`gdf1 zo-_3)Nblc4jB4^a(M;rnZ1kD|skuMv$B5_U*W^3);2-jz%6yFm54-Q^Y=rwV`sO$J zk7Rz8iBj|a8GeOE-u#~DJiig-az4*>6fynoQtgkj|2uLN(brFY-d5ksMje^33wb;7 zqxYvXmDj&2?;pKiRMGpZG1VqsAAH|bF}BUz6HDvJ+X>-$Dr>&5Jku7-jGlo_385c)%m{wiUZkW literal 0 HcmV?d00001 From 6e692b35bb57720331c06da400ed99a159f31fa5 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:43:51 -0400 Subject: [PATCH 024/128] [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://golang.org/cl/119640043 --- src/cmd/cgo/main.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 17b0cdd167..0dc22dcd45 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 From 1a1d4507128425c3f0a71fa878f40075dbe68e60 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:44:23 -0400 Subject: [PATCH 025/128] [dev.power64] cmd/9l: introduce the power64 linker, based loosely on 5l LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/cmd/9l/Makefile b/src/cmd/9l/Makefile new file mode 100644 index 0000000000..3f528d7517 --- /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 0000000000..5aeea1b6b0 --- /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 0000000000..9df5dc6148 --- /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 0000000000..af8dc15885 --- /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 0000000000..1ab18f491a --- /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); +} From 552d8b79dde79dac269b124337765bb7993ec922 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:44:38 -0400 Subject: [PATCH 026/128] [dev.power64] cmd/9l/9.out.h: introduce NFREG, REGG, REGRT1 and REGRT2 LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/125990043 --- src/cmd/9l/9.out.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h index 6e4f9ee1b6..e494e90ca9 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 */ From 4928b2074b70e701f8dcc3d09f4c46243482916a Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Mon, 11 Aug 2014 23:44:55 -0400 Subject: [PATCH 027/128] [dev.power64] cmd/9g: first check point LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c new file mode 100644 index 0000000000..af87b3a079 --- /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 0000000000..97a5a5d06c --- /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 0000000000..2b95dc7a6f --- /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 0000000000..999b630faa --- /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 0000000000..fdd7606bcd --- /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 0000000000..bb70bb7fdf --- /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 0000000000..d3cbcb9570 --- /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 0000000000..5721d7b04f --- /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 0000000000..0a51a533a0 --- /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 0000000000..bbebf3fe03 --- /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"); +// } + } +} From 5f691cfaf1a6a4e2365fad423c1fe1f9b7975efb Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:48:49 -0400 Subject: [PATCH 028/128] [dev.power64] runtime: manually written parts for linux/power64 and linux/power64le, checkpoint LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/pkg/runtime/arch_power64.h b/src/pkg/runtime/arch_power64.h new file mode 100644 index 0000000000..3d5b4943c7 --- /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 0000000000..d9241da98b --- /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 0000000000..52640f407a --- /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 0000000000..c08590ac97 --- /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 0000000000..4a2437c209 --- /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 0000000000..b618f0ad7b --- /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 0000000000..e944bcdbf8 --- /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 0000000000..051815dbce --- /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 0000000000..8406489209 --- /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 0000000000..8406489209 --- /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 0000000000..89c5c78485 --- /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 0000000000..c0c41efa95 --- /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 0000000000..ed8900c45e --- /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"); +} + From f3e2023764de0ee7bfd387cb629611cc4f989da7 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:03 -0400 Subject: [PATCH 029/128] [dev.power64] syscall: the manually written parts for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/pkg/syscall/asm_linux_power64x.s b/src/pkg/syscall/asm_linux_power64x.s new file mode 100644 index 0000000000..1dd23ef305 --- /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 0000000000..dbe37c44e1 --- /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) +} From e0aaf2b2dbbba264a112e498666821f412b87ba9 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:18 -0400 Subject: [PATCH 030/128] [dev.power64] syscall: auto-generated source for linux/power64 and linux/power64le. LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/pkg/syscall/zerrors_linux_power64.go b/src/pkg/syscall/zerrors_linux_power64.go new file mode 100644 index 0000000000..9409bdba32 --- /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 0000000000..de3b442a15 --- /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 0000000000..5f8feccc5c --- /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 0000000000..5f8feccc5c --- /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 0000000000..0567fd0ea8 --- /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 0000000000..52c63e3d3e --- /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 0000000000..5a34068bc1 --- /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 0000000000..647755cb12 --- /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 +) From c74a4d4addfeb4089efcef3ccf3658813d8bd9e9 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:31 -0400 Subject: [PATCH 031/128] [dev.power64] syscall: script changes for power64 LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/123290043 --- src/pkg/syscall/mkall.sh | 19 +++++++++++++++++-- src/pkg/syscall/mkerrors.sh | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/pkg/syscall/mkall.sh b/src/pkg/syscall/mkall.sh index 886db133cb..ac1c20f036 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 cf0afe0bdd..4711f307a8 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_/ && From f2d43ec7cd8727193130eee08331f7d963f59307 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:41 -0400 Subject: [PATCH 032/128] [dev.power64] os/signal: support for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/121580043 --- src/pkg/os/signal/sig.s | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pkg/os/signal/sig.s b/src/pkg/os/signal/sig.s index f860924aa0..c324fcda4e 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) From 2abf3c5583f0eda0b7f8334bd321ea16be6993a1 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:49:52 -0400 Subject: [PATCH 033/128] [dev.power64] runtime: changes to the portable part for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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(-) diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c index aa4cf5ee52..2149d7c723 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 af8bb1bc0e..748c4174bb 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 26e687e3b4..23513e1a7b 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 0a806e8fab..49ecd6cc36 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; From fb57459b48ea6bae22a270339aabe5c48a51b063 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:03 -0400 Subject: [PATCH 034/128] [dev.power64] runtime: move noasm_arm.goc to noasm.goc LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/121590043 --- src/pkg/runtime/{noasm_arm.goc => noasm.goc} | 2 ++ 1 file changed, 2 insertions(+) rename src/pkg/runtime/{noasm_arm.goc => noasm.goc} (97%) diff --git a/src/pkg/runtime/noasm_arm.goc b/src/pkg/runtime/noasm.goc similarity index 97% rename from src/pkg/runtime/noasm_arm.goc rename to src/pkg/runtime/noasm.goc index fe3591e8a3..4966677293 100644 --- a/src/pkg/runtime/noasm_arm.goc +++ b/src/pkg/runtime/noasm.goc @@ -5,6 +5,8 @@ // 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" From 91447ab502ee97f0666a807b9a1081cc4e7f7201 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:18 -0400 Subject: [PATCH 035/128] [dev.power64] runtime: auto-generated headers for linux/power64 and linux/power64le LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/pkg/runtime/defs_linux_power64.h b/src/pkg/runtime/defs_linux_power64.h new file mode 100644 index 0000000000..41db45ca14 --- /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 0000000000..41db45ca14 --- /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 From ab29d5b4ae54f256cb8bbed366b7c028e4993e99 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:30 -0400 Subject: [PATCH 036/128] [dev.power64] runtime: add defs3_linux.go to generate defs_linux_power64{,le}.h LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/pkg/runtime/defs1_linux.go b/src/pkg/runtime/defs1_linux.go index 451817a67a..c0b510ac41 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 0000000000..eb65f9d1ed --- /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 8657dbb0ec..553366a50b 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 From e7e668d7174517210608bf8e556124c777ec06b7 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:40 -0400 Subject: [PATCH 037/128] [dev.power64] math: implement Abs, add power64/power64le forwarding assembly functions LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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 diff --git a/src/pkg/math/abs_power64x.s b/src/pkg/math/abs_power64x.s new file mode 100644 index 0000000000..8fd8020f98 --- /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 0000000000..0cb86144a7 --- /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) From 56949d33d889778d03dd43afc37afdc3cf224223 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:50:51 -0400 Subject: [PATCH 038/128] [dev.power64] sync/atomic: implement for asm_power64x.s LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/124220043 --- src/pkg/sync/atomic/asm_power64x.s | 184 +++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/pkg/sync/atomic/asm_power64x.s diff --git a/src/pkg/sync/atomic/asm_power64x.s b/src/pkg/sync/atomic/asm_power64x.s new file mode 100644 index 0000000000..bdb1dcff49 --- /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) From b1c9a8bce3a0556f4661e535cff75e96d4dbd323 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 19:51:01 -0400 Subject: [PATCH 039/128] [dev.power64] cmd/9g: implement zerorange LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/121540043 --- src/cmd/9g/ggen.c | 69 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c index 999b630faa..09f51536a5 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. From 5e4989cf0a2a0d6fc0d0dbf6f476f20cf400e33b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:57:32 -0400 Subject: [PATCH 040/128] [dev.power64] cmd/gc: handle thechar=='9', disable nilopt() for now LGTM=rsc R=rsc, iant, dave CC=golang-codereviews https://golang.org/cl/121630043 --- src/cmd/gc/pgen.c | 4 ++-- src/cmd/gc/popt.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index cabba6824e..5ac46e774e 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 c8d60c5add..4c75e6c265 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; From f4529adabefa07b63b8bff23b5108f590a13e2b6 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:57:45 -0400 Subject: [PATCH 041/128] [dev.power64] liblink: support stack split, long conditional branches LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/123300043 --- src/liblink/asm9.c | 48 ++++++--- src/liblink/list9.c | 5 +- src/liblink/obj9.c | 234 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 242 insertions(+), 45 deletions(-) diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 647e6f178e..886edf347d 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 3299d269a3..9700a16849 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 63f5b59b01..90145a46f8 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 + 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 = 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 = 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; - q1->link = q->link; - q->link = q1; + 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; } From 560cf4c6de08228f18fbf32e5c7f939c0b4885ba Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:57:54 -0400 Subject: [PATCH 042/128] [dev.power64] cmd/9l: remove MAXIO (fix build) LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/124270043 --- src/cmd/9l/l.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/9l/l.h b/src/cmd/9l/l.h index d787f13844..dda741c56b 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, From 860f941e7fdcb22c6b4956f187cb47fd06833c12 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 20:58:05 -0400 Subject: [PATCH 043/128] [dev.power64] cmd/9c: fix endian issue in integer to floating point conversion LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/129850043 --- src/cmd/9c/txt.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/cmd/9c/txt.c b/src/cmd/9c/txt.c index 345976cf20..84aeb4d8a9 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 */ From 3e4dfdad34053d05be47bfe06c4243350bedd48f Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:22:27 -0400 Subject: [PATCH 044/128] [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://golang.org/cl/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(-) diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index af87b3a079..3644ebf8f6 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 be929e99ed..cb1873f853 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 bdba217478..b4134da368 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); From 27627fd8ed132006e52f141f2abca743bf365bca Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 12 Aug 2014 21:38:50 -0400 Subject: [PATCH 045/128] [dev.power64] hash/crc32: use portable castagnoli on power64 LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/128110044 --- src/pkg/hash/crc32/crc32_generic.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/hash/crc32/crc32_generic.go b/src/pkg/hash/crc32/crc32_generic.go index c3fdcd685c..1c7f806c60 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 From 53b78c84bc118d514c95794770c87dcb850368fb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 12 Aug 2014 21:41:42 -0400 Subject: [PATCH 046/128] [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://golang.org/cl/126100043 --- src/cmd/9a/lex.c | 123 ++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c index a9ad01eac0..116618f25a 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; + 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); - case 'D': - p = ARGF(); - if(p) { - if (nDlist%8 == 0) - Dlist = allocn(Dlist, nDlist*sizeof(char *), - 8*sizeof(char *)); - Dlist[nDlist++] = p; - } - break; + flagparse(&argc, &argv, usage); + ctxt->debugasm = debug['S']; - 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) + 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); From ca7f2c796f1badcc254c0608e304b25e2915683d Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:43:31 -0400 Subject: [PATCH 047/128] [dev.power64] reflect: add assembly stubs LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/126090043 --- src/pkg/reflect/asm_power64x.s | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/pkg/reflect/asm_power64x.s diff --git a/src/pkg/reflect/asm_power64x.s b/src/pkg/reflect/asm_power64x.s new file mode 100644 index 0000000000..78839075c4 --- /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) From c229cec23a228e0ce6962dae200736f516ede1f0 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:55:43 -0400 Subject: [PATCH 048/128] [dev.power64] runtime: implemnt runtime.switchtoM and runtime.onM LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/129860043 --- src/pkg/runtime/asm_power64x.s | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 52640f407a..5c67e19485 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 */ From 05d670f757d313abe9170365610ca3fcb7bd1607 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 21:56:20 -0400 Subject: [PATCH 049/128] [dev.power64] liblink: disable stack split for now LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/122460043 --- src/liblink/obj9.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 90145a46f8..321e2c9bf4 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; From dbf406a9d89c00ec1975368ae95a70da9f704eaa Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 22:07:15 -0400 Subject: [PATCH 050/128] [dev.power64] cmd/gc: disable magic multiply optimizations for now LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/126110043 --- src/cmd/gc/walk.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index cb1873f853..cf25a3eac7 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; From f0393221a7b693421816b9c5c6485bacb11b460a Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 22:25:43 -0400 Subject: [PATCH 051/128] [dev.power64] cmd/9g: clear p->reg for ATEXT LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/125150043 --- src/cmd/9g/gsubr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index bb70bb7fdf..0e5df5c6dc 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); From 9b88857f7565a426d1469e8a9b51d9bf045adc9b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 22:28:25 -0400 Subject: [PATCH 052/128] [dev.power64] runtime: disable GC and use a larger default stack LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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(-) diff --git a/src/pkg/runtime/malloc.go b/src/pkg/runtime/malloc.go index dedcea94a6..68baa80d52 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 e7955151ce..03622db283 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 ee5fd351d5..64d377754f 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, From 893f28ca16948530651394b83337e60f36bdc559 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 23:57:02 -0400 Subject: [PATCH 053/128] [dev.power64] cmd/9g: introduce ginscon2 for CMP/CMPU, use ginscon to ADD constants LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/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(-) diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index 3644ebf8f6..f8078aece3 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 2b95dc7a6f..319702200c 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 0e5df5c6dc..a5ce5f141f 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); */ From 268d90119947d88063964211c0f3b122fffc96a3 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 12 Aug 2014 23:57:42 -0400 Subject: [PATCH 054/128] [dev.power64] runtime: fix morestack Must not save LR. LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/129040044 --- src/pkg/runtime/asm_power64x.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 5c67e19485..2fbaf5a53e 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) From bc8d35a9cfc5c2da2ca9586e0aef457fd4bdc0bd Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:22:21 -0400 Subject: [PATCH 055/128] [dev.power64] cmd/cc: round argsize to multiples of wordsize on power64 LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/121640043 --- src/cmd/cc/pgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c index 0ee13787f0..c2cf0e1010 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; From 372b5cebe7ba84218fdc724b2f17279a53293836 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:22:34 -0400 Subject: [PATCH 056/128] [dev.power64] cmd/9g: use loops to do memmove in sgen() LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/128130044 --- src/cmd/9g/cgen.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index f8078aece3..a8d628f43b 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; From f375c0eb0d30f078baf5580c30b2a34f5507279b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:22:47 -0400 Subject: [PATCH 057/128] [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://golang.org/cl/129050043 --- src/liblink/obj9.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 321e2c9bf4..960083bf9b 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; From b6d6eb21ec37f2eba998572f858acaf7324ec245 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 01:23:00 -0400 Subject: [PATCH 058/128] [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://golang.org/cl/129850044 --- src/pkg/runtime/stack.h | 2 +- src/pkg/runtime/sys_power64x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkg/runtime/stack.h b/src/pkg/runtime/stack.h index 64d377754f..ee5fd351d5 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 ed8900c45e..79d976255f 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; } From f285537b7f16a726284b0a0b482a8733e16d9f01 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 11:39:07 -0400 Subject: [PATCH 059/128] [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://golang.org/cl/125200043 --- src/cmd/9g/gg.h | 1 - src/cmd/9g/gsubr.c | 25 ------------------------- 2 files changed, 26 deletions(-) diff --git a/src/cmd/9g/gg.h b/src/cmd/9g/gg.h index 319702200c..6aa00117f8 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 a5ce5f141f..d8842796a8 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) From 6e73ae88b58cab948490e97189e1746c85b88cc3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 14:36:29 -0400 Subject: [PATCH 060/128] [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://golang.org/cl/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 diff --git a/src/cmd/9l/obj.c b/src/cmd/9l/obj.c index 1ab18f491a..badb72a1ac 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 0000000000..502d40cb64 --- /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 3d5b4943c7..1dcbbc226c 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 2fbaf5a53e..59c7a9eb5a 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 635594c365..30594c5282 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 c0c41efa95..f5149eaeaf 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 1dd23ef305..c9b0fe320c 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 From ebf42035b76acad4c5f58b7904750b7fb0b25a42 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 14:52:01 -0400 Subject: [PATCH 061/128] [dev.power64] runtime: fix newstackcall moreframesize is a uint32, not a uint64. LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/124310043 --- src/pkg/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 59c7a9eb5a..e530e704ef 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 From 856124a1cdde18050146a9b15230fac2e618bf8e Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 14:52:11 -0400 Subject: [PATCH 062/128] [dev.power64] runtime: fix build LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/128180044 --- src/pkg/runtime/sys_linux_power64x.s | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index f5149eaeaf..df808a83c3 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 From f3f332851f9b9b7bc35a6a189c4a0e95c79a7956 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 13 Aug 2014 15:49:07 -0400 Subject: [PATCH 063/128] [dev.power64] cmd/9g: add missing break LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/125260043 --- src/cmd/9g/gsubr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index d8842796a8..dfdff05879 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): From 27e657ef68a67b3160358f6ab20f6338bbf30706 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 15:49:19 -0400 Subject: [PATCH 064/128] [dev.power64] cmd/9g: fix floating-point comparison for NaN LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/127300043 --- src/cmd/9g/cgen.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index a8d628f43b..6bb44f547c 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; From 404472e50b2430c3d67ce4544c02ee0c55cec95b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 15:50:06 -0400 Subject: [PATCH 065/128] [dev.power64] runtime: fix C prototype for cmallocgc LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/122520043 --- src/pkg/runtime/malloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/runtime/malloc.c b/src/pkg/runtime/malloc.c index d56d0dcf31..1e133168b1 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) From b7a6fd28db8a155946a9662c8ab984c4d5befe60 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 16:26:43 -0400 Subject: [PATCH 066/128] [dev.power64] runtime: fix reflect.call The code to copy out the results was incorrect. LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/122530043 --- src/pkg/runtime/asm_power64x.s | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index e530e704ef..1a72b1b3c2 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 From ba9a11e55765250a413396ecef36e1ba71a099cc Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 18:14:13 -0400 Subject: [PATCH 067/128] [dev.power64] liblink: fix handling of MOVD with large constants LGTM=minux R=golang-codereviews, minux CC=golang-codereviews https://golang.org/cl/122540043 --- src/liblink/asm9.c | 15 +++++++++------ src/liblink/obj9.c | 9 --------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 886edf347d..f1889a92c2 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 960083bf9b..3405fce477 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); From 76b1ddbb96e184a4a83b58bcc46af087aa711398 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 13 Aug 2014 18:32:54 -0400 Subject: [PATCH 068/128] [dev.power64] liblink: fix handling of $nnn(reg) LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/126180043 --- src/liblink/asm9.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index f1889a92c2..352fba9154 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); From 4f557008e85ee0381bc1955b943cc9f6d9679af0 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 11:57:10 -0400 Subject: [PATCH 069/128] [dev.power64] liblink: fix $large(SP) for floating point load/store Fixes test/cmplxdivide. LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/128190045 --- src/liblink/asm9.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 352fba9154..56582fe27d 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 */ From b697c120f6ccf30dbc26ce757122f2b4fd908f47 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 11:59:52 -0400 Subject: [PATCH 070/128] [dev.power64] reflect: now we find one big endian machine LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/124350043 --- src/pkg/reflect/value.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go index 576cbc3984..50f5315961 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" From 5f02073dedd5174db2e24ef1597f36606da9696b Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 11:59:58 -0400 Subject: [PATCH 071/128] [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://golang.org/cl/122550043 --- src/pkg/runtime/sys_linux_power64x.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index df808a83c3..1d985d1af1 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) From f464573c70b4de3ebfa8a7c038b183e583af2434 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 12:01:14 -0400 Subject: [PATCH 072/128] [dev.power64] runtime: add power64/power64le as supported arch to gcinfo_test.go LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/122560043 --- src/pkg/runtime/gcinfo_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pkg/runtime/gcinfo_test.go b/src/pkg/runtime/gcinfo_test.go index 6afa9a4e2b..5e5b7ec375 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") } From 7776b0a1cc8924b4dfb014715d5b87e8f7fcdca0 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 12:01:21 -0400 Subject: [PATCH 073/128] [dev.power64] syscall: re-generate using cgo compiled by gc, fix test failures LGTM=dave, rsc R=rsc, iant, dave CC=golang-codereviews https://golang.org/cl/127320043 --- 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(-) diff --git a/src/pkg/syscall/syscall_linux_power64x.go b/src/pkg/syscall/syscall_linux_power64x.go index dbe37c44e1..c0ea660d4f 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 8ea499246f..5e9f698cf1 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 9409bdba32..15e0770c18 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 de3b442a15..fdecdf24dd 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 5f8feccc5c..7808059cc8 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 5f8feccc5c..7808059cc8 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 5a34068bc1..204d806853 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 647755cb12..df481f5c76 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 { From b3375771fcd67d2dc7c7eee2bcd093ab4c126ec4 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 12:01:27 -0400 Subject: [PATCH 074/128] [dev.power64] runtime: don't fault on runtime.procyield, just return LGTM=dave, rsc R=rsc, iant, dave CC=golang-codereviews https://golang.org/cl/128230044 --- src/pkg/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/runtime/asm_power64x.s b/src/pkg/runtime/asm_power64x.s index 1a72b1b3c2..a0511de8e6 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) From 80e76e272adda0ab664cf5b6425e994b4e491e8c Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Thu, 14 Aug 2014 13:59:58 -0400 Subject: [PATCH 075/128] [dev.power64] test/nosplit.go: add power64 support LGTM=rsc R=rsc, iant CC=golang-codereviews https://golang.org/cl/125210043 --- test/nosplit.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/nosplit.go b/test/nosplit.go index 35aa51017a..de279efdd4 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -231,9 +231,17 @@ TestCases: } var buf bytes.Buffer - if goarch == "arm" { + ptrSize := 4 + switch goarch { + case "power64", "power64le": + ptrSize = 8 + fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n#define RET RETURN\n") + case "arm": fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n") - } else { + case "amd64": + ptrSize = 8 + fmt.Fprintf(&buf, "#define REGISTER AX\n") + default: fmt.Fprintf(&buf, "#define REGISTER AX\n") } @@ -255,7 +263,7 @@ TestCases: } name := m[1] size, _ := strconv.Atoi(m[2]) - if goarch == "amd64" && size%8 == 4 { + if size%ptrSize == 4 { continue TestCases } nosplit := m[3] From 25bde37af4042d430274895abb9751cb3c786730 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:34:14 -0400 Subject: [PATCH 076/128] [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://golang.org/cl/130000044 --- src/cmd/9c/reg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/9c/reg.c b/src/cmd/9c/reg.c index 658fa3211e..38bb2e9def 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: [PATCH 077/128] [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://golang.org/cl/130000043 --- src/pkg/runtime/os_linux.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/pkg/runtime/os_linux.c b/src/pkg/runtime/os_linux.c index b9ac8c619c..1751ea83b2 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. From aa739b8d03ece2858a016863b0890792291e430b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:34:37 -0400 Subject: [PATCH 078/128] [dev.power64] cmd/9g: correct floating point comparison LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/129210043 --- src/cmd/9g/cgen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c index 6bb44f547c..86a56975ad 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; From 25d4d75376ee94f652da6727405774141bc36ad1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:34:48 -0400 Subject: [PATCH 079/128] [dev.power64] cmd/dist: tell goc2c that power64 is 64-bit system LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/125300043 --- src/cmd/dist/goc2c.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cmd/dist/goc2c.c b/src/cmd/dist/goc2c.c index 38627657ec..72cbc1be62 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 From 0bee7f3a170f1847767b75000291d3033359037c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 14:35:00 -0400 Subject: [PATCH 080/128] [dev.power64] reflect: fix test not to hang even if TrySend lies LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/124360043 --- src/pkg/reflect/all_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go index f122711731..50d223f923 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) From 6edd1c6d1a0443086734221887b3b0a38b182281 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 15:29:05 -0400 Subject: [PATCH 081/128] [dev.power64] syscall: fix power64 page size LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/128260043 --- src/pkg/syscall/syscall_linux_power64x.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/syscall/syscall_linux_power64x.go b/src/pkg/syscall/syscall_linux_power64x.go index c0ea660d4f..fd043627a2 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) From ed68c7df5529fce8d244584b064b8fae473525c4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 15:29:37 -0400 Subject: [PATCH 082/128] [dev.power64] cmd/ld, runtime: detect, fix nosplit overflows LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/121690043 --- src/cmd/ld/lib.c | 33 +++++++++++++++------------------ src/pkg/runtime/os_linux.c | 15 ++++++++++++++- src/pkg/runtime/string.go | 4 ---- test/nosplit.go | 9 +++++---- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index b4134da368..5db41f9a71 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 1751ea83b2..8aadee7215 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 c5b0917482..69874e909b 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[:]) } diff --git a/test/nosplit.go b/test/nosplit.go index de279efdd4..b5399ad38d 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -126,8 +126,9 @@ main 136 nosplit; REJECT # Calling a nosplit function from a nosplit function requires # having room for the saved caller PC and the called frame. # Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes. +# Because Power64 doesn't save LR in the leaf, it gets an extra 8 bytes. main 112 nosplit call f; f 0 nosplit -main 116 nosplit call f; f 0 nosplit; REJECT amd64 +main 116 nosplit call f; f 0 nosplit main 120 nosplit call f; f 0 nosplit; REJECT amd64 main 124 nosplit call f; f 0 nosplit; REJECT amd64 386 main 128 nosplit call f; f 0 nosplit; REJECT @@ -136,8 +137,8 @@ main 136 nosplit call f; f 0 nosplit; REJECT # Calling a splitting function from a nosplit function requires # having room for the saved caller PC of the call but also the -# saved caller PC for the call to morestack. Again the ARM works -# in less space. +# saved caller PC for the call to morestack. +# Again the ARM and Power64 work in less space. main 104 nosplit call f; f 0 call f main 108 nosplit call f; f 0 call f main 112 nosplit call f; f 0 call f; REJECT amd64 @@ -235,7 +236,7 @@ TestCases: switch goarch { case "power64", "power64le": ptrSize = 8 - fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n#define RET RETURN\n") + fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n#define RET RETURN\n") case "arm": fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n") case "amd64": From 249e8f700ac332cf9ad74064837b5c66ebb96944 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 14 Aug 2014 16:34:28 -0400 Subject: [PATCH 083/128] [dev.power64] runtime: fix RuntimeGogoBytes on power64 LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/130030043 --- src/pkg/runtime/arch_power64.h | 2 +- src/pkg/runtime/arch_power64le.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkg/runtime/arch_power64.h b/src/pkg/runtime/arch_power64.h index 1dcbbc226c..7cfb9da2fc 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 d9241da98b..3015e70aa6 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 From f9fdc887ae71ebcf26c980f2f15ace2efec94881 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Fri, 15 Aug 2014 13:15:24 +1000 Subject: [PATCH 084/128] [dev.power64] runtime: define page size on power64le systems to be 64k Fixes #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://golang.org/cl/123520043 --- src/pkg/runtime/arch_power64le.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkg/runtime/arch_power64le.h b/src/pkg/runtime/arch_power64le.h index 3015e70aa6..684ac9953b 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 }; From fd21b9f8b5fbec92d5a332b91e2eedce6a2a9ad4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 15 Aug 2014 15:22:33 -0400 Subject: [PATCH 085/128] [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://golang.org/cl/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(-) diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c index e67b0af757..716cdd108d 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 eec34f2cb7..f29cf0108f 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 68baa80d52..df030794b5 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 1e26509bd9..41988415e0 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 03622db283..b1a8943115 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 3b1c5ba8cf..99271a532b 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 49ecd6cc36..88f24408ba 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 From e445f75dbc2e6a4f807017bd4f0cc935ab02c36a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 15 Aug 2014 15:28:08 -0400 Subject: [PATCH 086/128] [dev.power64] runtime: fix usleep not to smash saved LR LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/130760043 --- src/pkg/runtime/sys_linux_power64x.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pkg/runtime/sys_linux_power64x.s b/src/pkg/runtime/sys_linux_power64x.s index 1d985d1af1..fbd59a052f 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 From d0be55a66242cd8bea2f40b7ceca4b3651d0b720 Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Fri, 15 Aug 2014 15:31:54 -0400 Subject: [PATCH 087/128] [dev.power64] liblink: fix g->panicwrap update code generation LGTM=rsc R=golang-codereviews, rsc CC=golang-codereviews https://golang.org/cl/123400043 --- src/liblink/obj9.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 3405fce477..28793676cc 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; From 04d5796b2988a20175b8cb03eb7080cf4cca2179 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 18 Aug 2014 22:24:15 -0400 Subject: [PATCH 088/128] [dev.power64] liblink: recognize add instruction as adjusting SP LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/128360043 --- src/liblink/list9.c | 2 ++ src/liblink/obj9.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/liblink/list9.c b/src/liblink/list9.c index 9700a16849..9e205b7a9e 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 28793676cc..d0c14dfb57 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; } } From 977fba763a5e45e5527e45619ed0712ca09d910d Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 22 Oct 2014 14:02:04 -0400 Subject: [PATCH 089/128] [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://golang.org/cl/158350043 --- src/runtime/{noasm_arm.go => noasm.go} | 2 ++ 1 file changed, 2 insertions(+) rename src/runtime/{noasm_arm.go => noasm.go} (96%) diff --git a/src/runtime/noasm_arm.go b/src/runtime/noasm.go similarity index 96% rename from src/runtime/noasm_arm.go rename to src/runtime/noasm.go index dd3ef82676..43c16860b2 100644 --- a/src/runtime/noasm_arm.go +++ b/src/runtime/noasm.go @@ -5,6 +5,8 @@ // Routines that are implemented in assembly in asm_{amd64,386}.s // but are implemented in Go for arm. +// +build arm power64 power64le + package runtime func cmpstring(s1, s2 string) int { From a9b9ecc9ef3a73ac0ab74b57ca7ef864f1bd9ac8 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 22 Oct 2014 16:39:31 -0400 Subject: [PATCH 090/128] [dev.power64] runtime: fix early GC of Defer objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://golang.org/cl/161960044 --- src/runtime/mgc0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c index d376c1cf69..02f7eba120 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); } From a08783f078cb9069a0d439cb5e3f2a394be86ab3 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Thu, 23 Oct 2014 08:58:10 +1100 Subject: [PATCH 091/128] [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://golang.org/cl/158360043 --- src/runtime/defs3_linux.go | 2 +- src/runtime/defs_linux_power64le.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/defs3_linux.go b/src/runtime/defs3_linux.go index eb65f9d1ed..3551a4fa90 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 41db45ca14..64f145672c 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; From 11ec8ab5cbfd715b6aafdff486156a986bdd6318 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 24 Oct 2014 11:39:01 -0400 Subject: [PATCH 092/128] [dev.power64] liblink: print line numbers in disassembly on power64 Matching other platforms. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/161320043 --- src/liblink/list9.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liblink/list9.c b/src/liblink/list9.c index 9e205b7a9e..041c6884f1 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); From 93341e8664e66b217a6911a08e1c1dac9dcf004e Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 15:10:54 -0400 Subject: [PATCH 093/128] [dev.power64] cc: 8-byte align argument size on power64 LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/163370043 --- src/cmd/cc/pgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c index 2687e05a91..54cf0c5e11 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; From 32c75a2d3d121f31ace325d48d9fcbdde58cc042 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 15:25:40 -0400 Subject: [PATCH 094/128] [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://golang.org/cl/164920044 --- src/liblink/asm9.c | 69 +++++--------------- src/liblink/obj9.c | 159 ++++++++++++++++++++++++--------------------- 2 files changed, 102 insertions(+), 126 deletions(-) diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c index 47d515e054..c5a78e53ca 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 3906181a31..fa8af5f839 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, From 6be0c8a566f6747fd18e9f5f49df37a6cd289407 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 17:19:41 -0400 Subject: [PATCH 095/128] [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://golang.org/cl/157790044 --- src/liblink/obj9.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index fa8af5f839..3db08c5450 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); From 062e354c8412e338a3a7c7c2c81d72226e431bd5 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 27 Oct 2014 17:27:03 -0400 Subject: [PATCH 096/128] [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://golang.org/cl/161450043 --- src/math/stubs_power64x.s | 2 +- src/runtime/arch_power64.go | 8 + src/runtime/arch_power64le.go | 8 + src/runtime/asm_power64x.s | 480 +++++++++++++----------------- 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, 343 insertions(+), 384 deletions(-) create mode 100644 src/runtime/arch_power64.go create mode 100644 src/runtime/arch_power64le.go diff --git a/src/math/stubs_power64x.s b/src/math/stubs_power64x.s index 0cb86144a7..36b762554a 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 0000000000..270cd7b957 --- /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 0000000000..270cd7b957 --- /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 a0511de8e6..76bf42094d 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 0(FP), R3 - MOVD 8(FP), R4 + MOVD ptr+0(FP), R3 + MOVD val+8(FP), R4 SYNC MOVD R4, 0(R3) RETURN -// void jmpdefer(fn, sp); +// void runtime·atomicor8(byte volatile*, byte); +TEXT runtime·atomicor8(SB), NOSPLIT, $0-9 + MOVD 0(FP), R3 + MOVD 8(FP), R4 + SYNC + LWAR (R3), R5 + OR R4, R5 + STWCCC R5, (R3) + BNE -3(PC) + SYNC + ISYNC + RETURN + +// void jmpdefer(fv, sp); // called from deferreturn. // 1. grab stored LR for caller // 2. sub 4 bytes to get back to BL deferreturn @@ -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 c08590ac97..e72871761d 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 d56274f2dc..1e883b72c0 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 64f145672c..93742fa346 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 4a2437c209..dfad64b6f5 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 b618f0ad7b..2b04d8319a 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 e944bcdbf8..970b6a6733 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 051815dbce..85ce847334 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 fbd59a052f..fb24d3e795 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 bdb1dcff49..1130d3c168 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 d4ca868f17..43561e2019 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 c9b0fe320c..be8518a455 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 From 1b130a08d8cb1c40f6edd5a1785272d5db8d6c16 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 28 Oct 2014 09:56:33 +1100 Subject: [PATCH 097/128] [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://golang.org/cl/161470043 --- src/runtime/defs_linux_power64le.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/runtime/defs_linux_power64le.h b/src/runtime/defs_linux_power64le.h index 64f145672c..93742fa346 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; }; From cb4f5e19704fe2c6eb2505d23d3150476a5ae8aa Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 28 Oct 2014 11:15:48 +1100 Subject: [PATCH 098/128] [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://golang.org/cl/158710043 --- src/runtime/asm_power64x.s | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index 76bf42094d..b489f6accb 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) From c2364b58cc482cf12ab675763e0857e58e92a43a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 28 Oct 2014 10:14:19 -0400 Subject: [PATCH 099/128] [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://golang.org/cl/161540043 --- src/liblink/obj9.c | 118 ++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 3db08c5450..0bae64d0b8 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; + 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 = ACMP; - p->from.type = D_REG; - p->from.reg = 0; - p->to.type = D_REG; - p->to.reg = 3; + q = appendp(ctxt, q); + q->as = ACMP; + q->from.type = D_REG; + q->from.reg = 0; + q->to.type = D_REG; + q->to.reg = 3; - p = appendp(ctxt, p); - p->as = ABEQ; - p->to.type = D_BRANCH; - p1 = p; + q = appendp(ctxt, q); + q->as = ABEQ; + q->to.type = D_BRANCH; + p1 = q; - 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 = 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; + 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; - 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 + 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 - p = appendp(ctxt, p); - p->as = ANOP; - p1->pcond = p; - p2->pcond = p; + q = appendp(ctxt, q); + q->as = ANOP; + p1->pcond = q; + p2->pcond = q; } break; From c8f50b298cdf378889cff2a1b7355f7a1cb08a0a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 28 Oct 2014 15:08:09 -0400 Subject: [PATCH 100/128] [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://golang.org/cl/160690043 --- src/cmd/9a/lex.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c index bd38493d5a..26f21f7436 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); From 87b4149b22feb9d8d52da1730b455e39436a3a8d Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 28 Oct 2014 15:57:33 -0400 Subject: [PATCH 101/128] [dev.power64] runtime: fix atomicor8 for power64x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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://golang.org/cl/165820043 --- src/runtime/asm_power64x.s | 26 ++++++++++++++++++++------ src/runtime/runtime.c | 6 ++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index b489f6accb..21220e5cb8 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 b3503fb909..d984983ce2 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"); From b55791e2008703b33883e48e72a347ba07a65486 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 28 Oct 2014 21:50:16 -0400 Subject: [PATCH 102/128] [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://golang.org/cl/159670043 --- src/cmd/5a/a.h | 3 + src/cmd/5a/a.y | 26 +- src/cmd/5a/y.tab.c | 2093 +++++++++++------------ 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 | 1152 +++++++------ src/cmd/8a/a.h | 3 + src/cmd/8a/a.y | 25 +- src/cmd/8a/y.tab.c | 1166 +++++++------ src/cmd/9a/a.h | 3 + src/cmd/9a/a.y | 26 +- src/cmd/9a/y.tab.c | 2746 +++++++++++++------------------ 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, 3643 insertions(+), 4235 deletions(-) diff --git a/src/cmd/5a/a.h b/src/cmd/5a/a.h index bb60fe7de2..df9838ad37 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 ad647606ef..d365c75343 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 a6251b8352..ace80c7e0e 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,56 +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 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" - -/* 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 # define 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; + int yyn = yypact[yystate]; - /* 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) + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else { - 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; + 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; - 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; - } - } - } +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; } - - 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_ - } - - { - YYSIZE_T 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. | @@ -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. */ +/* The look-ahead symbol. */ int yychar; - -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval 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 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 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 16: -/* Line 1787 of yacc.c */ -#line 117 "a.y" +#line 127 "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" +#line 134 "a.y" { - outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), NREG, &(yyvsp[(5) - (5)].addr)); + outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr)); } break; case 18: -/* Line 1787 of yacc.c */ -#line 131 "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" { 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 19: +#line 145 "a.y" { - outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, NREG, &(yyvsp[(4) - (4)].addr)); + outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); + } + break; + + case 20: +#line 152 "a.y" + { + outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); } break; case 21: -/* Line 1787 of yacc.c */ -#line 149 "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" - { - outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); - } - break; - - case 23: -/* Line 1787 of yacc.c */ -#line 163 "a.y" +#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 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 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 37: -/* Line 1787 of yacc.c */ -#line 262 "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" - { - 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" +#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 f11fb85c6a..f75cb22a75 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 b3fb0bb19f..e1927b6d40 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 1089d4061c..29011c7ffb 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 b69fd95b53..a698079d23 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,151 +1722,167 @@ 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 32: +#line 125 "a.y" + { + (yyval.addr2).from = nullgen; + (yyval.addr2).to = nullgen; + } + break; + + case 33: +#line 132 "a.y" + { + (yyval.addr2).from = (yyvsp[(1) - (3)].addr); + (yyval.addr2).to = (yyvsp[(3) - (3)].addr); + } + break; + case 34: -#line 129 "a.y" +#line 139 "a.y" { - (yyval.addr2).from = nullgen; - (yyval.addr2).to = nullgen; + (yyval.addr2).from = (yyvsp[(1) - (3)].addr); + (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; case 35: -#line 136 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 36: -#line 143 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 37: -#line 150 "a.y" +#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 37: +#line 158 "a.y" + { + (yyval.addr2).from = nullgen; + (yyval.addr2).to = (yyvsp[(2) - (2)].addr); + } + break; + + case 38: +#line 163 "a.y" + { + (yyval.addr2).from = nullgen; + (yyval.addr2).to = (yyvsp[(1) - (1)].addr); + } + break; + case 39: -#line 162 "a.y" +#line 170 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); @@ -1884,7 +1890,7 @@ yyreduce: break; case 40: -#line 167 "a.y" +#line 175 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); @@ -1892,31 +1898,15 @@ yyreduce: break; case 41: -#line 174 "a.y" - { - (yyval.addr2).from = nullgen; - (yyval.addr2).to = (yyvsp[(2) - (2)].addr); - } - break; - - case 42: -#line 179 "a.y" - { - (yyval.addr2).from = nullgen; - (yyval.addr2).to = (yyvsp[(1) - (1)].addr); - } - break; - - case 43: -#line 184 "a.y" +#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 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 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 45: -#line 199 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 46: -#line 204 "a.y" - { - (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" +#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,28 +2109,44 @@ 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 76: +#line 374 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = (yyvsp[(1) - (1)].lval); + } + break; + + case 77: +#line 379 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = (yyvsp[(1) - (1)].lval); + } + break; + + case 78: +#line 384 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = (yyvsp[(1) - (1)].lval); + } + break; + case 79: -#line 381 "a.y" +#line 389 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); @@ -2146,15 +2154,15 @@ yyreduce: break; case 80: -#line 386 "a.y" +#line 394 "a.y" { (yyval.addr) = nullgen; - (yyval.addr).type = (yyvsp[(1) - (1)].lval); + (yyval.addr).type = D_SP; } break; case 81: -#line 391 "a.y" +#line 399 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); @@ -2162,7 +2170,7 @@ yyreduce: break; case 82: -#line 396 "a.y" +#line 404 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); @@ -2170,49 +2178,25 @@ yyreduce: break; case 83: -#line 401 "a.y" +#line 410 "a.y" { (yyval.addr) = nullgen; - (yyval.addr).type = D_SP; + (yyval.addr).type = D_CONST; + (yyval.addr).offset = (yyvsp[(2) - (2)].lval); } break; case 84: -#line 406 "a.y" +#line 418 "a.y" { (yyval.addr) = nullgen; - (yyval.addr).type = (yyvsp[(1) - (1)].lval); + (yyval.addr).type = D_CONST; + (yyval.addr).offset = (yyvsp[(2) - (2)].lval); } break; case 85: -#line 411 "a.y" - { - (yyval.addr) = nullgen; - (yyval.addr).type = (yyvsp[(1) - (1)].lval); - } - break; - - case 86: -#line 417 "a.y" - { - (yyval.addr) = nullgen; - (yyval.addr).type = D_CONST; - (yyval.addr).offset = (yyvsp[(2) - (2)].lval); - } - break; - - case 87: -#line 425 "a.y" - { - (yyval.addr) = nullgen; - (yyval.addr).type = D_CONST; - (yyval.addr).offset = (yyvsp[(2) - (2)].lval); - } - break; - - case 88: -#line 431 "a.y" +#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 adc388ca9f..a1aca07aea 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 6bcf1313bf..c810d38577 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 85279c21f9..f284d8ea2e 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,146 +1720,162 @@ 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 31: +#line 127 "a.y" + { + (yyval.addr2).from = nullgen; + (yyval.addr2).to = nullgen; + } + break; + + case 32: +#line 134 "a.y" + { + (yyval.addr2).from = (yyvsp[(1) - (3)].addr); + (yyval.addr2).to = (yyvsp[(3) - (3)].addr); + } + break; + case 33: -#line 131 "a.y" +#line 141 "a.y" { - (yyval.addr2).from = nullgen; - (yyval.addr2).to = nullgen; + (yyval.addr2).from = (yyvsp[(1) - (3)].addr); + (yyval.addr2).to = (yyvsp[(3) - (3)].addr); } break; case 34: -#line 138 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 35: -#line 145 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 36: -#line 152 "a.y" +#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 36: +#line 160 "a.y" + { + (yyval.addr2).from = nullgen; + (yyval.addr2).to = (yyvsp[(2) - (2)].addr); + } + break; + + case 37: +#line 165 "a.y" + { + (yyval.addr2).from = nullgen; + (yyval.addr2).to = (yyvsp[(1) - (1)].addr); + } + break; + case 38: -#line 164 "a.y" +#line 172 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(2) - (2)].addr); @@ -1875,7 +1883,7 @@ yyreduce: break; case 39: -#line 169 "a.y" +#line 177 "a.y" { (yyval.addr2).from = nullgen; (yyval.addr2).to = (yyvsp[(1) - (1)].addr); @@ -1883,31 +1891,15 @@ yyreduce: break; case 40: -#line 176 "a.y" - { - (yyval.addr2).from = nullgen; - (yyval.addr2).to = (yyvsp[(2) - (2)].addr); - } - break; - - case 41: -#line 181 "a.y" - { - (yyval.addr2).from = nullgen; - (yyval.addr2).to = (yyvsp[(1) - (1)].addr); - } - break; - - case 42: -#line 186 "a.y" +#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 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 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 44: -#line 201 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 45: -#line 206 "a.y" - { - (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" +#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 55: +#line 275 "a.y" + { + (yyval.addr2).from = (yyvsp[(1) - (3)].addr); + (yyval.addr2).to = (yyvsp[(3) - (3)].addr); + } + break; + + case 56: +#line 282 "a.y" + { + (yyval.addr2).from = (yyvsp[(1) - (3)].addr); + (yyval.addr2).to = (yyvsp[(3) - (3)].addr); + } + break; + case 57: -#line 277 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 58: -#line 284 "a.y" - { - (yyval.addr2).from = (yyvsp[(1) - (3)].addr); - (yyval.addr2).to = (yyvsp[(3) - (3)].addr); - } - break; - - case 59: -#line 289 "a.y" +#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,28 +2096,44 @@ 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 75: +#line 373 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = (yyvsp[(1) - (1)].lval); + } + break; + + case 76: +#line 378 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = (yyvsp[(1) - (1)].lval); + } + break; + + case 77: +#line 383 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = (yyvsp[(1) - (1)].lval); + } + break; + case 78: -#line 380 "a.y" +#line 388 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); @@ -2131,15 +2141,15 @@ yyreduce: break; case 79: -#line 385 "a.y" +#line 393 "a.y" { (yyval.addr) = nullgen; - (yyval.addr).type = (yyvsp[(1) - (1)].lval); + (yyval.addr).type = D_SP; } break; case 80: -#line 390 "a.y" +#line 398 "a.y" { (yyval.addr) = nullgen; (yyval.addr).type = (yyvsp[(1) - (1)].lval); @@ -2147,31 +2157,7 @@ yyreduce: break; case 81: -#line 395 "a.y" - { - (yyval.addr) = nullgen; - (yyval.addr).type = (yyvsp[(1) - (1)].lval); - } - break; - - case 82: -#line 400 "a.y" - { - (yyval.addr) = nullgen; - (yyval.addr).type = D_SP; - } - break; - - case 83: #line 405 "a.y" - { - (yyval.addr) = nullgen; - (yyval.addr).type = (yyvsp[(1) - (1)].lval); - } - break; - - case 84: -#line 412 "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 629543f13f..7a01fc9479 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 41776fd3c3..b366146156 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 e81db9924c..6025a2402c 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, 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, - 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, + 160, 159, 0, 83, 160, 159, 159, 112, 107, 117, + 159, 159, 0, 0, 0, 124, 0, 0, 8, 0, + 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 10, 170, 169, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 173, 0, 146, 145, + 149, 171, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, + 0, 0, 0, 0, 0, 0, 126, 0, 68, 69, + 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, + 0, 0, 0, 0, 0, 160, 82, 0, 110, 111, + 108, 109, 114, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 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; + int yyn = yypact[yystate]; - /* 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) + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else { - 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; + 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; - 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; - } - } +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; } - - 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. | @@ -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,630 +1945,492 @@ 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: - -/* Line 1806 of yacc.c */ -#line 127 "a.y" + case 18: +#line 130 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 20: - -/* Line 1806 of yacc.c */ + case 19: #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 */ + case 20: #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 */ + case 21: #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 */ + case 22: #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 */ + case 23: #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" + case 24: +#line 157 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 26: - -/* Line 1806 of yacc.c */ + case 25: #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 */ + case 26: #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 */ + case 27: #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" + case 28: +#line 176 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 30: - -/* Line 1806 of yacc.c */ + case 29: #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" + case 30: +#line 187 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 32: - -/* Line 1806 of yacc.c */ + case 31: #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 */ + case 32: #line 195 "a.y" + { + outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); + } + break; + + case 33: +#line 199 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 34: - -/* Line 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 */ + case 35: #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" + case 36: +#line 214 "a.y" { outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); } break; - case 39: + case 37: +#line 218 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 38: #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" + case 39: +#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 41: - -/* Line 1806 of yacc.c */ + case 40: #line 236 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 42: - -/* Line 1806 of yacc.c */ + case 41: #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: + case 42: +#line 244 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 43: #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 */ + case 44: #line 252 "a.y" + { + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + } + break; + + case 45: +#line 256 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 46: - -/* Line 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" - { - 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 */ + case 51: #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" + case 52: +#line 287 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 55: + case 53: +#line 294 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 54: #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" + case 55: +#line 305 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr)); } break; - case 58: - -/* Line 1806 of yacc.c */ -#line 313 "a.y" + case 56: +#line 309 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; - case 59: + case 57: +#line 317 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 58: #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)); - } - 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: + case 68: +#line 366 "a.y" + { + outcode((yyvsp[(1) - (3)].lval), &nullgen, NREG, &(yyvsp[(3) - (3)].addr)); + } + break; -/* 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)); - } - 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: + case 71: +#line 378 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* 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)); - } - 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: + case 74: +#line 390 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr)); + } + break; -/* 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 77: +#line 402 "a.y" + { + Addr g; + g = nullgen; + g.type = D_CONST; + g.offset = (yyvsp[(2) - (6)].lval); + outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + } + break; + + case 78: +#line 410 "a.y" + { + Addr g; + g = nullgen; + g.type = D_CONST; + g.offset = (yyvsp[(2) - (6)].lval); + outcode((yyvsp[(1) - (6)].lval), &g, (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + } + break; + case 79: - -/* Line 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" +#line 418 "a.y" { Addr g; g = nullgen; @@ -2629,325 +2440,253 @@ yyreduce: } break; - case 82: + case 80: +#line 429 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen); + } + break; -/* Line 1806 of yacc.c */ + case 81: #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 */ + case 82: #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" + case 83: +#line 441 "a.y" { outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); } break; - case 86: + case 84: +#line 448 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 85: #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 */ + case 86: #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" + 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: + case 88: +#line 464 "a.y" + { + outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); + } + break; -/* Line 1806 of yacc.c */ + case 89: #line 468 "a.y" + { + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr)); + } + break; + + case 90: +#line 475 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 91: - -/* Line 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 */ + 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: - -/* Line 1806 of yacc.c */ -#line 491 "a.y" + case 94: +#line 494 "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 */ + case 95: #line 498 "a.y" { outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; - case 97: - -/* Line 1806 of yacc.c */ + case 96: #line 502 "a.y" { outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; - case 98: - -/* Line 1806 of yacc.c */ + case 97: #line 506 "a.y" { outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr)); } break; - case 99: - -/* Line 1806 of yacc.c */ -#line 510 "a.y" + case 98: +#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 100: - -/* Line 1806 of yacc.c */ + case 99: #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" + case 100: +#line 525 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; - case 102: - -/* Line 1806 of yacc.c */ + case 101: #line 529 "a.y" + { + outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), NREG, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr)); + } + break; + + case 102: +#line 533 "a.y" { outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), NREG, &(yyvsp[(4) - (4)].addr)); } break; case 103: - -/* Line 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)); - } - 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" + case 107: +#line 556 "a.y" { outcode((yyvsp[(1) - (2)].lval), &nullgen, NREG, &nullgen); } break; - case 110: + case 108: +#line 560 "a.y" + { + outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen); + } + break; -/* 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: + case 113: +#line 583 "a.y" + { + outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), NREG, &nullgen); + } + break; -/* Line 1806 of yacc.c */ + case 114: #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" + 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: + case 121: +#line 643 "a.y" + { + outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); + } + break; -/* Line 1806 of yacc.c */ -#line 644 "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 123: +#line 651 "a.y" { outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr)); } break; case 124: - -/* Line 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" +#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,21 +2869,17 @@ yyreduce: } break; - case 142: + case 139: +#line 755 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = D_FREG; + (yyval.addr).reg = (yyvsp[(1) - (1)].lval); + } + break; -/* Line 1806 of yacc.c */ + case 140: #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; @@ -3199,21 +2887,17 @@ yyreduce: } break; - case 144: + case 141: +#line 769 "a.y" + { + (yyval.addr) = nullgen; + (yyval.addr).type = D_CREG; + (yyval.addr).reg = (yyvsp[(1) - (1)].lval); + } + break; -/* Line 1806 of yacc.c */ + case 142: #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; @@ -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 f1b4a72236..e6b93a2ece 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 e24db1bc0b..f586aaa20e 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 20d3c47c94..d0b3969bda 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 709834180e..7a0fdfa73a 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 28875bc55a..de3ef3a237 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 621d13187a..8942b11acb 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 21220e5cb8..f77658032e 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 1520aea2e0..3f20b69c82 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 94a2c7f236..ec24f1db23 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 b4b671f773..50f327b4ed 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 bdea28c7c0..15b18ff8f8 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 a961c71a83..3bf8b1d411 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 bd397d72a7..8a8928e066 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 161eaec19d..71ece9ecbf 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 2c40fc433b..66d03c27da 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 33b91e872f..d8d86ffadf 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 bd285f3998..033a036427 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 47985f31f5..16cd721d9b 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 c30c2a8933..06a0dc5dd7 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 d354ab4837..432deadf44 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 5cda7768ae..b1ae5eceec 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 0ebdab6ee2..3981893b01 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 932fe9dd24..13fb5bdc93 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 e6190ce684..8b95f6d6c1 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 From 097362fd2e01735b25b79c71ba6005cd38f81da0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 10:45:41 -0400 Subject: [PATCH 103/128] [dev.power64] runtime: match argument/return type signedness in power64x assembly Previously, the power64x runtime assembly was sloppy about using sign-extending versus zero-extending moves of arguments and return values. I think all of the cases that actually mattered have been fixed in recent CLs; this CL fixes up the few remaining mismatches. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/162480043 --- src/runtime/asm_power64x.s | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index f77658032e..b6eac96110 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -299,7 +299,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0 // Note: can't just "BR NAME(SB)" - bad inlining results. TEXT ·reflectcall(SB), NOSPLIT, $-8-24 - MOVW argsize+16(FP), R3 + MOVWZ argsize+16(FP), R3 DISPATCH(runtime·call16, 16) DISPATCH(runtime·call32, 32) DISPATCH(runtime·call64, 64) @@ -336,7 +336,7 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ NO_LOCAL_POINTERS; \ /* copy arguments to stack */ \ MOVD argptr+8(FP), R3; \ - MOVW argsize+16(FP), R4; \ + MOVWZ argsize+16(FP), R4; \ MOVD R1, R5; \ ADD $(8-1), R5; \ SUB $1, R3; \ @@ -354,8 +354,8 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ BL (CTR); \ /* copy return values back */ \ MOVD argptr+8(FP), R3; \ - MOVW argsize+16(FP), R4; \ - MOVW retoffset+20(FP), R6; \ + MOVWZ argsize+16(FP), R4; \ + MOVWZ retoffset+20(FP), R6; \ MOVD R1, R5; \ ADD R6, R5; \ ADD R6, R3; \ @@ -398,7 +398,7 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) -// bool cas(int32 *val, int32 old, int32 new) +// bool cas(uint32 *val, uint32 old, uint32 new) // Atomically: // if(*val == old){ // *val = new; @@ -407,8 +407,8 @@ CALLFN(·call1073741824, 1073741824) // return 0; TEXT runtime·cas(SB), NOSPLIT, $0-17 MOVD p+0(FP), R3 - MOVW old+8(FP), R4 - MOVW new+12(FP), R5 + MOVWZ old+8(FP), R4 + MOVWZ new+12(FP), R5 cas_again: SYNC LWAR (R3), R6 From 36d417c0e380b8ea762812b415796cf4b0af72de Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 11:17:26 -0400 Subject: [PATCH 104/128] [dev.power64] runtime: test CAS on large unsigned 32-bit numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a test to runtime·check to ensure CAS of large unsigned 32-bit numbers does not accidentally sign-extend its arguments. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/162490044 --- src/runtime/runtime.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index f19f8e4be3..a684142848 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -226,6 +226,12 @@ runtime·check(void) if(z != 4) runtime·throw("cas4"); + z = 0xffffffff; + if(!runtime·cas(&z, 0xffffffff, 0xfffffffe)) + runtime·throw("cas5"); + if(z != 0xfffffffe) + runtime·throw("cas6"); + k = (byte*)0xfedcb123; if(sizeof(void*) == 8) k = (byte*)((uintptr)k<<10); From 4cf28a11e3807f2f34785d6d4e6aac0821bac654 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 12:08:21 -0400 Subject: [PATCH 105/128] [dev.power64] runtime: fix out-of-date comment in panic LGTM=bradfitz R=rsc, bradfitz CC=golang-codereviews https://golang.org/cl/162500043 --- src/runtime/panic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/panic.c b/src/runtime/panic.c index 46683b2b0c..b19fdd0e18 100644 --- a/src/runtime/panic.c +++ b/src/runtime/panic.c @@ -69,7 +69,7 @@ runtime·recovery_m(G *gp) // each call to deferproc. // (The pc we're returning to does pop pop // before it tests the return value.) - // On the arm there are 2 saved LRs mixed in too. + // On the arm and power there are 2 saved LRs mixed in too. if(thechar == '5' || thechar == '9') gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr); else From 8a09639ae8b02317d990ef8e8c5929baf96659cd Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 15:58:30 -0400 Subject: [PATCH 106/128] [dev.power64] runtime: make asm_power64x.s go vet-clean No real problems found. Just lots of argument names that didn't quite match up. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/169790043 --- src/runtime/asm_power64x.s | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index b6eac96110..e1f8a84aff 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -86,7 +86,7 @@ TEXT runtime·reginit(SB),NOSPLIT,$-8-0 // void gosave(Gobuf*) // save state in Gobuf; setjmp TEXT runtime·gosave(SB), NOSPLIT, $-8-8 - MOVD gobuf+0(FP), R3 + MOVD buf+0(FP), R3 MOVD R1, gobuf_sp(R3) MOVD LR, R31 MOVD R31, gobuf_pc(R3) @@ -99,7 +99,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8 // void gogo(Gobuf*) // restore state from Gobuf; longjmp TEXT runtime·gogo(SB), NOSPLIT, $-8-8 - MOVD gobuf+0(FP), R5 + MOVD buf+0(FP), R5 MOVD gobuf_g(R5), g // make sure g is not nil MOVD 0(g), R4 MOVD gobuf_sp(R5), R1 @@ -299,7 +299,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0 // Note: can't just "BR NAME(SB)" - bad inlining results. TEXT ·reflectcall(SB), NOSPLIT, $-8-24 - MOVWZ argsize+16(FP), R3 + MOVWZ n+16(FP), R3 DISPATCH(runtime·call16, 16) DISPATCH(runtime·call32, 32) DISPATCH(runtime·call64, 64) @@ -335,8 +335,8 @@ TEXT ·reflectcall(SB), NOSPLIT, $-8-24 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ NO_LOCAL_POINTERS; \ /* copy arguments to stack */ \ - MOVD argptr+8(FP), R3; \ - MOVWZ argsize+16(FP), R4; \ + MOVD arg+8(FP), R3; \ + MOVWZ n+16(FP), R4; \ MOVD R1, R5; \ ADD $(8-1), R5; \ SUB $1, R3; \ @@ -353,8 +353,8 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ PCDATA $PCDATA_StackMapIndex, $0; \ BL (CTR); \ /* copy return values back */ \ - MOVD argptr+8(FP), R3; \ - MOVWZ argsize+16(FP), R4; \ + MOVD arg+8(FP), R3; \ + MOVWZ n+16(FP), R4; \ MOVWZ retoffset+20(FP), R6; \ MOVD R1, R5; \ ADD R6, R5; \ @@ -398,7 +398,7 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) -// bool cas(uint32 *val, uint32 old, uint32 new) +// bool cas(uint32 *ptr, uint32 old, uint32 new) // Atomically: // if(*val == old){ // *val = new; @@ -406,7 +406,7 @@ CALLFN(·call1073741824, 1073741824) // } else // return 0; TEXT runtime·cas(SB), NOSPLIT, $0-17 - MOVD p+0(FP), R3 + MOVD ptr+0(FP), R3 MOVWZ old+8(FP), R4 MOVWZ new+12(FP), R5 cas_again: @@ -425,7 +425,7 @@ cas_fail: MOVD $0, R3 BR -5(PC) -// bool runtime·cas64(uint64 *val, uint64 old, uint64 new) +// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new) // Atomically: // if(*val == *old){ // *val = new; @@ -434,7 +434,7 @@ cas_fail: // return 0; // } TEXT runtime·cas64(SB), NOSPLIT, $0-25 - MOVD p+0(FP), R3 + MOVD ptr+0(FP), R3 MOVD old+8(FP), R4 MOVD new+16(FP), R5 cas64_again: @@ -475,12 +475,12 @@ TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16 TEXT runtime·casp(SB), NOSPLIT, $0-25 BR runtime·cas64(SB) -// uint32 xadd(uint32 volatile *val, int32 delta) +// uint32 xadd(uint32 volatile *ptr, int32 delta) // Atomically: // *val += delta; // return *val; TEXT runtime·xadd(SB), NOSPLIT, $0-20 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVW delta+8(FP), R5 SYNC LWAR (R4), R3 @@ -493,7 +493,7 @@ TEXT runtime·xadd(SB), NOSPLIT, $0-20 RETURN TEXT runtime·xadd64(SB), NOSPLIT, $0-24 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVD delta+8(FP), R5 SYNC LDAR (R4), R3 @@ -506,7 +506,7 @@ TEXT runtime·xadd64(SB), NOSPLIT, $0-24 RETURN TEXT runtime·xchg(SB), NOSPLIT, $0-20 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVW new+8(FP), R5 SYNC LWAR (R4), R3 @@ -518,7 +518,7 @@ TEXT runtime·xchg(SB), NOSPLIT, $0-20 RETURN TEXT runtime·xchg64(SB), NOSPLIT, $0-24 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVD new+8(FP), R5 SYNC LDAR (R4), R3 @@ -651,7 +651,7 @@ TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16 RETURN TEXT runtime·getcallersp(SB),NOSPLIT,$0-16 - MOVD sp+0(FP), R3 + MOVD argp+0(FP), R3 SUB $8, R3 MOVD R3, ret+8(FP) RETURN @@ -695,22 +695,23 @@ TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0 TEXT runtime·memeq(SB),NOSPLIT,$-8-25 MOVD a+0(FP), R3 MOVD b+8(FP), R4 - MOVD count+16(FP), R5 + MOVD size+16(FP), R5 SUB $1, R3 SUB $1, R4 ADD R3, R5, R8 loop: CMP R3, R8 - BNE 4(PC) + BNE test MOVD $1, R3 MOVB R3, ret+24(FP) RETURN +test: MOVBZU 1(R3), R6 MOVBZU 1(R4), R7 CMP R6, R7 BEQ loop - MOVB R0, ret+24(FP) + MOVB $0, ret+24(FP) RETURN // eqstring tests whether two strings are equal. From c24156bafe24a82ca4c182f289b1bff121ea72e0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 16:44:42 -0400 Subject: [PATCH 107/128] [dev.power64] runtime: fix a syntax error that slipped in to asm_power64x.s Apparently I had already moved on to fixing another problem when I submitted CL 169790043. LGTM=dave R=rsc, dave CC=golang-codereviews https://golang.org/cl/165210043 --- src/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index e1f8a84aff..ab2db061c2 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -711,7 +711,7 @@ test: CMP R6, R7 BEQ loop - MOVB $0, ret+24(FP) + MOVB R0, ret+24(FP) RETURN // eqstring tests whether two strings are equal. From 6e86003651be7feb6da46360d6c411ff1c29b7f5 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 11:08:27 -0400 Subject: [PATCH 108/128] [dev.power64] 9g: fix under-zeroing in clearfat All three cases of clearfat were wrong on power64x. The cases that handle 1032 bytes and up and 32 bytes and up both use MOVDU (one directly generated in a loop and the other via duffzero), which leaves the pointer register pointing at the *last written* address. The generated code was not accounting for this, so the byte fill loop was re-zeroing the last zeroed dword, rather than the bytes following the last zeroed dword. Fix this by simply adding an additional 8 byte offset to the byte zeroing loop. The case that handled under 32 bytes was also wrong. It didn't update the pointer register at all, so the byte zeroing loop was simply re-zeroing the beginning of region. Again, the fix is to add an offset to the byte zeroing loop to account for this. LGTM=dave, bradfitz R=rsc, dave, bradfitz CC=golang-codereviews https://golang.org/cl/168870043 --- src/cmd/9g/ggen.c | 20 +++++++---- src/runtime/asm_power64x.s | 2 +- test/clearfat.go | 68 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 test/clearfat.go diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c index c41d8eb414..7d9cf5050d 100644 --- a/src/cmd/9g/ggen.c +++ b/src/cmd/9g/ggen.c @@ -900,7 +900,7 @@ ret: void clearfat(Node *nl) { - uint64 w, c, q, t; + uint64 w, c, q, t, boff; Node dst, end, r0, *f; Prog *p, *pl; @@ -944,6 +944,8 @@ clearfat(Node *nl) patch(gbranch(ABNE, T, 0), pl); regfree(&end); + // The loop leaves R3 on the last zeroed dword + boff = 8; } else if(q >= 4) { p = gins(ASUB, N, &dst); p->from.type = D_CONST; @@ -953,17 +955,21 @@ clearfat(Node *nl) afunclit(&p->to, f); // 4 and 128 = magic constants: see ../../runtime/asm_power64x.s p->to.offset = 4*(128-q); - } else - for(t = 0; t < q; t++) { - p = gins(AMOVD, &r0, &dst); - p->to.type = D_OREG; - p->to.offset = 8*t; + // duffzero leaves R3 on the last zeroed dword + boff = 8; + } else { + for(t = 0; t < q; t++) { + p = gins(AMOVD, &r0, &dst); + p->to.type = D_OREG; + p->to.offset = 8*t; + } + boff = 8*q; } for(t = 0; t < c; t++) { p = gins(AMOVB, &r0, &dst); p->to.type = D_OREG; - p->to.offset = t; + p->to.offset = t+boff; } reg[REGRT1]--; } diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index ab2db061c2..2ad3e56e94 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -829,7 +829,7 @@ notfound: // 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. +// On return, R3 points to the last zeroed dword. TEXT runtime·duffzero(SB), NOSPLIT, $-8-0 MOVDU R0, 8(R3) MOVDU R0, 8(R3) diff --git a/test/clearfat.go b/test/clearfat.go new file mode 100644 index 0000000000..45d539306e --- /dev/null +++ b/test/clearfat.go @@ -0,0 +1,68 @@ +// runoutput + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check that {5,6,8,9}g/ggen.c:clearfat is zeroing the entire object. + +package main + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +const ntest = 1100 + +func main() { + var decls, calls bytes.Buffer + + for i := 1; i <= ntest; i++ { + s := strconv.Itoa(i) + decls.WriteString(strings.Replace(decl, "$", s, -1)) + calls.WriteString(strings.Replace("poison$()\n\tclearfat$()\n\t", "$", s, -1)) + } + + program = strings.Replace(program, "$DECLS", decls.String(), 1) + program = strings.Replace(program, "$CALLS", calls.String(), 1) + fmt.Print(program) +} + +var program = `package main + +var count int + +$DECLS + +func main() { + $CALLS + if count != 0 { + println("failed", count, "case(s)") + } +} +` + +const decl = ` +func poison$() { + // Grow and poison the stack space that will be used by clearfat$ + var t [2*$]byte + for i := range t { + t[i] = 0xff + } +} + +func clearfat$() { + var t [$]byte + + for _, x := range t { + if x != 0 { +// println("clearfat$: index", i, "expected 0, got", x) + count++ + break + } + } +} +` From 40a5b3ecb1578a68b0423b8ef4eaebd5fb4c7869 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 13:39:36 -0400 Subject: [PATCH 109/128] [dev.power64] runtime: fix fastrand1 on power64x fastrand1 depends on testing the high bit of its uint32 state. For efficiency, all of the architectures implement this as a sign bit test. However, on power64, fastrand1 was using a 64-bit sign test on the zero-extended 32-bit state. This always failed, causing fastrand1 to have very short periods and often decay to 0 and get stuck. Fix this by using a 32-bit signed compare instead of a 64-bit compare. This fixes various tests for the randomization of select of map iteration. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/166990043 --- src/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index 2ad3e56e94..713cc5f549 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -965,7 +965,7 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4 MOVD g_m(g), R4 MOVWZ m_fastrand(R4), R3 ADD R3, R3 - CMP R3, $0 + CMPW R3, $0 BGE 2(PC) XOR $0x88888eef, R3 MOVW R3, m_fastrand(R4) From 700ab16daf01e77f77faca242e148ad2100b6627 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 15:29:03 -0400 Subject: [PATCH 110/128] [dev.power64] reflect: fix asm on power64x reflect/asm_power64x.s was missing changes made to other platforms for stack maps. This CL ports those changes. With this fix, the reflect test passes on power64x. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/170870043 --- src/reflect/asm_power64x.s | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/reflect/asm_power64x.s b/src/reflect/asm_power64x.s index e430cdf04c..4720638242 100644 --- a/src/reflect/asm_power64x.s +++ b/src/reflect/asm_power64x.s @@ -5,12 +5,14 @@ // +build power64 power64le #include "textflag.h" +#include "funcdata.h" // makeFuncStub is the code half of the function returned by MakeFunc. // See the comment on the declaration of makeFuncStub in makefunc.go // for more details. -// No argsize here, gc generates argsize info at call site. +// No arg size here, runtime pulls arg map out of the func value. TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16 + NO_LOCAL_POINTERS MOVD R11, 8(R1) MOVD $argframe+0(FP), R3 MOVD R3, 16(R1) @@ -20,8 +22,9 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16 // 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. +// No arg size here; runtime pulls arg map out of the func value. TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16 + NO_LOCAL_POINTERS MOVD R11, 8(R1) MOVD $argframe+0(FP), R3 MOVD R3, 16(R1) From e1db508ffdcfbb78a73c6df7e3d0a6b0cb6f001a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 16:58:12 -0400 Subject: [PATCH 111/128] [dev.power64] runtime: fix gcinfo_test on power64x The GC info masks for slices and strings were changed in commit caab29a25f68, but the reference masks used by gcinfo_test for power64x hadn't caught up. Now they're identical to amd64, so this CL fixes this test by combining the reference masks for these platforms. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/162620044 --- src/runtime/gcinfo_test.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go index 7d432983b1..2c6d4d662f 100644 --- a/src/runtime/gcinfo_test.go +++ b/src/runtime/gcinfo_test.go @@ -137,7 +137,7 @@ func infoBigStruct() []byte { BitsScalar, BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64 BitsPointer, BitsDead, // i string } - case "amd64": + case "amd64", "power64", "power64le": return []byte{ BitsPointer, // q *int BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte @@ -153,12 +153,6 @@ func infoBigStruct() []byte { BitsScalar, BitsScalar, BitsDead, BitsScalar, BitsScalar, // t int; y uint16; u uint64 BitsPointer, BitsDead, // i string } - case "power64", "power64le": - return []byte{ - BitsPointer, BitsScalar, BitsScalar, BitsScalar, - BitsMultiWord, BitsSlice, BitsScalar, BitsScalar, - BitsScalar, BitsScalar, BitsMultiWord, BitsString, - } default: panic("unknown arch") } From 84f7ac98f7f187ce851b87d020bdc8efe6a15f1f Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Sun, 2 Nov 2014 11:23:41 +1100 Subject: [PATCH 112/128] [dev.power64] cmd/objdump: disable tests on power64/power64le LGTM=rsc, austin R=austin, rsc, bradfitz CC=golang-codereviews https://golang.org/cl/164300043 --- src/cmd/objdump/objdump_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index 0a2d2565a7..41f51ebf20 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -49,6 +49,10 @@ func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno stri case "android", "nacl": t.Skipf("skipping on %s", runtime.GOOS) } + switch runtime.GOARCH { + case "power64", "power64le": + t.Skipf("skipping on %s, issue 9039", runtime.GOARCH) + } cmd := exec.Command(exe, os.Args[0], startaddr, endaddr) out, err := cmd.CombinedOutput() @@ -199,6 +203,10 @@ func testDisasm(t *testing.T, flags ...string) { } func TestDisasm(t *testing.T) { + switch runtime.GOARCH { + case "power64", "power64le": + t.Skipf("skipping on %s, issue 9039", runtime.GOARCH) + } testDisasm(t) } @@ -207,5 +215,9 @@ func TestDisasmExtld(t *testing.T) { case "plan9", "windows": t.Skipf("skipping on %s", runtime.GOOS) } + switch runtime.GOARCH { + case "power64", "power64le": + t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH) + } testDisasm(t, "-ldflags=-linkmode=external") } From 810019286fdb8ad6b60096f2b0e2dcf0bc900c3a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 3 Nov 2014 15:48:51 -0500 Subject: [PATCH 113/128] [dev.power64] 9g: fix nilopt Previously, nilopt was disabled on power64x because it threw away "seemly random segments of code." Indeed, excise on power64x failed to preserve the link field, so it excised not only the requested instruction but all following instructions in the function. Fix excise to retain the link field while otherwise zeroing the instruction. This makes nilopt safe on power64x. It still fails nilptr3.go's tests for removal of repeated nil checks because those depend on also optimizing away repeated loads, which doesn't currently happen on power64x. LGTM=dave, rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/168120043 --- src/cmd/9g/peep.c | 4 +++- src/cmd/gc/popt.c | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cmd/9g/peep.c b/src/cmd/9g/peep.c index 5721d7b04f..ec314d6338 100644 --- a/src/cmd/9g/peep.c +++ b/src/cmd/9g/peep.c @@ -44,13 +44,15 @@ peep(Prog *p) void excise(Flow *r) { - Prog *p; + Prog *p, *l; p = r->prog; if(debug['P'] && debug['v']) print("%P ===delete===\n", p); + l = p->link; *p = zprog; p->as = ANOP; + p->link = l; ostats.ndelmov++; } diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c index 6e6db88ef8..993bb24821 100644 --- a/src/cmd/gc/popt.c +++ b/src/cmd/gc/popt.c @@ -847,10 +847,6 @@ 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; From 473bfae5ae3c4adccebc14bca40d0fb0a2ff09ab Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 3 Nov 2014 17:24:13 -0500 Subject: [PATCH 114/128] [dev.power64] liblink: fix printing of branch targets Print PC stored in target Prog* of branch instructions when available instead of the offset stored in the branch instruction. The offset tends to be wrong after code transformations, so previously this led to confusing listings. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/168980043 --- src/liblink/list9.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/liblink/list9.c b/src/liblink/list9.c index 041c6884f1..c9190d8940 100644 --- a/src/liblink/list9.c +++ b/src/liblink/list9.c @@ -259,11 +259,12 @@ Dconv(Fmt *fp) sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v); else sprint(str, "%.5lux(BRANCH)", v); - } else - if(a->sym != nil) - sprint(str, "%s+%lld(APC)", a->sym->name, a->offset); - else - sprint(str, "%lld(APC)", a->offset); + } else if(a->u.branch != nil) + sprint(str, "%lld", a->u.branch->pc); + else if(a->sym != nil) + sprint(str, "%s+%lld(APC)", a->sym->name, a->offset); + else + sprint(str, "%lld(APC)", a->offset); break; case D_FCONST: From d10a115ef9511b9be8b1f7b0fb5a292a9917aab9 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 3 Nov 2014 17:25:03 -0500 Subject: [PATCH 115/128] [dev.power64] test: disable nilptr3 test on power64x The remaining failures in this test are because of incomplete optimization support on power64x. Tracked in issue 9058. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/168130043 --- test/nilptr3.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/nilptr3.go b/test/nilptr3.go index 2757daef0b..9d65e1e91b 100644 --- a/test/nilptr3.go +++ b/test/nilptr3.go @@ -1,4 +1,6 @@ // errorcheck -0 -d=nil +// Fails on power64x because of incomplete optimization. See issue 9058. +// +build !power64,!power64le // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style From a5e1e1599c427013cbbaec5716da4fefbd67a4d1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 3 Nov 2014 17:25:36 -0500 Subject: [PATCH 116/128] [dev.power64] test: "fix" live.go test on power64x On power64x, this one line in live.go reports that t is live because of missing optimization passes. This isn't what this test is trying to test, so shuffle bad40 so that it still accomplishes the intent of the test without also depending on optimization. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/167110043 --- test/live.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/live.go b/test/live.go index f15bb74ba1..f69d0a4c1e 100644 --- a/test/live.go +++ b/test/live.go @@ -614,8 +614,8 @@ func newT40() *T40 { func bad40() { t := newT40() - println() _ = t + println() } func good40() { From fa32e922d54c2a2d4b9bb97009ac6e3c84af3dd6 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 4 Nov 2014 16:34:56 -0500 Subject: [PATCH 117/128] [dev.power64] gc: convert Bits to a uint64 array So far all of our architectures have had at most 32 registers, so we've been able to use entry 0 in the Bits uint32 array directly as a register mask. Power64 has 64 registers, so this converts Bits to a uint64 array so we can continue to use entry 0 directly as a register mask on Power64. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/169060043 --- src/cmd/5g/opt.h | 14 +++++++------- src/cmd/5g/reg.c | 48 +++++++++++++++++++++++------------------------ src/cmd/6g/opt.h | 14 +++++++------- src/cmd/6g/reg.c | 46 ++++++++++++++++++++++----------------------- src/cmd/8g/opt.h | 14 +++++++------- src/cmd/8g/reg.c | 46 ++++++++++++++++++++++----------------------- src/cmd/gc/bits.c | 34 ++++++++++++++++++++------------- src/cmd/gc/go.h | 12 +++++++----- 8 files changed, 119 insertions(+), 109 deletions(-) diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h index 1946c1d33c..5016d1cc83 100644 --- a/src/cmd/5g/opt.h +++ b/src/cmd/5g/opt.h @@ -63,8 +63,8 @@ enum uint32 BLOAD(Reg*); uint32 BSTORE(Reg*); -uint32 LOAD(Reg*); -uint32 STORE(Reg*); +uint64 LOAD(Reg*); +uint64 STORE(Reg*); */ // A Reg is a wrapper around a single Prog (one instruction) that holds @@ -145,7 +145,7 @@ void synch(Reg*, Bits); uint32 allreg(uint32, Rgn*); void paint1(Reg*, int); uint32 paint2(Reg*, int); -void paint3(Reg*, int, int32, int); +void paint3(Reg*, int, uint32, int); void addreg(Adr*, int); void dumpit(char *str, Flow *r0, int); @@ -156,10 +156,10 @@ void peep(Prog*); void excise(Flow*); int copyu(Prog*, Adr*, Adr*); -int32 RtoB(int); -int32 FtoB(int); -int BtoR(int32); -int BtoF(int32); +uint32 RtoB(int); +uint32 FtoB(int); +int BtoR(uint32); +int BtoF(uint32); /* * prog.c diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 8e49a2d9c8..5b25adaf45 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -35,7 +35,7 @@ #include "opt.h" #define NREGVAR 32 -#define REGBITS ((uint32)0xffffffff) +#define REGBITS ((uint64)0xffffffffull) /*c2go enum { NREGVAR = 32, REGBITS = 0xffffffff, @@ -86,7 +86,7 @@ setaddrs(Bits bit) i = bnum(bit); node = var[i].node; n = var[i].name; - bit.b[i/32] &= ~(1L<<(i%32)); + biclr(&bit, i); // disable all pieces of that variable for(i=0; i 1) print("\n"); paint1(r, i); - bit.b[i/32] &= ~(1L<<(i%32)); + biclr(&bit, i); if(change <= 0) { if(debug['R']) print("%L $%d: %Q\n", @@ -570,7 +570,7 @@ walkvardef(Node *n, Reg *r, int active) break; for(v=n->opt; v!=nil; v=v->nextinnode) { bn = v - var; - r1->act.b[bn/32] |= 1L << (bn%32); + biset(&r1->act, bn); } if(r1->f.prog->as == ABL) break; @@ -606,7 +606,7 @@ addsplits(void) ~(r->calahead.b[z] & addrs.b[z]); while(bany(&bit)) { i = bnum(bit); - bit.b[i/32] &= ~(1L << (i%32)); + biclr(&bit, i); } } } @@ -972,10 +972,10 @@ prop(Reg *r, Bits ref, Bits cal) for(z=0; z= nvar || ((cal.b[z]>>i)&1) == 0) + for(i=0; i<64; i++) { + if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0) continue; - v = var+z*32+i; + v = var+z*64+i; if(v->node->opt == nil) // v represents fixed register, not Go variable continue; @@ -991,10 +991,10 @@ prop(Reg *r, Bits ref, Bits cal) // This will set the bits at most twice, keeping the overall loop linear. v1 = v->node->opt; j = v1 - var; - if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) { + if(v == v1 || !btest(&cal, j)) { for(; v1 != nil; v1 = v1->nextinnode) { j = v1 - var; - cal.b[j/32] |= 1<<(j&31); + biset(&cal, j); } } } @@ -1115,10 +1115,10 @@ paint1(Reg *r, int bn) Reg *r1; Prog *p; int z; - uint32 bb; + uint64 bb; - z = bn/32; - bb = 1L<<(bn%32); + z = bn/64; + bb = 1LL<<(bn%64); if(r->act.b[z] & bb) return; for(;;) { @@ -1193,10 +1193,10 @@ paint2(Reg *r, int bn) { Reg *r1; int z; - uint32 bb, vreg; + uint64 bb, vreg; - z = bn/32; - bb = 1L << (bn%32); + z = bn/64; + bb = 1LL << (bn%64); vreg = regbits; if(!(r->act.b[z] & bb)) return vreg; @@ -1240,15 +1240,15 @@ paint2(Reg *r, int bn) } void -paint3(Reg *r, int bn, int32 rb, int rn) +paint3(Reg *r, int bn, uint32 rb, int rn) { Reg *r1; Prog *p; int z; - uint32 bb; + uint64 bb; - z = bn/32; - bb = 1L << (bn%32); + z = bn/64; + bb = 1LL << (bn%64); if(r->act.b[z] & bb) return; for(;;) { @@ -1333,7 +1333,7 @@ addreg(Adr *a, int rn) * 10 R10 * 12 R12 */ -int32 +uint32 RtoB(int r) { if(r >= REGTMP-2 && r != 12) // excluded R9 and R10 for m and g, but not R12 @@ -1342,7 +1342,7 @@ RtoB(int r) } int -BtoR(int32 b) +BtoR(uint32 b) { b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12 if(b == 0) @@ -1357,7 +1357,7 @@ BtoR(int32 b) * ... ... * 31 F15 */ -int32 +uint32 FtoB(int f) { @@ -1367,7 +1367,7 @@ FtoB(int f) } int -BtoF(int32 b) +BtoF(uint32 b) { b &= 0xfffc0000L; diff --git a/src/cmd/6g/opt.h b/src/cmd/6g/opt.h index dbd039d89f..4c9bb89fc8 100644 --- a/src/cmd/6g/opt.h +++ b/src/cmd/6g/opt.h @@ -63,8 +63,8 @@ enum uint32 BLOAD(Reg*); uint32 BSTORE(Reg*); -uint32 LOAD(Reg*); -uint32 STORE(Reg*); +uint64 LOAD(Reg*); +uint64 STORE(Reg*); */ // A Reg is a wrapper around a single Prog (one instruction) that holds @@ -141,7 +141,7 @@ void synch(Reg*, Bits); uint32 allreg(uint32, Rgn*); void paint1(Reg*, int); uint32 paint2(Reg*, int); -void paint3(Reg*, int, int32, int); +void paint3(Reg*, int, uint32, int); void addreg(Adr*, int); void dumpone(Flow*, int); void dumpit(char*, Flow*, int); @@ -153,10 +153,10 @@ void peep(Prog*); void excise(Flow*); int copyu(Prog*, Adr*, Adr*); -int32 RtoB(int); -int32 FtoB(int); -int BtoR(int32); -int BtoF(int32); +uint32 RtoB(int); +uint32 FtoB(int); +int BtoR(uint32); +int BtoF(uint32); /* * prog.c diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index 1f757e1972..8d600d6433 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -34,7 +34,7 @@ #include "opt.h" #define NREGVAR 32 /* 16 general + 16 floating */ -#define REGBITS ((uint32)0xffffffff) +#define REGBITS ((uint64)0xffffffffull) /*c2go enum { NREGVAR = 32, REGBITS = 0xffffffff, @@ -71,7 +71,7 @@ setaddrs(Bits bit) i = bnum(bit); node = var[i].node; n = var[i].name; - bit.b[i/32] &= ~(1L<<(i%32)); + biclr(&bit, i); // disable all pieces of that variable for(i=0; ivarno = i; change = 0; paint1(r, i); - bit.b[i/32] &= ~(1L<<(i%32)); + biclr(&bit, i); if(change <= 0) continue; rgp->cost = change; @@ -477,7 +477,7 @@ walkvardef(Node *n, Reg *r, int active) break; for(v=n->opt; v!=nil; v=v->nextinnode) { bn = v - var; - r1->act.b[bn/32] |= 1L << (bn%32); + biset(&r1->act, bn); } if(r1->f.prog->as == ACALL) break; @@ -822,10 +822,10 @@ prop(Reg *r, Bits ref, Bits cal) for(z=0; z= nvar || ((cal.b[z]>>i)&1) == 0) + for(i=0; i<64; i++) { + if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0) continue; - v = var+z*32+i; + v = var+z*64+i; if(v->node->opt == nil) // v represents fixed register, not Go variable continue; @@ -841,10 +841,10 @@ prop(Reg *r, Bits ref, Bits cal) // This will set the bits at most twice, keeping the overall loop linear. v1 = v->node->opt; j = v1 - var; - if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) { + if(v == v1 || !btest(&cal, j)) { for(; v1 != nil; v1 = v1->nextinnode) { j = v1 - var; - cal.b[j/32] |= 1UL<<(j&31); + biset(&cal, j); } } } @@ -959,10 +959,10 @@ paint1(Reg *r, int bn) { Reg *r1; int z; - uint32 bb; + uint64 bb; - z = bn/32; - bb = 1L<<(bn%32); + z = bn/64; + bb = 1LL<<(bn%64); if(r->act.b[z] & bb) return; for(;;) { @@ -1061,10 +1061,10 @@ paint2(Reg *r, int bn) { Reg *r1; int z; - uint32 bb, vreg, x; + uint64 bb, vreg, x; - z = bn/32; - bb = 1L << (bn%32); + z = bn/64; + bb = 1LL << (bn%64); vreg = regbits; if(!(r->act.b[z] & bb)) return vreg; @@ -1117,15 +1117,15 @@ paint2(Reg *r, int bn) } void -paint3(Reg *r, int bn, int32 rb, int rn) +paint3(Reg *r, int bn, uint32 rb, int rn) { Reg *r1; Prog *p; int z; - uint32 bb; + uint64 bb; - z = bn/32; - bb = 1L << (bn%32); + z = bn/64; + bb = 1LL << (bn%64); if(r->act.b[z] & bb) return; for(;;) { @@ -1198,7 +1198,7 @@ addreg(Adr *a, int rn) ostats.ncvtreg++; } -int32 +uint32 RtoB(int r) { @@ -1208,7 +1208,7 @@ RtoB(int r) } int -BtoR(int32 b) +BtoR(uint32 b) { b &= 0xffffL; if(nacl) @@ -1224,7 +1224,7 @@ BtoR(int32 b) * ... * 31 X15 */ -int32 +uint32 FtoB(int f) { if(f < D_X0 || f > D_X15) @@ -1233,7 +1233,7 @@ FtoB(int f) } int -BtoF(int32 b) +BtoF(uint32 b) { b &= 0xFFFF0000L; diff --git a/src/cmd/8g/opt.h b/src/cmd/8g/opt.h index 09f58c40ae..0e2d165b17 100644 --- a/src/cmd/8g/opt.h +++ b/src/cmd/8g/opt.h @@ -63,8 +63,8 @@ enum uint32 BLOAD(Reg*); uint32 BSTORE(Reg*); -uint32 LOAD(Reg*); -uint32 STORE(Reg*); +uint64 LOAD(Reg*); +uint64 STORE(Reg*); */ // A Reg is a wrapper around a single Prog (one instruction) that holds @@ -159,7 +159,7 @@ void synch(Reg*, Bits); uint32 allreg(uint32, Rgn*); void paint1(Reg*, int); uint32 paint2(Reg*, int); -void paint3(Reg*, int, int32, int); +void paint3(Reg*, int, uint32, int); void addreg(Adr*, int); void dumpone(Flow*, int); void dumpit(char*, Flow*, int); @@ -171,10 +171,10 @@ void peep(Prog*); void excise(Flow*); int copyu(Prog*, Adr*, Adr*); -int32 RtoB(int); -int32 FtoB(int); -int BtoR(int32); -int BtoF(int32); +uint32 RtoB(int); +uint32 FtoB(int); +int BtoR(uint32); +int BtoF(uint32); /* * prog.c diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index 302b273a1b..0fbe684821 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -34,7 +34,7 @@ #include "opt.h" #define NREGVAR 16 /* 8 integer + 8 floating */ -#define REGBITS ((uint32)0xffff) +#define REGBITS ((uint64)0xffffull) /*c2go enum { NREGVAR = 16, REGBITS = (1<varno = i; change = 0; paint1(r, i); - bit.b[i/32] &= ~(1L<<(i%32)); + biclr(&bit, i); if(change <= 0) continue; rgp->cost = change; @@ -446,7 +446,7 @@ walkvardef(Node *n, Reg *r, int active) break; for(v=n->opt; v!=nil; v=v->nextinnode) { bn = v - var; - r1->act.b[bn/32] |= 1L << (bn%32); + biset(&r1->act, bn); } if(r1->f.prog->as == ACALL) break; @@ -788,10 +788,10 @@ prop(Reg *r, Bits ref, Bits cal) for(z=0; z= nvar || ((cal.b[z]>>i)&1) == 0) + for(i=0; i<64; i++) { + if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0) continue; - v = var+z*32+i; + v = var+z*64+i; if(v->node->opt == nil) // v represents fixed register, not Go variable continue; @@ -807,10 +807,10 @@ prop(Reg *r, Bits ref, Bits cal) // This will set the bits at most twice, keeping the overall loop linear. v1 = v->node->opt; j = v1 - var; - if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) { + if(v == v1 || !btest(&cal, j)) { for(; v1 != nil; v1 = v1->nextinnode) { j = v1 - var; - cal.b[j/32] |= 1<<(j&31); + biset(&cal, j); } } } @@ -926,10 +926,10 @@ paint1(Reg *r, int bn) Reg *r1; Prog *p; int z; - uint32 bb; + uint64 bb; - z = bn/32; - bb = 1L<<(bn%32); + z = bn/64; + bb = 1LL<<(bn%64); if(r->act.b[z] & bb) return; for(;;) { @@ -1038,10 +1038,10 @@ paint2(Reg *r, int bn) { Reg *r1; int z; - uint32 bb, vreg, x; + uint64 bb, vreg, x; - z = bn/32; - bb = 1L << (bn%32); + z = bn/64; + bb = 1LL << (bn%64); vreg = regbits; if(!(r->act.b[z] & bb)) return vreg; @@ -1094,15 +1094,15 @@ paint2(Reg *r, int bn) } void -paint3(Reg *r, int bn, int32 rb, int rn) +paint3(Reg *r, int bn, uint32 rb, int rn) { Reg *r1; Prog *p; int z; - uint32 bb; + uint64 bb; - z = bn/32; - bb = 1L << (bn%32); + z = bn/64; + bb = 1LL << (bn%64); if(r->act.b[z] & bb) return; for(;;) { @@ -1175,7 +1175,7 @@ addreg(Adr *a, int rn) ostats.ncvtreg++; } -int32 +uint32 RtoB(int r) { @@ -1185,7 +1185,7 @@ RtoB(int r) } int -BtoR(int32 b) +BtoR(uint32 b) { b &= 0xffL; @@ -1194,7 +1194,7 @@ BtoR(int32 b) return bitno(b) + D_AX; } -int32 +uint32 FtoB(int f) { if(f < D_X0 || f > D_X7) @@ -1203,7 +1203,7 @@ FtoB(int f) } int -BtoF(int32 b) +BtoF(uint32 b) { b &= 0xFF00L; if(b == 0) diff --git a/src/cmd/gc/bits.c b/src/cmd/gc/bits.c index 2e79f6f1de..fe9a168dcd 100644 --- a/src/cmd/gc/bits.c +++ b/src/cmd/gc/bits.c @@ -95,11 +95,11 @@ int bnum(Bits a) { int i; - int32 b; + uint64 b; for(i=0; ib[n/64] & (1LL << (n%64))) != 0; +} + +void +biset(Bits *a, uint n) +{ + a->b[n/64] |= 1LL << (n%64); +} + +void +biclr(Bits *a, uint n) +{ + a->b[n/64] &= ~(1LL << (n%64)); } -*/ int -bitno(int32 b) +bitno(uint64 b) { int i; - for(i=0; i<32; i++) - if(b & (1L< Date: Wed, 5 Nov 2014 15:36:47 -0500 Subject: [PATCH 118/128] [dev.power64] 6g: don't create variables for indirect addresses Previously, mkvar treated, for example, 0(AX) the same as AX. As a result, a move to an indirect address would be marked as *setting* the register, rather than just using it, resulting in unnecessary register moves. Fix this by not producing variables for indirect addresses. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/164610043 --- src/cmd/6g/reg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index 8d600d6433..afd3f1056e 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -621,6 +621,9 @@ mkvar(Reg *r, Adr *a) if(r != R) r->use1.b[0] |= doregbits(a->index); + if(t >= D_INDIR && t < 2*D_INDIR) + goto none; + switch(t) { default: regu = doregbits(t); From f45fd5753c4f1fd6ab472e219598523516855b40 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 6 Nov 2014 14:37:39 -0500 Subject: [PATCH 119/128] [dev.power64] gc: fix etype of strings The etype of references to strings was being incorrectly set to TINT32 on all platforms. Change it to TSTRING. It seems this doesn't matter for compilation, since x86 uses LEA instructions to load string addresses and arm and power64 disassemble the string into its constituent pieces (with the correct types), but it helps when debugging. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/170100043 --- src/cmd/5g/gobj.c | 2 +- src/cmd/6g/gobj.c | 2 +- src/cmd/8g/gobj.c | 2 +- src/cmd/9g/gobj.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/5g/gobj.c b/src/cmd/5g/gobj.c index 5e988878f7..65f731685e 100644 --- a/src/cmd/5g/gobj.c +++ b/src/cmd/5g/gobj.c @@ -86,7 +86,7 @@ datagostring(Strlit *sval, Addr *a) sym = stringsym(sval->s, sval->len); a->type = D_OREG; a->name = D_EXTERN; - a->etype = TINT32; + a->etype = TSTRING; a->offset = 0; // header a->reg = NREG; a->sym = linksym(sym); diff --git a/src/cmd/6g/gobj.c b/src/cmd/6g/gobj.c index 04e837b138..dbb4ff62c4 100644 --- a/src/cmd/6g/gobj.c +++ b/src/cmd/6g/gobj.c @@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a) a->sym = linksym(sym); a->node = sym->def; a->offset = 0; // header - a->etype = TINT32; + a->etype = TSTRING; } void diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c index fa0605e6c7..af287f7023 100644 --- a/src/cmd/8g/gobj.c +++ b/src/cmd/8g/gobj.c @@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a) a->sym = linksym(sym); a->node = sym->def; a->offset = 0; // header - a->etype = TINT32; + a->etype = TSTRING; } void diff --git a/src/cmd/9g/gobj.c b/src/cmd/9g/gobj.c index fdd7606bcd..3da55878a7 100644 --- a/src/cmd/9g/gobj.c +++ b/src/cmd/9g/gobj.c @@ -89,7 +89,7 @@ datagostring(Strlit *sval, Addr *a) a->reg = NREG; a->node = sym->def; a->offset = 0; // header - a->etype = TINT32; + a->etype = TSTRING; } void From 22c929f538483a02707b2caef91a1d3b55a72ef5 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 6 Nov 2014 14:41:44 -0500 Subject: [PATCH 120/128] [dev.power64] 9g: fix addr width calculation; enable MOV* width check 9g's naddr was missing assignments to a->width in several cases, so the optimizer was getting bogus width information. Add them. This correct width information also lets us enable the width check in gins for MOV*. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/167310043 --- src/cmd/9g/gsubr.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index d8b62b1da2..f7a4290818 100644 --- a/src/cmd/9g/gsubr.c +++ b/src/cmd/9g/gsubr.c @@ -1001,10 +1001,13 @@ hard: Prog* gins(int as, Node *f, Node *t) { - //int32 w; + int32 w; Prog *p; Addr af, at; + // TODO(austin): Add self-move test like in 6g (but be careful + // of truncation moves) + memset(&af, 0, sizeof af); memset(&at, 0, sizeof at); if(f != N) @@ -1021,9 +1024,6 @@ gins(int as, Node *f, Node *t) 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: @@ -1049,12 +1049,11 @@ gins(int as, Node *f, Node *t) w = 8; break; } - if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) { + if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != D_REG && at.width > w))) { dump("f", f); dump("t", t); fatal("bad width: %P (%d, %d)\n", p, af.width, at.width); } - */ return p; } @@ -1116,12 +1115,9 @@ naddr(Node *n, Addr *a, int canemitcode) case ONAME: a->etype = 0; - a->width = 0; a->reg = NREG; - if(n->type != T) { + 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; @@ -1242,15 +1238,16 @@ naddr(Node *n, Addr *a, int canemitcode) naddr(n->left, a, canemitcode); a->etype = simtype[tptr]; if(a->type == D_CONST && a->offset == 0) - break; // len(nil) + break; // itab(nil) + a->width = widthptr; break; case OSPTR: // pointer in a string or slice naddr(n->left, a, canemitcode); + a->etype = simtype[tptr]; if(a->type == D_CONST && a->offset == 0) break; // ptr(nil) - a->etype = simtype[tptr]; a->offset += Array_array; a->width = widthptr; break; @@ -1262,6 +1259,7 @@ naddr(Node *n, Addr *a, int canemitcode) if(a->type == D_CONST && a->offset == 0) break; // len(nil) a->offset += Array_nel; + a->width = widthint; break; case OCAP: @@ -1271,11 +1269,13 @@ naddr(Node *n, Addr *a, int canemitcode) if(a->type == D_CONST && a->offset == 0) break; // cap(nil) a->offset += Array_cap; + a->width = widthint; break; case OADDR: naddr(n->left, a, canemitcode); a->etype = tptr; + a->width = widthptr; switch(a->type) { case D_OREG: a->type = D_CONST; @@ -1288,6 +1288,7 @@ naddr(Node *n, Addr *a, int canemitcode) default: fatal("naddr: OADDR %d\n", a->type); } + break; } } From e156f0e9971ca77ed6f9cb34e36ed73145bfa177 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 6 Nov 2014 15:35:53 -0500 Subject: [PATCH 121/128] [dev.power64] 5g: fix etype and width of itable Addrs For OITAB nodes, 5g's naddr was setting the wrong etype and failing to set the width of the resulting Addr. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/171220043 --- src/cmd/5g/gsubr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c index 06e274e14d..f09197963c 100644 --- a/src/cmd/5g/gsubr.c +++ b/src/cmd/5g/gsubr.c @@ -1353,9 +1353,10 @@ naddr(Node *n, Addr *a, int canemitcode) case OITAB: // itable of interface value naddr(n->left, a, canemitcode); - a->etype = TINT32; + a->etype = simtype[tptr]; if(a->type == D_CONST && a->offset == 0) break; // len(nil) + a->width = widthptr; break; case OSPTR: From 7739533f61616ba71ef691489c0eeab2a59bd9e9 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 7 Nov 2014 10:43:55 -0500 Subject: [PATCH 122/128] [dev.power64] 5g: fix mistaken bit-wise AND in regopt Replace a bit-wise AND with a logical one. This happened to work before because bany returns 0 or 1, but the intent here is clearly logical (and this makes 5g match with 6g and 8g). LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/172850043 --- src/cmd/5g/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 5b25adaf45..712841329e 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -393,7 +393,7 @@ loop2: 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) & !r->f.refset) { + if(bany(&bit) && !r->f.refset) { // should never happen - all variables are preset if(debug['w']) print("%L: used and not set: %Q\n", r->f.prog->lineno, bit); From c1e8c57c3d0083fafaf451db7b9b018e16d3669b Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 12 Nov 2014 14:16:49 -0500 Subject: [PATCH 123/128] [dev.power64] 9g: fix width check and width calculation for OADDR LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/174970043 --- src/cmd/9g/gsubr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c index f7a4290818..e5cd5ed4bf 100644 --- a/src/cmd/9g/gsubr.c +++ b/src/cmd/9g/gsubr.c @@ -1046,6 +1046,8 @@ gins(int as, Node *f, Node *t) break; case AMOVD: case AMOVDU: + if(af.type == D_CONST) + break; w = 8; break; } @@ -1275,7 +1277,6 @@ naddr(Node *n, Addr *a, int canemitcode) case OADDR: naddr(n->left, a, canemitcode); a->etype = tptr; - a->width = widthptr; switch(a->type) { case D_OREG: a->type = D_CONST; From 60f66aa817790ee55956552540ca49ea76fc9077 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 12 Nov 2014 14:58:43 -0500 Subject: [PATCH 124/128] [dev.power64] 9g: proginfo fixes For D_OREG addresses, store the used registers in regindex instead of reguse because they're really part of addressing. Add implicit register use/set for DUFFZERO/DUFFCOPY. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/174050044 --- src/cmd/9g/prog.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/cmd/9g/prog.c b/src/cmd/9g/prog.c index 0a51a533a0..e3e50f28a9 100644 --- a/src/cmd/9g/prog.c +++ b/src/cmd/9g/prog.c @@ -96,11 +96,8 @@ static ProgInfo progtable[ALAST] = { [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}, }; @@ -118,14 +115,14 @@ proginfo(ProgInfo *info, Prog *p) info->flags |= /*CanRegRead |*/ RightRead; } - if(p->from.type == D_OREG && p->from.reg != NREG) { - info->reguse |= RtoB(p->from.reg); + if((p->from.type == D_OREG || p->from.type == D_CONST) && p->from.reg != NREG) { + info->regindex |= RtoB(p->from.reg); if(info->flags & PostInc) { info->regset |= RtoB(p->from.reg); } } - if(p->to.type == D_OREG && p->to.reg != NREG) { - info->reguse |= RtoB(p->to.reg); + if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) { + info->regindex |= RtoB(p->to.reg); if(info->flags & PostInc) { info->regset |= RtoB(p->to.reg); } @@ -135,4 +132,13 @@ proginfo(ProgInfo *info, Prog *p) info->flags &= ~LeftRead; info->flags |= LeftAddr; } + + if(p->as == ADUFFZERO) { + info->reguse |= RtoB(0) | RtoB(2); + info->regset |= RtoB(2); + } + if(p->as == ADUFFCOPY) { + info->reguse |= RtoB(0) | RtoB(2) | RtoB(3); + info->regset |= RtoB(2) | RtoB(3); + } } From 8c060d9392d44916588780fe976c888f3ba8a60e Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 12 Nov 2014 17:19:02 -0500 Subject: [PATCH 125/128] [dev.power64] liblink: improve documentation of struct Prog LGTM=dave, rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/169460043 --- include/link.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/link.h b/include/link.h index c80f467580..06f3ebb489 100644 --- a/include/link.h +++ b/include/link.h @@ -54,7 +54,7 @@ struct Addr { char sval[8]; float64 dval; - Prog* branch; // for 5g, 6g, 8g + Prog* branch; // for 5g, 6g, 8g, 9g } u; LSym* sym; @@ -89,10 +89,13 @@ struct Prog int32 lineno; Prog* link; short as; - uchar reg; // arm, power64 only - uchar scond; // arm only + uchar scond; // arm only; condition codes + + // operands Addr from; - Addr from3; // power64 only, fma and rlwm + uchar reg; // arm, power64 only (e.g., ADD from, reg, to); + // also used for ADATA width on arm, power64 + Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to) Addr to; // for 5g, 6g, 8g internal use From c3dadb3d190973b888f5f83de3a3cccdbe7fc949 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 13 Nov 2014 13:34:20 -0500 Subject: [PATCH 126/128] [dev.power64] 6g,8g: remove unnecessary and incorrect reg use scanning Previously, the 6g and 8g registerizers scanned for used registers beyond the end of a region being considered for registerization. This ancient artifact was copied from the C compilers, where it was probably necessary to track implicitly used registers. In the Go compilers it's harmless (because it can only over-restrict the set of available registers), but no longer necessary because the Go compilers correctly track register use/set information. The consequences of this extra scan were (at least) that 1) we would not consider allocating the AX register if there was a deferproc call in the future because deferproc uses AX as a return register, so we see the use of AX, but don't track that AX is set by the CALL, and 2) we could not consider allocating the DX register if there was a MUL in the future because MUL implicitly sets DX and (thanks to an abuse of copyu in this code) we would also consider DX used. This commit fixes these problems by nuking this code. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/174110043 --- src/cmd/6g/reg.c | 50 +----------------------------------------------- src/cmd/8g/reg.c | 48 +--------------------------------------------- 2 files changed, 2 insertions(+), 96 deletions(-) diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index afd3f1056e..4ce2f4db00 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -1019,52 +1019,12 @@ paint1(Reg *r, int bn) } } -uint32 -regset(Reg *r, uint32 bb) -{ - uint32 b, set; - Adr v; - int c; - - set = 0; - v = zprog.from; - while(b = bb & ~(bb-1)) { - v.type = b & 0xFFFF? BtoR(b): BtoF(b); - if(v.type == 0) - fatal("zero v.type for %#ux", b); - c = copyu(r->f.prog, &v, nil); - if(c == 3) - set |= b; - bb &= ~b; - } - return set; -} - -uint32 -reguse(Reg *r, uint32 bb) -{ - uint32 b, set; - Adr v; - int c; - - set = 0; - v = zprog.from; - while(b = bb & ~(bb-1)) { - v.type = b & 0xFFFF? BtoR(b): BtoF(b); - c = copyu(r->f.prog, &v, nil); - if(c == 1 || c == 2 || c == 4) - set |= b; - bb &= ~b; - } - return set; -} - uint32 paint2(Reg *r, int bn) { Reg *r1; int z; - uint64 bb, vreg, x; + uint64 bb, vreg; z = bn/64; bb = 1LL << (bn%64); @@ -1108,14 +1068,6 @@ paint2(Reg *r, int bn) break; } - bb = vreg; - for(; r; r=(Reg*)r->f.s1) { - x = r->regu & ~bb; - if(x) { - vreg |= reguse(r, x); - bb |= regset(r, x); - } - } return vreg; } diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index 0fbe684821..79d60bed55 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -995,50 +995,12 @@ paint1(Reg *r, int bn) } } -uint32 -regset(Reg *r, uint32 bb) -{ - uint32 b, set; - Adr v; - int c; - - set = 0; - v = zprog.from; - while(b = bb & ~(bb-1)) { - v.type = b & 0xFF ? BtoR(b): BtoF(b); - c = copyu(r->f.prog, &v, nil); - if(c == 3) - set |= b; - bb &= ~b; - } - return set; -} - -uint32 -reguse(Reg *r, uint32 bb) -{ - uint32 b, set; - Adr v; - int c; - - set = 0; - v = zprog.from; - while(b = bb & ~(bb-1)) { - v.type = b & 0xFF ? BtoR(b): BtoF(b); - c = copyu(r->f.prog, &v, nil); - if(c == 1 || c == 2 || c == 4) - set |= b; - bb &= ~b; - } - return set; -} - uint32 paint2(Reg *r, int bn) { Reg *r1; int z; - uint64 bb, vreg, x; + uint64 bb, vreg; z = bn/64; bb = 1LL << (bn%64); @@ -1082,14 +1044,6 @@ paint2(Reg *r, int bn) break; } - bb = vreg; - for(; r; r=(Reg*)r->f.s1) { - x = r->regu & ~bb; - if(x) { - vreg |= reguse(r, x); - bb |= regset(r, x); - } - } return vreg; } From 231b8d61e9a7eec0e2145217828a4881392db230 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 13 Nov 2014 13:48:59 -0500 Subject: [PATCH 127/128] [dev.power64] 9l: remove enum as's tag for c2go None of the other compilers have a tag for this enum. Cleaning all of this up to use proper types will happen after the conversion. LGTM=minux, rsc R=rsc, minux CC=golang-codereviews https://golang.org/cl/166690043 --- src/cmd/9l/9.out.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h index e494e90ca9..08a339318d 100644 --- a/src/cmd/9l/9.out.h +++ b/src/cmd/9l/9.out.h @@ -131,7 +131,7 @@ enum C_NCLASS, /* must be the last */ }; -enum as +enum { AXXX, AADD, @@ -501,7 +501,7 @@ enum D_R0 = 0, // type is D_REG D_F0 = D_R0+NREG, // type is D_FREG -/* reg names iff type is D_SPR */ +/* reg names in offset field iff type is D_SPR */ D_XER = 1, D_LR = 8, D_CTR = 9 From 743bdf612a63d631bac88a6b857094152ac33d5c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 13 Nov 2014 13:51:44 -0500 Subject: [PATCH 128/128] [dev.power64] 9g: implement regopt This adds registerization support to 9g equivalent to what the other compilers have. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/174980043 --- src/cmd/9g/opt.h | 49 +- src/cmd/9g/reg.c | 1214 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1233 insertions(+), 30 deletions(-) diff --git a/src/cmd/9g/opt.h b/src/cmd/9g/opt.h index d3cbcb9570..7f15b5a69f 100644 --- a/src/cmd/9g/opt.h +++ b/src/cmd/9g/opt.h @@ -70,24 +70,40 @@ struct Reg { Flow f; - Bits set; // variables written by this instruction. - Bits use1; // variables read by prog->from. - Bits use2; // variables read by prog->to. + Bits set; // regopt variables written by this instruction. + Bits use1; // regopt variables read by prog->from. + Bits use2; // regopt variables read by prog->to. + // refahead/refbehind are the regopt variables whose current + // value may be used in the following/preceding instructions + // up to a CALL (or the value is clobbered). Bits refbehind; Bits refahead; + // calahead/calbehind are similar, but for variables in + // instructions that are reachable after hitting at least one + // CALL. Bits calbehind; Bits calahead; Bits regdiff; Bits act; - int32 regu; // register used bitmap + uint64 regu; // register used bitmap }; #define R ((Reg*)0) /*c2go extern Reg *R; */ #define NRGN 600 /*c2go enum { NRGN = 600 }; */ + +// A Rgn represents a single regopt variable over a region of code +// where a register could potentially be dedicated to that variable. +// The code encompassed by a Rgn is defined by the flow graph, +// starting at enter, flood-filling forward while varno is refahead +// and backward while varno is refbehind, and following branches. A +// single variable may be represented by multiple disjoint Rgns and +// each Rgn may choose a different register for that variable. +// Registers are allocated to regions greedily in order of descending +// cost. struct Rgn { Reg* enter; @@ -104,7 +120,7 @@ EXTERN Rgn* rgp; EXTERN int nregion; EXTERN int nvar; EXTERN int32 regbits; -EXTERN int32 exregbits; +EXTERN int32 exregbits; // TODO(austin) not used; remove EXTERN Bits externs; EXTERN Bits params; EXTERN Bits consts; @@ -118,10 +134,8 @@ EXTERN struct { int32 ncvtreg; int32 nspill; - int32 nreload; int32 ndelmov; int32 nvar; - int32 naddr; } ostats; /* @@ -133,10 +147,10 @@ void addmove(Reg*, int, int, int); Bits mkvar(Reg*, Adr*); void prop(Reg*, Bits, Bits); void synch(Reg*, Bits); -uint32 allreg(uint32, Rgn*); +uint64 allreg(uint64, Rgn*); void paint1(Reg*, int); -uint32 paint2(Reg*, int); -void paint3(Reg*, int, int32, int); +uint64 paint2(Reg*, int, int); +void paint3(Reg*, int, uint64, int); void addreg(Adr*, int); void dumpone(Flow*, int); void dumpit(char*, Flow*, int); @@ -160,8 +174,8 @@ 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 reguse; // registers implicitly used by this instruction + uint64 regset; // registers implicitly set by this instruction uint64 regindex; // registers used by addressing mode }; @@ -182,20 +196,21 @@ enum SizeF = 1<<7, // float aka float32 SizeD = 1<<8, // double aka float64 - // Left side: address taken, read, write. + // Left side (Prog.from): address taken, read, write. LeftAddr = 1<<9, LeftRead = 1<<10, LeftWrite = 1<<11, - - // Register in middle; never written. + + // Register in middle (Prog.reg); only ever read. RegRead = 1<<12, CanRegRead = 1<<13, - - // Right side: address taken, read, write. + + // Right side (Prog.to): address taken, read, write. RightAddr = 1<<14, RightRead = 1<<15, RightWrite = 1<<16, + // Instruction updates whichever of from/to is type D_OREG PostInc = 1<<17, // Instruction kinds diff --git a/src/cmd/9g/reg.c b/src/cmd/9g/reg.c index bbebf3fe03..b911a23998 100644 --- a/src/cmd/9g/reg.c +++ b/src/cmd/9g/reg.c @@ -33,14 +33,1197 @@ #include "gg.h" #include "opt.h" -void -regopt(Prog *p) +#define NREGVAR 64 /* 32 general + 32 floating */ +#define REGBITS ((uint64)0xffffffffffffffffull) +/*c2go enum { + NREGVAR = 64, + REGBITS = 0xffffffffffffffff, +}; +*/ + +static Reg* firstr; +static int first = 1; + +int +rcmp(const void *a1, const void *a2) { - USED(p); - // TODO(minux) + Rgn *p1, *p2; + int c1, c2; + + p1 = (Rgn*)a1; + p2 = (Rgn*)a2; + c1 = p2->cost; + c2 = p1->cost; + if(c1 -= c2) + return c1; + return p2->varno - p1->varno; +} + +static void +setaddrs(Bits bit) +{ + int i, n; + Var *v; + Node *node; + + while(bany(&bit)) { + // convert each bit to a variable + i = bnum(bit); + node = var[i].node; + n = var[i].name; + biclr(&bit, i); + + // disable all pieces of that variable + for(i=0; inode == node && v->name == n) + v->addr = 2; + } + } +} + +static char* regname[] = { + ".R0", + ".R1", + ".R2", + ".R3", + ".R4", + ".R5", + ".R6", + ".R7", + ".R8", + ".R9", + ".R10", + ".R11", + ".R12", + ".R13", + ".R14", + ".R15", + ".R16", + ".R17", + ".R18", + ".R19", + ".R20", + ".R21", + ".R22", + ".R23", + ".R24", + ".R25", + ".R26", + ".R27", + ".R28", + ".R29", + ".R30", + ".R31", + ".F0", + ".F1", + ".F2", + ".F3", + ".F4", + ".F5", + ".F6", + ".F7", + ".F8", + ".F9", + ".F10", + ".F11", + ".F12", + ".F13", + ".F14", + ".F15", + ".F16", + ".F17", + ".F18", + ".F19", + ".F20", + ".F21", + ".F22", + ".F23", + ".F24", + ".F25", + ".F26", + ".F27", + ".F28", + ".F29", + ".F30", + ".F31", +}; + +static Node* regnodes[NREGVAR]; + +static void walkvardef(Node *n, Reg *r, int active); + +void +regopt(Prog *firstp) +{ + Reg *r, *r1; + Prog *p; + Graph *g; + ProgInfo info; + int i, z, active; + uint64 vreg, usedreg; + Bits bit; + + if(first) { + fmtinstall('Q', Qconv); + first = 0; + } + + mergetemp(firstp); + + /* + * control flow is more complicated in generated go code + * than in generated c code. define pseudo-variables for + * registers, so we have complete register usage information. + */ + nvar = NREGVAR; + memset(var, 0, NREGVAR*sizeof var[0]); + for(i=0; iopt = nil; + return; + } + + firstr = (Reg*)g->start; + + for(r = firstr; r != R; r = (Reg*)r->f.link) { + p = r->f.prog; + if(p->as == AVARDEF || p->as == AVARKILL) + continue; + proginfo(&info, p); + + // Avoid making variables for direct-called functions. + if(p->as == ABL && p->to.name == D_EXTERN) + continue; + + // from vs to doesn't matter for registers + r->use1.b[0] |= info.reguse | info.regindex; + r->set.b[0] |= info.regset; + + // Compute used register for from + bit = mkvar(r, &p->from); + if(info.flags & LeftAddr) + setaddrs(bit); + if(info.flags & LeftRead) + for(z=0; zuse1.b[z] |= bit.b[z]; + + // Compute used register for reg + if(info.flags & RegRead) { + if(p->from.type != D_FREG) + r->use1.b[0] |= RtoB(p->reg); + else + r->use1.b[0] |= FtoB(D_F0+p->reg); + } + + // Currently we never generate three register forms. + // If we do, this will need to change. + if(p->from3.type != D_NONE) + fatal("regopt not implemented for from3"); + + // Compute used register for to + bit = mkvar(r, &p->to); + if(info.flags & RightAddr) + setaddrs(bit); + if(info.flags & RightRead) + for(z=0; zuse2.b[z] |= bit.b[z]; + if(info.flags & RightWrite) + for(z=0; zset.b[z] |= bit.b[z]; + } + + for(i=0; iaddr) { + bit = blsh(i); + for(z=0; zaddr, v->etype, v->width, v->node, v->offset); + } + + if(debug['R'] && debug['v']) + dumpit("pass1", &firstr->f, 1); + + /* + * pass 2 + * find looping structure + */ + flowrpo(g); + + if(debug['R'] && debug['v']) + dumpit("pass2", &firstr->f, 1); + + /* + * pass 2.5 + * iterate propagating fat vardef covering forward + * r->act records vars with a VARDEF since the last CALL. + * (r->act will be reused in pass 5 for something else, + * but we'll be done with it by then.) + */ + active = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) { + r->f.active = 0; + r->act = zbits; + } + for(r = firstr; r != R; r = (Reg*)r->f.link) { + p = r->f.prog; + if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) { + active++; + walkvardef(p->to.node, r, active); + } + } + + /* + * pass 3 + * iterate propagating usage + * back until flow graph is complete + */ +loop1: + change = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) + r->f.active = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) + if(r->f.prog->as == ARET) + prop(r, zbits, zbits); +loop11: + /* pick up unreachable code */ + i = 0; + for(r = firstr; r != R; r = r1) { + r1 = (Reg*)r->f.link; + if(r1 && r1->f.active && !r->f.active) { + prop(r, zbits, zbits); + i = 1; + } + } + if(i) + goto loop11; + if(change) + goto loop1; + + if(debug['R'] && debug['v']) + dumpit("pass3", &firstr->f, 1); + + /* + * pass 4 + * iterate propagating register/variable synchrony + * forward until graph is complete + */ +loop2: + change = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) + r->f.active = 0; + synch(firstr, zbits); + if(change) + goto loop2; + + if(debug['R'] && debug['v']) + dumpit("pass4", &firstr->f, 1); + + /* + * pass 4.5 + * move register pseudo-variables into regu. + */ + for(r = firstr; r != R; r = (Reg*)r->f.link) { + r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS; + + r->set.b[0] &= ~REGBITS; + r->use1.b[0] &= ~REGBITS; + r->use2.b[0] &= ~REGBITS; + r->refbehind.b[0] &= ~REGBITS; + r->refahead.b[0] &= ~REGBITS; + r->calbehind.b[0] &= ~REGBITS; + r->calahead.b[0] &= ~REGBITS; + r->regdiff.b[0] &= ~REGBITS; + r->act.b[0] &= ~REGBITS; + } + + if(debug['R'] && debug['v']) + dumpit("pass4.5", &firstr->f, 1); + + /* + * pass 5 + * isolate regions + * calculate costs (paint1) + */ + r = firstr; + if(r) { + for(z=0; zrefahead.b[z] | r->calahead.b[z]) & + ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]); + if(bany(&bit) && !r->f.refset) { + // should never happen - all variables are preset + if(debug['w']) + print("%L: used and not set: %Q\n", r->f.prog->lineno, bit); + r->f.refset = 1; + } + } + for(r = firstr; r != R; r = (Reg*)r->f.link) + r->act = zbits; + rgp = region; + nregion = 0; + for(r = firstr; r != R; r = (Reg*)r->f.link) { + for(z=0; zset.b[z] & + ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]); + if(bany(&bit) && !r->f.refset) { + if(debug['w']) + print("%L: set and not used: %Q\n", r->f.prog->lineno, bit); + r->f.refset = 1; + excise(&r->f); + } + for(z=0; zact.b[z] | addrs.b[z]); + while(bany(&bit)) { + i = bnum(bit); + rgp->enter = r; + rgp->varno = i; + change = 0; + paint1(r, i); + biclr(&bit, i); + if(change <= 0) + continue; + rgp->cost = change; + nregion++; + if(nregion >= NRGN) { + if(debug['R'] && debug['v']) + print("too many regions\n"); + goto brk; + } + rgp++; + } + } +brk: + qsort(region, nregion, sizeof(region[0]), rcmp); + + if(debug['R'] && debug['v']) + dumpit("pass5", &firstr->f, 1); + + /* + * pass 6 + * determine used registers (paint2) + * replace code (paint3) + */ + rgp = region; + if(debug['R'] && debug['v']) + print("\nregisterizing\n"); + for(i=0; icost, rgp->varno, rgp->enter->f.prog->pc); + bit = blsh(rgp->varno); + usedreg = paint2(rgp->enter, rgp->varno, 0); + vreg = allreg(usedreg, rgp); + if(rgp->regno != 0) { + if(debug['R'] && debug['v']) { + Var *v; + + v = var + rgp->varno; + print("registerize %N+%lld (bit=%2d et=%2E) in %R usedreg=%llx vreg=%llx\n", + v->node, v->offset, rgp->varno, v->etype, rgp->regno, usedreg, vreg); + } + paint3(rgp->enter, rgp->varno, vreg, rgp->regno); + } + rgp++; + } + + /* + * free aux structures. peep allocates new ones. + */ + for(i=0; iopt = nil; + flowend(g); + firstr = R; + + if(debug['R'] && debug['v']) { + // Rebuild flow graph, since we inserted instructions + g = flowstart(firstp, sizeof(Reg)); + firstr = (Reg*)g->start; + dumpit("pass6", &firstr->f, 1); + flowend(g); + firstr = R; + } + + /* + * pass 7 + * peep-hole on basic block + */ + if(!debug['R'] || debug['P']) + peep(firstp); + + /* + * eliminate nops + */ + for(p=firstp; p!=P; p=p->link) { + while(p->link != P && p->link->as == ANOP) + p->link = p->link->link; + if(p->to.type == D_BRANCH) + while(p->to.u.branch != P && p->to.u.branch->as == ANOP) + p->to.u.branch = p->to.u.branch->link; + } + + if(debug['R']) { + if(ostats.ncvtreg || + ostats.nspill || + ostats.ndelmov || + ostats.nvar || + 0) + print("\nstats\n"); + + if(ostats.ncvtreg) + print(" %4d cvtreg\n", ostats.ncvtreg); + if(ostats.nspill) + print(" %4d spill\n", ostats.nspill); + if(ostats.ndelmov) + print(" %4d delmov\n", ostats.ndelmov); + if(ostats.nvar) + print(" %4d var\n", ostats.nvar); + + memset(&ostats, 0, sizeof(ostats)); + } + return; } +static void +walkvardef(Node *n, Reg *r, int active) +{ + Reg *r1, *r2; + int bn; + Var *v; + + for(r1=r; r1!=R; r1=(Reg*)r1->f.s1) { + if(r1->f.active == active) + break; + r1->f.active = active; + if(r1->f.prog->as == AVARKILL && r1->f.prog->to.node == n) + break; + for(v=n->opt; v!=nil; v=v->nextinnode) { + bn = v - var; + biset(&r1->act, bn); + } + if(r1->f.prog->as == ABL) + break; + } + + for(r2=r; r2!=r1; r2=(Reg*)r2->f.s1) + if(r2->f.s2 != nil) + walkvardef(n, (Reg*)r2->f.s2, active); +} + +/* + * add mov b,rn + * just after r + */ +void +addmove(Reg *r, int bn, int rn, int f) +{ + Prog *p, *p1, *p2; + Adr *a; + Var *v; + + p1 = mal(sizeof(*p1)); + *p1 = zprog; + p = r->f.prog; + + // If there's a stack fixup coming (ADD $n,R1 after BL newproc or BL deferproc), + // delay the load until after the fixup. + p2 = p->link; + if(p2 && p2->as == AADD && p2->to.reg == REGSP && p2->to.type == D_REG) + p = p2; + + p1->link = p->link; + p->link = p1; + p1->lineno = p->lineno; + + v = var + bn; + + a = &p1->to; + a->name = v->name; + a->node = v->node; + a->sym = linksym(v->node->sym); + a->offset = v->offset; + a->etype = v->etype; + a->type = D_OREG; + if(a->etype == TARRAY || a->sym == nil) + a->type = D_CONST; + + if(v->addr) + fatal("addmove: shouldn't be doing this %A\n", a); + + switch(v->etype) { + default: + print("What is this %E\n", v->etype); + + case TINT8: + p1->as = AMOVB; + break; + case TBOOL: + case TUINT8: +//print("movbu %E %d %S\n", v->etype, bn, v->sym); + p1->as = AMOVBZ; + break; + case TINT16: + p1->as = AMOVH; + break; + case TUINT16: + p1->as = AMOVHZ; + break; + case TINT32: + p1->as = AMOVW; + break; + case TUINT32: + case TPTR32: + p1->as = AMOVWZ; + break; + case TINT64: + case TUINT64: + case TPTR64: + p1->as = AMOVD; + break; + case TFLOAT32: + p1->as = AFMOVS; + break; + case TFLOAT64: + p1->as = AFMOVD; + break; + } + + p1->from.type = D_REG; + p1->from.reg = rn; + if(rn >= NREG) { + p1->from.type = D_FREG; + p1->from.reg = rn-NREG; + } + if(!f) { + p1->from = *a; + *a = zprog.from; + a->type = D_REG; + a->reg = rn; + if(rn >= NREG) { + a->type = D_FREG; + a->reg = rn-NREG; + } + if(v->etype == TUINT8 || v->etype == TBOOL) + p1->as = AMOVBZ; + if(v->etype == TUINT16) + p1->as = AMOVHZ; + } + if(debug['R']) + print("%P\t.a%P\n", p, p1); + ostats.nspill++; +} + +static int +overlap(int64 o1, int w1, int64 o2, int w2) +{ + int64 t1, t2; + + t1 = o1+w1; + t2 = o2+w2; + + if(!(t1 > o2 && t2 > o1)) + return 0; + + return 1; +} + +Bits +mkvar(Reg *r, Adr *a) +{ + USED(r); + Var *v; + int i, t, n, et, z, flag; + int64 w; + int64 o; + Bits bit; + Node *node; + + // mark registers used + t = a->type; + switch(t) { + default: + print("type %d %d %D\n", t, a->name, a); + goto none; + + case D_NONE: + goto none; + + case D_BRANCH: + case D_CONST: + case D_FCONST: + case D_SCONST: + case D_SPR: + case D_OREG: + break; + + case D_REG: + if(a->reg != NREG) { + bit = zbits; + bit.b[0] = RtoB(a->reg); + return bit; + } + break; + + case D_FREG: + if(a->reg != NREG) { + bit = zbits; + bit.b[0] = FtoB(D_F0+a->reg); + return bit; + } + break; + } + + switch(a->name) { + default: + goto none; + + case D_EXTERN: + case D_STATIC: + case D_AUTO: + case D_PARAM: + n = a->name; + break; + } + + node = a->node; + if(node == N || node->op != ONAME || node->orig == N) + goto none; + node = node->orig; + if(node->orig != node) + fatal("%D: bad node", a); + if(node->sym == S || node->sym->name[0] == '.') + goto none; + et = a->etype; + o = a->offset; + w = a->width; + if(w < 0) + fatal("bad width %lld for %D", w, a); + + flag = 0; + for(i=0; inode == node && v->name == n) { + if(v->offset == o) + if(v->etype == et) + if(v->width == w) + return blsh(i); + + // if they overlap, disable both + if(overlap(v->offset, v->width, o, w)) { + v->addr = 1; + flag = 1; + } + } + } + + switch(et) { + case 0: + case TFUNC: + goto none; + } + + if(nvar >= NVAR) { + if(debug['w'] > 1 && node != N) + fatal("variable not optimized: %#N", node); + + // If we're not tracking a word in a variable, mark the rest as + // having its address taken, so that we keep the whole thing + // live at all calls. otherwise we might optimize away part of + // a variable but not all of it. + for(i=0; inode == node) + v->addr = 1; + } + goto none; + } + + i = nvar; + nvar++; + v = var+i; + v->offset = o; + v->name = n; + v->etype = et; + v->width = w; + v->addr = flag; // funny punning + v->node = node; + + // node->opt is the head of a linked list + // of Vars within the given Node, so that + // we can start at a Var and find all the other + // Vars in the same Go variable. + v->nextinnode = node->opt; + node->opt = v; + + bit = blsh(i); + if(n == D_EXTERN || n == D_STATIC) + for(z=0; zclass == PPARAM) + for(z=0; zclass == PPARAMOUT) + for(z=0; zaddrtaken) + v->addr = 1; + + // Disable registerization for globals, because: + // (1) we might panic at any time and we want the recovery code + // to see the latest values (issue 1304). + // (2) we don't know what pointers might point at them and we want + // loads via those pointers to see updated values and vice versa (issue 7995). + // + // Disable registerization for results if using defer, because the deferred func + // might recover and return, causing the current values to be used. + if(node->class == PEXTERN || (hasdefer && node->class == PPARAMOUT)) + v->addr = 1; + + if(debug['R']) + print("bit=%2d et=%2E w=%lld+%lld %#N %D flag=%d\n", i, et, o, w, node, a, v->addr); + ostats.nvar++; + + return bit; + +none: + return zbits; +} + +void +prop(Reg *r, Bits ref, Bits cal) +{ + Reg *r1, *r2; + int z, i, j; + Var *v, *v1; + + for(r1 = r; r1 != R; r1 = (Reg*)r1->f.p1) { + for(z=0; 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->f.prog->as) { + case ABL: + if(noreturn(r1->f.prog)) + break; + + // Mark all input variables (ivar) as used, because that's what the + // liveness bitmaps say. The liveness bitmaps say that so that a + // panic will not show stale values in the parameter dump. + // Mark variables with a recent VARDEF (r1->act) as used, + // so that the optimizer flushes initializations to memory, + // so that if a garbage collection happens during this CALL, + // the collector will see initialized memory. Again this is to + // match what the liveness bitmaps say. + for(z=0; zact.b[z]; + ref.b[z] = 0; + } + + // cal.b is the current approximation of what's live across the call. + // Every bit in cal.b is a single stack word. For each such word, + // find all the other tracked stack words in the same Go variable + // (struct/slice/string/interface) and mark them live too. + // This is necessary because the liveness analysis for the garbage + // collector works at variable granularity, not at word granularity. + // It is fundamental for slice/string/interface: the garbage collector + // needs the whole value, not just some of the words, in order to + // interpret the other bits correctly. Specifically, slice needs a consistent + // ptr and cap, string needs a consistent ptr and len, and interface + // needs a consistent type word and data word. + for(z=0; z= nvar || ((cal.b[z]>>i)&1) == 0) + continue; + v = var+z*64+i; + if(v->node->opt == nil) // v represents fixed register, not Go variable + continue; + + // v->node->opt is the head of a linked list of Vars + // corresponding to tracked words from the Go variable v->node. + // Walk the list and set all the bits. + // For a large struct this could end up being quadratic: + // after the first setting, the outer loop (for z, i) would see a 1 bit + // for all of the remaining words in the struct, and for each such + // word would go through and turn on all the bits again. + // To avoid the quadratic behavior, we only turn on the bits if + // v is the head of the list or if the head's bit is not yet turned on. + // This will set the bits at most twice, keeping the overall loop linear. + v1 = v->node->opt; + j = v1 - var; + if(v == v1 || !btest(&cal, j)) { + for(; v1 != nil; v1 = v1->nextinnode) { + j = v1 - var; + biset(&cal, j); + } + } + } + } + break; + + case ATEXT: + for(z=0; 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->f.active) + break; + r1->f.active = 1; + } + for(; r != r1; r = (Reg*)r->f.p1) + for(r2 = (Reg*)r->f.p2; r2 != R; r2 = (Reg*)r2->f.p2link) + prop(r2, r->refbehind, r->calbehind); +} + +void +synch(Reg *r, Bits dif) +{ + Reg *r1; + int z; + + for(r1 = r; r1 != R; r1 = (Reg*)r1->f.s1) { + for(z=0; 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->f.active) + break; + r1->f.active = 1; + for(z=0; zcalbehind.b[z] & r1->calahead.b[z]); + if(r1->f.s2 != nil) + synch((Reg*)r1->f.s2, dif); + } +} + +uint64 +allreg(uint64 b, Rgn *r) +{ + Var *v; + int i; + + v = var + r->varno; + r->regno = 0; + switch(v->etype) { + + default: + fatal("unknown etype %d/%E", bitno(b), v->etype); + break; + + case TINT8: + case TUINT8: + case TINT16: + case TUINT16: + case TINT32: + case TUINT32: + case TINT64: + case TUINT64: + case TINT: + case TUINT: + case TUINTPTR: + case TBOOL: + case TPTR32: + case TPTR64: + i = BtoR(~b); + if(i && r->cost > 0) { + r->regno = i; + return RtoB(i); + } + break; + + case TFLOAT32: + case TFLOAT64: + i = BtoF(~b); + if(i && r->cost > 0) { + r->regno = i; + return FtoB(i); + } + break; + } + return 0; +} + +void +paint1(Reg *r, int bn) +{ + Reg *r1; + int z; + uint64 bb; + + z = bn/64; + bb = 1LL<<(bn%64); + if(r->act.b[z] & bb) + return; + for(;;) { + if(!(r->refbehind.b[z] & bb)) + break; + r1 = (Reg*)r->f.p1; + if(r1 == R) + break; + if(!(r1->refahead.b[z] & bb)) + break; + if(r1->act.b[z] & bb) + break; + r = r1; + } + + if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) { + change -= CLOAD * r->f.loop; + } + for(;;) { + r->act.b[z] |= bb; + + if(r->f.prog->as != ANOP) { // don't give credit for NOPs + if(r->use1.b[z] & bb) + change += CREF * r->f.loop; + if((r->use2.b[z]|r->set.b[z]) & bb) + change += CREF * r->f.loop; + } + + if(STORE(r) & r->regdiff.b[z] & bb) { + change -= CLOAD * r->f.loop; + } + + if(r->refbehind.b[z] & bb) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) + if(r1->refahead.b[z] & bb) + paint1(r1, bn); + + if(!(r->refahead.b[z] & bb)) + break; + r1 = (Reg*)r->f.s2; + if(r1 != R) + if(r1->refbehind.b[z] & bb) + paint1(r1, bn); + r = (Reg*)r->f.s1; + if(r == R) + break; + if(r->act.b[z] & bb) + break; + if(!(r->refbehind.b[z] & bb)) + break; + } +} + +uint64 +paint2(Reg *r, int bn, int depth) +{ + Reg *r1; + int z; + uint64 bb, vreg; + + z = bn/64; + bb = 1LL << (bn%64); + vreg = regbits; + if(!(r->act.b[z] & bb)) + return vreg; + for(;;) { + if(!(r->refbehind.b[z] & bb)) + break; + r1 = (Reg*)r->f.p1; + if(r1 == R) + break; + if(!(r1->refahead.b[z] & bb)) + break; + if(!(r1->act.b[z] & bb)) + break; + r = r1; + } + for(;;) { + if(debug['R'] && debug['v']) + print(" paint2 %d %P\n", depth, r->f.prog); + + r->act.b[z] &= ~bb; + + vreg |= r->regu; + + if(r->refbehind.b[z] & bb) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) + if(r1->refahead.b[z] & bb) + vreg |= paint2(r1, bn, depth+1); + + if(!(r->refahead.b[z] & bb)) + break; + r1 = (Reg*)r->f.s2; + if(r1 != R) + if(r1->refbehind.b[z] & bb) + vreg |= paint2(r1, bn, depth+1); + r = (Reg*)r->f.s1; + if(r == R) + break; + if(!(r->act.b[z] & bb)) + break; + if(!(r->refbehind.b[z] & bb)) + break; + } + return vreg; +} + +void +paint3(Reg *r, int bn, uint64 rb, int rn) +{ + Reg *r1; + Prog *p; + int z; + uint64 bb; + + z = bn/64; + bb = 1LL << (bn%64); + if(r->act.b[z] & bb) + return; + for(;;) { + if(!(r->refbehind.b[z] & bb)) + break; + r1 = (Reg*)r->f.p1; + if(r1 == R) + break; + if(!(r1->refahead.b[z] & bb)) + break; + if(r1->act.b[z] & bb) + break; + r = r1; + } + + if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) + addmove(r, bn, rn, 0); + for(;;) { + r->act.b[z] |= bb; + p = r->f.prog; + + if(r->use1.b[z] & bb) { + if(debug['R'] && debug['v']) + print("%P", p); + addreg(&p->from, rn); + if(debug['R'] && debug['v']) + print(" ===change== %P\n", p); + } + if((r->use2.b[z]|r->set.b[z]) & bb) { + if(debug['R'] && debug['v']) + print("%P", p); + addreg(&p->to, rn); + if(debug['R'] && debug['v']) + print(" ===change== %P\n", p); + } + + if(STORE(r) & r->regdiff.b[z] & bb) + addmove(r, bn, rn, 1); + r->regu |= rb; + + if(r->refbehind.b[z] & bb) + for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link) + if(r1->refahead.b[z] & bb) + paint3(r1, bn, rb, rn); + + if(!(r->refahead.b[z] & bb)) + break; + r1 = (Reg*)r->f.s2; + if(r1 != R) + if(r1->refbehind.b[z] & bb) + paint3(r1, bn, rb, rn); + r = (Reg*)r->f.s1; + if(r == R) + break; + if(r->act.b[z] & bb) + break; + if(!(r->refbehind.b[z] & bb)) + break; + } +} + +void +addreg(Adr *a, int rn) +{ + a->sym = nil; + a->node = nil; + a->name = D_NONE; + a->type = D_REG; + a->reg = rn; + if(rn >= NREG) { + a->type = D_FREG; + a->reg = rn-NREG; + } + + ostats.ncvtreg++; +} + /* * track register variables including external registers: * bit reg @@ -56,7 +1239,7 @@ regopt(Prog *p) uint64 RtoB(int r) { - if(r >= D_R0 && r <= D_R0+31) + if(r > D_R0 && r <= D_R0+31) return 1ULL << (r - D_R0); return 0; } @@ -64,7 +1247,7 @@ RtoB(int r) int BtoR(uint64 b) { - b &= 0xffffffff; + b &= 0xffffffffull; if(b == 0) return 0; return bitno(b) + D_R0; @@ -139,6 +1322,7 @@ void dumpit(char *str, Flow *r0, int isreg) { Flow *r, *r1; + int s1v, s2v; print("\n%s\n", str); for(r = r0; r != nil; r = r->link) { @@ -150,12 +1334,16 @@ dumpit(char *str, Flow *r0, int isreg) print(" %.4ud", (int)r1->prog->pc); print("\n"); } -// r1 = r->s1; -// if(r1 != R) { -// print(" succ:"); -// for(; r1 != R; r1 = r1->s1) -// print(" %.4ud", (int)r1->prog->pc); -// print("\n"); -// } + // If at least one successor is "interesting", print both + s1v = (r->s1 != nil) && (r->s1->prog != r->prog->link); + s2v = (r->s2 != nil) && (r->s2->prog != r->prog->link); + if(s1v || s2v) { + print(" succ:"); + if(r->s1 != nil) + print(" %.4ud", (int)r->s1->prog->pc); + if(r->s2 != nil) + print(" %.4ud", (int)r->s2->prog->pc); + print("\n"); + } } }