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:
parent
d8d4802f80
commit
12fc1c7d3e
4 changed files with 85 additions and 33 deletions
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue