diff --git a/sys/src/cmd/7l/asmout.c b/sys/src/cmd/7l/asmout.c index 7a3c7b4f9..1e993439b 100644 --- a/sys/src/cmd/7l/asmout.c +++ b/sys/src/cmd/7l/asmout.c @@ -722,27 +722,24 @@ asmout(Prog *p, Optab *o) if(as == AMOV){ as = AORR; r = REGZERO; - }else if(as == AMOVW){ + }else if(as == AMOVW || as == AMOVWU){ as = AORRW; r = REGZERO; } o1 = opirr(as); - s = o1 & S64? 64: 32; mask = findmask(p->from.offset); if(mask == nil) - mask = findmask(p->from.offset | (p->from.offset<<32)); - if(mask != nil){ - o1 |= ((mask->r&(s-1))<<16) | (((mask->s-1)&(s-1))<<10); - if(s == 64){ - if(mask->e == 64 && ((uvlong)p->from.offset>>32) != 0) - o1 |= 1<<22; - }else{ - u = (uvlong)p->from.offset >> 32; - if(u != 0 && u != 0xFFFFFFFF) - diag("mask needs 64 bits %#llux\n%P", p->from.offset, p); - } - }else - diag("invalid mask %#llux\n%P", p->from.offset, p); /* probably shouldn't happen */ + mask = findmask(p->from.offset | p->from.offset<<32); + if(mask == nil) + diag("invalid mask %#llux\n%P", p->from.offset, p); + switch(mask->e){ + case 2: o1 |= 0xF000; break; + case 4: o1 |= 0xE000; break; + case 8: o1 |= 0xC000; break; + case 16: o1 |= 0x8000; break; + case 64: o1 |= ((o1&S64)!=0)<<22; break; + } + o1 |= (mask->r<<16) | ((mask->s-1)<<10); o1 |= (r<<5) | rt; break; @@ -1591,7 +1588,7 @@ oaddi(long o1, long v, int r, int rt) } /* - * load a a literal value into dr + * load a literal value into dr */ static long omovlit(int as, Prog *p, Adr *a, int dr) diff --git a/sys/src/cmd/7l/l.h b/sys/src/cmd/7l/l.h index ac0dae6dc..73852d65e 100644 --- a/sys/src/cmd/7l/l.h +++ b/sys/src/cmd/7l/l.h @@ -158,7 +158,9 @@ enum C_ADDCON0, /* 12-bit unsigned, unshifted */ C_ADDCON, /* 12-bit unsigned, shifted left by 0 or 12 */ C_MOVCON, /* generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16 */ - C_BITCON, /* bimm32 */ + C_BITCON, /* bimm32/bimm64 */ + C_BITCON32, /* bimm32 */ + C_BITCON64, /* bimm64 */ C_ABCON, /* could be C_ADDCON or C_BITCON */ C_MBCON, /* could be C_MOVCON or C_BITCON */ C_LCON, /* 32-bit constant */ diff --git a/sys/src/cmd/7l/optab.c b/sys/src/cmd/7l/optab.c index c462857ed..a2d5bae36 100644 --- a/sys/src/cmd/7l/optab.c +++ b/sys/src/cmd/7l/optab.c @@ -42,25 +42,42 @@ Optab optab[] = /* logical operations */ { AAND, C_REG, C_REG, C_REG, 1, 4, 0 }, + { AANDW, C_REG, C_REG, C_REG, 1, 4, 0 }, { AAND, C_REG, C_NONE, C_REG, 1, 4, 0 }, + { AANDW, C_REG, C_NONE, C_REG, 1, 4, 0 }, { ABIC, C_REG, C_REG, C_REG, 1, 4, 0 }, + { ABICW, C_REG, C_REG, C_REG, 1, 4, 0 }, { ABIC, C_REG, C_NONE, C_REG, 1, 4, 0 }, + { ABICW, C_REG, C_NONE, C_REG, 1, 4, 0 }, - { AAND, C_BITCON, C_REG, C_REG, 53, 4, 0 }, - { AAND, C_BITCON, C_NONE, C_REG, 53, 4, 0 }, - { ABIC, C_BITCON, C_REG, C_REG, 53, 4, 0 }, - { ABIC, C_BITCON, C_NONE, C_REG, 53, 4, 0 }, + { AAND, C_BITCON64,C_REG,C_REG, 53, 4, 0 }, + { AANDW, C_BITCON32,C_REG,C_REG, 53, 4, 0 }, + { AAND, C_BITCON64,C_NONE,C_REG, 53, 4, 0 }, + { AANDW, C_BITCON32,C_NONE,C_REG, 53, 4, 0 }, + { ABIC, C_BITCON64,C_REG,C_REG, 53, 4, 0 }, + { ABICW, C_BITCON32,C_REG,C_REG, 53, 4, 0 }, + { ABIC, C_BITCON64,C_NONE,C_REG, 53, 4, 0 }, + { ABICW, C_BITCON32,C_NONE,C_REG, 53, 4, 0 }, { AAND, C_LCON, C_REG, C_REG, 28, 8, 0, LFROM }, + { AANDW, C_LCON, C_REG, C_REG, 28, 8, 0, LFROM }, { AAND, C_LCON, C_NONE, C_REG, 28, 8, 0, LFROM }, + { AANDW, C_LCON, C_NONE, C_REG, 28, 8, 0, LFROM }, { ABIC, C_LCON, C_REG, C_REG, 28, 8, 0, LFROM }, + { ABICW, C_LCON, C_REG, C_REG, 28, 8, 0, LFROM }, { ABIC, C_LCON, C_NONE, C_REG, 28, 8, 0, LFROM }, + { ABICW, C_LCON, C_NONE, C_REG, 28, 8, 0, LFROM }, { AAND, C_SHIFT,C_REG, C_REG, 3, 4, 0 }, + { AANDW, C_SHIFT,C_REG, C_REG, 3, 4, 0 }, { AAND, C_SHIFT,C_NONE, C_REG, 3, 4, 0 }, + { AANDW, C_SHIFT,C_NONE, C_REG, 3, 4, 0 }, { ABIC, C_SHIFT,C_REG, C_REG, 3, 4, 0 }, + { ABICW, C_SHIFT,C_REG, C_REG, 3, 4, 0 }, { ABIC, C_SHIFT,C_NONE, C_REG, 3, 4, 0 }, + { ABICW, C_SHIFT,C_NONE, C_REG, 3, 4, 0 }, + /* moves */ { AMOV, C_RSP, C_NONE, C_RSP, 24, 4, 0 }, { AMVN, C_REG, C_NONE, C_REG, 24, 4, 0 }, { AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0 }, @@ -70,12 +87,13 @@ Optab optab[] = /* TO DO: MVN C_SHIFT */ /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ - { AMOVW, C_MOVCON, C_NONE, C_REG, 32, 4, 0 }, + { AMOVW, C_MOVCON, C_NONE, C_REG, 32, 4, 0 }, { AMOV, C_MOVCON, C_NONE, C_REG, 32, 4, 0 }, -// { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 }, +// { AMOVW, C_ADDCON, C_NONE, C_REG, 2, 4, 0 }, // { AMOV, C_ADDCON, C_NONE, C_REG, 2, 4, 0 }, -// { AMOVW, C_BITCON, C_NONE, C_REG, 53, 4, 0 }, -// { AMOV, C_BITCON, C_NONE, C_REG, 53, 4, 0 }, + + { AMOV, C_BITCON64, C_NONE, C_REG, 53, 4, 0 }, + { AMOVW, C_BITCON32, C_NONE, C_REG, 53, 4, 0 }, { AMOVK, C_LCON, C_NONE, C_REG, 33, 4, 0 }, diff --git a/sys/src/cmd/7l/span.c b/sys/src/cmd/7l/span.c index a2d724ac8..a2894d29b 100644 --- a/sys/src/cmd/7l/span.c +++ b/sys/src/cmd/7l/span.c @@ -7,7 +7,7 @@ static struct { ulong size; } pool; -static void checkpool(Prog*, int); +static void checkpool(Prog*, int); static void flushpool(Prog*, int); static int ispcdisp(long); @@ -329,11 +329,31 @@ isaddcon(vlong v) return v <= 0xFFF; } +static int +isbitcon64(uvlong v) +{ + return findmask(v) != nil; +} + +static int +isbitcon32(uvlong v) +{ + return (v >> 32) == 0 && findmask(v | v<<32) != nil; +} + static int isbitcon(uvlong v) { - /* fancy bimm32 or bimm64? */ - return findmask(v) != nil || (v>>32) == 0 && findmask(v | (v<<32)) != nil; + Mask *m; + + if((v >> 32) != 0) + return 0; + m = findmask(v); + if(m == nil) + return 0; + if(m->s >= 32) + return 0; + return 1; } static int @@ -618,6 +638,10 @@ aclass(Adr *a) } if(isbitcon(v)) return C_BITCON; + if(isbitcon64(v)) + return C_BITCON64; + if(isbitcon32(v)) + return C_BITCON32; return C_LCON; case D_EXTERN: @@ -716,6 +740,8 @@ oplook(Prog *p) if(o->a2 == a2 || c2[o->a2]) if(c1[o->a1]) if(c3[o->a3]) { + if(0) + print("%P\t-> %d (%d %d %d)\n", p, o->type, o->a1, o->a2, o->a3); p->optab = (o-optab)+1; return o; } @@ -755,6 +781,11 @@ cmp(int a, int b) return 1; break; + case C_BITCON32: + case C_BITCON64: + if(b == C_BITCON) + return 1; + /* wet floor */ case C_BITCON: if(b == C_ABCON || b == C_MBCON) return 1; @@ -766,7 +797,7 @@ cmp(int a, int b) break; case C_LCON: - if(b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON) + if(b == C_ZCON || b == C_BITCON || b == C_BITCON32 || b == C_BITCON64 || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON) return 1; break; @@ -934,20 +965,24 @@ buildop(void) break; case AAND: /* logical immediate, logical shifted register */ oprange[AANDS] = t; + oprange[AEOR] = t; + oprange[AORR] = t; + break; + case AANDW: oprange[AANDSW] = t; oprange[AANDW] = t; - oprange[AEOR] = t; oprange[AEORW] = t; - oprange[AORR] = t; oprange[AORRW] = t; break; case ABIC: /* only logical shifted register */ oprange[ABICS] = t; + oprange[AEON] = t; + oprange[AORN] = t; + break; + case ABICW: oprange[ABICSW] = t; oprange[ABICW] = t; - oprange[AEON] = t; oprange[AEONW] = t; - oprange[AORN] = t; oprange[AORNW] = t; break; case ANEG: