Commit a0084b34 authored by Shenghou Ma's avatar Shenghou Ma

cmd/5a, cmd/5l: add MULW{T,B} and MULAW{T,B} support for ARM

        Supported in ARMv5TE and above.
        Also corrected MULA disassembly listing.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6265045
parent f51390b2
......@@ -286,18 +286,19 @@ inst:
outcode(AWORD, Always, &nullgen, NREG, &g);
}
/*
* MULL hi,lo,r1,r2
* MULL r1,r2,(hi,lo)
*/
| LTYPEM cond reg ',' reg ',' regreg
{
outcode($1, $2, &$3, $5.reg, &$7);
}
/*
* MULA hi,lo,r1,r2
* MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
* MULAW{T,B} r1,r2,r3,r4
*/
| LTYPEN cond reg ',' reg ',' reg ',' spreg
{
$7.type = D_REGREG;
$7.type = D_REGREG2;
$7.offset = $9;
outcode($1, $2, &$3, $5.reg, &$7);
}
......
......@@ -408,6 +408,11 @@ struct
"UNDEF", LTYPEE, AUNDEF,
"CLZ", LTYPE2, ACLZ,
"MULWT", LTYPE1, AMULWT,
"MULWB", LTYPE1, AMULWB,
"MULAWT", LTYPEN, AMULAWT,
"MULAWB", LTYPEN, AMULAWB,
0
};
......@@ -511,6 +516,7 @@ zaddr(Gen *a, int s)
break;
case D_REGREG:
case D_REGREG2:
Bputc(&obuf, a->offset);
break;
......
This diff is collapsed.
......@@ -176,7 +176,7 @@ cgen64(Node *n, Node *res)
p1->from.type = D_REG;
p1->from.reg = bl.val.u.reg;
p1->reg = ch.val.u.reg;
p1->to.type = D_REGREG;
p1->to.type = D_REGREG2;
p1->to.reg = ah.val.u.reg;
p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);
......@@ -186,7 +186,7 @@ cgen64(Node *n, Node *res)
p1->from.type = D_REG;
p1->from.reg = bh.val.u.reg;
p1->reg = cl.val.u.reg;
p1->to.type = D_REGREG;
p1->to.type = D_REGREG2;
p1->to.reg = ah.val.u.reg;
p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);
......
......@@ -147,6 +147,7 @@ zaddr(Biobuf *b, Addr *a, int s)
break;
case D_REGREG:
case D_REGREG2:
Bputc(b, a->offset);
break;
......
......@@ -153,6 +153,12 @@ Dconv(Fmt *fp)
sprint(str, "%M(R%d)(REG)", a, a->reg);
break;
case D_REGREG2:
sprint(str, "R%d,R%d", a->reg, (int)a->offset);
if(a->name != D_NONE || a->sym != S)
sprint(str, "%M(R%d)(REG)", a, a->reg);
break;
case D_FREG:
sprint(str, "F%d", a->reg);
if(a->name != D_NONE || a->sym != S)
......
......@@ -1213,7 +1213,7 @@ copyau(Adr *a, Adr *v)
if(a->reg == v->reg)
return 1;
} else
if(a->type == D_REGREG) {
if(a->type == D_REGREG || a->type == D_REGREG2) {
if(a->reg == v->reg)
return 1;
if(a->offset == v->reg)
......@@ -1276,7 +1276,7 @@ copysub(Adr *a, Adr *v, Adr *s, int f)
if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
} else
if(a->type == D_REGREG) {
if(a->type == D_REGREG || a->type == D_REGREG2) {
if(a->offset == v->reg)
a->offset = s->reg;
if(a->reg == v->reg)
......
......@@ -874,6 +874,7 @@ mkvar(Reg *r, Adr *a)
goto onereg;
case D_REGREG:
case D_REGREG2:
bit = zbits;
if(a->offset != NREG)
bit.b[0] |= RtoB(a->offset);
......
......@@ -189,6 +189,11 @@ enum as
ACLZ,
AMULWT,
AMULWB,
AMULAWT,
AMULAWB,
ALAST,
};
......@@ -242,12 +247,14 @@ enum as
#define D_SHIFT (D_NONE+19)
#define D_FPCR (D_NONE+20)
#define D_REGREG (D_NONE+21)
#define D_REGREG (D_NONE+21) // (reg, reg)
#define D_ADDR (D_NONE+22)
#define D_SBIG (D_NONE+23)
#define D_CONST2 (D_NONE+24)
#define D_REGREG2 (D_NONE+25) // reg, reg
/* name */
#define D_EXTERN (D_NONE+3)
#define D_STATIC (D_NONE+4)
......
......@@ -1806,6 +1806,19 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
o1 |= p->to.reg << 12;
o1 |= p->from.reg;
break;
case 98: /* MULW{T,B} Rs, Rm, Rd */
o1 = oprrr(p->as, p->scond);
o1 |= p->to.reg << 16;
o1 |= p->from.reg << 8;
o1 |= p->reg;
break;
case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
o1 = oprrr(p->as, p->scond);
o1 |= p->to.reg << 12;
o1 |= p->from.reg << 8;
o1 |= p->reg;
o1 |= p->to.offset << 16;
break;
}
out[0] = o1;
......@@ -1967,6 +1980,15 @@ oprrr(int a, int sc)
case ACLZ:
// CLZ doesn't support .S
return (o & (0xf<<28)) | (0x16f<<16) | (0xf1<<4);
case AMULWT:
return (o & (0xf<<28)) | (0x12 << 20) | (0xe<<4);
case AMULWB:
return (o & (0xf<<28)) | (0x12 << 20) | (0xa<<4);
case AMULAWT:
return (o & (0xf<<28)) | (0x12 << 20) | (0xc<<4);
case AMULAWB:
return (o & (0xf<<28)) | (0x12 << 20) | (0x8<<4);
}
diag("bad rrr %d", a);
prasm(curp);
......
......@@ -212,6 +212,7 @@ enum
C_NONE = 0,
C_REG,
C_REGREG,
C_REGREG2,
C_SHIFT,
C_FREG,
C_PSR,
......
......@@ -225,6 +225,12 @@ Dconv(Fmt *fp)
snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
break;
case D_REGREG2:
snprint(str, sizeof str, "R%d,R%d", a->reg, (int)a->offset);
if(a->name != D_NONE || a->sym != S)
snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
break;
case D_FREG:
snprint(str, sizeof str, "F%d", a->reg);
if(a->name != D_NONE || a->sym != S)
......@@ -438,6 +444,7 @@ cnames[] =
[C_RCON] = "C_RCON",
[C_REG] = "C_REG",
[C_REGREG] = "C_REGREG",
[C_REGREG2] = "C_REGREG2",
[C_ROREG] = "C_ROREG",
[C_SAUTO] = "C_SAUTO",
[C_SBRA] = "C_SBRA",
......
......@@ -338,6 +338,7 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
break;
case D_REGREG:
case D_REGREG2:
a->offset = BGETC(f);
break;
......
......@@ -103,6 +103,7 @@ Optab optab[] =
{ ADIV, C_REG, C_NONE, C_REG, 16, 4, 0 },
{ AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0 },
{ AMULA, C_REG, C_REG, C_REGREG2, 17, 4, 0 },
{ AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP },
{ AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0 },
......@@ -238,5 +239,8 @@ Optab optab[] =
{ ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0 },
{ AMULWT, C_REG, C_REG, C_REG, 98, 4, 0 },
{ AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0 },
{ AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0 },
};
......@@ -447,6 +447,9 @@ aclass(Adr *a)
case D_REGREG:
return C_REGREG;
case D_REGREG2:
return C_REGREG2;
case D_SHIFT:
return C_SHIFT;
......@@ -835,12 +838,20 @@ buildop(void)
break;
case AMULL:
oprange[AMULA] = oprange[r];
oprange[AMULAL] = oprange[r];
oprange[AMULLU] = oprange[r];
oprange[AMULALU] = oprange[r];
break;
case AMULWT:
oprange[AMULWB] = oprange[r];
break;
case AMULAWT:
oprange[AMULAWB] = oprange[r];
break;
case AMULA:
case ALDREX:
case ASTREX:
case ALDREXD:
......
......@@ -124,6 +124,7 @@ addr(Biobuf *bp)
case D_FPCR:
break;
case D_REGREG:
case D_REGREG2:
Bgetc(bp);
break;
case D_CONST2:
......
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