ref: 12fc1c7d3e04649fb7d213d16f9da597726dd7b6
parent: d8d4802f80b40bc9a43031e3d6484aa237e7d444
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Apr 8 10:12:01 EDT 2019
7l: fix bitcon instruction selection and encoding the possible bitmasks generated depend on the data width of the instruction, so we introduce C_BITCON32 and C_BITCON64 operand types to keep them apart. the encoding of the bitcon operation was wrong.
--- a/sys/src/cmd/7l/asmout.c
+++ b/sys/src/cmd/7l/asmout.c
@@ -722,27 +722,24 @@
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 @@
}
/*
- * load a a literal value into dr
+ * load a literal value into dr
*/
static long
omovlit(int as, Prog *p, Adr *a, int dr)
--- a/sys/src/cmd/7l/l.h
+++ b/sys/src/cmd/7l/l.h
@@ -158,7 +158,9 @@
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 */
--- a/sys/src/cmd/7l/optab.c
+++ b/sys/src/cmd/7l/optab.c
@@ -42,25 +42,42 @@
/* 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 @@
/* 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 },
--- a/sys/src/cmd/7l/span.c
+++ b/sys/src/cmd/7l/span.c
@@ -7,7 +7,7 @@
ulong size;
} pool;
-static void checkpool(Prog*, int);
+static void checkpool(Prog*, int);
static void flushpool(Prog*, int);
static int ispcdisp(long);
@@ -330,10 +330,30 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
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: