mirror of
https://github.com/golang/go.git
synced 2026-01-30 23:52:05 +03:00
Compare commits
141 Commits
go1.4
...
dev.power6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7904e951d4 | ||
|
|
1222cc4682 | ||
|
|
a11f256436 | ||
|
|
5b38501a4f | ||
|
|
9e7bed88cd | ||
|
|
743bdf612a | ||
|
|
231b8d61e9 | ||
|
|
c3dadb3d19 | ||
|
|
8c060d9392 | ||
|
|
60f66aa817 | ||
|
|
c1e8c57c3d | ||
|
|
7739533f61 | ||
|
|
e156f0e997 | ||
|
|
22c929f538 | ||
|
|
f45fd5753c | ||
|
|
4f81684f86 | ||
|
|
fa32e922d5 | ||
|
|
a5e1e1599c | ||
|
|
d10a115ef9 | ||
|
|
473bfae5ae | ||
|
|
810019286f | ||
|
|
31b1207fde | ||
|
|
84f7ac98f7 | ||
|
|
e1db508ffd | ||
|
|
700ab16daf | ||
|
|
40a5b3ecb1 | ||
|
|
6e86003651 | ||
|
|
c24156bafe | ||
|
|
8a09639ae8 | ||
|
|
4cf28a11e3 | ||
|
|
36d417c0e3 | ||
|
|
097362fd2e | ||
|
|
599199fd9f | ||
|
|
b55791e200 | ||
|
|
87b4149b22 | ||
|
|
c8f50b298c | ||
|
|
c2364b58cc | ||
|
|
cb4f5e1970 | ||
|
|
1b130a08d8 | ||
|
|
062e354c84 | ||
|
|
6be0c8a566 | ||
|
|
5a653089ef | ||
|
|
32c75a2d3d | ||
|
|
93341e8664 | ||
|
|
11ec8ab5cb | ||
|
|
a08783f078 | ||
|
|
a9b9ecc9ef | ||
|
|
f0bd539c59 | ||
|
|
977fba763a | ||
|
|
2bd616b1a7 | ||
|
|
3208250185 | ||
|
|
04d5796b29 | ||
|
|
d0be55a662 | ||
|
|
e445f75dbc | ||
|
|
fd21b9f8b5 | ||
|
|
f9fdc887ae | ||
|
|
249e8f700a | ||
|
|
ed68c7df55 | ||
|
|
6edd1c6d1a | ||
|
|
0bee7f3a17 | ||
|
|
25d4d75376 | ||
|
|
aa739b8d03 | ||
|
|
ecbe6b9f7f | ||
|
|
25bde37af4 | ||
|
|
80e76e272a | ||
|
|
b3375771fc | ||
|
|
7776b0a1cc | ||
|
|
f464573c70 | ||
|
|
5f02073ded | ||
|
|
b697c120f6 | ||
|
|
4f557008e8 | ||
|
|
76b1ddbb96 | ||
|
|
ba9a11e557 | ||
|
|
b7a6fd28db | ||
|
|
404472e50b | ||
|
|
27e657ef68 | ||
|
|
f3f332851f | ||
|
|
856124a1cd | ||
|
|
ebf42035b7 | ||
|
|
6e73ae88b5 | ||
|
|
f285537b7f | ||
|
|
b6d6eb21ec | ||
|
|
f375c0eb0d | ||
|
|
372b5cebe7 | ||
|
|
bc8d35a9cf | ||
|
|
268d901199 | ||
|
|
893f28ca16 | ||
|
|
9b88857f75 | ||
|
|
f0393221a7 | ||
|
|
dbf406a9d8 | ||
|
|
05d670f757 | ||
|
|
c229cec23a | ||
|
|
ca7f2c796f | ||
|
|
53b78c84bc | ||
|
|
27627fd8ed | ||
|
|
3e4dfdad34 | ||
|
|
860f941e7f | ||
|
|
560cf4c6de | ||
|
|
f4529adabe | ||
|
|
5e4989cf0a | ||
|
|
b1c9a8bce3 | ||
|
|
56949d33d8 | ||
|
|
e7e668d717 | ||
|
|
ab29d5b4ae | ||
|
|
91447ab502 | ||
|
|
fb57459b48 | ||
|
|
2abf3c5583 | ||
|
|
f2d43ec7cd | ||
|
|
c74a4d4add | ||
|
|
e0aaf2b2db | ||
|
|
f3e2023764 | ||
|
|
5f691cfaf1 | ||
|
|
4928b2074b | ||
|
|
552d8b79dd | ||
|
|
1a1d450712 | ||
|
|
6e692b35bb | ||
|
|
059d089fc0 | ||
|
|
5cb7da7547 | ||
|
|
8881e032d4 | ||
|
|
26c9bbf736 | ||
|
|
40d7a6d582 | ||
|
|
05d72029db | ||
|
|
5b0ac5f76e | ||
|
|
6e02e1cfc2 | ||
|
|
95e8a3a1da | ||
|
|
4be75c8f26 | ||
|
|
7c33e5078f | ||
|
|
bcf7f61f83 | ||
|
|
fcb842c645 | ||
|
|
83f6aadf16 | ||
|
|
2358603f0c | ||
|
|
c689eb9b21 | ||
|
|
7582ecc996 | ||
|
|
117b1d4685 | ||
|
|
9512e470e1 | ||
|
|
ffb07c0e6c | ||
|
|
245ed93c20 | ||
|
|
bd69b4479a | ||
|
|
ccd880f290 | ||
|
|
8ad746d226 | ||
|
|
dc2bb6d061 |
@@ -2,13 +2,13 @@ syntax:glob
|
||||
.DS_Store
|
||||
.git
|
||||
.gitignore
|
||||
*.[568ao]
|
||||
*.a[568o]
|
||||
*.[5689ao]
|
||||
*.a[5689o]
|
||||
*.so
|
||||
*.pyc
|
||||
._*
|
||||
.nfs.*
|
||||
[568a].out
|
||||
[5689a].out
|
||||
*~
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
@@ -54,7 +54,7 @@ struct Addr
|
||||
{
|
||||
char sval[8];
|
||||
float64 dval;
|
||||
Prog* branch; // for 5g, 6g, 8g
|
||||
Prog* branch; // for 5g, 6g, 8g, 9g
|
||||
} u;
|
||||
|
||||
LSym* sym;
|
||||
@@ -62,9 +62,9 @@ struct Addr
|
||||
short type;
|
||||
uint8 index;
|
||||
int8 scale;
|
||||
int8 reg; // for 5l
|
||||
int8 name; // for 5l
|
||||
int8 class; // for 5l
|
||||
int8 reg; // for 5l, 9l
|
||||
int8 name; // for 5l, 9l
|
||||
int8 class; // for 5l, 9l
|
||||
uint8 etype; // for 5g, 6g, 8g
|
||||
int32 offset2; // for 5l, 8l
|
||||
struct Node* node; // for 5g, 6g, 8g
|
||||
@@ -89,9 +89,13 @@ struct Prog
|
||||
int32 lineno;
|
||||
Prog* link;
|
||||
short as;
|
||||
uchar reg; // arm only
|
||||
uchar scond; // arm only
|
||||
uchar scond; // arm only; condition codes
|
||||
|
||||
// operands
|
||||
Addr from;
|
||||
uchar reg; // arm, power64 only (e.g., ADD from, reg, to);
|
||||
// also used for ADATA width on arm, power64
|
||||
Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
|
||||
Addr to;
|
||||
|
||||
// for 5g, 6g, 8g internal use
|
||||
@@ -103,11 +107,11 @@ struct Prog
|
||||
Prog* comefrom; // 6l, 8l
|
||||
Prog* pcrel; // 5l
|
||||
int32 spadj;
|
||||
uchar mark;
|
||||
uint16 mark;
|
||||
uint16 optab; // 5l, 9l
|
||||
uchar back; // 6l, 8l
|
||||
uchar ft; /* 6l, 8l oclass cache */
|
||||
uchar tt; // 6l, 8l
|
||||
uint16 optab; // 5l
|
||||
uchar isize; // 6l, 8l
|
||||
|
||||
char width; /* fake for DATA */
|
||||
@@ -233,10 +237,12 @@ enum
|
||||
enum
|
||||
{
|
||||
R_ADDR = 1,
|
||||
R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power
|
||||
R_SIZE,
|
||||
R_CALL, // relocation for direct PC-relative call
|
||||
R_CALLARM, // relocation for ARM direct call
|
||||
R_CALLIND, // marker for indirect call (no actual relocating necessary)
|
||||
R_CALLPOWER, // relocation for Power direct call
|
||||
R_CONST,
|
||||
R_PCREL,
|
||||
R_TLS,
|
||||
@@ -529,6 +535,9 @@ void span6(Link *ctxt, LSym *s);
|
||||
// asm8.c
|
||||
void span8(Link *ctxt, LSym *s);
|
||||
|
||||
// asm9.c
|
||||
void span9(Link *ctxt, LSym *s);
|
||||
|
||||
// data.c
|
||||
vlong addaddr(Link *ctxt, LSym *s, LSym *t);
|
||||
vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add);
|
||||
@@ -576,10 +585,11 @@ Prog* copyp(Link*, Prog*);
|
||||
Prog* appendp(Link*, Prog*);
|
||||
vlong atolwhex(char*);
|
||||
|
||||
// list[568].c
|
||||
// list[5689].c
|
||||
void listinit5(void);
|
||||
void listinit6(void);
|
||||
void listinit8(void);
|
||||
void listinit9(void);
|
||||
|
||||
// obj.c
|
||||
int linklinefmt(Link *ctxt, Fmt *fp);
|
||||
@@ -611,20 +621,29 @@ char* headstr(int);
|
||||
extern char* anames5[];
|
||||
extern char* anames6[];
|
||||
extern char* anames8[];
|
||||
extern char* anames9[];
|
||||
|
||||
extern char* cnames5[];
|
||||
extern char* cnames9[];
|
||||
|
||||
extern char* dnames5[];
|
||||
extern char* dnames6[];
|
||||
extern char* dnames8[];
|
||||
extern char* dnames9[];
|
||||
|
||||
extern LinkArch link386;
|
||||
extern LinkArch linkamd64;
|
||||
extern LinkArch linkamd64p32;
|
||||
extern LinkArch linkarm;
|
||||
extern LinkArch linkpower64;
|
||||
extern LinkArch linkpower64le;
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "D" Addr*
|
||||
#pragma varargck type "lD" Addr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "^" int
|
||||
#pragma varargck type "^" int // for 5l/9l, C_* classes (liblink internal)
|
||||
|
||||
// TODO(ality): remove this workaround.
|
||||
// It's here because Pconv in liblink/list?.c references %L.
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
defaultcc: golang-codereviews@googlegroups.com
|
||||
contributors: http://go.googlecode.com/hg/CONTRIBUTORS
|
||||
|
||||
@@ -3603,11 +3603,17 @@ class MercurialVCS(VersionControlSystem):
|
||||
if use_hg_shell:
|
||||
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True)
|
||||
else:
|
||||
base_content = str(self.repo[base_rev][oldrelpath].data())
|
||||
try:
|
||||
base_content = str(self.repo[base_rev][oldrelpath].data())
|
||||
except Exception:
|
||||
pass
|
||||
is_binary = "\0" in base_content # Mercurial's heuristic
|
||||
if status != "R":
|
||||
new_content = open(relpath, "rb").read()
|
||||
is_binary = is_binary or "\0" in new_content
|
||||
try:
|
||||
new_content = open(relpath, "rb").read()
|
||||
is_binary = is_binary or "\0" in new_content
|
||||
except Exception:
|
||||
pass
|
||||
if is_binary and base_content and use_hg_shell:
|
||||
# Fetch again without converting newlines
|
||||
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
|
||||
|
||||
@@ -67,6 +67,7 @@ struct Sym
|
||||
int32 value;
|
||||
ushort type;
|
||||
char *name;
|
||||
char* labelname;
|
||||
char sym;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
@@ -136,6 +137,8 @@ void newio(void);
|
||||
void newfile(char*, int);
|
||||
Sym* slookup(char*);
|
||||
Sym* lookup(void);
|
||||
Sym* labellookup(Sym*);
|
||||
void settext(LSym*);
|
||||
void syminit(Sym*);
|
||||
int32 yylex(void);
|
||||
int getc(void);
|
||||
|
||||
@@ -73,15 +73,11 @@ prog:
|
||||
line
|
||||
|
||||
line:
|
||||
LLAB ':'
|
||||
{
|
||||
if($1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME ':'
|
||||
LNAME ':'
|
||||
{
|
||||
$1 = labellookup($1);
|
||||
if($1->type == LLAB && $1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->labelname);
|
||||
$1->type = LLAB;
|
||||
$1->value = pc;
|
||||
}
|
||||
@@ -218,18 +214,21 @@ inst:
|
||||
*/
|
||||
| LTYPEB name ',' imm
|
||||
{
|
||||
settext($2.sym);
|
||||
$4.type = D_CONST2;
|
||||
$4.offset2 = ArgsSizeUnknown;
|
||||
outcode($1, Always, &$2, 0, &$4);
|
||||
}
|
||||
| LTYPEB name ',' con ',' imm
|
||||
{
|
||||
settext($2.sym);
|
||||
$6.type = D_CONST2;
|
||||
$6.offset2 = ArgsSizeUnknown;
|
||||
outcode($1, Always, &$2, $4, &$6);
|
||||
}
|
||||
| LTYPEB name ',' con ',' imm '-' con
|
||||
{
|
||||
settext($2.sym);
|
||||
$6.type = D_CONST2;
|
||||
$6.offset2 = $8;
|
||||
outcode($1, Always, &$2, $4, &$6);
|
||||
@@ -373,15 +372,10 @@ rel:
|
||||
}
|
||||
| LNAME offset
|
||||
{
|
||||
$1 = labellookup($1);
|
||||
$$ = nullgen;
|
||||
if(pass == 2)
|
||||
yyerror("undefined label: %s", $1->name);
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LLAB offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
if(pass == 2 && $1->type != LLAB)
|
||||
yyerror("undefined label: %s", $1->labelname);
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $1->value + $2;
|
||||
}
|
||||
|
||||
2093
src/cmd/5a/y.tab.c
2093
src/cmd/5a/y.tab.c
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,24 @@
|
||||
/* A Bison parser, made by GNU Bison 2.7.12-4996. */
|
||||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
@@ -26,20 +29,10 @@
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
#ifndef YY_YY_Y_TAB_H_INCLUDED
|
||||
# define YY_YY_Y_TAB_H_INCLUDED
|
||||
/* Enabling traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
@@ -148,41 +141,24 @@ extern int yydebug;
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
/* Line 2053 of yacc.c */
|
||||
#line 39 "a.y"
|
||||
|
||||
{
|
||||
Sym *sym;
|
||||
int32 lval;
|
||||
double dval;
|
||||
char sval[8];
|
||||
Addr addr;
|
||||
|
||||
|
||||
/* Line 2053 of yacc.c */
|
||||
#line 166 "y.tab.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
}
|
||||
/* Line 1529 of yacc.c. */
|
||||
#line 157 "y.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
#ifdef YYPARSE_PARAM
|
||||
#if defined __STDC__ || defined __cplusplus
|
||||
int yyparse (void *YYPARSE_PARAM);
|
||||
#else
|
||||
int yyparse ();
|
||||
#endif
|
||||
#else /* ! YYPARSE_PARAM */
|
||||
#if defined __STDC__ || defined __cplusplus
|
||||
int yyparse (void);
|
||||
#else
|
||||
int yyparse ();
|
||||
#endif
|
||||
#endif /* ! YYPARSE_PARAM */
|
||||
|
||||
#endif /* !YY_YY_Y_TAB_H_INCLUDED */
|
||||
|
||||
@@ -86,7 +86,7 @@ datagostring(Strlit *sval, Addr *a)
|
||||
sym = stringsym(sval->s, sval->len);
|
||||
a->type = D_OREG;
|
||||
a->name = D_EXTERN;
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
a->offset = 0; // header
|
||||
a->reg = NREG;
|
||||
a->sym = linksym(sym);
|
||||
|
||||
@@ -1353,9 +1353,10 @@ naddr(Node *n, Addr *a, int canemitcode)
|
||||
case OITAB:
|
||||
// itable of interface value
|
||||
naddr(n->left, a, canemitcode);
|
||||
a->etype = TINT32;
|
||||
a->etype = simtype[tptr];
|
||||
if(a->type == D_CONST && a->offset == 0)
|
||||
break; // len(nil)
|
||||
a->width = widthptr;
|
||||
break;
|
||||
|
||||
case OSPTR:
|
||||
|
||||
@@ -63,8 +63,8 @@ enum
|
||||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
@@ -75,12 +75,18 @@ struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
@@ -93,6 +99,16 @@ struct Reg
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
@@ -144,8 +160,8 @@ 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);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpit(char *str, Flow *r0, int);
|
||||
|
||||
@@ -156,10 +172,10 @@ void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
@@ -187,16 +203,16 @@ enum
|
||||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Register in middle; never written.
|
||||
// Register in middle (Prog.reg); only ever read.
|
||||
RegRead = 1<<12,
|
||||
CanRegRead = 1<<13,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<14,
|
||||
RightRead = 1<<15,
|
||||
RightWrite = 1<<16,
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "opt.h"
|
||||
|
||||
#define NREGVAR 32
|
||||
#define REGBITS ((uint32)0xffffffff)
|
||||
#define REGBITS ((uint64)0xffffffffull)
|
||||
/*c2go enum {
|
||||
NREGVAR = 32,
|
||||
REGBITS = 0xffffffff,
|
||||
@@ -86,7 +86,7 @@ setaddrs(Bits bit)
|
||||
i = bnum(bit);
|
||||
node = var[i].node;
|
||||
n = var[i].name;
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
|
||||
// disable all pieces of that variable
|
||||
for(i=0; i<nvar; i++) {
|
||||
@@ -393,7 +393,7 @@ loop2:
|
||||
for(z=0; z<BITS; z++)
|
||||
bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
|
||||
~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
|
||||
if(bany(&bit) & !r->f.refset) {
|
||||
if(bany(&bit) && !r->f.refset) {
|
||||
// should never happen - all variables are preset
|
||||
if(debug['w'])
|
||||
print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
|
||||
@@ -425,7 +425,7 @@ loop2:
|
||||
if(debug['R'] > 1)
|
||||
print("\n");
|
||||
paint1(r, i);
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
if(change <= 0) {
|
||||
if(debug['R'])
|
||||
print("%L $%d: %Q\n",
|
||||
@@ -454,9 +454,13 @@ brk:
|
||||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(debug['R']) {
|
||||
if(rgp->regno >= NREG)
|
||||
@@ -477,9 +481,6 @@ brk:
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
@@ -488,6 +489,15 @@ brk:
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
@@ -570,7 +580,7 @@ walkvardef(Node *n, Reg *r, int active)
|
||||
break;
|
||||
for(v=n->opt; v!=nil; v=v->nextinnode) {
|
||||
bn = v - var;
|
||||
r1->act.b[bn/32] |= 1L << (bn%32);
|
||||
biset(&r1->act, bn);
|
||||
}
|
||||
if(r1->f.prog->as == ABL)
|
||||
break;
|
||||
@@ -606,7 +616,7 @@ addsplits(void)
|
||||
~(r->calahead.b[z] & addrs.b[z]);
|
||||
while(bany(&bit)) {
|
||||
i = bnum(bit);
|
||||
bit.b[i/32] &= ~(1L << (i%32));
|
||||
biclr(&bit, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -972,10 +982,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
||||
for(z=0; z<BITS; z++) {
|
||||
if(cal.b[z] == 0)
|
||||
continue;
|
||||
for(i=0; i<32; i++) {
|
||||
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
for(i=0; i<64; i++) {
|
||||
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
continue;
|
||||
v = var+z*32+i;
|
||||
v = var+z*64+i;
|
||||
if(v->node->opt == nil) // v represents fixed register, not Go variable
|
||||
continue;
|
||||
|
||||
@@ -991,10 +1001,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
||||
// This will set the bits at most twice, keeping the overall loop linear.
|
||||
v1 = v->node->opt;
|
||||
j = v1 - var;
|
||||
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
|
||||
if(v == v1 || !btest(&cal, j)) {
|
||||
for(; v1 != nil; v1 = v1->nextinnode) {
|
||||
j = v1 - var;
|
||||
cal.b[j/32] |= 1<<(j&31);
|
||||
biset(&cal, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,10 +1125,10 @@ paint1(Reg *r, int bn)
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L<<(bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
@@ -1189,14 +1199,14 @@ paint1(Reg *r, int bn)
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb, vreg;
|
||||
uint64 bb, vreg;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
vreg = regbits;
|
||||
if(!(r->act.b[z] & bb))
|
||||
return vreg;
|
||||
@@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
|
||||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
@@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
|
||||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
@@ -1240,15 +1253,15 @@ paint2(Reg *r, int bn)
|
||||
}
|
||||
|
||||
void
|
||||
paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
paint3(Reg *r, int bn, uint32 rb, int rn)
|
||||
{
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
@@ -1333,7 +1346,7 @@ addreg(Adr *a, int rn)
|
||||
* 10 R10
|
||||
* 12 R12
|
||||
*/
|
||||
int32
|
||||
uint32
|
||||
RtoB(int r)
|
||||
{
|
||||
if(r >= REGTMP-2 && r != 12) // excluded R9 and R10 for m and g, but not R12
|
||||
@@ -1342,8 +1355,10 @@ RtoB(int r)
|
||||
}
|
||||
|
||||
int
|
||||
BtoR(int32 b)
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
// TODO Allow R0 and R1, but be careful with a 0 return
|
||||
// TODO Allow R9. Only R10 is reserved now (just g, not m).
|
||||
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
|
||||
if(b == 0)
|
||||
return 0;
|
||||
@@ -1357,7 +1372,7 @@ BtoR(int32 b)
|
||||
* ... ...
|
||||
* 31 F15
|
||||
*/
|
||||
int32
|
||||
uint32
|
||||
FtoB(int f)
|
||||
{
|
||||
|
||||
@@ -1367,7 +1382,7 @@ FtoB(int f)
|
||||
}
|
||||
|
||||
int
|
||||
BtoF(int32 b)
|
||||
BtoF(uint32 b)
|
||||
{
|
||||
|
||||
b &= 0xfffc0000L;
|
||||
@@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" (only)");
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != nil) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +338,8 @@ enum
|
||||
D_STATIC = (D_NONE+4),
|
||||
D_AUTO = (D_NONE+5),
|
||||
D_PARAM = (D_NONE+6),
|
||||
|
||||
D_LAST = (D_NONE+26),
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -70,6 +70,7 @@ struct Sym
|
||||
vlong value;
|
||||
ushort type;
|
||||
char *name;
|
||||
char* labelname;
|
||||
char sym;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
@@ -148,6 +149,8 @@ void newio(void);
|
||||
void newfile(char*, int);
|
||||
Sym* slookup(char*);
|
||||
Sym* lookup(void);
|
||||
Sym* labellookup(Sym*);
|
||||
void settext(LSym*);
|
||||
void syminit(Sym*);
|
||||
int32 yylex(void);
|
||||
int getc(void);
|
||||
|
||||
@@ -71,15 +71,11 @@ prog:
|
||||
line
|
||||
|
||||
line:
|
||||
LLAB ':'
|
||||
{
|
||||
if($1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME ':'
|
||||
LNAME ':'
|
||||
{
|
||||
$1 = labellookup($1);
|
||||
if($1->type == LLAB && $1->value != pc)
|
||||
yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
|
||||
$1->type = LLAB;
|
||||
$1->value = pc;
|
||||
}
|
||||
@@ -197,11 +193,13 @@ spec1: /* DATA */
|
||||
spec2: /* TEXT */
|
||||
mem ',' imm2
|
||||
{
|
||||
settext($1.sym);
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| mem ',' con ',' imm2
|
||||
{
|
||||
settext($1.sym);
|
||||
$$.from = $1;
|
||||
$$.from.scale = $3;
|
||||
$$.to = $5;
|
||||
@@ -363,15 +361,10 @@ rel:
|
||||
}
|
||||
| LNAME offset
|
||||
{
|
||||
$1 = labellookup($1);
|
||||
$$ = nullgen;
|
||||
if(pass == 2)
|
||||
yyerror("undefined label: %s", $1->name);
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LLAB offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
if(pass == 2 && $1->type != LLAB)
|
||||
yyerror("undefined label: %s", $1->labelname);
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $1->value + $2;
|
||||
}
|
||||
|
||||
1152
src/cmd/6a/y.tab.c
1152
src/cmd/6a/y.tab.c
File diff suppressed because it is too large
Load Diff
@@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
|
||||
a->sym = linksym(sym);
|
||||
a->node = sym->def;
|
||||
a->offset = 0; // header
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -63,8 +63,8 @@ enum
|
||||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
@@ -75,12 +75,18 @@ struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
@@ -93,6 +99,16 @@ struct Reg
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
@@ -140,8 +156,8 @@ 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);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
@@ -153,10 +169,10 @@ void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
@@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
|
||||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint32 reguse; // required registers used by this instruction
|
||||
uint32 regset; // required registers set by this instruction
|
||||
uint32 reguse; // registers implicitly used by this instruction
|
||||
uint32 regset; // registers implicitly set by this instruction
|
||||
uint32 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
@@ -187,12 +203,12 @@ enum
|
||||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<12,
|
||||
RightRead = 1<<13,
|
||||
RightWrite = 1<<14,
|
||||
|
||||
140
src/cmd/6g/reg.c
140
src/cmd/6g/reg.c
@@ -34,7 +34,7 @@
|
||||
#include "opt.h"
|
||||
|
||||
#define NREGVAR 32 /* 16 general + 16 floating */
|
||||
#define REGBITS ((uint32)0xffffffff)
|
||||
#define REGBITS ((uint64)0xffffffffull)
|
||||
/*c2go enum {
|
||||
NREGVAR = 32,
|
||||
REGBITS = 0xffffffff,
|
||||
@@ -71,7 +71,7 @@ setaddrs(Bits bit)
|
||||
i = bnum(bit);
|
||||
node = var[i].node;
|
||||
n = var[i].name;
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
|
||||
// disable all pieces of that variable
|
||||
for(i=0; i<nvar; i++) {
|
||||
@@ -364,7 +364,7 @@ loop2:
|
||||
rgp->varno = i;
|
||||
change = 0;
|
||||
paint1(r, i);
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
if(change <= 0)
|
||||
continue;
|
||||
rgp->cost = change;
|
||||
@@ -389,9 +389,13 @@ brk:
|
||||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(rgp->regno != 0) {
|
||||
if(debug['R'] && debug['v']) {
|
||||
@@ -406,9 +410,6 @@ brk:
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
@@ -417,6 +418,15 @@ brk:
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
@@ -477,7 +487,7 @@ walkvardef(Node *n, Reg *r, int active)
|
||||
break;
|
||||
for(v=n->opt; v!=nil; v=v->nextinnode) {
|
||||
bn = v - var;
|
||||
r1->act.b[bn/32] |= 1L << (bn%32);
|
||||
biset(&r1->act, bn);
|
||||
}
|
||||
if(r1->f.prog->as == ACALL)
|
||||
break;
|
||||
@@ -621,6 +631,9 @@ mkvar(Reg *r, Adr *a)
|
||||
if(r != R)
|
||||
r->use1.b[0] |= doregbits(a->index);
|
||||
|
||||
if(t >= D_INDIR && t < 2*D_INDIR)
|
||||
goto none;
|
||||
|
||||
switch(t) {
|
||||
default:
|
||||
regu = doregbits(t);
|
||||
@@ -822,10 +835,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
||||
for(z=0; z<BITS; z++) {
|
||||
if(cal.b[z] == 0)
|
||||
continue;
|
||||
for(i=0; i<32; i++) {
|
||||
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
for(i=0; i<64; i++) {
|
||||
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
continue;
|
||||
v = var+z*32+i;
|
||||
v = var+z*64+i;
|
||||
if(v->node->opt == nil) // v represents fixed register, not Go variable
|
||||
continue;
|
||||
|
||||
@@ -841,10 +854,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
||||
// This will set the bits at most twice, keeping the overall loop linear.
|
||||
v1 = v->node->opt;
|
||||
j = v1 - var;
|
||||
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
|
||||
if(v == v1 || !btest(&cal, j)) {
|
||||
for(; v1 != nil; v1 = v1->nextinnode) {
|
||||
j = v1 - var;
|
||||
cal.b[j/32] |= 1UL<<(j&31);
|
||||
biset(&cal, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -959,10 +972,10 @@ paint1(Reg *r, int bn)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L<<(bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
@@ -1017,54 +1030,14 @@ paint1(Reg *r, int bn)
|
||||
}
|
||||
|
||||
uint32
|
||||
regset(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFFFF? BtoR(b): BtoF(b);
|
||||
if(v.type == 0)
|
||||
fatal("zero v.type for %#ux", b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 3)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
reguse(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFFFF? BtoR(b): BtoF(b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 1 || c == 2 || c == 4)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb, vreg, x;
|
||||
uint64 bb, vreg;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
vreg = regbits;
|
||||
if(!(r->act.b[z] & bb))
|
||||
return vreg;
|
||||
@@ -1081,6 +1054,9 @@ paint2(Reg *r, int bn)
|
||||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
@@ -1088,14 +1064,14 @@ paint2(Reg *r, int bn)
|
||||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
@@ -1105,27 +1081,19 @@ paint2(Reg *r, int bn)
|
||||
break;
|
||||
}
|
||||
|
||||
bb = vreg;
|
||||
for(; r; r=(Reg*)r->f.s1) {
|
||||
x = r->regu & ~bb;
|
||||
if(x) {
|
||||
vreg |= reguse(r, x);
|
||||
bb |= regset(r, x);
|
||||
}
|
||||
}
|
||||
return vreg;
|
||||
}
|
||||
|
||||
void
|
||||
paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
paint3(Reg *r, int bn, uint32 rb, int rn)
|
||||
{
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
@@ -1198,7 +1166,7 @@ addreg(Adr *a, int rn)
|
||||
ostats.ncvtreg++;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
RtoB(int r)
|
||||
{
|
||||
|
||||
@@ -1208,7 +1176,7 @@ RtoB(int r)
|
||||
}
|
||||
|
||||
int
|
||||
BtoR(int32 b)
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
b &= 0xffffL;
|
||||
if(nacl)
|
||||
@@ -1224,7 +1192,7 @@ BtoR(int32 b)
|
||||
* ...
|
||||
* 31 X15
|
||||
*/
|
||||
int32
|
||||
uint32
|
||||
FtoB(int f)
|
||||
{
|
||||
if(f < D_X0 || f > D_X15)
|
||||
@@ -1233,7 +1201,7 @@ FtoB(int f)
|
||||
}
|
||||
|
||||
int
|
||||
BtoF(int32 b)
|
||||
BtoF(uint32 b)
|
||||
{
|
||||
|
||||
b &= 0xFFFF0000L;
|
||||
@@ -1304,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != R) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,6 +865,8 @@ enum
|
||||
|
||||
D_INDIR, /* additive */
|
||||
|
||||
D_LAST,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
|
||||
@@ -70,6 +70,7 @@ struct Sym
|
||||
int32 value;
|
||||
ushort type;
|
||||
char *name;
|
||||
char* labelname;
|
||||
char sym;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
@@ -148,6 +149,8 @@ void newio(void);
|
||||
void newfile(char*, int);
|
||||
Sym* slookup(char*);
|
||||
Sym* lookup(void);
|
||||
Sym* labellookup(Sym*);
|
||||
void settext(LSym*);
|
||||
void syminit(Sym*);
|
||||
int32 yylex(void);
|
||||
int getc(void);
|
||||
|
||||
@@ -74,15 +74,11 @@ prog:
|
||||
line
|
||||
|
||||
line:
|
||||
LLAB ':'
|
||||
{
|
||||
if($1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME ':'
|
||||
LNAME ':'
|
||||
{
|
||||
$1 = labellookup($1);
|
||||
if($1->type == LLAB && $1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->labelname);
|
||||
$1->type = LLAB;
|
||||
$1->value = pc;
|
||||
}
|
||||
@@ -199,11 +195,13 @@ spec1: /* DATA */
|
||||
spec2: /* TEXT */
|
||||
mem ',' imm2
|
||||
{
|
||||
settext($1.sym);
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| mem ',' con ',' imm2
|
||||
{
|
||||
settext($1.sym);
|
||||
$$.from = $1;
|
||||
$$.from.scale = $3;
|
||||
$$.to = $5;
|
||||
@@ -362,15 +360,10 @@ rel:
|
||||
}
|
||||
| LNAME offset
|
||||
{
|
||||
$1 = labellookup($1);
|
||||
$$ = nullgen;
|
||||
if(pass == 2)
|
||||
yyerror("undefined label: %s", $1->name);
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LLAB offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
if(pass == 2 && $1->type != LLAB)
|
||||
yyerror("undefined label: %s", $1->labelname);
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $1->value + $2;
|
||||
}
|
||||
|
||||
1166
src/cmd/8a/y.tab.c
1166
src/cmd/8a/y.tab.c
File diff suppressed because it is too large
Load Diff
@@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
|
||||
a->sym = linksym(sym);
|
||||
a->node = sym->def;
|
||||
a->offset = 0; // header
|
||||
a->etype = TINT32;
|
||||
a->etype = TSTRING;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -63,8 +63,8 @@ enum
|
||||
|
||||
uint32 BLOAD(Reg*);
|
||||
uint32 BSTORE(Reg*);
|
||||
uint32 LOAD(Reg*);
|
||||
uint32 STORE(Reg*);
|
||||
uint64 LOAD(Reg*);
|
||||
uint64 STORE(Reg*);
|
||||
*/
|
||||
|
||||
// A Reg is a wrapper around a single Prog (one instruction) that holds
|
||||
@@ -75,12 +75,18 @@ struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
@@ -106,6 +112,16 @@ struct Reg
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
@@ -158,8 +174,8 @@ 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);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
@@ -171,10 +187,10 @@ void peep(Prog*);
|
||||
void excise(Flow*);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
uint32 RtoB(int);
|
||||
uint32 FtoB(int);
|
||||
int BtoR(uint32);
|
||||
int BtoF(uint32);
|
||||
|
||||
/*
|
||||
* prog.c
|
||||
@@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
|
||||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint32 reguse; // required registers used by this instruction
|
||||
uint32 regset; // required registers set by this instruction
|
||||
uint32 reguse; // registers implicitly used by this instruction
|
||||
uint32 regset; // registers implicitly set by this instruction
|
||||
uint32 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
@@ -205,12 +221,12 @@ enum
|
||||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<12,
|
||||
RightRead = 1<<13,
|
||||
RightWrite = 1<<14,
|
||||
|
||||
135
src/cmd/8g/reg.c
135
src/cmd/8g/reg.c
@@ -34,7 +34,7 @@
|
||||
#include "opt.h"
|
||||
|
||||
#define NREGVAR 16 /* 8 integer + 8 floating */
|
||||
#define REGBITS ((uint32)0xffff)
|
||||
#define REGBITS ((uint64)0xffffull)
|
||||
/*c2go enum {
|
||||
NREGVAR = 16,
|
||||
REGBITS = (1<<NREGVAR) - 1,
|
||||
@@ -71,7 +71,7 @@ setaddrs(Bits bit)
|
||||
i = bnum(bit);
|
||||
node = var[i].node;
|
||||
n = var[i].name;
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
|
||||
// disable all pieces of that variable
|
||||
for(i=0; i<nvar; i++) {
|
||||
@@ -336,7 +336,7 @@ loop2:
|
||||
rgp->varno = i;
|
||||
change = 0;
|
||||
paint1(r, i);
|
||||
bit.b[i/32] &= ~(1L<<(i%32));
|
||||
biclr(&bit, i);
|
||||
if(change <= 0)
|
||||
continue;
|
||||
rgp->cost = change;
|
||||
@@ -358,18 +358,19 @@ brk:
|
||||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(rgp->regno != 0)
|
||||
paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
@@ -378,6 +379,15 @@ brk:
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
@@ -446,7 +456,7 @@ walkvardef(Node *n, Reg *r, int active)
|
||||
break;
|
||||
for(v=n->opt; v!=nil; v=v->nextinnode) {
|
||||
bn = v - var;
|
||||
r1->act.b[bn/32] |= 1L << (bn%32);
|
||||
biset(&r1->act, bn);
|
||||
}
|
||||
if(r1->f.prog->as == ACALL)
|
||||
break;
|
||||
@@ -788,10 +798,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
||||
for(z=0; z<BITS; z++) {
|
||||
if(cal.b[z] == 0)
|
||||
continue;
|
||||
for(i=0; i<32; i++) {
|
||||
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
for(i=0; i<64; i++) {
|
||||
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
|
||||
continue;
|
||||
v = var+z*32+i;
|
||||
v = var+z*64+i;
|
||||
if(v->node->opt == nil) // v represents fixed register, not Go variable
|
||||
continue;
|
||||
|
||||
@@ -807,10 +817,10 @@ prop(Reg *r, Bits ref, Bits cal)
|
||||
// This will set the bits at most twice, keeping the overall loop linear.
|
||||
v1 = v->node->opt;
|
||||
j = v1 - var;
|
||||
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
|
||||
if(v == v1 || !btest(&cal, j)) {
|
||||
for(; v1 != nil; v1 = v1->nextinnode) {
|
||||
j = v1 - var;
|
||||
cal.b[j/32] |= 1<<(j&31);
|
||||
biset(&cal, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -926,10 +936,10 @@ paint1(Reg *r, int bn)
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L<<(bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL<<(bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
@@ -996,52 +1006,14 @@ paint1(Reg *r, int bn)
|
||||
}
|
||||
|
||||
uint32
|
||||
regset(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFF ? BtoR(b): BtoF(b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 3)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
reguse(Reg *r, uint32 bb)
|
||||
{
|
||||
uint32 b, set;
|
||||
Adr v;
|
||||
int c;
|
||||
|
||||
set = 0;
|
||||
v = zprog.from;
|
||||
while(b = bb & ~(bb-1)) {
|
||||
v.type = b & 0xFF ? BtoR(b): BtoF(b);
|
||||
c = copyu(r->f.prog, &v, nil);
|
||||
if(c == 1 || c == 2 || c == 4)
|
||||
set |= b;
|
||||
bb &= ~b;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
uint32 bb, vreg, x;
|
||||
uint64 bb, vreg;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
vreg = regbits;
|
||||
if(!(r->act.b[z] & bb))
|
||||
return vreg;
|
||||
@@ -1058,6 +1030,9 @@ paint2(Reg *r, int bn)
|
||||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
@@ -1065,14 +1040,14 @@ paint2(Reg *r, int bn)
|
||||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
@@ -1082,27 +1057,19 @@ paint2(Reg *r, int bn)
|
||||
break;
|
||||
}
|
||||
|
||||
bb = vreg;
|
||||
for(; r; r=(Reg*)r->f.s1) {
|
||||
x = r->regu & ~bb;
|
||||
if(x) {
|
||||
vreg |= reguse(r, x);
|
||||
bb |= regset(r, x);
|
||||
}
|
||||
}
|
||||
return vreg;
|
||||
}
|
||||
|
||||
void
|
||||
paint3(Reg *r, int bn, int32 rb, int rn)
|
||||
paint3(Reg *r, int bn, uint32 rb, int rn)
|
||||
{
|
||||
Reg *r1;
|
||||
Prog *p;
|
||||
int z;
|
||||
uint32 bb;
|
||||
uint64 bb;
|
||||
|
||||
z = bn/32;
|
||||
bb = 1L << (bn%32);
|
||||
z = bn/64;
|
||||
bb = 1LL << (bn%64);
|
||||
if(r->act.b[z] & bb)
|
||||
return;
|
||||
for(;;) {
|
||||
@@ -1175,7 +1142,7 @@ addreg(Adr *a, int rn)
|
||||
ostats.ncvtreg++;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
RtoB(int r)
|
||||
{
|
||||
|
||||
@@ -1185,7 +1152,7 @@ RtoB(int r)
|
||||
}
|
||||
|
||||
int
|
||||
BtoR(int32 b)
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
|
||||
b &= 0xffL;
|
||||
@@ -1194,7 +1161,7 @@ BtoR(int32 b)
|
||||
return bitno(b) + D_AX;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
FtoB(int f)
|
||||
{
|
||||
if(f < D_X0 || f > D_X7)
|
||||
@@ -1203,7 +1170,7 @@ FtoB(int f)
|
||||
}
|
||||
|
||||
int
|
||||
BtoF(int32 b)
|
||||
BtoF(uint32 b)
|
||||
{
|
||||
b &= 0xFF00L;
|
||||
if(b == 0)
|
||||
@@ -1273,12 +1240,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != nil) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,6 +654,8 @@ enum
|
||||
|
||||
D_CONST2 = D_INDIR+D_INDIR,
|
||||
|
||||
D_LAST,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
|
||||
10
src/cmd/9a/Makefile
Normal file
10
src/cmd/9a/Makefile
Normal 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
170
src/cmd/9a/a.h
Normal 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
991
src/cmd/9a/a.y
Normal 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
21
src/cmd/9a/doc.go
Normal 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
725
src/cmd/9a/lex.c
Normal 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
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
188
src/cmd/9a/y.tab.h
Normal 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
5
src/cmd/9c/Makefile
Normal 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
14
src/cmd/9c/Notes
Normal 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
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
17
src/cmd/9c/doc.go
Normal 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
350
src/cmd/9c/gc.h
Normal 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
37
src/cmd/9c/list.c
Normal 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
105
src/cmd/9c/machcap.c
Normal 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
638
src/cmd/9c/mul.c
Normal 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
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
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
291
src/cmd/9c/sgen.c
Normal 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
407
src/cmd/9c/swt.c
Normal 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, ®node, 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
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
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
16
src/cmd/9g/doc.go
Normal 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
54
src/cmd/9g/galign.c
Normal 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
117
src/cmd/9g/gg.h
Normal 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);
|
||||
1040
src/cmd/9g/ggen.c
Normal file
1040
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
240
src/cmd/9g/gobj.c
Normal 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 = TSTRING;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
1707
src/cmd/9g/gsubr.c
Normal file
1707
src/cmd/9g/gsubr.c
Normal file
File diff suppressed because it is too large
Load Diff
234
src/cmd/9g/opt.h
Normal file
234
src/cmd/9g/opt.h
Normal file
@@ -0,0 +1,234 @@
|
||||
// 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; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
uint64 regu; // register used bitmap
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
/*c2go extern Reg *R; */
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
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; // TODO(austin) not used; remove
|
||||
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 ndelmov;
|
||||
int32 nvar;
|
||||
} 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);
|
||||
uint64 allreg(uint64, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint64 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint64, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
void dumpit(char*, Flow*, int);
|
||||
|
||||
/*
|
||||
* 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; // registers implicitly used by this instruction
|
||||
uint64 regset; // registers implicitly 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 (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Register in middle (Prog.reg); only ever read.
|
||||
RegRead = 1<<12,
|
||||
CanRegRead = 1<<13,
|
||||
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<14,
|
||||
RightRead = 1<<15,
|
||||
RightWrite = 1<<16,
|
||||
|
||||
// Instruction updates whichever of from/to is type D_OREG
|
||||
PostInc = 1<<17,
|
||||
|
||||
// Instruction kinds
|
||||
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,
|
||||
};
|
||||
96
src/cmd/9g/peep.c
Normal file
96
src/cmd/9g/peep.c
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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, *l;
|
||||
|
||||
p = r->prog;
|
||||
if(debug['P'] && debug['v'])
|
||||
print("%P ===delete===\n", p);
|
||||
l = p->link;
|
||||
*p = zprog;
|
||||
p->as = ANOP;
|
||||
p->link = l;
|
||||
ostats.ndelmov++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
144
src/cmd/9g/prog.c
Normal file
144
src/cmd/9g/prog.c
Normal file
@@ -0,0 +1,144 @@
|
||||
// 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},
|
||||
|
||||
[ADUFFZERO]= {Call},
|
||||
[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.type == D_CONST) && p->from.reg != NREG) {
|
||||
info->regindex |= RtoB(p->from.reg);
|
||||
if(info->flags & PostInc) {
|
||||
info->regset |= RtoB(p->from.reg);
|
||||
}
|
||||
}
|
||||
if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) {
|
||||
info->regindex |= 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;
|
||||
}
|
||||
|
||||
if(p->as == ADUFFZERO) {
|
||||
info->reguse |= RtoB(0) | RtoB(2);
|
||||
info->regset |= RtoB(2);
|
||||
}
|
||||
if(p->as == ADUFFCOPY) {
|
||||
info->reguse |= RtoB(0) | RtoB(2) | RtoB(3);
|
||||
info->regset |= RtoB(2) | RtoB(3);
|
||||
}
|
||||
}
|
||||
1346
src/cmd/9g/reg.c
Normal file
1346
src/cmd/9g/reg.c
Normal file
File diff suppressed because it is too large
Load Diff
516
src/cmd/9l/9.out.h
Normal file
516
src/cmd/9l/9.out.h
Normal file
@@ -0,0 +1,516 @@
|
||||
// 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
|
||||
{
|
||||
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.
|
||||
|
||||
D_LAST,
|
||||
|
||||
/* reg names for 9g OREGISTER */
|
||||
D_R0 = 0, // type is D_REG
|
||||
D_F0 = D_R0+NREG, // type is D_FREG
|
||||
|
||||
/* reg names in offset field 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
5
src/cmd/9l/Makefile
Normal 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
338
src/cmd/9l/asm.c
Normal 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
16
src/cmd/9l/doc.go
Normal 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
100
src/cmd/9l/l.h
Normal 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
40
src/cmd/9l/list.c
Normal 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
108
src/cmd/9l/obj.c
Normal 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);
|
||||
}
|
||||
@@ -220,6 +220,31 @@ slookup(char *s)
|
||||
return lookup();
|
||||
}
|
||||
|
||||
LSym *thetext;
|
||||
|
||||
void
|
||||
settext(LSym *s)
|
||||
{
|
||||
thetext = s;
|
||||
}
|
||||
|
||||
Sym*
|
||||
labellookup(Sym *s)
|
||||
{
|
||||
char *p;
|
||||
Sym *lab;
|
||||
|
||||
if(thetext == nil) {
|
||||
s->labelname = s->name;
|
||||
return s;
|
||||
}
|
||||
p = smprint("%s.%s", thetext->name, s->name);
|
||||
lab = slookup(p);
|
||||
free(p);
|
||||
lab->labelname = s->name;
|
||||
return lab;
|
||||
}
|
||||
|
||||
Sym*
|
||||
lookup(void)
|
||||
{
|
||||
|
||||
@@ -65,14 +65,14 @@ argsize(int doret)
|
||||
}
|
||||
//print(" %d %T\n", s, t);
|
||||
}
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s = (s+7) & ~7;
|
||||
else
|
||||
s = (s+3) & ~3;
|
||||
if(doret && thisfn->link->etype != TVOID) {
|
||||
s = align(s, thisfn->link, Aarg1, nil);
|
||||
s = align(s, thisfn->link, Aarg2, nil);
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s = (s+7) & ~7;
|
||||
else
|
||||
s = (s+3) & ~3;
|
||||
|
||||
@@ -130,15 +130,23 @@ func usage() {
|
||||
}
|
||||
|
||||
var ptrSizeMap = map[string]int64{
|
||||
"386": 4,
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"386": 4,
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"ppc64": 8,
|
||||
"ppc64le": 8,
|
||||
"power64": 8,
|
||||
"power64le": 8,
|
||||
}
|
||||
|
||||
var intSizeMap = map[string]int64{
|
||||
"386": 4,
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"386": 4,
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"ppc64": 8,
|
||||
"ppc64le": 8,
|
||||
"power64": 8,
|
||||
"power64le": 8,
|
||||
}
|
||||
|
||||
var cPrefix string
|
||||
|
||||
49
src/cmd/dist/build.c
vendored
49
src/cmd/dist/build.c
vendored
@@ -39,7 +39,7 @@ static void dopack(char*, char*, char**, int);
|
||||
static char *findgoversion(void);
|
||||
|
||||
// The known architecture letters.
|
||||
static char *gochars = "5668";
|
||||
static char *gochars = "566899";
|
||||
|
||||
// The known architectures.
|
||||
static char *okgoarch[] = {
|
||||
@@ -48,6 +48,8 @@ static char *okgoarch[] = {
|
||||
"amd64",
|
||||
"amd64p32",
|
||||
"386",
|
||||
"power64",
|
||||
"power64le",
|
||||
};
|
||||
|
||||
// The known operating systems.
|
||||
@@ -344,6 +346,7 @@ static char *oldtool[] = {
|
||||
"5a", "5c", "5g", "5l",
|
||||
"6a", "6c", "6g", "6l",
|
||||
"8a", "8c", "8g", "8l",
|
||||
"9a", "9c", "9g", "9l",
|
||||
"6cov",
|
||||
"6nm",
|
||||
"6prof",
|
||||
@@ -521,6 +524,7 @@ static struct {
|
||||
"anames5.c",
|
||||
"anames6.c",
|
||||
"anames8.c",
|
||||
"anames9.c",
|
||||
}},
|
||||
{"cmd/cc", {
|
||||
"-pgen.c",
|
||||
@@ -549,6 +553,11 @@ static struct {
|
||||
"../cc/pswt.c",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
|
||||
}},
|
||||
{"cmd/9c", {
|
||||
"../cc/pgen.c",
|
||||
"../cc/pswt.c",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
|
||||
}},
|
||||
{"cmd/5g", {
|
||||
"../gc/cplx.c",
|
||||
"../gc/pgen.c",
|
||||
@@ -573,6 +582,14 @@ static struct {
|
||||
"../gc/popt.h",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
|
||||
}},
|
||||
{"cmd/9g", {
|
||||
"../gc/cplx.c",
|
||||
"../gc/pgen.c",
|
||||
"../gc/plive.c",
|
||||
"../gc/popt.c",
|
||||
"../gc/popt.h",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
|
||||
}},
|
||||
{"cmd/5l", {
|
||||
"../ld/*",
|
||||
}},
|
||||
@@ -582,6 +599,9 @@ static struct {
|
||||
{"cmd/8l", {
|
||||
"../ld/*",
|
||||
}},
|
||||
{"cmd/9l", {
|
||||
"../ld/*",
|
||||
}},
|
||||
{"cmd/go", {
|
||||
"zdefaultcc.go",
|
||||
}},
|
||||
@@ -618,6 +638,7 @@ static struct {
|
||||
{"anames5.c", mkanames},
|
||||
{"anames6.c", mkanames},
|
||||
{"anames8.c", mkanames},
|
||||
{"anames9.c", mkanames},
|
||||
{"zasm_", mkzasm},
|
||||
{"zdefaultcc.go", mkzdefaultcc},
|
||||
{"zsys_", mkzsys},
|
||||
@@ -1163,12 +1184,26 @@ shouldbuild(char *file, char *dir)
|
||||
|
||||
// Check file name for GOOS or GOARCH.
|
||||
name = lastelem(file);
|
||||
for(i=0; i<nelem(okgoos); i++)
|
||||
if(contains(name, okgoos[i]) && !streq(okgoos[i], goos))
|
||||
for(i=0; i<nelem(okgoos); i++) {
|
||||
if(streq(okgoos[i], goos))
|
||||
continue;
|
||||
p = xstrstr(name, okgoos[i]);
|
||||
if(p == nil)
|
||||
continue;
|
||||
p += xstrlen(okgoos[i]);
|
||||
if(*p == '.' || *p == '_' || *p == '\0')
|
||||
return 0;
|
||||
for(i=0; i<nelem(okgoarch); i++)
|
||||
if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch))
|
||||
}
|
||||
for(i=0; i<nelem(okgoarch); i++) {
|
||||
if(streq(okgoarch[i], goarch))
|
||||
continue;
|
||||
p = xstrstr(name, okgoarch[i]);
|
||||
if(p == nil)
|
||||
continue;
|
||||
p += xstrlen(okgoarch[i]);
|
||||
if(*p == '.' || *p == '_' || *p == '\0')
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Omit test files.
|
||||
if(contains(name, "_test"))
|
||||
@@ -1367,6 +1402,10 @@ static char *cleantab[] = {
|
||||
"cmd/8c",
|
||||
"cmd/8g",
|
||||
"cmd/8l",
|
||||
"cmd/9a",
|
||||
"cmd/9c",
|
||||
"cmd/9g",
|
||||
"cmd/9l",
|
||||
"cmd/cc",
|
||||
"cmd/gc",
|
||||
"cmd/go",
|
||||
|
||||
89
src/cmd/dist/buildgc.c
vendored
89
src/cmd/dist/buildgc.c
vendored
@@ -63,22 +63,36 @@ gcopnames(char *dir, char *file)
|
||||
vfree(&fields);
|
||||
}
|
||||
|
||||
// mkanames reads [568].out.h and writes anames[568].c
|
||||
static int
|
||||
xatoi(char *s, char **end)
|
||||
{
|
||||
int val = 0;
|
||||
for(; *s && *s >= '0' && *s <= '9'; ++s)
|
||||
val = val * 10 + (*s - '0');
|
||||
*end = s;
|
||||
return val;
|
||||
}
|
||||
|
||||
// mkanames reads [5689].out.h and writes anames[5689].c
|
||||
// The format is much the same as the Go opcodes above.
|
||||
// it also writes out cnames array for C_* constants.
|
||||
// It also writes out cnames array for C_* constants and the dnames
|
||||
// array for D_* constants.
|
||||
void
|
||||
mkanames(char *dir, char *file)
|
||||
{
|
||||
int i, j, ch;
|
||||
int i, j, ch, n, unknown;
|
||||
Buf in, b, out, out2;
|
||||
Vec lines;
|
||||
char *p;
|
||||
char *p, *p2;
|
||||
Vec dnames[128];
|
||||
|
||||
binit(&b);
|
||||
binit(&in);
|
||||
binit(&out);
|
||||
binit(&out2);
|
||||
vinit(&lines);
|
||||
for(i=0; i<nelem(dnames); i++)
|
||||
vinit(&dnames[i]);
|
||||
|
||||
ch = file[xstrlen(file)-3];
|
||||
bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
|
||||
@@ -87,10 +101,12 @@ mkanames(char *dir, char *file)
|
||||
|
||||
// Include link.h so that the extern declaration there is
|
||||
// checked against the non-extern declaration we are generating.
|
||||
bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
|
||||
bwritestr(&out, bprintf(&b, "\n"));
|
||||
|
||||
bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch));
|
||||
@@ -127,6 +143,69 @@ mkanames(char *dir, char *file)
|
||||
if(j>0)
|
||||
bwriteb(&out, &out2);
|
||||
|
||||
j=unknown=0;
|
||||
n=-1;
|
||||
for(i=0; i<lines.len; i++) {
|
||||
if(hasprefix(lines.p[i], "\tD_")) {
|
||||
p = xstrstr(lines.p[i], ",");
|
||||
if(p)
|
||||
*p = '\0';
|
||||
p = xstrstr(lines.p[i], "\n");
|
||||
if(p)
|
||||
*p = '\0';
|
||||
|
||||
// Parse explicit value, if any
|
||||
p = xstrstr(lines.p[i], "=");
|
||||
if(p) {
|
||||
// Skip space after '='
|
||||
p2 = p + 1;
|
||||
while(*p2 == ' ' || *p2 == '\t')
|
||||
p2++;
|
||||
n = xatoi(p2, &p2);
|
||||
// We can't do anything about
|
||||
// non-numeric values or anything that
|
||||
// follows
|
||||
while(*p2 == ' ' || *p2 == '\t')
|
||||
p2++;
|
||||
if(*p2 != 0) {
|
||||
unknown = 1;
|
||||
continue;
|
||||
}
|
||||
// Truncate space before '='
|
||||
while(*(p-1) == ' ' || *(p-1) == '\t')
|
||||
p--;
|
||||
*p = '\0';
|
||||
unknown = 0;
|
||||
} else {
|
||||
n++;
|
||||
}
|
||||
|
||||
if(unknown || n >= nelem(dnames))
|
||||
continue;
|
||||
|
||||
p = lines.p[i] + 3;
|
||||
if(xstrcmp(p, "LAST") == 0)
|
||||
continue;
|
||||
vadd(&dnames[n], p);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if(j>0){
|
||||
bwritestr(&out, bprintf(&b, "char* dnames%c[D_LAST] = {\n", ch));
|
||||
for(i=0; i<nelem(dnames); i++) {
|
||||
if(dnames[i].len == 0)
|
||||
continue;
|
||||
bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
|
||||
for(j=0; j<dnames[i].len; j++) {
|
||||
if(j != 0)
|
||||
bwritestr(&out, "/");
|
||||
bwritestr(&out, dnames[i].p[j]);
|
||||
}
|
||||
bwritestr(&out, "\",\n");
|
||||
}
|
||||
bwritestr(&out, "};\n");
|
||||
}
|
||||
|
||||
writefile(&out, file, 0);
|
||||
|
||||
bfree(&b);
|
||||
@@ -134,4 +213,6 @@ mkanames(char *dir, char *file)
|
||||
bfree(&out);
|
||||
bfree(&out2);
|
||||
vfree(&lines);
|
||||
for(i=0; i<nelem(dnames); i++)
|
||||
vfree(&dnames[i]);
|
||||
}
|
||||
|
||||
7
src/cmd/dist/buildruntime.c
vendored
7
src/cmd/dist/buildruntime.c
vendored
@@ -148,6 +148,13 @@ static struct {
|
||||
{"arm", "",
|
||||
"#define LR R14\n"
|
||||
},
|
||||
|
||||
{"power64", "",
|
||||
"#define g R30\n"
|
||||
},
|
||||
{"power64le", "",
|
||||
"#define g R30\n"
|
||||
},
|
||||
};
|
||||
|
||||
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
|
||||
|
||||
4
src/cmd/dist/unix.c
vendored
4
src/cmd/dist/unix.c
vendored
@@ -708,6 +708,10 @@ main(int argc, char **argv)
|
||||
gohostarch = "386";
|
||||
else if(contains(u.machine, "arm"))
|
||||
gohostarch = "arm";
|
||||
else if(contains(u.machine, "ppc64le"))
|
||||
gohostarch = "power64le";
|
||||
else if(contains(u.machine, "ppc64"))
|
||||
gohostarch = "power64";
|
||||
else
|
||||
fatal("unknown architecture: %s", u.machine);
|
||||
}
|
||||
|
||||
@@ -95,11 +95,11 @@ int
|
||||
bnum(Bits a)
|
||||
{
|
||||
int i;
|
||||
int32 b;
|
||||
uint64 b;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(b = a.b[i])
|
||||
return 32*i + bitno(b);
|
||||
return 64*i + bitno(b);
|
||||
fatal("bad in bnum");
|
||||
return 0;
|
||||
}
|
||||
@@ -110,27 +110,35 @@ blsh(uint n)
|
||||
Bits c;
|
||||
|
||||
c = zbits;
|
||||
c.b[n/32] = 1L << (n%32);
|
||||
c.b[n/64] = 1LL << (n%64);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
int
|
||||
bset(Bits a, uint n)
|
||||
btest(Bits *a, uint n)
|
||||
{
|
||||
if(a.b[n/32] & (1L << (n%32)))
|
||||
return 1;
|
||||
return 0;
|
||||
return (a->b[n/64] & (1LL << (n%64))) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
biset(Bits *a, uint n)
|
||||
{
|
||||
a->b[n/64] |= 1LL << (n%64);
|
||||
}
|
||||
|
||||
void
|
||||
biclr(Bits *a, uint n)
|
||||
{
|
||||
a->b[n/64] &= ~(1LL << (n%64));
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
bitno(int32 b)
|
||||
bitno(uint64 b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<32; i++)
|
||||
if(b & (1L<<i))
|
||||
for(i=0; i<64; i++)
|
||||
if(b & (1LL<<i))
|
||||
return i;
|
||||
fatal("bad in bitno");
|
||||
return 0;
|
||||
@@ -157,7 +165,7 @@ Qconv(Fmt *fp)
|
||||
if(var[i].offset != 0)
|
||||
fmtprint(fp, "%+lld", (vlong)var[i].offset);
|
||||
}
|
||||
bits.b[i/32] &= ~(1L << (i%32));
|
||||
biclr(&bits, i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -704,13 +704,13 @@ enum
|
||||
Ecomplit = 1<<11, // type in composite literal
|
||||
};
|
||||
|
||||
#define BITS 5
|
||||
#define NVAR (BITS*sizeof(uint32)*8)
|
||||
#define BITS 3
|
||||
#define NVAR (BITS*sizeof(uint64)*8)
|
||||
|
||||
typedef struct Bits Bits;
|
||||
struct Bits
|
||||
{
|
||||
uint32 b[BITS];
|
||||
uint64 b[BITS];
|
||||
};
|
||||
|
||||
EXTERN Bits zbits;
|
||||
@@ -1027,12 +1027,14 @@ int Qconv(Fmt *fp);
|
||||
Bits band(Bits a, Bits b);
|
||||
int bany(Bits *a);
|
||||
int beq(Bits a, Bits b);
|
||||
int bitno(int32 b);
|
||||
int bitno(uint64 b);
|
||||
Bits blsh(uint n);
|
||||
Bits bnot(Bits a);
|
||||
int bnum(Bits a);
|
||||
Bits bor(Bits a, Bits b);
|
||||
int bset(Bits a, uint n);
|
||||
int btest(Bits *a, uint n);
|
||||
void biset(Bits *a, uint n);
|
||||
void biclr(Bits *a, uint n);
|
||||
|
||||
/*
|
||||
* bv.c
|
||||
|
||||
@@ -471,7 +471,7 @@ allocauto(Prog* ptxt)
|
||||
stksize = rnd(stksize, n->type->align);
|
||||
if(haspointers(n->type))
|
||||
stkptrsize = stksize;
|
||||
if(thechar == '5')
|
||||
if(thechar == '5' || thechar == '9')
|
||||
stksize = rnd(stksize, widthptr);
|
||||
if(stksize >= (1ULL<<31)) {
|
||||
setlineno(curfn);
|
||||
@@ -528,7 +528,7 @@ cgen_checknil(Node *n)
|
||||
dump("checknil", n);
|
||||
fatal("bad checknil");
|
||||
}
|
||||
if((thechar == '5' && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
|
||||
if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
|
||||
regalloc(®, types[tptr], n);
|
||||
cgen(n, ®);
|
||||
gins(ACHECKNIL, ®, N);
|
||||
|
||||
@@ -3301,6 +3301,9 @@ walkrotate(Node **np)
|
||||
int w, sl, sr, s;
|
||||
Node *l, *r;
|
||||
Node *n;
|
||||
|
||||
if(thechar == '9')
|
||||
return;
|
||||
|
||||
n = *np;
|
||||
|
||||
@@ -3426,6 +3429,10 @@ walkdiv(Node **np, NodeList **init)
|
||||
Type *twide;
|
||||
Magic m;
|
||||
|
||||
// TODO(minux)
|
||||
if(thechar == '9')
|
||||
return;
|
||||
|
||||
n = *np;
|
||||
if(n->right->op != OLITERAL)
|
||||
return;
|
||||
|
||||
@@ -445,11 +445,11 @@ blk(LSym *start, int64 addr, int64 size)
|
||||
continue;
|
||||
if(sym->value >= eaddr)
|
||||
break;
|
||||
ctxt->cursym = sym;
|
||||
if(sym->value < addr) {
|
||||
diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
|
||||
errorexit();
|
||||
}
|
||||
ctxt->cursym = sym;
|
||||
for(; addr < sym->value; addr++)
|
||||
cput(0);
|
||||
p = sym->p;
|
||||
@@ -463,6 +463,8 @@ blk(LSym *start, int64 addr, int64 size)
|
||||
diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size);
|
||||
errorexit();
|
||||
}
|
||||
if(sym->value+sym->size >= eaddr)
|
||||
break;
|
||||
}
|
||||
|
||||
for(; addr < eaddr; addr++)
|
||||
|
||||
@@ -10,8 +10,8 @@ Ld is the portable code for a modified version of the Plan 9 linker. The origin
|
||||
|
||||
http://plan9.bell-labs.com/magic/man2html/1/8l
|
||||
|
||||
It reads object files (.5, .6, or .8 files) and writes a binary named for the
|
||||
architecture (5.out, 6.out, 8.out) by default (if $GOOS is windows, a .exe suffix
|
||||
It reads object files (.5, .6, .8, .9 files) and writes a binary named for the
|
||||
architecture (5.out, 6.out, 8.out, 9.out) by default (if $GOOS is windows, a .exe suffix
|
||||
will be appended).
|
||||
|
||||
Major changes include:
|
||||
@@ -22,7 +22,7 @@ Original options are listed on the manual page linked above.
|
||||
|
||||
Usage:
|
||||
go tool 6l [flags] mainObj
|
||||
Substitute 6l with 8l or 5l as appropriate.
|
||||
Substitute 6l with 5l, 8l or 9l as appropriate.
|
||||
|
||||
Options new in this version:
|
||||
|
||||
|
||||
@@ -2189,7 +2189,7 @@ dwarfaddshstrings(LSym *shstrtab)
|
||||
elfstrdbg[ElfStrDebugStr] = addstring(shstrtab, ".debug_str");
|
||||
elfstrdbg[ElfStrGDBScripts] = addstring(shstrtab, ".debug_gdb_scripts");
|
||||
if(linkmode == LinkExternal) {
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
elfstrdbg[ElfStrRelDebugInfo] = addstring(shstrtab, ".rela.debug_info");
|
||||
elfstrdbg[ElfStrRelDebugAranges] = addstring(shstrtab, ".rela.debug_aranges");
|
||||
elfstrdbg[ElfStrRelDebugLine] = addstring(shstrtab, ".rela.debug_line");
|
||||
@@ -2244,7 +2244,7 @@ dwarfaddelfrelocheader(int elfstr, ElfShdr *shdata, vlong off, vlong size)
|
||||
ElfShdr *sh;
|
||||
|
||||
sh = newElfShdr(elfstrdbg[elfstr]);
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
sh->type = SHT_RELA;
|
||||
} else {
|
||||
sh->type = SHT_REL;
|
||||
|
||||
@@ -45,6 +45,7 @@ elfinit(void)
|
||||
switch(thechar) {
|
||||
// 64-bit architectures
|
||||
case '6':
|
||||
case '9':
|
||||
elf64 = 1;
|
||||
hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
|
||||
hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */
|
||||
@@ -678,7 +679,7 @@ elfdynhash(void)
|
||||
elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0));
|
||||
}
|
||||
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
sy = linklookup(ctxt, ".rela.plt", 0);
|
||||
if(sy->size > 0) {
|
||||
elfwritedynent(s, DT_PLTREL, DT_RELA);
|
||||
@@ -804,7 +805,7 @@ elfshreloc(Section *sect)
|
||||
if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
|
||||
return nil;
|
||||
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
prefix = ".rela";
|
||||
typ = SHT_RELA;
|
||||
} else {
|
||||
@@ -931,7 +932,7 @@ doelf(void)
|
||||
debug['s'] = 0;
|
||||
debug['d'] = 1;
|
||||
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
addstring(shstrtab, ".rela.text");
|
||||
addstring(shstrtab, ".rela.rodata");
|
||||
addstring(shstrtab, ".rela.typelink");
|
||||
@@ -954,7 +955,7 @@ doelf(void)
|
||||
|
||||
if(flag_shared) {
|
||||
addstring(shstrtab, ".init_array");
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
addstring(shstrtab, ".rela.init_array");
|
||||
else
|
||||
addstring(shstrtab, ".rel.init_array");
|
||||
@@ -975,7 +976,7 @@ doelf(void)
|
||||
addstring(shstrtab, ".dynamic");
|
||||
addstring(shstrtab, ".dynsym");
|
||||
addstring(shstrtab, ".dynstr");
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
addstring(shstrtab, ".rela");
|
||||
addstring(shstrtab, ".rela.plt");
|
||||
} else {
|
||||
@@ -990,7 +991,7 @@ doelf(void)
|
||||
s = linklookup(ctxt, ".dynsym", 0);
|
||||
s->type = SELFROSECT;
|
||||
s->reachable = 1;
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s->size += ELF64SYMSIZE;
|
||||
else
|
||||
s->size += ELF32SYMSIZE;
|
||||
@@ -1004,7 +1005,7 @@ doelf(void)
|
||||
dynstr = s;
|
||||
|
||||
/* relocation table */
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s = linklookup(ctxt, ".rela", 0);
|
||||
else
|
||||
s = linklookup(ctxt, ".rel", 0);
|
||||
@@ -1031,7 +1032,7 @@ doelf(void)
|
||||
|
||||
elfsetupplt();
|
||||
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s = linklookup(ctxt, ".rela.plt", 0);
|
||||
else
|
||||
s = linklookup(ctxt, ".rel.plt", 0);
|
||||
@@ -1056,13 +1057,13 @@ doelf(void)
|
||||
*/
|
||||
elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0));
|
||||
elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0));
|
||||
if(thechar == '6')
|
||||
if(thechar == '6' || thechar == '9')
|
||||
elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
|
||||
else
|
||||
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
|
||||
elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0));
|
||||
elfwritedynentsymsize(s, DT_STRSZ, linklookup(ctxt, ".dynstr", 0));
|
||||
if(thechar == '6') {
|
||||
if(thechar == '6' || thechar == '9') {
|
||||
elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0));
|
||||
elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0));
|
||||
elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
|
||||
@@ -1148,6 +1149,9 @@ asmbelf(vlong symo)
|
||||
case '8':
|
||||
eh->machine = EM_386;
|
||||
break;
|
||||
case '9':
|
||||
eh->machine = EM_PPC64;
|
||||
break;
|
||||
}
|
||||
|
||||
startva = INITTEXT - HEADR;
|
||||
@@ -1488,7 +1492,10 @@ elfobj:
|
||||
eh->ident[EI_CLASS] = ELFCLASS64;
|
||||
else
|
||||
eh->ident[EI_CLASS] = ELFCLASS32;
|
||||
eh->ident[EI_DATA] = ELFDATA2LSB;
|
||||
if(ctxt->arch->endian == BigEndian)
|
||||
eh->ident[EI_DATA] = ELFDATA2MSB;
|
||||
else
|
||||
eh->ident[EI_DATA] = ELFDATA2LSB;
|
||||
eh->ident[EI_VERSION] = EV_CURRENT;
|
||||
|
||||
if(linkmode == LinkExternal)
|
||||
|
||||
@@ -436,6 +436,12 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case '9':
|
||||
if(obj->machine != ElfMachPower64 || hdr->ident[4] != ElfClass64) {
|
||||
diag("%s: elf object but not power64", pn);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// load section list into memory.
|
||||
|
||||
@@ -594,6 +594,7 @@ hostlink(void)
|
||||
argv[argc++] = "-m32";
|
||||
break;
|
||||
case '6':
|
||||
case '9':
|
||||
argv[argc++] = "-m64";
|
||||
break;
|
||||
case '5':
|
||||
@@ -1033,7 +1034,7 @@ static LSym *newstack;
|
||||
|
||||
enum
|
||||
{
|
||||
HasLinkRegister = (thechar == '5'),
|
||||
HasLinkRegister = (thechar == '5' || thechar == '9'),
|
||||
};
|
||||
|
||||
// TODO: Record enough information in new object files to
|
||||
@@ -1042,7 +1043,7 @@ enum
|
||||
static int
|
||||
callsize(void)
|
||||
{
|
||||
if(thechar == '5')
|
||||
if(HasLinkRegister)
|
||||
return 0;
|
||||
return RegSize;
|
||||
}
|
||||
@@ -1052,7 +1053,7 @@ dostkcheck(void)
|
||||
{
|
||||
Chain ch;
|
||||
LSym *s;
|
||||
|
||||
|
||||
morestack = linklookup(ctxt, "runtime.morestack", 0);
|
||||
newstack = linklookup(ctxt, "runtime.newstack", 0);
|
||||
|
||||
@@ -1076,19 +1077,19 @@ dostkcheck(void)
|
||||
continue;
|
||||
|
||||
if(s->nosplit) {
|
||||
ctxt->cursym = s;
|
||||
ch.sym = s;
|
||||
stkcheck(&ch, 0);
|
||||
}
|
||||
ctxt->cursym = s;
|
||||
ch.sym = s;
|
||||
stkcheck(&ch, 0);
|
||||
}
|
||||
}
|
||||
for(s = ctxt->textp; s != nil; s = s->next) {
|
||||
if(!s->nosplit) {
|
||||
ctxt->cursym = s;
|
||||
ch.sym = s;
|
||||
stkcheck(&ch, 0);
|
||||
ctxt->cursym = s;
|
||||
ch.sym = s;
|
||||
stkcheck(&ch, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
stkcheck(Chain *up, int depth)
|
||||
@@ -1106,7 +1107,7 @@ stkcheck(Chain *up, int depth)
|
||||
// function at top of safe zone once.
|
||||
if(limit == StackLimit-callsize()) {
|
||||
if(s->stkcheck)
|
||||
return 0;
|
||||
return 0;
|
||||
s->stkcheck = 1;
|
||||
}
|
||||
|
||||
@@ -1154,6 +1155,7 @@ stkcheck(Chain *up, int depth)
|
||||
switch(r->type) {
|
||||
case R_CALL:
|
||||
case R_CALLARM:
|
||||
case R_CALLPOWER:
|
||||
// Direct call.
|
||||
ch.limit = limit - pcsp.value - callsize();
|
||||
ch.sym = r->sym;
|
||||
@@ -1164,8 +1166,8 @@ stkcheck(Chain *up, int depth)
|
||||
// to StackLimit beyond the frame size.
|
||||
if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
|
||||
limit = StackLimit + s->locals;
|
||||
if(thechar == '5')
|
||||
limit += 4; // saved LR
|
||||
if(HasLinkRegister)
|
||||
limit += RegSize;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1184,7 +1186,7 @@ stkcheck(Chain *up, int depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1213,7 +1215,7 @@ stkprint(Chain *ch, int limit)
|
||||
else
|
||||
print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
|
||||
} else {
|
||||
stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
|
||||
stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
|
||||
if(!HasLinkRegister)
|
||||
print("\t%d\ton entry to %s\n", ch->limit, name);
|
||||
}
|
||||
@@ -1533,7 +1535,7 @@ callgraph(void)
|
||||
r = &s->r[i];
|
||||
if(r->sym == nil)
|
||||
continue;
|
||||
if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT)
|
||||
if((r->type == R_CALL || r->type == R_CALLARM || r->type == R_CALLPOWER) && r->sym->type == STEXT)
|
||||
Bprint(&bso, "%s calls %s\n", s->name, r->sym->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ machoinit(void)
|
||||
switch(thechar) {
|
||||
// 64-bit architectures
|
||||
case '6':
|
||||
case '9':
|
||||
macho64 = 1;
|
||||
break;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
|
||||
{
|
||||
switch(thechar) {
|
||||
case '6':
|
||||
case '9':
|
||||
LPUT(off);
|
||||
cput(info);
|
||||
cput(other);
|
||||
|
||||
@@ -49,6 +49,10 @@ func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno stri
|
||||
case "android", "nacl":
|
||||
t.Skipf("skipping on %s", runtime.GOOS)
|
||||
}
|
||||
switch runtime.GOARCH {
|
||||
case "power64", "power64le":
|
||||
t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
|
||||
}
|
||||
|
||||
cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
|
||||
out, err := cmd.CombinedOutput()
|
||||
@@ -199,6 +203,10 @@ func testDisasm(t *testing.T, flags ...string) {
|
||||
}
|
||||
|
||||
func TestDisasm(t *testing.T) {
|
||||
switch runtime.GOARCH {
|
||||
case "power64", "power64le":
|
||||
t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
|
||||
}
|
||||
testDisasm(t)
|
||||
}
|
||||
|
||||
@@ -207,5 +215,9 @@ func TestDisasmExtld(t *testing.T) {
|
||||
case "plan9", "windows":
|
||||
t.Skipf("skipping on %s", runtime.GOOS)
|
||||
}
|
||||
switch runtime.GOARCH {
|
||||
case "power64", "power64le":
|
||||
t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH)
|
||||
}
|
||||
testDisasm(t, "-ldflags=-linkmode=external")
|
||||
}
|
||||
|
||||
@@ -1414,6 +1414,184 @@ var rppcStrings = []intName{
|
||||
func (i R_PPC) String() string { return stringName(uint32(i), rppcStrings, false) }
|
||||
func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) }
|
||||
|
||||
// Relocation types for PowerPC 64.
|
||||
type R_PPC64 int
|
||||
|
||||
const (
|
||||
R_PPC64_NONE R_PPC64 = 0
|
||||
R_PPC64_ADDR32 R_PPC64 = 1
|
||||
R_PPC64_ADDR24 R_PPC64 = 2
|
||||
R_PPC64_ADDR16 R_PPC64 = 3
|
||||
R_PPC64_ADDR16_LO R_PPC64 = 4
|
||||
R_PPC64_ADDR16_HI R_PPC64 = 5
|
||||
R_PPC64_ADDR16_HA R_PPC64 = 6
|
||||
R_PPC64_ADDR14 R_PPC64 = 7
|
||||
R_PPC64_ADDR14_BRTAKEN R_PPC64 = 8
|
||||
R_PPC64_ADDR14_BRNTAKEN R_PPC64 = 9
|
||||
R_PPC64_REL24 R_PPC64 = 10
|
||||
R_PPC64_REL14 R_PPC64 = 11
|
||||
R_PPC64_REL14_BRTAKEN R_PPC64 = 12
|
||||
R_PPC64_REL14_BRNTAKEN R_PPC64 = 13
|
||||
R_PPC64_GOT16 R_PPC64 = 14
|
||||
R_PPC64_GOT16_LO R_PPC64 = 15
|
||||
R_PPC64_GOT16_HI R_PPC64 = 16
|
||||
R_PPC64_GOT16_HA R_PPC64 = 17
|
||||
R_PPC64_JMP_SLOT R_PPC64 = 21
|
||||
R_PPC64_REL32 R_PPC64 = 26
|
||||
R_PPC64_ADDR64 R_PPC64 = 38
|
||||
R_PPC64_ADDR16_HIGHER R_PPC64 = 39
|
||||
R_PPC64_ADDR16_HIGHERA R_PPC64 = 40
|
||||
R_PPC64_ADDR16_HIGHEST R_PPC64 = 41
|
||||
R_PPC64_ADDR16_HIGHESTA R_PPC64 = 42
|
||||
R_PPC64_REL64 R_PPC64 = 44
|
||||
R_PPC64_TOC16 R_PPC64 = 47
|
||||
R_PPC64_TOC16_LO R_PPC64 = 48
|
||||
R_PPC64_TOC16_HI R_PPC64 = 49
|
||||
R_PPC64_TOC16_HA R_PPC64 = 50
|
||||
R_PPC64_TOC R_PPC64 = 51
|
||||
R_PPC64_ADDR16_DS R_PPC64 = 56
|
||||
R_PPC64_ADDR16_LO_DS R_PPC64 = 57
|
||||
R_PPC64_GOT16_DS R_PPC64 = 58
|
||||
R_PPC64_GOT16_LO_DS R_PPC64 = 59
|
||||
R_PPC64_TOC16_DS R_PPC64 = 63
|
||||
R_PPC64_TOC16_LO_DS R_PPC64 = 64
|
||||
R_PPC64_TLS R_PPC64 = 67
|
||||
R_PPC64_DTPMOD64 R_PPC64 = 68
|
||||
R_PPC64_TPREL16 R_PPC64 = 69
|
||||
R_PPC64_TPREL16_LO R_PPC64 = 70
|
||||
R_PPC64_TPREL16_HI R_PPC64 = 71
|
||||
R_PPC64_TPREL16_HA R_PPC64 = 72
|
||||
R_PPC64_TPREL64 R_PPC64 = 73
|
||||
R_PPC64_DTPREL16 R_PPC64 = 74
|
||||
R_PPC64_DTPREL16_LO R_PPC64 = 75
|
||||
R_PPC64_DTPREL16_HI R_PPC64 = 76
|
||||
R_PPC64_DTPREL16_HA R_PPC64 = 77
|
||||
R_PPC64_DTPREL64 R_PPC64 = 78
|
||||
R_PPC64_GOT_TLSGD16 R_PPC64 = 79
|
||||
R_PPC64_GOT_TLSGD16_LO R_PPC64 = 80
|
||||
R_PPC64_GOT_TLSGD16_HI R_PPC64 = 81
|
||||
R_PPC64_GOT_TLSGD16_HA R_PPC64 = 82
|
||||
R_PPC64_GOT_TLSLD16 R_PPC64 = 83
|
||||
R_PPC64_GOT_TLSLD16_LO R_PPC64 = 84
|
||||
R_PPC64_GOT_TLSLD16_HI R_PPC64 = 85
|
||||
R_PPC64_GOT_TLSLD16_HA R_PPC64 = 86
|
||||
R_PPC64_GOT_TPREL16_DS R_PPC64 = 87
|
||||
R_PPC64_GOT_TPREL16_LO_DS R_PPC64 = 88
|
||||
R_PPC64_GOT_TPREL16_HI R_PPC64 = 89
|
||||
R_PPC64_GOT_TPREL16_HA R_PPC64 = 90
|
||||
R_PPC64_GOT_DTPREL16_DS R_PPC64 = 91
|
||||
R_PPC64_GOT_DTPREL16_LO_DS R_PPC64 = 92
|
||||
R_PPC64_GOT_DTPREL16_HI R_PPC64 = 93
|
||||
R_PPC64_GOT_DTPREL16_HA R_PPC64 = 94
|
||||
R_PPC64_TPREL16_DS R_PPC64 = 95
|
||||
R_PPC64_TPREL16_LO_DS R_PPC64 = 96
|
||||
R_PPC64_TPREL16_HIGHER R_PPC64 = 97
|
||||
R_PPC64_TPREL16_HIGHERA R_PPC64 = 98
|
||||
R_PPC64_TPREL16_HIGHEST R_PPC64 = 99
|
||||
R_PPC64_TPREL16_HIGHESTA R_PPC64 = 100
|
||||
R_PPC64_DTPREL16_DS R_PPC64 = 101
|
||||
R_PPC64_DTPREL16_LO_DS R_PPC64 = 102
|
||||
R_PPC64_DTPREL16_HIGHER R_PPC64 = 103
|
||||
R_PPC64_DTPREL16_HIGHERA R_PPC64 = 104
|
||||
R_PPC64_DTPREL16_HIGHEST R_PPC64 = 105
|
||||
R_PPC64_DTPREL16_HIGHESTA R_PPC64 = 106
|
||||
R_PPC64_TLSGD R_PPC64 = 107
|
||||
R_PPC64_TLSLD R_PPC64 = 108
|
||||
R_PPC64_REL16 R_PPC64 = 249
|
||||
R_PPC64_REL16_LO R_PPC64 = 250
|
||||
R_PPC64_REL16_HI R_PPC64 = 251
|
||||
R_PPC64_REL16_HA R_PPC64 = 252
|
||||
)
|
||||
|
||||
var rppc64Strings = []intName{
|
||||
{0, "R_PPC64_NONE"},
|
||||
{1, "R_PPC64_ADDR32"},
|
||||
{2, "R_PPC64_ADDR24"},
|
||||
{3, "R_PPC64_ADDR16"},
|
||||
{4, "R_PPC64_ADDR16_LO"},
|
||||
{5, "R_PPC64_ADDR16_HI"},
|
||||
{6, "R_PPC64_ADDR16_HA"},
|
||||
{7, "R_PPC64_ADDR14"},
|
||||
{8, "R_PPC64_ADDR14_BRTAKEN"},
|
||||
{9, "R_PPC64_ADDR14_BRNTAKEN"},
|
||||
{10, "R_PPC64_REL24"},
|
||||
{11, "R_PPC64_REL14"},
|
||||
{12, "R_PPC64_REL14_BRTAKEN"},
|
||||
{13, "R_PPC64_REL14_BRNTAKEN"},
|
||||
{14, "R_PPC64_GOT16"},
|
||||
{15, "R_PPC64_GOT16_LO"},
|
||||
{16, "R_PPC64_GOT16_HI"},
|
||||
{17, "R_PPC64_GOT16_HA"},
|
||||
{21, "R_PPC64_JMP_SLOT"},
|
||||
{26, "R_PPC64_REL32"},
|
||||
{38, "R_PPC64_ADDR64"},
|
||||
{39, "R_PPC64_ADDR16_HIGHER"},
|
||||
{40, "R_PPC64_ADDR16_HIGHERA"},
|
||||
{41, "R_PPC64_ADDR16_HIGHEST"},
|
||||
{42, "R_PPC64_ADDR16_HIGHESTA"},
|
||||
{44, "R_PPC64_REL64"},
|
||||
{47, "R_PPC64_TOC16"},
|
||||
{48, "R_PPC64_TOC16_LO"},
|
||||
{49, "R_PPC64_TOC16_HI"},
|
||||
{50, "R_PPC64_TOC16_HA"},
|
||||
{51, "R_PPC64_TOC"},
|
||||
{56, "R_PPC64_ADDR16_DS"},
|
||||
{57, "R_PPC64_ADDR16_LO_DS"},
|
||||
{58, "R_PPC64_GOT16_DS"},
|
||||
{59, "R_PPC64_GOT16_LO_DS"},
|
||||
{63, "R_PPC64_TOC16_DS"},
|
||||
{64, "R_PPC64_TOC16_LO_DS"},
|
||||
{67, "R_PPC64_TLS"},
|
||||
{68, "R_PPC64_DTPMOD64"},
|
||||
{69, "R_PPC64_TPREL16"},
|
||||
{70, "R_PPC64_TPREL16_LO"},
|
||||
{71, "R_PPC64_TPREL16_HI"},
|
||||
{72, "R_PPC64_TPREL16_HA"},
|
||||
{73, "R_PPC64_TPREL64"},
|
||||
{74, "R_PPC64_DTPREL16"},
|
||||
{75, "R_PPC64_DTPREL16_LO"},
|
||||
{76, "R_PPC64_DTPREL16_HI"},
|
||||
{77, "R_PPC64_DTPREL16_HA"},
|
||||
{78, "R_PPC64_DTPREL64"},
|
||||
{79, "R_PPC64_GOT_TLSGD16"},
|
||||
{80, "R_PPC64_GOT_TLSGD16_LO"},
|
||||
{81, "R_PPC64_GOT_TLSGD16_HI"},
|
||||
{82, "R_PPC64_GOT_TLSGD16_HA"},
|
||||
{83, "R_PPC64_GOT_TLSLD16"},
|
||||
{84, "R_PPC64_GOT_TLSLD16_LO"},
|
||||
{85, "R_PPC64_GOT_TLSLD16_HI"},
|
||||
{86, "R_PPC64_GOT_TLSLD16_HA"},
|
||||
{87, "R_PPC64_GOT_TPREL16_DS"},
|
||||
{88, "R_PPC64_GOT_TPREL16_LO_DS"},
|
||||
{89, "R_PPC64_GOT_TPREL16_HI"},
|
||||
{90, "R_PPC64_GOT_TPREL16_HA"},
|
||||
{91, "R_PPC64_GOT_DTPREL16_DS"},
|
||||
{92, "R_PPC64_GOT_DTPREL16_LO_DS"},
|
||||
{93, "R_PPC64_GOT_DTPREL16_HI"},
|
||||
{94, "R_PPC64_GOT_DTPREL16_HA"},
|
||||
{95, "R_PPC64_TPREL16_DS"},
|
||||
{96, "R_PPC64_TPREL16_LO_DS"},
|
||||
{97, "R_PPC64_TPREL16_HIGHER"},
|
||||
{98, "R_PPC64_TPREL16_HIGHERA"},
|
||||
{99, "R_PPC64_TPREL16_HIGHEST"},
|
||||
{100, "R_PPC64_TPREL16_HIGHESTA"},
|
||||
{101, "R_PPC64_DTPREL16_DS"},
|
||||
{102, "R_PPC64_DTPREL16_LO_DS"},
|
||||
{103, "R_PPC64_DTPREL16_HIGHER"},
|
||||
{104, "R_PPC64_DTPREL16_HIGHERA"},
|
||||
{105, "R_PPC64_DTPREL16_HIGHEST"},
|
||||
{106, "R_PPC64_DTPREL16_HIGHESTA"},
|
||||
{107, "R_PPC64_TLSGD"},
|
||||
{108, "R_PPC64_TLSLD"},
|
||||
{249, "R_PPC64_REL16"},
|
||||
{250, "R_PPC64_REL16_LO"},
|
||||
{251, "R_PPC64_REL16_HI"},
|
||||
{252, "R_PPC64_REL16_HA"},
|
||||
}
|
||||
|
||||
func (i R_PPC64) String() string { return stringName(uint32(i), rppc64Strings, false) }
|
||||
func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) }
|
||||
|
||||
// Relocation types for SPARC.
|
||||
type R_SPARC int
|
||||
|
||||
|
||||
@@ -532,6 +532,9 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
|
||||
if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 {
|
||||
return f.applyRelocationsARM64(dst, rels)
|
||||
}
|
||||
if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 {
|
||||
return f.applyRelocationsPPC64(dst, rels)
|
||||
}
|
||||
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
@@ -671,6 +674,51 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
|
||||
// 24 is the size of Rela64.
|
||||
if len(rels)%24 != 0 {
|
||||
return errors.New("length of relocation section is not a multiple of 24")
|
||||
}
|
||||
|
||||
symbols, _, err := f.getSymbols(SHT_SYMTAB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b := bytes.NewReader(rels)
|
||||
var rela Rela64
|
||||
|
||||
for b.Len() > 0 {
|
||||
binary.Read(b, f.ByteOrder, &rela)
|
||||
symNo := rela.Info >> 32
|
||||
t := R_PPC64(rela.Info & 0xffff)
|
||||
|
||||
if symNo == 0 || symNo > uint64(len(symbols)) {
|
||||
continue
|
||||
}
|
||||
sym := &symbols[symNo-1]
|
||||
if SymType(sym.Info&0xf) != STT_SECTION {
|
||||
// We don't handle non-section relocations for now.
|
||||
continue
|
||||
}
|
||||
|
||||
switch t {
|
||||
case R_PPC64_ADDR64:
|
||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
||||
continue
|
||||
}
|
||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
|
||||
case R_PPC64_ADDR32:
|
||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
||||
continue
|
||||
}
|
||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *File) DWARF() (*dwarf.Data, error) {
|
||||
// There are many other DWARF sections, but these
|
||||
// are the required ones, and the debug/dwarf package
|
||||
@@ -693,7 +741,7 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
||||
// If there's a relocation table for .debug_info, we have to process it
|
||||
// now otherwise the data in .debug_info is invalid for x86-64 objects.
|
||||
rela := f.Section(".rela.debug_info")
|
||||
if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64) {
|
||||
if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64 || f.Machine == EM_PPC64) {
|
||||
data, err := rela.Data()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -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)}}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"testdata/go-relocation-test-gcc482-ppc64le.obj",
|
||||
[]relocationTestEntry{
|
||||
{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"testdata/go-relocation-test-clang-x86.obj",
|
||||
[]relocationTestEntry{
|
||||
|
||||
BIN
src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
vendored
Normal file
BIN
src/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj
vendored
Normal file
Binary file not shown.
@@ -1384,6 +1384,8 @@ func ArchChar(goarch string) (string, error) {
|
||||
return "6", nil
|
||||
case "arm":
|
||||
return "5", nil
|
||||
case "power64", "power64le":
|
||||
return "9", nil
|
||||
}
|
||||
return "", errors.New("unsupported GOARCH " + goarch)
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
package build
|
||||
|
||||
const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
|
||||
const goarchList = "386 amd64 amd64p32 arm "
|
||||
const goarchList = "386 amd64 amd64p32 arm power64 power64le "
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build 386 arm
|
||||
// +build 386 arm power64 power64le
|
||||
|
||||
package crc32
|
||||
|
||||
|
||||
2784
src/liblink/asm9.c
Normal file
2784
src/liblink/asm9.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -82,6 +82,19 @@ Pconv(Fmt *fp)
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
|
||||
if(p->from.type != D_NONE)
|
||||
s += sprint(s, " from={%#D}", &p->from);
|
||||
if(p->reg)
|
||||
s += sprint(s, " reg=%d", p->reg);
|
||||
if(p->to.type != D_NONE)
|
||||
s += sprint(s, " to={%#D}", &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
switch(p->as) {
|
||||
case ADATA:
|
||||
sprint(str, "%.5lld (%L) %A %D/%d,%D",
|
||||
@@ -126,6 +139,31 @@ Dconv(Fmt *fp)
|
||||
a = va_arg(fp->args, Addr*);
|
||||
i = a->type;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
s += sprint(s, "type=");
|
||||
if(i == D_NONE) {
|
||||
sprint(s, "NONE");
|
||||
goto brk;
|
||||
}
|
||||
if(i >= D_INDIR) {
|
||||
i -= D_INDIR;
|
||||
s += sprint(s, "INDIR+");
|
||||
}
|
||||
if(i >= 0 && i < D_LAST && dnames6[i] != nil)
|
||||
s += sprint(s, "%s ", dnames6[i]);
|
||||
else
|
||||
s += sprint(s, "%d ", i);
|
||||
s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
|
||||
if(a->class != 0)
|
||||
s += sprint(s, " class=%s", cnames9[(int)a->class]);
|
||||
if(a->sym != nil)
|
||||
s += sprint(s, " sym=%s", a->sym->name);
|
||||
if(a->type == D_BRANCH && a->u.branch != nil)
|
||||
s += sprint(s, " branch=%.5lld", a->u.branch->pc);
|
||||
goto brk;
|
||||
}
|
||||
|
||||
if(fp->flags & FmtLong) {
|
||||
if(i == D_CONST)
|
||||
sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
|
||||
|
||||
451
src/liblink/list9.c
Normal file
451
src/liblink/list9.c
Normal file
@@ -0,0 +1,451 @@
|
||||
// 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(fp->flags & FmtSharp) {
|
||||
s = str;
|
||||
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
|
||||
if(p->from.type != D_NONE)
|
||||
s += sprint(s, " from={%#D}", &p->from);
|
||||
if(p->reg)
|
||||
s += sprint(s, " reg=%d", p->reg);
|
||||
if(p->from3.type != D_NONE)
|
||||
s += sprint(s, " from3={%#D}", &p->from3);
|
||||
if(p->to.type != D_NONE)
|
||||
s += sprint(s, " to={%#D}", &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
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 & FmtSharp) {
|
||||
char *s = str;
|
||||
if(a->type == D_NONE) {
|
||||
sprint(s, "type=NONE");
|
||||
goto ret;
|
||||
}
|
||||
if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
|
||||
s += sprint(s, "type=%s ", dnames9[a->type]);
|
||||
else
|
||||
s += sprint(s, "type=%d ", a->type);
|
||||
if(a->name >= 0 && a->name < D_LAST && dnames9[a->name] != nil)
|
||||
s += sprint(s, "name=%s ", dnames9[a->name]);
|
||||
else
|
||||
s += sprint(s, "name=%d ", a->name);
|
||||
s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
|
||||
if(a->class != 0)
|
||||
s += sprint(s, " class=%s", cnames9[a->class]);
|
||||
if(a->reg != NREG)
|
||||
s += sprint(s, " reg=%d", a->reg);
|
||||
if(a->sym != nil)
|
||||
s += sprint(s, " sym=%s", a->sym->name);
|
||||
if(a->type == D_BRANCH && a->u.branch != nil)
|
||||
s += sprint(s, " branch=%.5lld", a->u.branch->pc);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
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->u.branch != nil)
|
||||
sprint(str, "%lld", a->u.branch->pc);
|
||||
else if(a->sym != nil)
|
||||
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%lld(APC)", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
//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
1086
src/liblink/obj9.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -142,6 +142,8 @@ writeobj(Link *ctxt, Biobuf *b)
|
||||
edata = nil;
|
||||
for(pl = ctxt->plist; pl != nil; pl = pl->link) {
|
||||
for(p = pl->firstpc; p != nil; p = plink) {
|
||||
if(ctxt->debugasm && ctxt->debugvlog)
|
||||
print("obj: %p %P\n", p, p);
|
||||
plink = p->link;
|
||||
p->link = nil;
|
||||
|
||||
@@ -365,7 +367,10 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
|
||||
name = "";
|
||||
if(r->sym != nil)
|
||||
name = r->sym->name;
|
||||
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
|
||||
if(ctxt->arch->thechar == '5' || ctxt->arch->thechar == '9')
|
||||
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%llux\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
|
||||
else
|
||||
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,7 +782,7 @@ rdsym(Link *ctxt, Biobuf *f, char *pkg)
|
||||
s->type = SRODATA;
|
||||
adduint32(ctxt, s, i32);
|
||||
s->reachable = 0;
|
||||
} else if(strncmp(s->name, "$f64.", 5) == 0) {
|
||||
} else if(strncmp(s->name, "$f64.", 5) == 0 || strncmp(s->name, "$i64.", 5) == 0) {
|
||||
int64 i64;
|
||||
i64 = strtoull(s->name+5, nil, 16);
|
||||
s->type = SRODATA;
|
||||
|
||||
835
src/liblink/sched9.c
Normal file
835
src/liblink/sched9.c
Normal 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
14
src/math/abs_power64x.s
Normal 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
|
||||
46
src/math/big/arith_power64x.s
Normal file
46
src/math/big/arith_power64x.s
Normal 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)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user