typedef struct Pcdata Pcdata;
typedef struct Pciter Pciter;
-// prevent incompatible type signatures between liblink and 8l on Plan 9
-#pragma incomplete struct Node
-
+// An Addr is an argument to an instruction.
+// The general forms and their encodings are:
+//
+// sym±offset(symkind)(reg)(index*scale)
+// Memory reference at address &sym(symkind) + offset + reg + index*scale.
+// Any of sym(symkind), ±offset, (reg), (index*scale), and *scale can be omitted.
+// If (reg) and *scale are both omitted, the resulting expression (index) is parsed as (reg).
+// To force a parsing as index*scale, write (index*1).
+// Encoding:
+// type = TYPE_MEM
+// name = symkind (NAME_AUTO, ...) or 0 (NAME_NONE)
+// sym = sym
+// offset = ±offset
+// reg = reg (REG_*)
+// index = index (REG_*)
+// scale = scale (1, 2, 4, 8)
+//
+// $<mem>
+// Effective address of memory reference <mem>, defined above.
+// Encoding: same as memory reference, but type = TYPE_ADDR.
+//
+// $<±integer value>
+// This is a special case of $<mem>, in which only ±offset is present.
+// It has a separate type for easy recognition.
+// Encoding:
+// type = TYPE_CONST
+// offset = ±integer value
+//
+// *<mem>
+// Indirect reference through memory reference <mem>, defined above.
+// Only used on x86 for CALL/JMP *sym(SB), which calls/jumps to a function
+// pointer stored in the data word sym(SB), not a function named sym(SB).
+// Encoding: same as above, but type = TYPE_INDIR.
+//
+// $*$<mem>
+// No longer used.
+// On machines with actual SB registers, $*$<mem> forced the
+// instruction encoding to use a full 32-bit constant, never a
+// reference relative to SB.
+//
+// $<floating point literal>
+// Floating point constant value.
+// Encoding:
+// type = TYPE_FCONST
+// u.dval = floating point value
+//
+// $<string literal, up to 8 chars>
+// String literal value (raw bytes used for DATA instruction).
+// Encoding:
+// type = TYPE_SCONST
+// u.sval = string
+//
+// <register name>
+// Any register: integer, floating point, control, segment, and so on.
+// If looking for specific register kind, must check type and reg value range.
+// Encoding:
+// type = TYPE_REG
+// reg = reg (REG_*)
+//
+// x(PC)
+// Encoding:
+// type = TYPE_BRANCH
+// u.branch = Prog* reference OR ELSE offset = target pc (branch takes priority)
+//
+// $±x-±y
+// Final argument to TEXT, specifying local frame size x and argument size y.
+// In this form, x and y are integer literals only, not arbitrary expressions.
+// This avoids parsing ambiguities due to the use of - as a separator.
+// The ± are optional.
+// If the final argument to TEXT omits the -±y, the encoding should still
+// use TYPE_TEXTSIZE (not TYPE_CONST), with u.argsize = ArgsSizeUnknown.
+// Encoding:
+// type = TYPE_TEXTSIZE
+// offset = x
+// u.argsize = y
+//
+// reg<<shift, reg>>shift, reg->shift, reg@>shift
+// Shifted register value, for ARM.
+// In this form, reg must be a register and shift can be a register or an integer constant.
+// Encoding:
+// type = TYPE_SHIFT
+// offset = (reg&15) | shifttype<<5 | count
+// shifttype = 0, 1, 2, 3 for <<, >>, ->, @>
+// count = (reg&15)<<8 | 1<<4 for a register shift count, (n&31)<<7 for an integer constant.
+//
+// (reg, reg)
+// A destination register pair. When used as the last argument of an instruction,
+// this form makes clear that both registers are destinations.
+// Encoding:
+// type = TYPE_REGREG
+// reg = first register
+// offset = second register
+//
+// reg, reg
+// TYPE_REGREG2, to be removed.
+//
struct Addr
{
- vlong offset;
-
+ int16 type; // could be int8
+ int16 reg;
+ int16 index;
+ int8 scale;
+ int8 name;
+ int64 offset;
+ LSym* sym;
+
union
{
char sval[8];
float64 dval;
- Prog* branch; // for 5g, 6g, 8g, 9g
+ Prog* branch;
+ int32 argsize; // for 5l, 8l
+ uint64 bits; // raw union bits, for testing if anything has been written to any field
} u;
- LSym* sym;
+ // gotype is the name of the Go type descriptor for sym.
+ // It cannot be set using assembly syntax.
+ // It is generated by the Go compiler for global declarations,
+ // to convey information about pointer locations to the back end
+ // and for use in generating debug information.
LSym* gotype;
- short type;
- uint8 index;
- int8 scale;
- int8 reg; // for 5l, 9l; GPRs and FPRs both start at 0
- 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
- int64 width; // for 5g, 6g, 8g
+
+ int8 class; // for internal use by liblink
+ uint8 etype; // for internal use by 5g, 6g, 8g
+ void* node; // for internal use by 5g, 6g, 8g
+ int64 width; // for internal use by 5g, 6g, 8g
+};
+
+enum {
+ NAME_NONE = 0,
+ NAME_EXTERN,
+ NAME_STATIC,
+ NAME_AUTO,
+ NAME_PARAM,
+};
+
+enum {
+ TYPE_NONE = 0,
+ TYPE_BRANCH = 5, // avoid accidental conflicts with NAME_*
+ TYPE_TEXTSIZE,
+ TYPE_MEM,
+ TYPE_CONST,
+ TYPE_FCONST,
+ TYPE_SCONST,
+ TYPE_REG,
+ TYPE_ADDR,
+ TYPE_SHIFT,
+ TYPE_REGREG,
+ TYPE_REGREG2,
+ TYPE_INDIR,
};
struct Reloc
LSym* xsym;
};
+// TODO(rsc): Describe prog.
+// TODO(rsc): Describe TEXT/GLOBL flag in from3, DATA width in from3.
struct Prog
{
vlong pc;
// operands
Addr from;
- uchar reg; // arm, ppc64 only (e.g., ADD from, reg, to);
+ int16 reg; // arm, ppc64 only (e.g., ADD from, reg, to);
// starts at 0 for both GPRs and FPRs;
// also used for ADATA width on arm, ppc64
- Addr from3; // ppc64 only (e.g., RLWM/FMADD from, reg, from3, to)
+ Addr from3; // addl source argument (e.g., RLWM/FMADD from, reg, from3, to)
Addr to;
// for 5g, 6g, 8g internal use
void* opt;
- // for 5l, 6l, 8l internal use
+ // for liblink internal use
Prog* forwd;
Prog* pcond;
- Prog* comefrom; // 6l, 8l
- Prog* pcrel; // 5l
+ Prog* comefrom; // amd64, 386
+ Prog* pcrel; // arm
int32 spadj;
uint16 mark;
- uint16 optab; // 5l, 9l
- uchar back; // 6l, 8l
- uchar ft; /* 6l, 8l oclass cache */
- uchar tt; // 6l, 8l
- uchar isize; // 6l, 8l
+ uint16 optab; // arm, ppc64
+ uchar back; // amd64, 386
+ uchar ft; // oclass cache
+ uchar tt; // oclass cache
+ uchar isize; // amd64, 386
uchar printed;
char width; /* fake for DATA */
char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */
+};
+
+extern Prog zprog; // zeroed Prog
+
+// Prog.as opcodes.
+// These are the portable opcodes, common to all architectures.
+// Each architecture defines many more arch-specific opcodes,
+// with values starting at A_ARCHSPECIFIC.
+enum {
+ AXXX = 0,
+
+ ACALL,
+ ACHECKNIL,
+ ADATA,
+ ADUFFCOPY,
+ ADUFFZERO,
+ AEND,
+ AFUNCDATA,
+ AGLOBL,
+ AJMP,
+ ANOP,
+ APCDATA,
+ ARET,
+ ATEXT,
+ ATYPE,
+ AUNDEF,
+ AUSEFIELD,
+ AVARDEF,
+ AVARKILL,
- /*c2go uchar TEXTFLAG; */
+ A_ARCHSPECIFIC, // first architecture-specific opcode value
};
// prevent incompatible type signatures between liblink and 8l on Plan 9
RV_TYPE_MASK = (RV_CHECK_OVERFLOW - 1),
};
-// Auto.type
+// Auto.name
enum
{
A_AUTO = 1,
LSym* asym;
Auto* link;
int32 aoffset;
- int16 type;
+ int16 name;
LSym* gotype;
};
int thechar; // '5', '6', and so on
int32 endian; // LittleEndian or BigEndian
- void (*addstacksplit)(Link*, LSym*);
+ void (*preprocess)(Link*, LSym*);
void (*assemble)(Link*, LSym*);
- int (*datasize)(Prog*);
void (*follow)(Link*, LSym*);
- int (*iscall)(Prog*);
- int (*isdata)(Prog*);
- Prog* (*prg)(void);
void (*progedit)(Link*, Prog*);
- void (*settextflag)(Prog*, int);
- int (*symtype)(Addr*);
- int (*textflag)(Prog*);
int minlc;
int ptrsize;
int regsize;
-
- // TODO: Give these the same values on all systems.
- int D_ADDR;
- int D_AUTO;
- int D_BRANCH;
- int D_CONST;
- int D_EXTERN;
- int D_FCONST;
- int D_NONE;
- int D_PARAM;
- int D_SCONST;
- int D_STATIC;
- int D_OREG;
-
- int ACALL;
- int ADATA;
- int AEND;
- int AFUNCDATA;
- int AGLOBL;
- int AJMP;
- int ANOP;
- int APCDATA;
- int ARET;
- int ATEXT;
- int ATYPE;
- int AUSEFIELD;
};
/* executable header types */
void* erealloc(void *p, long n);
char* estrdup(char *p);
char* expandpkg(char *t0, char *pkg);
+void linksetexp(void);
+char* expstring(void);
+
+extern int fieldtrack_enabled;
+extern int framepointer_enabled;
// ld.c
void addhist(Link *ctxt, int32 line, int type);
extern LinkArch linkppc64;
extern LinkArch linkppc64le;
+extern int linkbasepointer;
+extern void linksetexp(void);
+
#pragma varargck type "A" int
#pragma varargck type "E" uint
#pragma varargck type "D" Addr*