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){
|
||||
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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 },
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue