Skip to content

Commit

Permalink
Merge branch 'master' of github.com:D-Programming-Language/dmd
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Nov 22, 2011
2 parents 28647db + 0f8ae51 commit 6f8b4db
Showing 1 changed file with 142 additions and 83 deletions.
225 changes: 142 additions & 83 deletions src/backend/cod3.c
Expand Up @@ -2697,93 +2697,25 @@ code *prolog()
c = cat(c,nteh_setsp(0x89)); // MOV __context[EBP].esp,ESP
#endif

// Load register parameters off of the stack. Do not use
// assignaddr(), as it will replace the stack reference with
// the register!
// Keep track of used registers.
unsigned usedregs = 0;
for (si = 0; si < globsym.top; si++)
{ symbol *s = globsym.tab[si];
code *c2;
unsigned sz = type_size(s->Stype);
if (s->Sclass == SCfastpar)
usedregs |= mask[s->Spreg];
}
namedargs = usedregs;

if ((s->Sclass == SCregpar || s->Sclass == SCparameter) &&
s->Sfl == FLreg &&
(refparam
#if MARS
// This variable has been reference by a nested function
|| s->Stype->Tty & mTYvolatile
#endif
))
// Do register argument to stack moves.
for (si = 0; si < globsym.top; si++)
{ symbol *s = globsym.tab[si];
if (s->Sclass == SCfastpar && s->Sfl != FLreg)
{
/* MOV reg,param[BP] */
//assert(refparam);
if (mask[s->Sreglsw] & XMMREGS)
{
unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; // MOVSS/D xreg,mem
unsigned xreg = s->Sreglsw - XMM0;
code *c2 = genc1(CNIL,op,modregxrm(2,xreg,BPRM),FLconst,Poff + s->Soffset);
if (!hasframe)
{ // Convert to ESP relative address rather than EBP
c2->Irm = modregxrm(2,xreg,4);
c2->Isib = modregrm(0,4,SP);
c2->IEVpointer1 += EBPtoESP;
}
c = cat(c,c2);
}
else
{
code *c2 = genc1(CNIL,0x8B ^ (sz == 1),
modregxrm(2,s->Sreglsw,BPRM),FLconst,Poff + s->Soffset);
if (!I16 && sz == SHORTSIZE)
c2->Iflags |= CFopsize; // operand size
if (I64 && sz == REGSIZE)
c2->Irex |= REX_W;
if (!hasframe)
{ /* Convert to ESP relative address rather than EBP */
assert(!I16);
c2->Irm = modregxrm(2,s->Sreglsw,4);
c2->Isib = modregrm(0,4,SP);
c2->IEVpointer1 += EBPtoESP;
}
if (sz > REGSIZE)
{
code *c3 = genc1(CNIL,0x8B,
modregxrm(2,s->Sregmsw,BPRM),FLconst,Poff + s->Soffset + REGSIZE);
if (I64)
c3->Irex |= REX_W;
if (!hasframe)
{ /* Convert to ESP relative address rather than EBP */
assert(!I16);
c3->Irm = modregxrm(2,s->Sregmsw,4);
c3->Isib = modregrm(0,4,SP);
c3->IEVpointer1 += EBPtoESP;
}
c2 = cat(c2,c3);
}
c = cat(c,c2);
}
}
else if (s->Sclass == SCfastpar)
{ // Argument is passed in a register
unsigned preg = s->Spreg;
assert(usedregs & mask[preg]); // bug 6189
usedregs &= ~mask[preg];

namedargs |= mask[preg];

if (s->Sfl == FLreg)
{ // MOV reg,preg
if (mask[preg] & XMMREGS)
{
unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; // MOVSS/D xreg,preg
unsigned xreg = s->Sreglsw - XMM0;
c = gen2(c,op,modregxrmx(3,xreg,preg - XMM0));
}
else
{
c = genmovreg(c,s->Sreglsw,preg);
if (I64 && sz == 8)
code_orrex(c, REX_W);
}
}
else if (s->Sflags & SFLdead ||
if (s->Sflags & SFLdead ||
(!anyiasm && !(s->Sflags & SFLread) && s->Sflags & SFLunambig &&
#if MARS
// This variable has been reference by a nested function
Expand All @@ -2796,6 +2728,7 @@ code *prolog()
}
else
{
unsigned sz = type_size(s->Stype);
targ_size_t offset = Aoff + BPoff + s->Soffset;
int op = 0x89; // MOV x[EBP],preg
if (preg >= XMM0 && preg <= XMM15)
Expand All @@ -2813,7 +2746,7 @@ code *prolog()
if (!(pushalloc && preg == pushallocreg))
{
// MOV x[EBP],preg
c2 = genc1(CNIL,op,
code *c2 = genc1(CNIL,op,
modregxrm(2,preg,BPRM),FLconst, offset);
if (preg >= XMM0 && preg <= XMM15)
{
Expand All @@ -2836,7 +2769,7 @@ code *prolog()
{
// MOV offset[ESP],preg
// BUG: byte size?
c2 = genc1(CNIL,op,
code *c2 = genc1(CNIL,op,
(modregrm(0,4,SP) << 8) |
modregxrm(2,preg,4),FLconst,offset);
if (preg >= XMM0 && preg <= XMM15)
Expand All @@ -2856,6 +2789,132 @@ code *prolog()
}
}

#ifdef DEBUG
// check that SFLmark flag is not used
for (si = 0; si < globsym.top; si++)
{ symbol *s = globsym.tab[si];
assert(!(s->Sflags & SFLmark));
}
#endif

// Do register argument to register variable moves.
while (1)
{
size_t cnt=0, defer=0;
for (si = 0; si < globsym.top; si++)
{ symbol *s = globsym.tab[si];
if (s->Sclass != SCfastpar || s->Sfl != FLreg ||
s->Spreg == s->Sreglsw || s->Sflags & SFLmark)
continue;

++cnt;
if (usedregs & mask[s->Sreglsw])
{
++defer;
continue;
}

s->Sflags |= SFLmark;

// MOV reg,preg
unsigned preg = s->Spreg;
assert(usedregs & mask[preg]); // bug 6189
usedregs &= ~mask[preg];
usedregs |= mask[s->Sreglsw];

unsigned sz = type_size(s->Stype);
if (mask[preg] & XMMREGS)
{
unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; // MOVSS/D xreg,preg
unsigned xreg = s->Sreglsw - XMM0;
c = gen2(c,op,modregxrmx(3,xreg,preg - XMM0));
}
else
{
c = genmovreg(c,s->Sreglsw,preg);
if (I64 && sz == 8)
code_orrex(c, REX_W);
}
}
if (defer)
assert(defer < cnt); // no cyclic register moves
else
break;
}

for (si = 0; si < globsym.top; si++)
{ symbol *s = globsym.tab[si];
s->Sflags &= ~SFLmark;
}


// Do stack argument to register variable moves.
for (si = 0; si < globsym.top; si++)
{ symbol *s = globsym.tab[si];
unsigned sz = type_size(s->Stype);
if ((s->Sclass == SCregpar || s->Sclass == SCparameter) &&
s->Sfl == FLreg &&
(refparam
#if MARS
// This variable has been reference by a nested function
|| s->Stype->Tty & mTYvolatile
#endif
))
{
/* MOV reg,param[BP] */
//assert(refparam);
assert(!(usedregs & mask[s->Sreglsw])); // bug 6189
usedregs |= mask[s->Sreglsw];
if (mask[s->Sreglsw] & XMMREGS)
{
unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; // MOVSS/D xreg,mem
unsigned xreg = s->Sreglsw - XMM0;
code *c2 = genc1(CNIL,op,modregxrm(2,xreg,BPRM),FLconst,Poff + s->Soffset);
if (!hasframe)
{ // Convert to ESP relative address rather than EBP
c2->Irm = modregxrm(2,xreg,4);
c2->Isib = modregrm(0,4,SP);
c2->IEVpointer1 += EBPtoESP;
}
c = cat(c,c2);
}
else
{
code *c2 = genc1(CNIL,0x8B ^ (sz == 1),
modregxrm(2,s->Sreglsw,BPRM),FLconst,Poff + s->Soffset);
if (!I16 && sz == SHORTSIZE)
c2->Iflags |= CFopsize; // operand size
if (I64 && sz == REGSIZE)
c2->Irex |= REX_W;
if (!hasframe)
{ /* Convert to ESP relative address rather than EBP */
assert(!I16);
c2->Irm = modregxrm(2,s->Sreglsw,4);
c2->Isib = modregrm(0,4,SP);
c2->IEVpointer1 += EBPtoESP;
}
if (sz > REGSIZE)
{
assert(!(usedregs & mask[s->Sregmsw])); // bug 6189
usedregs |= mask[s->Sregmsw];
code *c3 = genc1(CNIL,0x8B,
modregxrm(2,s->Sregmsw,BPRM),FLconst,Poff + s->Soffset + REGSIZE);
if (I64)
c3->Irex |= REX_W;
if (!hasframe)
{ /* Convert to ESP relative address rather than EBP */
assert(!I16);
c3->Irm = modregxrm(2,s->Sregmsw,4);
c3->Isib = modregrm(0,4,SP);
c3->IEVpointer1 += EBPtoESP;
}
c2 = cat(c2,c3);
}
c = cat(c,c2);
}
}
}

/* Load arguments passed in registers into the varargs save area
* so they can be accessed by va_arg().
*/
Expand Down

0 comments on commit 6f8b4db

Please sign in to comment.