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