425 lines
7.9 KiB
C
425 lines
7.9 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
#include "../7c/7.out.h"
|
|
#include "../cc/compat.h"
|
|
|
|
#define LIBNAMELEN 300
|
|
|
|
void addlibpath(char*);
|
|
int fileexists(char*);
|
|
int find1(long, int);
|
|
char* findlib(char*);
|
|
|
|
typedef struct Adr Adr;
|
|
typedef struct Autom Auto;
|
|
typedef struct Count Count;
|
|
typedef struct Ieee Ieee;
|
|
typedef struct Prog Prog;
|
|
typedef struct Sym Sym;
|
|
typedef struct Mask Mask;
|
|
typedef struct Optab Optab;
|
|
typedef struct Oprang Oprang;
|
|
typedef uchar Opcross[32][2][32];
|
|
|
|
#define P ((Prog*)0)
|
|
#define S ((Sym*)0)
|
|
#define TNAME (curtext&&curtext->from.sym?curtext->from.sym->name:noname)
|
|
|
|
struct Adr
|
|
{
|
|
union
|
|
{
|
|
vlong u0offset;
|
|
char* u0sval;
|
|
Ieee* u0ieee;
|
|
} u0;
|
|
union
|
|
{
|
|
Auto* u1autom;
|
|
Sym* u1sym;
|
|
} u1;
|
|
char type;
|
|
char reg;
|
|
char name;
|
|
char class;
|
|
};
|
|
|
|
#define offset u0.u0offset
|
|
#define sval u0.u0sval
|
|
#define ieee u0.u0ieee
|
|
|
|
#define autom u1.u1autom
|
|
#define sym u1.u1sym
|
|
|
|
struct Prog
|
|
{
|
|
Adr from;
|
|
Adr from3; /* third register operand */
|
|
Adr to;
|
|
union
|
|
{
|
|
long u0regused;
|
|
Prog* u0forwd;
|
|
} u0;
|
|
Prog* cond;
|
|
Prog* link;
|
|
vlong pc;
|
|
long line;
|
|
uchar mark;
|
|
ushort optab;
|
|
ushort as;
|
|
uchar reg;
|
|
};
|
|
#define regused u0.u0regused
|
|
#define forwd u0.u0forwd
|
|
|
|
struct Sym
|
|
{
|
|
char *name;
|
|
short type;
|
|
short version;
|
|
short become;
|
|
short frame;
|
|
char dupok;
|
|
uchar subtype;
|
|
ushort file;
|
|
vlong value;
|
|
long sig;
|
|
Sym* link;
|
|
};
|
|
|
|
#define SIGNINTERN (1729*325*1729) /* signature of internal functions such as _div */
|
|
|
|
struct Autom
|
|
{
|
|
Sym* asym;
|
|
Auto* link;
|
|
long aoffset;
|
|
short type;
|
|
};
|
|
|
|
struct Optab
|
|
{
|
|
ushort as;
|
|
char a1;
|
|
char a2;
|
|
char a3;
|
|
char type;
|
|
char size;
|
|
char param;
|
|
char flag;
|
|
};
|
|
struct Oprang
|
|
{
|
|
Optab* start;
|
|
Optab* stop;
|
|
};
|
|
struct Mask
|
|
{
|
|
uchar s;
|
|
uchar e;
|
|
uchar r;
|
|
uvlong v;
|
|
};
|
|
|
|
enum
|
|
{
|
|
STEXT = 1,
|
|
SDATA,
|
|
SBSS,
|
|
SDATA1,
|
|
SXREF,
|
|
SLEAF,
|
|
SFILE,
|
|
SCONST,
|
|
SSTRING,
|
|
SUNDEF,
|
|
|
|
SIMPORT,
|
|
SEXPORT,
|
|
|
|
LFROM = 1<<0,
|
|
LTO = 1<<1,
|
|
LPOOL = 1<<2,
|
|
|
|
C_NONE = 0,
|
|
C_REG,
|
|
C_RSP, /* D_REG or D_SP */
|
|
C_SHIFT, /* D_SHIFT: shift type, amount, value */
|
|
C_EXTREG, /* D_EXTREG: reg, ext type, shift */
|
|
C_FREG,
|
|
C_SPR,
|
|
C_COND,
|
|
|
|
C_ZCON, /* 0 (matching C_REG, not C_RSP, allowing REGZERO) */
|
|
C_ADDCON0, /* 12-bit unsigned, unshifted */
|
|
C_ADDCON, /* 12-bit unsigned, shifted left by 0 or 12 */
|
|
C_MOVCON, /* generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16 */
|
|
C_BITCON, /* bimm32/bimm64 */
|
|
C_BITCON32, /* bimm32 */
|
|
C_BITCON64, /* bimm64 */
|
|
C_ABCON, /* could be C_ADDCON or C_BITCON */
|
|
C_MBCON, /* could be C_MOVCON or C_BITCON */
|
|
C_LCON, /* 32-bit constant */
|
|
C_FCON, /* floating-point constant */
|
|
C_VCON, /* 64-bit constant */
|
|
|
|
C_AACON, /* ADDCON offset in auto constant $a(FP) */
|
|
C_LACON, /* 32-bit offset in auto constant $a(FP) */
|
|
|
|
C_AECON, /* ADDCON offset in extern constant $e(SB) */
|
|
|
|
C_SBRA,
|
|
C_LBRA,
|
|
|
|
C_NPAUTO, /* -512 <= x < 0, 0 mod 8 */
|
|
C_NSAUTO, /* -256 <= x < 0 */
|
|
C_PSAUTO, /* 0 to 255 */
|
|
C_PPAUTO, /* 0 to 504, 0 mod 8 */
|
|
C_UAUTO4K, /* 0 to 4095 */
|
|
C_UAUTO8K, /* 0 to 8190, 0 mod 2 */
|
|
C_UAUTO16K, /* 0 to 16380, 0 mod 4 */
|
|
C_UAUTO32K, /* 0 to 32760, 0 mod 8 */
|
|
C_UAUTO64K, /* 0 to 65520, 0 mod 16 */
|
|
C_LAUTO, /* any other 32-bit constant */
|
|
|
|
C_SEXT1, /* 0 to 4095, direct */
|
|
C_SEXT2, /* 0 to 8190 */
|
|
C_SEXT4, /* 0 to 16380 */
|
|
C_SEXT8, /* 0 to 32760 */
|
|
C_SEXT16, /* 0 to 65520 */
|
|
C_LEXT,
|
|
|
|
C_NPOREG, /* mirror NPAUTO etc, except for ZOREG */
|
|
C_NSOREG,
|
|
C_ZOREG,
|
|
C_PSOREG,
|
|
C_PPOREG,
|
|
C_UOREG4K,
|
|
C_UOREG8K,
|
|
C_UOREG16K,
|
|
C_UOREG32K,
|
|
C_UOREG64K,
|
|
C_LOREG,
|
|
|
|
C_ADDR, /* relocatable address for dynamic loading */
|
|
C_ROFF, /* register offset (inc register extended) */
|
|
C_XPOST,
|
|
C_XPRE,
|
|
|
|
C_VREG,
|
|
|
|
C_GOK,
|
|
C_NCLASS, /* must be last */
|
|
|
|
/* mark flags */
|
|
FOLL = 1<<0,
|
|
LABEL = 1<<1,
|
|
LEAF = 1<<2,
|
|
FLOAT = 1<<3,
|
|
BRANCH = 1<<4,
|
|
LOAD = 1<<5,
|
|
SYNC = 1<<6,
|
|
NOSCHED = 1<<7,
|
|
|
|
MINSIZ = 64,
|
|
|
|
Roffset = 22, /* no. bits for offset in relocation address */
|
|
Rindex = 10, /* no. bits for index in relocation address */
|
|
|
|
STACKALIGN = 16, /* alignment of stack */
|
|
PCSZ= 8, /* size of PC */
|
|
};
|
|
|
|
enum
|
|
{
|
|
|
|
STRINGSZ = 200,
|
|
NHASH = 10007,
|
|
NHUNK = 100000,
|
|
MAXIO = 8192,
|
|
MAXHIST = 20, /* limit of path elements for history symbols */
|
|
};
|
|
|
|
EXTERN union
|
|
{
|
|
struct
|
|
{
|
|
uchar obuf[MAXIO]; /* output buffer */
|
|
uchar ibuf[MAXIO]; /* input buffer */
|
|
} u;
|
|
char dbuf[1];
|
|
} buf;
|
|
|
|
#define cbuf u.obuf
|
|
#define xbuf u.ibuf
|
|
|
|
EXTERN long HEADR; /* length of header */
|
|
EXTERN int HEADTYPE; /* type of header */
|
|
EXTERN long INITDAT; /* data location */
|
|
EXTERN long INITRND; /* data round above text location */
|
|
EXTERN long INITTEXT; /* text location */
|
|
EXTERN long INITTEXTP; /* text location (physical) */
|
|
EXTERN char* INITENTRY; /* entry point */
|
|
EXTERN long autosize;
|
|
EXTERN Biobuf bso;
|
|
EXTERN long bsssize;
|
|
EXTERN int cbc;
|
|
EXTERN uchar* cbp;
|
|
EXTERN int cout;
|
|
EXTERN Auto* curauto;
|
|
EXTERN Auto* curhist;
|
|
EXTERN Prog* curp;
|
|
EXTERN Prog* curtext;
|
|
EXTERN Prog* datap;
|
|
EXTERN long datsize;
|
|
EXTERN char debug[128];
|
|
EXTERN Prog* etextp;
|
|
EXTERN Prog* firstp;
|
|
|
|
EXTERN char fnuxi4[4];
|
|
EXTERN char fnuxi8[8];
|
|
EXTERN char inuxi1[1];
|
|
EXTERN char inuxi2[2];
|
|
EXTERN char inuxi4[4];
|
|
EXTERN uchar inuxi8[8];
|
|
|
|
EXTERN Sym* hash[NHASH];
|
|
EXTERN Sym* histfrog[MAXHIST];
|
|
EXTERN int histfrogp;
|
|
EXTERN int histgen;
|
|
|
|
EXTERN char* library[50];
|
|
EXTERN char* libraryobj[50];
|
|
EXTERN int libraryp;
|
|
EXTERN Prog* lastp;
|
|
EXTERN long lcsize;
|
|
EXTERN char literal[32];
|
|
EXTERN int nerrors;
|
|
EXTERN char* noname;
|
|
EXTERN vlong instoffset;
|
|
EXTERN Opcross opcross[8];
|
|
EXTERN char* outfile;
|
|
EXTERN vlong pc;
|
|
EXTERN uchar repop[ALAST];
|
|
EXTERN long symsize;
|
|
EXTERN Prog* textp;
|
|
EXTERN vlong textsize;
|
|
EXTERN int version;
|
|
EXTERN char xcmp[C_NCLASS][C_NCLASS];
|
|
EXTERN int xrefresolv;
|
|
EXTERN Prog zprg;
|
|
EXTERN int dtype;
|
|
|
|
EXTERN int doexp, dlm;
|
|
EXTERN int imports, nimports;
|
|
EXTERN int exports, nexports;
|
|
EXTERN char* EXPTAB;
|
|
EXTERN Prog undefp;
|
|
|
|
#define UP (&undefp)
|
|
|
|
extern char* anames[];
|
|
extern char* cnames[];
|
|
extern Optab optab[];
|
|
|
|
EXTERN Prog* blitrl;
|
|
EXTERN Prog* elitrl;
|
|
|
|
#pragma varargck argpos diag 1
|
|
|
|
#pragma varargck type "A" int
|
|
#pragma varargck type "A" uint
|
|
#pragma varargck type "C" int
|
|
#pragma varargck type "D" Adr*
|
|
#pragma varargck type "N" Adr*
|
|
#pragma varargck type "P" Prog*
|
|
#pragma varargck type "S" char*
|
|
|
|
|
|
int Aconv(Fmt*);
|
|
int Cconv(Fmt*);
|
|
int Dconv(Fmt*);
|
|
int Nconv(Fmt*);
|
|
int Pconv(Fmt*);
|
|
int Rconv(Fmt*);
|
|
int Sconv(Fmt*);
|
|
int aclass(Adr*);
|
|
void addpool(Prog*, Adr*);
|
|
vlong atolwhex(char*);
|
|
void asmb(void);
|
|
void asmdyn(void);
|
|
void asmlc(void);
|
|
void asmout(Prog*, Optab*);
|
|
void asmsym(void);
|
|
Prog* brchain(Prog*);
|
|
Prog* brloop(Prog*);
|
|
void buildop(void);
|
|
void buildrep(int, int);
|
|
void cflush(void);
|
|
void ckoff(Sym*, long);
|
|
int chipfloat(Ieee*);
|
|
int cmp(int, int);
|
|
int compound(Prog*);
|
|
void cput(int);
|
|
void datblk(long, long, int);
|
|
void diag(char*, ...);
|
|
void dodata(void);
|
|
void doprof1(void);
|
|
void doprof2(void);
|
|
void dynreloc(Sym*, long, int);
|
|
vlong entryvalue(void);
|
|
void errorexit(void);
|
|
void export(void);
|
|
void follow(void);
|
|
void histtoauto(void);
|
|
int isnop(Prog*);
|
|
double ieeedtod(Ieee*);
|
|
long ieeedtof(Ieee*);
|
|
void import(void);
|
|
void ldobj(int, long, char*);
|
|
void listinit(void);
|
|
void llput(vlong);
|
|
void llputl(vlong);
|
|
void loadlib(void);
|
|
Sym* lookup(char*, int);
|
|
void lput(long);
|
|
void lputl(long);
|
|
void mkfwd(void);
|
|
int movcon(vlong);
|
|
void names(void);
|
|
void nocache(Prog*);
|
|
void nuxiinit(void);
|
|
void objfile(char*);
|
|
vlong offsetshift(vlong, int);
|
|
Optab* oplook(Prog*);
|
|
void patch(void);
|
|
int pseudo(Prog*);
|
|
void prasm(Prog*);
|
|
Prog* prg(void);
|
|
void putsymb(char*, int, vlong, int);
|
|
void readundefs(char*, int);
|
|
long regoff(Adr*);
|
|
int relinv(int);
|
|
vlong rnd(vlong, long);
|
|
void span(void);
|
|
void undef(void);
|
|
void wput(long);
|
|
void wputl(long);
|
|
void noops(void);
|
|
Mask* findmask(uvlong);
|
|
void xdefine(char*, int, long);
|
|
void xfol(Prog*);
|
|
void zerosig(char*);
|
|
|
|
|
|
#pragma varargck type "R" int
|
|
|
|
/* for ../ld */
|
|
#define isbranch(a) ((a) == AB)
|
|
#define iscall(a) ((a) == ABL)
|
|
#define isreturn(a) ((a) == ARETURN || (a) == ARET || (a) == AERET)
|
|
#define branchop() AB
|
|
#define canfollow(a) ((a) != ATEXT && (a) != ABCASE)
|