Commit 4be75c8f authored by Shenghou Ma's avatar Shenghou Ma

[dev.power64] include/link.h, liblink: convert 9l functions to liblink

This replaces CL 122990043.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123010043
parent 7c33e507
...@@ -62,9 +62,9 @@ struct Addr ...@@ -62,9 +62,9 @@ struct Addr
short type; short type;
uint8 index; uint8 index;
int8 scale; int8 scale;
int8 reg; // for 5l int8 reg; // for 5l, 9l
int8 name; // for 5l int8 name; // for 5l, 9l
int8 class; // for 5l int8 class; // for 5l, 9l
uint8 etype; // for 5g, 6g, 8g uint8 etype; // for 5g, 6g, 8g
int32 offset2; // for 5l, 8l int32 offset2; // for 5l, 8l
struct Node* node; // for 5g, 6g, 8g struct Node* node; // for 5g, 6g, 8g
...@@ -89,9 +89,10 @@ struct Prog ...@@ -89,9 +89,10 @@ struct Prog
int32 lineno; int32 lineno;
Prog* link; Prog* link;
short as; short as;
uchar reg; // arm only uchar reg; // arm, power64 only
uchar scond; // arm only uchar scond; // arm only
Addr from; Addr from;
Addr from3; // power64 only, fma and rlwm
Addr to; Addr to;
// for 5g, 6g, 8g internal use // for 5g, 6g, 8g internal use
...@@ -103,11 +104,11 @@ struct Prog ...@@ -103,11 +104,11 @@ struct Prog
Prog* comefrom; // 6l, 8l Prog* comefrom; // 6l, 8l
Prog* pcrel; // 5l Prog* pcrel; // 5l
int32 spadj; int32 spadj;
uchar mark; uint16 mark;
uint16 optab; // 5l, 9l
uchar back; // 6l, 8l uchar back; // 6l, 8l
uchar ft; /* 6l, 8l oclass cache */ uchar ft; /* 6l, 8l oclass cache */
uchar tt; // 6l, 8l uchar tt; // 6l, 8l
uint16 optab; // 5l
uchar isize; // 6l, 8l uchar isize; // 6l, 8l
char width; /* fake for DATA */ char width; /* fake for DATA */
...@@ -232,10 +233,12 @@ enum ...@@ -232,10 +233,12 @@ enum
enum enum
{ {
R_ADDR = 1, R_ADDR = 1,
R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power
R_SIZE, R_SIZE,
R_CALL, // relocation for direct PC-relative call R_CALL, // relocation for direct PC-relative call
R_CALLARM, // relocation for ARM direct call R_CALLARM, // relocation for ARM direct call
R_CALLIND, // marker for indirect call (no actual relocating necessary) R_CALLIND, // marker for indirect call (no actual relocating necessary)
R_CALLPOWER, // relocation for Power direct call
R_CONST, R_CONST,
R_PCREL, R_PCREL,
R_TLS, R_TLS,
...@@ -526,6 +529,9 @@ void span6(Link *ctxt, LSym *s); ...@@ -526,6 +529,9 @@ void span6(Link *ctxt, LSym *s);
// asm8.c // asm8.c
void span8(Link *ctxt, LSym *s); void span8(Link *ctxt, LSym *s);
// asm9.c
void span9(Link *ctxt, LSym *s);
// data.c // data.c
vlong addaddr(Link *ctxt, LSym *s, LSym *t); vlong addaddr(Link *ctxt, LSym *s, LSym *t);
vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add); vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add);
...@@ -572,10 +578,11 @@ Prog* copyp(Link*, Prog*); ...@@ -572,10 +578,11 @@ Prog* copyp(Link*, Prog*);
Prog* appendp(Link*, Prog*); Prog* appendp(Link*, Prog*);
vlong atolwhex(char*); vlong atolwhex(char*);
// list[568].c // list[5689].c
void listinit5(void); void listinit5(void);
void listinit6(void); void listinit6(void);
void listinit8(void); void listinit8(void);
void listinit9(void);
// obj.c // obj.c
int linklinefmt(Link *ctxt, Fmt *fp); int linklinefmt(Link *ctxt, Fmt *fp);
...@@ -607,20 +614,24 @@ char* headstr(int); ...@@ -607,20 +614,24 @@ char* headstr(int);
extern char* anames5[]; extern char* anames5[];
extern char* anames6[]; extern char* anames6[];
extern char* anames8[]; extern char* anames8[];
extern char* anames9[];
extern char* cnames5[]; extern char* cnames5[];
extern char* cnames9[];
extern LinkArch link386; extern LinkArch link386;
extern LinkArch linkamd64; extern LinkArch linkamd64;
extern LinkArch linkamd64p32; extern LinkArch linkamd64p32;
extern LinkArch linkarm; extern LinkArch linkarm;
extern LinkArch linkpower64;
extern LinkArch linkpower64le;
#pragma varargck type "A" int #pragma varargck type "A" int
#pragma varargck type "D" Addr* #pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr* #pragma varargck type "lD" Addr*
#pragma varargck type "P" Prog* #pragma varargck type "P" Prog*
#pragma varargck type "R" int #pragma varargck type "R" int
#pragma varargck type "^" int #pragma varargck type "^" int // for 5l/9l, C_* classes (liblink internal)
// TODO(ality): remove this workaround. // TODO(ality): remove this workaround.
// It's here because Pconv in liblink/list?.c references %L. // It's here because Pconv in liblink/list?.c references %L.
......
This diff is collapsed.
...@@ -27,29 +27,61 @@ ...@@ -27,29 +27,61 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// +build ignore #include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "../cmd/9l/9.out.h"
#include "l.h" enum
{
STRINGSZ = 1000,
};
static int Aconv(Fmt*);
static int Dconv(Fmt*);
static int Pconv(Fmt*);
static int Rconv(Fmt*);
static int DSconv(Fmt*);
static int Mconv(Fmt*);
static int DRconv(Fmt*);
//
// Format conversions
// %A int Opcodes (instruction mnemonics)
//
// %D Addr* Addresses (instruction operands)
// Flags: "%lD": seperate the high and low words of a constant by "-"
//
// %P Prog* Instructions
//
// %R int Registers
//
// %$ char* String constant addresses (for internal use only)
// %^ int C_* classes (for liblink internal use)
#pragma varargck type "$" char*
#pragma varargck type "M" Addr*
void void
listinit(void) listinit9(void)
{ {
fmtinstall('A', Aconv); fmtinstall('A', Aconv);
fmtinstall('D', Dconv); fmtinstall('D', Dconv);
fmtinstall('P', Pconv); fmtinstall('P', Pconv);
fmtinstall('S', Sconv);
fmtinstall('N', Nconv);
fmtinstall('R', Rconv); fmtinstall('R', Rconv);
}
void // for liblink internal use
prasm(Prog *p) fmtinstall('^', DRconv);
{
print("%P\n", p); // for internal use
fmtinstall('$', DSconv);
fmtinstall('M', Mconv);
} }
int static Prog* bigP;
static int
Pconv(Fmt *fp) Pconv(Fmt *fp)
{ {
char str[STRINGSZ], *s; char str[STRINGSZ], *s;
...@@ -57,26 +89,36 @@ Pconv(Fmt *fp) ...@@ -57,26 +89,36 @@ Pconv(Fmt *fp)
int a; int a;
p = va_arg(fp->args, Prog*); p = va_arg(fp->args, Prog*);
curp = p; bigP = p;
a = p->as; a = p->as;
if(a == ADATA || a == AINIT || a == ADYNT) if(a == ADATA || a == AINIT || a == ADYNT)
sprint(str, "(%d) %A %D/%d,%D", p->line, a, &p->from, p->reg, &p->to); sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else { 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; s = str;
if(p->mark & NOSCHED) if(p->mark & NOSCHED)
s += sprint(s, "*"); s += sprint(s, "*");
if(p->reg == NREG && p->from3.type == D_NONE) if(p->reg == NREG && p->from3.type == D_NONE)
sprint(s, "(%d) %A %D,%D", p->line, a, &p->from, &p->to); sprint(s, "%.5lld (%d) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
else else
if(a != ATEXT && p->from.type == D_OREG) { if(a != ATEXT && p->from.type == D_OREG) {
sprint(s, "(%d) %A %lld(R%d+R%d),%D", p->line, a, sprint(s, "%.5lld (%d) %A %lld(R%d+R%d),%D", p->pc, p->lineno, a,
p->from.offset, p->from.reg, p->reg, &p->to); p->from.offset, p->from.reg, p->reg, &p->to);
} else } else
if(p->to.type == D_OREG) { if(p->to.type == D_OREG) {
sprint(s, "(%d) %A %D,%lld(R%d+R%d)", p->line, a, sprint(s, "%.5lld (%d) %A %D,%lld(R%d+R%d)", p->pc, p->lineno, a,
&p->from, p->to.offset, p->to.reg, p->reg); &p->from, p->to.offset, p->to.reg, p->reg);
} else { } else {
s += sprint(s, "(%d) %A %D", p->line, a, &p->from); s += sprint(s, "%.5lld (%L) %A %D", p->pc, p->lineno, a, &p->from);
if(p->reg != NREG) if(p->reg != NREG)
s += sprint(s, ",%c%d", p->from.type==D_FREG?'F':'R', p->reg); s += sprint(s, ",%c%d", p->from.type==D_FREG?'F':'R', p->reg);
if(p->from3.type != D_NONE) if(p->from3.type != D_NONE)
...@@ -87,7 +129,7 @@ Pconv(Fmt *fp) ...@@ -87,7 +129,7 @@ Pconv(Fmt *fp)
return fmtstrcpy(fp, str); return fmtstrcpy(fp, str);
} }
int static int
Aconv(Fmt *fp) Aconv(Fmt *fp)
{ {
char *s; char *s;
...@@ -96,55 +138,65 @@ Aconv(Fmt *fp) ...@@ -96,55 +138,65 @@ Aconv(Fmt *fp)
a = va_arg(fp->args, int); a = va_arg(fp->args, int);
s = "???"; s = "???";
if(a >= AXXX && a < ALAST) if(a >= AXXX && a < ALAST)
s = anames[a]; s = anames9[a];
return fmtstrcpy(fp, s); return fmtstrcpy(fp, s);
} }
int static int
Dconv(Fmt *fp) Dconv(Fmt *fp)
{ {
char str[STRINGSZ]; char str[STRINGSZ];
Adr *a; Addr *a;
long v; int32 v;
a = va_arg(fp->args, Adr*); a = va_arg(fp->args, Addr*);
switch(a->type) {
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: default:
sprint(str, "GOK-type(%d)", a->type); sprint(str, "GOK-type(%d)", a->type);
break; break;
case D_NONE: case D_NONE:
str[0] = 0; str[0] = 0;
if(a->name != D_NONE || a->reg != NREG || a->sym != S) if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
sprint(str, "%N(R%d)(NONE)", a, a->reg); sprint(str, "%M(R%d)(NONE)", a, a->reg);
break; break;
case D_CONST: case D_CONST:
case D_DCONST: case D_DCONST:
if(a->reg != NREG) if(a->reg != NREG)
sprint(str, "$%N(R%d)", a, a->reg); sprint(str, "$%M(R%d)", a, a->reg);
else else
sprint(str, "$%N", a); sprint(str, "$%M", a);
break; break;
case D_OREG: case D_OREG:
if(a->reg != NREG) if(a->reg != NREG)
sprint(str, "%N(R%d)", a, a->reg); sprint(str, "%M(R%d)", a, a->reg);
else else
sprint(str, "%N", a); sprint(str, "%M", a);
break; break;
case D_REG: case D_REG:
sprint(str, "R%d", a->reg); sprint(str, "R%d", a->reg);
if(a->name != D_NONE || a->sym != S) if(a->name != D_NONE || a->sym != nil)
sprint(str, "%N(R%d)(REG)", a, a->reg); sprint(str, "%M(R%d)(REG)", a, a->reg);
break; break;
case D_FREG: case D_FREG:
sprint(str, "F%d", a->reg); sprint(str, "F%d", a->reg);
if(a->name != D_NONE || a->sym != S) if(a->name != D_NONE || a->sym != nil)
sprint(str, "%N(F%d)(REG)", a, a->reg); sprint(str, "%M(F%d)(REG)", a, a->reg);
break; break;
case D_CREG: case D_CREG:
...@@ -152,12 +204,12 @@ Dconv(Fmt *fp) ...@@ -152,12 +204,12 @@ Dconv(Fmt *fp)
strcpy(str, "CR"); strcpy(str, "CR");
else else
sprint(str, "CR%d", a->reg); sprint(str, "CR%d", a->reg);
if(a->name != D_NONE || a->sym != S) if(a->name != D_NONE || a->sym != nil)
sprint(str, "%N(C%d)(REG)", a, a->reg); sprint(str, "%M(C%d)(REG)", a, a->reg);
break; break;
case D_SPR: case D_SPR:
if(a->name == D_NONE && a->sym == S) { if(a->name == D_NONE && a->sym == nil) {
switch((ulong)a->offset) { switch((ulong)a->offset) {
case D_XER: sprint(str, "XER"); break; case D_XER: sprint(str, "XER"); break;
case D_LR: sprint(str, "LR"); break; case D_LR: sprint(str, "LR"); break;
...@@ -167,18 +219,18 @@ Dconv(Fmt *fp) ...@@ -167,18 +219,18 @@ Dconv(Fmt *fp)
break; break;
} }
sprint(str, "SPR-GOK(%d)", a->reg); sprint(str, "SPR-GOK(%d)", a->reg);
if(a->name != D_NONE || a->sym != S) if(a->name != D_NONE || a->sym != nil)
sprint(str, "%N(SPR-GOK%d)(REG)", a, a->reg); sprint(str, "%M(SPR-GOK%d)(REG)", a, a->reg);
break; break;
case D_DCR: case D_DCR:
if(a->name == D_NONE && a->sym == S) { if(a->name == D_NONE && a->sym == nil) {
sprint(str, "DCR(%lld)", a->offset); sprint(str, "DCR(%lld)", a->offset);
break; break;
} }
sprint(str, "DCR-GOK(%d)", a->reg); sprint(str, "DCR-GOK(%d)", a->reg);
if(a->name != D_NONE || a->sym != S) if(a->name != D_NONE || a->sym != nil)
sprint(str, "%N(DCR-GOK%d)(REG)", a, a->reg); sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg);
break; break;
case D_OPT: case D_OPT:
...@@ -197,57 +249,71 @@ Dconv(Fmt *fp) ...@@ -197,57 +249,71 @@ Dconv(Fmt *fp)
break; break;
case D_BRANCH: case D_BRANCH:
if(curp->cond != P) { if(bigP->pcond != nil) {
v = curp->cond->pc; v = bigP->pcond->pc;
if(v >= INITTEXT) //if(v >= INITTEXT)
v -= INITTEXT-HEADR; // v -= INITTEXT-HEADR;
if(a->sym != S) if(a->sym != nil)
sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v); sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v);
else else
sprint(str, "%.5lux(BRANCH)", v); sprint(str, "%.5lux(BRANCH)", v);
} else } else
if(a->sym != S) if(a->sym != nil)
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset); sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
else else
sprint(str, "%lld(APC)", a->offset); sprint(str, "%lld(APC)", a->offset);
break; break;
case D_FCONST: case D_FCONST:
sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l); //sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
sprint(str, "$%.17g", a->u.dval);
break; break;
case D_SCONST: case D_SCONST:
sprint(str, "$\"%S\"", a->sval); sprint(str, "$\"%$\"", a->u.sval);
break; break;
} }
ret:
return fmtstrcpy(fp, str); return fmtstrcpy(fp, str);
} }
int static int
Nconv(Fmt *fp) Mconv(Fmt *fp)
{ {
char str[STRINGSZ]; char str[STRINGSZ];
Adr *a; Addr *a;
Sym *s; LSym *s;
long l; int32 l;
a = va_arg(fp->args, Adr*); a = va_arg(fp->args, Addr*);
s = a->sym; s = a->sym;
if(s == S) { //if(s == nil) {
// l = a->offset;
// if((vlong)l != a->offset)
// sprint(str, "0x%llux", a->offset);
// else
// sprint(str, "%lld", a->offset);
// goto out;
//}
switch(a->name) {
default:
sprint(str, "GOK-name(%d)", a->name);
break;
case D_NONE:
l = a->offset; l = a->offset;
if((vlong)l != a->offset) if((vlong)l != a->offset)
sprint(str, "0x%llux", a->offset); sprint(str, "0x%llux", a->offset);
else else
sprint(str, "%lld", a->offset); sprint(str, "%lld", a->offset);
goto out;
}
switch(a->name) {
default:
sprint(str, "GOK-name(%d)", a->name);
break; break;
case D_EXTERN: case D_EXTERN:
sprint(str, "%s+%lld(SB)", s->name, a->offset); if(a->offset != 0)
sprint(str, "%s+%lld(SB)", s->name, a->offset);
else
sprint(str, "%s(SB)", s->name, a->offset);
break; break;
case D_STATIC: case D_STATIC:
...@@ -255,19 +321,36 @@ Nconv(Fmt *fp) ...@@ -255,19 +321,36 @@ Nconv(Fmt *fp)
break; break;
case D_AUTO: case D_AUTO:
sprint(str, "%s-%lld(SP)", s->name, -a->offset); if(s == nil)
sprint(str, "%lld(SP)", -a->offset);
else
sprint(str, "%s-%lld(SP)", s->name, -a->offset);
break; break;
case D_PARAM: case D_PARAM:
sprint(str, "%s+%lld(FP)", s->name, a->offset); if(s == nil)
sprint(str, "%lld(FP)", a->offset);
else
sprint(str, "%s+%lld(FP)", s->name, a->offset);
break; break;
} }
out: //out:
return fmtstrcpy(fp, str); return fmtstrcpy(fp, str);
} }
int static int
Rconv(Fmt *fp) Rconv(Fmt *fp)
{
char str[STRINGSZ];
int r;
r = va_arg(fp->args, int);
sprint(str, "r%d", r);
return fmtstrcpy(fp, str);
}
static int
DRconv(Fmt *fp)
{ {
char *s; char *s;
int a; int a;
...@@ -275,19 +358,19 @@ Rconv(Fmt *fp) ...@@ -275,19 +358,19 @@ Rconv(Fmt *fp)
a = va_arg(fp->args, int); a = va_arg(fp->args, int);
s = "C_??"; s = "C_??";
if(a >= C_NONE && a <= C_NCLASS) if(a >= C_NONE && a <= C_NCLASS)
s = cnames[a]; s = cnames9[a];
return fmtstrcpy(fp, s); return fmtstrcpy(fp, s);
} }
int static int
Sconv(Fmt *fp) DSconv(Fmt *fp)
{ {
int i, c; int i, c;
char str[STRINGSZ], *p, *a; char str[STRINGSZ], *p, *a;
a = va_arg(fp->args, char*); a = va_arg(fp->args, char*);
p = str; p = str;
for(i=0; i<sizeof(long); i++) { for(i=0; i<sizeof(int32); i++) {
c = a[i] & 0xff; c = a[i] & 0xff;
if(c >= 'a' && c <= 'z' || if(c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z' || c >= 'A' && c <= 'Z' ||
...@@ -319,24 +402,3 @@ Sconv(Fmt *fp) ...@@ -319,24 +402,3 @@ Sconv(Fmt *fp)
*p = 0; *p = 0;
return fmtstrcpy(fp, str); return fmtstrcpy(fp, str);
} }
void
diag(char *fmt, ...)
{
char buf[STRINGSZ], *tn;
va_list arg;
tn = "??none??";
if(curtext != P && curtext->from.sym != S)
tn = curtext->from.sym->name;
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
print("%s: %s\n", tn, buf);
nerrors++;
if(nerrors > 10) {
print("too many errors\n");
errorexit();
}
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment