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.
This commit is contained in:
cinap_lenrek 2019-04-08 14:12:01 +02:00
parent d8d4802f80
commit 12fc1c7d3e
4 changed files with 85 additions and 33 deletions

View file

@ -722,27 +722,24 @@ asmout(Prog *p, Optab *o)
if(as == AMOV){ if(as == AMOV){
as = AORR; as = AORR;
r = REGZERO; r = REGZERO;
}else if(as == AMOVW){ }else if(as == AMOVW || as == AMOVWU){
as = AORRW; as = AORRW;
r = REGZERO; r = REGZERO;
} }
o1 = opirr(as); o1 = opirr(as);
s = o1 & S64? 64: 32;
mask = findmask(p->from.offset); mask = findmask(p->from.offset);
if(mask == nil) if(mask == nil)
mask = findmask(p->from.offset | (p->from.offset<<32)); mask = findmask(p->from.offset | p->from.offset<<32);
if(mask != nil){ if(mask == nil)
o1 |= ((mask->r&(s-1))<<16) | (((mask->s-1)&(s-1))<<10); diag("invalid mask %#llux\n%P", p->from.offset, p);
if(s == 64){ switch(mask->e){
if(mask->e == 64 && ((uvlong)p->from.offset>>32) != 0) case 2: o1 |= 0xF000; break;
o1 |= 1<<22; case 4: o1 |= 0xE000; break;
}else{ case 8: o1 |= 0xC000; break;
u = (uvlong)p->from.offset >> 32; case 16: o1 |= 0x8000; break;
if(u != 0 && u != 0xFFFFFFFF) case 64: o1 |= ((o1&S64)!=0)<<22; break;
diag("mask needs 64 bits %#llux\n%P", p->from.offset, p); }
} o1 |= (mask->r<<16) | ((mask->s-1)<<10);
}else
diag("invalid mask %#llux\n%P", p->from.offset, p); /* probably shouldn't happen */
o1 |= (r<<5) | rt; o1 |= (r<<5) | rt;
break; 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 static long
omovlit(int as, Prog *p, Adr *a, int dr) omovlit(int as, Prog *p, Adr *a, int dr)

View file

@ -158,7 +158,9 @@ enum
C_ADDCON0, /* 12-bit unsigned, unshifted */ C_ADDCON0, /* 12-bit unsigned, unshifted */
C_ADDCON, /* 12-bit unsigned, shifted left by 0 or 12 */ 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_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_ABCON, /* could be C_ADDCON or C_BITCON */
C_MBCON, /* could be C_MOVCON or C_BITCON */ C_MBCON, /* could be C_MOVCON or C_BITCON */
C_LCON, /* 32-bit constant */ C_LCON, /* 32-bit constant */

View file

@ -42,25 +42,42 @@ Optab optab[] =
/* logical operations */ /* logical operations */
{ AAND, C_REG, C_REG, C_REG, 1, 4, 0 }, { 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 }, { 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 }, { 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 }, { 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_BITCON64,C_REG,C_REG, 53, 4, 0 },
{ AAND, C_BITCON, C_NONE, C_REG, 53, 4, 0 }, { AANDW, C_BITCON32,C_REG,C_REG, 53, 4, 0 },
{ ABIC, C_BITCON, C_REG, C_REG, 53, 4, 0 }, { AAND, C_BITCON64,C_NONE,C_REG, 53, 4, 0 },
{ ABIC, C_BITCON, 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { AMOV, C_RSP, C_NONE, C_RSP, 24, 4, 0 },
{ AMVN, C_REG, C_NONE, C_REG, 24, 4, 0 }, { AMVN, C_REG, C_NONE, C_REG, 24, 4, 0 },
{ AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0 }, { AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0 },
@ -70,12 +87,13 @@ Optab optab[] =
/* TO DO: MVN C_SHIFT */ /* TO DO: MVN C_SHIFT */
/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */ /* 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 }, { 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 }, // { 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 }, { AMOVK, C_LCON, C_NONE, C_REG, 33, 4, 0 },

View file

@ -7,7 +7,7 @@ static struct {
ulong size; ulong size;
} pool; } pool;
static void checkpool(Prog*, int); static void checkpool(Prog*, int);
static void flushpool(Prog*, int); static void flushpool(Prog*, int);
static int ispcdisp(long); static int ispcdisp(long);
@ -329,11 +329,31 @@ isaddcon(vlong v)
return v <= 0xFFF; 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 static int
isbitcon(uvlong v) isbitcon(uvlong v)
{ {
/* fancy bimm32 or bimm64? */ Mask *m;
return findmask(v) != nil || (v>>32) == 0 && findmask(v | (v<<32)) != nil;
if((v >> 32) != 0)
return 0;
m = findmask(v);
if(m == nil)
return 0;
if(m->s >= 32)
return 0;
return 1;
} }
static int static int
@ -618,6 +638,10 @@ aclass(Adr *a)
} }
if(isbitcon(v)) if(isbitcon(v))
return C_BITCON; return C_BITCON;
if(isbitcon64(v))
return C_BITCON64;
if(isbitcon32(v))
return C_BITCON32;
return C_LCON; return C_LCON;
case D_EXTERN: case D_EXTERN:
@ -716,6 +740,8 @@ oplook(Prog *p)
if(o->a2 == a2 || c2[o->a2]) if(o->a2 == a2 || c2[o->a2])
if(c1[o->a1]) if(c1[o->a1])
if(c3[o->a3]) { 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; p->optab = (o-optab)+1;
return o; return o;
} }
@ -755,6 +781,11 @@ cmp(int a, int b)
return 1; return 1;
break; break;
case C_BITCON32:
case C_BITCON64:
if(b == C_BITCON)
return 1;
/* wet floor */
case C_BITCON: case C_BITCON:
if(b == C_ABCON || b == C_MBCON) if(b == C_ABCON || b == C_MBCON)
return 1; return 1;
@ -766,7 +797,7 @@ cmp(int a, int b)
break; break;
case C_LCON: 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; return 1;
break; break;
@ -934,20 +965,24 @@ buildop(void)
break; break;
case AAND: /* logical immediate, logical shifted register */ case AAND: /* logical immediate, logical shifted register */
oprange[AANDS] = t; oprange[AANDS] = t;
oprange[AEOR] = t;
oprange[AORR] = t;
break;
case AANDW:
oprange[AANDSW] = t; oprange[AANDSW] = t;
oprange[AANDW] = t; oprange[AANDW] = t;
oprange[AEOR] = t;
oprange[AEORW] = t; oprange[AEORW] = t;
oprange[AORR] = t;
oprange[AORRW] = t; oprange[AORRW] = t;
break; break;
case ABIC: /* only logical shifted register */ case ABIC: /* only logical shifted register */
oprange[ABICS] = t; oprange[ABICS] = t;
oprange[AEON] = t;
oprange[AORN] = t;
break;
case ABICW:
oprange[ABICSW] = t; oprange[ABICSW] = t;
oprange[ABICW] = t; oprange[ABICW] = t;
oprange[AEON] = t;
oprange[AEONW] = t; oprange[AEONW] = t;
oprange[AORN] = t;
oprange[AORNW] = t; oprange[AORNW] = t;
break; break;
case ANEG: case ANEG: