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){
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)

View file

@ -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 */

View file

@ -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 },

View file

@ -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: