Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 595

Show
Ignore:
Timestamp:
08/03/10 08:49:16 (14 years ago)
Author:
walter
Message:

more XMM regs

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/dmd-1.x/src/backend/cgcod.c

    r579 r595  
    17821782#define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__) 
    17831783#endif 
    17841784{       regm_t r,s; 
    17851785        regm_t retregs; 
    17861786        unsigned reg; 
    17871787        unsigned msreg,lsreg; 
    17881788        int count; 
    17891789        unsigned size; 
    17901790 
    17911791#if 0 
    17921792//      if (pass == PASSfinal) 
    17931793        {   dbg_printf("allocreg %s,%d: regcon.mvar %s regcon.cse.mval %s msavereg %s *pretregs %s tym ", 
    17941794                file,line,regm_str(regcon.mvar),regm_str(regcon.cse.mval), 
    17951795                regm_str(msavereg),regm_str(*pretregs)); 
    17961796            WRTYxx(tym); 
    17971797            dbg_printf("\n"); 
    17981798        } 
    17991799#endif 
    18001800        tym = tybasic(tym); 
    18011801        size = tysize[tym]; 
    1802         *pretregs &= mES | allregs
     1802        *pretregs &= mES | allregs | XMMREGS
    18031803        retregs = *pretregs; 
    18041804        if ((retregs & regcon.mvar) == retregs) // if exactly in reg vars 
    18051805        { 
    18061806            if (size <= REGSIZE) 
    18071807            {   *preg = findreg(retregs); 
    18081808                assert(retregs == mask[*preg]); /* no more bits are set */ 
    18091809            } 
    18101810            else if (size <= 2 * REGSIZE) 
    18111811            {   *preg = findregmsw(retregs); 
    18121812                assert(retregs & mLSW); 
    18131813            } 
    18141814            else 
    18151815                assert(0); 
    18161816            return getregs(retregs); 
    18171817        } 
    18181818        count = 0; 
    18191819L1: 
    18201820        //printf("L1: allregs = x%x, *pretregs = x%x\n", allregs, *pretregs); 
    18211821        assert(++count < 10);           /* fail instead of hanging if blocked */ 
    18221822        s = retregs & mES; 
  • branches/dmd-1.x/src/backend/cgen.c

    r577 r595  
    4545void code_orflag(code *c,unsigned flag) 
    4646{ 
    4747    if (flag && c) 
    4848    {   while (c->next) 
    4949            c = c->next; 
    5050        c->Iflags |= flag; 
    5151    } 
    5252} 
    5353 
    5454/***************************** 
    5555 * Set rex bits on last code in list. 
    5656 */ 
    5757 
    5858void code_orrex(code *c,unsigned rex) 
    5959{ 
    6060    if (rex && c) 
    6161    {   while (c->next) 
    6262            c = c->next; 
    6363        c->Irex |= rex; 
    6464    } 
     65} 
     66 
     67/************************************** 
     68 * Set the opcode fields in cs. 
     69 * This is ridiculously complex, cs.Iop should 
     70 * just be an unsigned. 
     71 */ 
     72code *setOpcode(code *c, code *cs, unsigned op) 
     73{ 
     74    cs->Iflags = 0; 
     75    if (op > 0xFF) 
     76    { 
     77        switch (op & 0xFF0000) 
     78        { 
     79            case 0: 
     80                break; 
     81            case 0x660000: 
     82                cs->Iflags = CFopsize; 
     83                break; 
     84            case 0xF20000:                      // REPNE 
     85            case 0xF30000:                      // REP/REPE 
     86                c = gen1(c, op >> 16); 
     87                break; 
     88        } 
     89        cs->Iop = op >> 8; 
     90        cs->Iop2 = op & 0xFF; 
     91    } 
     92    else 
     93        cs->Iop = op; 
     94    return c; 
    6595} 
    6696 
    6797/***************************** 
    6898 * Concatenate two code lists together. Return pointer to result. 
    6999 */ 
    70100 
    71101#if TX86 && __INTSIZE == 4 && __SC__ 
    72102__declspec(naked) code * __pascal cat(code *c1,code *c2) 
    73103{ 
    74104    _asm 
    75105    { 
    76106        mov     EAX,c1-4[ESP] 
    77107        mov     ECX,c2-4[ESP] 
    78108        test    EAX,EAX 
    79109        jne     L6D 
    80110        mov     EAX,ECX 
    81111        ret     8 
    82112 
    83113L6D:    mov     EDX,EAX 
    84114        cmp     dword ptr [EAX],0 
     
    364394    {   cs.Iop = op >> 8; 
    365395        cs.Iop2 = op & 0xFF; 
    366396    } 
    367397    else 
    368398        cs.Iop = op; 
    369399    cs.Iea = ea; 
    370400    cs.Iflags = CFoff; 
    371401    cs.IFL2 = FLconst; 
    372402    cs.IEV2.Vsize_t = EV2; 
    373403    return gen(c,&cs); 
    374404} 
    375405 
    376406/***************** 
    377407 * Generate code. 
    378408 */ 
    379409 
    380410code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 
    381411{   code cs; 
    382412 
    383413    assert(FL1 < FLMAX); 
    384     assert(op < 256); 
    385     cs.Iop = op; 
     414    if (op > 0xFF) 
     415    { 
     416        c = setOpcode(c, &cs, op); 
     417        cs.Iflags |= CFoff; 
     418    } 
     419    else 
     420    {   cs.Iop = op; 
     421        cs.Iflags = CFoff; 
     422    } 
    386423    cs.Iea = ea; 
    387     cs.Iflags = CFoff; 
    388424    cs.IFL1 = FL1; 
    389425    cs.IEV1.Vsize_t = EV1; 
    390426    return gen(c,&cs); 
    391427} 
    392428 
    393429/***************** 
    394430 * Generate code. 
    395431 */ 
    396432 
    397433code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
    398434{   code cs; 
    399435 
    400436    assert(FL1 < FLMAX); 
    401437    assert(op < 256); 
    402438    cs.Iop = op; 
    403439    cs.Iea = ea; 
    404440    cs.Iflags = CFoff; 
    405441    cs.IFL1 = FL1; 
    406442    cs.IEV1.Vsize_t = EV1; 
    407443    assert(FL2 < FLMAX); 
  • branches/dmd-1.x/src/backend/cod1.c

    r592 r595  
    538538 
    539539/****************************** 
    540540 * Routine to aid in setting things up for gen(). 
    541541 * Look for common subexpression. 
    542542 * Can handle indirection operators, but not if they're common subs. 
    543543 * Input: 
    544544 *      e ->    elem where we get some of the data from 
    545545 *      cs ->   partially filled code to add 
    546546 *      op =    opcode 
    547547 *      reg =   reg field of (mod reg r/m) 
    548548 *      offset = data to be added to Voffset field 
    549549 *      keepmsk = mask of registers we must not destroy 
    550550 *      desmsk  = mask of registers destroyed by executing the instruction 
    551551 * Returns: 
    552552 *      pointer to code generated 
    553553 */ 
    554554 
    555555code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    556556        regm_t keepmsk,regm_t desmsk) 
    557557{ 
    558   code *c,*cg,*cd
     558  code *c,*cg,*cd,*cprefix
    559559 
    560560#ifdef DEBUG 
    561561  if (debugw) 
    562562    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 
    563563            e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 
    564564#endif 
    565565 
    566566  assert(e); 
    567567  cs->Iflags = 0; 
    568568  cs->Irex = 0; 
    569   cs->Iop = op
    570   if (!I16 && op >= 0x100)               // if 2 byte opcode 
    571   {     cs->Iop = op >> 8
    572         cs->Iop2 = op; 
    573   } 
     569  cprefix = NULL
     570  if (op > 0xFF)               // if 2 byte opcode 
     571        cprefix = setOpcode(NULL, cs, op)
     572  else 
     573        cs->Iop = op; 
    574574  tym_t tym = e->Ety; 
    575575  int sz = tysize(tym); 
    576576 
    577577  /* Determine if location we want to get is in a register. If so,      */ 
    578578  /* substitute the register for the EA.                                */ 
    579579  /* Note that operators don't go through this. CSE'd operators are     */ 
    580580  /* picked up by comsub().                                             */ 
    581581  if (e->Ecount &&                      /* if cse                       */ 
    582582      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    583583      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
    584584      (op != 0xFF || reg != 3) &&       /* and not CALLF MEM16          */ 
    585585      (op & 0xFFF8) != 0xD8)            // and not 8087 opcode 
    586586  { 
    587587        assert(!EOP(e));                /* can't handle this            */ 
    588588        regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 
    589589        if (sz > REGSIZE)               // value is in 2 or 4 registers 
    590590        { 
    591591                if (I16 && sz == 8)     // value is in 4 registers 
    592592                {       static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 
    593593                        rm &= rmask[offset >> 1]; 
     
    658658                code_orrex(cd, REX_W); 
    659659        } 
    660660        else if (reg == 6)                      // if DIV 
    661661        {   cd = genregs(cd,0x33,DX,DX);        // XOR DX,DX 
    662662            if (I64 && sz == 8) 
    663663                code_orrex(cd, REX_W); 
    664664        } 
    665665  } 
    666666 
    667667  // Eliminate MOV reg,reg 
    668668  if ((cs->Iop & 0xFC) == 0x88 && 
    669669      (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 
    670670  { 
    671671        unsigned r = cs->Irm & 7; 
    672672        if (cs->Irex & REX_B) 
    673673            r |= 8; 
    674674        if (r == reg) 
    675675            cs->Iop = NOP; 
    676676  } 
    677677 
    678   return cat4(c,cg,cd,gen(CNIL,cs)); 
     678  return cat4(c,cg,cd,gen(cprefix,cs)); 
    679679} 
    680680 
    681681/************************** 
    682682 * Get addressing mode. 
    683683 */ 
    684684 
    685685unsigned getaddrmode(regm_t idxregs) 
    686686{ 
    687687    unsigned mode; 
    688688 
    689689    if (I16) 
    690690    { 
    691691        mode =  (idxregs & mBX) ? modregrm(2,0,7) :     /* [BX] */ 
    692692                (idxregs & mDI) ? modregrm(2,0,5):      /* [DI] */ 
    693693                (idxregs & mSI) ? modregrm(2,0,4):      /* [SI] */ 
    694694                                  (assert(0),1); 
    695695    } 
    696696    else 
    697697    {   unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 
    698698        mode = modregrmx(2,0,reg); 
     
    36263626            if (tyfloating(tym))                // TYdouble or TYdouble_alias 
    36273627                gen2(ce,0xD1,modregrm(3,4,reg));        // SHL reg,1 
    36283628            c = cat(c,ce); 
    36293629 
    36303630            while ((i -= REGSIZE) >= 0) 
    36313631            { 
    36323632                c1 = loadea(e,&cs,0x0B,reg,i,regm,0);   // OR reg,data+i 
    36333633                if (i == 0) 
    36343634                    c1->Iflags |= CFpsw;                // need the flags on last OR 
    36353635                c = cat(c,c1); 
    36363636            } 
    36373637        } 
    36383638        else if (sz == LNGDBLSIZE)                      // TYldouble 
    36393639            return load87(e,0,pretregs,NULL,-1); 
    36403640        else 
    36413641            assert(0); 
    36423642        return c; 
    36433643  } 
    36443644  /* not for flags only */ 
    36453645  flags = *pretregs & mPSW;             /* save original                */ 
    3646   forregs = *pretregs & (mBP | ALLREGS | mES); 
     3646  forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 
    36473647  if (*pretregs & mSTACK) 
    36483648        forregs |= DOUBLEREGS; 
    36493649  if (e->Eoper == OPconst) 
    36503650  {     regm_t save; 
    36513651 
    36523652        if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,&reg)) 
    36533653            forregs = mask[reg]; 
    36543654 
    36553655        save = regcon.immed.mval; 
    36563656        c = allocreg(&forregs,&reg,tym);        /* allocate registers   */ 
    36573657        regcon.immed.mval = save;               // KLUDGE! 
    36583658        if (sz <= REGSIZE) 
    36593659        { 
    36603660            if (sz == 1) 
    36613661                flags |= 1; 
    36623662            else if (!I16 && sz == SHORTSIZE && 
    36633663                     !(mask[reg] & regcon.mvar) && 
    36643664                     !(config.flags4 & CFG4speed) 
    36653665                    ) 
    36663666                flags |= 2; 
     
    37443744                printf("forregs = x%x\n",forregs); 
    37453745        } 
    37463746#endif 
    37473747        assert(forregs & BYTEREGS); 
    37483748        if (!I16) 
    37493749            c = cat(c,loadea(e,&cs,0x8A,reg,0,0,0));    // MOV regL,data 
    37503750        else 
    37513751        {   nregm = tyuns(tym) ? BYTEREGS : mAX; 
    37523752            if (*pretregs & nregm) 
    37533753                nreg = reg;                     /* already allocated    */ 
    37543754            else 
    37553755                c = cat(c,allocreg(&nregm,&nreg,tym)); 
    37563756            ce = loadea(e,&cs,0x8A,nreg,0,0,0); /* MOV nregL,data       */ 
    37573757            c = cat(c,ce); 
    37583758            if (reg != nreg) 
    37593759            {   genmovreg(c,reg,nreg);          /* MOV reg,nreg         */ 
    37603760                cssave(e,mask[nreg],FALSE); 
    37613761            } 
    37623762        } 
    37633763    } 
     3764    else if (forregs & XMMREGS) 
     3765    { 
     3766        assert(sz == 4 || sz == 8);             // float or double 
     3767        unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 
     3768        ce = loadea(e,&cs,op,reg,0,RMload,0); // MOVSS/MOVSD reg,data 
     3769        c = cat(c,ce); 
     3770    } 
    37643771    else if (sz <= REGSIZE) 
    37653772    { 
    37663773        ce = loadea(e,&cs,0x8B,reg,0,RMload,0); // MOV reg,data 
    37673774        c = cat(c,ce); 
    37683775    } 
    37693776    else if (sz <= 2 * REGSIZE && forregs & mES) 
    37703777    { 
    37713778        ce = loadea(e,&cs,0xC4,reg,0,0,mES);    /* LES data             */ 
    37723779        c = cat(c,ce); 
    37733780    } 
    37743781    else if (sz <= 2 * REGSIZE) 
    37753782    { 
    37763783        if (I32 && sz == 8 && 
    37773784            (*pretregs & (mSTACK | mPSW)) == mSTACK) 
    37783785        {   int i; 
    37793786 
    37803787            assert(0); 
    37813788            /* Note that we allocreg(DOUBLEREGS) needlessly     */ 
    37823789            stackchanged = 1; 
    37833790            i = DOUBLESIZE - REGSIZE; 
  • branches/dmd-1.x/src/backend/cod3.c

    r589 r595  
    17471747            } 
    17481748            c = cat(c,c2); 
    17491749        } 
    17501750        else if (s->Sclass == SCfastpar) 
    17511751        {   unsigned preg = s->Spreg; 
    17521752 
    17531753            if (s->Sfl == FLreg) 
    17541754            {   // MOV reg,preg 
    17551755                c = genmovreg(c,s->Sreglsw,preg); 
    17561756                if (I64 && sz == 8) 
    17571757                    code_orrex(c, REX_W); 
    17581758            } 
    17591759            else if (s->Sflags & SFLdead || 
    17601760                (!anyiasm && !(s->Sflags & SFLread) && s->Sflags & SFLunambig && 
    17611761#if MARS 
    17621762                 // This variable has been reference by a nested function 
    17631763                 !(s->Stype->Tty & mTYvolatile) && 
    17641764#endif 
    17651765                 (config.flags4 & CFG4optimized || !config.fulltypes))) 
    17661766            { 
     1767                // Ignore it, as it is never referenced 
    17671768                ; 
    17681769            } 
    17691770            else 
    17701771            { 
    17711772                targ_size_t offset = Aoff + BPoff + s->Soffset; 
     1773                int op = 0x89;                  // MOV x[EBP],preg 
     1774                if (preg >= XMM0 && preg <= XMM15) 
     1775                { 
     1776                    if (sz == 8) 
     1777                        op = 0xF20F11;          // MOVSD x[EBP],preg 
     1778                    else 
     1779                    { 
     1780                        assert(sz == 4); 
     1781                        op = 0xF30F11;          // MOVSS x[EBP],preg 
     1782                    } 
     1783                } 
    17721784                if (hasframe) 
    17731785                { 
    17741786                    if (!(pushalloc && preg == pushallocreg)) 
    1775                     {   // MOV x[EBP],preg 
    1776                         c2 = genc1(CNIL,0x89, 
     1787                    { 
     1788                        // MOV x[EBP],preg 
     1789                        c2 = genc1(CNIL,op, 
    17771790                            modregxrm(2,preg,BPRM),FLconst, offset); 
     1791                        if (preg >= XMM0 && preg <= XMM15) 
     1792                        { 
     1793                        } 
     1794                        else 
     1795                        { 
    17781796//printf("%s Aoff = %d, BPoff = %d, Soffset = %d\n", s->Sident, Aoff, BPoff, s->Soffset); 
    1779 //                      if (offset & 2) 
    1780 //                          c2->Iflags |= CFopsize; 
    1781                         if (I64 && sz == 8) 
    1782                             code_orrex(c2, REX_W); 
     1797//                          if (offset & 2) 
     1798//                              c2->Iflags |= CFopsize; 
     1799                            if (I64 && sz == 8) 
     1800                                code_orrex(c2, REX_W); 
     1801                        } 
    17831802                        c = cat(c, c2); 
    17841803                    } 
    17851804                } 
    17861805                else 
    17871806                { 
    1788                     code *clast; 
    1789  
    17901807                    offset += EBPtoESP; 
    1791 #if 1 
    17921808                    if (!(pushalloc && preg == pushallocreg)) 
    1793 #else 
    1794                     if (offset == 0 && (clast = code_last(c)) != NULL && 
    1795                         (clast->Iop & 0xF8) == 0x50) 
    17961809                    { 
    1797                         clast->Iop = 0x50 + preg; 
    1798                     } 
    1799                     else 
    1800 #endif 
    1801                     {   // MOV offset[ESP],preg 
     1810                        // MOV offset[ESP],preg 
    18021811                        // BUG: byte size? 
    1803                         c2 = genc1(CNIL,0x89,modregxrm(2,preg,4),FLconst,offset); 
    1804                         c2->Isib = modregrm(0,4,SP); 
    1805                         if (I64 && sz == 8) 
    1806                             c2->Irex |= REX_W; 
    1807 //                      if (offset & 2) 
    1808 //                          c2->Iflags |= CFopsize; 
     1812                        c2 = genc1(CNIL,op, 
     1813                            (modregrm(0,4,SP) << 8) | 
     1814                            modregxrm(2,preg,4),FLconst,offset); 
     1815                        if (preg >= XMM0 && preg <= XMM15) 
     1816                        { 
     1817                        } 
     1818                        else 
     1819                        { 
     1820                            if (I64 && sz == 8) 
     1821                                c2->Irex |= REX_W; 
     1822//                          if (offset & 2) 
     1823//                              c2->Iflags |= CFopsize; 
     1824                        } 
    18091825                        c = cat(c,c2); 
    18101826                    } 
    18111827                } 
    18121828            } 
    18131829        } 
    18141830    } 
    18151831 
    18161832#if 0 && TARGET_LINUX 
    18171833    if (gotref) 
    18181834    {                                   // position independent reference 
    18191835        c = cat(c, cod3_load_got()); 
    18201836    } 
    18211837#endif 
    18221838 
    18231839    return c; 
    18241840} 
    18251841 
    18261842/******************************* 
    18271843 * Generate and return function epilog. 
    18281844 * Output: 
  • branches/dmd-1.x/src/backend/code.h

    r581 r595  
    3232#define SI      6 
    3333#define DI      7 
    3434 
    3535#define R8      8 
    3636#define R9      9 
    3737#define R10     10 
    3838#define R11     11 
    3939#define R12     12 
    4040#define R13     13 
    4141#define R14     14 
    4242#define R15     15 
    4343 
    4444#define XMM0    16 
    4545#define XMM1    17 
    4646#define XMM2    18 
    4747#define XMM3    19 
    4848#define XMM4    20 
    4949#define XMM5    21 
    5050#define XMM6    22 
    5151#define XMM7    23 
    52  
    53 /* There are also XMM8..XMM15 */ 
     52/* There are also XMM8..XMM14 */ 
     53#define XMM15   31 
     54 
    5455 
    5556#define ES      24 
    5657#define PSW     25 
    5758#define STACK   26      // top of stack 
    5859#define ST0     27      // 8087 top of stack register 
    5960#define ST01    28      // top two 8087 registers; for complex types 
    6061 
    6162#define NOREG   29     // no register 
    6263 
    6364#define AL      0 
    6465#define CL      1 
    6566#define DL      2 
    6667#define BL      3 
    6768#define AH      4 
    6869#define CH      5 
    6970#define DH      6 
    7071#define BH      7 
    7172 
    7273#define mAX     1 
    7374#define mCX     2 
     
    794795void iasm_term( void ); 
    795796regm_t iasm_regs( block *bp ); 
    796797 
    797798// nteh.c 
    798799code *nteh_prolog(void); 
    799800code *nteh_epilog(void); 
    800801void nteh_usevars(void); 
    801802void nteh_gentables(void); 
    802803code *nteh_setsp(int op); 
    803804code *nteh_filter(block *b); 
    804805void nteh_framehandler(symbol *); 
    805806code *nteh_gensindex(int); 
    806807#define GENSINDEXSIZE 7 
    807808code *nteh_monitor_prolog(Symbol *shandle); 
    808809code *nteh_monitor_epilog(regm_t retregs); 
    809810 
    810811// cgen.c 
    811812code *code_last(code *c); 
    812813void code_orflag(code *c,unsigned flag); 
    813814void code_orrex(code *c,unsigned rex); 
     815code *setOpcode(code *c, code *cs, unsigned op); 
    814816code * __pascal cat (code *c1 , code *c2 ); 
    815817code * cat3 (code *c1 , code *c2 , code *c3 ); 
    816818code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 ); 
    817819code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 ); 
    818820code *gen (code *c , code *cs ); 
    819821code *gen1 (code *c , unsigned op ); 
    820822code *gen2 (code *c , unsigned op , unsigned rm ); 
    821823code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib); 
    822824code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg ); 
    823825code *genpush (code *c , unsigned reg ); 
    824826code *genpop (code *c , unsigned reg ); 
    825827code *gentstreg (code *c , unsigned reg ); 
    826828code *genasm (code *c , char *s , unsigned slen ); 
    827829code *genmovreg (code *c , unsigned to , unsigned from ); 
    828830code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ ); 
    829831code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si ); 
    830832code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s ); 
    831833code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 ); 
    832834code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 ); 
    833835code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 ); 
  • trunk/src/backend/cgcod.c

    r579 r595  
    17821782#define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__) 
    17831783#endif 
    17841784{       regm_t r,s; 
    17851785        regm_t retregs; 
    17861786        unsigned reg; 
    17871787        unsigned msreg,lsreg; 
    17881788        int count; 
    17891789        unsigned size; 
    17901790 
    17911791#if 0 
    17921792//      if (pass == PASSfinal) 
    17931793        {   dbg_printf("allocreg %s,%d: regcon.mvar %s regcon.cse.mval %s msavereg %s *pretregs %s tym ", 
    17941794                file,line,regm_str(regcon.mvar),regm_str(regcon.cse.mval), 
    17951795                regm_str(msavereg),regm_str(*pretregs)); 
    17961796            WRTYxx(tym); 
    17971797            dbg_printf("\n"); 
    17981798        } 
    17991799#endif 
    18001800        tym = tybasic(tym); 
    18011801        size = tysize[tym]; 
    1802         *pretregs &= mES | allregs
     1802        *pretregs &= mES | allregs | XMMREGS
    18031803        retregs = *pretregs; 
    18041804        if ((retregs & regcon.mvar) == retregs) // if exactly in reg vars 
    18051805        { 
    18061806            if (size <= REGSIZE) 
    18071807            {   *preg = findreg(retregs); 
    18081808                assert(retregs == mask[*preg]); /* no more bits are set */ 
    18091809            } 
    18101810            else if (size <= 2 * REGSIZE) 
    18111811            {   *preg = findregmsw(retregs); 
    18121812                assert(retregs & mLSW); 
    18131813            } 
    18141814            else 
    18151815                assert(0); 
    18161816            return getregs(retregs); 
    18171817        } 
    18181818        count = 0; 
    18191819L1: 
    18201820        //printf("L1: allregs = x%x, *pretregs = x%x\n", allregs, *pretregs); 
    18211821        assert(++count < 10);           /* fail instead of hanging if blocked */ 
    18221822        s = retregs & mES; 
  • trunk/src/backend/cgen.c

    r577 r595  
    4545void code_orflag(code *c,unsigned flag) 
    4646{ 
    4747    if (flag && c) 
    4848    {   while (c->next) 
    4949            c = c->next; 
    5050        c->Iflags |= flag; 
    5151    } 
    5252} 
    5353 
    5454/***************************** 
    5555 * Set rex bits on last code in list. 
    5656 */ 
    5757 
    5858void code_orrex(code *c,unsigned rex) 
    5959{ 
    6060    if (rex && c) 
    6161    {   while (c->next) 
    6262            c = c->next; 
    6363        c->Irex |= rex; 
    6464    } 
     65} 
     66 
     67/************************************** 
     68 * Set the opcode fields in cs. 
     69 * This is ridiculously complex, cs.Iop should 
     70 * just be an unsigned. 
     71 */ 
     72code *setOpcode(code *c, code *cs, unsigned op) 
     73{ 
     74    cs->Iflags = 0; 
     75    if (op > 0xFF) 
     76    { 
     77        switch (op & 0xFF0000) 
     78        { 
     79            case 0: 
     80                break; 
     81            case 0x660000: 
     82                cs->Iflags = CFopsize; 
     83                break; 
     84            case 0xF20000:                      // REPNE 
     85            case 0xF30000:                      // REP/REPE 
     86                c = gen1(c, op >> 16); 
     87                break; 
     88        } 
     89        cs->Iop = op >> 8; 
     90        cs->Iop2 = op & 0xFF; 
     91    } 
     92    else 
     93        cs->Iop = op; 
     94    return c; 
    6595} 
    6696 
    6797/***************************** 
    6898 * Concatenate two code lists together. Return pointer to result. 
    6999 */ 
    70100 
    71101#if TX86 && __INTSIZE == 4 && __SC__ 
    72102__declspec(naked) code * __pascal cat(code *c1,code *c2) 
    73103{ 
    74104    _asm 
    75105    { 
    76106        mov     EAX,c1-4[ESP] 
    77107        mov     ECX,c2-4[ESP] 
    78108        test    EAX,EAX 
    79109        jne     L6D 
    80110        mov     EAX,ECX 
    81111        ret     8 
    82112 
    83113L6D:    mov     EDX,EAX 
    84114        cmp     dword ptr [EAX],0 
     
    364394    {   cs.Iop = op >> 8; 
    365395        cs.Iop2 = op & 0xFF; 
    366396    } 
    367397    else 
    368398        cs.Iop = op; 
    369399    cs.Iea = ea; 
    370400    cs.Iflags = CFoff; 
    371401    cs.IFL2 = FLconst; 
    372402    cs.IEV2.Vsize_t = EV2; 
    373403    return gen(c,&cs); 
    374404} 
    375405 
    376406/***************** 
    377407 * Generate code. 
    378408 */ 
    379409 
    380410code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 
    381411{   code cs; 
    382412 
    383413    assert(FL1 < FLMAX); 
    384     assert(op < 256); 
    385     cs.Iop = op; 
     414    if (op > 0xFF) 
     415    { 
     416        c = setOpcode(c, &cs, op); 
     417        cs.Iflags |= CFoff; 
     418    } 
     419    else 
     420    {   cs.Iop = op; 
     421        cs.Iflags = CFoff; 
     422    } 
    386423    cs.Iea = ea; 
    387     cs.Iflags = CFoff; 
    388424    cs.IFL1 = FL1; 
    389425    cs.IEV1.Vsize_t = EV1; 
    390426    return gen(c,&cs); 
    391427} 
    392428 
    393429/***************** 
    394430 * Generate code. 
    395431 */ 
    396432 
    397433code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
    398434{   code cs; 
    399435 
    400436    assert(FL1 < FLMAX); 
    401437    assert(op < 256); 
    402438    cs.Iop = op; 
    403439    cs.Iea = ea; 
    404440    cs.Iflags = CFoff; 
    405441    cs.IFL1 = FL1; 
    406442    cs.IEV1.Vsize_t = EV1; 
    407443    assert(FL2 < FLMAX); 
  • trunk/src/backend/cod1.c

    r592 r595  
    538538 
    539539/****************************** 
    540540 * Routine to aid in setting things up for gen(). 
    541541 * Look for common subexpression. 
    542542 * Can handle indirection operators, but not if they're common subs. 
    543543 * Input: 
    544544 *      e ->    elem where we get some of the data from 
    545545 *      cs ->   partially filled code to add 
    546546 *      op =    opcode 
    547547 *      reg =   reg field of (mod reg r/m) 
    548548 *      offset = data to be added to Voffset field 
    549549 *      keepmsk = mask of registers we must not destroy 
    550550 *      desmsk  = mask of registers destroyed by executing the instruction 
    551551 * Returns: 
    552552 *      pointer to code generated 
    553553 */ 
    554554 
    555555code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    556556        regm_t keepmsk,regm_t desmsk) 
    557557{ 
    558   code *c,*cg,*cd
     558  code *c,*cg,*cd,*cprefix
    559559 
    560560#ifdef DEBUG 
    561561  if (debugw) 
    562562    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 
    563563            e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 
    564564#endif 
    565565 
    566566  assert(e); 
    567567  cs->Iflags = 0; 
    568568  cs->Irex = 0; 
    569   cs->Iop = op
    570   if (!I16 && op >= 0x100)               // if 2 byte opcode 
    571   {     cs->Iop = op >> 8
    572         cs->Iop2 = op; 
    573   } 
     569  cprefix = NULL
     570  if (op > 0xFF)               // if 2 byte opcode 
     571        cprefix = setOpcode(NULL, cs, op)
     572  else 
     573        cs->Iop = op; 
    574574  tym_t tym = e->Ety; 
    575575  int sz = tysize(tym); 
    576576 
    577577  /* Determine if location we want to get is in a register. If so,      */ 
    578578  /* substitute the register for the EA.                                */ 
    579579  /* Note that operators don't go through this. CSE'd operators are     */ 
    580580  /* picked up by comsub().                                             */ 
    581581  if (e->Ecount &&                      /* if cse                       */ 
    582582      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    583583      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
    584584      (op != 0xFF || reg != 3) &&       /* and not CALLF MEM16          */ 
    585585      (op & 0xFFF8) != 0xD8)            // and not 8087 opcode 
    586586  { 
    587587        assert(!EOP(e));                /* can't handle this            */ 
    588588        regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 
    589589        if (sz > REGSIZE)               // value is in 2 or 4 registers 
    590590        { 
    591591                if (I16 && sz == 8)     // value is in 4 registers 
    592592                {       static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 
    593593                        rm &= rmask[offset >> 1]; 
     
    658658                code_orrex(cd, REX_W); 
    659659        } 
    660660        else if (reg == 6)                      // if DIV 
    661661        {   cd = genregs(cd,0x33,DX,DX);        // XOR DX,DX 
    662662            if (I64 && sz == 8) 
    663663                code_orrex(cd, REX_W); 
    664664        } 
    665665  } 
    666666 
    667667  // Eliminate MOV reg,reg 
    668668  if ((cs->Iop & 0xFC) == 0x88 && 
    669669      (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 
    670670  { 
    671671        unsigned r = cs->Irm & 7; 
    672672        if (cs->Irex & REX_B) 
    673673            r |= 8; 
    674674        if (r == reg) 
    675675            cs->Iop = NOP; 
    676676  } 
    677677 
    678   return cat4(c,cg,cd,gen(CNIL,cs)); 
     678  return cat4(c,cg,cd,gen(cprefix,cs)); 
    679679} 
    680680 
    681681/************************** 
    682682 * Get addressing mode. 
    683683 */ 
    684684 
    685685unsigned getaddrmode(regm_t idxregs) 
    686686{ 
    687687    unsigned mode; 
    688688 
    689689    if (I16) 
    690690    { 
    691691        mode =  (idxregs & mBX) ? modregrm(2,0,7) :     /* [BX] */ 
    692692                (idxregs & mDI) ? modregrm(2,0,5):      /* [DI] */ 
    693693                (idxregs & mSI) ? modregrm(2,0,4):      /* [SI] */ 
    694694                                  (assert(0),1); 
    695695    } 
    696696    else 
    697697    {   unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 
    698698        mode = modregrmx(2,0,reg); 
     
    36263626            if (tyfloating(tym))                // TYdouble or TYdouble_alias 
    36273627                gen2(ce,0xD1,modregrm(3,4,reg));        // SHL reg,1 
    36283628            c = cat(c,ce); 
    36293629 
    36303630            while ((i -= REGSIZE) >= 0) 
    36313631            { 
    36323632                c1 = loadea(e,&cs,0x0B,reg,i,regm,0);   // OR reg,data+i 
    36333633                if (i == 0) 
    36343634                    c1->Iflags |= CFpsw;                // need the flags on last OR 
    36353635                c = cat(c,c1); 
    36363636            } 
    36373637        } 
    36383638        else if (sz == LNGDBLSIZE)                      // TYldouble 
    36393639            return load87(e,0,pretregs,NULL,-1); 
    36403640        else 
    36413641            assert(0); 
    36423642        return c; 
    36433643  } 
    36443644  /* not for flags only */ 
    36453645  flags = *pretregs & mPSW;             /* save original                */ 
    3646   forregs = *pretregs & (mBP | ALLREGS | mES); 
     3646  forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 
    36473647  if (*pretregs & mSTACK) 
    36483648        forregs |= DOUBLEREGS; 
    36493649  if (e->Eoper == OPconst) 
    36503650  {     regm_t save; 
    36513651 
    36523652        if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,&reg)) 
    36533653            forregs = mask[reg]; 
    36543654 
    36553655        save = regcon.immed.mval; 
    36563656        c = allocreg(&forregs,&reg,tym);        /* allocate registers   */ 
    36573657        regcon.immed.mval = save;               // KLUDGE! 
    36583658        if (sz <= REGSIZE) 
    36593659        { 
    36603660            if (sz == 1) 
    36613661                flags |= 1; 
    36623662            else if (!I16 && sz == SHORTSIZE && 
    36633663                     !(mask[reg] & regcon.mvar) && 
    36643664                     !(config.flags4 & CFG4speed) 
    36653665                    ) 
    36663666                flags |= 2; 
     
    37443744                printf("forregs = x%x\n",forregs); 
    37453745        } 
    37463746#endif 
    37473747        assert(forregs & BYTEREGS); 
    37483748        if (!I16) 
    37493749            c = cat(c,loadea(e,&cs,0x8A,reg,0,0,0));    // MOV regL,data 
    37503750        else 
    37513751        {   nregm = tyuns(tym) ? BYTEREGS : mAX; 
    37523752            if (*pretregs & nregm) 
    37533753                nreg = reg;                     /* already allocated    */ 
    37543754            else 
    37553755                c = cat(c,allocreg(&nregm,&nreg,tym)); 
    37563756            ce = loadea(e,&cs,0x8A,nreg,0,0,0); /* MOV nregL,data       */ 
    37573757            c = cat(c,ce); 
    37583758            if (reg != nreg) 
    37593759            {   genmovreg(c,reg,nreg);          /* MOV reg,nreg         */ 
    37603760                cssave(e,mask[nreg],FALSE); 
    37613761            } 
    37623762        } 
    37633763    } 
     3764    else if (forregs & XMMREGS) 
     3765    { 
     3766        assert(sz == 4 || sz == 8);             // float or double 
     3767        unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 
     3768        ce = loadea(e,&cs,op,reg,0,RMload,0); // MOVSS/MOVSD reg,data 
     3769        c = cat(c,ce); 
     3770    } 
    37643771    else if (sz <= REGSIZE) 
    37653772    { 
    37663773        ce = loadea(e,&cs,0x8B,reg,0,RMload,0); // MOV reg,data 
    37673774        c = cat(c,ce); 
    37683775    } 
    37693776    else if (sz <= 2 * REGSIZE && forregs & mES) 
    37703777    { 
    37713778        ce = loadea(e,&cs,0xC4,reg,0,0,mES);    /* LES data             */ 
    37723779        c = cat(c,ce); 
    37733780    } 
    37743781    else if (sz <= 2 * REGSIZE) 
    37753782    { 
    37763783        if (I32 && sz == 8 && 
    37773784            (*pretregs & (mSTACK | mPSW)) == mSTACK) 
    37783785        {   int i; 
    37793786 
    37803787            assert(0); 
    37813788            /* Note that we allocreg(DOUBLEREGS) needlessly     */ 
    37823789            stackchanged = 1; 
    37833790            i = DOUBLESIZE - REGSIZE; 
  • trunk/src/backend/cod3.c

    r589 r595  
    17471747            } 
    17481748            c = cat(c,c2); 
    17491749        } 
    17501750        else if (s->Sclass == SCfastpar) 
    17511751        {   unsigned preg = s->Spreg; 
    17521752 
    17531753            if (s->Sfl == FLreg) 
    17541754            {   // MOV reg,preg 
    17551755                c = genmovreg(c,s->Sreglsw,preg); 
    17561756                if (I64 && sz == 8) 
    17571757                    code_orrex(c, REX_W); 
    17581758            } 
    17591759            else if (s->Sflags & SFLdead || 
    17601760                (!anyiasm && !(s->Sflags & SFLread) && s->Sflags & SFLunambig && 
    17611761#if MARS 
    17621762                 // This variable has been reference by a nested function 
    17631763                 !(s->Stype->Tty & mTYvolatile) && 
    17641764#endif 
    17651765                 (config.flags4 & CFG4optimized || !config.fulltypes))) 
    17661766            { 
     1767                // Ignore it, as it is never referenced 
    17671768                ; 
    17681769            } 
    17691770            else 
    17701771            { 
    17711772                targ_size_t offset = Aoff + BPoff + s->Soffset; 
     1773                int op = 0x89;                  // MOV x[EBP],preg 
     1774                if (preg >= XMM0 && preg <= XMM15) 
     1775                { 
     1776                    if (sz == 8) 
     1777                        op = 0xF20F11;          // MOVSD x[EBP],preg 
     1778                    else 
     1779                    { 
     1780                        assert(sz == 4); 
     1781                        op = 0xF30F11;          // MOVSS x[EBP],preg 
     1782                    } 
     1783                } 
    17721784                if (hasframe) 
    17731785                { 
    17741786                    if (!(pushalloc && preg == pushallocreg)) 
    1775                     {   // MOV x[EBP],preg 
    1776                         c2 = genc1(CNIL,0x89, 
     1787                    { 
     1788                        // MOV x[EBP],preg 
     1789                        c2 = genc1(CNIL,op, 
    17771790                            modregxrm(2,preg,BPRM),FLconst, offset); 
     1791                        if (preg >= XMM0 && preg <= XMM15) 
     1792                        { 
     1793                        } 
     1794                        else 
     1795                        { 
    17781796//printf("%s Aoff = %d, BPoff = %d, Soffset = %d\n", s->Sident, Aoff, BPoff, s->Soffset); 
    1779 //                      if (offset & 2) 
    1780 //                          c2->Iflags |= CFopsize; 
    1781                         if (I64 && sz == 8) 
    1782                             code_orrex(c2, REX_W); 
     1797//                          if (offset & 2) 
     1798//                              c2->Iflags |= CFopsize; 
     1799                            if (I64 && sz == 8) 
     1800                                code_orrex(c2, REX_W); 
     1801                        } 
    17831802                        c = cat(c, c2); 
    17841803                    } 
    17851804                } 
    17861805                else 
    17871806                { 
    1788                     code *clast; 
    1789  
    17901807                    offset += EBPtoESP; 
    1791 #if 1 
    17921808                    if (!(pushalloc && preg == pushallocreg)) 
    1793 #else 
    1794                     if (offset == 0 && (clast = code_last(c)) != NULL && 
    1795                         (clast->Iop & 0xF8) == 0x50) 
    17961809                    { 
    1797                         clast->Iop = 0x50 + preg; 
    1798                     } 
    1799                     else 
    1800 #endif 
    1801                     {   // MOV offset[ESP],preg 
     1810                        // MOV offset[ESP],preg 
    18021811                        // BUG: byte size? 
    1803                         c2 = genc1(CNIL,0x89,modregxrm(2,preg,4),FLconst,offset); 
    1804                         c2->Isib = modregrm(0,4,SP); 
    1805                         if (I64 && sz == 8) 
    1806                             c2->Irex |= REX_W; 
    1807 //                      if (offset & 2) 
    1808 //                          c2->Iflags |= CFopsize; 
     1812                        c2 = genc1(CNIL,op, 
     1813                            (modregrm(0,4,SP) << 8) | 
     1814                            modregxrm(2,preg,4),FLconst,offset); 
     1815                        if (preg >= XMM0 && preg <= XMM15) 
     1816                        { 
     1817                        } 
     1818                        else 
     1819                        { 
     1820                            if (I64 && sz == 8) 
     1821                                c2->Irex |= REX_W; 
     1822//                          if (offset & 2) 
     1823//                              c2->Iflags |= CFopsize; 
     1824                        } 
    18091825                        c = cat(c,c2); 
    18101826                    } 
    18111827                } 
    18121828            } 
    18131829        } 
    18141830    } 
    18151831 
    18161832#if 0 && TARGET_LINUX 
    18171833    if (gotref) 
    18181834    {                                   // position independent reference 
    18191835        c = cat(c, cod3_load_got()); 
    18201836    } 
    18211837#endif 
    18221838 
    18231839    return c; 
    18241840} 
    18251841 
    18261842/******************************* 
    18271843 * Generate and return function epilog. 
    18281844 * Output: 
  • trunk/src/backend/code.h

    r581 r595  
    3232#define SI      6 
    3333#define DI      7 
    3434 
    3535#define R8      8 
    3636#define R9      9 
    3737#define R10     10 
    3838#define R11     11 
    3939#define R12     12 
    4040#define R13     13 
    4141#define R14     14 
    4242#define R15     15 
    4343 
    4444#define XMM0    16 
    4545#define XMM1    17 
    4646#define XMM2    18 
    4747#define XMM3    19 
    4848#define XMM4    20 
    4949#define XMM5    21 
    5050#define XMM6    22 
    5151#define XMM7    23 
    52  
    53 /* There are also XMM8..XMM15 */ 
     52/* There are also XMM8..XMM14 */ 
     53#define XMM15   31 
     54 
    5455 
    5556#define ES      24 
    5657#define PSW     25 
    5758#define STACK   26      // top of stack 
    5859#define ST0     27      // 8087 top of stack register 
    5960#define ST01    28      // top two 8087 registers; for complex types 
    6061 
    6162#define NOREG   29     // no register 
    6263 
    6364#define AL      0 
    6465#define CL      1 
    6566#define DL      2 
    6667#define BL      3 
    6768#define AH      4 
    6869#define CH      5 
    6970#define DH      6 
    7071#define BH      7 
    7172 
    7273#define mAX     1 
    7374#define mCX     2 
     
    794795void iasm_term( void ); 
    795796regm_t iasm_regs( block *bp ); 
    796797 
    797798// nteh.c 
    798799code *nteh_prolog(void); 
    799800code *nteh_epilog(void); 
    800801void nteh_usevars(void); 
    801802void nteh_gentables(void); 
    802803code *nteh_setsp(int op); 
    803804code *nteh_filter(block *b); 
    804805void nteh_framehandler(symbol *); 
    805806code *nteh_gensindex(int); 
    806807#define GENSINDEXSIZE 7 
    807808code *nteh_monitor_prolog(Symbol *shandle); 
    808809code *nteh_monitor_epilog(regm_t retregs); 
    809810 
    810811// cgen.c 
    811812code *code_last(code *c); 
    812813void code_orflag(code *c,unsigned flag); 
    813814void code_orrex(code *c,unsigned rex); 
     815code *setOpcode(code *c, code *cs, unsigned op); 
    814816code * __pascal cat (code *c1 , code *c2 ); 
    815817code * cat3 (code *c1 , code *c2 , code *c3 ); 
    816818code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 ); 
    817819code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 ); 
    818820code *gen (code *c , code *cs ); 
    819821code *gen1 (code *c , unsigned op ); 
    820822code *gen2 (code *c , unsigned op , unsigned rm ); 
    821823code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib); 
    822824code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg ); 
    823825code *genpush (code *c , unsigned reg ); 
    824826code *genpop (code *c , unsigned reg ); 
    825827code *gentstreg (code *c , unsigned reg ); 
    826828code *genasm (code *c , char *s , unsigned slen ); 
    827829code *genmovreg (code *c , unsigned to , unsigned from ); 
    828830code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ ); 
    829831code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si ); 
    830832code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s ); 
    831833code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 ); 
    832834code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 ); 
    833835code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 );