Commit 2a740096 authored by Ken Thompson's avatar Ken Thompson

add TST op code

R=r
CC=golang-dev
https://golang.org/cl/4000041
parent b9fb6ddd
......@@ -671,7 +671,8 @@ agen(Node *n, Node *res)
p1 = gins(AMOVW, N, &n3);
datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
p1->from.type = D_CONST;
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
} else
if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3;
n1.op = OINDREG;
n1.type = types[tptr];
......@@ -813,6 +814,28 @@ agenr(Node *n, Node *a, Node *res)
agen(n, a);
}
void
gencmp0(Node *n, Type *t, int o, Prog *to)
{
Node n1, n2, n3;
int a;
regalloc(&n1, t, N);
cgen(n, &n1);
a = optoas(OCMP, t);
if(a != ACMP) {
nodconst(&n2, t, 0);
regalloc(&n3, t, N);
gmove(&n2, &n3);
gcmp(a, &n1, &n3);
regfree(&n3);
} else
gins(ATST, &n1, N);
a = optoas(o, t);
patch(gbranch(optoas(o, t), t), to);
regfree(&n1);
}
/*
* generate:
* if(n == true) goto to;
......@@ -856,18 +879,10 @@ bgen(Node *n, int true, Prog *to)
switch(n->op) {
default:
def:
regalloc(&n1, n->type, N);
cgen(n, &n1);
nodconst(&n2, n->type, 0);
regalloc(&n3, n->type, N);
gmove(&n2, &n3);
gcmp(optoas(OCMP, n->type), &n1, &n3);
a = ABNE;
a = ONE;
if(!true)
a = ABEQ;
patch(gbranch(a, n->type), to);
regfree(&n1);
regfree(&n3);
a = OEQ;
gencmp0(n, n->type, a, to);
goto ret;
case OLITERAL:
......@@ -876,23 +891,6 @@ bgen(Node *n, int true, Prog *to)
patch(gbranch(AB, T), to);
goto ret;
case ONAME:
if(n->addable == 0)
goto def;
nodconst(&n1, n->type, 0);
regalloc(&n2, n->type, N);
regalloc(&n3, n->type, N);
gmove(&n1, &n2);
cgen(n, &n3);
gcmp(optoas(OCMP, n->type), &n2, &n3);
a = ABNE;
if(!true)
a = ABEQ;
patch(gbranch(a, n->type), to);
regfree(&n2);
regfree(&n3);
goto ret;
case OANDAND:
if(!true)
goto caseor;
......@@ -975,6 +973,16 @@ bgen(Node *n, int true, Prog *to)
yyerror("illegal array comparison");
break;
}
regalloc(&n1, types[tptr], N);
agen(nl, &n1);
n2 = n1;
n2.op = OINDREG;
n2.xoffset = Array_array;
gencmp0(&n2, types[tptr], a, to);
regfree(&n1);
break;
a = optoas(a, types[tptr]);
regalloc(&n1, types[tptr], N);
regalloc(&n3, types[tptr], N);
......@@ -1000,6 +1008,16 @@ bgen(Node *n, int true, Prog *to)
yyerror("illegal interface comparison");
break;
}
regalloc(&n1, types[tptr], N);
agen(nl, &n1);
n2 = n1;
n2.op = OINDREG;
n2.xoffset = 0;
gencmp0(&n2, types[tptr], a, to);
regfree(&n1);
break;
a = optoas(a, types[tptr]);
regalloc(&n1, types[tptr], N);
regalloc(&n3, types[tptr], N);
......@@ -1039,6 +1057,17 @@ bgen(Node *n, int true, Prog *to)
break;
}
if(nr->op == OLITERAL) {
if(nr->val.ctype == CTINT && mpgetfix(nr->val.u.xval) == 0) {
gencmp0(nl, nl->type, a, to);
break;
}
if(nr->val.ctype == CTNIL) {
gencmp0(nl, nl->type, a, to);
break;
}
}
a = optoas(a, nr->type);
if(nr->ullman >= UINF) {
......
......@@ -233,8 +233,7 @@ cgen64(Node *n, Node *res)
// shift is >= 1<<32
split64(r, &cl, &ch);
gmove(&ch, &s);
p1 = gins(AMOVW, &s, &s);
p1->scond |= C_SBIT;
p1 = gins(ATST, &s, N);
p6 = gbranch(ABNE, T);
gmove(&cl, &s);
splitclean();
......@@ -242,8 +241,7 @@ cgen64(Node *n, Node *res)
gmove(r, &s);
p6 = P;
}
p1 = gins(AMOVW, &s, &s);
p1->scond |= C_SBIT;
p1 = gins(ATST, &s, N);
// shift == 0
p1 = gins(AMOVW, &bl, &al);
......@@ -390,8 +388,7 @@ olsh_break:
// shift is >= 1<<32
split64(r, &cl, &ch);
gmove(&ch, &s);
p1 = gins(AMOVW, &s, &s);
p1->scond |= C_SBIT;
p1 = gins(ATST, &s, N);
p6 = gbranch(ABNE, T);
gmove(&cl, &s);
splitclean();
......@@ -399,8 +396,7 @@ olsh_break:
gmove(r, &s);
p6 = P;
}
p1 = gins(AMOVW, &s, &s);
p1->scond |= C_SBIT;
p1 = gins(ATST, &s, N);
// shift == 0
p1 = gins(AMOVW, &bl, &al);
......
......@@ -595,8 +595,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
}
// test for shift being 0
p1 = gins(AMOVW, &n1, &n1);
p1->scond |= C_SBIT;
p1 = gins(ATST, &n1, N);
p3 = gbranch(ABEQ, T);
// test and fix up large shifts
......
......@@ -89,11 +89,11 @@ loop1:
/*
* elide shift into D_SHIFT operand of subsequent instruction
*/
if(shiftprop(r)) {
excise(r);
t++;
break;
}
// if(shiftprop(r)) {
// excise(r);
// t++;
// break;
// }
break;
case AMOVW:
......@@ -101,10 +101,10 @@ loop1:
case AMOVD:
if(!regtyp(&p->to))
break;
if(isdconst(&p->from)) {
constprop(&p->from, &p->to, r->s1);
break;
}
// if(isdconst(&p->from)) {
// constprop(&p->from, &p->to, r->s1);
// break;
// }
if(!regtyp(&p->from))
break;
if(p->from.type != p->to.type)
......@@ -166,87 +166,89 @@ loop1:
excise(r1);
}
for(r=firstr; r!=R; r=r->link) {
p = r->prog;
switch(p->as) {
case AMOVW:
case AMOVB:
case AMOVBU:
if(p->from.type == D_OREG && p->from.offset == 0)
xtramodes(r, &p->from);
else if(p->to.type == D_OREG && p->to.offset == 0)
xtramodes(r, &p->to);
else
continue;
break;
case ACMP:
/*
* elide CMP $0,x if calculation of x can set condition codes
*/
if(isdconst(&p->from) || p->from.offset != 0)
continue;
r2 = r->s1;
if(r2 == R)
continue;
t = r2->prog->as;
switch(t) {
default:
continue;
case ABEQ:
case ABNE:
case ABMI:
case ABPL:
break;
case ABGE:
t = ABPL;
break;
case ABLT:
t = ABMI;
break;
case ABHI:
t = ABNE;
break;
case ABLS:
t = ABEQ;
break;
}
r1 = r;
do
r1 = uniqp(r1);
while (r1 != R && r1->prog->as == ANOP);
if(r1 == R)
continue;
p1 = r1->prog;
if(p1->to.type != D_REG)
continue;
if(p1->to.reg != p->reg)
if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
continue;
switch(p1->as) {
default:
continue;
case AMOVW:
if(p1->from.type != D_REG)
continue;
case AAND:
case AEOR:
case AORR:
case ABIC:
case AMVN:
case ASUB:
case ARSB:
case AADD:
case AADC:
case ASBC:
case ARSC:
break;
}
p1->scond |= C_SBIT;
r2->prog->as = t;
excise(r);
continue;
}
}
// for(r=firstr; r!=R; r=r->link) {
// p = r->prog;
// switch(p->as) {
// case AMOVW:
// case AMOVB:
// case AMOVBU:
// if(p->from.type == D_OREG && p->from.offset == 0)
// xtramodes(r, &p->from);
// else
// if(p->to.type == D_OREG && p->to.offset == 0)
// xtramodes(r, &p->to);
// else
// continue;
// break;
// case ACMP:
// /*
// * elide CMP $0,x if calculation of x can set condition codes
// */
// if(isdconst(&p->from) || p->from.offset != 0)
// continue;
// r2 = r->s1;
// if(r2 == R)
// continue;
// t = r2->prog->as;
// switch(t) {
// default:
// continue;
// case ABEQ:
// case ABNE:
// case ABMI:
// case ABPL:
// break;
// case ABGE:
// t = ABPL;
// break;
// case ABLT:
// t = ABMI;
// break;
// case ABHI:
// t = ABNE;
// break;
// case ABLS:
// t = ABEQ;
// break;
// }
// r1 = r;
// do
// r1 = uniqp(r1);
// while (r1 != R && r1->prog->as == ANOP);
// if(r1 == R)
// continue;
// p1 = r1->prog;
// if(p1->to.type != D_REG)
// continue;
// if(p1->to.reg != p->reg)
// if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
// continue;
//
// switch(p1->as) {
// default:
// continue;
// case AMOVW:
// if(p1->from.type != D_REG)
// continue;
// case AAND:
// case AEOR:
// case AORR:
// case ABIC:
// case AMVN:
// case ASUB:
// case ARSB:
// case AADD:
// case AADC:
// case ASBC:
// case ARSC:
// break;
// }
// p1->scond |= C_SBIT;
// r2->prog->as = t;
// excise(r);
// continue;
// }
// }
predicate();
}
......@@ -331,7 +333,6 @@ subprop(Reg *r0)
case ABL:
return 0;
case ACMP:
case ACMN:
case AADD:
case ASUB:
......@@ -346,8 +347,6 @@ subprop(Reg *r0)
case ADIV:
case ADIVU:
case ACMPF:
case ACMPD:
case AADDD:
case AADDF:
case ASUBD:
......@@ -648,6 +647,7 @@ shiftprop(Reg *r)
print("\t=>%P", p1);
}
case ABIC:
case ATST:
case ACMP:
case ACMN:
if(p1->reg == n)
......@@ -922,8 +922,7 @@ copyu(Prog *p, Adr *v, Adr *s)
switch(p->as) {
default:
if(debug['P'])
print(" (?)");
print("copyu: cant find %A\n", p->as);
return 2;
case AMOVM:
......@@ -1028,6 +1027,7 @@ copyu(Prog *p, Adr *v, Adr *s)
case ACMPF:
case ACMPD:
case ATST:
case ACMP:
case ACMN:
case ACASE:
......@@ -1138,6 +1138,7 @@ a2type(Prog *p)
switch(p->as) {
case ATST:
case ACMP:
case ACMN:
......@@ -1369,9 +1370,9 @@ int
modifiescpsr(Prog *p)
{
switch(p->as) {
case ATST:
case ATEQ:
case ACMN:
case ATST:
case ACMP:
case AMULU:
case ADIVU:
......
......@@ -137,7 +137,8 @@ regopt(Prog *firstp)
uint32 vreg;
Bits bit;
return; // disabled for the moment
return;
if(first == 0) {
fmtinstall('Q', Qconv);
}
......@@ -479,7 +480,7 @@ brk:
* peep-hole on basic block
*/
if(!debug['R'] || debug['P']) {
// peep();
peep();
}
/*
......
......@@ -793,7 +793,8 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na
rt = 0;
if(p->as == AMOVW || p->as == AMVN)
r = 0;
else if(r == NREG)
else
if(r == NREG)
r = rt;
o1 |= rf | (r<<16) | (rt<<12);
break;
......@@ -1558,6 +1559,12 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na
o1 |= (p->from.reg<<16);
o1 |= (p->to.reg<<12);
break;
case 90: /* tst reg */
o1 = oprrr(AMOVW, p->scond);
o1 |= p->from.reg | (p->from.reg<<12);
o1 |= 1 << 20; // SBIT
break;
}
out[0] = o1;
......
......@@ -64,7 +64,7 @@ Optab optab[] =
{ AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL },
{ ABL, C_NONE, C_NONE, C_ROREG, 7, 8, 0 },
{ ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0 },
{ ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0 },
{ ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0 },
{ ASLL, C_RCON, C_REG, C_REG, 8, 4, 0 },
{ ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0 },
......@@ -251,5 +251,7 @@ Optab optab[] =
{ AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0 },
{ AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0 },
{ ATST, C_REG, C_NONE, C_NONE, 90, 4, 0 },
{ AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0 },
};
......@@ -962,7 +962,6 @@ buildop(void)
oprange[ABIC] = oprange[r];
break;
case ACMP:
oprange[ATST] = oprange[r];
oprange[ATEQ] = oprange[r];
oprange[ACMN] = oprange[r];
break;
......@@ -1055,6 +1054,7 @@ buildop(void)
case ALDREX:
case ASTREX:
case ATST:
break;
}
}
......
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