Showing with 98 additions and 5 deletions.
  1. +1 −0 src/backend/cgcs.c
  2. +80 −0 src/backend/cod4.c
  3. +1 −0 src/backend/code.h
  4. +1 −0 src/backend/code_x86.h
  5. +2 −0 src/backend/glocal.c
  6. +1 −0 src/backend/gloop.c
  7. +4 −0 src/backend/gother.c
  8. +1 −0 src/backend/oper.h
  9. +7 −5 src/backend/optabgen.c
1 change: 1 addition & 0 deletions src/backend/cgcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ STATIC void ecom(elem **pe)
case OPbtc:
case OPbts:
case OPbtr:
case OPcmpxchg:
ecom(&e->E1);
ecom(&e->E2);
touchfunc(0); // indirect assignment
Expand Down
80 changes: 80 additions & 0 deletions src/backend/cod4.c
Original file line number Diff line number Diff line change
Expand Up @@ -3767,4 +3767,84 @@ code *cdpair(elem *e, regm_t *pretregs)
return cat4(c1,c2,cg,fixresult(e,regs1 | regs2,pretregs));
}

/*************************
* Generate code for OPcmpxchg
*/

code *cdcmpxchg(elem *e, regm_t *pretregs)
{
/* The form is:
* OPcmpxchg
* / \
* lvalue OPparam
* / \
* old new
*/
code *cr1,*cr,*cl,*c,cs;

//printf("cdmulass(e=%p, *pretregs = %s)\n",e,regm_str(*pretregs));
elem *e1 = e->E1;
elem *e2 = e->E2;
assert(e2->Eoper == OPparam);
assert(!e2->Ecount);

tym_t tyml = tybasic(e1->Ety); // type of lvalue
unsigned sz = tysize[tyml];

if (I32 && sz == 8)
{
regm_t retregs = mDX|mAX;
cr1 = codelem(e2->E1,&retregs,FALSE); // [DX,AX] = e2->E1

retregs = mCX|mBX;
cr = scodelem(e2->E2,&retregs,mDX|mAX,FALSE); // [CX,BX] = e2->E2
cl = getlvalue(&cs,e1,mCX|mBX|mAX|mDX); // get EA
cs.Iop = 0x0FC7; // CMPXCHG8B EA
cs.Iflags |= CFpsw;
code_newreg(&cs,1);
c = getregs(mDX|mAX); // CMPXCHG destroys these regs
if (e1->Ety & mTYvolatile)
c = gen1(c,LOCK); // LOCK prefix
c = gen(c,&cs);
assert(!e1->Ecount);
freenode(e1);
}
else
{
unsigned byte = (sz == 1); // 1 for byte operation
unsigned char word = (!I16 && sz == SHORTSIZE) ? CFopsize : 0;
unsigned rex = (I64 && sz == 8) ? REX_W : 0;

regm_t retregs = mAX;
cr1 = codelem(e2->E1,&retregs,FALSE); // AX = e2->E1

retregs = (ALLREGS | mBP) & ~mAX;
cr = scodelem(e2->E2,&retregs,mAX,FALSE); // load rvalue in reg
cl = getlvalue(&cs,e1,mAX | retregs); // get EA
cs.Iop = 0x0FB1 ^ byte; // CMPXCHG EA,reg
cs.Iflags |= CFpsw | word;
cs.Irex |= rex;
unsigned reg = findreg(retregs);
code_newreg(&cs,reg);
c = getregs(mAX); // CMPXCHG destroys AX
if (e1->Ety & mTYvolatile)
c = gen1(c,LOCK); // LOCK prefix
c = gen(c,&cs);
assert(!e1->Ecount);
freenode(e1);
}

regm_t retregs;
if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register
{
unsigned reg;
code *cg = allocreg(&retregs,&reg,TYint);
cg = gen2(cg,0x0F94,modregrmx(3,0,reg)); // SETZ reg
*pretregs = retregs;
c = cat(c,cg);
}

return cat4(cr1,cr,cl,c);
}

#endif // !SPP
1 change: 1 addition & 0 deletions src/backend/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ code *getoffset (elem *e , unsigned reg );
cd_t cdneg;
cd_t cdabs;
cd_t cdpost;
cd_t cdcmpxchg;
cd_t cderr;
cd_t cdinfo;
cd_t cddctor;
Expand Down
1 change: 1 addition & 0 deletions src/backend/code_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ extern regm_t BYTEREGS;
#define LOOP 0xE2
#define LES 0xC4
#define LEA 0x8D
#define LOCK 0xF0

