[dev.garbage] all: merge dev.power64 (5ad5e85cfb99) into dev.garbage

The goal here is to get the big-endian fixes so that
in some upcoming code movement for write barriers
I don't make them unmergeable.

LGTM=rlh
R=rlh
CC=golang-codereviews
https://golang.org/cl/166890043
This commit is contained in:
Russ Cox 2014-10-29 12:25:24 -04:00
commit d6f4e5020b
158 changed files with 39414 additions and 2818 deletions

View file

@ -2,13 +2,13 @@ syntax:glob
.DS_Store .DS_Store
.git .git
.gitignore .gitignore
*.[568ao] *.[5689ao]
*.a[568o] *.a[5689o]
*.so *.so
*.pyc *.pyc
._* ._*
.nfs.* .nfs.*
[568a].out [5689a].out
*~ *~
*.orig *.orig
*.rej *.rej

View file

@ -62,9 +62,9 @@ struct Addr
short type; short type;
uint8 index; uint8 index;
int8 scale; int8 scale;
int8 reg; // for 5l int8 reg; // for 5l, 9l
int8 name; // for 5l int8 name; // for 5l, 9l
int8 class; // for 5l int8 class; // for 5l, 9l
uint8 etype; // for 5g, 6g, 8g uint8 etype; // for 5g, 6g, 8g
int32 offset2; // for 5l, 8l int32 offset2; // for 5l, 8l
struct Node* node; // for 5g, 6g, 8g struct Node* node; // for 5g, 6g, 8g
@ -89,9 +89,10 @@ struct Prog
int32 lineno; int32 lineno;
Prog* link; Prog* link;
short as; short as;
uchar reg; // arm only uchar reg; // arm, power64 only
uchar scond; // arm only uchar scond; // arm only
Addr from; Addr from;
Addr from3; // power64 only, fma and rlwm
Addr to; Addr to;
// for 5g, 6g, 8g internal use // for 5g, 6g, 8g internal use
@ -103,11 +104,11 @@ struct Prog
Prog* comefrom; // 6l, 8l Prog* comefrom; // 6l, 8l
Prog* pcrel; // 5l Prog* pcrel; // 5l
int32 spadj; int32 spadj;
uchar mark; uint16 mark;
uint16 optab; // 5l, 9l
uchar back; // 6l, 8l uchar back; // 6l, 8l
uchar ft; /* 6l, 8l oclass cache */ uchar ft; /* 6l, 8l oclass cache */
uchar tt; // 6l, 8l uchar tt; // 6l, 8l
uint16 optab; // 5l
uchar isize; // 6l, 8l uchar isize; // 6l, 8l
char width; /* fake for DATA */ char width; /* fake for DATA */
@ -233,10 +234,12 @@ enum
enum enum
{ {
R_ADDR = 1, R_ADDR = 1,
R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power
R_SIZE, R_SIZE,
R_CALL, // relocation for direct PC-relative call R_CALL, // relocation for direct PC-relative call
R_CALLARM, // relocation for ARM direct call R_CALLARM, // relocation for ARM direct call
R_CALLIND, // marker for indirect call (no actual relocating necessary) R_CALLIND, // marker for indirect call (no actual relocating necessary)
R_CALLPOWER, // relocation for Power direct call
R_CONST, R_CONST,
R_PCREL, R_PCREL,
R_TLS, R_TLS,
@ -529,6 +532,9 @@ void span6(Link *ctxt, LSym *s);
// asm8.c // asm8.c
void span8(Link *ctxt, LSym *s); void span8(Link *ctxt, LSym *s);
// asm9.c
void span9(Link *ctxt, LSym *s);
// data.c // data.c
vlong addaddr(Link *ctxt, LSym *s, LSym *t); vlong addaddr(Link *ctxt, LSym *s, LSym *t);
vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add); vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add);
@ -576,10 +582,11 @@ Prog* copyp(Link*, Prog*);
Prog* appendp(Link*, Prog*); Prog* appendp(Link*, Prog*);
vlong atolwhex(char*); vlong atolwhex(char*);
// list[568].c // list[5689].c
void listinit5(void); void listinit5(void);
void listinit6(void); void listinit6(void);
void listinit8(void); void listinit8(void);
void listinit9(void);
// obj.c // obj.c
int linklinefmt(Link *ctxt, Fmt *fp); int linklinefmt(Link *ctxt, Fmt *fp);
@ -611,20 +618,24 @@ char* headstr(int);
extern char* anames5[]; extern char* anames5[];
extern char* anames6[]; extern char* anames6[];
extern char* anames8[]; extern char* anames8[];
extern char* anames9[];
extern char* cnames5[]; extern char* cnames5[];
extern char* cnames9[];
extern LinkArch link386; extern LinkArch link386;
extern LinkArch linkamd64; extern LinkArch linkamd64;
extern LinkArch linkamd64p32; extern LinkArch linkamd64p32;
extern LinkArch linkarm; extern LinkArch linkarm;
extern LinkArch linkpower64;
extern LinkArch linkpower64le;
#pragma varargck type "A" int #pragma varargck type "A" int
#pragma varargck type "D" Addr* #pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr* #pragma varargck type "lD" Addr*
#pragma varargck type "P" Prog* #pragma varargck type "P" Prog*
#pragma varargck type "R" int #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. // TODO(ality): remove this workaround.
// It's here because Pconv in liblink/list?.c references %L. // It's here because Pconv in liblink/list?.c references %L.

View file

@ -1 +1,2 @@
defaultcc: golang-codereviews@googlegroups.com defaultcc: golang-codereviews@googlegroups.com
contributors: http://go.googlecode.com/hg/CONTRIBUTORS

View file

@ -3603,11 +3603,17 @@ class MercurialVCS(VersionControlSystem):
if use_hg_shell: if use_hg_shell:
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True) base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True)
else: else:
base_content = str(self.repo[base_rev][oldrelpath].data()) try:
base_content = str(self.repo[base_rev][oldrelpath].data())
except Exception:
pass
is_binary = "\0" in base_content # Mercurial's heuristic is_binary = "\0" in base_content # Mercurial's heuristic
if status != "R": if status != "R":
new_content = open(relpath, "rb").read() try:
is_binary = is_binary or "\0" in new_content new_content = open(relpath, "rb").read()
is_binary = is_binary or "\0" in new_content
except Exception:
pass
if is_binary and base_content and use_hg_shell: if is_binary and base_content and use_hg_shell:
# Fetch again without converting newlines # Fetch again without converting newlines
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],

View file

@ -67,6 +67,7 @@ struct Sym
int32 value; int32 value;
ushort type; ushort type;
char *name; char *name;
char* labelname;
char sym; char sym;
}; };
#define S ((Sym*)0) #define S ((Sym*)0)
@ -136,6 +137,8 @@ void newio(void);
void newfile(char*, int); void newfile(char*, int);
Sym* slookup(char*); Sym* slookup(char*);
Sym* lookup(void); Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*); void syminit(Sym*);
int32 yylex(void); int32 yylex(void);
int getc(void); int getc(void);

View file

@ -73,15 +73,11 @@ prog:
line line
line: line:
LLAB ':' LNAME ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
{ {
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB; $1->type = LLAB;
$1->value = pc; $1->value = pc;
} }
@ -218,18 +214,21 @@ inst:
*/ */
| LTYPEB name ',' imm | LTYPEB name ',' imm
{ {
settext($2.sym);
$4.type = D_CONST2; $4.type = D_CONST2;
$4.offset2 = ArgsSizeUnknown; $4.offset2 = ArgsSizeUnknown;
outcode($1, Always, &$2, 0, &$4); outcode($1, Always, &$2, 0, &$4);
} }
| LTYPEB name ',' con ',' imm | LTYPEB name ',' con ',' imm
{ {
settext($2.sym);
$6.type = D_CONST2; $6.type = D_CONST2;
$6.offset2 = ArgsSizeUnknown; $6.offset2 = ArgsSizeUnknown;
outcode($1, Always, &$2, $4, &$6); outcode($1, Always, &$2, $4, &$6);
} }
| LTYPEB name ',' con ',' imm '-' con | LTYPEB name ',' con ',' imm '-' con
{ {
settext($2.sym);
$6.type = D_CONST2; $6.type = D_CONST2;
$6.offset2 = $8; $6.offset2 = $8;
outcode($1, Always, &$2, $4, &$6); outcode($1, Always, &$2, $4, &$6);
@ -373,15 +372,10 @@ rel:
} }
| LNAME offset | LNAME offset
{ {
$1 = labellookup($1);
$$ = nullgen; $$ = nullgen;
if(pass == 2) if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->name); yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
$$.type = D_BRANCH; $$.type = D_BRANCH;
$$.offset = $1->value + $2; $$.offset = $1->value + $2;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,24 @@
/* A Bison parser, made by GNU Bison 2.7.12-4996. */ /* A Bison parser, made by GNU Bison 2.3. */
/* Bison interface for Yacc-like parsers in C /* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. 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
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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation; either version 2, or (at your option)
(at your option) any later version. any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains /* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work 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 special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public Bison output files to be licensed under the GNU General Public
License without this special exception. License without this special exception.
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ 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. */ /* Tokens. */
#ifndef YYTOKENTYPE #ifndef YYTOKENTYPE
# define YYTOKENTYPE # define YYTOKENTYPE
@ -148,41 +141,24 @@ extern int yydebug;
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE typedef union YYSTYPE
{
/* Line 2053 of yacc.c */
#line 39 "a.y" #line 39 "a.y"
{
Sym *sym; Sym *sym;
int32 lval; int32 lval;
double dval; double dval;
char sval[8]; char sval[8];
Addr addr; Addr addr;
}
/* Line 1529 of yacc.c. */
/* Line 2053 of yacc.c */ #line 157 "y.tab.h"
#line 166 "y.tab.h" YYSTYPE;
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif #endif
extern YYSTYPE yylval; 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 */

View file

@ -70,6 +70,7 @@ struct Sym
vlong value; vlong value;
ushort type; ushort type;
char *name; char *name;
char* labelname;
char sym; char sym;
}; };
#define S ((Sym*)0) #define S ((Sym*)0)
@ -148,6 +149,8 @@ void newio(void);
void newfile(char*, int); void newfile(char*, int);
Sym* slookup(char*); Sym* slookup(char*);
Sym* lookup(void); Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*); void syminit(Sym*);
int32 yylex(void); int32 yylex(void);
int getc(void); int getc(void);

View file

@ -71,15 +71,11 @@ prog:
line line
line: line:
LLAB ':' LNAME ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
{ {
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
$1->type = LLAB; $1->type = LLAB;
$1->value = pc; $1->value = pc;
} }
@ -197,11 +193,13 @@ spec1: /* DATA */
spec2: /* TEXT */ spec2: /* TEXT */
mem ',' imm2 mem ',' imm2
{ {
settext($1.sym);
$$.from = $1; $$.from = $1;
$$.to = $3; $$.to = $3;
} }
| mem ',' con ',' imm2 | mem ',' con ',' imm2
{ {
settext($1.sym);
$$.from = $1; $$.from = $1;
$$.from.scale = $3; $$.from.scale = $3;
$$.to = $5; $$.to = $5;
@ -363,15 +361,10 @@ rel:
} }
| LNAME offset | LNAME offset
{ {
$1 = labellookup($1);
$$ = nullgen; $$ = nullgen;
if(pass == 2) if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->name); yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
$$.type = D_BRANCH; $$.type = D_BRANCH;
$$.offset = $1->value + $2; $$.offset = $1->value + $2;
} }

File diff suppressed because it is too large Load diff

View file

@ -70,6 +70,7 @@ struct Sym
int32 value; int32 value;
ushort type; ushort type;
char *name; char *name;
char* labelname;
char sym; char sym;
}; };
#define S ((Sym*)0) #define S ((Sym*)0)
@ -148,6 +149,8 @@ void newio(void);
void newfile(char*, int); void newfile(char*, int);
Sym* slookup(char*); Sym* slookup(char*);
Sym* lookup(void); Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*); void syminit(Sym*);
int32 yylex(void); int32 yylex(void);
int getc(void); int getc(void);

View file

@ -74,15 +74,11 @@ prog:
line line
line: line:
LLAB ':' LNAME ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
{ {
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB; $1->type = LLAB;
$1->value = pc; $1->value = pc;
} }
@ -199,11 +195,13 @@ spec1: /* DATA */
spec2: /* TEXT */ spec2: /* TEXT */
mem ',' imm2 mem ',' imm2
{ {
settext($1.sym);
$$.from = $1; $$.from = $1;
$$.to = $3; $$.to = $3;
} }
| mem ',' con ',' imm2 | mem ',' con ',' imm2
{ {
settext($1.sym);
$$.from = $1; $$.from = $1;
$$.from.scale = $3; $$.from.scale = $3;
$$.to = $5; $$.to = $5;
@ -362,15 +360,10 @@ rel:
} }
| LNAME offset | LNAME offset
{ {
$1 = labellookup($1);
$$ = nullgen; $$ = nullgen;
if(pass == 2) if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->name); yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
$$.type = D_BRANCH; $$.type = D_BRANCH;
$$.offset = $1->value + $2; $$.offset = $1->value + $2;
} }

File diff suppressed because it is too large Load diff

10
src/cmd/9a/Makefile Normal file
View file

@ -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

170
src/cmd/9a/a.h Normal file
View file

@ -0,0 +1,170 @@
// cmd/9a/a.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <bio.h>
#include <link.h>
#include "../9l/9.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
#undef getc
#undef ungetc
#undef BUFSIZ
#define getc ccgetc
#define ungetc ccungetc
typedef struct Sym Sym;
typedef struct Io Io;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 8192
#define BUFSIZ 8192
#define HISTSZ 20
#define NINCLUDE 10
#define NHUNK 10000
#ifndef EOF
#define EOF (-1)
#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
char* macro;
vlong value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
};
EXTERN int debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char** Dlist;
EXTERN int nDlist;
EXTERN int newflag;
EXTERN char* hunk;
EXTERN char** include;
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN int32 lineno;
EXTERN int nerrors;
EXTERN int32 nhunk;
EXTERN int nosched;
EXTERN int ninclude;
EXTERN int32 nsymb;
EXTERN Addr nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN int32 pc;
EXTERN int peekc;
EXTERN int sym;
EXTERN char* symb;
EXTERN int thechar;
EXTERN char* thestring;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
void* alloc(int32);
void* allocn(void*, int32, int32);
void ensuresymb(int32);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void pinit(char*);
void cclean(void);
void outcode(int, Addr*, int, Addr*);
void outgcode(int, Addr*, int, Addr*, Addr*);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void macprag(void);
void maclin(void);
void macif(int);
void macend(void);
void dodefine(char*);
void prfile(int32);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);

991
src/cmd/9a/a.y Normal file
View file

@ -0,0 +1,991 @@
// cmd/9a/a.y from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
%{
#include <u.h>
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
#include "../../runtime/funcdata.h"
%}
%union
{
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
}
%left '|'
%left '^'
%left '&'
%left '<' '>'
%left '+' '-'
%left '*' '/' '%'
%token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
%token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
%token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
%token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
%token <lval> LREG LFREG LR LCR LF LFPSCR
%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR
%token <lval> LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
%token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
%token <dval> LFCONST
%token <sval> LSCONST
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset sreg
%type <addr> addr rreg regaddr name creg freg xlreg lr ctr
%type <addr> imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
%%
prog:
| prog line
line:
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB;
$1->value = pc;
}
line
| LNAME '=' expr ';'
{
$1->type = LVAR;
$1->value = $3;
}
| LVAR '=' expr ';'
{
if($1->value != $3)
yyerror("redeclaration of %s", $1->name);
$1->value = $3;
}
| LSCHED ';'
{
nosched = $1;
}
| ';'
| inst ';'
| error ';'
inst:
/*
* load ints and bytes
*/
LMOVW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW addr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB addr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
/*
* load floats
*/
| LFMOV addr ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV regaddr ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV fimm ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV freg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV freg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
/*
* store ints and bytes
*/
| LMOVW rreg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB rreg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
/*
* store floats
*/
| LMOVW freg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW freg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
/*
* floating point status
*/
| LMOVW fpscr ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW freg ',' fpscr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW freg ',' imm ',' fpscr
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LMOVW fpscr ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW imm ',' fpscrf
{
outcode($1, &$2, NREG, &$4);
}
| LMTFSB imm ',' con
{
outcode($1, &$2, $4, &nullgen);
}
/*
* field moves (mtcrf)
*/
| LMOVW rreg ',' imm ',' lcr
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LMOVW rreg ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' lcr
{
outcode($1, &$2, NREG, &$4);
}
/*
* integer operations
* logical instructions
* shift instructions
* unary instructions
*/
| LADDW rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LADDW imm ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LADDW rreg ',' imm ',' rreg
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LADDW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LADDW imm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LLOGW rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LLOGW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LSHW rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LSHW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LSHW imm ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LSHW imm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LABS rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LABS rreg
{
outcode($1, &$2, NREG, &$2);
}
/*
* multiply-accumulate
*/
| LMA rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
/*
* move immediate: macro for cau+or, addi, addis, and other combinations
*/
| LMOVW imm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW ximm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
/*
* condition register operations
*/
| LCROP cbit ',' cbit
{
outcode($1, &$2, $4.reg, &$4);
}
| LCROP cbit ',' con ',' cbit
{
outcode($1, &$2, $4, &$6);
}
/*
* condition register moves
* move from machine state register
*/
| LMOVW creg ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW psr ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW lcr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW psr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW xlreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' xlreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW creg ',' psr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' psr
{
outcode($1, &$2, NREG, &$4);
}
/*
* branch, branch conditional
* branch conditional register
* branch conditional to count register
*/
| LBRA rel
{
outcode($1, &nullgen, NREG, &$2);
}
| LBRA addr
{
outcode($1, &nullgen, NREG, &$2);
}
| LBRA '(' xlreg ')'
{
outcode($1, &nullgen, NREG, &$3);
}
| LBRA ',' rel
{
outcode($1, &nullgen, NREG, &$3);
}
| LBRA ',' addr
{
outcode($1, &nullgen, NREG, &$3);
}
| LBRA ',' '(' xlreg ')'
{
outcode($1, &nullgen, NREG, &$4);
}
| LBRA creg ',' rel
{
outcode($1, &$2, NREG, &$4);
}
| LBRA creg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LBRA creg ',' '(' xlreg ')'
{
outcode($1, &$2, NREG, &$5);
}
| LBRA con ',' rel
{
outcode($1, &nullgen, $2, &$4);
}
| LBRA con ',' addr
{
outcode($1, &nullgen, $2, &$4);
}
| LBRA con ',' '(' xlreg ')'
{
outcode($1, &nullgen, $2, &$5);
}
| LBRA con ',' con ',' rel
{
Addr g;
g = nullgen;
g.type = D_CONST;
g.offset = $2;
outcode($1, &g, $4, &$6);
}
| LBRA con ',' con ',' addr
{
Addr g;
g = nullgen;
g.type = D_CONST;
g.offset = $2;
outcode($1, &g, $4, &$6);
}
| LBRA con ',' con ',' '(' xlreg ')'
{
Addr g;
g = nullgen;
g.type = D_CONST;
g.offset = $2;
outcode($1, &g, $4, &$7);
}
/*
* conditional trap
*/
| LTRAP rreg ',' sreg
{
outcode($1, &$2, $4, &nullgen);
}
| LTRAP imm ',' sreg
{
outcode($1, &$2, $4, &nullgen);
}
| LTRAP rreg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LTRAP comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
/*
* floating point operate
*/
| LFCONV freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFADD freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFADD freg ',' freg ',' freg
{
outcode($1, &$2, $4.reg, &$6);
}
| LFMA freg ',' freg ',' freg ',' freg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LFCMP freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFCMP freg ',' freg ',' creg
{
outcode($1, &$2, $6.reg, &$4);
}
/*
* CMP
*/
| LCMP rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LCMP rreg ',' imm
{
outcode($1, &$2, NREG, &$4);
}
| LCMP rreg ',' rreg ',' creg
{
outcode($1, &$2, $6.reg, &$4);
}
| LCMP rreg ',' imm ',' creg
{
outcode($1, &$2, $6.reg, &$4);
}
/*
* rotate and mask
*/
| LRLWM imm ',' rreg ',' imm ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LRLWM imm ',' rreg ',' mask ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LRLWM rreg ',' rreg ',' imm ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LRLWM rreg ',' rreg ',' mask ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
/*
* load/store multiple
*/
| LMOVMW addr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVMW rreg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
/*
* various indexed load/store
* indexed unary (eg, cache clear)
*/
| LXLD regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LXLD regaddr ',' imm ',' rreg
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LXST rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
| LXST rreg ',' imm ',' regaddr
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LXMV regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LXMV rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
| LXOP regaddr
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* NOP
*/
| LNOP comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
| LNOP rreg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LNOP freg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LNOP ',' rreg
{
outcode($1, &nullgen, NREG, &$3);
}
| LNOP ',' freg
{
outcode($1, &nullgen, NREG, &$3);
}
| LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* word
*/
| LWORD imm comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LWORD ximm comma
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* PCDATA
*/
| LPCDAT imm ',' imm
{
if($2.type != D_CONST || $4.type != D_CONST)
yyerror("arguments to PCDATA must be integer constants");
outcode($1, &$2, NREG, &$4);
}
/*
* FUNCDATA
*/
| LFUNCDAT imm ',' addr
{
if($2.type != D_CONST)
yyerror("index for FUNCDATA must be integer constant");
if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
yyerror("value for FUNCDATA must be symbol reference");
outcode($1, &$2, NREG, &$4);
}
/*
* END
*/
| LEND comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
/*
* TEXT/GLOBL
*/
| LTEXT name ',' imm
{
settext($2.sym);
outcode($1, &$2, NREG, &$4);
}
| LTEXT name ',' con ',' imm
{
settext($2.sym);
$6.offset &= 0xffffffffull;
$6.offset |= (vlong)ArgsSizeUnknown << 32;
outcode($1, &$2, $4, &$6);
}
| LTEXT name ',' con ',' imm '-' con
{
settext($2.sym);
$6.offset &= 0xffffffffull;
$6.offset |= ($8 & 0xffffffffull) << 32;
outcode($1, &$2, $4, &$6);
}
/*
* DATA
*/
| LDATA name '/' con ',' imm
{
outcode($1, &$2, $4, &$6);
}
| LDATA name '/' con ',' ximm
{
outcode($1, &$2, $4, &$6);
}
| LDATA name '/' con ',' fimm
{
outcode($1, &$2, $4, &$6);
}
/*
* RETURN
*/
| LRETRN comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
rel:
con '(' LPC ')'
{
$$ = nullgen;
$$.type = D_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
{
$1 = labellookup($1);
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $1->value + $2;
}
rreg:
sreg
{
$$ = nullgen;
$$.type = D_REG;
$$.reg = $1;
}
xlreg:
lr
| ctr
lr:
LLR
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
lcr:
LCR
{
$$ = nullgen;
$$.type = D_CREG;
$$.reg = NREG; /* whole register */
}
ctr:
LCTR
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
msr:
LMSR
{
$$ = nullgen;
$$.type = D_MSR;
}
psr:
LSPREG
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
| LSPR '(' con ')'
{
$$ = nullgen;
$$.type = $1;
$$.offset = $3;
}
| msr
fpscr:
LFPSCR
{
$$ = nullgen;
$$.type = D_FPSCR;
$$.reg = NREG;
}
fpscrf:
LFPSCR '(' con ')'
{
$$ = nullgen;
$$.type = D_FPSCR;
$$.reg = $3;
}
freg:
LFREG
{
$$ = nullgen;
$$.type = D_FREG;
$$.reg = $1;
}
| LF '(' con ')'
{
$$ = nullgen;
$$.type = D_FREG;
$$.reg = $3;
}
creg:
LCREG
{
$$ = nullgen;
$$.type = D_CREG;
$$.reg = $1;
}
| LCR '(' con ')'
{
$$ = nullgen;
$$.type = D_CREG;
$$.reg = $3;
}
cbit: con
{
$$ = nullgen;
$$.type = D_REG;
$$.reg = $1;
}
mask:
con ',' con
{
int mb, me;
uint32 v;
$$ = nullgen;
$$.type = D_CONST;
mb = $1;
me = $3;
if(mb < 0 || mb > 31 || me < 0 || me > 31){
yyerror("illegal mask start/end value(s)");
mb = me = 0;
}
if(mb <= me)
v = ((uint32)~0L>>mb) & (~0L<<(31-me));
else
v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
$$.offset = v;
}
ximm:
'$' addr
{
$$ = $2;
$$.type = D_CONST;
}
| '$' LSCONST
{
$$ = nullgen;
$$.type = D_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
}
fimm:
'$' LFCONST
{
$$ = nullgen;
$$.type = D_FCONST;
$$.u.dval = $2;
}
| '$' '-' LFCONST
{
$$ = nullgen;
$$.type = D_FCONST;
$$.u.dval = -$3;
}
imm: '$' con
{
$$ = nullgen;
$$.type = D_CONST;
$$.offset = $2;
}
sreg:
LREG
| LR '(' con ')'
{
if($$ < 0 || $$ >= NREG)
print("register value out of range\n");
$$ = $3;
}
regaddr:
'(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $2;
$$.offset = 0;
}
| '(' sreg '+' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $2;
$$.scale = $4;
$$.offset = 0;
}
addr:
name
| con '(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $3;
$$.offset = $1;
}
name:
con '(' pointer ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = $3;
$$.sym = nil;
$$.offset = $1;
}
| LNAME offset '(' pointer ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = D_STATIC;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $4;
}
comma:
| ','
offset:
{
$$ = 0;
}
| '+' con
{
$$ = $2;
}
| '-' con
{
$$ = -$2;
}
pointer:
LSB
| LSP
| LFP
con:
LCONST
| LVAR
{
$$ = $1->value;
}
| '-' con
{
$$ = -$2;
}
| '+' con
{
$$ = $2;
}
| '~' con
{
$$ = ~$2;
}
| '(' expr ')'
{
$$ = $2;
}
expr:
con
| expr '+' expr
{
$$ = $1 + $3;
}
| expr '-' expr
{
$$ = $1 - $3;
}
| expr '*' expr
{
$$ = $1 * $3;
}
| expr '/' expr
{
$$ = $1 / $3;
}
| expr '%' expr
{
$$ = $1 % $3;
}
| expr '<' '<' expr
{
$$ = $1 << $4;
}
| expr '>' '>' expr
{
$$ = $1 >> $4;
}
| expr '&' expr
{
$$ = $1 & $3;
}
| expr '^' expr
{
$$ = $1 ^ $3;
}
| expr '|' expr
{
$$ = $1 | $3;
}

21
src/cmd/9a/doc.go Normal file
View file

@ -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

725
src/cmd/9a/lex.c Normal file
View file

