static int32 immaddr(int32);
static int32 opbra(Link*, int, int);
-static Opcross opcross[8];
static Oprang oprange[ALAST];
-static char xcmp[C_GOK+1][C_GOK+1];
-static uchar repop[ALAST];
+static uchar xcmp[C_GOK+1][C_GOK+1];
static Prog zprg = {
.as = AGOK,
if(m % 4 != 0 || p->pc % 4 != 0) {
ctxt->diag("pc invalid: %P size=%d", p, m);
}
- if(m > sizeof(out))
- ctxt->diag("instruction size too large: %d > %d", m, sizeof(out));
+ if(m/4 > nelem(out))
+ ctxt->diag("instruction size too large: %d > %d", m/4, nelem(out));
if(m == 0 && (p->as != AFUNCDATA && p->as != APCDATA && p->as != ADATABUNDLEEND)) {
if(p->as == ATEXT) {
ctxt->autosize = p->to.offset + 4;
return 0;
}
+static int aconsize(Link *ctxt);
+
static int
aclass(Link *ctxt, Addr *a)
{
case D_NONE:
ctxt->instoffset = a->offset;
if(a->reg != NREG)
- goto aconsize;
+ return aconsize(ctxt);
t = immrot(ctxt->instoffset);
if(t)
case D_AUTO:
ctxt->instoffset = ctxt->autosize + a->offset;
- goto aconsize;
+ return aconsize(ctxt);
case D_PARAM:
ctxt->instoffset = ctxt->autosize + a->offset + 4L;
- aconsize:
- t = immrot(ctxt->instoffset);
- if(t)
- return C_RACON;
- return C_LACON;
+ return aconsize(ctxt);
}
return C_GOK;
return C_GOK;
}
+static int
+aconsize(Link *ctxt)
+{
+ int t;
+
+ t = immrot(ctxt->instoffset);
+ if(t)
+ return C_RACON;
+ return C_LACON;
+}
+
static void
prasm(Prog *p)
{
oplook(Link *ctxt, Prog *p)
{
int a1, a2, a3, r;
- char *c1, *c3;
+ uchar *c1, *c3;
Optab *o, *e;
a1 = p->optab;
r = p->as;
o = oprange[r].start;
if(o == 0) {
- a1 = opcross[repop[r]][a1][a2][a3];
- if(a1) {
- p->optab = a1+1;
- return optab+a1;
- }
o = oprange[r].stop; /* just generate an error */
}
if(0 /*debug['O']*/) {
}
}
+static int32 mov(Link*, Prog*);
+
static void
asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
{
break;
case 3: /* add R<<[IR],[R],R */
- mov:
- aclass(ctxt, &p->from);
- o1 = oprrr(ctxt, p->as, p->scond);
- o1 |= p->from.offset;
- rt = p->to.reg;
- r = p->reg;
- if(p->to.type == D_NONE)
- rt = 0;
- if(p->as == AMOVW || p->as == AMVN)
- r = 0;
- else if(r == NREG)
- r = rt;
- o1 |= (r<<16) | (rt<<12);
+ o1 = mov(ctxt, p);
break;
case 4: /* add $I,[R],R */
o1 |= p->from.reg << 0;
break;
- case 38: /* movm $con,oreg -> stm */
- o1 = (0x4 << 25);
- o1 |= p->from.offset & 0xffff;
- o1 |= p->to.reg << 16;
- aclass(ctxt, &p->to);
- goto movm;
-
- case 39: /* movm oreg,$con -> ldm */
- o1 = (0x4 << 25) | (1 << 20);
- o1 |= p->to.offset & 0xffff;
- o1 |= p->from.reg << 16;
- aclass(ctxt, &p->from);
- movm:
+ case 38:
+ case 39:
+ switch(o->type) {
+ case 38: /* movm $con,oreg -> stm */
+ o1 = (0x4 << 25);
+ o1 |= p->from.offset & 0xffff;
+ o1 |= p->to.reg << 16;
+ aclass(ctxt, &p->to);
+ break;
+
+ case 39: /* movm oreg,$con -> ldm */
+ o1 = (0x4 << 25) | (1 << 20);
+ o1 |= p->to.offset & 0xffff;
+ o1 |= p->from.reg << 16;
+ aclass(ctxt, &p->from);
+ break;
+ }
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in MOVM; %P", p);
o1 |= (p->scond & C_SCOND) << 28;
if(p->from.reg == NREG) {
if(p->as != AMOVW)
ctxt->diag("byte MOV from shifter operand");
- goto mov;
+ o1 = mov(ctxt, p);
+ break;
}
if(p->from.offset&(1<<4))
ctxt->diag("bad shift in LDR");
case 60: /* movb R(R),R -> ldrsb indexed */
if(p->from.reg == NREG) {
ctxt->diag("byte MOV from shifter operand");
- goto mov;
+ o1 = mov(ctxt, p);
+ break;
}
if(p->from.offset&(~0xf))
ctxt->diag("bad shift in LDRSB");
return;
}
+static int32
+mov(Link *ctxt, Prog *p)
+{
+ int32 o1;
+ int rt, r;
+
+ aclass(ctxt, &p->from);
+ o1 = oprrr(ctxt, p->as, p->scond);
+ o1 |= p->from.offset;
+ rt = p->to.reg;
+ r = p->reg;
+ if(p->to.type == D_NONE)
+ rt = 0;
+ if(p->as == AMOVW || p->as == AMVN)
+ r = 0;
+ else if(r == NREG)
+ r = rt;
+ o1 |= (r<<16) | (rt<<12);
+ return o1;
+}
+
static int32
oprrr(Link *ctxt, int a, int sc)
{
FuncAlign = 16
};
-extern char *anames6[];
-
typedef struct Optab Optab;
typedef struct Movtab Movtab;
Maxand = 10, /* in -a output width of the byte codes */
};
-static char ycover[Ymax*Ymax];
+static uchar ycover[Ymax*Ymax];
static int reg[D_NONE];
static int regrex[D_NONE+1];
static void asmins(Link *ctxt, Prog *p);
}
static void
-bytereg(Addr *a, char *t)
+bytereg(Addr *a, uint8 *t)
{
if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15)) {
a->type = D_AL + (a->type-D_AX);
break;
}
default:
- if(ctxt->andptr == ctxt->and || ctxt->andptr[-1] != Pm)
+ if(ctxt->andptr == ctxt->and || ctxt->and[ctxt->andptr - ctxt->and - 1] != Pm)
*ctxt->andptr++ = Pm;
break;
}
asmando(ctxt, &p->to, o->op[z+1]);
break;
+ case Zcallindreg:
+ r = addrel(ctxt->cursym);
+ r->off = p->pc;
+ r->type = R_CALLIND;
+ r->siz = 0;
+ // fallthrough
case Zo_m64:
- case_Zo_m64:
*ctxt->andptr++ = op;
asmandsz(ctxt, &p->to, o->op[z+1], 0, 1);
break;
put4(ctxt, 0);
break;
- case Zcallindreg:
- r = addrel(ctxt->cursym);
- r->off = p->pc;
- r->type = R_CALLIND;
- r->siz = 0;
- goto case_Zo_m64;
-
case Zbr:
case Zjmp:
case Zloop:
static void
asmins(Link *ctxt, Prog *p)
{
- int n, np, c;
+ int i, n, np, c;
uchar *and0;
Reloc *r;
ctxt->andptr++;
}
n = ctxt->andptr - ctxt->and;
- for(r=ctxt->cursym->r+ctxt->cursym->nr; r-- > ctxt->cursym->r; ) {
+ for(i=ctxt->cursym->nr-1; i>=0; i--) {
+ r = ctxt->cursym->r+i;
if(r->off < p->pc)
break;
if(ctxt->rexflag)