This source file includes following definitions.
- nopout
- symtype
- isdata
- iscall
- datasize
- textflag
- settextflag
- canuselocaltls
- progedit
- nacladdr
- parsetextconst
- addstacksplit
- indir_cx
- load_g_cx
- stacksplit
- follow
- nofollow
- pushpop
- relinv
- xfol
- prg
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "../cmd/6l/6.out.h"
#include "../pkg/runtime/stack.h"
static Prog zprg = {
.back = 2,
.as = AGOK,
.from = {
.type = D_NONE,
.index = D_NONE,
},
.to = {
.type = D_NONE,
.index = D_NONE,
},
};
static void
nopout(Prog *p)
{
p->as = ANOP;
p->from.type = D_NONE;
p->to.type = D_NONE;
}
static int
symtype(Addr *a)
{
int t;
t = a->type;
if(t == D_ADDR)
t = a->index;
return t;
}
static int
isdata(Prog *p)
{
return p->as == ADATA || p->as == AGLOBL;
}
static int
iscall(Prog *p)
{
return p->as == ACALL;
}
static int
datasize(Prog *p)
{
return p->from.scale;
}
static int
textflag(Prog *p)
{
return p->from.scale;
}
static void
settextflag(Prog *p, int f)
{
p->from.scale = f;
}
static void nacladdr(Link*, Prog*, Addr*);
static int
canuselocaltls(Link *ctxt)
{
switch(ctxt->headtype) {
case Hwindows:
return 0;
}
return 1;
}
static void
progedit(Link *ctxt, Prog *p)
{
char literal[64];
LSym *s;
Prog *q;
if(canuselocaltls(ctxt)) {
if((p->as == AMOVQ || p->as == AMOVL) && p->from.type == D_TLS && D_AX <= p->to.type && p->to.type <= D_R15 && ctxt->headtype != Hsolaris)
nopout(p);
if(p->from.index == D_TLS && D_INDIR+D_AX <= p->from.type && p->from.type <= D_INDIR+D_R15) {
p->from.type = D_INDIR+D_TLS;
p->from.scale = 0;
p->from.index = D_NONE;
}
if(p->to.index == D_TLS && D_INDIR+D_AX <= p->to.type && p->to.type <= D_INDIR+D_R15) {
p->to.type = D_INDIR+D_TLS;
p->to.scale = 0;
p->to.index = D_NONE;
}
} else {
if((p->as == AMOVQ || p->as == AMOVL) && p->from.type == D_INDIR+D_TLS && D_AX <= p->to.type && p->to.type <= D_R15) {
q = appendp(ctxt, p);
q->as = p->as;
q->from = p->from;
q->from.type = D_INDIR + p->to.type;
q->from.index = D_TLS;
q->from.scale = 2;
q->to = p->to;
p->from.type = D_TLS;
p->from.index = D_NONE;
p->from.offset = 0;
}
}
if(ctxt->headtype == Hwindows || ctxt->headtype == Hplan9) {
if(p->from.scale == 1 && p->from.index == D_TLS)
p->from.scale = 2;
if(p->to.scale == 1 && p->to.index == D_TLS)
p->to.scale = 2;
}
if(ctxt->headtype == Hnacl) {
nacladdr(ctxt, p, &p->from);
nacladdr(ctxt, p, &p->to);
}
if(ctxt->mode == 0)
ctxt->mode = 64;
p->mode = ctxt->mode;
switch(p->as) {
case AMODE:
if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE) {
switch((int)p->from.offset) {
case 16:
case 32:
case 64:
ctxt->mode = p->from.offset;
break;
}
}
nopout(p);
break;
}
switch(p->as) {
case ACALL:
case AJMP:
case ARET:
if((p->to.type == D_EXTERN || p->to.type == D_STATIC) && p->to.sym != nil)
p->to.type = D_BRANCH;
break;
}
switch(p->as) {
case AFMOVF:
case AFADDF:
case AFSUBF:
case AFSUBRF:
case AFMULF:
case AFDIVF:
case AFDIVRF:
case AFCOMF:
case AFCOMFP:
case AMOVSS:
case AADDSS:
case ASUBSS:
case AMULSS:
case ADIVSS:
case ACOMISS:
case AUCOMISS:
if(p->from.type == D_FCONST) {
int32 i32;
float32 f32;
f32 = p->from.u.dval;
memmove(&i32, &f32, 4);
sprint(literal, "$f32.%08ux", (uint32)i32);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint32(ctxt, s, i32);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
break;
case AFMOVD:
case AFADDD:
case AFSUBD:
case AFSUBRD:
case AFMULD:
case AFDIVD:
case AFDIVRD:
case AFCOMD:
case AFCOMDP:
case AMOVSD:
case AADDSD:
case ASUBSD:
case AMULSD:
case ADIVSD:
case ACOMISD:
case AUCOMISD:
if(p->from.type == D_FCONST) {
int64 i64;
memmove(&i64, &p->from.u.dval, 8);
sprint(literal, "$f64.%016llux", (uvlong)i64);
s = linklookup(ctxt, literal, 0);
if(s->type == 0) {
s->type = SRODATA;
adduint64(ctxt, s, i64);
s->reachable = 0;
}
p->from.type = D_EXTERN;
p->from.sym = s;
p->from.offset = 0;
}
break;
}
}
static void
nacladdr(Link *ctxt, Prog *p, Addr *a)
{
if(p->as == ALEAL || p->as == ALEAQ)
return;
if(a->type == D_BP || a->type == D_INDIR+D_BP) {
ctxt->diag("invalid address: %P", p);
return;
}
if(a->type == D_INDIR+D_TLS)
a->type = D_INDIR+D_BP;
else if(a->type == D_TLS)
a->type = D_BP;
if(D_INDIR <= a->type && a->type <= D_INDIR+D_INDIR) {
switch(a->type) {
case D_INDIR+D_BP:
case D_INDIR+D_SP:
case D_INDIR+D_R15:
break;
default:
if(a->index != D_NONE)
ctxt->diag("invalid address %P", p);
a->index = a->type - D_INDIR;
if(a->index != D_NONE)
a->scale = 1;
a->type = D_INDIR+D_R15;
break;
}
}
}
static char*
morename[] =
{
"runtime.morestack00",
"runtime.morestack00_noctxt",
"runtime.morestack10",
"runtime.morestack10_noctxt",
"runtime.morestack01",
"runtime.morestack01_noctxt",
"runtime.morestack11",
"runtime.morestack11_noctxt",
"runtime.morestack8",
"runtime.morestack8_noctxt",
"runtime.morestack16",
"runtime.morestack16_noctxt",
"runtime.morestack24",
"runtime.morestack24_noctxt",
"runtime.morestack32",
"runtime.morestack32_noctxt",
"runtime.morestack40",
"runtime.morestack40_noctxt",
"runtime.morestack48",
"runtime.morestack48_noctxt",
};
static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int32, int, Prog**);
static void indir_cx(Link*, Addr*);
static void
parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
{
*textstksiz = arg & 0xffffffffLL;
if(*textstksiz & 0x80000000LL)
*textstksiz = -(-*textstksiz & 0xffffffffLL);
*textarg = (arg >> 32) & 0xffffffffLL;
if(*textarg & 0x80000000LL)
*textarg = 0;
*textarg = (*textarg+7) & ~7LL;
}
static void
addstacksplit(Link *ctxt, LSym *cursym)
{
Prog *p, *q, *q1;
int32 autoffset, deltasp;
int a, pcsize;
uint32 i;
vlong textstksiz, textarg;
if(ctxt->gmsym == nil)
ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
if(ctxt->symmorestack[0] == nil) {
if(nelem(morename) > nelem(ctxt->symmorestack))
sysfatal("Link.symmorestack needs at least %d elements", nelem(morename));
for(i=0; i<nelem(morename); i++)
ctxt->symmorestack[i] = linklookup(ctxt, morename[i], 0);
}
ctxt->cursym = cursym;
if(cursym->text == nil || cursym->text->link == nil)
return;
p = cursym->text;
parsetextconst(p->to.offset, &textstksiz, &textarg);
autoffset = textstksiz;
if(autoffset < 0)
autoffset = 0;
cursym->args = p->to.offset>>32;
cursym->locals = textstksiz;
if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) {
for(q = p; q != nil; q = q->link) {
if(q->as == ACALL)
goto noleaf;
if((q->as == ADUFFCOPY || q->as == ADUFFZERO) && autoffset >= StackSmall - 8)
goto noleaf;
}
p->from.scale |= NOSPLIT;
noleaf:;
}
q = nil;
if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) {
p = appendp(ctxt, p);
p = load_g_cx(ctxt, p);
}
if(!(cursym->text->from.scale & NOSPLIT))
p = stacksplit(ctxt, p, autoffset, textarg, !(cursym->text->from.scale&NEEDCTXT), &q);
if(autoffset) {
if(autoffset%ctxt->arch->regsize != 0)
ctxt->diag("unaligned stack size %d", autoffset);
p = appendp(ctxt, p);
p->as = AADJSP;
p->from.type = D_CONST;
p->from.offset = autoffset;
p->spadj = autoffset;
} else {
p = appendp(ctxt, p);
p->as = ANOP;
p->spadj = -ctxt->arch->ptrsize;
p = appendp(ctxt, p);
p->as = ANOP;
p->spadj = ctxt->arch->ptrsize;
}
if(q != nil)
q->pcond = p;
deltasp = autoffset;
if(cursym->text->from.scale & WRAPPER) {
p = appendp(ctxt, p);
p->as = AADDL;
p->from.type = D_CONST;
p->from.offset = autoffset + ctxt->arch->regsize;
indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize;
}
if(ctxt->debugstack > 1 && autoffset) {
p = appendp(ctxt, p);
p->as = AMOVQ;
indir_cx(ctxt, &p->from);
p->from.offset = 0;
p->to.type = D_BX;
p = appendp(ctxt, p);
p->as = ASUBQ;
p->from.type = D_CONST;
p->from.offset = StackSmall+32;
p->to.type = D_BX;
p = appendp(ctxt, p);
p->as = ACMPQ;
p->from.type = D_SP;
p->to.type = D_BX;
p = appendp(ctxt, p);
p->as = AJHI;
p->to.type = D_BRANCH;
q1 = p;
p = appendp(ctxt, p);
p->as = AINT;
p->from.type = D_CONST;
p->from.offset = 3;
p = appendp(ctxt, p);
p->as = ANOP;
q1->pcond = p;
}
if(ctxt->debugzerostack && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
p = appendp(ctxt, p);
p->as = AMOVQ;
p->from.type = D_SP;
p->to.type = D_DI;
p = appendp(ctxt, p);
p->as = AMOVQ;
p->from.type = D_CONST;
p->from.offset = autoffset/8;
p->to.type = D_CX;
p = appendp(ctxt, p);
p->as = AMOVQ;
p->from.type = D_CONST;
p->from.offset = 0;
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = AREP;
p = appendp(ctxt, p);
p->as = ASTOSQ;
}
for(; p != nil; p = p->link) {
pcsize = p->mode/8;
a = p->from.type;
if(a == D_AUTO)
p->from.offset += deltasp;
if(a == D_PARAM)
p->from.offset += deltasp + pcsize;
a = p->to.type;
if(a == D_AUTO)
p->to.offset += deltasp;
if(a == D_PARAM)
p->to.offset += deltasp + pcsize;
switch(p->as) {
default:
continue;
case APUSHL:
case APUSHFL:
deltasp += 4;
p->spadj = 4;
continue;
case APUSHQ:
case APUSHFQ:
deltasp += 8;
p->spadj = 8;
continue;
case APUSHW:
case APUSHFW:
deltasp += 2;
p->spadj = 2;
continue;
case APOPL:
case APOPFL:
deltasp -= 4;
p->spadj = -4;
continue;
case APOPQ:
case APOPFQ:
deltasp -= 8;
p->spadj = -8;
continue;
case APOPW:
case APOPFW:
deltasp -= 2;
p->spadj = -2;
continue;
case ARET:
break;
}
if(autoffset != deltasp)
ctxt->diag("unbalanced PUSH/POP");
if(cursym->text->from.scale & WRAPPER) {
p = load_g_cx(ctxt, p);
p = appendp(ctxt, p);
p->as = ASUBL;
p->from.type = D_CONST;
p->from.offset = autoffset + ctxt->arch->regsize;
indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize;
p = appendp(ctxt, p);
p->as = ARET;
}
if(autoffset) {
p->as = AADJSP;
p->from.type = D_CONST;
p->from.offset = -autoffset;
p->spadj = -autoffset;
p = appendp(ctxt, p);
p->as = ARET;
p->spadj = +autoffset;
}
if(p->to.sym)
p->as = AJMP;
}
}
static void
indir_cx(Link *ctxt, Addr *a)
{
if(ctxt->headtype == Hnacl) {
a->type = D_INDIR + D_R15;
a->index = D_CX;
a->scale = 1;
return;
}
a->type = D_INDIR+D_CX;
}
static Prog*
load_g_cx(Link *ctxt, Prog *p)
{
Prog *next;
p->as = AMOVQ;
if(ctxt->arch->ptrsize == 4)
p->as = AMOVL;
p->from.type = D_INDIR+D_TLS;
p->from.offset = 0;
p->to.type = D_CX;
next = p->link;
progedit(ctxt, p);
while(p->link != next)
p = p->link;
if(p->from.index == D_TLS)
p->from.scale = 2;
return p;
}
static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
uint32 moreconst1, moreconst2, i;
int cmp, lea, mov, sub;
cmp = ACMPQ;
lea = ALEAQ;
mov = AMOVQ;
sub = ASUBQ;
if(ctxt->headtype == Hnacl) {
cmp = ACMPL;
lea = ALEAL;
mov = AMOVL;
sub = ASUBL;
}
if(ctxt->debugstack) {
p = appendp(ctxt, p);
p->as = cmp;
indir_cx(ctxt, &p->from);
p->from.offset = 8;
p->to.type = D_SP;
p = appendp(ctxt, p);
p->as = AJHI;
p->to.type = D_BRANCH;
p->to.offset = 4;
q1 = p;
p = appendp(ctxt, p);
p->as = AINT;
p->from.type = D_CONST;
p->from.offset = 3;
p = appendp(ctxt, p);
p->as = ANOP;
q1->pcond = p;
}
q1 = nil;
if(framesize <= StackSmall) {
p = appendp(ctxt, p);
p->as = cmp;
p->from.type = D_SP;
indir_cx(ctxt, &p->to);
} else if(framesize <= StackBig) {
p = appendp(ctxt, p);
p->as = lea;
p->from.type = D_INDIR+D_SP;
p->from.offset = -(framesize-StackSmall);
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = cmp;
p->from.type = D_AX;
indir_cx(ctxt, &p->to);
} else {
p = appendp(ctxt, p);
p->as = mov;
indir_cx(ctxt, &p->from);
p->from.offset = 0;
p->to.type = D_SI;
p = appendp(ctxt, p);
p->as = cmp;
p->from.type = D_SI;
p->to.type = D_CONST;
p->to.offset = StackPreempt;
p = appendp(ctxt, p);
p->as = AJEQ;
p->to.type = D_BRANCH;
q1 = p;
p = appendp(ctxt, p);
p->as = lea;
p->from.type = D_INDIR+D_SP;
p->from.offset = StackGuard;
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = sub;
p->from.type = D_SI;
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = cmp;
p->from.type = D_AX;
p->to.type = D_CONST;
p->to.offset = framesize+(StackGuard-StackSmall);
}
p = appendp(ctxt, p);
p->as = AJHI;
p->to.type = D_BRANCH;
q = p;
moreconst1 = 0;
if(StackTop + textarg + ctxt->arch->ptrsize + framesize + ctxt->arch->ptrsize + StackLimit >= StackMin)
moreconst1 = framesize;
moreconst2 = textarg;
if(moreconst2 == 1)
moreconst2 = 0;
if((moreconst2&7) != 0)
ctxt->diag("misaligned argument size in stack split");
p = appendp(ctxt, p);
if(moreconst1 == 0 && moreconst2 == 0) {
p->as = ACALL;
p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[0*2+noctxt];
} else
if(moreconst1 != 0 && moreconst2 == 0) {
p->as = AMOVL;
p->from.type = D_CONST;
p->from.offset = moreconst1;
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[1*2+noctxt];
} else
if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) {
i = moreconst2/8 + 3;
p->as = ACALL;
p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[i*2+noctxt];
} else
if(moreconst1 == 0 && moreconst2 != 0) {
p->as = AMOVL;
p->from.type = D_CONST;
p->from.offset = moreconst2;
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[2*2+noctxt];
} else {
p->as = AMOVQ;
p->from.type = D_CONST;
p->from.offset = (uint64)moreconst2 << 32;
p->from.offset |= moreconst1;
p->to.type = D_AX;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[3*2+noctxt];
}
p = appendp(ctxt, p);
p->as = AJMP;
p->to.type = D_BRANCH;
p->pcond = ctxt->cursym->text->link;
if(q != nil)
q->pcond = p->link;
if(q1 != nil)
q1->pcond = q->link;
*jmpok = q;
return p;
}
static void xfol(Link*, Prog*, Prog**);
static void
follow(Link *ctxt, LSym *s)
{
Prog *firstp, *lastp;
ctxt->cursym = s;
firstp = ctxt->arch->prg();
lastp = firstp;
xfol(ctxt, s->text, &lastp);
lastp->link = nil;
s->text = firstp->link;
}
static int
nofollow(int a)
{
switch(a) {
case AJMP:
case ARET:
case AIRETL:
case AIRETQ:
case AIRETW:
case ARETFL:
case ARETFQ:
case ARETFW:
case AUNDEF:
return 1;
}
return 0;
}
static int
pushpop(int a)
{
switch(a) {
case APUSHL:
case APUSHFL:
case APUSHQ:
case APUSHFQ:
case APUSHW:
case APUSHFW:
case APOPL:
case APOPFL:
case APOPQ:
case APOPFQ:
case APOPW:
case APOPFW:
return 1;
}
return 0;
}
static int
relinv(int a)
{
switch(a) {
case AJEQ: return AJNE;
case AJNE: return AJEQ;
case AJLE: return AJGT;
case AJLS: return AJHI;
case AJLT: return AJGE;
case AJMI: return AJPL;
case AJGE: return AJLT;
case AJPL: return AJMI;
case AJGT: return AJLE;
case AJHI: return AJLS;
case AJCS: return AJCC;
case AJCC: return AJCS;
case AJPS: return AJPC;
case AJPC: return AJPS;
case AJOS: return AJOC;
case AJOC: return AJOS;
}
sysfatal("unknown relation: %s", anames6[a]);
return 0;
}
static void
xfol(Link *ctxt, Prog *p, Prog **last)
{
Prog *q;
int i;
enum as a;
loop:
if(p == nil)
return;
if(p->as == AJMP)
if((q = p->pcond) != nil && q->as != ATEXT) {
p->mark = 1;
p = q;
if(p->mark == 0)
goto loop;
}
if(p->mark) {
for(i=0,q=p; i<4; i++,q=q->link) {
if(q == nil)
break;
if(q == *last)
break;
a = q->as;
if(a == ANOP) {
i--;
continue;
}
if(nofollow(a) || pushpop(a))
break;
if(q->pcond == nil || q->pcond->mark)
continue;
if(a == ACALL || a == ALOOP)
continue;
for(;;) {
if(p->as == ANOP) {
p = p->link;
continue;
}
q = copyp(ctxt, p);
p = p->link;
q->mark = 1;
(*last)->link = q;
*last = q;
if(q->as != a || q->pcond == nil || q->pcond->mark)
continue;
q->as = relinv(q->as);
p = q->pcond;
q->pcond = q->link;
q->link = p;
xfol(ctxt, q->link, last);
p = q->link;
if(p->mark)
return;
goto loop;
}
}
q = ctxt->arch->prg();
q->as = AJMP;
q->lineno = p->lineno;
q->to.type = D_BRANCH;
q->to.offset = p->pc;
q->pcond = p;
p = q;
}
p->mark = 1;
(*last)->link = p;
*last = p;
a = p->as;
if(nofollow(a))
return;
if(p->pcond != nil && a != ACALL) {
if((q = brchain(ctxt, p->pcond)) != nil)
p->pcond = q;
if((q = brchain(ctxt, p->link)) != nil)
p->link = q;
if(p->from.type == D_CONST) {
if(p->from.offset == 1) {
p->as = relinv(a);
q = p->link;
p->link = p->pcond;
p->pcond = q;
}
} else {
q = p->link;
if(q->mark)
if(a != ALOOP) {
p->as = relinv(a);
p->link = p->pcond;
p->pcond = q;
}
}
xfol(ctxt, p->link, last);
if(p->pcond->mark)
return;
p = p->pcond;
goto loop;
}
p = p->link;
goto loop;
}
static Prog*
prg(void)
{
Prog *p;
p = emallocz(sizeof(*p));
*p = zprg;
return p;
}
LinkArch linkamd64 = {
.name = "amd64",
.thechar = '6',
.addstacksplit = addstacksplit,
.assemble = span6,
.datasize = datasize,
.follow = follow,
.iscall = iscall,
.isdata = isdata,
.prg = prg,
.progedit = progedit,
.settextflag = settextflag,
.symtype = symtype,
.textflag = textflag,
.minlc = 1,
.ptrsize = 8,
.regsize = 8,
.D_ADDR = D_ADDR,
.D_AUTO = D_AUTO,
.D_BRANCH = D_BRANCH,
.D_CONST = D_CONST,
.D_EXTERN = D_EXTERN,
.D_FCONST = D_FCONST,
.D_NONE = D_NONE,
.D_PARAM = D_PARAM,
.D_SCONST = D_SCONST,
.D_STATIC = D_STATIC,
.ACALL = ACALL,
.ADATA = ADATA,
.AEND = AEND,
.AFUNCDATA = AFUNCDATA,
.AGLOBL = AGLOBL,
.AJMP = AJMP,
.ANOP = ANOP,
.APCDATA = APCDATA,
.ARET = ARET,
.ATEXT = ATEXT,
.ATYPE = ATYPE,
.AUSEFIELD = AUSEFIELD,
};
LinkArch linkamd64p32 = {
.name = "amd64p32",
.thechar = '6',
.addstacksplit = addstacksplit,
.assemble = span6,
.datasize = datasize,
.follow = follow,
.iscall = iscall,
.isdata = isdata,
.prg = prg,
.progedit = progedit,
.settextflag = settextflag,
.symtype = symtype,
.textflag = textflag,
.minlc = 1,
.ptrsize = 4,
.regsize = 8,
.D_ADDR = D_ADDR,
.D_AUTO = D_AUTO,
.D_BRANCH = D_BRANCH,
.D_CONST = D_CONST,
.D_EXTERN = D_EXTERN,
.D_FCONST = D_FCONST,
.D_NONE = D_NONE,
.D_PARAM = D_PARAM,
.D_SCONST = D_SCONST,
.D_STATIC = D_STATIC,
.ACALL = ACALL,
.ADATA = ADATA,
.AEND = AEND,
.AFUNCDATA = AFUNCDATA,
.AGLOBL = AGLOBL,
.AJMP = AJMP,
.ANOP = ANOP,
.APCDATA = APCDATA,
.ARET = ARET,
.ATEXT = ATEXT,
.ATYPE = ATYPE,
.AUSEFIELD = AUSEFIELD,
};