@ -0,0 +1,725 @@
// cmd/9a/lex.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include <u.h>
#include <libc.h>
#include "a.h"
#include "y.tab.h"
enum
{
Plan9 = 1<<0,
Unix = 1<<1,
Windows = 1<<2,
};
int
systemtype(int sys)
{
#ifdef _WIN32
return sys&Windows;
#else
return sys&Plan9;
#endif
}
int
pathchar(void)
{
return '/';
}
int
Lconv(Fmt *fp)
{
return linklinefmt(ctxt, fp);
}
void
dodef(char *p)
{
if(nDlist%8 == 0)
Dlist = allocn(Dlist, nDlist*sizeof(char *),
8*sizeof(char *));
Dlist[nDlist++] = p;
}
LinkArch* thelinkarch = &linkpower64;
void
usage(void)
{
print("usage: %ca [options] file.c...\n", thechar);
flagprint(1);
errorexit();
}
void
main(int argc, char *argv[])
{
char *p;
thechar = '9';
thestring = "power64";
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = getgoarch();
if(strncmp(p, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
if(strcmp(p, "power64le") == 0)
thelinkarch = &linkpower64le;
ctxt = linknew(thelinkarch);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit9();
fmtinstall('L', Lconv);
ensuresymb(NSYMB);
memset(debug, 0, sizeof(debug));
cinit();
outfile = 0;
setinclude(".");
flagfn1("D", "name[=value]: add #define", dodef);
flagfn1("I", "dir: add dir to include path", setinclude);
flagcount("S", "print assembly and machine code", &debug['S']);
flagcount("m", "debug preprocessor macros", &debug['m']);
flagstr("o", "file: set output file", &outfile);
flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
if(argc < 1)
usage();
if(argc > 1){
print("can't assemble multiple files\n");
errorexit();
}
if(assemble(argv[0]))
errorexit();
Bflush(&bstdout);
exits(0);
}
int
assemble(char *file)
{
char *ofile, *p;
int i, of;
ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
strcpy(ofile, file);
p = utfrrune(ofile, pathchar());
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
outfile = p;
if(outfile){
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
p = utfrune(outfile, 0);
p[0] = '.';
p[1] = thechar;
p[2] = 0;
} else
outfile = "/dev/null";
}
of = create(outfile, OWRITE, 0664);
if(of < 0) {
yyerror("%ca: cannot create %s", thechar, outfile);
errorexit();
}
Binit(&obuf, of, OWRITE);
Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
Bprint(&obuf, "!\n");
for(pass = 1; pass <= 2; pass++) {
nosched = 0;
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
cclean();
if(nerrors)
return nerrors;
}
writeobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
struct
{
char *name;
ushort type;
ushort value;
} itab[] =
{
"SP", LSP, D_AUTO,
"SB", LSB, D_EXTERN,
"FP", LFP, D_PARAM,
"PC", LPC, D_BRANCH,
"LR", LLR, D_LR,
"CTR", LCTR, D_CTR,
"XER", LSPREG, D_XER,
"MSR", LMSR, D_MSR,
"FPSCR", LFPSCR, D_FPSCR,
"SPR", LSPR, D_SPR,
"DCR", LSPR, D_DCR,
"CR", LCR, 0,
"CR0", LCREG, 0,
"CR1", LCREG, 1,
"CR2", LCREG, 2,
"CR3", LCREG, 3,
"CR4", LCREG, 4,
"CR5", LCREG, 5,
"CR6", LCREG, 6,
"CR7", LCREG, 7,
"R", LR, 0,
"R0", LREG, 0,
"R1", LREG, 1,
"R2", LREG, 2,
"R3", LREG, 3,
"R4", LREG, 4,
"R5", LREG, 5,
"R6", LREG, 6,
"R7", LREG, 7,
"R8", LREG, 8,
"R9", LREG, 9,
"R10", LREG, 10,
"R11", LREG, 11,
"R12", LREG, 12,
"R13", LREG, 13,
"R14", LREG, 14,
"R15", LREG, 15,
"R16", LREG, 16,
"R17", LREG, 17,
"R18", LREG, 18,
"R19", LREG, 19,
"R20", LREG, 20,
"R21", LREG, 21,
"R22", LREG, 22,
"R23", LREG, 23,
"R24", LREG, 24,
"R25", LREG, 25,
"R26", LREG, 26,
"R27", LREG, 27,
"R28", LREG, 28,
"R29", LREG, 29,
"R30", LREG, 30,
"R31", LREG, 31,
"F", LF, 0,
"F0", LFREG, 0,
"F1", LFREG, 1,
"F2", LFREG, 2,
"F3", LFREG, 3,
"F4", LFREG, 4,
"F5", LFREG, 5,
"F6", LFREG, 6,
"F7", LFREG, 7,
"F8", LFREG, 8,
"F9", LFREG, 9,
"F10", LFREG, 10,
"F11", LFREG, 11,
"F12", LFREG, 12,
"F13", LFREG, 13,
"F14", LFREG, 14,
"F15", LFREG, 15,
"F16", LFREG, 16,
"F17", LFREG, 17,
"F18", LFREG, 18,
"F19", LFREG, 19,
"F20", LFREG, 20,
"F21", LFREG, 21,
"F22", LFREG, 22,
"F23", LFREG, 23,
"F24", LFREG, 24,
"F25", LFREG, 25,
"F26", LFREG, 26,
"F27", LFREG, 27,
"F28", LFREG, 28,
"F29", LFREG, 29,
"F30", LFREG, 30,
"F31", LFREG, 31,
"CREQV", LCROP, ACREQV,
"CRXOR", LCROP, ACRXOR,
"CRAND", LCROP, ACRAND,
"CROR", LCROP, ACROR,
"CRANDN", LCROP, ACRANDN,
"CRORN", LCROP, ACRORN,
"CRNAND", LCROP, ACRNAND,
"CRNOR", LCROP, ACRNOR,
"ADD", LADDW, AADD,
"ADDV", LADDW, AADDV,
"ADDCC", LADDW, AADDCC,
"ADDVCC", LADDW, AADDVCC,
"ADDC", LADDW, AADDC,
"ADDCV", LADDW, AADDCV,
"ADDCCC", LADDW, AADDCCC,
"ADDCVCC", LADDW, AADDCVCC,
"ADDE", LLOGW, AADDE,
"ADDEV", LLOGW, AADDEV,
"ADDECC", LLOGW, AADDECC,
"ADDEVCC", LLOGW, AADDEVCC,
"ADDME", LABS, AADDME,
"ADDMEV", LABS, AADDMEV,
"ADDMECC", LABS, AADDMECC,
"ADDMEVCC", LABS, AADDMEVCC,
"ADDZE", LABS, AADDZE,
"ADDZEV", LABS, AADDZEV,
"ADDZECC", LABS, AADDZECC,
"ADDZEVCC", LABS, AADDZEVCC,
"SUB", LADDW, ASUB,
"SUBV", LADDW, ASUBV,
"SUBCC", LADDW, ASUBCC,
"SUBVCC", LADDW, ASUBVCC,
"SUBE", LLOGW, ASUBE,
"SUBECC", LLOGW, ASUBECC,
"SUBEV", LLOGW, ASUBEV,
"SUBEVCC", LLOGW, ASUBEVCC,
"SUBC", LADDW, ASUBC,
"SUBCCC", LADDW, ASUBCCC,
"SUBCV", LADDW, ASUBCV,
"SUBCVCC", LADDW, ASUBCVCC,
"SUBME", LABS, ASUBME,
"SUBMEV", LABS, ASUBMEV,
"SUBMECC", LABS, ASUBMECC,
"SUBMEVCC", LABS, ASUBMEVCC,
"SUBZE", LABS, ASUBZE,
"SUBZEV", LABS, ASUBZEV,
"SUBZECC", LABS, ASUBZECC,
"SUBZEVCC", LABS, ASUBZEVCC,
"AND", LADDW, AAND,
"ANDCC", LADDW, AANDCC, /* includes andil & andiu */
"ANDN", LLOGW, AANDN,
"ANDNCC", LLOGW, AANDNCC,
"EQV", LLOGW, AEQV,
"EQVCC", LLOGW, AEQVCC,
"NAND", LLOGW, ANAND,
"NANDCC", LLOGW, ANANDCC,
"NOR", LLOGW, ANOR,
"NORCC", LLOGW, ANORCC,
"OR", LADDW, AOR, /* includes oril & oriu */
"ORCC", LADDW, AORCC,
"ORN", LLOGW, AORN,
"ORNCC", LLOGW, AORNCC,
"XOR", LADDW, AXOR, /* includes xoril & xoriu */
"XORCC", LLOGW, AXORCC,
"EXTSB", LABS, AEXTSB,
"EXTSBCC", LABS, AEXTSBCC,
"EXTSH", LABS, AEXTSH,
"EXTSHCC", LABS, AEXTSHCC,
"CNTLZW", LABS, ACNTLZW,
"CNTLZWCC", LABS, ACNTLZWCC,
"RLWMI", LRLWM, ARLWMI,
"RLWMICC", LRLWM, ARLWMICC,
"RLWNM", LRLWM, ARLWNM,
"RLWNMCC", LRLWM, ARLWNMCC,
"SLW", LSHW, ASLW,
"SLWCC", LSHW, ASLWCC,
"SRW", LSHW, ASRW,
"SRWCC", LSHW, ASRWCC,
"SRAW", LSHW, ASRAW,
"SRAWCC", LSHW, ASRAWCC,
"BR", LBRA, ABR,
"BC", LBRA, ABC,
"BCL", LBRA, ABC,
"BL", LBRA, ABL,
"BEQ", LBRA, ABEQ,
"BNE", LBRA, ABNE,
"BGT", LBRA, ABGT,
"BGE", LBRA, ABGE,
"BLT", LBRA, ABLT,
"BLE", LBRA, ABLE,
"BVC", LBRA, ABVC,
"BVS", LBRA, ABVS,
"CMP", LCMP, ACMP,
"CMPU", LCMP, ACMPU,
"CMPW", LCMP, ACMPW,
"CMPWU", LCMP, ACMPWU,
"DIVW", LLOGW, ADIVW,
"DIVWV", LLOGW, ADIVWV,
"DIVWCC", LLOGW, ADIVWCC,
"DIVWVCC", LLOGW, ADIVWVCC,
"DIVWU", LLOGW, ADIVWU,
"DIVWUV", LLOGW, ADIVWUV,
"DIVWUCC", LLOGW, ADIVWUCC,
"DIVWUVCC", LLOGW, ADIVWUVCC,
"FABS", LFCONV, AFABS,
"FABSCC", LFCONV, AFABSCC,
"FNEG", LFCONV, AFNEG,
"FNEGCC", LFCONV, AFNEGCC,
"FNABS", LFCONV, AFNABS,
"FNABSCC", LFCONV, AFNABSCC,
"FADD", LFADD, AFADD,
"FADDCC", LFADD, AFADDCC,
"FSUB", LFADD, AFSUB,
"FSUBCC", LFADD, AFSUBCC,
"FMUL", LFADD, AFMUL,
"FMULCC", LFADD, AFMULCC,
"FDIV", LFADD, AFDIV,
"FDIVCC", LFADD, AFDIVCC,
"FRSP", LFCONV, AFRSP,
"FRSPCC", LFCONV, AFRSPCC,
"FCTIW", LFCONV, AFCTIW,
"FCTIWCC", LFCONV, AFCTIWCC,
"FCTIWZ", LFCONV, AFCTIWZ,
"FCTIWZCC", LFCONV, AFCTIWZCC,
"FMADD", LFMA, AFMADD,
"FMADDCC", LFMA, AFMADDCC,
"FMSUB", LFMA, AFMSUB,
"FMSUBCC", LFMA, AFMSUBCC,
"FNMADD", LFMA, AFNMADD,
"FNMADDCC", LFMA, AFNMADDCC,
"FNMSUB", LFMA, AFNMSUB,
"FNMSUBCC", LFMA, AFNMSUBCC,
"FMADDS", LFMA, AFMADDS,
"FMADDSCC", LFMA, AFMADDSCC,
"FMSUBS", LFMA, AFMSUBS,
"FMSUBSCC", LFMA, AFMSUBSCC,
"FNMADDS", LFMA, AFNMADDS,
"FNMADDSCC", LFMA, AFNMADDSCC,
"FNMSUBS", LFMA, AFNMSUBS,
"FNMSUBSCC", LFMA, AFNMSUBSCC,
"FCMPU", LFCMP, AFCMPU,
"FCMPO", LFCMP, AFCMPO,
"MTFSB0", LMTFSB, AMTFSB0,
"MTFSB1", LMTFSB, AMTFSB1,
"FMOVD", LFMOV, AFMOVD,
"FMOVS", LFMOV, AFMOVS,
"FMOVDCC", LFCONV, AFMOVDCC, /* fmr. */
"GLOBL", LTEXT, AGLOBL,
"MOVB", LMOVB, AMOVB,
"MOVBZ", LMOVB, AMOVBZ,
"MOVBU", LMOVB, AMOVBU,
"MOVBZU", LMOVB, AMOVBZU,
"MOVH", LMOVB, AMOVH,
"MOVHZ", LMOVB, AMOVHZ,
"MOVHU", LMOVB, AMOVHU,
"MOVHZU", LMOVB, AMOVHZU,
"MOVHBR", LXMV, AMOVHBR,
"MOVWBR", LXMV, AMOVWBR,
"MOVW", LMOVW, AMOVW,
"MOVWU", LMOVW, AMOVWU,
"MOVMW", LMOVMW, AMOVMW,
"MOVFL", LMOVW, AMOVFL,
"MULLW", LADDW, AMULLW, /* includes multiply immediate 10-139 */
"MULLWV", LLOGW, AMULLWV,
"MULLWCC", LLOGW, AMULLWCC,
"MULLWVCC", LLOGW, AMULLWVCC,
"MULHW", LLOGW, AMULHW,
"MULHWCC", LLOGW, AMULHWCC,
"MULHWU", LLOGW, AMULHWU,
"MULHWUCC", LLOGW, AMULHWUCC,
"NEG", LABS, ANEG,
"NEGV", LABS, ANEGV,
"NEGCC", LABS, ANEGCC,
"NEGVCC", LABS, ANEGVCC,
"NOP", LNOP, ANOP, /* ori 0,0,0 */
"SYSCALL", LNOP, ASYSCALL,
"UNDEF", LNOP, AUNDEF,
"RETURN", LRETRN, ARETURN,
"RFI", LRETRN, ARFI,
"RFCI", LRETRN, ARFCI,
"DATA", LDATA, ADATA,
"END", LEND, AEND,
"TEXT", LTEXT, ATEXT,
/* 64-bit instructions */
"CNTLZD", LABS, ACNTLZD,
"CNTLZDCC", LABS, ACNTLZDCC,
"DIVD", LLOGW, ADIVD,
"DIVDCC", LLOGW, ADIVDCC,
"DIVDVCC", LLOGW, ADIVDVCC,
"DIVDV", LLOGW, ADIVDV,
"DIVDU", LLOGW, ADIVDU,
"DIVDUCC", LLOGW, ADIVDUCC,
"DIVDUVCC", LLOGW, ADIVDUVCC,
"DIVDUV", LLOGW, ADIVDUV,
"EXTSW", LABS, AEXTSW,
"EXTSWCC", LABS, AEXTSWCC,
"FCTID", LFCONV, AFCTID,
"FCTIDCC", LFCONV, AFCTIDCC,
"FCTIDZ", LFCONV, AFCTIDZ,
"FCTIDZCC", LFCONV, AFCTIDZCC,
"FCFID", LFCONV, AFCFID,
"FCFIDCC", LFCONV, AFCFIDCC,
"LDAR", LXLD, ALDAR,
"MOVD", LMOVW, AMOVD,
"MOVDU", LMOVW, AMOVDU,
"MOVWZ", LMOVW, AMOVWZ,
"MOVWZU", LMOVW, AMOVWZU,
"MULHD", LLOGW, AMULHD,
"MULHDCC", LLOGW, AMULHDCC,
"MULHDU", LLOGW, AMULHDU,
"MULHDUCC", LLOGW, AMULHDUCC,
"MULLD", LADDW, AMULLD, /* includes multiply immediate? */
"MULLDCC", LLOGW, AMULLDCC,
"MULLDVCC", LLOGW, AMULLDVCC,
"MULLDV", LLOGW, AMULLDV,
"RFID", LRETRN, ARFID,
"HRFID", LRETRN, AHRFID,
"RLDMI", LRLWM, ARLDMI,
"RLDMICC", LRLWM, ARLDMICC,
"RLDC", LRLWM, ARLDC,
"RLDCCC", LRLWM, ARLDCCC,
"RLDCR", LRLWM, ARLDCR,
"RLDCRCC", LRLWM, ARLDCRCC,
"RLDCL", LRLWM, ARLDCL,
"RLDCLCC", LRLWM, ARLDCLCC,
"SLBIA", LNOP, ASLBIA,
"SLBIE", LNOP, ASLBIE,
"SLBMFEE", LABS, ASLBMFEE,
"SLBMFEV", LABS, ASLBMFEV,
"SLBMTE", LABS, ASLBMTE,
"SLD", LSHW, ASLD,
"SLDCC", LSHW, ASLDCC,
"SRD", LSHW, ASRD,
"SRAD", LSHW, ASRAD,
"SRADCC", LSHW, ASRADCC,
"SRDCC", LSHW, ASRDCC,
"STDCCC", LXST, ASTDCCC,
"TD", LADDW, ATD,
/* pseudo instructions */
"REM", LLOGW, AREM,
"REMCC", LLOGW, AREMCC,
"REMV", LLOGW, AREMV,
"REMVCC", LLOGW, AREMVCC,
"REMU", LLOGW, AREMU,
"REMUCC", LLOGW, AREMUCC,
"REMUV", LLOGW, AREMUV,
"REMUVCC", LLOGW, AREMUVCC,
"REMD", LLOGW, AREMD,
"REMDCC", LLOGW, AREMDCC,
"REMDV", LLOGW, AREMDV,
"REMDVCC", LLOGW, AREMDVCC,
"REMDU", LLOGW, AREMDU,
"REMDUCC", LLOGW, AREMDUCC,
"REMDUV", LLOGW, AREMDUV,
"REMDUVCC", LLOGW, AREMDUVCC,
/* special instructions */
"DCBF", LXOP, ADCBF,
"DCBI", LXOP, ADCBI,
"DCBST", LXOP, ADCBST,
"DCBT", LXOP, ADCBT,
"DCBTST", LXOP, ADCBTST,
"DCBZ", LXOP, ADCBZ,
"ICBI", LXOP, AICBI,
"ECIWX", LXLD, AECIWX,
"ECOWX", LXST, AECOWX,
"LWAR", LXLD, ALWAR,
"LWAR", LXLD, ALWAR,
"STWCCC", LXST, ASTWCCC,
"EIEIO", LRETRN, AEIEIO,
"TLBIE", LNOP, ATLBIE,
"TLBIEL", LNOP, ATLBIEL,
"LSW", LXLD, ALSW,
"STSW", LXST, ASTSW,
"ISYNC", LRETRN, AISYNC,
"SYNC", LRETRN, ASYNC,
"TLBSYNC", LRETRN, ATLBSYNC,
"PTESYNC", LRETRN, APTESYNC,
/* "TW", LADDW, ATW,*/
"WORD", LWORD, AWORD,
"DWORD", LWORD, ADWORD,
"SCHED", LSCHED, 0,
"NOSCHED", LSCHED, 0x80,
"PCDATA", LPCDAT, APCDATA,
"FUNCDATA", LFUNCDAT, AFUNCDATA,
0
};
void
cinit(void)
{
Sym *s;
int i;
nullgen.type = D_NONE;
nullgen.name = D_NONE;
nullgen.reg = NREG;
nullgen.scale = NREG; // replaced Gen.xreg with Prog.scale
nerrors = 0;
iostack = I;
iofree = I;
peekc = IGN;
nhunk = 0;
for(i=0; i<NHASH; i++)
hash[i] = S;
for(i=0; itab[i].name; i++) {
s = slookup(itab[i].name);
s->type = itab[i].type;
s->value = itab[i].value;
}
}
void
syminit(Sym *s)
{
s->type = LNAME;
s->value = 0;
}
void
cclean(void)
{
outcode(AEND, &nullgen, NREG, &nullgen);
}
static Prog *lastpc;
void
outcode(int a, Addr *g1, int reg, Addr *g2)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
if(g1->scale != NREG) {
if(reg != NREG || g2->scale != NREG)
yyerror("bad addressing modes");
reg = g1->scale;
} else
if(g2->scale != NREG) {
if(reg != NREG)
yyerror("bad addressing modes");
reg = g2->scale;
}
p = ctxt->arch->prg();
p->as = a;
p->lineno = lineno;
if(nosched)
p->mark |= NOSCHED;
p->from = *g1;
p->reg = reg;
p->to = *g2;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
void
outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
p = ctxt->arch->prg();
p->as = a;
p->lineno = lineno;
if(nosched)
p->mark |= NOSCHED;
p->from = *g1;
p->reg = reg;
p->from3 = *g2;
p->to = *g3;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
#include "../cc/lexbody"
#include "../cc/macbody"

3398
src/cmd/9a/y.tab.c Normal file

File diff suppressed because it is too large Load diff

188
src/cmd/9a/y.tab.h Normal file
View file

@ -0,0 +1,188 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LMOVW = 258,
LMOVB = 259,
LABS = 260,
LLOGW = 261,
LSHW = 262,
LADDW = 263,
LCMP = 264,
LCROP = 265,
LBRA = 266,
LFMOV = 267,
LFCONV = 268,
LFCMP = 269,
LFADD = 270,
LFMA = 271,
LTRAP = 272,
LXORW = 273,
LNOP = 274,
LEND = 275,
LRETT = 276,
LWORD = 277,
LTEXT = 278,
LDATA = 279,
LRETRN = 280,
LCONST = 281,
LSP = 282,
LSB = 283,
LFP = 284,
LPC = 285,
LCREG = 286,
LFLUSH = 287,
LREG = 288,
LFREG = 289,
LR = 290,
LCR = 291,
LF = 292,
LFPSCR = 293,
LLR = 294,
LCTR = 295,
LSPR = 296,
LSPREG = 297,
LSEG = 298,
LMSR = 299,
LPCDAT = 300,
LFUNCDAT = 301,
LSCHED = 302,
LXLD = 303,
LXST = 304,
LXOP = 305,
LXMV = 306,
LRLWM = 307,
LMOVMW = 308,
LMOVEM = 309,
LMOVFL = 310,
LMTFSB = 311,
LMA = 312,
LFCONST = 313,
LSCONST = 314,
LNAME = 315,
LLAB = 316,
LVAR = 317
};
#endif
/* Tokens. */
#define LMOVW 258
#define LMOVB 259
#define LABS 260
#define LLOGW 261
#define LSHW 262
#define LADDW 263
#define LCMP 264
#define LCROP 265
#define LBRA 266
#define LFMOV 267
#define LFCONV 268
#define LFCMP 269
#define LFADD 270
#define LFMA 271
#define LTRAP 272
#define LXORW 273
#define LNOP 274
#define LEND 275
#define LRETT 276
#define LWORD 277
#define LTEXT 278
#define LDATA 279
#define LRETRN 280
#define LCONST 281
#define LSP 282
#define LSB 283
#define LFP 284
#define LPC 285
#define LCREG 286
#define LFLUSH 287
#define LREG 288
#define LFREG 289
#define LR 290
#define LCR 291
#define LF 292
#define LFPSCR 293
#define LLR 294
#define LCTR 295
#define LSPR 296
#define LSPREG 297
#define LSEG 298
#define LMSR 299
#define LPCDAT 300
#define LFUNCDAT 301
#define LSCHED 302
#define LXLD 303
#define LXST 304
#define LXOP 305
#define LXMV 306
#define LRLWM 307
#define LMOVMW 308
#define LMOVEM 309
#define LMOVFL 310
#define LMTFSB 311
#define LMA 312
#define LFCONST 313
#define LSCONST 314
#define LNAME 315
#define LLAB 316
#define LVAR 317
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 38 "a.y"
{
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
}
/* Line 1529 of yacc.c. */
#line 181 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

5
src/cmd/9c/Makefile Normal file
View file

@ -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

14
src/cmd/9c/Notes Normal file
View file

@ -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

1147
src/cmd/9c/cgen.c Normal file

File diff suppressed because it is too large Load diff

17
src/cmd/9c/doc.go Normal file
View file

@ -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

350
src/cmd/9c/gc.h Normal file
View file

@ -0,0 +1,350 @@
// cmd/9c/gc.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include "../cc/cc.h"
#include "../9l/9.out.h"
/*
* 9c/powerpc64
*/
#define SZ_CHAR 1
#define SZ_SHORT 2
#define SZ_INT 4
#define SZ_LONG 4
#define SZ_IND 8
#define SZ_FLOAT 4
#define SZ_VLONG 8
#define SZ_DOUBLE 8
#define FNX 100
typedef struct Case Case;
typedef struct C1 C1;
typedef struct Multab Multab;
typedef struct Hintab Hintab;
typedef struct Reg Reg;
typedef struct Rgn Rgn;
#define A ((Adr*)0)
#define INDEXED 9
#define P ((Prog*)0)
struct Case
{
Case* link;
vlong val;
int32 label;
char def;
char isv;
};
#define C ((Case*)0)
struct C1
{
vlong val;
int32 label;
};
struct Multab
{
int32 val;
char code[20];
};
struct Hintab
{
ushort val;
char hint[10];
};
struct Reg
{
int32 pc;
int32 rpo; /* reverse post ordering */
Bits set;
Bits use1;
Bits use2;
Bits refbehind;
Bits refahead;
Bits calbehind;
Bits calahead;
Bits regdiff;
Bits act;
int32 regu;
int32 loop; /* could be shorter */
union
{
Reg* log5;
int32 active;
};
Reg* p1;
Reg* p2;
Reg* p2link;
Reg* s1;
Reg* s2;
Reg* link;
Prog* prog;
};
#define R ((Reg*)0)
#define NRGN 600
struct Rgn
{
Reg* enter;
short cost;
short varno;
short regno;
};
EXTERN int32 breakpc;
EXTERN int32 nbreak;
EXTERN Case* cases;
EXTERN Node constnode;
EXTERN Node fconstnode;
EXTERN Node vconstnode;
EXTERN int32 continpc;
EXTERN int32 curarg;
EXTERN int32 cursafe;
EXTERN Prog* lastp;
extern int hintabsize;
EXTERN int32 maxargsafe;
EXTERN Multab multab[20];
EXTERN int mnstring;
EXTERN Node* nodrat;
EXTERN Node* nodret;
EXTERN Node* nodsafe;
EXTERN int32 nrathole;
EXTERN int32 nstring;
EXTERN Prog* p;
EXTERN int32 pc;
EXTERN Node regnode;
EXTERN Node qregnode;
EXTERN char string[NSNAME];
EXTERN Sym* symrathole;
EXTERN Node znode;
EXTERN Prog zprog;
EXTERN int reg[NREG+NREG];
EXTERN int32 exregoffset;
EXTERN int32 exfregoffset;
EXTERN uchar typechlpv[NTYPE];
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
#define CLOAD 5
#define CREF 5
#define CINF 1000
#define LOOP 3
EXTERN Rgn region[NRGN];
EXTERN Rgn* rgp;
EXTERN int nregion;
EXTERN int nvar;
EXTERN Bits externs;
EXTERN Bits params;
EXTERN Bits consts;
EXTERN Bits addrs;
EXTERN int32 regbits;
EXTERN int32 exregbits;
EXTERN int change;
EXTERN int suppress;
EXTERN Reg* firstr;
EXTERN Reg* lastr;
EXTERN Reg zreg;
EXTERN Reg* freer;
EXTERN Var var[NVAR];
EXTERN int32* idom;
EXTERN Reg** rpo2r;
EXTERN int32 maxnr;
#define R0ISZERO (debug['0']==0)
extern char* anames[];
extern Hintab hintab[];
/*
* sgen.c
*/
void codgen(Node*, Node*);
void gen(Node*);
void usedset(Node*, int);
void noretval(int);
void xcom(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
vlong argsize(int);
/*
* cgen.c
*/
void cgen(Node*, Node*);
void reglcgen(Node*, Node*, Node*);
void lcgen(Node*, Node*);
void bcgen(Node*, int);
void boolgen(Node*, int, Node*);
void sugen(Node*, Node*, int32);
void layout(Node*, Node*, int, int, Node*);
/*
* txt.c
*/
void ginit(void);
void gclean(void);
void nextpc(void);
void gargs(Node*, Node*, Node*);
void garg1(Node*, Node*, Node*, int, Node**);
Node* nodconst(int32);
Node* nod32const(vlong);
Node* nodfconst(double);
Node* nodgconst(vlong v, Type *t);
void nodreg(Node*, Node*, int);
void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);
void regsalloc(Node*, Node*);
void regaalloc1(Node*, Node*);
void regaalloc(Node*, Node*);
void regind(Node*, Node*);
void gprep(Node*, Node*);
void raddr(Node*, Prog*);
void naddr(Node*, Addr*);
void gmove(Node*, Node*);
void gins(int a, Node*, Node*);
void gopcode(int, Node*, Node*, Node*);
int samaddr(Node*, Node*);
void gbranch(int);
int immconst(Node*);
void patch(Prog*, int32);
int sconst(Node*);
int sval(int32);
int uconst(Node*);
void gpseudo(int, Sym*, Node*);
void gprefetch(Node*);
void gpcdata(int, int);
/*
* swt.c
*/
int swcmp(const void*, const void*);
void doswit(Node*);
void swit1(C1*, int, int32, Node*);
void swit2(C1*, int, int32, Node*, Node*);
void newcase(void);
void bitload(Node*, Node*, Node*, Node*, Node*);
void bitstore(Node*, Node*, Node*, Node*, Node*);
int32 outstring(char*, int32);
int mulcon(Node*, Node*);
Multab* mulcon0(Node*, int32);
int mulcon1(Node*, int32, Node*);
void nullwarn(Node*, Node*);
void sextern(Sym*, Node*, int32, int32);
void gextern(Sym*, Node*, int32, int32);
void outcode(void);
/*
* list
*/
void listinit(void);
int Pconv(Fmt*);
int Aconv(Fmt*);
int Dconv(Fmt*);
int Sconv(Fmt*);
int Nconv(Fmt*);
int Bconv(Fmt*);
/*
* reg.c
*/
Reg* rega(void);
int rcmp(const void*, const void*);
void regopt(Prog*);
void addmove(Reg*, int, int, int);
Bits mkvar(Addr*, int);
void prop(Reg*, Bits, Bits);
void loopit(Reg*, int32);
void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int);
uint32 paint2(Reg*, int);
void paint3(Reg*, int, int32, int);
void addreg(Addr*, int);
/*
* peep.c
*/
void peep(void);
void excise(Reg*);
Reg* uniqp(Reg*);
Reg* uniqs(Reg*);
int regtyp(Addr*);
int regzer(Addr*);
int anyvar(Addr*);
int subprop(Reg*);
int copyprop(Reg*);
int copy1(Addr*, Addr*, Reg*, int);
int copyu(Prog*, Addr*, Addr*);
int copyas(Addr*, Addr*);
int copyau(Addr*, Addr*);
int copyau1(Prog*, Addr*);
int copysub(Addr*, Addr*, Addr*, int);
int copysub1(Prog*, Addr*, Addr*, int);
int32 RtoB(int);
int32 FtoB(int);
int BtoR(int32);
int BtoF(int32);
/*
* com64.c
*/
int com64(Node*);
void com64init(void);
void bool64(Node*);
#pragma varargck type "A" int
#pragma varargck type "B" Bits
#pragma varargck type "D" Addr*
#pragma varargck type "N" Addr*
#pragma varargck type "P" Prog*
#pragma varargck type "S" char*

37
src/cmd/9c/list.c Normal file
View file

@ -0,0 +1,37 @@
// cmd/9c/list.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include "gc.h"
void
listinit(void)
{
listinit9();
}

105
src/cmd/9c/machcap.c Normal file
View file

@ -0,0 +1,105 @@
// cmd/9c/machcap.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
int
machcap(Node *n)
{
if(n == Z)
return 1; /* test */
switch(n->op) {
case OMUL:
case OLMUL:
case OASMUL:
case OASLMUL:
if(typechlv[n->type->etype])
return 1;
break;
case OADD:
case OAND:
case OOR:
case OSUB:
case OXOR:
case OASHL:
case OLSHR:
case OASHR:
if(typechlv[n->left->type->etype])
return 1;
break;
case OCAST:
return 1;
case OCOND:
case OCOMMA:
case OLIST:
case OANDAND:
case OOROR:
case ONOT:
return 1;
case OASADD:
case OASSUB:
case OASAND:
case OASOR:
case OASXOR:
return 1;
case OASASHL:
case OASASHR:
case OASLSHR:
return 1;
case OPOSTINC:
case OPOSTDEC:
case OPREINC:
case OPREDEC:
return 1;
case OEQ:
case ONE:
case OLE:
case OGT:
case OLT:
case OGE:
case OHI:
case OHS:
case OLO:
case OLS:
return 1;
case ONEG:
case OCOM:
break;
}
return 0;
}

638
src/cmd/9c/mul.c Normal file
View file

@ -0,0 +1,638 @@
// cmd/9c/mul.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
/*
* code sequences for multiply by constant.
* [a-l][0-3]
* lsl $(A-'a'),r0,r1
* [+][0-7]
* add r0,r1,r2
* [-][0-7]
* sub r0,r1,r2
*/
static int multabp;
static int32 mulval;
static char* mulcp;
static int32 valmax;
static int shmax;
static int docode(char *hp, char *cp, int r0, int r1);
static int gen1(int len);
static int gen2(int len, int32 r1);
static int gen3(int len, int32 r0, int32 r1, int flag);
enum
{
SR1 = 1<<0, /* r1 has been shifted */
SR0 = 1<<1, /* r0 has been shifted */
UR1 = 1<<2, /* r1 has not been used */
UR0 = 1<<3, /* r0 has not been used */
};
Multab*
mulcon0(Node *n, int32 v)
{
int a1, a2, g;
Multab *m, *m1;
char hint[10];
if(v < 0)
v = -v;
/*
* look in cache
*/
m = multab;
for(g=0; g<nelem(multab); g++) {
if(m->val == v) {
if(m->code[0] == 0)
return 0;
return m;
}
m++;
}
/*
* select a spot in cache to overwrite
*/
multabp++;
if(multabp < 0 || multabp >= nelem(multab))
multabp = 0;
m = multab+multabp;
m->val = v;
mulval = v;
/*
* look in execption hint table
*/
a1 = 0;
a2 = hintabsize;
for(;;) {
if(a1 >= a2)
goto no;
g = (a2 + a1)/2;
if(v < hintab[g].val) {
a2 = g;
continue;
}
if(v > hintab[g].val) {
a1 = g+1;
continue;
}
break;
}
if(docode(hintab[g].hint, m->code, 1, 0))
return m;
print("%L: multiply table failure %ld\n", n->lineno, v);
m->code[0] = 0;
return 0;
no:
/*
* try to search
*/
hint[0] = 0;
for(g=1; g<=6; g++) {
if(g >= 6 && v >= 65535)
break;
mulcp = hint+g;
*mulcp = 0;
if(gen1(g)) {
if(docode(hint, m->code, 1, 0))
return m;
print("%L: multiply table failure (g=%d h=%s) %ld\n",
n->lineno, g, hint, v);
break;
}
}
/*
* try a recur followed by a shift
*/
g = 0;
while(!(v & 1)) {
g++;
v >>= 1;
}
if(g) {
m1 = mulcon0(n, v);
if(m1) {
strcpy(m->code, m1->code);
sprint(strchr(m->code, 0), "%c0", g+'a');
return m;
}
}
m->code[0] = 0;
return 0;
}
static int
docode(char *hp, char *cp, int r0, int r1)
{
int c, i;
c = *hp++;
*cp = c;
cp += 2;
switch(c) {
default:
c -= 'a';
if(c < 1 || c >= 30)
break;
for(i=0; i<4; i++) {
switch(i) {
case 0:
if(docode(hp, cp, r0<<c, r1))
goto out;
break;
case 1:
if(docode(hp, cp, r1<<c, r1))
goto out;
break;
case 2:
if(docode(hp, cp, r0, r0<<c))
goto out;
break;
case 3:
if(docode(hp, cp, r0, r1<<c))
goto out;
break;
}
}
break;
case '+':
for(i=0; i<8; i++) {
cp[-1] = i+'0';
switch(i) {
case 1:
if(docode(hp, cp, r0+r1, r1))
goto out;
break;
case 5:
if(docode(hp, cp, r0, r0+r1))
goto out;
break;
}
}
break;
case '-':
for(i=0; i<8; i++) {
cp[-1] = i+'0';
switch(i) {
case 1:
if(docode(hp, cp, r0-r1, r1))
goto out;
break;
case 2:
if(docode(hp, cp, r1-r0, r1))
goto out;
break;
case 5:
if(docode(hp, cp, r0, r0-r1))
goto out;
break;
case 6:
if(docode(hp, cp, r0, r1-r0))
goto out;
break;
}
}
break;
case 0:
if(r0 == mulval)
return 1;
}
return 0;
out:
cp[-1] = i+'0';
return 1;
}
static int
gen1(int len)
{
int i;
for(shmax=1; shmax<30; shmax++) {
valmax = 1<<shmax;
if(valmax >= mulval)
break;
}
if(mulval == 1)
return 1;
len--;
for(i=1; i<=shmax; i++)
if(gen2(len, 1<<i)) {
*--mulcp = 'a'+i;
return 1;
}
return 0;
}
static int
gen2(int len, int32 r1)
{
int i;
if(len <= 0) {
if(r1 == mulval)
return 1;
return 0;
}
len--;
if(len == 0)
goto calcr0;
if(gen3(len, r1, r1+1, UR1)) {
i = '+';
goto out;
}
if(gen3(len, r1-1, r1, UR0)) {
i = '-';
goto out;
}
if(gen3(len, 1, r1+1, UR1)) {
i = '+';
goto out;
}
if(gen3(len, 1, r1-1, UR1)) {
i = '-';
goto out;
}
return 0;
calcr0:
if(mulval == r1+1) {
i = '+';
goto out;
}
if(mulval == r1-1) {
i = '-';
goto out;
}
return 0;
out:
*--mulcp = i;
return 1;
}
static int
gen3(int len, int32 r0, int32 r1, int flag)
{
int i, f1, f2;
int32 x;
if(r0 <= 0 ||
r0 >= r1 ||
r1 > valmax)
return 0;
len--;
if(len == 0)
goto calcr0;
if(!(flag & UR1)) {
f1 = UR1|SR1;
for(i=1; i<=shmax; i++) {
x = r0<<i;
if(x > valmax)
break;
if(gen3(len, r0, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & UR0)) {
f1 = UR1|SR1;
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x > valmax)
break;
if(gen3(len, r1, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & SR1)) {
f1 = UR1|SR1|(flag&UR0);
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x > valmax)
break;
if(gen3(len, r0, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & SR0)) {
f1 = UR0|SR0|(flag&(SR1|UR1));
f2 = UR1|SR1;
if(flag & UR1)
f2 |= UR0;
if(flag & SR1)
f2 |= SR0;
for(i=1; i<=shmax; i++) {
x = r0<<i;
if(x > valmax)
break;
if(x > r1) {
if(gen3(len, r1, x, f2)) {
i += 'a';
goto out;
}
} else
if(gen3(len, x, r1, f1)) {
i += 'a';
goto out;
}
}
}
x = r1+r0;
if(gen3(len, r0, x, UR1)) {
i = '+';
goto out;
}
if(gen3(len, r1, x, UR1)) {
i = '+';
goto out;
}
x = r1-r0;
if(gen3(len, x, r1, UR0)) {
i = '-';
goto out;
}
if(x > r0) {
if(gen3(len, r0, x, UR1)) {
i = '-';
goto out;
}
} else
if(gen3(len, x, r0, UR0)) {
i = '-';
goto out;
}
return 0;
calcr0:
f1 = flag & (UR0|UR1);
if(f1 == UR1) {
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x >= mulval) {
if(x == mulval) {
i += 'a';
goto out;
}
break;
}
}
}
if(mulval == r1+r0) {
i = '+';
goto out;
}
if(mulval == r1-r0) {
i = '-';
goto out;
}
return 0;
out:
*--mulcp = i;
return 1;
}
/*
* hint table has numbers that
* the search algorithm fails on.
* <1000:
* all numbers
* <5000:
* ÷ by 5
* <10000:
* ÷ by 50
* <65536:
* ÷ by 250
*/
Hintab hintab[] =
{
683, "b++d+e+",
687, "b+e++e-",
691, "b++d+e+",
731, "b++d+e+",
811, "b++d+i+",
821, "b++e+e+",
843, "b+d++e+",
851, "b+f-+e-",
853, "b++e+e+",
877, "c++++g-",
933, "b+c++g-",
981, "c-+e-d+",
1375, "b+c+b+h-",
1675, "d+b++h+",
2425, "c++f-e+",
2675, "c+d++f-",
2750, "b+d-b+h-",
2775, "c-+g-e-",
3125, "b++e+g+",
3275, "b+c+g+e+",
3350, "c++++i+",
3475, "c-+e-f-",
3525, "c-+d+g-",
3625, "c-+e-j+",
3675, "b+d+d+e+",
3725, "b+d-+h+",
3925, "b+d+f-d-",
4275, "b+g++e+",
4325, "b+h-+d+",
4425, "b+b+g-j-",
4525, "b+d-d+f+",
4675, "c++d-g+",
4775, "b+d+b+g-",
4825, "c+c-+i-",
4850, "c++++i-",
4925, "b++e-g-",
4975, "c+f++e-",
5500, "b+g-c+d+",
6700, "d+b++i+",
9700, "d++++j-",
11000, "b+f-c-h-",
11750, "b+d+g+j-",
12500, "b+c+e-k+",
13250, "b+d+e-f+",
13750, "b+h-c-d+",
14250, "b+g-c+e-",
14500, "c+f+j-d-",
14750, "d-g--f+",
16750, "b+e-d-n+",
17750, "c+h-b+e+",
18250, "d+b+h-d+",
18750, "b+g-++f+",
19250, "b+e+b+h+",
19750, "b++h--f-",
20250, "b+e-l-c+",
20750, "c++bi+e-",
21250, "b+i+l+c+",
22000, "b+e+d-g-",
22250, "b+d-h+k-",
22750, "b+d-e-g+",
23250, "b+c+h+e-",
23500, "b+g-c-g-",
23750, "b+g-b+h-",
24250, "c++g+m-",
24750, "b+e+e+j-",
25000, "b++dh+g+",
25250, "b+e+d-g-",
25750, "b+e+b+j+",
26250, "b+h+c+e+",
26500, "b+h+c+g+",
26750, "b+d+e+g-",
27250, "b+e+e+f+",
27500, "c-i-c-d+",
27750, "b+bd++j+",
28250, "d-d-++i-",
28500, "c+c-h-e-",
29000, "b+g-d-f+",
29500, "c+h+++e-",
29750, "b+g+f-c+",
30250, "b+f-g-c+",
33500, "c-f-d-n+",
33750, "b+d-b+j-",
34250, "c+e+++i+",
35250, "e+b+d+k+",
35500, "c+e+d-g-",
35750, "c+i-++e+",
36250, "b+bh-d+e+",
36500, "c+c-h-e-",
36750, "d+e--i+",
37250, "b+g+g+b+",
37500, "b+h-b+f+",
37750, "c+be++j-",
38500, "b+e+b+i+",
38750, "d+i-b+d+",
39250, "b+g-l-+d+",
39500, "b+g-c+g-",
39750, "b+bh-c+f-",
40250, "b+bf+d+g-",
40500, "b+g-c+g+",
40750, "c+b+i-e+",
41250, "d++bf+h+",
41500, "b+j+c+d-",
41750, "c+f+b+h-",
42500, "c+h++g+",
42750, "b+g+d-f-",
43250, "b+l-e+d-",
43750, "c+bd+h+f-",
44000, "b+f+g-d-",
44250, "b+d-g--f+",
44500, "c+e+c+h+",
44750, "b+e+d-h-",
45250, "b++g+j-g+",
45500, "c+d+e-g+",
45750, "b+d-h-e-",
46250, "c+bd++j+",
46500, "b+d-c-j-",
46750, "e-e-b+g-",
47000, "b+c+d-j-",
47250, "b+e+e-g-",
47500, "b+g-c-h-",
47750, "b+f-c+h-",
48250, "d--h+n-",
48500, "b+c-g+m-",
48750, "b+e+e-g+",
49500, "c-f+e+j-",
49750, "c+c+g++f-",
50000, "b+e+e+k+",
50250, "b++i++g+",
50500, "c+g+f-i+",
50750, "b+e+d+k-",
51500, "b+i+c-f+",
51750, "b+bd+g-e-",
52250, "b+d+g-j+",
52500, "c+c+f+g+",
52750, "b+c+e+i+",
53000, "b+i+c+g+",
53500, "c+g+g-n+",
53750, "b+j+d-c+",
54250, "b+d-g-j-",
54500, "c-f+e+f+",
54750, "b+f-+c+g+",
55000, "b+g-d-g-",
55250, "b+e+e+g+",
55500, "b+cd++j+",
55750, "b+bh-d-f-",
56250, "c+d-b+j-",
56500, "c+d+c+i+",
56750, "b+e+d++h-",
57000, "b+d+g-f+",
57250, "b+f-m+d-",
57750, "b+i+c+e-",
58000, "b+e+d+h+",
58250, "c+b+g+g+",
58750, "d-e-j--e+",
59000, "d-i-+e+",
59250, "e--h-m+",
59500, "c+c-h+f-",
59750, "b+bh-e+i-",
60250, "b+bh-e-e-",
60500, "c+c-g-g-",
60750, "b+e-l-e-",
61250, "b+g-g-c+",
61750, "b+g-c+g+",
62250, "f--+c-i-",
62750, "e+f--+g+",
64750, "b+f+d+p-",
};
int hintabsize = nelem(hintab);

1076
src/cmd/9c/peep.c Normal file

File diff suppressed because it is too large Load diff

1163
src/cmd/9c/reg.c Normal file

File diff suppressed because it is too large Load diff

291
src/cmd/9c/sgen.c Normal file
View file

@ -0,0 +1,291 @@
// cmd/9c/sgen.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
Prog*
gtext(Sym *s, int32 stkoff)
{
vlong v;
v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
if((textflag & NOSPLIT) && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
return p;
}
void
noretval(int n)
{
if(n & 1) {
gins(ANOP, Z, Z);
p->to.type = D_REG;
p->to.reg = REGRET;
}
if(n & 2) {
gins(ANOP, Z, Z);
p->to.type = D_FREG;
p->to.reg = FREGRET;
}
}
/*
* calculate addressability as follows
* CONST ==> 20 $value
* NAME ==> 10 name
* REGISTER ==> 11 register
* INDREG ==> 12 *[(reg)+offset]
* &10 ==> 2 $name
* ADD(2, 20) ==> 2 $name+offset
* ADD(3, 20) ==> 3 $(reg)+offset
* &12 ==> 3 $(reg)+offset
* *11 ==> 11 ??
* *2 ==> 10 name
* *3 ==> 12 *(reg)+offset
* calculate complexity (number of registers)
*/
void
xcom(Node *n)
{
Node *l, *r;
int v;
if(n == Z)
return;
l = n->left;
r = n->right;
n->addable = 0;
n->complex = 0;
switch(n->op) {
case OCONST:
n->addable = 20;
return;
case OREGISTER:
n->addable = 11;
return;
case OINDREG:
n->addable = 12;
return;
case ONAME:
n->addable = 10;
return;
case OADDR:
xcom(l);
if(l->addable == 10)
n->addable = 2;
if(l->addable == 12)
n->addable = 3;
break;
case OIND:
xcom(l);
if(l->addable == 11)
n->addable = 12;
if(l->addable == 3)
n->addable = 12;
if(l->addable == 2)
n->addable = 10;
break;
case OADD:
xcom(l);
xcom(r);
if(l->addable == 20) {
if(r->addable == 2)
n->addable = 2;
if(r->addable == 3)
n->addable = 3;
}
if(r->addable == 20) {
if(l->addable == 2)
n->addable = 2;
if(l->addable == 3)
n->addable = 3;
}
break;
case OASMUL:
case OASLMUL:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASASHL;
r->vconst = v;
r->type = types[TINT];
}
break;
case OMUL:
case OLMUL:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASHL;
r->vconst = v;
r->type = types[TINT];
}
v = vlog(l);
if(v >= 0) {
n->op = OASHL;
n->left = r;
n->right = l;
r = l;
l = n->left;
r->vconst = v;
r->type = types[TINT];
simplifyshift(n);
}
break;
case OASLDIV:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASLSHR;
r->vconst = v;
r->type = types[TINT];
}
break;
case OLDIV:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OLSHR;
r->vconst = v;
r->type = types[TINT];
simplifyshift(n);
}
break;
case OASLMOD:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASAND;
r->vconst--;
}
break;
case OLMOD:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OAND;
r->vconst--;
}
break;
case OLSHR:
case OASHL:
case OASHR:
xcom(l);
xcom(r);
simplifyshift(n);
break;
default:
if(l != Z)
xcom(l);
if(r != Z)
xcom(r);
break;
}
if(n->addable >= 10)
return;
if(l != Z)
n->complex = l->complex;
if(r != Z) {
if(r->complex == n->complex)
n->complex = r->complex+1;
else
if(r->complex > n->complex)
n->complex = r->complex;
}
if(n->complex == 0)
n->complex++;
// if(com64(n))
// return;
switch(n->op) {
case OFUNC:
n->complex = FNX;
break;
case OEQ:
case ONE:
case OLE:
case OLT:
case OGE:
case OGT:
case OHI:
case OHS:
case OLO:
case OLS:
/*
* immediate operators, make const on right
*/
if(l->op == OCONST) {
n->left = r;
n->right = l;
n->op = invrel[relindex(n->op)];
}
break;
case OADD:
case OXOR:
case OAND:
case OOR:
/*
* immediate operators, make const on right
*/
if(l->op == OCONST) {
n->left = r;
n->right = l;
}
break;
}
}

407
src/cmd/9c/swt.c Normal file
View file

@ -0,0 +1,407 @@
// cmd/9c/swt.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
void
swit1(C1 *q, int nc, int32 def, Node *n)
{
Node tn, nod;
regalloc(&nod, n, Z);
/* always signed */
if(typev[n->type->etype])
nod.type = types[TVLONG];
else
nod.type = types[TLONG];
cgen(n, &nod);
regalloc(&tn, &regnode, Z);
swit2(q, nc, def, &nod, &tn);
regfree(&tn);
regfree(&nod);
}
void
swit2(C1 *q, int nc, int32 def, Node *n, Node *tn)
{
C1 *r;
int i;
Prog *sp;
if(nc < 5) {
for(i=0; i<nc; i++) {
if(sval(q->val)) {
gopcode(OEQ, n, Z, nodconst(q->val));
} else {
gopcode(OSUB, nodconst(q->val), n, tn);
gopcode(OEQ, tn, Z, nodconst(0));
}
patch(p, q->label);
q++;
}
gbranch(OGOTO);
patch(p, def);
return;
}
i = nc / 2;
r = q+i;
if(sval(r->val)) {
gopcode(OGT, n, Z, nodconst(r->val));
sp = p;
} else {
gopcode(OSUB, nodconst(r->val), n, tn);
gopcode(OGT, tn, Z, nodconst(0));
sp = p;
}
gbranch(OGOTO);
p->as = ABEQ;
patch(p, r->label);
swit2(q, i, def, n, tn);
patch(sp, pc);
swit2(r+1, nc-i-1, def, n, tn);
}
void
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
int sh;
int32 v;
Node *l;
/*
* n1 gets adjusted/masked value
* n2 gets address of cell
* n3 gets contents of cell
*/
l = b->left;
if(n2 != Z) {
regalloc(n1, l, nn);
reglcgen(n2, l, Z);
regalloc(n3, l, Z);
gopcode(OAS, n2, Z, n3);
gopcode(OAS, n3, Z, n1);
} else {
regalloc(n1, l, nn);
cgen(l, n1);
}
if(b->type->shift == 0 && typeu[b->type->etype]) {
v = ~0 + (1L << b->type->nbits);
gopcode(OAND, nodconst(v), Z, n1);
} else {
sh = 32 - b->type->shift - b->type->nbits;
if(sh > 0)
gopcode(OASHL, nodconst(sh), Z, n1);
sh += b->type->shift;
if(sh > 0)
if(typeu[b->type->etype])
gopcode(OLSHR, nodconst(sh), Z, n1);
else
gopcode(OASHR, nodconst(sh), Z, n1);
}
}
void
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
int32 v;
Node nod, *l;
int sh;
/*
* n1 has adjusted/masked value
* n2 has address of cell
* n3 has contents of cell
*/
l = b->left;
regalloc(&nod, l, Z);
v = ~0 + (1L << b->type->nbits);
gopcode(OAND, nodconst(v), Z, n1);
gopcode(OAS, n1, Z, &nod);
if(nn != Z)
gopcode(OAS, n1, Z, nn);
sh = b->type->shift;
if(sh > 0)
gopcode(OASHL, nodconst(sh), Z, &nod);
v <<= sh;
gopcode(OAND, nodconst(~v), Z, n3);
gopcode(OOR, n3, Z, &nod);
gopcode(OAS, &nod, Z, n2);
regfree(&nod);
regfree(n1);
regfree(n2);
regfree(n3);
}
int32
outstring(char *s, int32 n)
{
int32 r;
if(suppress)
return nstring;
r = nstring;
while(n) {
string[mnstring] = *s++;
mnstring++;
nstring++;
if(mnstring >= NSNAME) {
gpseudo(ADATA, symstring, nodconst(0L));
p->from.offset += nstring - NSNAME;
p->reg = NSNAME;
p->to.type = D_SCONST;
memmove(p->to.u.sval, string, NSNAME);
mnstring = 0;
}
n--;
}
return r;
}
int
mulcon(Node *n, Node *nn)
{
Node *l, *r, nod1, nod2;
Multab *m;
int32 v;
int o;
char code[sizeof(m->code)+2], *p;
if(typefd[n->type->etype])
return 0;
l = n->left;
r = n->right;
if(l->op == OCONST) {
l = r;
r = n->left;
}
if(r->op != OCONST)
return 0;
v = convvtox(r->vconst, n->type->etype);
if(v != r->vconst) {
if(debug['M'])
print("%L multiply conv: %lld\n", n->lineno, r->vconst);
return 0;
}
m = mulcon0(n, v);
if(!m) {
if(debug['M'])
print("%L multiply table: %lld\n", n->lineno, r->vconst);
return 0;
}
memmove(code, m->code, sizeof(m->code));
code[sizeof(m->code)] = 0;
p = code;
if(p[1] == 'i')
p += 2;
regalloc(&nod1, n, nn);
cgen(l, &nod1);
if(v < 0)
gopcode(ONEG, &nod1, Z, &nod1);
regalloc(&nod2, n, Z);
loop:
switch(*p) {
case 0:
regfree(&nod2);
gopcode(OAS, &nod1, Z, nn);
regfree(&nod1);
return 1;
case '+':
o = OADD;
goto addsub;
case '-':
o = OSUB;
addsub: /* number is r,n,l */
v = p[1] - '0';
r = &nod1;
if(v&4)
r = &nod2;
n = &nod1;
if(v&2)
n = &nod2;
l = &nod1;
if(v&1)
l = &nod2;
gopcode(o, l, n, r);
break;
default: /* op is shiftcount, number is r,l */
v = p[1] - '0';
r = &nod1;
if(v&2)
r = &nod2;
l = &nod1;
if(v&1)
l = &nod2;
v = *p - 'a';
if(v < 0 || v >= 32) {
diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
break;
}
gopcode(OASHL, nodconst(v), l, r);
break;
}
p += 2;
goto loop;
}
void
sextern(Sym *s, Node *a, int32 o, int32 w)
{
int32 e, lw;
for(e=0; e<w; e+=NSNAME) {
lw = NSNAME;
if(w-e < lw)
lw = w-e;
gpseudo(ADATA, s, nodconst(0));
p->from.offset += o+e;
p->reg = lw;
p->to.type = D_SCONST;
memmove(p->to.u.sval, a->cstring+e, lw);
}
}
void
gextern(Sym *s, Node *a, int32 o, int32 w)
{
gpseudo(ADATA, s, a);
p->from.offset += o;
p->reg = w;
if(p->to.type == D_OREG)
p->to.type = D_CONST;
}
void
outcode(void)
{
Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
if(pragcgobuf.to > pragcgobuf.start) {
Bprint(&outbuf, "\n");
Bprint(&outbuf, "$$ // exports\n\n");
Bprint(&outbuf, "$$ // local types\n\n");
Bprint(&outbuf, "$$ // cgo\n");
Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
Bprint(&outbuf, "\n$$\n\n");
}
Bprint(&outbuf, "!\n");
writeobj(ctxt, &outbuf);
lastp = nil;
}
int32
align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
int w, packw;
o = i;
w = 1;
packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
break;
case Asu2: /* padding at end of a struct */
w = *maxalign;
if(w < 1)
w = 1;
if(packflg)
packw = packflg;
break;
case Ael1: /* initial allign of struct element */
for(v=t; v->etype==TARRAY; v=v->link)
;
if(v->etype == TSTRUCT || v->etype == TUNION)
w = v->align;
else
w = ewidth[v->etype];
if(w < 1 || w > SZ_VLONG)
fatal(Z, "align");
if(packflg)
packw = packflg;
break;
case Ael2: /* width of a struct element */
o += t->width;
break;
case Aarg0: /* initial passbyptr argument in arg list */
if(typesu[t->etype]) {
o = align(o, types[TIND], Aarg1, nil);
o = align(o, types[TIND], Aarg2, nil);
}
break;
case Aarg1: /* initial align of parameter */
w = ewidth[t->etype];
if(w <= 0 || w >= SZ_VLONG) {
w = SZ_VLONG;
break;
}
w = 1;
break;
case Aarg2: /* width of a parameter */
o += t->width;
w = t->width;
if(w > SZ_VLONG)
w = SZ_VLONG;
break;
case Aaut3: /* total align of automatic */
o = align(o, t, Ael1, nil);
o = align(o, t, Ael2, nil);
break;
}
if(packw != 0 && xround(o, w) != xround(o, packw))
diag(Z, "#pragma pack changes offset of %T", t);
o = xround(o, w);
if(maxalign && *maxalign < w)
*maxalign = w;
if(debug['A'])
print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
return o;
}
int32
maxround(int32 max, int32 v)
{
v = xround(v, SZ_VLONG);
if(v > max)
return v;
return max;
}