#define JO 0x70
#define JNO 0x71
Expand Down
2 changes: 2 additions & 0 deletions src/backend/glocal.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ STATIC void local_exp(elem *e,int goal)
case OPandass:
case OPxorass:
case OPorass:
case OPcmpxchg:
if (ERTOL(e))
{ local_exp(e->E2,1);
case OPnegass:
Expand Down Expand Up @@ -561,6 +562,7 @@ STATIC int local_getflags(elem *e,symbol *s)
case OPandass:
case OPxorass:
case OPorass:
case OPcmpxchg:
if (e->E1->Eoper == OPvar)
{ symbol *s1;

Expand Down
1 change: 1 addition & 0 deletions src/backend/gloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,7 @@ STATIC void markinvar(elem *n,vec_t rd)
case OPpostinc: case OPpostdec:
case OPcall:
case OPvecsto:
case OPcmpxchg:
markinvar(n->E2,rd);
case OPnegass:
n1 = n->E1;
Expand Down
4 changes: 4 additions & 0 deletions src/backend/gother.c
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,10 @@ void elimass(elem *n)
case OPbts:
n->Eoper = OPbt;
break;
case OPcmpxchg:
n->Eoper = OPcomma;
n->E2->Eoper = OPcomma;
break;
default:
assert(0);
}
Expand Down
1 change: 1 addition & 0 deletions src/backend/oper.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ enum OPER
OPscale, // ldexp
OPyl2x, // y * log2(x)
OPyl2xp1, // y * log2(x + 1)
OPcmpxchg, // cmpxchg
#endif
OPstrlen, /* strlen() */
OPstrcpy, /* strcpy() */
Expand Down
12 changes: 7 additions & 5 deletions src/backend/optabgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ int _binary[] =
OPinfo,OParray,OPfield,OPnewarray,OPmultinewarray,OPinstanceof,OPfinalinstanceof,
OPcheckcast,OPpair,OPrpair,
OPbt,OPbtc,OPbtr,OPbts,OPror,OProl,OPbtst,
OPremquo,
OPremquo,OPcmpxchg,
#if TX86
OPoutp,OPscale,OPyl2x,OPyl2xp1,
OPvecsto,
Expand Down Expand Up @@ -83,7 +83,7 @@ int _assoc[] = {OPadd,OPand,OPor,OPxor,OPmul};
int _assign[] =
{OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass,
OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,OPpostinc,OPpostdec,
OPnegass,OPvecsto,
OPnegass,OPvecsto,OPcmpxchg,
};
int _wid[] =
{OPadd,OPmin,OPand,OPor,OPxor,OPcom,OPneg,OPmul,OPaddass,OPnegass,
Expand Down Expand Up @@ -113,7 +113,7 @@ int _def[] = {OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass,
OPcall,OPucall,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
OPnegass,OPnewarray,OPmultinewarray,
OPbtc,OPbtr,OPbts,
OPvecsto,
OPvecsto,OPcmpxchg,
};
int _sideff[] = {OPasm,OPucall,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
OPcall,OPeq,OPstreq,OPpostinc,OPpostdec,
Expand All @@ -123,6 +123,7 @@ int _sideff[] = {OPasm,OPucall,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,
OPmultinewarray,OPcheckcast,OPnullcheck,
OPbtc,OPbtr,OPbts,
OPhalt,OPdctor,OPddtor,
OPcmpxchg,
#if TX86 && MARS
OPva_start,
#endif
Expand All @@ -134,7 +135,7 @@ int _rtol[] = {OPeq,OPstreq,OPstrcpy,OPmemcpy,OPpostinc,OPpostdec,OPaddass,
OPminass,OPmulass,OPdivass,OPmodass,OPandass,
OPorass,OPxorass,OPshlass,OPshrass,OPashrass,
OPcall,OPcallns,OPinfo,OPmemset,
OPvecsto,
OPvecsto,OPcmpxchg,
};
int _ae[] = {OPvar,OPconst,OPrelconst,OPneg,
OPabs,OPrndtol,OPrint,
Expand Down Expand Up @@ -184,7 +185,7 @@ int _exp[] = {OPvar,OPconst,OPrelconst,OPneg,OPabs,OPrndtol,OPrint,
OPorass,OPxorass,OPshlass,OPshrass,OPashrass,OPoror,OPandand,OPcond,
OPbsf,OPbsr,OPbt,OPbtc,OPbtr,OPbts,OPbswap,OPbtst,OPpopcnt,
OProl,OPror,OPvector,
OPpair,OPrpair,OPframeptr,OPgot,OPremquo,
OPpair,OPrpair,OPframeptr,OPgot,OPremquo,OPcmpxchg,
OPcolon,OPcolon2,OPasm,OPstrcpy,OPmemcpy,OPmemset,OPstrcat,OPnegass,
#if TX86
OPsqrt,OPsin,OPcos,OPscale,OPyl2x,OPyl2xp1,
Expand Down Expand Up @@ -517,6 +518,7 @@ void dotab()
case OPyl2x: X("yl2x", elzot, cdscale);
case OPyl2xp1: X("yl2xp1", elzot, cdscale);
#endif
case OPcmpxchg: X("cas", elzot, cdcmpxchg);
case OPrint: X("rint", evalu8, cdneg);
case OPrndtol: X("rndtol", evalu8, cdrndtol);
case OPstrlen: X("strlen", elzot, cdstrlen);
Expand Down