1537
src/cmd/9c/txt.c Normal file

File diff suppressed because it is too large Load diff

1763
src/cmd/9g/cgen.c Normal file

File diff suppressed because it is too large Load diff

16
src/cmd/9g/doc.go Normal file
View file

@ -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

54
src/cmd/9g/galign.c Normal file
View file

@ -0,0 +1,54 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <u.h>
#include <libc.h>
#include "gg.h"
int thechar = '9';
char* thestring = "power64";
LinkArch* thelinkarch;
void
linkarchinit(void)
{
thestring = getgoarch();
if(strcmp(thestring, "power64le") == 0)
thelinkarch = &linkpower64le;
else
thelinkarch = &linkpower64;
}
vlong MAXWIDTH = 1LL<<50;
/*
* go declares several platform-specific type aliases:
* int, uint, float, and uintptr
*/
Typedef typedefs[] =
{
{"int", TINT, TINT64},
{"uint", TUINT, TUINT64},
{"uintptr", TUINTPTR, TUINT64},
{0}
};
void
betypeinit(void)
{
widthptr = 8;
widthint = 8;
widthreg = 8;
zprog.link = P;
zprog.as = AGOK;
zprog.reg = NREG;
zprog.from.name = D_NONE;
zprog.from.type = D_NONE;
zprog.from.reg = NREG;
zprog.to = zprog.from;
zprog.from3 = zprog.from;
listinit9();
}

117
src/cmd/9g/gg.h Normal file
View file

@ -0,0 +1,117 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef EXTERN
#define EXTERN extern
#endif
#include "../gc/go.h"
#include "../9l/9.out.h"
// TODO(minux): Remove when no longer used.
#define noimpl sysfatal("%s not implemented (%s:%d).", __func__, __FILE__, __LINE__)
#define TEXTFLAG reg
EXTERN int32 dynloc;
EXTERN uchar reg[NREG+NFREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Prog zprog;
EXTERN Node* newproc;
EXTERN Node* deferproc;
EXTERN Node* deferreturn;
EXTERN Node* panicindex;
EXTERN Node* panicslice;
EXTERN Node* panicdiv;
EXTERN Node* throwreturn;
extern vlong unmappedzero;
/*
* ggen.c
*/
void compile(Node*);
void gen(Node*);
Node* lookdot(Node*, Node*, int);
void cgen_as(Node*, Node*);
void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*);
void cgen_hmul(Node*, Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);
void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
int gen_as_init(Node*);
/*
* cgen.c
*/
void agen(Node*, Node*);
void agenr(Node*, Node*, Node*);
void cgenr(Node*, Node*, Node*);
void igen(Node*, Node*, Node*);
vlong fieldoffset(Type*, Node*);
void sgen(Node*, Node*, int64);
void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*);
void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
int componentgen(Node*, Node*);
/*
* gsubr.c
*/
void clearp(Prog*);
Prog* gbranch(int, Type*, int);
Prog* prog(int);
void gconv(int, int);
int conv2pt(Type*);
vlong convvtox(vlong, int);
void fnparam(Type*, int, int);
Prog* gop(int, Node*, Node*, Node*);
int optoas(int, Type*);
void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
void ginscon(int, vlong, Node*);
void ginscon2(int, Node*, vlong);
void buildtxt(void);
Plist* newplist(void);
int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*, Node*);
void nodfconst(Node*, Type*, Mpflt*);
void gtrack(Sym*);
void fixlargeoffset(Node *n);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*);
void complexgen(Node*, Node*);
/*
* gobj.c
*/
void datastring(char*, int, Addr*);
void datagostring(Strlit*, Addr*);
/*
* list.c
*/
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);

1034
src/cmd/9g/ggen.c Normal file

File diff suppressed because it is too large Load diff

240
src/cmd/9g/gobj.c Normal file
View file

@ -0,0 +1,240 @@
// Derived from Inferno utils/6c/swt.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
int
dsname(Sym *s, int off, char *t, int n)
{
Prog *p;
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.offset = off;
p->from.reg = NREG;
p->from.sym = linksym(s);
p->reg = n;
p->to.type = D_SCONST;
p->to.name = D_NONE;
p->to.reg = NREG;
p->to.offset = 0;
memmove(p->to.u.sval, t, n);
return off + n;
}
/*
* make a refer to the data s, s+len
* emitting DATA if needed.
*/
void
datastring(char *s, int len, Addr *a)
{
Sym *sym;
sym = stringsym(s, len);
a->type = D_OREG;
a->name = D_EXTERN;
a->etype = simtype[TINT];
a->offset = widthptr+widthint; // skip header
a->reg = NREG;
a->sym = linksym(sym);
a->node = sym->def;
}
/*
* make a refer to the string sval,
* emitting DATA if needed.
*/
void
datagostring(Strlit *sval, Addr *a)
{
Sym *sym;
sym = stringsym(sval->s, sval->len);
a->type = D_OREG;
a->name = D_EXTERN;
a->sym = linksym(sym);
a->reg = NREG;
a->node = sym->def;
a->offset = 0; // header
a->etype = TINT32;
}
void
gdata(Node *nam, Node *nr, int wid)
{
Prog *p;
if(nr->op == OLITERAL) {
switch(nr->val.ctype) {
case CTCPLX:
gdatacomplex(nam, nr->val.u.cval);
return;
case CTSTR:
gdatastring(nam, nr->val.u.sval);
return;
}
}
p = gins(ADATA, nam, nr);
p->reg = wid;
}
void
gdatacomplex(Node *nam, Mpcplx *cval)
{
Prog *p;
int w;
w = cplxsubtype(nam->type->etype);
w = types[w]->width;
p = gins(ADATA, nam, N);
p->reg = w;
p->to.type = D_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
p->reg = w;
p->from.offset += w;
p->to.type = D_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
void
gdatastring(Node *nam, Strlit *sval)
{
Prog *p;
Node nod1;
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
p->reg = types[tptr]->width;
p->to.type = D_CONST;
p->to.etype = simtype[tptr];
nodconst(&nod1, types[TINT], sval->len);
p = gins(ADATA, nam, &nod1);
p->reg = widthint;
p->from.offset += widthptr;
}
int
dstringptr(Sym *s, int off, char *str)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->reg = widthptr;
datastring(str, strlen(str)+1, &p->to);
p->to.type = D_CONST;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostrlitptr(Sym *s, int off, Strlit *lit)
{
Prog *p;
if(lit == nil)
return duintptr(s, off, 0);
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->reg = widthptr;
datagostring(lit, &p->to);
p->to.type = D_CONST;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostringptr(Sym *s, int off, char *str)
{
int n;
Strlit *lit;
if(str == nil)
return duintptr(s, off, 0);
n = strlen(str);
lit = mal(sizeof *lit + n);
strcpy(lit->s, str);
lit->len = n;
return dgostrlitptr(s, off, lit);
}
int
dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->reg = widthptr;
p->to.type = D_CONST;
p->to.name = D_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
return off;
}
void
nopout(Prog *p)
{
p->as = ANOP;
}

1705
src/cmd/9g/gsubr.c Normal file

File diff suppressed because it is too large Load diff

219
src/cmd/9g/opt.h Normal file
View file

@ -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,
};

94
src/cmd/9g/peep.c Normal file
View file

@ -0,0 +1,94 @@
// Derived from Inferno utils/6c/peep.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "opt.h"
void
peep(Prog *p)
{
USED(p);
// TODO(minux)
return;
}
void
excise(Flow *r)
{
Prog *p;
p = r->prog;
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
*p = zprog;
p->as = ANOP;
ostats.ndelmov++;
}
int
regtyp(Adr *a)
{
switch(a->type) {
default:
return 0;
case D_REG:
case D_FREG:
return 1;
}
}
int
sameaddr(Addr *a, Addr *v)
{
if(a->type != v->type)
return 0;
if(regtyp(v) && a->reg == v->reg)
return 1;
if(v->type == D_AUTO || v->type == D_PARAM)
if(v->offset == a->offset)
return 1;
return 0;
}
int
smallindir(Addr *a, Addr *reg)
{
return reg->type == D_REG && a->type == D_OREG &&
a->reg == reg->reg &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
return a->type == D_REG && a->reg == REGSP;
}

138
src/cmd/9g/prog.c Normal file
View file

@ -0,0 +1,138 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "opt.h"
enum {
LeftRdwr = LeftRead | LeftWrite,
RightRdwr = RightRead | RightWrite,
};
// This table gives the basic information about instruction
// generated by the compiler and processed in the optimizer.
// See opt.h for bit definitions.
//
// Instructions not generated need not be listed.
// As an exception to that rule, we typically write down all the
// size variants of an operation even if we just use a subset.
//
// The table is formatted for 8-space tabs.
static ProgInfo progtable[ALAST] = {
[ATYPE]= {Pseudo | Skip},
[ATEXT]= {Pseudo},
[AFUNCDATA]= {Pseudo},
[APCDATA]= {Pseudo},
[AUNDEF]= {Break},
[AUSEFIELD]= {OK},
[ACHECKNIL]= {LeftRead},
[AVARDEF]= {Pseudo | RightWrite},
[AVARKILL]= {Pseudo | RightWrite},
// NOP is an internal no-op that also stands
// for USED and SET annotations, not the Power opcode.
[ANOP]= {LeftRead | RightWrite},
// Integer
[AADD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASUB]= {SizeQ | LeftRead | RegRead | RightWrite},
[ANEG]= {SizeQ | LeftRead | RegRead | RightWrite},
[AAND]= {SizeQ | LeftRead | RegRead | RightWrite},
[AOR]= {SizeQ | LeftRead | RegRead | RightWrite},
[AXOR]= {SizeQ | LeftRead | RegRead | RightWrite},
[AMULLD]= {SizeQ | LeftRead | RegRead | RightWrite},
[AMULLW]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULHD]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULHDU]= {SizeL | LeftRead | RegRead | RightWrite},
[ADIVD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ADIVDU]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASLD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASRD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASRAD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ACMP]= {SizeQ | LeftRead | RightRead},
[ACMPU]= {SizeQ | LeftRead | RightRead},
[ATD]= {SizeQ | RightRead},
// Floating point.
[AFADD]= {SizeD | LeftRead | RegRead | RightWrite},
[AFADDS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFSUB]= {SizeD | LeftRead | RegRead | RightWrite},
[AFSUBS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFMUL]= {SizeD | LeftRead | RegRead | RightWrite},
[AFMULS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFDIV]= {SizeD | LeftRead | RegRead | RightWrite},
[AFDIVS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFCTIDZ]= {SizeF | LeftRead | RegRead | RightWrite},
[AFCFID]= {SizeF | LeftRead | RegRead | RightWrite},
[AFCMPU]= {SizeD | LeftRead | RightRead},
[AFRSP]= {SizeD | LeftRead | RightWrite | Conv},
// Moves
[AMOVB]= {SizeB | LeftRead | RightWrite | Move | Conv},
[AMOVBU]= {SizeB | LeftRead | RightWrite | Move | Conv | PostInc},
[AMOVBZ]= {SizeB | LeftRead | RightWrite | Move | Conv},
[AMOVH]= {SizeW | LeftRead | RightWrite | Move | Conv},
[AMOVHU]= {SizeW | LeftRead | RightWrite | Move | Conv | PostInc},
[AMOVHZ]= {SizeW | LeftRead | RightWrite | Move | Conv},
[AMOVW]= {SizeL | LeftRead | RightWrite | Move | Conv},
// there is no AMOVWU.
[AMOVWZU]= {SizeL | LeftRead | RightWrite | Move | Conv | PostInc},
[AMOVWZ]= {SizeL | LeftRead | RightWrite | Move | Conv},
[AMOVD]= {SizeQ | LeftRead | RightWrite | Move},
[AMOVDU]= {SizeQ | LeftRead | RightWrite | Move | PostInc},
[AFMOVS]= {SizeF | LeftRead | RightWrite | Move | Conv},
[AFMOVD]= {SizeD | LeftRead | RightWrite | Move},
// Jumps
[ABR]= {Jump | Break},
[ABL]= {Call},
[ABEQ]= {Cjmp},
[ABNE]= {Cjmp},
[ABGE]= {Cjmp},
[ABLT]= {Cjmp},
[ABGT]= {Cjmp},
[ABLE]= {Cjmp},
[ARETURN]= {Break},
// In addtion, duffzero reads R0,R2 and writes R2. This fact must be
// encoded in peep.c (TODO)
[ADUFFZERO]= {Call},
// In addtion, duffcopy reads R0,R2,R3 and writes R2,R3. This fact must be
// encoded in peep.c (TODO)
[ADUFFCOPY]= {Call},
};
void
proginfo(ProgInfo *info, Prog *p)
{
*info = progtable[p->as];
if(info->flags == 0) {
*info = progtable[AADD];
fatal("proginfo: unknown instruction %P", p);
}
if((info->flags & RegRead) && p->reg == NREG) {
info->flags &= ~RegRead;
info->flags |= /*CanRegRead |*/ RightRead;
}
if(p->from.type == D_OREG && p->from.reg != NREG) {
info->reguse |= RtoB(p->from.reg);
if(info->flags & PostInc) {
info->regset |= RtoB(p->from.reg);
}
}
if(p->to.type == D_OREG && p->to.reg != NREG) {
info->reguse |= RtoB(p->to.reg);
if(info->flags & PostInc) {
info->regset |= RtoB(p->to.reg);
}
}
if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) {
info->flags &= ~LeftRead;
info->flags |= LeftAddr;
}
}

161
src/cmd/9g/reg.c Normal file
View file

@ -0,0 +1,161 @@
// Derived from Inferno utils/6c/reg.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "opt.h"
void
regopt(Prog *p)
{
USED(p);
// TODO(minux)
return;
}
/*
* track register variables including external registers:
* bit reg
* 0 R0
* 1 R1
* ... ...
* 31 R31
* 32+0 F0
* 32+1 F1
* ... ...
* 32+31 F31
*/
uint64
RtoB(int r)
{
if(r >= D_R0 && r <= D_R0+31)
return 1ULL << (r - D_R0);
return 0;
}
int
BtoR(uint64 b)
{
b &= 0xffffffff;
if(b == 0)
return 0;
return bitno(b) + D_R0;
}
uint64
FtoB(int r)
{
if(r >= D_F0 && r <= D_F0+31)
return 1ULL << (32 + r - D_F0);
return 0;
}
int
BtoF(uint64 b)
{
b >>= 32;
if(b == 0)
return 0;
return bitno(b) + D_F0;
}
void
dumpone(Flow *f, int isreg)
{
int z;
Bits bit;
Reg *r;
print("%d:%P", f->loop, f->prog);
if(isreg) {
r = (Reg*)f;
for(z=0; z<BITS; z++)
bit.b[z] =
r->set.b[z] |
r->use1.b[z] |
r->use2.b[z] |
r->refbehind.b[z] |
r->refahead.b[z] |
r->calbehind.b[z] |
r->calahead.b[z] |
r->regdiff.b[z] |
r->act.b[z] |
0;
if(bany(&bit)) {
print("\t");
if(bany(&r->set))
print(" s:%Q", r->set);
if(bany(&r->use1))
print(" u1:%Q", r->use1);
if(bany(&r->use2))
print(" u2:%Q", r->use2);
if(bany(&r->refbehind))
print(" rb:%Q ", r->refbehind);
if(bany(&r->refahead))
print(" ra:%Q ", r->refahead);
if(bany(&r->calbehind))
print(" cb:%Q ", r->calbehind);
if(bany(&r->calahead))
print(" ca:%Q ", r->calahead);
if(bany(&r->regdiff))
print(" d:%Q ", r->regdiff);
if(bany(&r->act))
print(" a:%Q ", r->act);
}
}
print("\n");
}
void
dumpit(char *str, Flow *r0, int isreg)
{
Flow *r, *r1;
print("\n%s\n", str);
for(r = r0; r != nil; r = r->link) {
dumpone(r, isreg);
r1 = r->p2;
if(r1 != nil) {
print(" pred:");
for(; r1 != nil; r1 = r1->p2link)
print(" %.4ud", (int)r1->prog->pc);
print("\n");
}
// r1 = r->s1;
// if(r1 != R) {
// print(" succ:");
// for(; r1 != R; r1 = r1->s1)
// print(" %.4ud", (int)r1->prog->pc);
// print("\n");
// }
}
}

514
src/cmd/9l/9.out.h Normal file
View file

@ -0,0 +1,514 @@
// cmd/9c/9.out.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/*
* powerpc 64
*/
#define NSNAME 8
#define NSYM 50
#define NREG 32 /* number of general registers */
#define NFREG 32 /* number of floating point registers */
#include "../ld/textflag.h"
enum
{
REGZERO = 0, /* set to zero */
REGSP = 1,
REGSB = 2,
REGRET = 3,
REGARG = -1, /* -1 disables passing the first argument in register */
REGRT1 = 3, /* reserved for runtime, duffzero and duffcopy */
REGRT2 = 4, /* reserved for runtime, duffcopy */
REGMIN = 7, /* register variables allocated from here to REGMAX */
REGENV = 11, /* environment for closures */
REGMAX = 27,
REGEXT = 30, /* external registers allocated from here down */
REGG = 30, /* G */
REGTMP = 31, /* used by the linker */
FREGRET = 0,
FREGMIN = 17, /* first register variable */
FREGMAX = 26, /* last register variable for 9g only */
FREGEXT = 26, /* first external register */
FREGCVI = 27, /* floating conversion constant */
FREGZERO = 28, /* both float and double */
FREGHALF = 29, /* double */
FREGONE = 30, /* double */
FREGTWO = 31 /* double */
/*
* GENERAL:
*
* compiler allocates R3 up as temps
* compiler allocates register variables R7-R27
* compiler allocates external registers R30 down
*
* compiler allocates register variables F17-F26
* compiler allocates external registers F26 down
*/
};
enum {
BIG = 32768-8,
};
enum {
/* mark flags */
LABEL = 1<<0,
LEAF = 1<<1,
FLOAT = 1<<2,
BRANCH = 1<<3,
LOAD = 1<<4,
FCMP = 1<<5,
SYNC = 1<<6,
LIST = 1<<7,
FOLL = 1<<8,
NOSCHED = 1<<9,
};
enum
{
C_NONE,
C_REG,
C_FREG,
C_CREG,
C_SPR, /* special processor register */
C_ZCON,
C_SCON, /* 16 bit signed */
C_UCON, /* low 16 bits 0 */
C_ADDCON, /* -0x8000 <= v < 0 */
C_ANDCON, /* 0 < v <= 0xFFFF */
C_LCON, /* other 32 */
C_DCON, /* other 64 (could subdivide further) */
C_SACON,
C_SECON,
C_LACON,
C_LECON,
C_SBRA,
C_LBRA,
C_SAUTO,
C_LAUTO,
C_SEXT,
C_LEXT,
C_ZOREG,
C_SOREG,
C_LOREG,
C_FPSCR,
C_MSR,
C_XER,
C_LR,
C_CTR,
C_ANY,
C_GOK,
C_ADDR,
C_NCLASS, /* must be the last */
};
enum as
{
AXXX,
AADD,
AADDCC,
AADDV,
AADDVCC,
AADDC,
AADDCCC,
AADDCV,
AADDCVCC,
AADDME,
AADDMECC,
AADDMEVCC,
AADDMEV,
AADDE,
AADDECC,
AADDEVCC,
AADDEV,
AADDZE,
AADDZECC,
AADDZEVCC,
AADDZEV,
AAND,
AANDCC,
AANDN,
AANDNCC,
ABC,
ABCL,
ABEQ,
ABGE,
ABGT,
ABL,
ABLE,
ABLT,
ABNE,
ABR,
ABVC,
ABVS,
ACMP,
ACMPU,
ACNTLZW,
ACNTLZWCC,
ACRAND,
ACRANDN,
ACREQV,
ACRNAND,
ACRNOR,
ACROR,
ACRORN,
ACRXOR,
ADIVW,
ADIVWCC,
ADIVWVCC,
ADIVWV,
ADIVWU,
ADIVWUCC,
ADIVWUVCC,
ADIVWUV,
AEQV,
AEQVCC,
AEXTSB,
AEXTSBCC,
AEXTSH,
AEXTSHCC,
AFABS,
AFABSCC,
AFADD,
AFADDCC,
AFADDS,
AFADDSCC,
AFCMPO,
AFCMPU,
AFCTIW,
AFCTIWCC,
AFCTIWZ,
AFCTIWZCC,
AFDIV,
AFDIVCC,
AFDIVS,
AFDIVSCC,
AFMADD,
AFMADDCC,
AFMADDS,
AFMADDSCC,
AFMOVD,
AFMOVDCC,
AFMOVDU,
AFMOVS,
AFMOVSU,
AFMSUB,
AFMSUBCC,
AFMSUBS,
AFMSUBSCC,
AFMUL,
AFMULCC,
AFMULS,
AFMULSCC,
AFNABS,
AFNABSCC,
AFNEG,
AFNEGCC,
AFNMADD,
AFNMADDCC,
AFNMADDS,
AFNMADDSCC,
AFNMSUB,
AFNMSUBCC,
AFNMSUBS,
AFNMSUBSCC,
AFRSP,
AFRSPCC,
AFSUB,
AFSUBCC,
AFSUBS,
AFSUBSCC,
AMOVMW,
ALSW,
ALWAR,
AMOVWBR,
AMOVB,
AMOVBU,
AMOVBZ,
AMOVBZU,
AMOVH,
AMOVHBR,
AMOVHU,
AMOVHZ,
AMOVHZU,
AMOVW,
AMOVWU,
AMOVFL,
AMOVCRFS,
AMTFSB0,
AMTFSB0CC,
AMTFSB1,
AMTFSB1CC,
AMULHW,
AMULHWCC,
AMULHWU,
AMULHWUCC,
AMULLW,
AMULLWCC,
AMULLWVCC,
AMULLWV,
ANAND,
ANANDCC,
ANEG,
ANEGCC,
ANEGVCC,
ANEGV,
ANOR,
ANORCC,
AOR,
AORCC,
AORN,
AORNCC,
AREM,
AREMCC,
AREMV,
AREMVCC,
AREMU,
AREMUCC,
AREMUV,
AREMUVCC,
ARFI,
ARLWMI,
ARLWMICC,
ARLWNM,
ARLWNMCC,
ASLW,
ASLWCC,
ASRW,
ASRAW,
ASRAWCC,
ASRWCC,
ASTSW,
ASTWCCC,
ASUB,
ASUBCC,
ASUBVCC,
ASUBC,
ASUBCCC,
ASUBCV,
ASUBCVCC,
ASUBME,
ASUBMECC,
ASUBMEVCC,
ASUBMEV,
ASUBV,
ASUBE,
ASUBECC,
ASUBEV,
ASUBEVCC,
ASUBZE,
ASUBZECC,
ASUBZEVCC,
ASUBZEV,
ASYNC,
AXOR,
AXORCC,
ADCBF,
ADCBI,
ADCBST,
ADCBT,
ADCBTST,
ADCBZ,
AECIWX,
AECOWX,
AEIEIO,
AICBI,
AISYNC,
APTESYNC,
ATLBIE,
ATLBIEL,
ATLBSYNC,
ATW,
ASYSCALL,
ADATA,
AGLOBL,
AGOK,
AHISTORY,
ANAME,
ANOP,
ARETURN,
ATEXT,
AWORD,
AEND,
ADYNT,
AINIT,
ASIGNAME,
ARFCI,
/* optional on 32-bit */
AFRES,
AFRESCC,
AFRSQRTE,
AFRSQRTECC,
AFSEL,
AFSELCC,
AFSQRT,
AFSQRTCC,
AFSQRTS,
AFSQRTSCC,
/* 64-bit */
ACNTLZD,
ACNTLZDCC,
ACMPW, /* CMP with L=0 */
ACMPWU,
ADIVD,
ADIVDCC,
ADIVDVCC,
ADIVDV,
ADIVDU,
ADIVDUCC,
ADIVDUVCC,
ADIVDUV,
AEXTSW,
AEXTSWCC,
/* AFCFIW; AFCFIWCC */
AFCFID,
AFCFIDCC,
AFCTID,
AFCTIDCC,
AFCTIDZ,
AFCTIDZCC,
ALDAR,
AMOVD,
AMOVDU,
AMOVWZ,
AMOVWZU,
AMULHD,
AMULHDCC,
AMULHDU,
AMULHDUCC,
AMULLD,
AMULLDCC,
AMULLDVCC,
AMULLDV,
ARFID,
ARLDMI,
ARLDMICC,
ARLDC,
ARLDCCC,
ARLDCR,
ARLDCRCC,
ARLDCL,
ARLDCLCC,
ASLBIA,
ASLBIE,
ASLBMFEE,
ASLBMFEV,
ASLBMTE,
ASLD,
ASLDCC,
ASRD,
ASRAD,
ASRADCC,
ASRDCC,
ASTDCCC,
ATD,
/* 64-bit pseudo operation */
ADWORD,
AREMD,
AREMDCC,
AREMDV,
AREMDVCC,
AREMDU,
AREMDUCC,
AREMDUV,
AREMDUVCC,
/* more 64-bit operations */
AHRFID,
AUNDEF,
AUSEFIELD,
ATYPE,
AFUNCDATA,
APCDATA,
ACHECKNIL,
AVARDEF,
AVARKILL,
ADUFFCOPY,
ADUFFZERO,
ALAST
};
/* type/name */
enum
{
D_GOK = 0,
D_NONE,
/* name */
D_EXTERN,
D_STATIC,
D_AUTO,
D_PARAM,
/* type */
D_BRANCH,
D_OREG,
D_CONST,
D_FCONST,
D_SCONST,
D_REG,
D_FPSCR,
D_MSR,
D_FREG,
D_CREG,
D_SPR,
D_OPT, /* branch/trap option */
D_FILE,
D_FILE1,
D_DCR, /* device control register */
D_DCONST,
D_ADDR, // not used, use D_CONST with non-empty sym.
/* reg names for 9g OREGISTER */
D_R0 = 0, // type is D_REG
D_F0 = D_R0+NREG, // type is D_FREG
/* reg names iff type is D_SPR */
D_XER = 1,
D_LR = 8,
D_CTR = 9
/* and many supervisor level registers */
};
/*
* this is the ranlib header
*/
#define SYMDEF "__.GOSYMDEF"

5
src/cmd/9l/Makefile Normal file
View file

@ -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

338
src/cmd/9l/asm.c Normal file
View file

@ -0,0 +1,338 @@
// Inferno utils/5l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Writing object files.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
#include "../ld/dwarf.h"
char linuxdynld[] = "/lib64/ld64.so.1";
char freebsddynld[] = "XXX";
char openbsddynld[] = "XXX";
char netbsddynld[] = "XXX";
char dragonflydynld[] = "XXX";
char solarisdynld[] = "XXX";
static int
needlib(char *name)
{
char *p;
LSym *s;
if(*name == '\0')
return 0;
/* reuse hash code in symbol table */
p = smprint(".dynlib.%s", name);
s = linklookup(ctxt, p, 0);
free(p);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
return 1;
}
return 0;
}
int nelfsym = 1;
// b is the addresses, a is the I-form branch instruction template, peform
// addition so that the instruction jumps to address (offset) b.
static int32
braddoff(int32 a, int32 b)
{
return (((uint32)a) & 0xfc000003U) | (0x03fffffcU & (uint32)((a & 0x3fffffcU) + b));
}
void
adddynrela(LSym *rel, LSym *s, Reloc *r)
{
// TODO(minux)
USED(rel); USED(s); USED(r);
}
void
adddynrel(LSym *s, Reloc *r)
{
LSym *targ;
// TODO(minux)
targ = r->sym;
ctxt->cursym = s;
diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
}
int
elfreloc1(Reloc *r, vlong sectoff)
{
USED(r); USED(sectoff);
// TODO(minux)
return -1;
}
void
elfsetupplt(void)
{
// TODO(minux)
return;
}
int
machoreloc1(Reloc *r, vlong sectoff)
{
USED(r);
USED(sectoff);
return -1;
}
int
archreloc(Reloc *r, LSym *s, vlong *val)
{
uint32 o1, o2;
int32 t;
if(linkmode == LinkExternal) {
// TODO(minux): translate R_ADDRPOWER and R_CALLPOWER into standard ELF relocations.
// R_ADDRPOWER corresponds to R_PPC_ADDR16_HA and R_PPC_ADDR16_LO.
// R_CALLPOWER corresponds to R_PPC_REL24.
return -1;
}
switch(r->type) {
case R_CONST:
*val = r->add;
return 0;
case R_GOTOFF:
*val = symaddr(r->sym) + r->add - symaddr(linklookup(ctxt, ".got", 0));
return 0;
case R_ADDRPOWER:
// r->add is two power64 instructions holding an immediate 32-bit constant.
// We want to add r->sym's address to that constant.
// The encoding of the immediate x<<16 + y,
// where x is the low 16 bits of the first instruction and y is the low 16
// bits of the second. Both x and y are signed (int16, not uint16).
o1 = r->add >> 32;
o2 = r->add;
t = symaddr(r->sym);
if(t < 0) {
ctxt->diag("relocation for %s is too big (>=2G): %lld", s->name, symaddr(r->sym));
}
t += ((o1 & 0xffff) << 16) + ((int32)o2 << 16 >> 16);
if(t & 0x8000)
t += 0x10000;
o1 = (o1 & 0xffff0000) | ((t >> 16) & 0xffff);
o2 = (o2 & 0xffff0000) | (t & 0xffff);
// when laid out, the instruction order must always be o1, o2.
if(ctxt->arch->endian == BigEndian)
*val = ((vlong)o1 << 32) | o2;
else
*val = ((vlong)o2 << 32) | o1;
return 0;
case R_CALLPOWER:
*val = braddoff((uint32)r->add, (int32)(symaddr(r->sym) - (s->value + r->off)));
return 0;
}
return -1;
}
void
adddynsym(Link *ctxt, LSym *s)
{
USED(ctxt); USED(s);
// TODO(minux)
return;
}
void
adddynlib(char *lib)
{
LSym *s;
if(!needlib(lib))
return;
if(iself) {
s = linklookup(ctxt, ".dynstr", 0);
if(s->size == 0)
addstring(s, "");
elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
} else {
diag("adddynlib: unsupported binary format");
}
}
void
asmb(void)
{
uint32 symo;
Section *sect;
LSym *sym;
int i;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
if(iself)
asmbelfsetup();
sect = segtext.sect;
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len);
for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len);
}
if(segrodata.filelen > 0) {
if(debug['v'])
Bprint(&bso, "%5.2f rodatblk\n", cputime());
Bflush(&bso);
cseek(segrodata.fileoff);
datblk(segrodata.vaddr, segrodata.filelen);
}
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
Bflush(&bso);
cseek(segdata.fileoff);
datblk(segdata.vaddr, segdata.filelen);
/* output symbol table */
symsize = 0;
lcsize = 0;
symo = 0;
if(!debug['s']) {
// TODO: rationalize
if(debug['v'])
Bprint(&bso, "%5.2f sym\n", cputime());
Bflush(&bso);
switch(HEADTYPE) {
default:
if(iself)
goto ElfSym;
case Hplan9:
symo = segdata.fileoff+segdata.filelen;
break;
ElfSym:
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, INITRND);
break;
}
cseek(symo);
switch(HEADTYPE) {
default:
if(iself) {
if(debug['v'])
Bprint(&bso, "%5.2f elfsym\n", cputime());
asmelfsym();
cflush();
cwrite(elfstrdat, elfstrsize);
if(debug['v'])
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
if(linkmode == LinkExternal)
elfemitreloc();
}
break;
case Hplan9:
asmplan9sym();
cflush();
sym = linklookup(ctxt, "pclntab", 0);
if(sym != nil) {
lcsize = sym->np;
for(i=0; i < lcsize; i++)
cput(sym->p[i]);
cflush();
}
break;
}
}
ctxt->cursym = nil;
if(debug['v'])
Bprint(&bso, "%5.2f header\n", cputime());
Bflush(&bso);
cseek(0L);
switch(HEADTYPE) {
default:
case Hplan9: /* plan 9 */
LPUT(0x647); /* magic */
LPUT(segtext.filelen); /* sizes */
LPUT(segdata.filelen);
LPUT(segdata.len - segdata.filelen);
LPUT(symsize); /* nsyms */
LPUT(entryvalue()); /* va of entry */
LPUT(0L);
LPUT(lcsize);
break;
case Hlinux:
case Hfreebsd:
case Hnetbsd:
case Hopenbsd:
case Hnacl:
asmbelf(symo);
break;
}
cflush();
if(debug['c']){
print("textsize=%ulld\n", segtext.filelen);
print("datsize=%ulld\n", segdata.filelen);
print("bsssize=%ulld\n", segdata.len - segdata.filelen);
print("symsize=%d\n", symsize);
print("lcsize=%d\n", lcsize);
print("total=%lld\n", segtext.filelen+segdata.len+symsize+lcsize);
}
}
vlong
rnd(vlong v, int32 r)
{
vlong c;
if(r <= 0)
return v;
v += r - 1;
c = v % r;
if(c < 0)
c += r;
v -= c;
return v;
}

16
src/cmd/9l/doc.go Normal file
View file

@ -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

100
src/cmd/9l/l.h Normal file
View file

@ -0,0 +1,100 @@
// cmd/9l/l.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "9.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
enum
{
thechar = '9',
PtrSize = 8,
IntSize = 8,
RegSize = 8,
MaxAlign = 32, // max data alignment
FuncAlign = 8
};
#define P ((Prog*)0)
#define S ((LSym*)0)
enum
{
FPCHIP = 1,
STRINGSZ = 200,
MAXHIST = 20, /* limit of path elements for history symbols */
DATBLK = 1024,
NHASH = 10007,
NHUNK = 100000,
MINSIZ = 64,
NENT = 100,
NSCHED = 20,
MINLC = 4,
Roffset = 22, /* no. bits for offset in relocation address */
Rindex = 10 /* no. bits for index in relocation address */
};
EXTERN int32 autosize;
EXTERN LSym* datap;
EXTERN int debug[128];
EXTERN int32 lcsize;
EXTERN char literal[32];
EXTERN int nerrors;
EXTERN vlong instoffset;
EXTERN char* rpath;
EXTERN vlong pc;
EXTERN int32 symsize;
EXTERN int32 staticgen;
EXTERN Prog* lastp;
EXTERN vlong textsize;
void asmb(void);
void adddynlib(char *lib);
void adddynrel(LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
void listinit(void);
vlong rnd(vlong, int32);
#define LPUT(a) (ctxt->arch->endian == BigEndian ? lputb(a):lputl(a))
#define WPUT(a) (ctxt->arch->endian == BigEndian ? wputb(a):wputl(a))
#define VPUT(a) (ctxt->arch->endian == BigEndian ? vputb(a):vputl(a))
/* Used by ../ld/dwarf.c */
enum
{
DWARFREGSP = 1
};

40
src/cmd/9l/list.c Normal file
View file

@ -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();
}

108
src/cmd/9l/obj.c Normal file
View file

@ -0,0 +1,108 @@
// Inferno utils/5l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Reading object files.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
#include "../ld/dwarf.h"
#include <ar.h>
char *thestring = "power64";
LinkArch *thelinkarch;
void
linkarchinit(void)
{
thestring = getgoarch();
if(strcmp(thestring, "power64le") == 0)
thelinkarch = &linkpower64le;
else
thelinkarch = &linkpower64;
}
void
archinit(void)
{
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
// Go was built; see ../../make.bash.
if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
linkmode = LinkInternal;
switch(HEADTYPE) {
default:
if(linkmode == LinkAuto)
linkmode = LinkInternal;
if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
break;
}
switch(HEADTYPE) {
default:
diag("unknown -H option");
errorexit();
case Hplan9: /* plan 9 */
HEADR = 32L;
if(INITTEXT == -1)
INITTEXT = 4128;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 4096;
break;
case Hlinux: /* power64 elf */
debug['d'] = 1; // TODO(minux): dynamic linking is not supported yet.
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
INITTEXT = 0x10000 + HEADR;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 0x10000;
break;
case Hnacl:
elfinit();
HEADR = 0x10000;
funcalign = 16;
if(INITTEXT == -1)
INITTEXT = 0x20000;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 0x10000;
break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%ux is ignored because of -R0x%ux\n",
INITDAT, INITRND);
}

View file

@ -220,6 +220,31 @@ slookup(char *s)
return lookup(); 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* Sym*
lookup(void) lookup(void)
{ {

View file

@ -65,14 +65,14 @@ argsize(int doret)
} }
//print(" %d %T\n", s, t); //print(" %d %T\n", s, t);
} }
if(thechar == '6') if(thechar == '6' || thechar == '9')
s = (s+7) & ~7; s = (s+7) & ~7;
else else
s = (s+3) & ~3; s = (s+3) & ~3;
if(doret && thisfn->link->etype != TVOID) { if(doret && thisfn->link->etype != TVOID) {
s = align(s, thisfn->link, Aarg1, nil); s = align(s, thisfn->link, Aarg1, nil);
s = align(s, thisfn->link, Aarg2, nil); s = align(s, thisfn->link, Aarg2, nil);
if(thechar == '6') if(thechar == '6' || thechar == '9')
s = (s+7) & ~7; s = (s+7) & ~7;
else else
s = (s+3) & ~3; s = (s+3) & ~3;

View file

@ -130,15 +130,23 @@ func usage() {
} }
var ptrSizeMap = map[string]int64{ var ptrSizeMap = map[string]int64{
"386": 4, "386": 4,
"amd64": 8, "amd64": 8,
"arm": 4, "arm": 4,
"ppc64": 8,
"ppc64le": 8,
"power64": 8,
"power64le": 8,
} }
var intSizeMap = map[string]int64{ var intSizeMap = map[string]int64{
"386": 4, "386": 4,
"amd64": 8, "amd64": 8,
"arm": 4, "arm": 4,
"ppc64": 8,
"ppc64le": 8,
"power64": 8,
"power64le": 8,
} }
var cPrefix string var cPrefix string

49
src/cmd/dist/build.c vendored
View file

@ -39,7 +39,7 @@ static void dopack(char*, char*, char**, int);
static char *findgoversion(void); static char *findgoversion(void);
// The known architecture letters. // The known architecture letters.
static char *gochars = "5668"; static char *gochars = "566899";
// The known architectures. // The known architectures.
static char *okgoarch[] = { static char *okgoarch[] = {
@ -48,6 +48,8 @@ static char *okgoarch[] = {
"amd64", "amd64",
"amd64p32", "amd64p32",
"386", "386",
"power64",
"power64le",
}; };
// The known operating systems. // The known operating systems.
@ -344,6 +346,7 @@ static char *oldtool[] = {
"5a", "5c", "5g", "5l", "5a", "5c", "5g", "5l",
"6a", "6c", "6g", "6l", "6a", "6c", "6g", "6l",
"8a", "8c", "8g", "8l", "8a", "8c", "8g", "8l",
"9a", "9c", "9g", "9l",
"6cov", "6cov",
"6nm", "6nm",
"6prof", "6prof",
@ -521,6 +524,7 @@ static struct {
"anames5.c", "anames5.c",
"anames6.c", "anames6.c",
"anames8.c", "anames8.c",
"anames9.c",
}}, }},
{"cmd/cc", { {"cmd/cc", {
"-pgen.c", "-pgen.c",
@ -549,6 +553,11 @@ static struct {
"../cc/pswt.c", "../cc/pswt.c",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a", "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
}}, }},
{"cmd/9c", {
"../cc/pgen.c",
"../cc/pswt.c",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
}},
{"cmd/5g", { {"cmd/5g", {
"../gc/cplx.c", "../gc/cplx.c",
"../gc/pgen.c", "../gc/pgen.c",
@ -573,6 +582,14 @@ static struct {
"../gc/popt.h", "../gc/popt.h",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a", "$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", { {"cmd/5l", {
"../ld/*", "../ld/*",
}}, }},
@ -582,6 +599,9 @@ static struct {
{"cmd/8l", { {"cmd/8l", {
"../ld/*", "../ld/*",
}}, }},
{"cmd/9l", {
"../ld/*",
}},
{"cmd/go", { {"cmd/go", {
"zdefaultcc.go", "zdefaultcc.go",
}}, }},
@ -618,6 +638,7 @@ static struct {
{"anames5.c", mkanames}, {"anames5.c", mkanames},
{"anames6.c", mkanames}, {"anames6.c", mkanames},
{"anames8.c", mkanames}, {"anames8.c", mkanames},
{"anames9.c", mkanames},
{"zasm_", mkzasm}, {"zasm_", mkzasm},
{"zdefaultcc.go", mkzdefaultcc}, {"zdefaultcc.go", mkzdefaultcc},
{"zsys_", mkzsys}, {"zsys_", mkzsys},
@ -1163,12 +1184,26 @@ shouldbuild(char *file, char *dir)
// Check file name for GOOS or GOARCH. // Check file name for GOOS or GOARCH.
name = lastelem(file); name = lastelem(file);
for(i=0; i<nelem(okgoos); i++) for(i=0; i<nelem(okgoos); i++) {
if(contains(name, okgoos[i]) && !streq(okgoos[i], goos)) if(streq(okgoos[i], goos))
continue;
p = xstrstr(name, okgoos[i]);
if(p == nil)
continue;
p += xstrlen(okgoos[i]);
if(*p == '.' || *p == '_' || *p == '\0')
return 0; return 0;
for(i=0; i<nelem(okgoarch); i++) }
if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch)) for(i=0; i<nelem(okgoarch); i++) {
if(streq(okgoarch[i], goarch))
continue;
p = xstrstr(name, okgoarch[i]);
if(p == nil)
continue;
p += xstrlen(okgoarch[i]);
if(*p == '.' || *p == '_' || *p == '\0')
return 0; return 0;
}
// Omit test files. // Omit test files.
if(contains(name, "_test")) if(contains(name, "_test"))
@ -1367,6 +1402,10 @@ static char *cleantab[] = {
"cmd/8c", "cmd/8c",
"cmd/8g", "cmd/8g",
"cmd/8l", "cmd/8l",
"cmd/9a",
"cmd/9c",
"cmd/9g",
"cmd/9l",
"cmd/cc", "cmd/cc",
"cmd/gc", "cmd/gc",
"cmd/go", "cmd/go",

View file

@ -63,7 +63,7 @@ gcopnames(char *dir, char *file)
vfree(&fields); 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. // The format is much the same as the Go opcodes above.
// it also writes out cnames array for C_* constants. // it also writes out cnames array for C_* constants.
void void

View file

@ -148,6 +148,13 @@ static struct {
{"arm", "", {"arm", "",
"#define LR R14\n" "#define LR R14\n"
}, },
{"power64", "",
"#define g R30\n"
},
{"power64le", "",
"#define g R30\n"
},
}; };
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */ #define MAXWINCB 2000 /* maximum number of windows callbacks allowed */

4
src/cmd/dist/unix.c vendored
View file

@ -708,6 +708,10 @@ main(int argc, char **argv)
gohostarch = "386"; gohostarch = "386";
else if(contains(u.machine, "arm")) else if(contains(u.machine, "arm"))
gohostarch = "arm"; gohostarch = "arm";
else if(contains(u.machine, "ppc64le"))
gohostarch = "power64le";
else if(contains(u.machine, "ppc64"))
gohostarch = "power64";
else else
fatal("unknown architecture: %s", u.machine); fatal("unknown architecture: %s", u.machine);
} }

View file

@ -471,7 +471,7 @@ allocauto(Prog* ptxt)
stksize = rnd(stksize, n->type->align); stksize = rnd(stksize, n->type->align);
if(haspointers(n->type)) if(haspointers(n->type))
stkptrsize = stksize; stkptrsize = stksize;
if(thechar == '5') if(thechar == '5' || thechar == '9')
stksize = rnd(stksize, widthptr); stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) { if(stksize >= (1ULL<<31)) {
setlineno(curfn); setlineno(curfn);
@ -528,7 +528,7 @@ cgen_checknil(Node *n)
dump("checknil", n); dump("checknil", n);
fatal("bad checknil"); fatal("bad checknil");
} }
if((thechar == '5' && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) { if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
regalloc(&reg, types[tptr], n); regalloc(&reg, types[tptr], n);
cgen(n, &reg); cgen(n, &reg);
gins(ACHECKNIL, &reg, N); gins(ACHECKNIL, &reg, N);

View file

@ -847,6 +847,10 @@ nilopt(Prog *firstp)
Graph *g; Graph *g;
int ncheck, nkill; int ncheck, nkill;
// TODO(minux): nilopt on power64 throw away seemly random segment of code.
if(thechar == '9')
return;
g = flowstart(firstp, sizeof(NilFlow)); g = flowstart(firstp, sizeof(NilFlow));
if(g == nil) if(g == nil)
return; return;

View file

@ -3301,6 +3301,9 @@ walkrotate(Node **np)
int w, sl, sr, s; int w, sl, sr, s;
Node *l, *r; Node *l, *r;
Node *n; Node *n;
if(thechar == '9')
return;
n = *np; n = *np;
@ -3426,6 +3429,10 @@ walkdiv(Node **np, NodeList **init)
Type *twide; Type *twide;
Magic m; Magic m;
// TODO(minux)
if(thechar == '9')
return;
n = *np; n = *np;
if(n->right->op != OLITERAL) if(n->right->op != OLITERAL)
return; return;

View file

@ -445,11 +445,11 @@ blk(LSym *start, int64 addr, int64 size)
continue; continue;
if(sym->value >= eaddr) if(sym->value >= eaddr)
break; break;
ctxt->cursym = sym;
if(sym->value < addr) { if(sym->value < addr) {
diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type); diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
errorexit(); errorexit();
} }
ctxt->cursym = sym;
for(; addr < sym->value; addr++) for(; addr < sym->value; addr++)
cput(0); cput(0);
p = sym->p; p = sym->p;
@ -463,6 +463,8 @@ blk(LSym *start, int64 addr, int64 size)
diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size); diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size);
errorexit(); errorexit();
} }
if(sym->value+sym->size >= eaddr)
break;
} }
for(; addr < eaddr; addr++) for(; addr < eaddr; addr++)

View file

@ -10,8 +10,8 @@ Ld is the portable code for a modified version of the Plan 9 linker. The origin
http://plan9.bell-labs.com/magic/man2html/1/8l 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 It reads object files (.5, .6, .8, .9 files) and writes a binary named for the
architecture (5.out, 6.out, 8.out) by default (if $GOOS is windows, a .exe suffix architecture (5.out, 6.out, 8.out, 9.out) by default (if $GOOS is windows, a .exe suffix
will be appended). will be appended).
Major changes include: Major changes include:
@ -22,7 +22,7 @@ Original options are listed on the manual page linked above.
Usage: Usage:
go tool 6l [flags] mainObj 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: Options new in this version:

View file

@ -2189,7 +2189,7 @@ dwarfaddshstrings(LSym *shstrtab)
elfstrdbg[ElfStrDebugStr] = addstring(shstrtab, ".debug_str"); elfstrdbg[ElfStrDebugStr] = addstring(shstrtab, ".debug_str");
elfstrdbg[ElfStrGDBScripts] = addstring(shstrtab, ".debug_gdb_scripts"); elfstrdbg[ElfStrGDBScripts] = addstring(shstrtab, ".debug_gdb_scripts");
if(linkmode == LinkExternal) { if(linkmode == LinkExternal) {
if(thechar == '6') { if(thechar == '6' || thechar == '9') {
elfstrdbg[ElfStrRelDebugInfo] = addstring(shstrtab, ".rela.debug_info"); elfstrdbg[ElfStrRelDebugInfo] = addstring(shstrtab, ".rela.debug_info");
elfstrdbg[ElfStrRelDebugAranges] = addstring(shstrtab, ".rela.debug_aranges"); elfstrdbg[ElfStrRelDebugAranges] = addstring(shstrtab, ".rela.debug_aranges");
elfstrdbg[ElfStrRelDebugLine] = addstring(shstrtab, ".rela.debug_line"); elfstrdbg[ElfStrRelDebugLine] = addstring(shstrtab, ".rela.debug_line");
@ -2244,7 +2244,7 @@ dwarfaddelfrelocheader(int elfstr, ElfShdr *shdata, vlong off, vlong size)
ElfShdr *sh; ElfShdr *sh;
sh = newElfShdr(elfstrdbg[elfstr]); sh = newElfShdr(elfstrdbg[elfstr]);
if(thechar == '6') { if(thechar == '6' || thechar == '9') {
sh->type = SHT_RELA; sh->type = SHT_RELA;
} else { } else {
sh->type = SHT_REL; sh->type = SHT_REL;

View file

@ -45,6 +45,7 @@ elfinit(void)
switch(thechar) { switch(thechar) {
// 64-bit architectures // 64-bit architectures
case '6': case '6':
case '9':
elf64 = 1; elf64 = 1;
hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */ hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */ hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */
@ -678,7 +679,7 @@ elfdynhash(void)
elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0)); elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0));
} }
if(thechar == '6') { if(thechar == '6' || thechar == '9') {
sy = linklookup(ctxt, ".rela.plt", 0); sy = linklookup(ctxt, ".rela.plt", 0);
if(sy->size > 0) { if(sy->size > 0) {
elfwritedynent(s, DT_PLTREL, DT_RELA); elfwritedynent(s, DT_PLTREL, DT_RELA);
@ -804,7 +805,7 @@ elfshreloc(Section *sect)
if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0) if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
return nil; return nil;
if(thechar == '6') { if(thechar == '6' || thechar == '9') {
prefix = ".rela"; prefix = ".rela";
typ = SHT_RELA; typ = SHT_RELA;
} else { } else {
@ -931,7 +932,7 @@ doelf(void)
debug['s'] = 0; debug['s'] = 0;
debug['d'] = 1; debug['d'] = 1;
if(thechar == '6') { if(thechar == '6' || thechar == '9') {
addstring(shstrtab, ".rela.text"); addstring(shstrtab, ".rela.text");
addstring(shstrtab, ".rela.rodata"); addstring(shstrtab, ".rela.rodata");
addstring(shstrtab, ".rela.typelink"); addstring(shstrtab, ".rela.typelink");
@ -954,7 +955,7 @@ doelf(void)
if(flag_shared) { if(flag_shared) {
addstring(shstrtab, ".init_array"); addstring(shstrtab, ".init_array");
if(thechar == '6') if(thechar == '6' || thechar == '9')
addstring(shstrtab, ".rela.init_array"); addstring(shstrtab, ".rela.init_array");
else else
addstring(shstrtab, ".rel.init_array"); addstring(shstrtab, ".rel.init_array");
@ -975,7 +976,7 @@ doelf(void)
addstring(shstrtab, ".dynamic"); addstring(shstrtab, ".dynamic");
addstring(shstrtab, ".dynsym"); addstring(shstrtab, ".dynsym");
addstring(shstrtab, ".dynstr"); addstring(shstrtab, ".dynstr");
if(thechar == '6') { if(thechar == '6' || thechar == '9') {
addstring(shstrtab, ".rela"); addstring(shstrtab, ".rela");
addstring(shstrtab, ".rela.plt"); addstring(shstrtab, ".rela.plt");
} else { } else {
@ -990,7 +991,7 @@ doelf(void)
s = linklookup(ctxt, ".dynsym", 0); s = linklookup(ctxt, ".dynsym", 0);
s->type = SELFROSECT; s->type = SELFROSECT;
s->reachable = 1; s->reachable = 1;
if(thechar == '6') if(thechar == '6' || thechar == '9')
s->size += ELF64SYMSIZE; s->size += ELF64SYMSIZE;
else else
s->size += ELF32SYMSIZE; s->size += ELF32SYMSIZE;
@ -1004,7 +1005,7 @@ doelf(void)
dynstr = s; dynstr = s;
/* relocation table */ /* relocation table */
if(thechar == '6') if(thechar == '6' || thechar == '9')
s = linklookup(ctxt, ".rela", 0); s = linklookup(ctxt, ".rela", 0);
else else
s = linklookup(ctxt, ".rel", 0); s = linklookup(ctxt, ".rel", 0);
@ -1031,7 +1032,7 @@ doelf(void)
elfsetupplt(); elfsetupplt();
if(thechar == '6') if(thechar == '6' || thechar == '9')
s = linklookup(ctxt, ".rela.plt", 0); s = linklookup(ctxt, ".rela.plt", 0);
else else
s = linklookup(ctxt, ".rel.plt", 0); s = linklookup(ctxt, ".rel.plt", 0);
@ -1056,13 +1057,13 @@ doelf(void)
*/ */
elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0)); elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0));
elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0)); elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0));
if(thechar == '6') if(thechar == '6' || thechar == '9')
elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE); elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
else else
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE); elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0)); elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0));
elfwritedynentsymsize(s, DT_STRSZ, 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)); elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0));
elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0)); elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0));
elfwritedynent(s, DT_RELAENT, ELF64RELASIZE); elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
@ -1148,6 +1149,9 @@ asmbelf(vlong symo)
case '8': case '8':
eh->machine = EM_386; eh->machine = EM_386;
break; break;
case '9':
eh->machine = EM_PPC64;
break;
} }
startva = INITTEXT - HEADR; startva = INITTEXT - HEADR;
@ -1488,7 +1492,10 @@ elfobj:
eh->ident[EI_CLASS] = ELFCLASS64; eh->ident[EI_CLASS] = ELFCLASS64;
else else
eh->ident[EI_CLASS] = ELFCLASS32; 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; eh->ident[EI_VERSION] = EV_CURRENT;
if(linkmode == LinkExternal) if(linkmode == LinkExternal)

View file

@ -436,6 +436,12 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
return; return;
} }
break; 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. // load section list into memory.

View file

@ -594,6 +594,7 @@ hostlink(void)
argv[argc++] = "-m32"; argv[argc++] = "-m32";
break; break;
case '6': case '6':
case '9':
argv[argc++] = "-m64"; argv[argc++] = "-m64";
break; break;
case '5': case '5':
@ -1033,7 +1034,7 @@ static LSym *newstack;
enum enum
{ {
HasLinkRegister = (thechar == '5'), HasLinkRegister = (thechar == '5' || thechar == '9'),
}; };
// TODO: Record enough information in new object files to // TODO: Record enough information in new object files to
@ -1042,7 +1043,7 @@ enum
static int static int
callsize(void) callsize(void)
{ {
if(thechar == '5') if(HasLinkRegister)
return 0; return 0;
return RegSize; return RegSize;
} }
@ -1052,7 +1053,7 @@ dostkcheck(void)
{ {
Chain ch; Chain ch;
LSym *s; LSym *s;
morestack = linklookup(ctxt, "runtime.morestack", 0); morestack = linklookup(ctxt, "runtime.morestack", 0);
newstack = linklookup(ctxt, "runtime.newstack", 0); newstack = linklookup(ctxt, "runtime.newstack", 0);
@ -1076,19 +1077,19 @@ dostkcheck(void)
continue; continue;
if(s->nosplit) { if(s->nosplit) {
ctxt->cursym = s; ctxt->cursym = s;
ch.sym = s; ch.sym = s;
stkcheck(&ch, 0); stkcheck(&ch, 0);
} }
} }
for(s = ctxt->textp; s != nil; s = s->next) { for(s = ctxt->textp; s != nil; s = s->next) {
if(!s->nosplit) { if(!s->nosplit) {
ctxt->cursym = s; ctxt->cursym = s;
ch.sym = s; ch.sym = s;
stkcheck(&ch, 0); stkcheck(&ch, 0);
}
} }
} }
}
static int static int
stkcheck(Chain *up, int depth) stkcheck(Chain *up, int depth)
@ -1106,7 +1107,7 @@ stkcheck(Chain *up, int depth)
// function at top of safe zone once. // function at top of safe zone once.
if(limit == StackLimit-callsize()) { if(limit == StackLimit-callsize()) {
if(s->stkcheck) if(s->stkcheck)
return 0; return 0;
s->stkcheck = 1; s->stkcheck = 1;
} }
@ -1154,6 +1155,7 @@ stkcheck(Chain *up, int depth)
switch(r->type) { switch(r->type) {
case R_CALL: case R_CALL:
case R_CALLARM: case R_CALLARM:
case R_CALLPOWER:
// Direct call. // Direct call.
ch.limit = limit - pcsp.value - callsize(); ch.limit = limit - pcsp.value - callsize();
ch.sym = r->sym; ch.sym = r->sym;
@ -1164,8 +1166,8 @@ stkcheck(Chain *up, int depth)
// to StackLimit beyond the frame size. // to StackLimit beyond the frame size.
if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) { if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
limit = StackLimit + s->locals; limit = StackLimit + s->locals;
if(thechar == '5') if(HasLinkRegister)
limit += 4; // saved LR limit += RegSize;
} }
break; break;
@ -1184,7 +1186,7 @@ stkcheck(Chain *up, int depth)
break; break;
} }
} }
} }
return 0; return 0;
} }
@ -1213,7 +1215,7 @@ stkprint(Chain *ch, int limit)
else else
print("\t%d\tguaranteed after split check in %s\n", ch->limit, name); print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
} else { } else {
stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize); stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
if(!HasLinkRegister) if(!HasLinkRegister)
print("\t%d\ton entry to %s\n", ch->limit, name); print("\t%d\ton entry to %s\n", ch->limit, name);
} }
@ -1533,7 +1535,7 @@ callgraph(void)
r = &s->r[i]; r = &s->r[i];
if(r->sym == nil) if(r->sym == nil)
continue; 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); Bprint(&bso, "%s calls %s\n", s->name, r->sym->name);
} }
} }

View file

@ -44,6 +44,7 @@ machoinit(void)
switch(thechar) { switch(thechar) {
// 64-bit architectures // 64-bit architectures
case '6': case '6':
case '9':
macho64 = 1; macho64 = 1;
break; break;

View file

@ -78,6 +78,7 @@ putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
{ {
switch(thechar) { switch(thechar) {
case '6': case '6':
case '9':
LPUT(off); LPUT(off);
cput(info); cput(info);
cput(other); cput(other);

View file

@ -1414,6 +1414,184 @@ var rppcStrings = []intName{
func (i R_PPC) String() string { return stringName(uint32(i), rppcStrings, false) } func (i R_PPC) String() string { return stringName(uint32(i), rppcStrings, false) }
func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) } 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. // Relocation types for SPARC.
type R_SPARC int type R_SPARC int

View file

@ -532,6 +532,9 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 { if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 {
return f.applyRelocationsARM64(dst, rels) return f.applyRelocationsARM64(dst, rels)
} }
if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 {
return f.applyRelocationsPPC64(dst, rels)
}
return errors.New("not implemented") return errors.New("not implemented")
} }
@ -671,6 +674,51 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
return nil 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) { func (f *File) DWARF() (*dwarf.Data, error) {
// There are many other DWARF sections, but these // There are many other DWARF sections, but these
// are the required ones, and the debug/dwarf package // are the required ones, and the debug/dwarf package
@ -693,7 +741,7 @@ func (f *File) DWARF() (*dwarf.Data, error) {
// If there's a relocation table for .debug_info, we have to process it // 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. // now otherwise the data in .debug_info is invalid for x86-64 objects.
rela := f.Section(".rela.debug_info") rela := f.Section(".rela.debug_info")
if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64) { if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64 || f.Machine == EM_PPC64) {
data, err := rela.Data() data, err := rela.Data()
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -266,6 +266,12 @@ var relocationTests = []relocationTest{
{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x24)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x24)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
}, },
}, },
{
"testdata/go-relocation-test-gcc482-ppc64le.obj",
[]relocationTestEntry{
{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
},
},
{ {
"testdata/go-relocation-test-clang-x86.obj", "testdata/go-relocation-test-clang-x86.obj",
[]relocationTestEntry{ []relocationTestEntry{

Binary file not shown.

View file

@ -1384,6 +1384,8 @@ func ArchChar(goarch string) (string, error) {
return "6", nil return "6", nil
case "arm": case "arm":
return "5", nil return "5", nil
case "power64", "power64le":
return "9", nil
} }
return "", errors.New("unsupported GOARCH " + goarch) return "", errors.New("unsupported GOARCH " + goarch)
} }

View file

@ -5,4 +5,4 @@
package build package build
const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows " 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 "

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build 386 arm // +build 386 arm power64 power64le
package crc32 package crc32

2784
src/liblink/asm9.c Normal file

File diff suppressed because it is too large Load diff

409
src/liblink/list9.c Normal file
View file

@ -0,0 +1,409 @@
// cmd/9l/list.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "../cmd/9l/9.out.h"
enum
{
STRINGSZ = 1000,
};
static int Aconv(Fmt*);
static int Dconv(Fmt*);
static int Pconv(Fmt*);
static int Rconv(Fmt*);
static int DSconv(Fmt*);
static int Mconv(Fmt*);
static int DRconv(Fmt*);
//
// Format conversions
// %A int Opcodes (instruction mnemonics)
//
// %D Addr* Addresses (instruction operands)
// Flags: "%lD": seperate the high and low words of a constant by "-"
//
// %P Prog* Instructions
//
// %R int Registers
//
// %$ char* String constant addresses (for internal use only)
// %^ int C_* classes (for liblink internal use)
#pragma varargck type "$" char*
#pragma varargck type "M" Addr*
void
listinit9(void)
{
fmtinstall('A', Aconv);
fmtinstall('D', Dconv);
fmtinstall('P', Pconv);
fmtinstall('R', Rconv);
// for liblink internal use
fmtinstall('^', DRconv);
// for internal use
fmtinstall('$', DSconv);
fmtinstall('M', Mconv);
}
static Prog* bigP;
static int
Pconv(Fmt *fp)
{
char str[STRINGSZ], *s;
Prog *p;
int a;
p = va_arg(fp->args, Prog*);
bigP = p;
a = p->as;
if(a == ADATA || a == AINIT || a == ADYNT)
sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else if(a == ATEXT) {
if(p->reg != 0)
sprint(str, "%.5lld (%L) %A %D,%d,%lD", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else
sprint(str, "%.5lld (%L) %A %D,%lD", p->pc, p->lineno, a, &p->from, &p->to);
} else if(a == AGLOBL) {
if(p->reg != 0)
sprint(str, "%.5lld (%L) %A %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else
sprint(str, "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
} else {
s = str;
if(p->mark & NOSCHED)
s += sprint(s, "*");
if(p->reg == NREG && p->from3.type == D_NONE)
sprint(s, "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
else
if(a != ATEXT && p->from.type == D_OREG) {
sprint(s, "%.5lld (%L) %A %lld(R%d+R%d),%D", p->pc, p->lineno, a,
p->from.offset, p->from.reg, p->reg, &p->to);
} else
if(p->to.type == D_OREG) {
sprint(s, "%.5lld (%L) %A %D,%lld(R%d+R%d)", p->pc, p->lineno, a,
&p->from, p->to.offset, p->to.reg, p->reg);
} else {
s += sprint(s, "%.5lld (%L) %A %D", p->pc, p->lineno, a, &p->from);
if(p->reg != NREG)
s += sprint(s, ",%c%d", p->from.type==D_FREG?'F':'R', p->reg);
if(p->from3.type != D_NONE)
s += sprint(s, ",%D", &p->from3);
sprint(s, ",%D", &p->to);
}
if(p->spadj != 0)
return fmtprint(fp, "%s # spadj=%d", str, p->spadj);
}
return fmtstrcpy(fp, str);
}
static int
Aconv(Fmt *fp)
{
char *s;
int a;
a = va_arg(fp->args, int);
s = "???";
if(a >= AXXX && a < ALAST)
s = anames9[a];
return fmtstrcpy(fp, s);
}
static int
Dconv(Fmt *fp)
{
char str[STRINGSZ];
Addr *a;
int32 v;
a = va_arg(fp->args, Addr*);
if(fp->flags & FmtLong) {
if(a->type == D_CONST)
sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
else {
// ATEXT dst is not constant
sprint(str, "!!%D", a);
}
goto ret;
}
switch(a->type) {
default:
sprint(str, "GOK-type(%d)", a->type);
break;
case D_NONE:
str[0] = 0;
if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
sprint(str, "%M(R%d)(NONE)", a, a->reg);
break;
case D_CONST:
case D_DCONST:
if(a->reg != NREG)
sprint(str, "$%M(R%d)", a, a->reg);
else
sprint(str, "$%M", a);
break;
case D_OREG:
if(a->reg != NREG)
sprint(str, "%M(R%d)", a, a->reg);
else
sprint(str, "%M", a);
break;
case D_REG:
sprint(str, "R%d", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(R%d)(REG)", a, a->reg);
break;
case D_FREG:
sprint(str, "F%d", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(F%d)(REG)", a, a->reg);
break;
case D_CREG:
if(a->reg == NREG)
strcpy(str, "CR");
else
sprint(str, "CR%d", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(C%d)(REG)", a, a->reg);
break;
case D_SPR:
if(a->name == D_NONE && a->sym == nil) {
switch((ulong)a->offset) {
case D_XER: sprint(str, "XER"); break;
case D_LR: sprint(str, "LR"); break;
case D_CTR: sprint(str, "CTR"); break;
default: sprint(str, "SPR(%lld)", a->offset); break;
}
break;
}
sprint(str, "SPR-GOK(%d)", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(SPR-GOK%d)(REG)", a, a->reg);
break;
case D_DCR:
if(a->name == D_NONE && a->sym == nil) {
sprint(str, "DCR(%lld)", a->offset);
break;
}
sprint(str, "DCR-GOK(%d)", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg);
break;
case D_OPT:
sprint(str, "OPT(%d)", a->reg);
break;
case D_FPSCR:
if(a->reg == NREG)
strcpy(str, "FPSCR");
else
sprint(str, "FPSCR(%d)", a->reg);
break;
case D_MSR:
sprint(str, "MSR");
break;
case D_BRANCH:
if(bigP->pcond != nil) {
v = bigP->pcond->pc;
//if(v >= INITTEXT)
// v -= INITTEXT-HEADR;
if(a->sym != nil)
sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v);
else
sprint(str, "%.5lux(BRANCH)", v);
} else
if(a->sym != nil)
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
else
sprint(str, "%lld(APC)", a->offset);
break;
case D_FCONST:
//sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
sprint(str, "$%.17g", a->u.dval);
break;
case D_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
}
ret:
return fmtstrcpy(fp, str);
}
static int
Mconv(Fmt *fp)
{
char str[STRINGSZ];
Addr *a;
LSym *s;
int32 l;
a = va_arg(fp->args, Addr*);
s = a->sym;
//if(s == nil) {
// l = a->offset;
// if((vlong)l != a->offset)
// sprint(str, "0x%llux", a->offset);
// else
// sprint(str, "%lld", a->offset);
// goto out;
//}
switch(a->name) {
default:
sprint(str, "GOK-name(%d)", a->name);
break;
case D_NONE:
l = a->offset;
if((vlong)l != a->offset)
sprint(str, "0x%llux", a->offset);
else
sprint(str, "%lld", a->offset);
break;
case D_EXTERN:
if(a->offset != 0)
sprint(str, "%s+%lld(SB)", s->name, a->offset);
else
sprint(str, "%s(SB)", s->name, a->offset);
break;
case D_STATIC:
sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
break;
case D_AUTO:
if(s == nil)
sprint(str, "%lld(SP)", -a->offset);
else
sprint(str, "%s-%lld(SP)", s->name, -a->offset);
break;
case D_PARAM:
if(s == nil)
sprint(str, "%lld(FP)", a->offset);
else
sprint(str, "%s+%lld(FP)", s->name, a->offset);
break;
}
//out:
return fmtstrcpy(fp, str);
}
static int
Rconv(Fmt *fp)
{
char str[STRINGSZ];
int r;
r = va_arg(fp->args, int);
if(r < NREG)
sprint(str, "r%d", r);
else
sprint(str, "f%d", r-NREG);
return fmtstrcpy(fp, str);
}
static int
DRconv(Fmt *fp)
{
char *s;
int a;
a = va_arg(fp->args, int);
s = "C_??";
if(a >= C_NONE && a <= C_NCLASS)
s = cnames9[a];
return fmtstrcpy(fp, s);
}
static int
DSconv(Fmt *fp)
{
int i, c;
char str[STRINGSZ], *p, *a;
a = va_arg(fp->args, char*);
p = str;
for(i=0; i<sizeof(int32); i++) {
c = a[i] & 0xff;
if(c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9' ||
c == ' ' || c == '%') {
*p++ = c;
continue;
}
*p++ = '\\';
switch(c) {
case 0:
*p++ = 'z';
continue;
case '\\':
case '"':
*p++ = c;
continue;
case '\n':
*p++ = 'n';
continue;
case '\t':
*p++ = 't';
continue;
}
*p++ = (c>>6) + '0';
*p++ = ((c>>3) & 7) + '0';
*p++ = (c & 7) + '0';
}
*p = 0;
return fmtstrcpy(fp, str);
}

1086
src/liblink/obj9.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -142,6 +142,8 @@ writeobj(Link *ctxt, Biobuf *b)
edata = nil; edata = nil;
for(pl = ctxt->plist; pl != nil; pl = pl->link) { for(pl = ctxt->plist; pl != nil; pl = pl->link) {
for(p = pl->firstpc; p != nil; p = plink) { for(p = pl->firstpc; p != nil; p = plink) {
if(ctxt->debugasm && ctxt->debugvlog)
print("obj: %p %P\n", p, p);
plink = p->link; plink = p->link;
p->link = nil; p->link = nil;
@ -365,7 +367,10 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
name = ""; name = "";
if(r->sym != nil) if(r->sym != nil)
name = r->sym->name; name = r->sym->name;
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add); if(ctxt->arch->thechar == '5' || ctxt->arch->thechar == '9')
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%llux\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
else
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
} }
} }
@ -777,7 +782,7 @@ rdsym(Link *ctxt, Biobuf *f, char *pkg)
s->type = SRODATA; s->type = SRODATA;
adduint32(ctxt, s, i32); adduint32(ctxt, s, i32);
s->reachable = 0; 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; int64 i64;
i64 = strtoull(s->name+5, nil, 16); i64 = strtoull(s->name+5, nil, 16);
s->type = SRODATA; s->type = SRODATA;

835
src/liblink/sched9.c Normal file
View file

@ -0,0 +1,835 @@
// cmd/9l/sched.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// +build ignore
#include "l.h"
enum
{
E_ICC = 1<<0,
E_FCC = 1<<1,
E_MEM = 1<<2,
E_MEMSP = 1<<3, /* uses offset and size */
E_MEMSB = 1<<4, /* uses offset and size */
E_LR = 1<<5,
E_CR = 1<<6,
E_CTR = 1<<7,
E_XER = 1<<8,
E_CR0 = 0xF<<0,
E_CR1 = 0xF<<4,
ANYMEM = E_MEM|E_MEMSP|E_MEMSB,
ALL = ~0,
};
typedef struct Sch Sch;
typedef struct Dep Dep;
struct Dep
{
ulong ireg;
ulong freg;
ulong cc;
ulong cr;
};
struct Sch
{
Prog p;
Dep set;
Dep used;
long soffset;
char size;
char comp;
};
void regused(Sch*, Prog*);
int depend(Sch*, Sch*);
int conflict(Sch*, Sch*);
int offoverlap(Sch*, Sch*);
void dumpbits(Sch*, Dep*);
void
sched(Prog *p0, Prog *pe)
{
Prog *p, *q;
Sch sch[NSCHED], *s, *t, *u, *se, stmp;
if(!debug['Q'])
return;
/*
* build side structure
*/
s = sch;
for(p=p0;; p=p->link) {
memset(s, 0, sizeof(*s));
s->p = *p;
regused(s, p);
if(debug['X']) {
Bprint(&bso, "%P\tset", &s->p);
dumpbits(s, &s->set);
Bprint(&bso, "; used");
dumpbits(s, &s->used);
if(s->comp)
Bprint(&bso, "; compound");
if(s->p.mark & LOAD)
Bprint(&bso, "; load");
if(s->p.mark & BRANCH)
Bprint(&bso, "; branch");
if(s->p.mark & FCMP)
Bprint(&bso, "; fcmp");
Bprint(&bso, "\n");
}
s++;
if(p == pe)
break;
}
se = s;
for(s=se-1; s>=sch; s--) {
/*
* load delay. interlocked.
*/
if(s->p.mark & LOAD) {
if(s >= se-1)
continue;
if(!conflict(s, (s+1)))
continue;
/*
* s is load, s+1 is immediate use of result
* t is the trial instruction to insert between s and s+1
*/
for(t=s-1; t>=sch; t--) {
if(t->p.mark & BRANCH)
goto no2;
if(t->p.mark & FCMP)
if((s+1)->p.mark & BRANCH)
goto no2;
if(t->p.mark & LOAD)
if(conflict(t, (s+1)))
goto no2;
for(u=t+1; u<=s; u++)
if(depend(u, t))
goto no2;
goto out2;
no2:;
}
if(debug['X'])
Bprint(&bso, "?l%P\n", &s->p);
continue;
out2:
if(debug['X']) {
Bprint(&bso, "!l%P\n", &t->p);
Bprint(&bso, "%P\n", &s->p);
}
stmp = *t;
memmove(t, t+1, (uchar*)s - (uchar*)t);
*s = stmp;
s--;
continue;
}
/*
* fop2 delay.
*/
if(s->p.mark & FCMP) {
if(s >= se-1)
continue;
if(!((s+1)->p.mark & BRANCH))
continue;
/* t is the trial instruction to use */
for(t=s-1; t>=sch; t--) {
for(u=t+1; u<=s; u++)
if(depend(u, t))
goto no3;
goto out3;
no3:;
}
if(debug['X'])
Bprint(&bso, "?f%P\n", &s->p);
continue;
out3:
if(debug['X']) {
Bprint(&bso, "!f%P\n", &t->p);
Bprint(&bso, "%P\n", &s->p);
}
stmp = *t;
memmove(t, t+1, (uchar*)s - (uchar*)t);
*s = stmp;
s--;
continue;
}
}
/*
* put it all back
*/
for(s=sch, p=p0; s<se; s++, p=q) {
q = p->link;
if(q != s->p.link) {
*p = s->p;
p->link = q;
}
}
if(debug['X'])
Bprint(&bso, "\n");
}
void
regused(Sch *s, Prog *realp)
{
int c, ar, ad, ld, sz, nr, upd;
ulong m;
Prog *p;
p = &s->p;
s->comp = compound(p);
if(s->comp) {
s->set.ireg |= 1<<REGTMP;
s->used.ireg |= 1<<REGTMP;
}
ar = 0; /* dest is really reference */
ad = 0; /* source/dest is really address */
ld = 0; /* opcode is load instruction */
sz = 32*4; /* size of load/store for overlap computation */
nr = 0; /* source/dest is not really reg */
upd = 0; /* move with update; changes reg */
/*
* flags based on opcode
*/
switch(p->as) {
case ATEXT:
curtext = realp;
autosize = p->to.offset + 8;
ad = 1;
break;
case ABL:
s->set.cc |= E_LR;
ar = 1;
ad = 1;
break;
case ABR:
ar = 1;
ad = 1;
break;
case ACMP:
case ACMPU:
case ACMPW:
case ACMPWU:
s->set.cc |= E_ICC;
if(p->reg == 0)
s->set.cr |= E_CR0;
else
s->set.cr |= (0xF<<((p->reg&7)*4));
ar = 1;
break;
case AFCMPO:
case AFCMPU:
s->set.cc |= E_FCC;
if(p->reg == 0)
s->set.cr |= E_CR0;
else
s->set.cr |= (0xF<<((p->reg&7)*4));
ar = 1;
break;
case ACRAND:
case ACRANDN:
case ACREQV:
case ACRNAND:
case ACRNOR:
case ACROR:
case ACRORN:
case ACRXOR:
s->used.cr |= 1<<p->from.reg;
s->set.cr |= 1<<p->to.reg;
nr = 1;
break;
case ABCL: /* tricky */
s->used.cc |= E_FCC|E_ICC;
s->used.cr = ALL;
s->set.cc |= E_LR;
ar = 1;
break;
case ABC: /* tricky */
s->used.cc |= E_FCC|E_ICC;
s->used.cr = ALL;
ar = 1;
break;
case ABEQ:
case ABGE:
case ABGT:
case ABLE:
case ABLT:
case ABNE:
case ABVC:
case ABVS:
s->used.cc |= E_ICC;
s->used.cr |= E_CR0;
ar = 1;
break;
case ALSW:
case AMOVMW:
/* could do better */
sz = 32*4;
ld = 1;
break;
case AMOVBU:
case AMOVBZU:
upd = 1;
sz = 1;
ld = 1;
break;
case AMOVB:
case AMOVBZ:
sz = 1;
ld = 1;
break;
case AMOVHU:
case AMOVHZU:
upd = 1;
sz = 2;
ld = 1;
break;
case AMOVH:
case AMOVHBR:
case AMOVHZ:
sz = 2;
ld = 1;
break;
case AFMOVSU:
case AMOVWU:
case AMOVWZU:
upd = 1;
sz = 4;
ld = 1;
break;
case AFMOVS:
case AMOVW:
case AMOVWZ:
case AMOVWBR:
case ALWAR:
sz = 4;
ld = 1;
break;
case AFMOVDU:
upd = 1;
sz = 8;
ld = 1;
break;
case AFMOVD:
sz = 8;
ld = 1;
break;
case AFMOVDCC:
sz = 8;
ld = 1;
s->set.cc |= E_FCC;
s->set.cr |= E_CR1;
break;
case AMOVFL:
case AMOVCRFS:
case AMTFSB0:
case AMTFSB0CC:
case AMTFSB1:
case AMTFSB1CC:
s->set.ireg = ALL;
s->set.freg = ALL;
s->set.cc = ALL;
s->set.cr = ALL;
break;
case AADDCC:
case AADDVCC:
case AADDCCC:
case AADDCVCC:
case AADDMECC:
case AADDMEVCC:
case AADDECC:
case AADDEVCC:
case AADDZECC:
case AADDZEVCC:
case AANDCC:
case AANDNCC:
case ACNTLZWCC:
case ADIVWCC:
case ADIVWVCC:
case ADIVWUCC:
case ADIVWUVCC:
case AEQVCC:
case AEXTSBCC:
case AEXTSHCC:
case AMULHWCC:
case AMULHWUCC:
case AMULLWCC:
case AMULLWVCC:
case ANANDCC:
case ANEGCC:
case ANEGVCC:
case ANORCC:
case AORCC:
case AORNCC:
case AREMCC:
case AREMVCC:
case AREMUCC:
case AREMUVCC:
case ARLWMICC:
case ARLWNMCC:
case ASLWCC:
case ASRAWCC:
case ASRWCC:
case ASTWCCC:
case ASUBCC:
case ASUBVCC:
case ASUBCCC:
case ASUBCVCC:
case ASUBMECC:
case ASUBMEVCC:
case ASUBECC:
case ASUBEVCC:
case ASUBZECC:
case ASUBZEVCC:
case AXORCC:
s->set.cc |= E_ICC;
s->set.cr |= E_CR0;
break;
case AFABSCC:
case AFADDCC:
case AFADDSCC:
case AFCTIWCC:
case AFCTIWZCC:
case AFDIVCC:
case AFDIVSCC:
case AFMADDCC:
case AFMADDSCC:
case AFMSUBCC:
case AFMSUBSCC:
case AFMULCC:
case AFMULSCC:
case AFNABSCC:
case AFNEGCC:
case AFNMADDCC:
case AFNMADDSCC:
case AFNMSUBCC:
case AFNMSUBSCC:
case AFRSPCC:
case AFSUBCC:
case AFSUBSCC:
s->set.cc |= E_FCC;
s->set.cr |= E_CR1;
break;
}
/*
* flags based on 'to' field
*/
c = p->to.class;
if(c == 0) {
c = aclass(&p->to) + 1;
p->to.class = c;
}
c--;
switch(c) {
default:
print("unknown class %d %D\n", c, &p->to);
case C_NONE:
case C_ZCON:
case C_SCON:
case C_UCON:
case C_LCON:
case C_ADDCON:
case C_ANDCON:
case C_SBRA:
case C_LBRA:
break;
case C_CREG:
c = p->to.reg;
if(c == NREG)
s->set.cr = ALL;
else
s->set.cr |= (0xF << ((p->from.reg&7)*4));
s->set.cc = ALL;
break;
case C_SPR:
case C_FPSCR:
case C_MSR:
case C_XER:
s->set.ireg = ALL;
s->set.freg = ALL;
s->set.cc = ALL;
s->set.cr = ALL;
break;
case C_LR:
s->set.cc |= E_LR;
break;
case C_CTR:
s->set.cc |= E_CTR;
break;
case C_ZOREG:
case C_SOREG:
case C_LOREG:
c = p->to.reg;
s->used.ireg |= 1<<c;
if(upd)
s->set.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
m = ANYMEM;
if(c == REGSB)
m = E_MEMSB;
if(c == REGSP)
m = E_MEMSP;
if(ar)
s->used.cc |= m;
else
s->set.cc |= m;
break;
case C_SACON:
case C_LACON:
s->used.ireg |= 1<<REGSP;
if(upd)
s->set.ireg |= 1<<c;
break;
case C_SECON:
case C_LECON:
s->used.ireg |= 1<<REGSB;
if(upd)
s->set.ireg |= 1<<c;
break;
case C_REG:
if(nr)
break;
if(ar)
s->used.ireg |= 1<<p->to.reg;
else
s->set.ireg |= 1<<p->to.reg;
break;
case C_FREG:
if(ar)
s->used.freg |= 1<<p->to.reg;
else
s->set.freg |= 1<<p->to.reg;
break;
case C_SAUTO:
case C_LAUTO:
s->used.ireg |= 1<<REGSP;
if(upd)
s->set.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
if(ar)
s->used.cc |= E_MEMSP;
else
s->set.cc |= E_MEMSP;
break;
case C_SEXT:
case C_LEXT:
s->used.ireg |= 1<<REGSB;
if(upd)
s->set.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
if(ar)
s->used.cc |= E_MEMSB;
else
s->set.cc |= E_MEMSB;
break;
}
/*
* flags based on 'from' field
*/
c = p->from.class;
if(c == 0) {
c = aclass(&p->from) + 1;
p->from.class = c;
}
c--;
switch(c) {
default:
print("unknown class %d %D\n", c, &p->from);
case C_NONE:
case C_ZCON:
case C_SCON:
case C_UCON:
case C_LCON:
case C_ADDCON:
case C_ANDCON:
case C_SBRA:
case C_LBRA:
c = p->from.reg;
if(c != NREG)
s->used.ireg |= 1<<c;
break;
case C_CREG:
c = p->from.reg;
if(c == NREG)
s->used.cr = ALL;
else
s->used.cr |= (0xF << ((p->from.reg&7)*4));
s->used.cc = ALL;
break;
case C_SPR:
case C_FPSCR:
case C_MSR:
case C_XER:
s->set.ireg = ALL;
s->set.freg = ALL;
s->set.cc = ALL;
s->set.cr = ALL;
break;
case C_LR:
s->used.cc |= E_LR;
break;
case C_CTR:
s->used.cc |= E_CTR;
break;
case C_ZOREG:
case C_SOREG:
case C_LOREG:
c = p->from.reg;
s->used.ireg |= 1<<c;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
m = ANYMEM;
if(c == REGSB)
m = E_MEMSB;
if(c == REGSP)
m = E_MEMSP;
s->used.cc |= m;
break;
case C_SACON:
case C_LACON:
s->used.ireg |= 1<<REGSP;
break;
case C_SECON:
case C_LECON:
s->used.ireg |= 1<<REGSB;
break;
case C_REG:
if(nr)
break;
s->used.ireg |= 1<<p->from.reg;
break;
case C_FREG:
s->used.freg |= 1<<p->from.reg;
break;
case C_SAUTO:
case C_LAUTO:
s->used.ireg |= 1<<REGSP;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
s->used.cc |= E_MEMSP;
break;
case C_SEXT:
case C_LEXT:
s->used.ireg |= 1<<REGSB;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
s->used.cc |= E_MEMSB;
break;
}
c = p->reg;
if(c != NREG) {
if(p->from.type == D_FREG || p->to.type == D_FREG)
s->used.freg |= 1<<c;
else
s->used.ireg |= 1<<c;
}
}
/*
* test to see if 2 instrictions can be
* interchanged without changing semantics
*/
int
depend(Sch *sa, Sch *sb)
{
ulong x;
if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
return 1;
if(sb->set.ireg & sa->used.ireg)
return 1;
if(sa->set.freg & (sb->set.freg|sb->used.freg))
return 1;
if(sb->set.freg & sa->used.freg)
return 1;
if(sa->set.cr & (sb->set.cr|sb->used.cr))
return 1;
if(sb->set.cr & sa->used.cr)
return 1;
x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
(sb->set.cc & sa->used.cc);
if(x) {
/*
* allow SB and SP to pass each other.
* allow SB to pass SB iff doffsets are ok
* anything else conflicts
*/
if(x != E_MEMSP && x != E_MEMSB)
return 1;
x = sa->set.cc | sb->set.cc |
sa->used.cc | sb->used.cc;
if(x & E_MEM)
return 1;
if(offoverlap(sa, sb))
return 1;
}
return 0;
}
int
offoverlap(Sch *sa, Sch *sb)
{
if(sa->soffset < sb->soffset) {
if(sa->soffset+sa->size > sb->soffset)
return 1;
return 0;
}
if(sb->soffset+sb->size > sa->soffset)
return 1;
return 0;
}
/*
* test 2 adjacent instructions
* and find out if inserted instructions
* are desired to prevent stalls.
* first instruction is a load instruction.
*/
int
conflict(Sch *sa, Sch *sb)
{
if(sa->set.ireg & sb->used.ireg)
return 1;
if(sa->set.freg & sb->used.freg)
return 1;
if(sa->set.cr & sb->used.cr)
return 1;
return 0;
}
int
compound(Prog *p)
{
Optab *o;
o = oplook(p);
if(o->size != 4)
return 1;
if(p->to.type == D_REG && p->to.reg == REGSB)
return 1;
return 0;
}
void
dumpbits(Sch *s, Dep *d)
{
int i;
for(i=0; i<32; i++)
if(d->ireg & (1<<i))
Bprint(&bso, " R%d", i);
for(i=0; i<32; i++)
if(d->freg & (1<<i))
Bprint(&bso, " F%d", i);
for(i=0; i<32; i++)
if(d->cr & (1<<i))
Bprint(&bso, " C%d", i);
for(i=0; i<32; i++)
switch(d->cc & (1<<i)) {
default:
break;
case E_ICC:
Bprint(&bso, " ICC");
break;
case E_FCC:
Bprint(&bso, " FCC");
break;
case E_LR:
Bprint(&bso, " LR");
break;
case E_CR:
Bprint(&bso, " CR");
break;
case E_CTR:
Bprint(&bso, " CTR");
break;
case E_XER:
Bprint(&bso, " XER");
break;
case E_MEM:
Bprint(&bso, " MEM%d", s->size);
break;
case E_MEMSB:
Bprint(&bso, " SB%d", s->size);
break;
case E_MEMSP:
Bprint(&bso, " SP%d", s->size);
break;
}
}

14
src/math/abs_power64x.s Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
TEXT ·Abs(SB),NOSPLIT,$0-16
MOVD x+0(FP), R3
MOVD $((1<<63)-1), R4
AND R4, R3
MOVD R3, ret+8(FP)
RETURN

View file

@ -0,0 +1,46 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
// This file provides fast assembly versions for the elementary
// arithmetic operations on vectors implemented in arith.go.
TEXT ·mulWW(SB),NOSPLIT,$0
BR ·mulWW_g(SB)
TEXT ·divWW(SB),NOSPLIT,$0
BR ·divWW_g(SB)
TEXT ·addVV(SB),NOSPLIT,$0
BR ·addVV_g(SB)
TEXT ·subVV(SB),NOSPLIT,$0
BR ·subVV_g(SB)
TEXT ·addVW(SB),NOSPLIT,$0
BR ·addVW_g(SB)
TEXT ·subVW(SB),NOSPLIT,$0
BR ·subVW_g(SB)
TEXT ·shlVU(SB),NOSPLIT,$0
BR ·shlVU_g(SB)
TEXT ·shrVU(SB),NOSPLIT,$0
BR ·shrVU_g(SB)
TEXT ·mulAddVWW(SB),NOSPLIT,$0
BR ·mulAddVWW_g(SB)
TEXT ·addMulVVW(SB),NOSPLIT,$0
BR ·addMulVVW_g(SB)
TEXT ·divWVW(SB),NOSPLIT,$0
BR ·divWVW_g(SB)
TEXT ·bitLen(SB),NOSPLIT,$0
BR ·bitLen_g(SB)

91
src/math/stubs_power64x.s Normal file
View file

@ -0,0 +1,91 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
TEXT ·Asin(SB),NOSPLIT,$0
BR ·asin(SB)
TEXT ·Acos(SB),NOSPLIT,$0
BR ·acos(SB)
TEXT ·Atan2(SB),NOSPLIT,$0
BR ·atan2(SB)
TEXT ·Atan(SB),NOSPLIT,$0
BR ·atan(SB)
TEXT ·Dim(SB),NOSPLIT,$0
BR ·dim(SB)
TEXT ·Min(SB),NOSPLIT,$0
BR ·min(SB)
TEXT ·Max(SB),NOSPLIT,$0
BR ·max(SB)
TEXT ·Exp2(SB),NOSPLIT,$0
BR ·exp2(SB)
TEXT ·Expm1(SB),NOSPLIT,$0
BR ·expm1(SB)
TEXT ·Exp(SB),NOSPLIT,$0
BR ·exp(SB)
TEXT ·Floor(SB),NOSPLIT,$0
BR ·floor(SB)
TEXT ·Ceil(SB),NOSPLIT,$0
BR ·ceil(SB)
TEXT ·Trunc(SB),NOSPLIT,$0
BR ·trunc(SB)
TEXT ·Frexp(SB),NOSPLIT,$0
BR ·frexp(SB)
TEXT ·Hypot(SB),NOSPLIT,$0
BR ·hypot(SB)
TEXT ·Ldexp(SB),NOSPLIT,$0
BR ·ldexp(SB)
TEXT ·Log10(SB),NOSPLIT,$0
BR ·log10(SB)
TEXT ·Log2(SB),NOSPLIT,$0
BR ·log2(SB)
TEXT ·Log1p(SB),NOSPLIT,$0
BR ·log1p(SB)
TEXT ·Log(SB),NOSPLIT,$0
BR ·log(SB)
TEXT ·Modf(SB),NOSPLIT,$0
BR ·modf(SB)
TEXT ·Mod(SB),NOSPLIT,$0
BR ·mod(SB)
TEXT ·Remainder(SB),NOSPLIT,$0
BR ·remainder(SB)
TEXT ·Sincos(SB),NOSPLIT,$0
BR ·sincos(SB)
TEXT ·Sin(SB),NOSPLIT,$0
BR ·sin(SB)
TEXT ·Cos(SB),NOSPLIT,$0
BR ·cos(SB)
TEXT ·Sqrt(SB),NOSPLIT,$0
BR ·sqrt(SB)
TEXT ·Tan(SB),NOSPLIT,$0
BR ·tan(SB)

View file

@ -4,13 +4,19 @@
// Assembly to get into package runtime without using exported symbols. // Assembly to get into package runtime without using exported symbols.
// +build amd64 amd64p32 arm 386 // +build amd64 amd64p32 arm 386 power64 power64le
#include "textflag.h" #include "textflag.h"
#ifdef GOARCH_arm #ifdef GOARCH_arm
#define JMP B #define JMP B
#endif #endif
#ifdef GOARCH_power64
#define JMP BR
#endif
#ifdef GOARCH_power64le
#define JMP BR
#endif
TEXT ·signal_disable(SB),NOSPLIT,$0 TEXT ·signal_disable(SB),NOSPLIT,$0
JMP runtime·signal_disable(SB) JMP runtime·signal_disable(SB)

View file

@ -1052,6 +1052,11 @@ func TestChan(t *testing.T) {
ok = cv.TrySend(ValueOf(6)) ok = cv.TrySend(ValueOf(6))
if !ok { if !ok {
t.Errorf("TrySend on empty chan failed") t.Errorf("TrySend on empty chan failed")
select {
case x := <-c:
t.Errorf("TrySend failed but it did send %d", x)
default:
}
} else { } else {
if i = <-c; i != 6 { if i = <-c; i != 6 {
t.Errorf("TrySend 6, recv %d", i) t.Errorf("TrySend 6, recv %d", i)

View file

@ -0,0 +1,29 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
// makeFuncStub is the code half of the function returned by MakeFunc.
// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
MOVD R11, 8(R1)
MOVD $argframe+0(FP), R3
MOVD R3, 16(R1)
BL ·callReflect(SB)
RETURN
// methodValueCall is the code half of the function returned by makeMethodValue.
// See the comment on the declaration of methodValueCall in makefunc.go
// for more details.
// No argsize here, gc generates argsize info at call site.
TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
MOVD R11, 8(R1)
MOVD $argframe+0(FP), R3
MOVD R3, 16(R1)
BL ·callMethod(SB)
RETURN

View file

@ -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

View file

@ -0,0 +1,14 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
enum {
thechar = '9',
BigEndian = 1,
CacheLineSize = 64,
RuntimeGogoBytes = 64,
PhysPageSize = 65536,
PCQuantum = 4,
Int64Align = 8
};

View file

@ -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

View file

@ -0,0 +1,14 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
enum {
thechar = '9',
BigEndian = 0,
CacheLineSize = 64,
RuntimeGogoBytes = 64,
PhysPageSize = 65536,
PCQuantum = 4,
Int64Align = 8
};

View file

@ -486,11 +486,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-21
MOVL new_hi+16(FP), CX MOVL new_hi+16(FP), CX
LOCK LOCK
CMPXCHG8B 0(BP) CMPXCHG8B 0(BP)
JNZ cas64_fail JNZ fail
MOVL $1, AX MOVL $1, AX
MOVB AX, ret+20(FP) MOVB AX, ret+20(FP)
RET RET
cas64_fail: fail:
MOVL $0, AX MOVL $0, AX
MOVB AX, ret+20(FP) MOVB AX, ret+20(FP)
RET RET
@ -1356,29 +1356,29 @@ TEXT strings·IndexByte(SB),NOSPLIT,$0
// AX = 1/0/-1 // AX = 1/0/-1
TEXT runtime·cmpbody(SB),NOSPLIT,$0-0 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
CMPL SI, DI CMPL SI, DI
JEQ cmp_allsame JEQ allsame
CMPL BX, DX CMPL BX, DX
MOVL DX, BP MOVL DX, BP
CMOVLLT BX, BP // BP = min(alen, blen) CMOVLLT BX, BP // BP = min(alen, blen)
CMPL BP, $4 CMPL BP, $4
JB cmp_small JB small
TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2 TESTL $0x4000000, runtime·cpuid_edx(SB) // check for sse2
JE cmp_mediumloop JE mediumloop
cmp_largeloop: largeloop:
CMPL BP, $16 CMPL BP, $16
JB cmp_mediumloop JB mediumloop
MOVOU (SI), X0 MOVOU (SI), X0
MOVOU (DI), X1 MOVOU (DI), X1
PCMPEQB X0, X1 PCMPEQB X0, X1
PMOVMSKB X1, AX PMOVMSKB X1, AX
XORL $0xffff, AX // convert EQ to NE 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, SI
ADDL $16, DI ADDL $16, DI
SUBL $16, BP SUBL $16, BP
JMP cmp_largeloop JMP largeloop
cmp_diff16: diff16:
BSFL AX, BX // index of first byte that differs BSFL AX, BX // index of first byte that differs
XORL AX, AX XORL AX, AX
MOVB (SI)(BX*1), CX MOVB (SI)(BX*1), CX
@ -1387,25 +1387,25 @@ cmp_diff16:
LEAL -1(AX*2), AX // convert 1/0 to +1/-1 LEAL -1(AX*2), AX // convert 1/0 to +1/-1
RET RET
cmp_mediumloop: mediumloop:
CMPL BP, $4 CMPL BP, $4
JBE cmp_0through4 JBE _0through4
MOVL (SI), AX MOVL (SI), AX
MOVL (DI), CX MOVL (DI), CX
CMPL AX, CX CMPL AX, CX
JNE cmp_diff4 JNE diff4
ADDL $4, SI ADDL $4, SI
ADDL $4, DI ADDL $4, DI
SUBL $4, BP SUBL $4, BP
JMP cmp_mediumloop JMP mediumloop
cmp_0through4: _0through4:
MOVL -4(SI)(BP*1), AX MOVL -4(SI)(BP*1), AX
MOVL -4(DI)(BP*1), CX MOVL -4(DI)(BP*1), CX
CMPL AX, CX CMPL AX, CX
JEQ cmp_allsame JEQ allsame
cmp_diff4: diff4:
BSWAPL AX // reverse order of bytes BSWAPL AX // reverse order of bytes
BSWAPL CX BSWAPL CX
XORL AX, CX // find bit differences XORL AX, CX // find bit differences
@ -1416,37 +1416,37 @@ cmp_diff4:
RET RET
// 0-3 bytes in common // 0-3 bytes in common
cmp_small: small:
LEAL (BP*8), CX LEAL (BP*8), CX
NEGL CX NEGL CX
JEQ cmp_allsame JEQ allsame
// load si // load si
CMPB SI, $0xfc CMPB SI, $0xfc
JA cmp_si_high JA si_high
MOVL (SI), SI MOVL (SI), SI
JMP cmp_si_finish JMP si_finish
cmp_si_high: si_high:
MOVL -4(SI)(BP*1), SI MOVL -4(SI)(BP*1), SI
SHRL CX, SI SHRL CX, SI
cmp_si_finish: si_finish:
SHLL CX, SI SHLL CX, SI
// same for di // same for di
CMPB DI, $0xfc CMPB DI, $0xfc
JA cmp_di_high JA di_high
MOVL (DI), DI MOVL (DI), DI
JMP cmp_di_finish JMP di_finish
cmp_di_high: di_high:
MOVL -4(DI)(BP*1), DI MOVL -4(DI)(BP*1), DI
SHRL CX, DI SHRL CX, DI
cmp_di_finish: di_finish:
SHLL CX, DI SHLL CX, DI
BSWAPL SI // reverse order of bytes BSWAPL SI // reverse order of bytes
BSWAPL DI BSWAPL DI
XORL SI, DI // find bit differences XORL SI, DI // find bit differences
JEQ cmp_allsame JEQ allsame
BSRL DI, CX // index of highest bit difference BSRL DI, CX // index of highest bit difference
SHRL CX, SI // move a's bit to bottom SHRL CX, SI // move a's bit to bottom
ANDL $1, SI // mask bit ANDL $1, SI // mask bit
@ -1455,7 +1455,7 @@ cmp_di_finish:
// all the bytes in common are the same, so we just need // all the bytes in common are the same, so we just need
// to compare the lengths. // to compare the lengths.
cmp_allsame: allsame:
XORL AX, AX XORL AX, AX
XORL CX, CX XORL CX, CX
CMPL BX, DX CMPL BX, DX

View file

@ -461,11 +461,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25
MOVQ new+16(FP), CX MOVQ new+16(FP), CX
LOCK LOCK
CMPXCHGQ CX, 0(BX) CMPXCHGQ CX, 0(BX)
JNZ cas64_fail JNZ fail
MOVL $1, AX MOVL $1, AX
MOVB AX, ret+24(FP) MOVB AX, ret+24(FP)
RET RET
cas64_fail: fail:
MOVL $0, AX MOVL $0, AX
MOVB AX, ret+24(FP) MOVB AX, ret+24(FP)
RET RET
@ -890,24 +890,24 @@ TEXT runtime·aeshashbody(SB),NOSPLIT,$0-32
MOVO runtime·aeskeysched+0(SB), X2 MOVO runtime·aeskeysched+0(SB), X2
MOVO runtime·aeskeysched+16(SB), X3 MOVO runtime·aeskeysched+16(SB), X3
CMPQ CX, $16 CMPQ CX, $16
JB aessmall JB small
aesloop: loop:
CMPQ CX, $16 CMPQ CX, $16
JBE aesloopend JBE loopend
MOVOU (AX), X1 MOVOU (AX), X1
AESENC X2, X0 AESENC X2, X0
AESENC X1, X0 AESENC X1, X0
SUBQ $16, CX SUBQ $16, CX
ADDQ $16, AX ADDQ $16, AX
JMP aesloop JMP loop
// 1-16 bytes remaining // 1-16 bytes remaining
aesloopend: loopend:
// This load may overlap with the previous load above. // This load may overlap with the previous load above.
// We'll hash some bytes twice, but that's ok. // We'll hash some bytes twice, but that's ok.
MOVOU -16(AX)(CX*1), X1 MOVOU -16(AX)(CX*1), X1
JMP partial JMP partial
// 0-15 bytes // 0-15 bytes
aessmall: small:
TESTQ CX, CX TESTQ CX, CX
JE finalize // 0 bytes JE finalize // 0 bytes
@ -1050,18 +1050,18 @@ TEXT runtime·eqstring(SB),NOSPLIT,$0-33
MOVQ s1len+8(FP), AX MOVQ s1len+8(FP), AX
MOVQ s2len+24(FP), BX MOVQ s2len+24(FP), BX
CMPQ AX, BX CMPQ AX, BX
JNE different JNE noteq
MOVQ s1str+0(FP), SI MOVQ s1str+0(FP), SI
MOVQ s2str+16(FP), DI MOVQ s2str+16(FP), DI
CMPQ SI, DI CMPQ SI, DI
JEQ same JEQ eq
CALL runtime·memeqbody(SB) CALL runtime·memeqbody(SB)
MOVB AX, v+32(FP) MOVB AX, v+32(FP)
RET RET
same: eq:
MOVB $1, v+32(FP) MOVB $1, v+32(FP)
RET RET
different: noteq:
MOVB $0, v+32(FP) MOVB $0, v+32(FP)
RET RET
@ -1184,29 +1184,29 @@ TEXT runtime·cmpbytes(SB),NOSPLIT,$0-56
// AX = 1/0/-1 // AX = 1/0/-1
TEXT runtime·cmpbody(SB),NOSPLIT,$0-0 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
CMPQ SI, DI CMPQ SI, DI
JEQ cmp_allsame JEQ allsame
CMPQ BX, DX CMPQ BX, DX
MOVQ DX, BP MOVQ DX, BP
CMOVQLT BX, BP // BP = min(alen, blen) = # of bytes to compare CMOVQLT BX, BP // BP = min(alen, blen) = # of bytes to compare
CMPQ BP, $8 CMPQ BP, $8
JB cmp_small JB small
cmp_loop: loop:
CMPQ BP, $16 CMPQ BP, $16
JBE cmp_0through16 JBE _0through16
MOVOU (SI), X0 MOVOU (SI), X0
MOVOU (DI), X1 MOVOU (DI), X1
PCMPEQB X0, X1 PCMPEQB X0, X1
PMOVMSKB X1, AX PMOVMSKB X1, AX
XORQ $0xffff, AX // convert EQ to NE 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, SI
ADDQ $16, DI ADDQ $16, DI
SUBQ $16, BP SUBQ $16, BP
JMP cmp_loop JMP loop
// AX = bit mask of differences // AX = bit mask of differences
cmp_diff16: diff16:
BSFQ AX, BX // index of first byte that differs BSFQ AX, BX // index of first byte that differs
XORQ AX, AX XORQ AX, AX
MOVB (SI)(BX*1), CX MOVB (SI)(BX*1), CX
@ -1216,21 +1216,21 @@ cmp_diff16:
RET RET
// 0 through 16 bytes left, alen>=8, blen>=8 // 0 through 16 bytes left, alen>=8, blen>=8
cmp_0through16: _0through16:
CMPQ BP, $8 CMPQ BP, $8
JBE cmp_0through8 JBE _0through8
MOVQ (SI), AX MOVQ (SI), AX
MOVQ (DI), CX MOVQ (DI), CX
CMPQ AX, CX CMPQ AX, CX
JNE cmp_diff8 JNE diff8
cmp_0through8: _0through8:
MOVQ -8(SI)(BP*1), AX MOVQ -8(SI)(BP*1), AX
MOVQ -8(DI)(BP*1), CX MOVQ -8(DI)(BP*1), CX
CMPQ AX, CX CMPQ AX, CX
JEQ cmp_allsame JEQ allsame
// AX and CX contain parts of a and b that differ. // AX and CX contain parts of a and b that differ.
cmp_diff8: diff8:
BSWAPQ AX // reverse order of bytes BSWAPQ AX // reverse order of bytes
BSWAPQ CX BSWAPQ CX
XORQ AX, CX XORQ AX, CX
@ -1241,44 +1241,44 @@ cmp_diff8:
RET RET
// 0-7 bytes in common // 0-7 bytes in common
cmp_small: small:
LEAQ (BP*8), CX // bytes left -> bits left LEAQ (BP*8), CX // bytes left -> bits left
NEGQ CX // - bits lift (== 64 - bits left mod 64) NEGQ CX // - bits lift (== 64 - bits left mod 64)
JEQ cmp_allsame JEQ allsame
// load bytes of a into high bytes of AX // load bytes of a into high bytes of AX
CMPB SI, $0xf8 CMPB SI, $0xf8
JA cmp_si_high JA si_high
MOVQ (SI), SI MOVQ (SI), SI
JMP cmp_si_finish JMP si_finish
cmp_si_high: si_high:
MOVQ -8(SI)(BP*1), SI MOVQ -8(SI)(BP*1), SI
SHRQ CX, SI SHRQ CX, SI
cmp_si_finish: si_finish:
SHLQ CX, SI SHLQ CX, SI
// load bytes of b in to high bytes of BX // load bytes of b in to high bytes of BX
CMPB DI, $0xf8 CMPB DI, $0xf8
JA cmp_di_high JA di_high
MOVQ (DI), DI MOVQ (DI), DI
JMP cmp_di_finish JMP di_finish
cmp_di_high: di_high:
MOVQ -8(DI)(BP*1), DI MOVQ -8(DI)(BP*1), DI
SHRQ CX, DI SHRQ CX, DI
cmp_di_finish: di_finish:
SHLQ CX, DI SHLQ CX, DI
BSWAPQ SI // reverse order of bytes BSWAPQ SI // reverse order of bytes
BSWAPQ DI BSWAPQ DI
XORQ SI, DI // find bit differences XORQ SI, DI // find bit differences
JEQ cmp_allsame JEQ allsame
BSRQ DI, CX // index of highest bit difference BSRQ DI, CX // index of highest bit difference
SHRQ CX, SI // move a's bit to bottom SHRQ CX, SI // move a's bit to bottom
ANDQ $1, SI // mask bit ANDQ $1, SI // mask bit
LEAQ -1(SI*2), AX // 1/0 => +1/-1 LEAQ -1(SI*2), AX // 1/0 => +1/-1
RET RET
cmp_allsame: allsame:
XORQ AX, AX XORQ AX, AX
XORQ CX, CX XORQ CX, CX
CMPQ BX, DX CMPQ BX, DX
@ -1313,7 +1313,7 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0
MOVQ SI, DI MOVQ SI, DI
CMPQ BX, $16 CMPQ BX, $16
JLT indexbyte_small JLT small
// round up to first 16-byte boundary // round up to first 16-byte boundary
TESTQ $15, SI TESTQ $15, SI
@ -1371,7 +1371,7 @@ failure:
RET RET
// handle for lengths < 16 // handle for lengths < 16
indexbyte_small: small:
MOVQ BX, CX MOVQ BX, CX
REPN; SCASB REPN; SCASB
JZ success JZ success

View file

@ -444,11 +444,11 @@ TEXT runtime·cas64(SB), NOSPLIT, $0-25
MOVQ new+16(FP), CX MOVQ new+16(FP), CX
LOCK LOCK
CMPXCHGQ CX, 0(BX) CMPXCHGQ CX, 0(BX)
JNZ cas64_fail JNZ fail
MOVL $1, AX MOVL $1, AX
MOVB AX, ret+24(FP) MOVB AX, ret+24(FP)
RET RET
cas64_fail: fail:
MOVL $0, AX MOVL $0, AX
MOVB AX, ret+24(FP) MOVB AX, ret+24(FP)
RET RET
@ -834,29 +834,29 @@ TEXT runtime·cmpbytes(SB),NOSPLIT,$0-28
// AX = 1/0/-1 // AX = 1/0/-1
TEXT runtime·cmpbody(SB),NOSPLIT,$0-0 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
CMPQ SI, DI CMPQ SI, DI
JEQ cmp_allsame JEQ allsame
CMPQ BX, DX CMPQ BX, DX
MOVQ DX, R8 MOVQ DX, R8
CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare
CMPQ R8, $8 CMPQ R8, $8
JB cmp_small JB small
cmp_loop: loop:
CMPQ R8, $16 CMPQ R8, $16
JBE cmp_0through16 JBE _0through16
MOVOU (SI), X0 MOVOU (SI), X0
MOVOU (DI), X1 MOVOU (DI), X1
PCMPEQB X0, X1 PCMPEQB X0, X1
PMOVMSKB X1, AX PMOVMSKB X1, AX
XORQ $0xffff, AX // convert EQ to NE 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, SI
ADDQ $16, DI ADDQ $16, DI
SUBQ $16, R8 SUBQ $16, R8
JMP cmp_loop JMP loop
// AX = bit mask of differences // AX = bit mask of differences
cmp_diff16: diff16:
BSFQ AX, BX // index of first byte that differs BSFQ AX, BX // index of first byte that differs
XORQ AX, AX XORQ AX, AX
ADDQ BX, SI ADDQ BX, SI
@ -868,23 +868,23 @@ cmp_diff16:
RET RET
// 0 through 16 bytes left, alen>=8, blen>=8 // 0 through 16 bytes left, alen>=8, blen>=8
cmp_0through16: _0through16:
CMPQ R8, $8 CMPQ R8, $8
JBE cmp_0through8 JBE _0through8
MOVQ (SI), AX MOVQ (SI), AX
MOVQ (DI), CX MOVQ (DI), CX
CMPQ AX, CX CMPQ AX, CX
JNE cmp_diff8 JNE diff8
cmp_0through8: _0through8:
ADDQ R8, SI ADDQ R8, SI
ADDQ R8, DI ADDQ R8, DI
MOVQ -8(SI), AX MOVQ -8(SI), AX
MOVQ -8(DI), CX MOVQ -8(DI), CX
CMPQ AX, CX CMPQ AX, CX
JEQ cmp_allsame JEQ allsame
// AX and CX contain parts of a and b that differ. // AX and CX contain parts of a and b that differ.
cmp_diff8: diff8:
BSWAPQ AX // reverse order of bytes BSWAPQ AX // reverse order of bytes
BSWAPQ CX BSWAPQ CX
XORQ AX, CX XORQ AX, CX
@ -895,46 +895,46 @@ cmp_diff8:
RET RET
// 0-7 bytes in common // 0-7 bytes in common
cmp_small: small:
LEAQ (R8*8), CX // bytes left -> bits left LEAQ (R8*8), CX // bytes left -> bits left
NEGQ CX // - bits lift (== 64 - bits left mod 64) NEGQ CX // - bits lift (== 64 - bits left mod 64)
JEQ cmp_allsame JEQ allsame
// load bytes of a into high bytes of AX // load bytes of a into high bytes of AX
CMPB SI, $0xf8 CMPB SI, $0xf8
JA cmp_si_high JA si_high
MOVQ (SI), SI MOVQ (SI), SI
JMP cmp_si_finish JMP si_finish
cmp_si_high: si_high:
ADDQ R8, SI ADDQ R8, SI
MOVQ -8(SI), SI MOVQ -8(SI), SI
SHRQ CX, SI SHRQ CX, SI
cmp_si_finish: si_finish:
SHLQ CX, SI SHLQ CX, SI
// load bytes of b in to high bytes of BX // load bytes of b in to high bytes of BX
CMPB DI, $0xf8 CMPB DI, $0xf8
JA cmp_di_high JA di_high
MOVQ (DI), DI MOVQ (DI), DI
JMP cmp_di_finish JMP di_finish
cmp_di_high: di_high:
ADDQ R8, DI ADDQ R8, DI
MOVQ -8(DI), DI MOVQ -8(DI), DI
SHRQ CX, DI SHRQ CX, DI
cmp_di_finish: di_finish:
SHLQ CX, DI SHLQ CX, DI
BSWAPQ SI // reverse order of bytes BSWAPQ SI // reverse order of bytes
BSWAPQ DI BSWAPQ DI
XORQ SI, DI // find bit differences XORQ SI, DI // find bit differences
JEQ cmp_allsame JEQ allsame
BSRQ DI, CX // index of highest bit difference BSRQ DI, CX // index of highest bit difference
SHRQ CX, SI // move a's bit to bottom SHRQ CX, SI // move a's bit to bottom
ANDQ $1, SI // mask bit ANDQ $1, SI // mask bit
LEAQ -1(SI*2), AX // 1/0 => +1/-1 LEAQ -1(SI*2), AX // 1/0 => +1/-1
RET RET
cmp_allsame: allsame:
XORQ AX, AX XORQ AX, AX
XORQ CX, CX XORQ CX, CX
CMPQ BX, DX CMPQ BX, DX
@ -969,7 +969,7 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0
MOVL SI, DI MOVL SI, DI
CMPL BX, $16 CMPL BX, $16
JLT indexbyte_small JLT small
// round up to first 16-byte boundary // round up to first 16-byte boundary
TESTL $15, SI TESTL $15, SI
@ -1027,7 +1027,7 @@ failure:
RET RET
// handle for lengths < 16 // handle for lengths < 16
indexbyte_small: small:
MOVL BX, CX MOVL BX, CX
REPN; SCASB REPN; SCASB
JZ success JZ success

View file

@ -492,7 +492,7 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0
MOVW g_m(g), R8 MOVW g_m(g), R8
MOVW m_g0(R8), R3 MOVW m_g0(R8), R3
CMP R3, g CMP R3, g
BEQ asmcgocall_g0 BEQ g0
BL gosave<>(SB) BL gosave<>(SB)
MOVW R0, R5 MOVW R0, R5
MOVW R3, R0 MOVW R3, R0
@ -501,7 +501,7 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0
MOVW (g_sched+gobuf_sp)(g), R13 MOVW (g_sched+gobuf_sp)(g), R13
// Now on a scheduling stack (a pthread-created stack). // Now on a scheduling stack (a pthread-created stack).
asmcgocall_g0: g0:
SUB $24, R13 SUB $24, R13
BIC $0x7, R13 // alignment for gcc ABI BIC $0x7, R13 // alignment for gcc ABI
MOVW R4, 20(R13) // save old g MOVW R4, 20(R13) // save old g
@ -751,13 +751,13 @@ TEXT runtime·memeq(SB),NOSPLIT,$-4-13
ADD R1, R3, R6 ADD R1, R3, R6
MOVW $1, R0 MOVW $1, R0
MOVB R0, ret+12(FP) MOVB R0, ret+12(FP)
_next2: loop:
CMP R1, R6 CMP R1, R6
RET.EQ RET.EQ
MOVBU.P 1(R1), R4 MOVBU.P 1(R1), R4
MOVBU.P 1(R2), R5 MOVBU.P 1(R2), R5
CMP R4, R5 CMP R4, R5
BEQ _next2 BEQ loop
MOVW $0, R0 MOVW $0, R0
MOVB R0, ret+12(FP) MOVB R0, ret+12(FP)
@ -780,13 +780,13 @@ TEXT runtime·eqstring(SB),NOSPLIT,$-4-17
CMP R2, R3 CMP R2, R3
RET.EQ RET.EQ
ADD R2, R0, R6 ADD R2, R0, R6
_eqnext: loop:
CMP R2, R6 CMP R2, R6
RET.EQ RET.EQ
MOVBU.P 1(R2), R4 MOVBU.P 1(R2), R4
MOVBU.P 1(R3), R5 MOVBU.P 1(R3), R5
CMP R4, R5 CMP R4, R5
BEQ _eqnext BEQ loop
MOVB R7, v+16(FP) MOVB R7, v+16(FP)
RET RET
@ -801,26 +801,26 @@ TEXT bytes·Equal(SB),NOSPLIT,$0
MOVW b_len+16(FP), R3 MOVW b_len+16(FP), R3
CMP R1, R3 // unequal lengths are not equal CMP R1, R3 // unequal lengths are not equal
B.NE _notequal B.NE notequal
MOVW a+0(FP), R0 MOVW a+0(FP), R0
MOVW b+12(FP), R2 MOVW b+12(FP), R2
ADD R0, R1 // end ADD R0, R1 // end
_byteseq_next: loop:
CMP R0, R1 CMP R0, R1
B.EQ _equal // reached the end B.EQ equal // reached the end
MOVBU.P 1(R0), R4 MOVBU.P 1(R0), R4
MOVBU.P 1(R2), R5 MOVBU.P 1(R2), R5
CMP R4, R5 CMP R4, R5
B.EQ _byteseq_next B.EQ loop
_notequal: notequal:
MOVW $0, R0 MOVW $0, R0
MOVBU R0, ret+24(FP) MOVBU R0, ret+24(FP)
RET RET
_equal: equal:
MOVW $1, R0 MOVW $1, R0
MOVBU R0, ret+24(FP) MOVBU R0, ret+24(FP)
RET RET

981
src/runtime/asm_power64x.s Normal file
View file

@ -0,0 +1,981 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
#include "textflag.h"
TEXT runtime·rt0_go(SB),NOSPLIT,$0
// initialize essential registers
BL runtime·reginit(SB)
SUB $24, R1
MOVW R3, 8(R1) // argc
MOVD R4, 16(R1) // argv
// create istack out of the given (operating system) stack.
// _cgo_init may update stackguard.
MOVD $runtime·g0(SB), g
MOVD $(-64*1024), R31
ADD R31, R1, R3
MOVD R3, g_stackguard0(g)
MOVD R3, g_stackguard1(g)
MOVD R3, (g_stack+stack_lo)(g)
MOVD R1, (g_stack+stack_hi)(g)
// TODO: if there is a _cgo_init, call it.
// TODO: add TLS
// set the per-goroutine and per-mach "registers"
MOVD $runtime·m0(SB), R3
// save m->g0 = g0
MOVD g, m_g0(R3)
// save m0 to g0->m
MOVD R3, g_m(g)
BL runtime·check(SB)
// args are already prepared
BL runtime·args(SB)
BL runtime·osinit(SB)
BL runtime·schedinit(SB)
// create a new goroutine to start program
MOVD $runtime·main·f(SB), R3 // entry
MOVDU R3, -8(R1)
MOVDU R0, -8(R1)
MOVDU R0, -8(R1)
BL runtime·newproc(SB)
ADD $24, R1
// start this M
BL runtime·mstart(SB)
MOVD R0, 1(R0)
RETURN
DATA runtime·main·f+0(SB)/8,$runtime·main(SB)
GLOBL runtime·main·f(SB),RODATA,$8
TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
MOVD R0, 2(R0) // TODO: TD
RETURN
TEXT runtime·asminit(SB),NOSPLIT,$-8-0
RETURN
TEXT runtime·reginit(SB),NOSPLIT,$-8-0
// set R0 to zero, it's expected by the toolchain
XOR R0, R0
// initialize essential FP registers
FMOVD $4503601774854144.0, F27
FMOVD $0.5, F29
FSUB F29, F29, F28
FADD F29, F29, F30
FADD F30, F30, F31
RETURN
/*
* go-routine
*/
// void gosave(Gobuf*)
// save state in Gobuf; setjmp
TEXT runtime·gosave(SB), NOSPLIT, $-8-8
MOVD gobuf+0(FP), R3
MOVD R1, gobuf_sp(R3)
MOVD LR, R31
MOVD R31, gobuf_pc(R3)
MOVD g, gobuf_g(R3)
MOVD R0, gobuf_lr(R3)
MOVD R0, gobuf_ret(R3)
MOVD R0, gobuf_ctxt(R3)
RETURN
// void gogo(Gobuf*)
// restore state from Gobuf; longjmp
TEXT runtime·gogo(SB), NOSPLIT, $-8-8
MOVD gobuf+0(FP), R5
MOVD gobuf_g(R5), g // make sure g is not nil
MOVD 0(g), R4
MOVD gobuf_sp(R5), R1
MOVD gobuf_lr(R5), R31
MOVD R31, LR
MOVD gobuf_ret(R5), R3
MOVD gobuf_ctxt(R5), R11
MOVD R0, gobuf_sp(R5)
MOVD R0, gobuf_ret(R5)
MOVD R0, gobuf_lr(R5)
MOVD R0, gobuf_ctxt(R5)
CMP R0, R0 // set condition codes for == test, needed by stack split
MOVD gobuf_pc(R5), R31
MOVD R31, CTR
BR (CTR)
// void mcall(fn func(*g))
// Switch to m->g0's stack, call fn(g).
// Fn must never return. It should gogo(&g->sched)
// to keep running g.
TEXT runtime·mcall(SB), NOSPLIT, $-8-8
// Save caller state in g->sched
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD LR, R31
MOVD R31, (g_sched+gobuf_pc)(g)
MOVD R0, (g_sched+gobuf_lr)(g)
MOVD g, (g_sched+gobuf_g)(g)
// Switch to m->g0 & its stack, call fn.
MOVD g, R3
MOVD g_m(g), R8
MOVD m_g0(R8), g
CMP g, R3
BNE 2(PC)
BR runtime·badmcall(SB)
MOVD fn+0(FP), R11 // context
MOVD 0(R11), R4 // code pointer
MOVD R4, CTR
MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp
MOVDU R3, -8(R1)
MOVDU R0, -8(R1)
BL (CTR)
BR runtime·badmcall2(SB)
// switchtoM is a dummy routine that onM leaves at the bottom
// of the G stack. We need to distinguish the routine that
// lives at the bottom of the G stack from the one that lives
// at the top of the M stack because the one at the top of
// the M stack terminates the stack walk (see topofstack()).
TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
UNDEF
BL (LR) // make sure this function is not leaf
RETURN
// func onM_signalok(fn func())
TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8
MOVD g, R3 // R3 = g
MOVD g_m(R3), R4 // R4 = g->m
MOVD m_gsignal(R4), R4 // R4 = g->m->gsignal
MOVD fn+0(FP), R11 // context for call below
CMP R3, R4
BEQ onsignal
MOVD R11, 8(R1)
BL runtime·onM(SB)
RETURN
onsignal:
MOVD 0(R11), R3 // code pointer
MOVD R3, CTR
BL (CTR)
RETURN
// void onM(fn func())
TEXT runtime·onM(SB), NOSPLIT, $0-8
MOVD fn+0(FP), R3 // R3 = fn
MOVD R3, R11 // context
MOVD g_m(g), R4 // R4 = m
MOVD m_g0(R4), R5 // R5 = g0
CMP g, R5
BEQ onm
MOVD m_curg(R4), R6
CMP g, R6
BEQ oncurg
// Not g0, not curg. Must be gsignal, but that's not allowed.
// Hide call from linker nosplit analysis.
MOVD $runtime·badonm(SB), R3
MOVD R3, CTR
BL (CTR)
oncurg:
// save our state in g->sched. Pretend to
// be switchtoM if the G stack is scanned.
MOVD $runtime·switchtoM(SB), R6
ADD $8, R6 // get past prologue
MOVD R6, (g_sched+gobuf_pc)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD R0, (g_sched+gobuf_lr)(g)
MOVD g, (g_sched+gobuf_g)(g)
// switch to g0
MOVD R5, g
MOVD (g_sched+gobuf_sp)(g), R3
// make it look like mstart called onM on g0, to stop traceback
SUB $8, R3
MOVD $runtime·mstart(SB), R4
MOVD R4, 0(R3)
MOVD R3, R1
// call target function
MOVD 0(R11), R3 // code pointer
MOVD R3, CTR
BL (CTR)
// switch back to g
MOVD g_m(g), R3
MOVD m_curg(R3), g
MOVD (g_sched+gobuf_sp)(g), R1
MOVD R0, (g_sched+gobuf_sp)(g)
RETURN
onm:
// already on m stack, just call directly
MOVD 0(R11), R3 // code pointer
MOVD R3, CTR
BL (CTR)
RETURN
/*
* support for morestack
*/
// Called during function prolog when more stack is needed.
// Caller has already loaded:
// R3: framesize, R4: argsize, R5: LR
//
// The traceback routines see morestack on a g0 as being
// the top of a stack (for example, morestack calling newstack
// calling the scheduler calling newm calling gc), so we must
// record an argument size. For that purpose, it has no arguments.
TEXT runtime·morestack(SB),NOSPLIT,$-8-0
// Cannot grow scheduler stack (m->g0).
MOVD g_m(g), R7
MOVD m_g0(R7), R8
CMP g, R8
BNE 2(PC)
BL runtime·abort(SB)
// Cannot grow signal stack (m->gsignal).
MOVD m_gsignal(R7), R8
CMP g, R8
BNE 2(PC)
BL runtime·abort(SB)
// Called from f.
// Set g->sched to context in f.
MOVD R11, (g_sched+gobuf_ctxt)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD LR, R8
MOVD R8, (g_sched+gobuf_pc)(g)
MOVD R5, (g_sched+gobuf_lr)(g)
// Called from f.
// Set m->morebuf to f's caller.
MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
MOVD g, (m_morebuf+gobuf_g)(R7)
// Call newstack on m->g0's stack.
MOVD m_g0(R7), g
MOVD (g_sched+gobuf_sp)(g), R1
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// is still in this function, and not the beginning of the next.
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
MOVD R0, R11
BR runtime·morestack(SB)
// reflectcall: call a function with the given argument list
// func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
// we don't have variable-sized frames, so we use a small number
// of constant-sized-frame functions to encode a few bits of size in the pc.
// Caution: ugly multiline assembly macros in your future!
#define DISPATCH(NAME,MAXSIZE) \
MOVD $MAXSIZE, R31; \
CMP R3, R31; \
BGT 4(PC); \
MOVD $NAME(SB), R31; \
MOVD R31, CTR; \
BR (CTR)
// Note: can't just "BR NAME(SB)" - bad inlining results.
TEXT ·reflectcall(SB), NOSPLIT, $-8-24
MOVW argsize+16(FP), R3
DISPATCH(runtime·call16, 16)
DISPATCH(runtime·call32, 32)
DISPATCH(runtime·call64, 64)
DISPATCH(runtime·call128, 128)
DISPATCH(runtime·call256, 256)
DISPATCH(runtime·call512, 512)
DISPATCH(runtime·call1024, 1024)
DISPATCH(runtime·call2048, 2048)
DISPATCH(runtime·call4096, 4096)
DISPATCH(runtime·call8192, 8192)
DISPATCH(runtime·call16384, 16384)
DISPATCH(runtime·call32768, 32768)
DISPATCH(runtime·call65536, 65536)
DISPATCH(runtime·call131072, 131072)
DISPATCH(runtime·call262144, 262144)
DISPATCH(runtime·call524288, 524288)
DISPATCH(runtime·call1048576, 1048576)
DISPATCH(runtime·call2097152, 2097152)
DISPATCH(runtime·call4194304, 4194304)
DISPATCH(runtime·call8388608, 8388608)
DISPATCH(runtime·call16777216, 16777216)
DISPATCH(runtime·call33554432, 33554432)
DISPATCH(runtime·call67108864, 67108864)
DISPATCH(runtime·call134217728, 134217728)
DISPATCH(runtime·call268435456, 268435456)
DISPATCH(runtime·call536870912, 536870912)
DISPATCH(runtime·call1073741824, 1073741824)
MOVD $runtime·badreflectcall(SB), R31
MOVD R31, CTR
BR (CTR)
#define CALLFN(NAME,MAXSIZE) \
TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
NO_LOCAL_POINTERS; \
/* copy arguments to stack */ \
MOVD argptr+8(FP), R3; \
MOVW argsize+16(FP), R4; \
MOVD R1, R5; \
ADD $(8-1), R5; \
SUB $1, R3; \
ADD R5, R4; \
CMP R5, R4; \
BEQ 4(PC); \
MOVBZU 1(R3), R6; \
MOVBZU R6, 1(R5); \
BR -4(PC); \
/* call function */ \
MOVD f+0(FP), R11; \
MOVD (R11), R31; \
MOVD R31, CTR; \
PCDATA $PCDATA_StackMapIndex, $0; \
BL (CTR); \
/* copy return values back */ \
MOVD argptr+8(FP), R3; \
MOVW argsize+16(FP), R4; \
MOVW retoffset+20(FP), R6; \
MOVD R1, R5; \
ADD R6, R5; \
ADD R6, R3; \
SUB R6, R4; \
ADD $(8-1), R5; \
SUB $1, R3; \
ADD R5, R4; \
CMP R5, R4; \
BEQ 4(PC); \
MOVBZU 1(R5), R6; \
MOVBZU R6, 1(R3); \
BR -4(PC); \
RETURN
CALLFN(·call16, 16)
CALLFN(·call32, 32)
CALLFN(·call64, 64)
CALLFN(·call128, 128)
CALLFN(·call256, 256)
CALLFN(·call512, 512)
CALLFN(·call1024, 1024)
CALLFN(·call2048, 2048)
CALLFN(·call4096, 4096)
CALLFN(·call8192, 8192)
CALLFN(·call16384, 16384)
CALLFN(·call32768, 32768)
CALLFN(·call65536, 65536)
CALLFN(·call131072, 131072)
CALLFN(·call262144, 262144)
CALLFN(·call524288, 524288)
CALLFN(·call1048576, 1048576)
CALLFN(·call2097152, 2097152)
CALLFN(·call4194304, 4194304)
CALLFN(·call8388608, 8388608)
CALLFN(·call16777216, 16777216)
CALLFN(·call33554432, 33554432)
CALLFN(·call67108864, 67108864)
CALLFN(·call134217728, 134217728)
CALLFN(·call268435456, 268435456)
CALLFN(·call536870912, 536870912)
CALLFN(·call1073741824, 1073741824)
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
// if(*val == old){
// *val = new;
// return 1;
// } else
// return 0;
TEXT runtime·cas(SB), NOSPLIT, $0-17
MOVD p+0(FP), R3
MOVW old+8(FP), R4
MOVW new+12(FP), R5
cas_again:
SYNC
LWAR (R3), R6
CMPW R6, R4
BNE cas_fail
STWCCC R5, (R3)
BNE cas_again
MOVD $1, R3
SYNC
ISYNC
MOVB R3, ret+16(FP)
RETURN
cas_fail:
MOVD $0, R3
BR -5(PC)
// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
// Atomically:
// if(*val == *old){
// *val = new;
// return 1;
// } else {
// return 0;
// }
TEXT runtime·cas64(SB), NOSPLIT, $0-25
MOVD p+0(FP), R3
MOVD old+8(FP), R4
MOVD new+16(FP), R5
cas64_again:
SYNC
LDAR (R3), R6
CMP R6, R4
BNE cas64_fail
STDCCC R5, (R3)
BNE cas64_again
MOVD $1, R3
SYNC
ISYNC
MOVB R3, ret+24(FP)
RETURN
cas64_fail:
MOVD $0, R3
BR -5(PC)
TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
BR runtime·cas64(SB)
TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
BR runtime·atomicload64(SB)
TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
BR runtime·atomicload64(SB)
TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
BR runtime·atomicstore64(SB)
// bool casp(void **val, void *old, void *new)
// Atomically:
// if(*val == old){
// *val = new;
// return 1;
// } else
// return 0;
TEXT runtime·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-20
MOVD p+0(FP), R4
MOVW delta+8(FP), R5
SYNC
LWAR (R4), R3
ADD R5, R3
STWCCC R3, (R4)
BNE -4(PC)
SYNC
ISYNC
MOVW R3, ret+16(FP)
RETURN
TEXT runtime·xadd64(SB), NOSPLIT, $0-24
MOVD p+0(FP), R4
MOVD delta+8(FP), R5
SYNC
LDAR (R4), R3
ADD R5, R3
STDCCC R3, (R4)
BNE -4(PC)
SYNC
ISYNC
MOVD R3, ret+16(FP)
RETURN
TEXT runtime·xchg(SB), NOSPLIT, $0-20
MOVD p+0(FP), R4
MOVW new+8(FP), R5
SYNC
LWAR (R4), R3
STWCCC R5, (R4)
BNE -3(PC)
SYNC
ISYNC
MOVW R3, ret+16(FP)
RETURN
TEXT runtime·xchg64(SB), NOSPLIT, $0-24
MOVD p+0(FP), R4
MOVD new+8(FP), R5
SYNC
LDAR (R4), R3
STDCCC R5, (R4)
BNE -3(PC)
SYNC
ISYNC
MOVD R3, ret+16(FP)
RETURN
TEXT runtime·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
RETURN
TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16
BR runtime·atomicstore64(SB)
TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
MOVD ptr+0(FP), R3
MOVW val+8(FP), R4
SYNC
MOVW R4, 0(R3)
RETURN
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
MOVD ptr+0(FP), R3
MOVD val+8(FP), R4
SYNC
MOVD R4, 0(R3)
RETURN
// void runtime·atomicor8(byte volatile*, byte);
TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
MOVD ptr+0(FP), R3
MOVBZ val+8(FP), R4
// Align ptr down to 4 bytes so we can use 32-bit load/store.
// R5 = (R3 << 0) & ~3
RLDCR $0, R3, $~3, R5
// Compute val shift.
#ifdef GOARCH_power64
// Big endian. ptr = ptr ^ 3
XOR $3, R3
#endif
// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
RLDC $3, R3, $(3*8), R6
// Shift val for aligned ptr. R4 = val << R6
SLD R6, R4, R4
atomicor8_again:
SYNC
LWAR (R5), R6
OR R4, R6
STWCCC R6, (R5)
BNE atomicor8_again
SYNC
ISYNC
RETURN
// void jmpdefer(fv, sp);
// called from deferreturn.
// 1. grab stored LR for caller
// 2. sub 4 bytes to get back to BL deferreturn
// 3. BR to fn
TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
MOVD 0(R1), R31
SUB $4, R31
MOVD R31, LR
MOVD fv+0(FP), R11
MOVD argp+8(FP), R1
SUB $8, R1
MOVD 0(R11), R3
MOVD R3, CTR
BR (CTR)
// Save state of caller into g->sched. Smashes R31.
TEXT gosave<>(SB),NOSPLIT,$-8
MOVD LR, R31
MOVD R31, (g_sched+gobuf_pc)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD R0, (g_sched+gobuf_lr)(g)
MOVD R0, (g_sched+gobuf_ret)(g)
MOVD R0, (g_sched+gobuf_ctxt)(g)
RETURN
// asmcgocall(void(*fn)(void*), void *arg)
// Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI.
// See cgocall.c for more details.
TEXT ·asmcgocall(SB),NOSPLIT,$0-16
MOVD R0, 21(R0)
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
// Turn the fn into a Go func (by taking its address) and call
// cgocallback_gofunc.
TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
MOVD R0, 22(R0)
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
// See cgocall.c for more details.
TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
MOVD R0, 23(R0)
// void setg(G*); set g. for use by needm.
TEXT runtime·setg(SB), NOSPLIT, $0-8
MOVD R0, 24(R0)
// void setg_gcc(G*); set g called from gcc.
TEXT setg_gcc<>(SB),NOSPLIT,$0
MOVD R0, 25(R0)
TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-16
MOVD 0(R1), R3
MOVD R3, ret+8(FP)
RETURN
TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16
MOVD 0(R1), R3
MOVD R3,ret+8(FP)
RETURN
TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
MOVD pc+8(FP), R3
MOVD R3, 0(R1) // set calling pc
RETURN
TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
MOVD sp+0(FP), R3
SUB $8, R3
MOVD R3, ret+8(FP)
RETURN
// func gogetcallersp(p unsafe.Pointer) uintptr
TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
MOVD sp+0(FP), R3
SUB $8, R3
MOVD R3,ret+8(FP)
RETURN
TEXT runtime·abort(SB),NOSPLIT,$-8-0
MOVW (R0), R0
UNDEF
#define TBRL 268
#define TBRU 269 /* Time base Upper/Lower */
// int64 runtime·cputicks(void)
TEXT runtime·cputicks(SB),NOSPLIT,$0-8
MOVW SPR(TBRU), R4
MOVW SPR(TBRL), R3
MOVW SPR(TBRU), R5
CMPW R4, R5
BNE -4(PC)
SLD $32, R5
OR R5, R3
MOVD R3, ret+0(FP)
RETURN
// AES hashing not implemented for Power
TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·memeq(SB),NOSPLIT,$-8-25
MOVD a+0(FP), R3
MOVD b+8(FP), R4
MOVD count+16(FP), R5
SUB $1, R3
SUB $1, R4
ADD R3, R5, R8
loop:
CMP R3, R8
BNE 4(PC)
MOVD $1, R3
MOVB R3, ret+24(FP)
RETURN
MOVBZU 1(R3), R6
MOVBZU 1(R4), R7
CMP R6, R7
BEQ loop
MOVB R0, ret+24(FP)
RETURN
// eqstring tests whether two strings are equal.
// See runtime_test.go:eqstring_generic for
// equivalent Go code.
TEXT runtime·eqstring(SB),NOSPLIT,$0-33
MOVD s1len+8(FP), R4
MOVD s2len+24(FP), R5
CMP R4, R5
BNE noteq
MOVD s1str+0(FP), R3
MOVD s2str+16(FP), R4
SUB $1, R3
SUB $1, R4
ADD R3, R5, R8
loop:
CMP R3, R8
BNE 4(PC)
MOVD $1, R3
MOVB R3, ret+32(FP)
RETURN
MOVBZU 1(R3), R6
MOVBZU 1(R4), R7
CMP R6, R7
BEQ loop
noteq:
MOVB R0, ret+32(FP)
RETURN
// TODO: share code with memeq?
TEXT bytes·Equal(SB),NOSPLIT,$0-49
MOVD a_len+8(FP), R3
MOVD b_len+32(FP), R4
CMP R3, R4 // unequal lengths are not equal
BNE noteq
MOVD a+0(FP), R5
MOVD b+24(FP), R6
SUB $1, R5
SUB $1, R6
ADD R5, R3 // end-1
loop:
CMP R5, R3
BEQ equal // reached the end
MOVBZU 1(R5), R4
MOVBZU 1(R6), R7
CMP R4, R7
BEQ loop
noteq:
MOVBZ R0, ret+48(FP)
RETURN
equal:
MOVD $1, R3
MOVBZ R3, ret+48(FP)
RETURN
TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
MOVD s+0(FP), R3
MOVD s_len+8(FP), R4
MOVBZ c+24(FP), R5 // byte to find
MOVD R3, R6 // store base for later
SUB $1, R3
ADD R3, R4 // end-1
loop:
CMP R3, R4
BEQ notfound
MOVBZU 1(R3), R7
CMP R7, R5
BNE loop
SUB R6, R3 // remove base
MOVD R3, ret+32(FP)
RETURN
notfound:
MOVD $-1, R3
MOVD R3, ret+32(FP)
RETURN
TEXT strings·IndexByte(SB),NOSPLIT,$0
MOVD p+0(FP), R3
MOVD b_len+8(FP), R4
MOVBZ c+16(FP), R5 // byte to find
MOVD R3, R6 // store base for later
SUB $1, R3
ADD R3, R4 // end-1
loop:
CMP R3, R4
BEQ notfound
MOVBZU 1(R3), R7
CMP R7, R5
BNE loop
SUB R6, R3 // remove base
MOVD R3, ret+24(FP)
RETURN
notfound:
MOVD $-1, R3
MOVD R3, ret+24(FP)
RETURN
// A Duff's device for zeroing memory.
// The compiler jumps to computed addresses within
// this routine to zero chunks of memory. Do not
// change this code without also changing the code
// in ../../cmd/9g/ggen.c:/^clearfat.
// R0: always zero
// R3 (aka REGRT1): ptr to memory to be zeroed - 8
// R3 is updated as a side effect.
TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
RETURN
TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
MOVD g_m(g), R4
MOVWZ m_fastrand(R4), R3
ADD R3, R3
CMP R3, $0
BGE 2(PC)
XOR $0x88888eef, R3
MOVW R3, m_fastrand(R4)
MOVW R3, ret+0(FP)
RETURN
TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R3
RETURN
// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
// Must obey the gcc calling convention.
TEXT _cgo_topofstack(SB),NOSPLIT,$0
MOVD R0, 26(R0)

View file

@ -0,0 +1,40 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
// uint32 runtime·atomicload(uint32 volatile* addr)
TEXT ·atomicload(SB),NOSPLIT,$-8-12
MOVD 0(FP), R3
SYNC
MOVWZ 0(R3), R3
CMPW R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7,0x4
ISYNC
MOVW R3, ret+8(FP)
RETURN
// uint64 runtime·atomicload64(uint64 volatile* addr)
TEXT ·atomicload64(SB),NOSPLIT,$-8-16
MOVD 0(FP), R3
SYNC
MOVD 0(R3), R3
CMP R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7,0x4
ISYNC
MOVD R3, ret+8(FP)
RETURN
// void *runtime·atomicloadp(void *volatile *addr)
TEXT ·atomicloadp(SB),NOSPLIT,$-8-16
MOVD 0(FP), R3
SYNC
MOVD 0(R3), R3
CMP R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7,0x4
ISYNC
MOVD R3, ret+8(FP)
RETURN

View file

@ -7,6 +7,12 @@
#ifdef GOARCH_arm #ifdef GOARCH_arm
#define JMP B #define JMP B
#endif #endif
#ifdef GOARCH_power64
#define JMP BR
#endif
#ifdef GOARCH_power64le
#define JMP BR
#endif
TEXT ·setMaxStack(SB),NOSPLIT,$0-0 TEXT ·setMaxStack(SB),NOSPLIT,$0-0
JMP runtime·setMaxStack(SB) JMP runtime·setMaxStack(SB)

View file

@ -15,12 +15,14 @@ package runtime
/* /*
#include <ucontext.h> #include <ucontext.h>
#include <fcntl.h> #include <fcntl.h>
#include <asm/signal.h>
*/ */
import "C" import "C"
const ( const (
O_RDONLY = C.O_RDONLY O_RDONLY = C.O_RDONLY
O_CLOEXEC = C.O_CLOEXEC O_CLOEXEC = C.O_CLOEXEC
SA_RESTORER = C.SA_RESTORER
) )
type Usigset C.__sigset_t type Usigset C.__sigset_t

Some files were not shown because too many files have changed in this diff Show more