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

Changeset 577

Show
Ignore:
Timestamp:
07/13/10 20:22:22 (14 years ago)
Author:
walter
Message:

more 64

Files:

Legend:

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

    r569 r577  
    542542#define LARGECODE       (config.memmodel & 5) 
    543543 
    544544#define Smodel 0        /* 64k code, 64k data           */ 
    545545#define Mmodel 1        /* large code, 64k data         */ 
    546546#define Cmodel 2        /* 64k code, large data         */ 
    547547#define Lmodel 3        /* large code, large data       */ 
    548548#define Vmodel 4        /* large code, large data, vcm  */ 
    549549#define MEMMODELS 5     /* number of memory models      */ 
    550550#endif 
    551551 
    552552/* Segments     */ 
    553553#define CODE    1       /* code segment                 */ 
    554554#define DATA    2       /* initialized data             */ 
    555555#define CDATA   3       /* constant data                */ 
    556556#define UDATA   4       /* uninitialized data           */ 
    557557#define UNKNOWN 0x7FFF  // unknown segment 
    558558#define DGROUPIDX 1     /* group index of DGROUP        */ 
    559559 
    560560#define KEEPBITFIELDS 0 /* 0 means code generator cannot handle bit fields, */ 
    561561                        /* so replace them with shifts and masks        */ 
    562  
    563 #if TARGET_OSX 
    564 #define STACKALIGN      16 
    565 #else 
    566 #define STACKALIGN      0 
    567 #endif 
    568562 
    569563#define REGMAX  29      // registers are numbered 0..10 
    570564 
    571565typedef unsigned        tym_t;          // data type big enough for type masks 
    572566typedef int             SYMIDX;         // symbol table index 
    573567 
    574568#if 0 
    575569#if defined(__DMC__) && __DMC__ < 0x81e 
    576570typedef int bool; 
    577571#endif 
    578572#define bool int 
    579573#endif 
    580574 
    581575#define _chkstack()     (void)0 
    582576 
    583577/* For 32 bit compilations, we don't need far keyword   */ 
    584578#if 1 
    585579#define far 
    586580#define _far 
    587581#define __far 
  • branches/dmd-1.x/src/backend/cg87.c

    r569 r577  
    11// Copyright (C) 1987-1995 by Symantec 
    2 // Copyright (C) 2000-2009 by Digital Mars 
     2// Copyright (C) 2000-2010 by Digital Mars 
    33// All Rights Reserved 
    44// http://www.digitalmars.com 
    55// Written by Walter Bright 
    66/* 
    77 * This source file is made available for personal use 
    88 * only. The license is in /dmd/src/dmd/backendlicense.txt 
    99 * or /dm/src/dmd/backendlicense.txt 
    1010 * For any other uses, please contact Digital Mars. 
    1111 */ 
    1212 
    1313#if !SPP 
    1414 
    1515#include        <stdio.h> 
    1616#include        <string.h> 
    1717#include        <time.h> 
    1818#include        <math.h> 
    1919#include        "cc.h" 
    2020#include        "el.h" 
    2121#include        "oper.h" 
    2222#include        "code.h" 
     
    8080/********************************** 
    8181 * When we need to temporarilly save 8087 registers, we record information 
    8282 * about the save into an array of NDP structs: 
    8383 */ 
    8484 
    8585NDP *NDP::save = NULL; 
    8686int NDP::savemax = 0;           /* # of entries in NDP::save[]          */ 
    8787int NDP::savetop = 0;           /* # of entries used in NDP::save[]     */ 
    8888 
    8989#ifdef DEBUG 
    9090#define NDPSAVEINC 2            /* flush reallocation bugs              */ 
    9191#else 
    9292#define NDPSAVEINC 8            /* allocation chunk sizes               */ 
    9393#endif 
    9494 
    9595/**************************************** 
    9696 * Store/load to ndp save location i 
    9797 */ 
    9898 
    9999code *ndp_fstp(code *c, int i, tym_t ty) 
    100 { 
     100{   unsigned grex = I64 ? (REX_W << 16) : 0; 
    101101    switch (tybasic(ty)) 
    102102    { 
    103103        case TYfloat: 
    104104        case TYifloat: 
    105105        case TYcfloat: 
    106             c = genc1(c,0xD9,modregrm(2,3,BPRM),FLndp,i); // FSTP m32real i[BP] 
     106            c = genc1(c,0xD9,grex | modregrm(2,3,BPRM),FLndp,i); // FSTP m32real i[BP] 
    107107            break; 
    108108 
    109109        case TYdouble: 
    110110        case TYdouble_alias: 
    111111        case TYidouble: 
    112112        case TYcdouble: 
    113             c = genc1(c,0xDD,modregrm(2,3,BPRM),FLndp,i); // FSTP m64real i[BP] 
     113            c = genc1(c,0xDD,grex | modregrm(2,3,BPRM),FLndp,i); // FSTP m64real i[BP] 
    114114            break; 
    115115 
    116116        case TYldouble: 
    117117        case TYildouble: 
    118118        case TYcldouble: 
    119             c = genc1(c,0xDB,modregrm(2,7,BPRM),FLndp,i); // FSTP m80real i[BP] 
     119            c = genc1(c,0xDB,grex | modregrm(2,7,BPRM),FLndp,i); // FSTP m80real i[BP] 
    120120            break; 
    121121 
    122122        default: 
    123123            assert(0); 
    124124    } 
    125125    return c; 
    126126} 
    127127 
    128128code *ndp_fld(code *c, int i, tym_t ty) 
    129 { 
     129{   unsigned grex = I64 ? (REX_W << 16) : 0; 
    130130    switch (tybasic(ty)) 
    131131    { 
    132132        case TYfloat: 
    133133        case TYifloat: 
    134134        case TYcfloat: 
    135             c = genc1(c,0xD9,modregrm(2,0,BPRM),FLndp,i); 
     135            c = genc1(c,0xD9,grex | modregrm(2,0,BPRM),FLndp,i); 
    136136            break; 
    137137 
    138138        case TYdouble: 
    139139        case TYdouble_alias: 
    140140        case TYidouble: 
    141141        case TYcdouble: 
    142             c = genc1(c,0xDD,modregrm(2,0,BPRM),FLndp,i); 
     142            c = genc1(c,0xDD,grex | modregrm(2,0,BPRM),FLndp,i); 
    143143            break; 
    144144 
    145145        case TYldouble: 
    146146        case TYildouble: 
    147147        case TYcldouble: 
    148             c = genc1(c,0xDB,modregrm(2,5,BPRM),FLndp,i); // FLD m80real i[BP] 
     148            c = genc1(c,0xDB,grex | modregrm(2,5,BPRM),FLndp,i); // FLD m80real i[BP] 
    149149            break; 
    150150 
    151151        default: 
    152152            assert(0); 
    153153    } 
    154154    return c; 
    155155} 
    156156 
    157157/************************** 
    158158 * Return index of empty slot in NDP::save[]. 
    159159 */ 
    160160 
    161161STATIC int getemptyslot() 
    162162{       int i; 
    163163 
    164164        for (i = 0; i < NDP::savemax; i++) 
    165165                if (NDP::save[i].e == NULL) 
    166166                        goto L1; 
    167167        /* Out of room, reallocate NDP::save[]  */ 
    168168        NDP::save = (NDP *)mem_realloc(NDP::save, 
     
    428428            break; 
    429429        } 
    430430        if (_8087elems[i].e == e && 
    431431            _8087elems[i].offset == offset) 
    432432        {   //printf("cse found %d\n",i); 
    433433            //elem_print(e); 
    434434            break; 
    435435        } 
    436436    } 
    437437    return i; 
    438438} 
    439439 
    440440/************************************* 
    441441 * Reload common subexpression. 
    442442 */ 
    443443 
    444444code *comsub87(elem *e,regm_t *pretregs) 
    445445{   code *c; 
    446446 
    447447    // Look on 8087 stack 
    448     int i; 
    449  
    450     i = cse_get(e, 0); 
     448    int i = cse_get(e, 0); 
    451449 
    452450    if (tycomplex(e->Ety)) 
    453     {   unsigned sz; 
    454         int j; 
    455  
    456         sz = tysize(e->Ety); 
    457         j = cse_get(e, sz / 2); 
     451    { 
     452        unsigned sz = tysize(e->Ety); 
     453        int j = cse_get(e, sz / 2); 
    458454        if (i >= 0 && j >= 0) 
    459455        { 
    460456            c = push87(); 
    461457            c = cat(c, push87()); 
    462458            c = genf2(c,0xD9,0xC0 + i);         // FLD ST(i) 
    463459            c = genf2(c,0xD9,0xC0 + j + 1);     // FLD ST(j + 1) 
    464460            c = cat(c,fixresult_complex87(e,mST01,pretregs)); 
    465461        } 
    466462        else 
    467463            // Reload 
    468464            c = loaddata(e,pretregs); 
    469465    } 
    470466    else 
    471467    { 
    472468        if (i >= 0) 
    473469        { 
    474470            c = push87(); 
    475471            c = genf2(c,0xD9,0xC0 + i); // FLD ST(i) 
    476472            c = cat(c,fixresult(e,mST0,pretregs)); 
    477473        } 
    478474        else 
    479475            // Reload 
    480476            c = loaddata(e,pretregs); 
    481477    } 
    482478 
    483479    freenode(e); 
    484480    return c; 
    485481} 
    486482 
    487483 
    488484/************************** 
    489485 * Generate code to deal with floatreg. 
    490486 */ 
    491487 
    492488code * genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset) 
    493489{ 
    494490        floatreg = TRUE; 
    495491        reflocal = TRUE; 
    496492        if ((opcode & 0xF8) == 0xD8) 
    497493            c = genfwait(c); 
    498         return genc1(c,opcode,modregrm(2,reg,BPRM),FLfltreg,offset); 
     494        unsigned grex = I64 ? (REX_W << 16) : 0; 
     495        return genc1(c,opcode,grex | modregxrm(2,reg,BPRM),FLfltreg,offset); 
    499496} 
    500497 
    501498/******************************* 
    502499 * Decide if we need to gen an FWAIT. 
    503500 */ 
    504501 
    505502code *genfwait(code *c) 
    506503{ 
    507504    if (ADDFWAIT()) 
    508505        c = gen1(c,FWAIT); 
    509506    return c; 
    510507} 
    511508 
    512509/*************************************** 
    513510 * Generate floating point instruction. 
    514511 */ 
    515512 
    516513STATIC code * genf2(code *c,unsigned op,unsigned rm) 
    517514{ 
    518515    return gen2(genfwait(c),op,rm); 
     
    743740    tym_t tym; 
    744741    code *c1,*c2; 
    745742    unsigned sz; 
    746743 
    747744    //printf("fixresult87(e = %p, retregs = x%x, *pretregs = x%x)\n", e,retregs,*pretregs); 
    748745    //printf("fixresult87(e = %p, retregs = %s, *pretregs = %s)\n", e,regm_str(retregs),regm_str(*pretregs)); 
    749746    assert(!*pretregs || retregs); 
    750747    c1 = CNIL; 
    751748    c2 = CNIL; 
    752749    tym = tybasic(e->Ety); 
    753750    sz = tysize[tym]; 
    754751    //printf("tym = x%x, sz = %d\n", tym, sz); 
    755752 
    756753    if (*pretregs & mST01) 
    757754        return fixresult_complex87(e, retregs, pretregs); 
    758755 
    759756    /* if retregs needs to be transferred into the 8087 */ 
    760757    if (*pretregs & mST0 && retregs & (mBP | ALLREGS)) 
    761758    { 
    762759        assert(sz <= DOUBLESIZE); 
    763         if (I32
     760        if (!I16
    764761        { 
    765762 
    766763            if (*pretregs & mPSW) 
    767764            {   // Set flags 
    768                 regm_t r; 
    769  
    770                 r = retregs | mPSW; 
     765                regm_t r = retregs | mPSW; 
    771766                c1 = fixresult(e,retregs,&r); 
    772767            } 
    773768            c2 = push87(); 
    774             if (sz == REGSIZE) 
    775             {   unsigned reg; 
    776  
    777                 reg = findreg(retregs); 
     769            if (sz == REGSIZE || (I64 && sz == 4)) 
     770            { 
     771                unsigned reg = findreg(retregs); 
    778772                c2 = genfltreg(c2,0x89,reg,0);          // MOV fltreg,reg 
    779773                genfltreg(c2,0xD9,0,0);                 // FLD float ptr fltreg 
    780774            } 
    781775            else 
    782776            {   unsigned msreg,lsreg; 
    783777 
    784778                msreg = findregmsw(retregs); 
    785779                lsreg = findreglsw(retregs); 
    786780                c2 = genfltreg(c2,0x89,lsreg,0);        // MOV fltreg,lsreg 
    787781                genfltreg(c2,0x89,msreg,4);             // MOV fltreg+4,msreg 
    788782                genfltreg(c2,0xDD,0,0);                 // FLD double ptr fltreg 
    789783            } 
    790784        } 
    791785        else 
    792786        { 
    793787            regm = (sz == FLOATSIZE) ? FLOATREGS : DOUBLEREGS; 
    794788            regm |= *pretregs & mPSW; 
    795789            c1 = fixresult(e,retregs,&regm); 
    796790            regm = 0;           // don't worry about result from CLIBxxx 
    797791            c2 = callclib(e, 
    798792                    ((sz == FLOATSIZE) ? CLIBfltto87 : CLIBdblto87), 
    799793                    &regm,0); 
    800794        } 
    801795    } 
    802796    else if (*pretregs & (mBP | ALLREGS) && retregs & mST0) 
    803797    {   unsigned mf; 
    804798        unsigned reg; 
    805799 
    806800        assert(sz <= DOUBLESIZE); 
    807801        mf = (sz == FLOATSIZE) ? MFfloat : MFdouble; 
    808802        if (*pretregs & mPSW && !(retregs & mPSW)) 
    809803                c1 = genftst(c1,e,0); 
    810804        /* FSTP floatreg        */ 
    811805        pop87(); 
    812806        c1 = genfltreg(c1,ESC(mf,1),3,0); 
    813807        genfwait(c1); 
    814808        c2 = allocreg(pretregs,&reg,(sz == FLOATSIZE) ? TYfloat : TYdouble); 
    815809        if (sz == FLOATSIZE) 
    816810        { 
    817             if (I32
     811            if (!I16
    818812                c2 = genfltreg(c2,0x8B,reg,0); 
    819813            else 
    820814            {   c2 = genfltreg(c2,0x8B,reg,REGSIZE); 
    821815                genfltreg(c2,0x8B,findreglsw(*pretregs),0); 
    822816            } 
    823817        } 
    824818        else 
    825819        { 
    826             if (I32
     820            if (!I16
    827821            {   c2 = genfltreg(c2,0x8B,reg,REGSIZE); 
    828822                genfltreg(c2,0x8B,findreglsw(*pretregs),0); 
    829823            } 
    830824            else 
    831825            {   c2 = genfltreg(c2,0x8B,AX,6); 
    832826                genfltreg(c2,0x8B,BX,4); 
    833827                genfltreg(c2,0x8B,CX,2); 
    834828                genfltreg(c2,0x8B,DX,0); 
    835829            } 
    836830        } 
    837831    } 
    838832    else if (*pretregs == 0 && retregs == mST0) 
    839833    { 
    840834        c1 = genf2(c1,0xDD,modregrm(3,3,0));    // FPOP 
    841835        pop87(); 
    842836    } 
    843837    else 
    844838    {   if (*pretregs & mPSW) 
    845839        {   if (!(retregs & mPSW)) 
    846840            {   assert(retregs & mST0); 
     
    13821376            (e2->E1->Eoper == OPs32_d || e2->E1->Eoper == OPs64_d || e2->E1->Eoper == OPs16_d) && 
    13831377            e2->E1->E1->Eoper == OPvar 
    13841378          ) || 
    13851379          ((e2oper == OPs32_d || e2oper == OPs64_d || e2oper == OPs16_d) && 
    13861380            e2->E1->Eoper == OPvar 
    13871381          ) 
    13881382         ) 
    13891383        ) 
    13901384       ) 
    13911385    {   // Reverse order of evaluation 
    13921386        e1 = e->E2; 
    13931387        e2 = e->E1; 
    13941388        op = oprev[op + 1]; 
    13951389        reverse ^= 1; 
    13961390    } 
    13971391 
    13981392    c1 = codelem(e1,&retregs,FALSE); 
    13991393    note87(e1,0,0); 
    14001394 
    14011395    if (config.flags4 & CFG4fdivcall && e->Eoper == OPdiv) 
    1402     {   regm_t retregs; 
    1403  
    1404         retregs = mST0; 
     1396    { 
     1397        regm_t retregs = mST0; 
    14051398        c2 = load87(e2,0,&retregs,e1,-1); 
    14061399        c2 = cat(c2,makesure87(e1,0,1,0)); 
    14071400        if (op == 7)                    // if reverse divide 
    14081401            c2 = genf2(c2,0xD9,0xC8 + 1);       // FXCH ST(1) 
    14091402        c2 = cat(c2,callclib(e,CLIBfdiv87,&retregs,0)); 
    14101403        pop87(); 
    14111404        resregm = mST0; 
    14121405        freenode(e2); 
    14131406        c4 = fixresult87(e,resregm,pretregs); 
    14141407    } 
    14151408    else if (e->Eoper == OPmod) 
    14161409    { 
    14171410        /* 
    14181411         *              fld     tbyte ptr y 
    14191412         *              fld     tbyte ptr x             // ST = x, ST1 = y 
    14201413         *      FM1:    // We don't use fprem1 because for some inexplicable 
    14211414         *              // reason we get -5 when we do _modulo(15, 10) 
    14221415         *              fprem                           // ST = ST % ST1 
    14231416         *              fstsw   word ptr sw 
    14241417         *              fwait 
    14251418         *              mov     AH,byte ptr sw+1        // get msb of status word in AH 
    14261419         *              sahf                            // transfer to flags 
    14271420         *              jp      FM1                     // continue till ST < ST1 
    14281421         *              fstp    ST(1)                   // leave remainder on stack 
    14291422         */ 
    1430         regm_t retregs; 
    1431  
    1432         retregs = mST0; 
     1423        regm_t retregs = mST0; 
    14331424        c2 = load87(e2,0,&retregs,e1,-1); 
    14341425        c2 = cat(c2,makesure87(e1,0,1,0));      // now have x,y on stack; need y,x 
    14351426        if (!reverse)                           // if not reverse modulo 
    14361427            c2 = genf2(c2,0xD9,0xC8 + 1);       // FXCH ST(1) 
    14371428 
    14381429        c3 = gen2(NULL, 0xD9, 0xF8);            // FM1: FPREM 
    14391430        c3 = cg87_87topsw(c3); 
    14401431        c3 = genjmp(c3, JP, FLcode, (block *)c3); // JP FM1 
    14411432        c3 = genf2(c3,0xDD,0xD8 + 1);           // FSTP ST(1) 
    14421433 
    14431434        pop87(); 
    14441435        resregm = mST0; 
    14451436        freenode(e2); 
    14461437        c4 = fixresult87(e,resregm,pretregs); 
    14471438    } 
    14481439    else 
    14491440    {   c2 = load87(e2,0,pretregs,e1,op); 
    14501441        freenode(e2); 
    14511442    } 
    14521443    if (*pretregs & mST0) 
     
    15931584                            break; 
    15941585                    } 
    15951586                    note87(e,0,0); 
    15961587                } 
    15971588                break; 
    15981589            case OPd_f: 
    15991590            case OPf_d: 
    16001591            case OPd_ld: 
    16011592                mf1 = (tybasic(e->E1->Ety) == TYfloat || tybasic(e->E1->Ety) == TYifloat) 
    16021593                        ? MFfloat : MFdouble; 
    16031594                if (op != -1 && stackused) 
    16041595                    note87(eleft,eoffset,0);    // don't trash this value 
    16051596                if (e->E1->Eoper == OPvar || e->E1->Eoper == OPind) 
    16061597                { 
    16071598#if 1 
    16081599                L4: 
    16091600                    c = getlvalue(&cs,e->E1,0); 
    16101601                    cs.Iop = ESC(mf1,0); 
    16111602                    if (ADDFWAIT()) 
    16121603                        cs.Iflags |= CFwait; 
    1613                     if (I32
     1604                    if (!I16
    16141605                        cs.Iflags &= ~CFopsize; 
    16151606                    if (op != -1) 
    16161607                    {   cs.Irm |= modregrm(0,op,0); 
    16171608                        c = cat(c,makesure87(eleft,eoffset,0,0)); 
    16181609                    } 
    16191610                    else 
    16201611                    {   cs.Iop |= 1; 
    16211612                        c = cat(c,push87()); 
    16221613                    } 
    16231614                    c = gen(c,&cs);                     /* FLD / Fop    */ 
    16241615#else 
    16251616                    c = loadea(e->E1,&cs,ESC(mf1,1),0,0,0,0); /* FLD e->E1 */ 
    16261617#endif 
    16271618                    /* Variable cannot be put into a register anymore   */ 
    16281619                    if (e->E1->Eoper == OPvar) 
    16291620                        notreg(e->E1); 
    16301621                    freenode(e->E1); 
    16311622                } 
    16321623                else 
    16331624                { 
    16341625                    retregs = mST0; 
    16351626                    c = codelem(e->E1,&retregs,FALSE); 
    16361627                    if (op != -1) 
    16371628                    {   c = cat(c,makesure87(eleft,eoffset,1,0)); 
    16381629                        c = genf2(c,0xDE,modregrm(3,opr,1)); // FopRP 
    16391630                        pop87(); 
    16401631                    } 
    16411632                } 
    16421633                break; 
    16431634 
    16441635            case OPs64_d: 
    16451636                if (e->E1->Eoper == OPvar || 
    16461637                    (e->E1->Eoper == OPind && e->E1->Ecount == 0)) 
    16471638                { 
    16481639                    c = getlvalue(&cs,e->E1,0); 
    16491640                    cs.Iop = 0xDF; 
    16501641                    if (ADDFWAIT()) 
    16511642                        cs.Iflags |= CFwait; 
    1652                     if (I32
     1643                    if (!I16
    16531644                        cs.Iflags &= ~CFopsize; 
    16541645                    c = cat(c,push87()); 
    16551646                    cs.Irm |= modregrm(0,5,0); 
    16561647                    c = gen(c,&cs);                     // FILD m64 
    16571648                    // Variable cannot be put into a register anymore 
    16581649                    if (e->E1->Eoper == OPvar) 
    16591650                        notreg(e->E1); 
    16601651                    freenode(e->E1); 
    16611652                } 
    16621653                else 
    16631654                { 
    16641655                    retregs = ALLREGS; 
    16651656                    c = codelem(e->E1,&retregs,FALSE); 
    16661657                    reg = findreglsw(retregs); 
    16671658                    c = genfltreg(c,0x89,reg,0);        // MOV floatreg,reglsw 
    16681659                    reg = findregmsw(retregs); 
    16691660                    c = genfltreg(c,0x89,reg,4);        // MOV floatreg+4,regmsw 
    16701661                    c = cat(c,push87()); 
    16711662                    c = genfltreg(c,0xDF,5,0);          // FILD long long ptr floatreg 
    16721663                } 
     
    19081899        if (I32) 
    19091900            cs.Iflags &= ~CFopsize; 
    19101901        else if (ADDFWAIT()) 
    19111902            cs.Iflags |= CFwait; 
    19121903        c2 = gen(c2, &cs); 
    19131904#if LNGDBLSIZE == 12 
    19141905        /* This deals with the fact that 10 byte reals really 
    19151906         * occupy 12 bytes by zeroing the extra 2 bytes. 
    19161907         */ 
    19171908        if (op1 == 0xDB) 
    19181909        { 
    19191910            cs.Iop = 0xC7;                      // MOV EA+10,0 
    19201911            NEWREG(cs.Irm, 0); 
    19211912            cs.IEV1.sp.Voffset += 10; 
    19221913            cs.IFL2 = FLconst; 
    19231914            cs.IEV2.Vint = 0; 
    19241915            cs.Iflags |= CFopsize; 
    19251916            c2 = gen(c2, &cs); 
    19261917        } 
    19271918#endif 
    1928 #if LNGDBLSIZE == 16 
     1919        if (tysize[TYldouble] == 16) 
     1920        { 
    19291921        /* This deals with the fact that 10 byte reals really 
    19301922         * occupy 16 bytes by zeroing the extra 6 bytes. 
    19311923         */ 
    19321924        if (op1 == 0xDB) 
    19331925        { 
    19341926            cs.Iop = 0xC7;                      // MOV EA+10,0 
    19351927            NEWREG(cs.Irm, 0); 
    19361928            cs.IEV1.sp.Voffset += 10; 
    19371929            cs.IFL2 = FLconst; 
    19381930            cs.IEV2.Vint = 0; 
    19391931            cs.Iflags |= CFopsize; 
    19401932            c2 = gen(c2, &cs); 
    19411933 
    19421934            cs.IEV1.sp.Voffset += 2; 
    19431935            cs.Iflags &= ~CFopsize; 
    19441936            c2 = gen(c2, &cs); 
    19451937        } 
    1946 #endif 
     1938        } 
    19471939#endif 
    19481940        c2 = genfwait(c2); 
    19491941        freenode(e->E1); 
    19501942        c1 = cat3(c1,c2,fixresult87(e,mST0 | mPSW,pretregs)); 
    19511943        return c1; 
    19521944} 
    19531945 
    19541946/******************************* 
    19551947 * Perform an assignment to a long double/double/float. 
    19561948 */ 
    19571949 
    19581950code *complex_eq87(elem *e,regm_t *pretregs) 
    19591951{ 
    19601952        regm_t retregs; 
    19611953        code *c1,*c2; 
    19621954        code cs; 
    19631955        unsigned op1; 
    19641956        unsigned op2; 
    19651957        unsigned sz; 
    19661958        tym_t ty1; 
     
    20232015        if (fxch) 
    20242016            c2 = genf2(c2,0xD9,0xC8 + 1);       // FXCH ST(1) 
    20252017        cs.IEVoffset1 -= sz; 
    20262018        gen(c2, &cs); 
    20272019        if (fxch) 
    20282020            genf2(c2,0xD9,0xC8 + 1);            // FXCH ST(1) 
    20292021#if LNGDBLSIZE == 12 
    20302022        if (op1 == 0xDB) 
    20312023        { 
    20322024            cs.Iop = 0xC7;                      // MOV EA+10,0 
    20332025            NEWREG(cs.Irm, 0); 
    20342026            cs.IEV1.sp.Voffset += 10; 
    20352027            cs.IFL2 = FLconst; 
    20362028            cs.IEV2.Vint = 0; 
    20372029            cs.Iflags |= CFopsize; 
    20382030            c2 = gen(c2, &cs); 
    20392031            cs.IEVoffset1 += 12; 
    20402032            c2 = gen(c2, &cs);                  // MOV EA+22,0 
    20412033        } 
    20422034#endif 
    2043 #if LNGDBLSIZE == 16 
     2035        if (tysize[TYldouble] == 16) 
     2036        { 
    20442037        if (op1 == 0xDB) 
    20452038        { 
    20462039            cs.Iop = 0xC7;                      // MOV EA+10,0 
    20472040            NEWREG(cs.Irm, 0); 
    20482041            cs.IEV1.sp.Voffset += 10; 
    20492042            cs.IFL2 = FLconst; 
    20502043            cs.IEV2.Vint = 0; 
    20512044            cs.Iflags |= CFopsize; 
    20522045            c2 = gen(c2, &cs); 
    20532046 
    20542047            cs.IEV1.sp.Voffset += 2; 
    20552048            cs.Iflags &= ~CFopsize; 
    20562049            c2 = gen(c2, &cs); 
    20572050 
    20582051            cs.IEVoffset1 += 14; 
    20592052            cs.Iflags |= CFopsize; 
    20602053            c2 = gen(c2, &cs); 
    20612054 
    20622055            cs.IEV1.sp.Voffset += 2; 
    20632056            cs.Iflags &= ~CFopsize; 
    20642057            c2 = gen(c2, &cs); 
    20652058        } 
    2066 #endif 
     2059        } 
    20672060        c2 = genfwait(c2); 
    20682061        freenode(e->E1); 
    20692062        return cat3(c1,c2,fixresult_complex87(e,mST01 | mPSW,pretregs)); 
    20702063} 
    20712064 
    20722065/******************************* 
    20732066 * Perform an assignment while converting to integral type, 
    20742067 * i.e. handle (e1 = (int) e2) 
    20752068 */ 
    20762069 
    20772070code *cnvteq87(elem *e,regm_t *pretregs) 
    20782071{ 
    20792072        regm_t retregs; 
    20802073        code *c1,*c2; 
    20812074        code cs; 
    20822075        unsigned op1; 
    20832076        unsigned op2; 
    20842077        tym_t ty1; 
    20852078 
    20862079        assert(e->Eoper == OPeq); 
     
    22812274                jp      FM1 
    22822275                fxch    ST(1) 
    22832276                fld     E1.im 
    22842277        FM2:    fprem 
    22852278                fstsw   word ptr sw 
    22862279                fwait 
    22872280                mov     AH, byte ptr sw+1 
    22882281                jp      FM2 
    22892282                fstp    ST(1) 
    22902283     */ 
    22912284 
    22922285    ty1 = tybasic(e->E1->Ety); 
    22932286    sz2 = tysize[ty1] / 2; 
    22942287 
    22952288    retregs = mST0; 
    22962289    cr = codelem(e->E2,&retregs,FALSE);         // FLD E2 
    22972290    note87(e->E2,0,0); 
    22982291    cl = getlvalue(&cs,e->E1,0); 
    22992292    cl = cat(cl,makesure87(e->E2,0,0,0)); 
    23002293    cs.Iflags |= ADDFWAIT() ? CFwait : 0; 
    2301     if (I32
     2294    if (!I16
    23022295        cs.Iflags &= ~CFopsize; 
    23032296 
    23042297    c = push87(); 
    23052298    switch (ty1) 
    23062299    { 
    23072300        case TYcdouble:  cs.Iop = ESC(MFdouble,1);      break; 
    23082301        case TYcfloat:   cs.Iop = ESC(MFfloat,1);       break; 
    23092302        case TYcldouble: cs.Iop = 0xDB; cs.Irm |= modregrm(0, 5, 0); break; 
    23102303        default: 
    23112304            assert(0); 
    23122305    } 
    23132306    c = gen(c,&cs);                             // FLD E1.re 
    23142307 
    23152308    code *c1; 
    23162309 
    23172310    c1 = gen2(NULL, 0xD9, 0xF8);                // FPREM 
    23182311    c1 = cg87_87topsw(c1); 
    23192312    c1 = genjmp(c1, JP, FLcode, (block *)c1);   // JP FM1 
    23202313    c1 = genf2(c1, 0xD9, 0xC8 + 1);             // FXCH ST(1) 
    23212314    c = cat(c,c1); 
     
    23932386    if (!tycomplex(e->E2->Ety) && 
    23942387        (e->Eoper == OPmulass || e->Eoper == OPdivass)) 
    23952388    { 
    23962389        retregs = mST0; 
    23972390        cr = codelem(e->E2, &retregs, FALSE); 
    23982391        note87(e->E2, 0, 0); 
    23992392        cl = getlvalue(&cs, e->E1, 0); 
    24002393        cl = cat(cl,makesure87(e->E2,0,0,0)); 
    24012394        cl = cat(cl,push87()); 
    24022395        cl = genf2(cl,0xD9,0xC0);               // FLD ST(0) 
    24032396        goto L1; 
    24042397    } 
    24052398    else 
    24062399    { 
    24072400        cr = loadComplex(e->E2); 
    24082401        cl = getlvalue(&cs,e->E1,0); 
    24092402        cl = cat(cl,makesure87(e->E2,sz2,0,0)); 
    24102403        cl = cat(cl,makesure87(e->E2,0,1,0)); 
    24112404    } 
    24122405    cs.Iflags |= ADDFWAIT() ? CFwait : 0; 
    2413     if (I32
     2406    if (!I16
    24142407        cs.Iflags &= ~CFopsize; 
    24152408 
    24162409    switch (e->Eoper) 
    24172410    { 
    24182411        case OPpostinc: 
    24192412        case OPaddass: 
    24202413        case OPpostdec: 
    24212414        case OPminass: 
    24222415        L1: 
    24232416            if (ty1 == TYcldouble) 
    24242417            { 
    24252418                c = push87(); 
    24262419                c = cat(c, push87()); 
    24272420                cs.Iop = 0xDB; 
    24282421                cs.Irm |= modregrm(0, 5, 0);    // FLD tbyte ptr ... 
    24292422                c = gen(c,&cs);                 // FLD e->E1.re 
    24302423                cs.IEVoffset1 += sz2; 
    24312424                gen(c,&cs);                     // FLD e->E1.im 
    24322425                genf2(c, 0xDE, op2 + 2);        // FADDP/FSUBRP ST(2),ST 
    24332426                genf2(c, 0xDE, op2 + 2);        // FADDP/FSUBRP ST(2),ST 
     
    25812574                    cs.IEVoffset1 -= sz2; 
    25822575                    gen(c, &cs);                // FST mreal.re 
    25832576                    retregs = mST01; 
    25842577                } 
    25852578                else 
    25862579                { 
    25872580                    cs.Irm |= modregrm(0, 3, 0); 
    25882581                    gen(c, &cs);                // FSTP mreal.im 
    25892582                    cs.IEVoffset1 -= sz2; 
    25902583                    gen(c, &cs);                // FSTP mreal.re 
    25912584                    pop87(); 
    25922585                    pop87(); 
    25932586                    retregs = 0; 
    25942587                } 
    25952588                goto L3; 
    25962589            } 
    25972590 
    25982591        case OPdivass: 
    25992592            c = push87(); 
    26002593            c = cat(c, push87()); 
    2601             idxregs = idxregm(cs.Irm,cs.Isib);  // mask of index regs used 
     2594            idxregs = idxregm(&cs);             // mask of index regs used 
    26022595            if (ty1 == TYcldouble) 
    26032596            { 
    26042597                cs.Iop = 0xDB; 
    26052598                cs.Irm |= modregrm(0, 5, 0);    // FLD tbyte ptr ... 
    26062599                c = gen(c,&cs);                 // FLD e->E1.re 
    26072600                genf2(c,0xD9,0xC8 + 2);         // FXCH ST(2) 
    26082601                cs.IEVoffset1 += sz2; 
    26092602                gen(c,&cs);                     // FLD e->E1.im 
    26102603                genf2(c,0xD9,0xC8 + 2);         // FXCH ST(2) 
    26112604                retregs = mST01; 
    26122605                c = cat(c,callclib(e, CLIBcdiv, &retregs, idxregs)); 
    26132606                goto L2; 
    26142607            } 
    26152608            else 
    26162609            { 
    26172610                cs.Iop = (ty1 == TYcfloat) ? 0xD9 : 0xDD; 
    26182611                cs.Irm |= modregrm(0, 0, 0);    // FLD tbyte ptr ... 
    26192612                c = gen(c,&cs);                 // FLD e->E1.re 
    26202613                genf2(c,0xD9,0xC8 + 2);         // FXCH ST(2) 
    26212614                cs.IEVoffset1 += sz2; 
     
    26522645 
    26532646/************************** 
    26542647 * OPnegass 
    26552648 */ 
    26562649 
    26572650code *cdnegass87(elem *e,regm_t *pretregs) 
    26582651{   regm_t retregs; 
    26592652    tym_t tyml; 
    26602653    unsigned op; 
    26612654    targ_long val; 
    26622655    code *cl,*cr,*c,cs; 
    26632656    elem *e1; 
    26642657    int sz; 
    26652658 
    26662659    //printf("cdnegass87(e = %p, *pretregs = x%x)\n", e, *pretregs); 
    26672660    e1 = e->E1; 
    26682661    tyml = tybasic(e1->Ety);            // type of lvalue 
    26692662    sz = tysize[tyml]; 
    26702663 
    26712664    cl = getlvalue(&cs,e1,0); 
    2672     cr = modEA(cs.Irm); 
     2665    cr = modEA(&cs); 
    26732666    cs.Irm |= modregrm(0,6,0); 
    26742667    cs.Iop = 0x80; 
     2668    cs.Irex = 0; 
    26752669#if LNGDBLSIZE > 10 
    26762670    if (tyml == TYldouble || tyml == TYildouble) 
    26772671        cs.IEVoffset1 += 10 - 1; 
    26782672    else if (tyml == TYcldouble) 
    26792673        cs.IEVoffset1 += LNGDBLSIZE + 10 - 1; 
    26802674    else 
    26812675#endif 
    26822676        cs.IEVoffset1 += sz - 1; 
    26832677    cs.IFL2 = FLconst; 
    26842678    cs.IEV2.Vuns = 0x80; 
    26852679    c = gen(NULL,&cs);                  // XOR 7[EA],0x80 
    26862680    if (tycomplex(tyml)) 
    26872681    { 
    26882682        cs.IEVoffset1 -= sz / 2; 
    26892683        gen(c,&cs);                     // XOR 7[EA],0x80 
    26902684    } 
    26912685    c = cat3(cl,cr,c); 
    26922686 
    26932687    if (*pretregs) 
    26942688    { 
     
    27182712} 
    27192713 
    27202714/************************ 
    27212715 * Take care of OPpostinc and OPpostdec. 
    27222716 */ 
    27232717 
    27242718code *post87(elem *e,regm_t *pretregs) 
    27252719{ 
    27262720        regm_t retregs; 
    27272721        code *cl,*cr,*c; 
    27282722        code cs; 
    27292723        unsigned op; 
    27302724        unsigned op1; 
    27312725        unsigned reg; 
    27322726        tym_t ty1; 
    27332727 
    27342728        //printf("post87()\n"); 
    27352729        assert(*pretregs); 
    27362730        cl = getlvalue(&cs,e->E1,0); 
    27372731        cs.Iflags |= ADDFWAIT() ? CFwait : 0; 
    2738         if (I32
     2732        if (!I16
    27392733            cs.Iflags &= ~CFopsize; 
    27402734        ty1 = tybasic(e->E1->Ety); 
    27412735        switch (ty1) 
    27422736        {   case TYdouble_alias: 
    27432737            case TYidouble: 
    27442738            case TYdouble: 
    27452739            case TYcdouble:     op1 = ESC(MFdouble,1);  reg = 0;        break; 
    27462740            case TYifloat: 
    27472741            case TYfloat: 
    27482742            case TYcfloat:      op1 = ESC(MFfloat,1);   reg = 0;        break; 
    27492743            case TYildouble: 
    27502744            case TYldouble: 
    27512745            case TYcldouble:    op1 = 0xDB;             reg = 5;        break; 
    27522746            default: 
    27532747                assert(0); 
    27542748        } 
    27552749        NEWREG(cs.Irm, reg); 
    27562750        if (reg == 5) 
    27572751            reg = 7; 
    27582752        else 
     
    28052799 *      OPd_s32 
    28062800 *      OPd_u16 
    28072801 *      OPd_s64 
    28082802 */ 
    28092803 
    28102804code *cnvt87(elem *e,regm_t *pretregs) 
    28112805{ 
    28122806        regm_t retregs; 
    28132807        code *c1,*c2; 
    28142808        unsigned mf,rf,reg; 
    28152809        tym_t tym; 
    28162810        int clib; 
    28172811        int sz; 
    28182812        int szoff; 
    28192813 
    28202814        //printf("cnvt87(e = %p, *pretregs = x%x)\n", e, *pretregs); 
    28212815        assert(*pretregs); 
    28222816        tym = e->Ety; 
    28232817        sz = tysize(tym); 
    28242818        szoff = sz; 
     2819        unsigned grex = I64 ? REX_W << 16 : 0; 
    28252820 
    28262821        switch (e->Eoper) 
    28272822        {   case OPd_s16: 
    28282823                clib = CLIBdblint87; 
    28292824                mf = ESC(MFword,1); 
    28302825                rf = 3; 
    28312826                break; 
    28322827 
    28332828            case OPd_u16: 
    28342829                szoff = 4; 
    28352830            case OPd_s32: 
    28362831                clib = CLIBdbllng87; 
    28372832                mf = ESC(MFlong,1); 
    28382833                rf = 3; 
    28392834                break; 
    28402835 
    28412836            case OPd_s64: 
    28422837                clib = CLIBdblllng; 
    28432838                mf = 0xDF; 
    28442839                rf = 7; 
    28452840                break; 
    28462841 
    28472842            default: 
    28482843                assert(0); 
    28492844        } 
    28502845 
    2851         if (!I32)                       // C may change the default control word 
     2846        if (I16)                       // C may change the default control word 
    28522847        { 
    28532848            if (clib == CLIBdblllng) 
    28542849            {   retregs = I32 ? DOUBLEREGS_32 : DOUBLEREGS_16; 
    28552850                c1 = codelem(e->E1,&retregs,FALSE); 
    28562851                c2 = callclib(e,clib,pretregs,0); 
    28572852            } 
    28582853            else 
    28592854            {   retregs = mST0; //I32 ? DOUBLEREGS_32 : DOUBLEREGS_16; 
    28602855                c1 = codelem(e->E1,&retregs,FALSE); 
    28612856                c2 = callclib(e,clib,pretregs,0); 
    28622857                pop87(); 
    28632858            } 
    28642859        } 
    28652860        else if (1) 
    28662861        {   //  Generate: 
    28672862            //  sub     ESP,12 
    28682863            //  fstcw   8[ESP] 
    28692864            //  fldcw   roundto0 
    28702865            //  fistp   long64 ptr [ESP] 
    28712866            //  fldcw   8[ESP] 
    28722867            //  pop     lsw 
    28732868            //  pop     msw 
    28742869            //  add     ESP,4 
    28752870 
    28762871            unsigned szpush = szoff + 2; 
    28772872            if (config.flags3 & CFG3pic) 
    28782873                szpush += 2; 
    28792874            szpush = (szpush + REGSIZE - 1) & ~(REGSIZE - 1); 
    28802875 
    28812876            retregs = mST0; 
    28822877            c1 = codelem(e->E1,&retregs,FALSE); 
    28832878 
    28842879            if (szpush == REGSIZE) 
    28852880                c1 = gen1(c1,0x50 + AX);                // PUSH EAX 
    28862881            else 
    2887                 c1 = genc2(c1,0x81,modregrm(3,5,SP), szpush);   // SUB ESP,12 
     2882                c1 = genc2(c1,0x81,grex | modregrm(3,5,SP), szpush);   // SUB ESP,12 
    28882883            c1 = genfwait(c1); 
    2889             genc1(c1,0xD9,modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP] 
     2884            genc1(c1,0xD9,grex | modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP] 
    28902885 
    28912886            c1 = genfwait(c1); 
    28922887 
    28932888            if (config.flags3 & CFG3pic) 
    28942889            { 
    2895                 genc(c1,0xC7,modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto0 
     2890                genc(c1,0xC7,grex | modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto0 
    28962891                code_orflag(c1, CFopsize); 
    2897                 genc1(c1,0xD9,modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP] 
     2892                genc1(c1,0xD9,grex | modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP] 
    28982893            } 
    28992894            else 
    29002895                c1 = genrnd(c1, CW_roundto0);   // FLDCW roundto0 
    29012896 
    29022897            pop87(); 
    29032898 
    29042899            c1 = genfwait(c1); 
    2905             gen2sib(c1,mf,modregrm(0,rf,4),modregrm(0,4,SP));                   // FISTP [ESP] 
     2900            gen2sib(c1,mf,grex | modregrm(0,rf,4),modregrm(0,4,SP));                   // FISTP [ESP] 
    29062901 
    29072902            retregs = *pretregs & (ALLREGS | mBP); 
    29082903            if (!retregs) 
    29092904                    retregs = ALLREGS; 
    29102905            c2 = allocreg(&retregs,&reg,tym); 
    29112906 
    29122907            c2 = genfwait(c2);                                                          // FWAIT 
    2913             c2 = genc1(c2,0xD9,modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff);   // FLDCW szoff[ESP] 
     2908            c2 = genc1(c2,0xD9,grex | modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff);   // FLDCW szoff[ESP] 
    29142909 
    29152910            if (szoff > REGSIZE) 
    29162911            {   szpush -= REGSIZE; 
    2917                 c2 = gen1(c2,0x58 + findreglsw(retregs));       // POP lsw 
     2912                c2 = genpop(c2,findreglsw(retregs));       // POP lsw 
    29182913            } 
    29192914            szpush -= REGSIZE; 
    2920             c2 = gen1(c2,0x58 + reg);                           // POP reg 
     2915            c2 = genpop(c2,reg);                           // POP reg 
    29212916 
    29222917            if (szpush) 
    2923                 genc2(c2,0x81,modregrm(3,0,SP), szpush);        // ADD ESP,4 
     2918                genc2(c2,0x81,grex | modregrm(3,0,SP), szpush);        // ADD ESP,4 
    29242919            c2 = cat(c2,fixresult(e,retregs,pretregs)); 
    29252920        } 
    29262921        else 
    29272922        { 
    29282923            // This is incorrect. For -inf and nan, the 8087 returns the largest 
    29292924            // negative int (0x80000....). For -inf, 0x7FFFF... should be returned, 
    29302925            // and for nan, 0 should be returned. 
    29312926            retregs = mST0; 
    29322927            c1 = codelem(e->E1,&retregs,FALSE); 
    29332928 
    29342929            c1 = genfwait(c1); 
    29352930            c1 = genrnd(c1, CW_roundto0);       // FLDCW roundto0 
    29362931 
    29372932            pop87(); 
    29382933            c1 = genfltreg(c1,mf,rf,0);         // FISTP floatreg 
    29392934            retregs = *pretregs & (ALLREGS | mBP); 
    29402935            if (!retregs) 
    29412936                    retregs = ALLREGS; 
    29422937            c2 = allocreg(&retregs,&reg,tym); 
    29432938 
  • branches/dmd-1.x/src/backend/cg.c

    r558 r577  
    3636                                // of the public name index of a COMDAT) 
    3737 
    3838/* Stack offsets        */ 
    3939targ_size_t localsize,          /* amt subtracted from SP for local vars */ 
    4040        Toff,                   /* base for temporaries                 */ 
    4141        Poff,Aoff;              // comsubexps, params, regs, autos 
    4242 
    4343/* The following are initialized for the 8088. cod3_set386() will 
    4444 * change them if generating code for the 386, cod3_set64() for 64 bit code. 
    4545 */ 
    4646int     BPRM = 6;               /* R/M value for [BP] or [EBP]          */ 
    4747regm_t  fregsaved = mBP | mSI | mDI;    // mask of registers saved across 
    4848                                        // function calls 
    4949                                        // (add in mBX for I32) 
    5050regm_t  FLOATREGS = FLOATREGS_16; 
    5151regm_t  FLOATREGS2 = FLOATREGS2_16; 
    5252regm_t  DOUBLEREGS = DOUBLEREGS_16; 
    5353 
    5454symbol *localgot;               // reference to GOT for this function 
    5555symbol *tls_get_addr_sym;       // function __tls_get_addr 
     56 
     57#if TARGET_OSX 
     58int STACKALIGN = 16; 
     59#else 
     60int STACKALIGN = 0; 
     61#endif 
  • branches/dmd-1.x/src/backend/cgcod.c

    r558 r577  
    1919 
    2020#if __sun&&__SVR4 
    2121#include        <alloca.h> 
    2222#endif 
    2323 
    2424#include        "cc.h" 
    2525#include        "el.h" 
    2626#include        "oper.h" 
    2727#include        "code.h" 
    2828#include        "global.h" 
    2929#include        "type.h" 
    3030#include        "exh.h" 
    3131 
    3232static char __file__[] = __FILE__;      /* for tassert.h                */ 
    3333#include        "tassert.h" 
    3434 
    3535STATIC void resetEcomsub(elem *e); 
    3636STATIC code * loadcse(elem *,unsigned,regm_t); 
    3737STATIC void blcodgen(block *); 
    3838STATIC void cgcod_eh(); 
    39 STATIC int numbitsset(regm_t); 
    4039STATIC code * cse_save(regm_t ms); 
    4140STATIC int cse_simple(elem *e,int i); 
    4241STATIC code * comsub(elem *,regm_t *); 
    4342 
    4443bool floatreg;                  // !=0 if floating register is required 
    4544 
    4645targ_size_t Aoffset;            // offset of automatics and registers 
    4746targ_size_t Toffset;            // offset of temporaries 
    4847targ_size_t EEoffset;           // offset of SCstack variables from ESP 
    4948int Aalign;                     // alignment for Aoffset 
    5049 
    5150CGstate cgstate;                // state of code generator 
    5251 
    5352/************************************ 
    5453 * # of bytes that SP is beyond BP. 
    5554 */ 
    5655 
    5756unsigned stackpush; 
    5857 
    5958int stackchanged;               /* set to !=0 if any use of the stack 
     
    15611560        case TYcdouble: 
    15621561            if (I64) 
    15631562                return mXMM0 | mXMM1; 
    15641563        case TYcldouble: 
    15651564            return mST01; 
    15661565 
    15671566        default: 
    15681567#if DEBUG 
    15691568            WRTYxx(tym); 
    15701569#endif 
    15711570            assert(0); 
    15721571            return 0; 
    15731572    } 
    15741573} 
    15751574 
    15761575 
    15771576/****************************** 
    15781577 * Count the number of bits set in a register mask. 
    15791578 */ 
    15801579 
    1581 STATIC int numbitsset(regm_t regm) 
     1580int numbitsset(regm_t regm) 
    15821581{   int n; 
    15831582 
    15841583    n = 0; 
    15851584    if (regm) 
    15861585        do 
    15871586            n++; 
    15881587        while ((regm &= regm - 1) != 0); 
    15891588    return n; 
    15901589} 
    15911590 
    15921591/****************************** 
    15931592 * Given a register mask, find and return the number 
    15941593 * of the first register that fits. 
    15951594 */ 
    15961595 
    15971596#undef findreg 
    15981597 
    15991598unsigned findreg(regm_t regm 
    16001599#ifdef DEBUG 
    16011600        ,int line,const char *file 
  • branches/dmd-1.x/src/backend/cgen.c

    r569 r577  
    147147    unsigned reg; 
    148148 
    149149#ifdef DEBUG                            /* this is a high usage routine */ 
    150150    assert(cs); 
    151151#endif 
    152152    assert(I64 || cs->Irex == 0); 
    153153    ce = code_calloc(); 
    154154    *ce = *cs; 
    155155    if (config.flags4 & CFG4optimized && 
    156156        ce->IFL2 == FLconst && 
    157157        (ce->Iop == 0x81 || ce->Iop == 0x80) && 
    158158        reghasvalue((ce->Iop == 0x80) ? BYTEREGS : ALLREGS,ce->IEV2.Vlong,&reg) && 
    159159        !(ce->Iflags & CFopsize && I16) 
    160160       ) 
    161161    {   // See if we can replace immediate instruction with register instruction 
    162162        static unsigned char regop[8] = 
    163163                { 0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38 }; 
    164164 
    165165//printf("replacing 0x%02x, val = x%lx\n",ce->Iop,ce->IEV2.Vlong); 
    166166        ce->Iop = regop[(ce->Irm & modregrm(0,7,0)) >> 3] | (ce->Iop & 1); 
    167         ce->Irm = (ce->Irm & modregrm(3,0,7)) | modregrm(0,reg,0); 
     167        code_newreg(ce, reg); 
    168168    } 
    169169    code_next(ce) = CNIL; 
    170170    if (c) 
    171171    {   cstart = c; 
    172172        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    173173        code_next(c) = ce;                      /* link into list       */ 
    174174        return cstart; 
    175175    } 
    176176    return ce; 
    177177} 
    178178 
    179179code *gen1(code *c,unsigned op) 
    180180{ code *ce,*cstart; 
    181181 
    182182  ce = code_calloc(); 
    183183  ce->Iop = op; 
    184184  if (c) 
    185185  {     cstart = c; 
    186186        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    187187        code_next(c) = ce;                      /* link into list       */ 
    188188        return cstart; 
    189189  } 
    190190  return ce; 
    191191} 
    192192 
    193193code *gen2(code *c,unsigned op,unsigned rm) 
    194194{ code *ce,*cstart; 
    195195 
    196196  cstart = ce = code_calloc(); 
    197197  /*cxcalloc++;*/ 
    198198  if (op > 0xFF) 
    199199  {     ce->Iop = op >> 8; 
    200200        ce->Iop2 = op & 0xFF; 
    201201  } 
    202202  else 
    203203        ce->Iop = op; 
    204   ce->Irm = rm; 
    205   ce->Irex = rm >> 16; 
     204  ce->Iea = rm; 
    206205  if (c) 
    207206  {     cstart = c; 
    208207        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    209208        code_next(c) = ce;                      /* link into list       */ 
    210209  } 
    211210  return cstart; 
    212211} 
    213212 
    214213code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 
    215214{ code *ce,*cstart; 
    216215 
    217216  cstart = ce = code_calloc(); 
    218217  /*cxcalloc++;*/ 
    219218  ce->Iop = op; 
    220219  ce->Irm = rm; 
    221220  ce->Isib = sib; 
    222   ce->Irex = rm >> 16; 
     221  ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 
     222  if (sib & (REX_R << 16)) 
     223        ce->Irex |= REX_X; 
    223224  if (c) 
    224225  {     cstart = c; 
    225226        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    226227        code_next(c) = ce;                      /* link into list       */ 
    227228  } 
    228229  return cstart; 
    229230} 
    230231 
    231232code *genregs(code *c,unsigned op,unsigned dstreg,unsigned srcreg) 
    232233{ return gen2(c,op,modregxrmx(3,dstreg,srcreg)); } 
    233234 
    234235code *gentstreg(code *c,unsigned t) 
    235236{ 
    236237    c = gen2(c,0x85,modregxrmx(3,t,t));   // TEST t,t 
    237238    code_orflag(c,CFpsw); 
     239    return c; 
     240} 
     241 
     242code *genpush(code *c, unsigned reg) 
     243{ 
     244    c = gen1(c, 0x50 + (reg & 7)); 
     245    if (reg & 8) 
     246        code_orrex(c, REX_B); 
     247    return c; 
     248} 
     249 
     250code *genpop(code *c, unsigned reg) 
     251{ 
     252    c = gen1(c, 0x58 + (reg & 7)); 
     253    if (reg & 8) 
     254        code_orrex(c, REX_B); 
    238255    return c; 
    239256} 
    240257 
    241258/******************************** 
    242259 * Generate an ASM sequence. 
    243260 */ 
    244261 
    245262code *genasm(code *c,char *s,unsigned slen) 
    246263{   code *ce; 
    247264 
    248265    ce = code_calloc(); 
    249266    ce->Iop = ASM; 
    250267    ce->IFL1 = FLasm; 
    251268    ce->IEV1.as.len = slen; 
    252269    ce->IEV1.as.bytes = (char *) mem_malloc(slen); 
    253270    memcpy(ce->IEV1.as.bytes,s,slen); 
    254271    return cat(c,ce); 
    255272} 
    256273 
    257274/************************** 
     
    310327            gen(cj,&cs); 
    311328            break; 
    312329        case JNP << 8: 
    313330            /* Do a JP around the jump instruction      */ 
    314331            cnop = gennop(CNIL); 
    315332            c = genjmp(c,JP,FLcode,(block *) cnop); 
    316333            cat(cj,cnop); 
    317334            break; 
    318335        case 1 << 8:                    /* toggled no jump              */ 
    319336        case 0 << 8: 
    320337            break; 
    321338        default: 
    322339#ifdef DEBUG 
    323340            printf("jop = x%x\n",op); 
    324341#endif 
    325342            assert(0); 
    326343    } 
    327344    return cat(c,cj); 
    328345} 
    329346 
    330 code *gencs(code *c,unsigned op,unsigned rm,unsigned FL2,symbol *s) 
     347code *gencs(code *c,unsigned op,unsigned ea,unsigned FL2,symbol *s) 
    331348{   code cs; 
    332349 
    333350    cs.Iop = op; 
    334     cs.Irm = rm
     351    cs.Iea = ea
    335352    cs.Iflags = 0; 
    336     cs.Irex = rm >> 16; 
    337353    cs.IFL2 = FL2; 
    338354    cs.IEVsym2 = s; 
    339355    cs.IEVoffset2 = 0; 
    340356 
    341357    return gen(c,&cs); 
    342358} 
    343359 
    344 code *genc2(code *c,unsigned op,unsigned rm,targ_size_t EV2) 
     360code *genc2(code *c,unsigned op,unsigned ea,targ_size_t EV2) 
    345361{   code cs; 
    346362 
    347363    if (op > 0xFF) 
    348364    {   cs.Iop = op >> 8; 
    349365        cs.Iop2 = op & 0xFF; 
    350366    } 
    351367    else 
    352368        cs.Iop = op; 
    353     cs.Irm = rm
     369    cs.Iea = ea
    354370    cs.Iflags = CFoff; 
    355     cs.Irex = rm >> 16; 
    356371    cs.IFL2 = FLconst; 
    357372    cs.IEV2.Vsize_t = EV2; 
    358373    return gen(c,&cs); 
    359374} 
    360375 
    361376/***************** 
    362377 * Generate code. 
    363378 */ 
    364379 
    365 code *genc1(code *c,unsigned op,unsigned rm,unsigned FL1,targ_size_t EV1) 
     380code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 
    366381{   code cs; 
    367382 
    368383    assert(FL1 < FLMAX); 
    369384    assert(op < 256); 
    370385    cs.Iop = op; 
    371     cs.Irm = rm; 
    372     cs.Isib = rm >> 8; 
    373     cs.Irex = rm >> 16; 
     386    cs.Iea = ea; 
    374387    cs.Iflags = CFoff; 
    375388    cs.IFL1 = FL1; 
    376389    cs.IEV1.Vsize_t = EV1; 
    377390    return gen(c,&cs); 
    378391} 
    379392 
    380393/***************** 
    381394 * Generate code. 
    382395 */ 
    383396 
    384 code *genc(code *c,unsigned op,unsigned rm,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
     397code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
    385398{   code cs; 
    386399 
    387400    assert(FL1 < FLMAX); 
    388401    assert(op < 256); 
    389402    cs.Iop = op; 
    390     cs.Irm = rm; 
    391     cs.Isib = rm >> 8; 
    392     cs.Irex = rm >> 16; 
     403    cs.Iea = ea; 
    393404    cs.Iflags = CFoff; 
    394405    cs.IFL1 = FL1; 
    395406    cs.IEV1.Vsize_t = EV1; 
    396407    assert(FL2 < FLMAX); 
    397408    cs.IFL2 = FL2; 
    398409    cs.IEV2.Vsize_t = EV2; 
    399410    return gen(c,&cs); 
    400411} 
    401412 
    402413/*************************************** 
    403414 * Generate immediate multiply instruction for r1=r2*imm. 
    404415 * Optimize it into LEA's if we can. 
    405416 */ 
    406417 
    407418code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm) 
    408419{   code cs; 
    409420 
    410421    // These optimizations should probably be put into pinholeopt() 
    411422    switch (imm) 
    412423    {   case 1: 
  • branches/dmd-1.x/src/backend/cod1.c

    r552 r577  
    2626#include        "tassert.h" 
    2727 
    2828targ_size_t paramsize(elem *e,unsigned stackalign); 
    2929STATIC code * funccall (elem *,unsigned,unsigned,regm_t *,regm_t); 
    3030 
    3131/* array to convert from index register to r/m field    */ 
    3232                                       /* AX CX DX BX SP BP SI DI       */ 
    3333static const signed char regtorm32[8] = {  0, 1, 2, 3,-1, 5, 6, 7 }; 
    3434             signed char regtorm  [8] = { -1,-1,-1, 7,-1, 6, 4, 5 }; 
    3535 
    3636/************************** 
    3737 * Determine if e is a 32 bit scaled index addressing mode. 
    3838 * Returns: 
    3939 *      0       not a scaled index addressing mode 
    4040 *      !=0     the value for ss in the SIB byte 
    4141 */ 
    4242 
    4343int isscaledindex(elem *e) 
    4444{   targ_uns ss; 
    4545 
    46     assert(I32); 
     46    assert(!I16); 
    4747    while (e->Eoper == OPcomma) 
    4848        e = e->E2; 
    4949    if (!(e->Eoper == OPshl && !e->Ecount && 
    5050          e->E2->Eoper == OPconst && 
    5151          (ss = e->E2->EV.Vuns) <= 3 
    5252         ) 
    5353       ) 
    5454        ss = 0; 
    5555    return ss; 
    5656} 
    5757 
    5858/********************************************* 
    5959 * Generate code for which isscaledindex(e) returned a non-zero result. 
    6060 */ 
    6161 
    6262code *cdisscaledindex(elem *e,regm_t *pidxregs,regm_t keepmsk) 
    6363{   code *c; 
    6464    regm_t r; 
    6565 
    6666    // Load index register with result of e->E1 
     
    132132    { 
    133133        if (ssindex_array[i].product == product) 
    134134            return i; 
    135135    } 
    136136    return 0; 
    137137} 
    138138 
    139139/*************************************** 
    140140 * Build an EA of the form disp[base][index*scale]. 
    141141 * Input: 
    142142 *      c       struct to fill in 
    143143 *      base    base register (-1 if none) 
    144144 *      index   index register (-1 if none) 
    145145 *      scale   scale factor - 1,2,4,8 
    146146 *      disp    displacement 
    147147 */ 
    148148 
    149149void buildEA(code *c,int base,int index,int scale,targ_size_t disp) 
    150150{   unsigned char rm; 
    151151    unsigned char sib; 
     152    unsigned char rex = 0; 
    152153 
    153154    sib = 0; 
    154     if (I32
     155    if (!I16
    155156    {   unsigned ss; 
    156157 
    157158        assert(index != SP); 
    158159 
    159160        switch (scale) 
    160161        {   case 1:     ss = 0; break; 
    161162            case 2:     ss = 1; break; 
    162163            case 4:     ss = 2; break; 
    163164            case 8:     ss = 3; break; 
    164165            default:    assert(0); 
    165166        } 
    166167 
    167168        if (base == -1) 
    168169        { 
    169170            if (index == -1) 
    170171                rm = modregrm(0,0,5); 
    171172            else 
    172173            { 
    173174                rm  = modregrm(0,0,4); 
    174                 sib = modregrm(ss,index,5); 
     175                sib = modregrm(ss,index & 7,5); 
     176                if (index & 8) 
     177                    rex |= REX_X; 
    175178            } 
    176179        } 
    177180        else if (index == -1) 
    178181        { 
    179182            if (base == SP) 
    180183            { 
    181184                rm  = modregrm(2,0,4); 
    182185                sib = modregrm(0,4,SP); 
    183186            } 
    184187            else 
    185                 rm = modregrm(2,0,base); 
     188            {   rm = modregrm(2,0,base & 7); 
     189                if (base & 8) 
     190                    rex |= REX_B; 
     191            } 
    186192        } 
    187193        else 
    188194        { 
    189195            rm  = modregrm(2,0,4); 
    190             sib = modregrm(ss,index,base); 
     196            sib = modregrm(ss,index & 7,base & 7); 
     197            if (index & 8) 
     198                rex |= REX_X; 
     199            if (base & 8) 
     200                rex |= REX_B; 
    191201        } 
    192202    } 
    193203    else 
    194204    { 
    195205        // -1 AX CX DX BX SP BP SI DI 
    196206        static unsigned char EA16rm[9][9] = 
    197207        { 
    198208            {   0x06,0x09,0x09,0x09,0x87,0x09,0x86,0x84,0x85,   },      // -1 
    199209            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // AX 
    200210            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // CX 
    201211            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // DX 
    202212            {   0x87,0x09,0x09,0x09,0x09,0x09,0x09,0x80,0x81,   },      // BX 
    203213            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // SP 
    204214            {   0x86,0x09,0x09,0x09,0x09,0x09,0x09,0x82,0x83,   },      // BP 
    205215            {   0x84,0x09,0x09,0x09,0x80,0x09,0x82,0x09,0x09,   },      // SI 
    206216            {   0x85,0x09,0x09,0x09,0x81,0x09,0x83,0x09,0x09,   }       // DI 
    207217        }; 
    208218 
    209219        assert(scale == 1); 
    210220        rm = EA16rm[base + 1][index + 1]; 
    211221        assert(rm != 9); 
    212222    } 
    213223    c->Irm = rm; 
    214224    c->Isib = sib; 
     225    c->Irex = rex; 
    215226    c->IFL1 = FLconst; 
    216227    c->IEV1.Vuns = disp; 
    217228} 
    218229 
    219230/************************** 
    220231 * For elems in regcon that don't match regconsave, 
    221232 * clear the corresponding bit in regcon.cse.mval. 
    222233 * Do same for regcon.immed. 
    223234 */ 
    224235 
    225236void andregcon(con_t *pregconsave) 
    226 {   int i; 
    227     regm_t m; 
    228  
    229     m = ~1; 
    230     for (i = 0; i < REGMAX; i++) 
     237
     238    regm_t m = ~1; 
     239    for (int i = 0; i < REGMAX; i++) 
    231240    {   if (pregconsave->cse.value[i] != regcon.cse.value[i]) 
    232241            regcon.cse.mval &= m; 
    233242        if (pregconsave->immed.value[i] != regcon.immed.value[i]) 
    234243            regcon.immed.mval &= m; 
    235244        m <<= 1; 
    236245        m |= 1; 
    237246    } 
    238247    //printf("regcon.cse.mval = x%x, regconsave->mval = x%x ",regcon.cse.mval,pregconsave->cse.mval); 
    239248    regcon.used |= pregconsave->used; 
    240249    regcon.cse.mval &= pregconsave->cse.mval; 
    241250    regcon.immed.mval &= pregconsave->immed.mval; 
    242251    regcon.params &= pregconsave->params; 
    243252    //printf("regcon.cse.mval&regcon.cse.mops = x%x, regcon.cse.mops = x%x\n",regcon.cse.mval & regcon.cse.mops,regcon.cse.mops); 
    244253    regcon.cse.mops &= regcon.cse.mval; 
    245254} 
    246255 
    247256/********************************* 
    248257 * Scan down comma-expressions. 
    249258 * Output: 
    250259 *      *pe = first elem down right side that is not an OPcomma 
     
    295304    if (e) 
    296305    { 
    297306        unsigned stackpushsave; 
    298307        int stackcleansave; 
    299308 
    300309        stackpushsave = stackpush; 
    301310        stackcleansave = cgstate.stackclean; 
    302311        cgstate.stackclean = 0;                         // defer cleaning of stack 
    303312        c = cat(c,codelem(e,pretregs,constflag)); 
    304313        assert(cgstate.stackclean == 0); 
    305314        cgstate.stackclean = stackcleansave; 
    306315        c = genstackclean(c,stackpush - stackpushsave,*pretregs);       // do defered cleaning 
    307316    } 
    308317    return c; 
    309318} 
    310319 
    311320/******************************************** 
    312321 * Gen a save/restore sequence for mask of registers. 
    313322 */ 
    314323 
    315 void gensaverestore(regm_t regm,code **csave,code **crestore) 
    316 {   code *cs1; 
    317     code *cs2; 
    318     int i; 
    319  
    320     cs1 = NULL; 
    321     cs2 = NULL; 
     324void gensaverestore2(regm_t regm,code **csave,code **crestore) 
     325
     326    code *cs1 = *csave; 
     327    code *cs2 = *crestore; 
     328 
    322329    regm &= mBP | mES | ALLREGS; 
    323     for (i = 0; regm; i++) 
     330    for (int i = 0; regm; i++) 
    324331    { 
    325332        if (regm & 1) 
    326333        { 
    327             assert(i != ES);                    // fix later 
    328             cs1 = gen1(cs1,0x50 + i); 
    329             cs2 = cat(gen1(NULL,0x58 + i),cs2); 
     334            if (i == ES) 
     335            { 
     336                cs1 = gen1(cs1, 0x06);                  // PUSH ES 
     337                cs2 = cat(gen1(CNIL, 0x07),cs2);        // POP  ES 
     338            } 
     339            else 
     340            { 
     341                cs1 = gen1(cs1,0x50 + (i & 7));         // PUSH i 
     342                code *c = gen1(NULL, 0x58 + (i & 7));   // POP  i 
     343                if (i & 8) 
     344                {   code_orrex(cs1, REX_B); 
     345                    code_orrex(c, REX_B); 
     346                } 
     347                cs2 = cat(c,cs2); 
     348            } 
    330349        } 
    331350        regm >>= 1; 
    332351    } 
    333352    *csave = cs1; 
    334353    *crestore = cs2; 
     354} 
     355 
     356void gensaverestore(regm_t regm,code **csave,code **crestore) 
     357{ 
     358    *csave = NULL; 
     359    *crestore = NULL; 
     360    gensaverestore2(regm, csave, crestore); 
    335361} 
    336362 
    337363/**************************************** 
    338364 * Clean parameters off stack. 
    339365 * Input: 
    340366 *      numpara         amount to adjust stack pointer 
    341367 *      keepmsk         mask of registers to not destroy 
    342368 */ 
    343369 
    344370code *genstackclean(code *c,unsigned numpara,regm_t keepmsk) 
    345371{ 
    346372    //dbg_printf("genstackclean(numpara = %d, stackclean = %d)\n",numpara,cgstate.stackclean); 
    347373    if (numpara && (cgstate.stackclean || STACKALIGN == 16)) 
    348374    { 
    349375#if 0       // won't work if operand of scodelem 
    350376        if (numpara == stackpush &&             // if this is all those pushed 
    351377            needframe &&                        // and there will be a BP 
    352378            !config.windows && 
    353379            !(regcon.mvar & fregsaved)          // and no registers will be pushed 
    354380        ) 
    355381            c = genregs(c,0x89,BP,SP);  // MOV SP,BP 
    356382        else 
    357383#endif 
    358384        {   regm_t scratchm = 0; 
    359             unsigned r; 
    360385 
    361386            if (numpara == REGSIZE && config.flags4 & CFG4space) 
    362387            { 
    363388                scratchm = ALLREGS & ~keepmsk & regcon.used & ~regcon.mvar; 
    364389            } 
    365390 
    366391            if (scratchm) 
    367             {   c = cat(c,allocreg(&scratchm,&r,TYint)); 
     392            {   unsigned r; 
     393                c = cat(c,allocreg(&scratchm,&r,TYint)); 
    368394                c = gen1(c,0x58 + r);           // POP r 
    369395            } 
    370396            else 
    371                 c = genc2(c,0x81,modregrm(3,0,SP),numpara); // ADD SP,numpara 
     397            {   c = genc2(c,0x81,modregrm(3,0,SP),numpara); // ADD SP,numpara 
     398                if (I64) 
     399                    code_orrex(c, REX_W); 
     400            } 
    372401        } 
    373402        stackpush -= numpara; 
    374403        c = genadjesp(c,-numpara); 
    375404    } 
    376405    return c; 
    377406} 
    378407 
    379408 
    380409/********************************* 
    381410 * Generate code for a logical expression. 
    382411 * Input: 
    383412 *      e       elem 
    384413 *      jcond 
    385414 *         bit 1 if TRUE then goto jump address if e 
    386415 *               if FALSE then goto jump address if !e 
    387416 *         2    don't call save87() 
    388417 *      fltarg   FLcode or FLblock, flavor of target if e evaluates to jcond 
    389418 *      targ    either code or block pointer to destination 
    390419 */ 
    391420 
    392421code *logexp(elem *e,int jcond,unsigned fltarg,code *targ) 
    393 { code *cc,*c,*ce,*cnop; 
     422{ code *c,*ce,*cnop; 
    394423  regm_t retregs; 
    395424  unsigned op; 
    396   int no87; 
    397425 
    398426  //printf("logexp(e = %p, jcond = %d)\n", e, jcond); 
    399   no87 = (jcond & 2) == 0; 
     427  int no87 = (jcond & 2) == 0; 
    400428  _chkstack(); 
    401   cc = docommas(&e);            /* scan down commas                     */ 
     429  code *cc = docommas(&e);            // scan down commas 
    402430  cgstate.stackclean++; 
    403431 
    404432  if (EOP(e) && !e->Ecount)     /* if operator and not common sub */ 
    405433  {     con_t regconsave; 
    406434 
    407435        switch (e->Eoper) 
    408436        {   case OPoror: 
    409437                if (jcond & 1) 
    410438                {       c = logexp(e->E1,jcond,fltarg,targ); 
    411439                        regconsave = regcon; 
    412440                        ce = logexp(e->E2,jcond,fltarg,targ); 
    413441                } 
    414442                else 
    415443                {       cnop = gennop(CNIL); 
    416444                        c = logexp(e->E1,jcond | 1,FLcode,cnop); 
    417445                        regconsave = regcon; 
    418446                        ce = logexp(e->E2,jcond,fltarg,targ); 
    419447                        ce = cat(ce,cnop); 
    420448                } 
    421449                cnop = CNIL; 
     
    438466                freenode(e); 
    439467                c = cat4(cc,c,ce,cnop); 
    440468                goto Lret; 
    441469 
    442470            case OPnot: 
    443471                jcond ^= 1; 
    444472            case OPbool: 
    445473            case OPs8int: 
    446474            case OPu8int: 
    447475            case OPs16_32: 
    448476            case OPu16_32: 
    449477            case OPs32_64: 
    450478            case OPu32_64: 
    451479            case OPu32_d: 
    452480            case OPd_ld: 
    453481                c = logexp(e->E1,jcond,fltarg,targ); 
    454482                freenode(e); 
    455483                goto Lretc; 
    456484 
    457485            case OPcond: 
    458             {   code *cnop2; 
    459                 con_t regconold; 
    460  
    461                 cnop2 = gennop(CNIL);   /* addresses of start of leaves */ 
     486            { 
     487                code *cnop2 = gennop(CNIL);   // addresses of start of leaves 
    462488                cnop = gennop(CNIL); 
    463489                c = logexp(e->E1,FALSE,FLcode,cnop2);   /* eval condition */ 
    464                 regconold = regcon; 
     490                con_t regconold = regcon; 
    465491                ce = logexp(e->E2->E1,jcond,fltarg,targ); 
    466492                ce = genjmp(ce,JMP,FLcode,(block *) cnop); /* skip second leaf */ 
    467493 
    468494                regconsave = regcon; 
    469495                regcon = regconold; 
    470496 
    471497                code_next(cnop2) = logexp(e->E2->E2,jcond,fltarg,targ); 
    472498                andregcon(&regconold); 
    473499                andregcon(&regconsave); 
    474500                freenode(e->E2); 
    475501                freenode(e); 
    476502                c = cat6(cc,c,NULL,ce,cnop2,cnop); 
    477503                goto Lret; 
    478504            } 
    479505        } 
    480506  } 
    481507 
    482   /* Special code for signed long compare       */ 
     508  /* Special code for signed long compare. 
     509   * Not necessary for I64 until we do cents. 
     510   */ 
    483511  if (OTrel2(e->Eoper) &&               /* if < <= >= >                 */ 
    484512      !e->Ecount && 
    485       ( (!I32 && tybasic(e->E1->Ety) == TYlong  && tybasic(e->E2->Ety) == TYlong) || 
    486         ( I32 && tybasic(e->E1->Ety) == TYllong && tybasic(e->E2->Ety) == TYllong)) 
     513      ( (I16 && tybasic(e->E1->Ety) == TYlong  && tybasic(e->E2->Ety) == TYlong) || 
     514        (I32 && tybasic(e->E1->Ety) == TYllong && tybasic(e->E2->Ety) == TYllong)) 
    487515     ) 
    488516  { 
    489517        c = longcmp(e,jcond,fltarg,targ); 
    490518        goto Lretc; 
    491519  } 
    492520 
    493521  retregs = mPSW;               /* return result in flags               */ 
    494522  op = jmpopcode(e);            /* get jump opcode                      */ 
    495523  if (!(jcond & 1)) 
    496524        op ^= 0x101;            // toggle jump condition(s) 
    497525  c = codelem(e,&retregs,TRUE); /* evaluate elem                        */ 
    498526  if (no87) 
    499527        c = cat(c,cse_flush(no87));     // flush CSE's to memory 
    500528  genjmp(c,op,fltarg,(block *) targ);   /* generate jmp instruction     */ 
    501529Lretc: 
    502530  c = cat(cc,c); 
    503531Lret: 
    504532  cgstate.stackclean--; 
    505533  return c; 
    506534} 
    507535 
    508536 
    509537/****************************** 
    510538 * Routine to aid in setting things up for gen(). 
    511539 * Look for common subexpression. 
    512540 * Can handle indirection operators, but not if they're common subs. 
    513541 * Input: 
    514542 *      e ->    elem where we get some of the data from 
    515543 *      cs ->   partially filled code to add 
    516544 *      op =    opcode 
    517545 *      reg =   reg field of (mod reg r/m) 
    518546 *      offset = data to be added to Voffset field 
    519547 *      keepmsk = mask of registers we must not destroy 
    520548 *      desmsk  = mask of registers destroyed by executing the instruction 
    521549 * Returns: 
    522550 *      pointer to code generated 
    523551 */ 
    524552 
    525 code *loadea(elem *e,code __ss *cs,unsigned op,unsigned reg,targ_size_t offset, 
     553code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    526554        regm_t keepmsk,regm_t desmsk) 
    527 { unsigned i; 
    528   regm_t rm; 
    529   tym_t tym; 
     555
    530556  code *c,*cg,*cd; 
    531557 
    532558#ifdef DEBUG 
    533559  if (debugw) 
    534560    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%ld keepmsk=x%x desmsk=x%x\n", 
    535561            e,cs,op,reg,offset,keepmsk,desmsk); 
    536562#endif 
    537563 
    538564  assert(e); 
    539565  cs->Iflags = 0; 
    540566  cs->Irex = 0; 
    541567  cs->Iop = op; 
    542   if (I32 && op >= 0x100)               /* if 2 byte opcode             */ 
     568  if (!I16 && op >= 0x100)               // if 2 byte opcode 
    543569  {     cs->Iop = op >> 8; 
    544570        cs->Iop2 = op; 
    545571  } 
    546   tym = e->Ety; 
     572  tym_t tym = e->Ety; 
     573  int sz = tysize(tym); 
    547574 
    548575  /* Determine if location we want to get is in a register. If so,      */ 
    549576  /* substitute the register for the EA.                                */ 
    550577  /* Note that operators don't go through this. CSE'd operators are     */ 
    551578  /* picked up by comsub().                                             */ 
    552579  if (e->Ecount &&                      /* if cse                       */ 
    553580      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    554581      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
    555582      (op != 0xFF || reg != 3) &&       /* and not CALLF MEM16          */ 
    556583      (op & 0xFFF8) != 0xD8)            // and not 8087 opcode 
    557   {     int sz; 
    558  
     584  { 
    559585        assert(!EOP(e));                /* can't handle this            */ 
    560         rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; /* possible regs                */ 
    561         sz = tysize(tym); 
    562         if (sz > REGSIZE) 
     586        regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 
     587        if (sz > REGSIZE)               // value is in 2 or 4 registers 
    563588        { 
    564                 if (!I32 && sz == 8) 
     589                if (I16 && sz == 8)     // value is in 4 registers 
    565590                {       static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 
    566591                        rm &= rmask[offset >> 1]; 
    567592                } 
    568593 
    569594                else if (offset) 
    570595                        rm &= mMSW;             /* only high words      */ 
    571596                else 
    572597                        rm &= mLSW;             /* only low words       */ 
    573598        } 
    574         for (i = 0; rm; i++) 
     599        for (unsigned i = 0; rm; i++) 
    575600        {       if (mask[i] & rm) 
    576601                {       if (regcon.cse.value[i] == e && // if register has elem 
    577602                            /* watch out for a CWD destroying DX        */ 
    578603                            !(i == DX && op == 0xF7 && desmsk & mDX)) 
    579604                        { 
    580605                                /* if ES, then it can only be a load    */ 
    581606                                if (i == ES) 
    582607                                {       if (op != 0x8B) 
    583608                                            goto L1;    /* not a load   */ 
    584609                                        cs->Iop = 0x8C; /* MOV reg,ES   */ 
    585                                         cs->Irm = modregrm(3,0,reg); 
     610                                        cs->Irm = modregrm(3,0,reg & 7); 
     611                                        if (reg & 8) 
     612                                            code_orrex(cs, REX_B); 
    586613                                } 
    587                                 else    /* XXX reg,i                    */ 
    588                                         cs->Irm = modregrm(3,reg,i); 
     614                                else    // XXX reg,i 
     615                                { 
     616                                    cs->Irm = modregrm(3,reg & 7,i & 7); 
     617                                    if (reg & 8) 
     618                                        code_orrex(cs, REX_R); 
     619                                    if (i & 8) 
     620                                        code_orrex(cs, REX_B); 
     621                                } 
    589622                                c = CNIL; 
    590623                                goto L2; 
    591624                        } 
    592625                        rm &= ~mask[i]; 
    593626                } 
    594627        } 
    595628  } 
    596629 
    597630L1: 
    598631  c = getlvalue(cs,e,keepmsk); 
    599632  if (offset == REGSIZE) 
    600633        getlvalue_msw(cs); 
    601634  else 
    602635        cs->IEVoffset1 += offset; 
    603   cs->Irm |= modregrm(0,reg,0);         /* OR in reg field              */ 
    604   if (I32
     636  code_newreg(cs, reg);                         // OR in reg field 
     637  if (!I16
    605638  { 
    606639      if (reg == 6 && op == 0xFF ||             /* don't PUSH a word    */ 
    607640          op == 0x0FB7 || op == 0x0FBF ||       /* MOVZX/MOVSX          */ 
    608641          (op & 0xFFF8) == 0xD8 ||              /* 8087 instructions    */ 
    609642          op == 0x8D)                           /* LEA                  */ 
    610643            cs->Iflags &= ~CFopsize; 
    611644  } 
    612645  else if ((op & 0xFFF8) == 0xD8 && ADDFWAIT()) 
    613646        cs->Iflags |= CFwait; 
    614647L2: 
    615648  cg = getregs(desmsk);                 /* save any regs we destroy     */ 
    616649 
    617650  /* KLUDGE! fix up DX for divide instructions */ 
    618651  cd = CNIL; 
    619652  if (op == 0xF7 && desmsk == (mAX|mDX))        /* if we need to fix DX */ 
    620653  {     if (reg == 7)                           /* if IDIV              */ 
    621                 cd = gen1(cd,0x99);             /* CWD                  */ 
    622         else if (reg == 6)                      /* if DIV               */ 
    623                 cd = genregs(cd,0x33,DX,DX);    /* CLR DX               */ 
     654        {   cd = gen1(cd,0x99);                 // CWD 
     655            if (I64 && sz == 8) 
     656                code_orrex(cd, REX_W); 
     657        } 
     658        else if (reg == 6)                      // if DIV 
     659        {   cd = genregs(cd,0x33,DX,DX);        // XOR DX,DX 
     660            if (I64 && sz == 8) 
     661                code_orrex(cd, REX_W); 
     662        } 
    624663  } 
    625664 
    626665  // Eliminate MOV reg,reg 
    627666  if ((cs->Iop & 0xFC) == 0x88 && 
    628       (cs->Irm & 0xC7) == modregrm(3,0,reg)) 
    629         cs->Iop = NOP; 
     667      (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 
     668  { 
     669        unsigned r = cs->Irm & 7; 
     670        if (cs->Irex & REX_B) 
     671            r |= 8; 
     672        if (r == reg) 
     673            cs->Iop = NOP; 
     674  } 
    630675 
    631676  return cat4(c,cg,cd,gen(CNIL,cs)); 
    632677} 
    633678 
    634679 
    635680/************************** 
    636681 * Get addressing mode. 
    637682 */ 
    638683 
    639684unsigned getaddrmode(regm_t idxregs) 
    640685{ 
    641     unsigned reg; 
    642685    unsigned mode; 
    643686 
    644     if (I32) 
    645     {   reg = findreg(idxregs & (ALLREGS | mBP)); 
    646         mode = modregrm(2,0,reg); 
    647     } 
    648     else 
     687    if (I16) 
    649688    { 
    650689        mode =  (idxregs & mBX) ? modregrm(2,0,7) :     /* [BX] */ 
    651690                (idxregs & mDI) ? modregrm(2,0,5):      /* [DI] */ 
    652691                (idxregs & mSI) ? modregrm(2,0,4):      /* [SI] */ 
    653692                                  (assert(0),1); 
    654693    } 
     694    else 
     695    {   unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 
     696        mode = modregrmx(2,0,reg); 
     697    } 
    655698    return mode; 
     699} 
     700 
     701void setaddrmode(code *c, regm_t idxregs) 
     702{ 
     703    unsigned mode = getaddrmode(idxregs); 
     704    c->Irm = mode & 0xFF; 
     705    c->Irex &= ~REX_B; 
     706    c->Irex |= mode >> 16; 
    656707} 
    657708 
    658709/********************************************** 
    659710 */ 
    660711 
    661712void getlvalue_msw(code *c) 
    662713{ 
    663714    if (c->IFL1 == FLreg) 
    664     {   unsigned regmsw; 
    665  
    666         regmsw = c->IEVsym1->Sregmsw; 
    667         c->Irm = (c->Irm & ~7) | regmsw; 
     715    { 
     716        unsigned regmsw = c->IEVsym1->Sregmsw; 
     717        c->Irm = (c->Irm & ~7) | (regmsw & 7); 
     718        if (regmsw & 8) 
     719            c->Irex |= REX_B; 
     720        else 
     721            c->Irex &= ~REX_B; 
    668722    } 
    669723    else 
    670724        c->IEVoffset1 += REGSIZE; 
    671725} 
    672726 
    673727/********************************************** 
    674728 */ 
    675729 
    676730void getlvalue_lsw(code *c) 
    677731{ 
    678732    if (c->IFL1 == FLreg) 
    679     {   unsigned reglsw; 
    680  
    681         reglsw = c->IEVsym1->Sreglsw; 
    682         c->Irm = (c->Irm & ~7) | reglsw; 
     733    { 
     734        unsigned reglsw = c->IEVsym1->Sreglsw; 
     735        c->Irm = (c->Irm & ~7) | (reglsw & 7); 
     736        if (reglsw & 8) 
     737            c->Irex |= REX_B; 
     738        else 
     739            c->Irex &= ~REX_B; 
    683740    } 
    684741    else 
    685742        c->IEVoffset1 -= REGSIZE; 
    686743} 
    687744 
    688745/****************** 
    689746 * Compute addressing mode. 
    690747 * Generate & return sequence of code (if any). 
    691748 * Return in cs the info on it. 
    692749 * Input: 
    693750 *      pcs ->  where to store data about addressing mode 
    694751 *      e ->    the lvalue elem 
    695752 *      keepmsk mask of registers we must not destroy or use 
    696753 *              if (keepmsk & RMstore), this will be only a store operation 
    697754 *              into the lvalue 
    698755 *              if (keepmsk & RMload), this will be a read operation only 
    699756 */ 
    700757 
    701 code *getlvalue(code __ss *pcs,elem *e,regm_t keepmsk) 
     758code *getlvalue(code *pcs,elem *e,regm_t keepmsk) 
    702759{ regm_t idxregs; 
    703760  unsigned fl,f,opsave; 
    704761  code *c; 
    705762  elem *e1; 
    706763  elem *e11; 
    707764  elem *e12; 
    708765  bool e1isadd,e1free; 
    709766  unsigned reg; 
    710   tym_t ty; 
    711767  tym_t e1ty; 
    712768  symbol *s; 
    713   unsigned sz; 
    714769 
    715770  //printf("getlvalue(e = %p)\n",e); 
    716771  //elem_print(e); 
    717772  assert(e); 
    718773  elem_debug(e); 
    719774  if (e->Eoper == OPvar || e->Eoper == OPrelconst) 
    720775  {     s = e->EV.sp.Vsym; 
    721776        fl = s->Sfl; 
    722777        if (tyfloating(s->ty())) 
    723778            obj_fltused(); 
    724779  } 
    725780  else 
    726781        fl = FLoper; 
    727782  pcs->IFL1 = fl; 
    728783  pcs->Iflags = CFoff;                  /* only want offsets            */ 
    729784  pcs->Irex = 0; 
    730785  pcs->IEVoffset1 = 0; 
    731   ty = e->Ety; 
     786 
     787  tym_t ty = e->Ety; 
     788  unsigned sz = tysize(ty); 
    732789  if (tyfloating(ty)) 
    733790        obj_fltused(); 
    734   sz = tysize(ty); 
    735   if (I32 && sz == SHORTSIZE) 
     791  else if (I64 && sz == 8) 
     792        pcs->Irex |= REX_W; 
     793  if (!I16 && sz == SHORTSIZE) 
    736794        pcs->Iflags |= CFopsize; 
    737795  if (ty & mTYvolatile) 
    738796        pcs->Iflags |= CFvolatile; 
    739797  c = CNIL; 
    740798  switch (fl) 
    741799  { 
    742800#if 0 && TARGET_LINUX 
    743801    case FLgot: 
    744802    case FLgotoff: 
    745803        gotref = 1; 
    746804        pcs->IEVsym1 = s; 
    747805        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    748806        if (e->Eoper == OPvar && fl == FLgot) 
    749807        { 
    750808            code *c1; 
    751809            int saveop = pcs->Iop; 
    752810            idxregs = allregs & ~keepmsk;       // get a scratch register 
    753811            c = allocreg(&idxregs,&reg,TYptr); 
    754812            pcs->Irm = modregrm(2,reg,BX);      // BX has GOT 
    755813            pcs->Isib = 0; 
     
    801859            e11 = e1->E1; 
    802860        } 
    803861 
    804862        /* First see if we can replace *(e+&v) with 
    805863         *      MOV     idxreg,e 
    806864         *      EA =    [ES:] &v+idxreg 
    807865         */ 
    808866 
    809867        if (e1isadd && 
    810868            e12->Eoper == OPrelconst && 
    811869            (f = el_fl(e12)) != FLfardata && 
    812870            e1->Ecount == e1->Ecomsub && 
    813871            (!e1->Ecount || (~keepmsk & ALLREGS & mMSW) || (e1ty != TYfptr && e1ty != TYhptr)) && 
    814872            tysize(e11->Ety) == REGSIZE 
    815873           ) 
    816874        {   unsigned char t;            /* component of r/m field */ 
    817875            int ss; 
    818876            int ssi; 
    819877 
    820878            /*assert(datafl[f]);*/              /* what if addr of func? */ 
    821             if (I32
     879            if (!I16
    822880            {   /* Any register can be an index register        */ 
    823                 idxregs = allregs & ~keepmsk; 
     881                regm_t idxregs = allregs & ~keepmsk; 
    824882                assert(idxregs); 
    825883 
    826884                /* See if e1->E1 can be a scaled index  */ 
    827885                ss = isscaledindex(e11); 
    828886                if (ss) 
    829887                { 
    830888                    /* Load index register with result of e11->E1       */ 
    831889                    c = cdisscaledindex(e11,&idxregs,keepmsk); 
    832890                    reg = findreg(idxregs); 
    833891#if 0 && TARGET_LINUX 
    834892                    if (f == FLgot || f == FLgotoff)    // config.flags3 & CFG3pic 
    835893                    { 
    836894                        gotref = 1; 
    837895                        pcs->Irm = modregrm(2,0,4); 
    838896                        pcs->Isib = modregrm(ss,reg,BX); 
    839897                    } 
    840898                    else 
    841899#endif 
    842900                    { 
    843901                        t = stackfl[f] ? 2 : 0; 
    844902                        pcs->Irm = modregrm(t,0,4); 
    845                         pcs->Isib = modregrm(ss,reg,5); 
     903                        pcs->Isib = modregrm(ss,reg & 7,5); 
     904                        if (reg & 8) 
     905                            pcs->Irex |= REX_X; 
    846906                    } 
    847907                } 
    848908                else if ((e11->Eoper == OPmul || e11->Eoper == OPshl) && 
    849909                         !e11->Ecount && 
    850910                         e11->E2->Eoper == OPconst && 
    851911                         (ssi = ssindex(e11->Eoper,e11->E2->EV.Vuns)) != 0 
    852912                        ) 
    853913                { 
    854914                    regm_t scratchm; 
    855                     unsigned r; 
    856                     int ss1; 
    857915                    int ss2; 
    858                     char ssflags; 
    859916 
    860917#if 0 && TARGET_LINUX 
    861918                    assert(f != FLgot && f != FLgotoff); 
    862919#endif 
    863                     ssflags = ssindex_array[ssi].ssflags; 
     920                    char ssflags = ssindex_array[ssi].ssflags; 
    864921                    if (ssflags & SSFLnobp && stackfl[f]) 
    865922                        goto L6; 
    866923 
    867924                    // Load index register with result of e11->E1 
    868925                    c = scodelem(e11->E1,&idxregs,keepmsk,TRUE); 
    869926                    reg = findreg(idxregs); 
    870927 
    871                     ss1 = ssindex_array[ssi].ss1; 
     928                    int ss1 = ssindex_array[ssi].ss1; 
    872929                    if (ssflags & SSFLlea) 
    873930                    { 
    874931                        assert(!stackfl[f]); 
    875932                        pcs->Irm = modregrm(2,0,4); 
    876                         pcs->Isib = modregrm(ss1,reg,reg); 
     933                        pcs->Isib = modregrm(ss1,reg & 7,reg & 7); 
     934                        if (reg & 8) 
     935                            pcs->Irex |= REX_X | REX_B; 
    877936                    } 
    878937                    else 
    879938                    {   int rbase; 
     939                        unsigned r; 
    880940 
    881941                        scratchm = ALLREGS & ~keepmsk; 
    882942                        c = cat(c,allocreg(&scratchm,&r,TYint)); 
    883943 
    884944                        if (ssflags & SSFLnobase1) 
    885945                        {   t = 0; 
    886946                            rbase = 5; 
    887947                        } 
    888948                        else 
    889949                        {   t = 0; 
    890950                            rbase = reg; 
    891951                            if (rbase == BP) 
    892952                            {   static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 
    893953 
    894954                                // IMUL r,BP,imm32 
    895                                 c = genc2(c,0x69,modregrm(3,r,BP),imm32[ss1]); 
     955                                c = genc2(c,0x69,modregxrm(3,r,BP),imm32[ss1]); 
    896956                                goto L7; 
    897957                            } 
    898958                        } 
    899959 
    900                         c = gen2sib(c,0x8D,modregrm(t,r,4),modregrm(ss1,reg,rbase)); 
     960                        c = gen2sib(c,0x8D,modregxrm(t,r,4),modregrm(ss1,reg & 7,rbase & 7)); 
     961                        if (reg & 8) 
     962                            code_orrex(c, REX_X); 
     963                        if (rbase & 8) 
     964                            code_orrex(c, REX_B); 
     965 
    901966                        if (ssflags & SSFLnobase1) 
    902967                        {   code_last(c)->IFL1 = FLconst; 
    903968                            code_last(c)->IEV1.Vuns = 0; 
    904969                        } 
    905970                    L7: 
    906971                        if (ssflags & SSFLnobase) 
    907972                        {   t = stackfl[f] ? 2 : 0; 
    908973                            rbase = 5; 
    909974                        } 
    910975                        else 
    911976                        {   t = 2; 
    912977                            rbase = r; 
    913978                            assert(rbase != BP); 
    914979                        } 
    915980                        pcs->Irm = modregrm(t,0,4); 
    916                         pcs->Isib = modregrm(ssindex_array[ssi].ss2,r,rbase); 
     981                        pcs->Isib = modregrm(ssindex_array[ssi].ss2,r & 7,rbase & 7); 
     982                        if (r & 8) 
     983                            code_orrex(pcs, REX_X); 
     984                        if (rbase & 8) 
     985                            code_orrex(pcs, REX_B); 
    917986                    } 
    918987                    freenode(e11->E2); 
    919988                    freenode(e11); 
    920989                } 
    921990                else 
    922991                { 
    923992                 L6: 
    924993                    /* Load index register with result of e11   */ 
    925994                    c = scodelem(e11,&idxregs,keepmsk,TRUE); 
    926                     pcs->Irm = getaddrmode(idxregs); 
     995                    setaddrmode(pcs, idxregs); 
    927996#if 0 && TARGET_LINUX 
    928997                    if (e12->EV.sp.Vsym->Sfl == FLgot || e12->EV.sp.Vsym->Sfl == FLgotoff) 
    929998                    { 
    930999                        gotref = 1; 
    9311000#if 1 
    9321001                        reg = findreg(idxregs & (ALLREGS | mBP)); 
    9331002                        pcs->Irm = modregrm(2,0,4); 
    9341003                        pcs->Isib = modregrm(0,reg,BX); 
    9351004#else 
    9361005                        pcs->Isib = modregrm(0,pcs->Irm,BX); 
    9371006                        pcs->Irm = modregrm(2,0,4); 
    9381007#endif 
    9391008                    } 
    9401009                    else 
    9411010#endif 
    9421011                    if (stackfl[f])             /* if we need [EBP] too */ 
    943                     { 
    944                         pcs->Isib = modregrm(0,pcs->Irm,BP); 
     1012                    {   unsigned idx = pcs->Irm & 7; 
     1013                        if (pcs->Irex & REX_B) 
     1014                            pcs->Irex = (pcs->Irex & ~REX_B) | REX_X; 
     1015                        pcs->Isib = modregrm(0,idx,BP); 
    9451016                        pcs->Irm = modregrm(2,0,4); 
    9461017                    } 
    9471018                } 
    9481019            } 
    9491020            else 
    9501021            { 
    9511022                idxregs = IDXREGS & ~keepmsk;   /* only these can be index regs */ 
    9521023                assert(idxregs); 
    9531024#if 0 && TARGET_LINUX 
    9541025                assert(f != FLgot && f != FLgotoff); 
    9551026#endif 
    9561027                if (stackfl[f])                 /* if stack data type   */ 
    9571028                {   idxregs &= mSI | mDI;       /* BX can't index off stack */ 
    9581029                    if (!idxregs) goto L1;      /* index regs aren't avail */ 
    9591030                    t = 6;                      /* [BP+SI+disp]         */ 
    9601031                } 
    9611032                else 
    9621033                    t = 0;                      /* [SI + disp]          */ 
    9631034                c = scodelem(e11,&idxregs,keepmsk,TRUE); /* load idx reg */ 
    9641035                pcs->Irm = getaddrmode(idxregs) ^ t; 
     
    9811052            {   unsigned flagsave; 
    9821053 
    9831054                idxregs = IDXREGS & ~keepmsk; 
    9841055                c = cat(c,allocreg(&idxregs,&reg,TYoffset)); 
    9851056 
    9861057                /* If desired result is a far pointer, we'll have       */ 
    9871058                /* to load another register with the segment of v       */ 
    9881059                if (e1ty == TYfptr) 
    9891060                { 
    9901061                    unsigned msreg; 
    9911062 
    9921063                    idxregs |= mMSW & ALLREGS & ~keepmsk; 
    9931064                    c = cat(c,allocreg(&idxregs,&msreg,TYfptr)); 
    9941065                    msreg = findregmsw(idxregs); 
    9951066                                                /* MOV msreg,segreg     */ 
    9961067                    c = genregs(c,0x8C,segfl[f],msreg); 
    9971068                } 
    9981069                opsave = pcs->Iop; 
    9991070                flagsave = pcs->Iflags; 
    10001071                pcs->Iop = 0x8D; 
    1001                 pcs->Irm |= modregrm(0,reg,0); 
    1002                 if (I32
     1072                code_newreg(pcs, reg); 
     1073                if (!I16
    10031074                    pcs->Iflags &= ~CFopsize; 
    10041075                c = gen(c,pcs);                 /* LEA idxreg,EA        */ 
    10051076                cssave(e1,idxregs,TRUE); 
    1006                 if (I32
     1077                if (!I16
    10071078                    pcs->Iflags = flagsave; 
    10081079                if (stackfl[f] && (config.wflags & WFssneds))   // if pointer into stack 
    10091080                    pcs->Iflags |= CFss;        // add SS: override 
    10101081                pcs->Iop = opsave; 
    10111082                pcs->IFL1 = FLoffset; 
    10121083                pcs->IEV1.Vuns = 0; 
    1013                 pcs->Irm = getaddrmode(idxregs); 
     1084                setaddrmode(pcs, idxregs); 
    10141085            } 
    10151086            freenode(e12); 
    10161087            if (e1free) 
    10171088                freenode(e1); 
    10181089            goto Lptr; 
    10191090        } 
    10201091 
    10211092        L1: 
    10221093 
    10231094        /* The rest of the cases could be a far pointer */ 
    10241095 
    1025         idxregs = (I32 ? allregs : IDXREGS) & ~keepmsk; /* only these can be index regs */ 
     1096        idxregs = (I16 ? IDXREGS : allregs) & ~keepmsk; // only these can be index regs 
    10261097        assert(idxregs); 
    1027         if (I32 && sz == REGSIZE && keepmsk & RMstore) 
     1098        if (!I16 && 
     1099            (sz == REGSIZE || (I64 && sz == 4)) && 
     1100            keepmsk & RMstore) 
    10281101            idxregs |= regcon.mvar; 
    10291102 
    10301103#if !TARGET_FLAT 
    10311104        switch (e1ty) 
    10321105        {   case TYfptr:                        /* if far pointer       */ 
    10331106            case TYhptr: 
    10341107                idxregs = (mES | IDXREGS) & ~keepmsk;   // need segment too 
    10351108                assert(idxregs & mES); 
    10361109                pcs->Iflags |= CFes;            /* ES segment override  */ 
    10371110                break; 
    10381111            case TYsptr:                        /* if pointer to stack  */ 
    10391112                if (config.wflags & WFssneds)   // if SS != DS 
    10401113                    pcs->Iflags |= CFss;        /* then need SS: override */ 
    10411114                break; 
    10421115            case TYcptr:                        /* if pointer to code   */ 
    10431116                pcs->Iflags |= CFcs;            /* then need CS: override */ 
    10441117                break; 
    10451118        } 
    10461119#endif 
    10471120        pcs->IFL1 = FLoffset; 
     
    10541127         */ 
    10551128 
    10561129        if (e1isadd && e12->Eoper == OPconst && 
    10571130            tysize(e12->Ety) == REGSIZE && 
    10581131            (!e1->Ecount || !e1free) 
    10591132           ) 
    10601133        {   int ss; 
    10611134 
    10621135            pcs->IEV1.Vuns = e12->EV.Vuns; 
    10631136            freenode(e12); 
    10641137            if (e1free) freenode(e1); 
    10651138            if (I32 && e11->Eoper == OPadd && !e11->Ecount && 
    10661139                tysize(e11->Ety) == REGSIZE) 
    10671140            { 
    10681141                e12 = e11->E2; 
    10691142                e11 = e11->E1; 
    10701143                e1 = e1->E1; 
    10711144                e1free = TRUE; 
    10721145                goto L4; 
    10731146            } 
    1074             if (I32 && (ss = isscaledindex(e11)) != 0) 
     1147            if (!I16 && (ss = isscaledindex(e11)) != 0) 
    10751148            {   // (v * scale) + const 
    10761149                c = cdisscaledindex(e11,&idxregs,keepmsk); 
    10771150                reg = findreg(idxregs); 
    10781151                pcs->Irm = modregrm(0,0,4); 
    1079                 pcs->Isib = modregrm(ss,reg,5); 
     1152                pcs->Isib = modregrm(ss,reg & 7,5); 
     1153                if (reg & 8) 
     1154                    pcs->Irex |= REX_X; 
    10801155            } 
    10811156            else 
    10821157            { 
    10831158                c = scodelem(e11,&idxregs,keepmsk,TRUE); // load index reg 
    1084                 pcs->Irm = getaddrmode(idxregs); 
     1159                setaddrmode(pcs, idxregs); 
    10851160            } 
    10861161            goto Lptr; 
    10871162        } 
    10881163 
    10891164        /* Look for *(v1 + v2) 
    10901165         *      EA = [v1][v2] 
    10911166         */ 
    10921167 
    1093         if (I32 && e1isadd && (!e1->Ecount || !e1free) && 
     1168        if (!I16 && e1isadd && (!e1->Ecount || !e1free) && 
    10941169            tysize[e1ty] == REGSIZE) 
    10951170        {   code *c2; 
    10961171            regm_t idxregs2; 
    10971172            unsigned base,index; 
    10981173            int ss; 
    10991174 
    11001175        L4: 
    11011176            // Look for *(v1 + v2 << scale) 
    11021177            ss = isscaledindex(e12); 
    11031178            if (ss) 
    11041179            { 
    11051180                c = scodelem(e11,&idxregs,keepmsk,TRUE); 
    11061181                idxregs2 = allregs & ~(idxregs | keepmsk); 
    11071182                c2 = cdisscaledindex(e12,&idxregs2,keepmsk | idxregs); 
    11081183            } 
    11091184 
    11101185            // Look for *(v1 << scale + v2) 
    11111186            else if ((ss = isscaledindex(e11)) != 0) 
    11121187            { 
    11131188                idxregs2 = idxregs; 
     
    11221197                    ) 
    11231198            { 
    11241199                pcs->IEV1.Vuns = e11->E2->EV.Vuns; 
    11251200                idxregs2 = idxregs; 
    11261201                c = cdisscaledindex(e11->E1,&idxregs2,keepmsk); 
    11271202                idxregs = allregs & ~(idxregs2 | keepmsk); 
    11281203                c2 = scodelem(e12,&idxregs,keepmsk | idxregs2,TRUE); 
    11291204                freenode(e11->E2); 
    11301205                freenode(e11); 
    11311206            } 
    11321207            else 
    11331208            { 
    11341209                c = scodelem(e11,&idxregs,keepmsk,TRUE); 
    11351210                idxregs2 = allregs & ~(idxregs | keepmsk); 
    11361211                c2 = scodelem(e12,&idxregs2,keepmsk | idxregs,TRUE); 
    11371212            } 
    11381213            c = cat(c,c2); 
    11391214            base = findreg(idxregs); 
    11401215            index = findreg(idxregs2); 
    11411216            pcs->Irm  = modregrm(2,0,4); 
    1142             pcs->Isib = modregrm(ss,index,base); 
     1217            pcs->Isib = modregrm(ss,index & 7,base & 7); 
     1218            if (index & 8) 
     1219                pcs->Irex |= REX_X; 
     1220            if (base & 8) 
     1221                pcs->Irex |= REX_B; 
    11431222            if (e1free) freenode(e1); 
    11441223            goto Lptr; 
    11451224        } 
    11461225 
    11471226        /* give up and replace *e1 with 
    11481227         *      MOV     idxreg,e 
    11491228         *      EA =    0[idxreg] 
    11501229         * pinholeopt() will usually correct the 0, we need it in case 
    11511230         * we have a pointer to a long and need an offset to the second 
    11521231         * word. 
    11531232         */ 
    11541233 
    11551234        assert(e1free); 
    11561235        c = scodelem(e1,&idxregs,keepmsk,TRUE); /* load index register  */ 
    1157         pcs->Irm = getaddrmode(idxregs); 
     1236        setaddrmode(pcs, idxregs); 
    11581237    Lptr: 
    11591238        if (config.flags3 & CFG3ptrchk) 
    11601239            cod3_ptrchk(&c,pcs,keepmsk);        // validate pointer code 
    11611240        break; 
    11621241    case FLdatseg: 
    11631242        assert(0); 
    11641243#if 0 
    11651244        pcs->Irm = modregrm(0,0,BPRM); 
    11661245        pcs->IEVpointer1 = e->EVpointer; 
    11671246        break; 
    11681247#endif 
    11691248    case FLfltreg: 
    11701249        reflocal = TRUE; 
    11711250        pcs->Irm = modregrm(2,0,BPRM); 
    11721251        pcs->IEV1.Vint = 0; 
    11731252        break; 
    11741253    case FLreg: 
    11751254        goto L2; 
    11761255    case FLpara: 
    11771256        refparam = TRUE; 
    11781257        pcs->Irm = modregrm(2,0,BPRM); 
    11791258        goto L2; 
    11801259 
    11811260    case FLauto: 
    11821261        if (s->Sclass == SCfastpar && regcon.params & mask[s->Spreg]) 
    11831262        { 
    11841263            if (keepmsk & RMload) 
    11851264            { 
    11861265                if (sz == REGSIZE)      // could this be (sz <= REGSIZE) ? 
    11871266                { 
    1188                     pcs->Irm = modregrm(3,0,s->Spreg); 
     1267                    pcs->Irm = modregrm(3,0,s->Spreg & 7); 
     1268                    if (s->Spreg & 8) 
     1269                        pcs->Irex |= REX_B; 
    11891270                    regcon.used |= mask[s->Spreg]; 
    11901271                    break; 
    11911272                } 
    11921273            } 
    11931274            else 
    11941275                regcon.params &= ~mask[s->Spreg]; 
    11951276        } 
    11961277    case FLtmp: 
    11971278    case FLbprel: 
    11981279        reflocal = TRUE; 
    11991280        pcs->Irm = modregrm(2,0,BPRM); 
    12001281        goto L2; 
    12011282    case FLextern: 
    12021283        if (s->Sident[0] == '_' && memcmp(s->Sident + 1,"tls_array",10) == 0) 
    12031284        { 
    12041285#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    12051286            // Rewrite as GS:[0000] 
    12061287            pcs->Irm = modregrm(0, 0, BPRM); 
    12071288            pcs->IFL1 = FLconst; 
    12081289            pcs->IEV1.Vuns = 0; 
     
    12161297        goto L3; 
    12171298    case FLdata: 
    12181299    case FLudata: 
    12191300    case FLcsdata: 
    12201301#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    12211302    case FLgot: 
    12221303    case FLgotoff: 
    12231304    case FLtlsdata: 
    12241305#endif 
    12251306    L3: 
    12261307        pcs->Irm = modregrm(0,0,BPRM); 
    12271308    L2: 
    12281309        if (fl == FLreg) 
    12291310        {   assert(s->Sregm & regcon.mvar); 
    12301311            if ( 
    12311312                s->Sclass == SCregpar || 
    12321313                s->Sclass == SCparameter) 
    12331314            {   refparam = TRUE; 
    12341315                reflocal = TRUE;        // kludge to set up prolog 
    12351316            } 
    1236             pcs->Irm = modregrm(3,0,s->Sreglsw); 
     1317            pcs->Irm = modregrm(3,0,s->Sreglsw & 7); 
     1318            if (s->Sreglsw & 8) 
     1319                pcs->Irex |= REX_B; 
    12371320            if (e->EV.sp.Voffset == 1 && sz == 1) 
    12381321            {   assert(s->Sregm & BYTEREGS); 
     1322                assert(s->Sreglsw < 4); 
    12391323                pcs->Irm |= 4;                  // use 2nd byte of register 
    12401324            } 
    12411325            else 
    12421326                assert(!e->EV.sp.Voffset); 
    12431327        } 
    12441328        else if (s->ty() & mTYcs && !(fl == FLextern && LARGECODE)) 
    12451329        { 
    12461330            pcs->Iflags |= CFcs | CFoff; 
    12471331        } 
    12481332#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    12491333//      if (fl == FLtlsdata || s->ty() & mTYthread) 
    12501334//          pcs->Iflags |= CFgs; 
    12511335#endif 
    12521336        pcs->IEVsym1 = s; 
    12531337        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    12541338        if (sz == 1) 
    12551339        {   /* Don't use SI or DI for this variable     */ 
    12561340            s->Sflags |= GTbyte; 
    12571341            if (e->EV.sp.Voffset > 1) 
    12581342                s->Sflags &= ~GTregcand; 
    12591343        } 
    12601344        else if (e->EV.sp.Voffset) 
    12611345            s->Sflags &= ~GTregcand; 
    12621346        if (!(keepmsk & RMstore))               // if not store only 
    12631347        {   s->Sflags |= SFLread;               // assume we are doing a read 
    12641348        } 
    12651349        break; 
    12661350    case FLpseudo: 
    12671351#if MARS 
    12681352        assert(0); 
    12691353#else 
    1270     {   unsigned u; 
    1271  
    1272         u = s->Sreglsw; 
     1354    { 
     1355        unsigned u = s->Sreglsw; 
    12731356        c = getregs(pseudomask[u]); 
    12741357        pcs->Irm = modregrm(3,0,pseudoreg[u] & 7); 
    12751358        break; 
    12761359    } 
    12771360#endif 
    12781361    case FLfardata: 
    12791362        assert(!TARGET_FLAT); 
    12801363    case FLfunc:                                /* reading from code seg */ 
    12811364        if (config.exe & EX_flat) 
    12821365            goto L3; 
    12831366    Lfardata: 
    1284     {   regm_t regm; 
    1285         code *c1; 
    1286  
    1287         regm = ALLREGS & ~keepmsk;              /* need scratch register */ 
    1288         c1 = allocreg(&regm,&reg,TYint); 
     1367    { 
     1368        regm_t regm = ALLREGS & ~keepmsk;       // need scratch register 
     1369        code *c1 = allocreg(&regm,&reg,TYint); 
    12891370        /* MOV mreg,seg of symbol       */ 
    12901371        c = gencs(CNIL,0xB8 + reg,0,FLextern,s); 
    12911372        c->Iflags = CFseg; 
    1292         c = gen2(c,0x8E,modregrm(3,0,reg));     /* MOV ES,reg           */ 
     1373        c = gen2(c,0x8E,modregrmx(3,0,reg));     /* MOV ES,reg           */ 
    12931374        c = cat3(c1,getregs(mES),c); 
    12941375        pcs->Iflags |= CFes | CFoff;            /* ES segment override  */ 
    12951376        goto L3; 
    12961377    } 
    12971378 
    12981379    case FLstack: 
    1299         assert(I32); 
     1380        assert(!I16); 
    13001381        pcs->Irm = modregrm(2,0,4); 
    13011382        pcs->Isib = modregrm(0,4,SP); 
    13021383        pcs->IEVsym1 = s; 
    13031384        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    13041385        break; 
    13051386 
    13061387    default: 
    13071388#ifdef DEBUG 
    13081389        WRFL((enum FL)fl); 
    13091390        symbol_print(s); 
    13101391#endif 
    13111392        assert(0); 
    13121393  } 
    13131394  return c; 
    13141395} 
    13151396 
    13161397 
    13171398/******************************* 
    13181399 * Same as codelem(), but do not destroy the registers in keepmsk. 
    13191400 * Use scratch registers as much as possible, then use stack. 
     
    14321512 
    14331513        assert(i < REGMAX); 
    14341514        if (mi & tosave)        /* i = register to save                 */ 
    14351515        { 
    14361516            if (touse)          /* if any scratch registers             */ 
    14371517            {   for (j = 0; j < 8; j++) 
    14381518                {   regm_t mj = mask[j]; 
    14391519 
    14401520                    if (touse & mj) 
    14411521                    {   cs1 = genmovreg(cs1,j,i); 
    14421522                        cs2 = cat(genmovreg(CNIL,i,j),cs2); 
    14431523                        touse &= ~mj; 
    14441524                        mfuncreg &= ~mj; 
    14451525                        regcon.used |= mj; 
    14461526                        break; 
    14471527                    } 
    14481528                } 
    14491529                assert(j < 8); 
    14501530            } 
    14511531            else                        /* else use stack               */ 
     1532#if 0 
    14521533            {   int push,pop; 
    14531534 
    14541535                stackchanged = 1; 
    14551536                adjesp += REGSIZE; 
    14561537                if (i == ES) 
    14571538                {       push = 0x06; 
    14581539                        pop = 0x07; 
    14591540                } 
    14601541                else 
    14611542                {       push = 0x50 + i; 
    14621543                        pop = push | 8; 
    14631544                } 
    14641545                cs1 = gen1(cs1,push);                   /* PUSH i       */ 
    14651546                cs2 = cat(gen1(CNIL,pop),cs2);          /* POP i        */ 
    14661547            } 
     1548#else 
     1549            { 
     1550                stackchanged = 1; 
     1551                adjesp += REGSIZE; 
     1552                gensaverestore2(mask[i], &cs1, &cs2); 
     1553            } 
     1554#endif 
    14671555            cs3 = cat(getregs(mi),cs3); 
    14681556            tosave &= ~mi; 
    14691557        } 
    14701558  } 
    14711559  if (adjesp) 
    14721560  { 
    14731561        // If this is done an odd number of times, it 
    14741562        // will throw off the 8 byte stack alignment. 
    14751563        // We should *only* worry about this if a function 
    14761564        // was called in the code generation by codelem(). 
    14771565        int sz; 
    14781566        if (STACKALIGN == 16) 
    14791567            sz = -(adjesp & (STACKALIGN - 1)) & (STACKALIGN - 1); 
    14801568        else 
    14811569            sz = -(adjesp & 7) & 7; 
    1482         if (calledafunc && I32 && sz && (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 
    1483         {   code *cx; 
    1484  
     1570        if (calledafunc && !I16 && sz && (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 
     1571        { 
     1572            unsigned grex = I64 ? REX_W << 16 : 0; 
    14851573            regm_t mval_save = regcon.immed.mval; 
    14861574            regcon.immed.mval = 0;      // prevent reghasvalue() optimizations 
    14871575                                        // because c hasn't been executed yet 
    1488             cs1 = genc2(cs1,0x81,modregrm(3,5,SP),sz);  // SUB ESP,sz 
     1576            cs1 = genc2(cs1,0x81,grex | modregrm(3,5,SP),sz);  // SUB ESP,sz 
    14891577            regcon.immed.mval = mval_save; 
    14901578            cs1 = genadjesp(cs1, sz); 
    14911579 
    1492             cx = genc2(CNIL,0x81,modregrm(3,0,SP),sz);  // ADD ESP,sz 
     1580            code *cx = genc2(CNIL,0x81,grex | modregrm(3,0,SP),sz);  // ADD ESP,sz 
    14931581            cx = genadjesp(cx, -sz); 
    14941582            cs2 = cat(cx, cs2); 
    14951583        } 
    14961584 
    14971585        cs1 = genadjesp(cs1,adjesp); 
    14981586        cs2 = genadjesp(cs2,-adjesp); 
    14991587  } 
    15001588 
    15011589  calledafunc |= calledafuncsave; 
    15021590  msavereg &= ~keepmsk | overlap; /* remove from mask of regs to save   */ 
    15031591  mfuncreg &= oldmfuncreg;      /* update original                      */ 
    15041592#ifdef DEBUG 
    15051593  if (debugw) 
    15061594        printf("-scodelem(e=%p *pretregs=x%x keepmsk=x%x constflag=%d\n", 
    15071595                e,*pretregs,keepmsk,constflag); 
    15081596#endif 
    15091597  return cat4(cs1,c,cs3,cs2); 
    15101598} 
    15111599 
    15121600 
    15131601/***************************** 
    15141602 * Given an opcode and EA in cs, generate code 
    15151603 * for each floating register in turn. 
    15161604 * Input: 
    15171605 *      tym     either TYdouble or TYfloat 
    15181606 */ 
    15191607 
    1520 code *fltregs(code __ss *pcs,tym_t tym) 
     1608code *fltregs(code *pcs,tym_t tym) 
    15211609{   code *c; 
    15221610 
     1611    assert(!I64); 
    15231612    tym = tybasic(tym); 
    15241613    if (I32) 
    15251614    { 
    15261615        c = getregs((tym == TYfloat) ? mAX : mAX | mDX); 
    15271616        if (tym != TYfloat) 
    15281617        { 
    15291618            pcs->IEVoffset1 += REGSIZE; 
    15301619            NEWREG(pcs->Irm,DX); 
    15311620            c = gen(c,pcs); 
    15321621            pcs->IEVoffset1 -= REGSIZE; 
    15331622        } 
    15341623        NEWREG(pcs->Irm,AX); 
    15351624        c = gen(c,pcs); 
    15361625    } 
    15371626    else 
    15381627    { 
    15391628        c = getregs((tym == TYfloat) ? FLOATREGS_16 : DOUBLEREGS_16); 
    15401629        pcs->IEVoffset1 += (tym == TYfloat) ? 2 : 6; 
    15411630        if (tym == TYfloat) 
    15421631            NEWREG(pcs->Irm,DX); 
     
    15531642        {     pcs->IEVoffset1 -= 2; 
    15541643              NEWREG(pcs->Irm,CX); 
    15551644              gen(c,pcs); 
    15561645              pcs->IEVoffset1 -= 2;     /* note that exit is with Voffset unaltered */ 
    15571646              NEWREG(pcs->Irm,DX); 
    15581647              gen(c,pcs); 
    15591648        } 
    15601649    } 
    15611650    return c; 
    15621651} 
    15631652 
    15641653 
    15651654/***************************** 
    15661655 * Given a result in registers, test it for TRUE or FALSE. 
    15671656 * Will fail if TYfptr and the reg is ES! 
    15681657 * If saveflag is TRUE, preserve the contents of the 
    15691658 * registers. 
    15701659 */ 
    15711660 
    15721661code *tstresult(regm_t regm,tym_t tym,unsigned saveflag) 
    1573 { code *ce; 
    1574   unsigned reg; 
     1662
    15751663  unsigned scrreg;                      /* scratch register             */ 
    1576   unsigned sz; 
    15771664  regm_t scrregm; 
    15781665 
    15791666#ifdef DEBUG 
    15801667  if (!(regm & (mBP | ALLREGS))) 
    15811668        printf("tstresult(regm = x%x, tym = x%lx, saveflag = %d)\n", 
    15821669            regm,tym,saveflag); 
    15831670#endif 
    15841671  assert(regm & (mBP | ALLREGS)); 
    15851672  tym = tybasic(tym); 
    1586   ce = CNIL; 
    1587   reg = findreg(regm); 
    1588   sz = tysize[tym]; 
     1673  code *ce = CNIL; 
     1674  unsigned reg = findreg(regm); 
     1675  unsigned sz = tysize[tym]; 
    15891676  if (sz == 1) 
    15901677  {     assert(regm & BYTEREGS); 
    15911678        return genregs(ce,0x84,reg,reg);        // TEST regL,regL 
    15921679  } 
    15931680  if (sz <= REGSIZE) 
    15941681  { 
    1595     if (I32
     1682    if (!I16
    15961683    { 
    15971684        if (tym == TYfloat) 
    15981685        {   if (saveflag) 
    15991686            { 
    16001687                scrregm = allregs & ~regm;              /* possible scratch regs */ 
    16011688                ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 
    16021689                ce = genmovreg(ce,scrreg,reg);  /* MOV scrreg,msreg     */ 
    16031690                reg = scrreg; 
    16041691            } 
    16051692            ce = cat(ce,getregs(mask[reg])); 
    1606             return gen2(ce,0xD1,modregrm(3,4,reg)); /* SHL reg,1        */ 
     1693            return gen2(ce,0xD1,modregrmx(3,4,reg)); // SHL reg,1 
    16071694        } 
    16081695        ce = gentstreg(ce,reg);                 // TEST reg,reg 
    1609         if (tysize[tym] == SHORTSIZE) 
     1696        if (sz == SHORTSIZE) 
    16101697            ce->Iflags |= CFopsize;             /* 16 bit operands      */ 
     1698        else if (sz == 8) 
     1699            code_orrex(ce, REX_W); 
    16111700    } 
    16121701    else 
    16131702        ce = gentstreg(ce,reg);                 // TEST reg,reg 
    16141703    return ce; 
    16151704  } 
    16161705  if (saveflag || tyfv(tym)) 
    16171706  { 
    16181707        scrregm = ALLREGS & ~regm;              /* possible scratch regs */ 
    16191708        ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 
    16201709        if (I32 || sz == REGSIZE * 2) 
    16211710        {   code *c; 
    16221711 
    16231712            assert(regm & mMSW && regm & mLSW); 
    16241713 
    16251714            reg = findregmsw(regm); 
    16261715            if (I32) 
    16271716            { 
    16281717                if (tyfv(tym)) 
    16291718                {   c = genregs(CNIL,0x0F,scrreg,reg); 
    16301719                    c->Iop2 = 0xB7;                     /* MOVZX scrreg,msreg   */ 
     
    17011790 
    17021791//  printf("fixresult(e = %p, retregs = %s, *pretregs = %s)\n", 
    17031792//      e,regm_str(retregs),regm_str(*pretregs)); 
    17041793  if (*pretregs == 0) return CNIL;      /* if don't want result         */ 
    17051794  assert(e && retregs);                 /* need something to work with  */ 
    17061795  forccs = *pretregs & mPSW; 
    17071796  forregs = *pretregs & (mST01 | mST0 | mBP | ALLREGS | mES | mSTACK); 
    17081797  tym = tybasic(e->Ety); 
    17091798#if 0 
    17101799  if (tym == TYstruct) 
    17111800        // Hack to support cdstreq() 
    17121801        tym = TYfptr; 
    17131802#else 
    17141803  if (tym == TYstruct) 
    17151804        // Hack to support cdstreq() 
    17161805        tym = (forregs & mMSW) ? TYfptr : TYnptr; 
    17171806#endif 
    17181807  c = CNIL; 
    17191808  sz = tysize[tym]; 
    17201809  if (sz == 1) 
    1721   {     unsigned reg; 
    1722  
     1810  { 
    17231811        assert(retregs & BYTEREGS); 
    1724         reg = findreg(retregs); 
     1812        unsigned reg = findreg(retregs); 
    17251813        if (e->Eoper == OPvar && 
    17261814            e->EV.sp.Voffset == 1 && 
    17271815            e->EV.sp.Vsym->Sfl == FLreg) 
    17281816        { 
     1817            assert(reg < 4); 
    17291818            if (forccs) 
    17301819                c = gen2(c,0x84,modregrm(3,reg | 4,reg | 4));   // TEST regH,regH 
    17311820            forccs = 0; 
    17321821        } 
    17331822  } 
    17341823  if ((retregs & forregs) == retregs)   /* if already in right registers */ 
    17351824        *pretregs = retregs; 
    17361825  else if (forregs)             /* if return the result in registers    */ 
    1737   {     unsigned opsflag; 
    1738  
     1826  { 
    17391827        if (forregs & (mST01 | mST0)) 
    17401828            return fixresult87(e,retregs,pretregs); 
    17411829        ce = CNIL; 
    1742         opsflag = FALSE; 
    1743         if (!I32 && sz == 8) 
     1830        unsigned opsflag = FALSE; 
     1831        if (I16 && sz == 8) 
    17441832        {   if (forregs & mSTACK) 
    17451833            {   assert(retregs == DOUBLEREGS_16); 
    17461834                /* Push floating regs   */ 
    17471835                c = CNIL; 
    17481836                ce = gen1(ce,0x50 + AX); 
    17491837                gen1(ce,0x50 + BX); 
    17501838                gen1(ce,0x50 + CX); 
    17511839                gen1(ce,0x50 + DX); 
    17521840                stackpush += DOUBLESIZE; 
    17531841            } 
    17541842            else if (retregs & mSTACK) 
    17551843            {   assert(forregs == DOUBLEREGS_16); 
    17561844                /* Pop floating regs    */ 
    17571845                c = getregs(forregs); 
    17581846                ce = gen1(ce,0x58 + DX); 
    17591847                gen1(ce,0x58 + CX); 
    17601848                gen1(ce,0x58 + BX); 
    17611849                gen1(ce,0x58 + AX); 
    17621850                stackpush -= DOUBLESIZE; 
    17631851                retregs = DOUBLEREGS_16; /* for tstresult() below       */ 
     
    17961884                                        /* cuz we have real result in rreg */ 
    17971885        retregs = *pretregs & ~mPSW; 
    17981886  } 
    17991887  if (forccs)                           /* if return result in flags    */ 
    18001888        c = cat(c,tstresult(retregs,tym,forregs)); 
    18011889  return c; 
    18021890} 
    18031891 
    18041892 
    18051893/******************************** 
    18061894 * Generate code sequence to call C runtime library support routine. 
    18071895 *      clib = CLIBxxxx 
    18081896 *      keepmask = mask of registers not to destroy. Currently can 
    18091897 *              handle only 1. Should use a temporary rather than 
    18101898 *              push/pop for speed. 
    18111899 */ 
    18121900 
    18131901int clib_inited = 0;            // != 0 if initialized 
    18141902 
    18151903code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask) 
    1816 { code *c,*cpop; 
    1817   regm_t retregs; 
    1818   symbol *s; 
    1819   int i; 
    1820  
     1904
    18211905#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    18221906  static symbol lib[] = 
    18231907  { 
    18241908/* Convert destroyed regs into saved regs       */ 
    18251909#define Z(desregs)      (~(desregs) & (mBP| mES | ALLREGS)) 
    18261910#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    18271911#define N(name) "_" name 
    18281912#else 
    18291913#define N(name) name 
    18301914#endif 
    18311915 
    18321916/* Shorthand to map onto SYMBOLY()              */ 
    18331917#define Y(desregs,name)  SYMBOLY(FLfunc,Z(desregs),N(name),0) 
    18341918 
    18351919    Y(0,"_LCMP__"),                     // CLIBlcmp 
    18361920    Y(mAX|mCX|mDX,"_LMUL__"),           // CLIBlmul 
    18371921#if 1 
    18381922    Y(mAX|mBX|mCX|mDX,"_LDIV__"),       // CLIBldiv 
    18391923    Y(mAX|mBX|mCX|mDX,"_LDIV__"),       // CLIBlmod 
    18401924    Y(mAX|mBX|mCX|mDX,"_ULDIV__"),      // CLIBuldiv 
     
    20722156    {mAX,mAX,0,2},                      // _DBLINT87@   dblint87 
    20732157    {mDX|mAX,mAX,0,2},                  // _DBLLNG87@   dbllng87 
    20742158    {0,0,0,2},                          // _FTST@ 
    20752159    {mPSW,mPSW,0,INFfloat,0,2},         // _FCOMPP@ 
    20762160    {mPSW,mPSW,0,2},                    // _FTEST@ 
    20772161    {mPSW,mPSW,0,2},                    // _FTEST0@ 
    20782162    {mST0,mST0,0,INFfloat,1,1},         // _FDIV@ 
    20792163 
    20802164    {mST01,mST01,0,INF32|INFfloat,3,5}, // _Cmul 
    20812165    {mST01,mST01,0,INF32|INFfloat,0,2}, // _Cdiv 
    20822166    {mPSW, mPSW, 0,INF32|INFfloat,0,4}, // _Ccmp 
    20832167 
    20842168    {mST0,mST0,0,INF32|INFfloat,2,1},   // _U64_LDBL 
    20852169    {0,mDX|mAX,0,INF32|INFfloat,1,2},   // __LDBLULLNG 
    20862170  }; 
    20872171 
    20882172  if (!clib_inited)                             /* if not initialized   */ 
    20892173  { 
    20902174        assert(sizeof(lib) / sizeof(lib[0]) == CLIBMAX); 
    20912175        assert(sizeof(info) / sizeof(info[0]) == CLIBMAX); 
    2092         for (i = 0; i < CLIBMAX; i++) 
     2176        for (int i = 0; i < CLIBMAX; i++) 
    20932177        {   lib[i].Stype = tsclib; 
    20942178#if MARS 
    20952179            lib[i].Sxtrnnum = 0; 
    20962180            lib[i].Stypidx = 0; 
    20972181#endif 
    20982182        } 
    20992183 
    2100         if (I32
     2184        if (!I16
    21012185        {   /* Adjust table for 386     */ 
    21022186            lib[CLIBdbllng].Sregsaved  = Z(DOUBLEREGS_32); 
    21032187            lib[CLIBlngdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21042188            lib[CLIBdblint].Sregsaved  = Z(DOUBLEREGS_32); 
    21052189            lib[CLIBintdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21062190#if TARGET_WINDOS 
    21072191            lib[CLIBfneg].Sregsaved    = Z(FLOATREGS_32); 
    21082192            lib[CLIBdneg].Sregsaved    = Z(DOUBLEREGS_32); 
    21092193            lib[CLIBdbluns].Sregsaved  = Z(DOUBLEREGS_32); 
    21102194            lib[CLIBunsdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21112195            lib[CLIBdblulng].Sregsaved = Z(DOUBLEREGS_32); 
    21122196            lib[CLIBulngdbl].Sregsaved = Z(DOUBLEREGS_32); 
    21132197#endif 
    21142198            lib[CLIBdblflt].Sregsaved  = Z(DOUBLEREGS_32); 
    21152199            lib[CLIBfltdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21162200 
    21172201            lib[CLIBdblllng].Sregsaved = Z(DOUBLEREGS_32); 
    21182202            lib[CLIBllngdbl].Sregsaved = Z(DOUBLEREGS_32); 
    21192203            lib[CLIBdblullng].Sregsaved = Z(DOUBLEREGS_32); 
    21202204            lib[CLIBullngdbl].Sregsaved = Z(DOUBLEREGS_32); 
    21212205        } 
    21222206        clib_inited++; 
    21232207  } 
    21242208#undef Z 
    21252209 
    21262210  assert(clib < CLIBMAX); 
    2127   s = &lib[clib]; 
     2211  symbol *s = &lib[clib]; 
    21282212  assert(I32 || !(info[clib].flags & INF32)); 
    2129   cpop = CNIL; 
    2130   c = getregs((~s->Sregsaved & (mES | mBP | ALLREGS)) & ~keepmask); // mask of regs destroyed 
     2213  code *cpop = CNIL; 
     2214  code *c = getregs((~s->Sregsaved & (mES | mBP | ALLREGS)) & ~keepmask); // mask of regs destroyed 
    21312215  keepmask &= ~s->Sregsaved; 
    2132   int npushed = 0; 
     2216    int npushed = numbitsset(keepmask); 
     2217    gensaverestore2(keepmask, &c, &cpop); 
     2218#if 0 
    21332219  while (keepmask) 
    21342220  {     unsigned keepreg; 
    21352221 
    21362222        if (keepmask & (mBP|ALLREGS)) 
    21372223        {       keepreg = findreg(keepmask & (mBP|ALLREGS)); 
    21382224                c = gen1(c,0x50 + keepreg);             /* PUSH keepreg */ 
    21392225                cpop = cat(gen1(CNIL,0x58 + keepreg),cpop);     // POP keepreg 
    21402226                keepmask &= ~mask[keepreg]; 
    21412227                npushed++; 
    21422228        } 
    21432229        if (keepmask & mES) 
    21442230        {       c = gen1(c,0x06);                       /* PUSH ES      */ 
    21452231                cpop = cat(gen1(CNIL,0x07),cpop);       /* POP ES       */ 
    21462232                keepmask &= ~mES; 
    21472233                npushed++; 
    21482234        } 
    21492235  } 
     2236#endif 
    21502237 
    21512238    c = cat(c, save87regs(info[clib].push87)); 
    2152     for (i = 0; i < info[clib].push87; i++) 
     2239    for (int i = 0; i < info[clib].push87; i++) 
    21532240        c = cat(c, push87()); 
    21542241 
    2155     for (i = 0; i < info[clib].pop87; i++) 
     2242    for (int i = 0; i < info[clib].pop87; i++) 
    21562243        pop87(); 
    21572244 
    21582245  if (config.target_cpu >= TARGET_80386 && clib == CLIBlmul && !I32) 
    21592246  {     static char lmul[] = { 
    21602247            0x66,0xc1,0xe1,0x10,        // shl  ECX,16 
    21612248            0x8b,0xcb,                  // mov  CX,BX           ;ECX = CX,BX 
    21622249            0x66,0xc1,0xe0,0x10,        // shl  EAX,16 
    21632250            0x66,0x0f,0xac,0xd0,0x10,   // shrd EAX,EDX,16      ;EAX = DX,AX 
    21642251            0x66,0xf7,0xe1,             // mul  ECX 
    21652252            0x66,0x0f,0xa4,0xc2,0x10,   // shld EDX,EAX,16      ;DX,AX = EAX 
    21662253        }; 
    21672254 
    21682255        c = genasm(c,lmul,sizeof(lmul)); 
    21692256  } 
    21702257  else 
    21712258  {     makeitextern(s); 
    21722259        int nalign = 0; 
    21732260        if (STACKALIGN == 16) 
    21742261        {   // Align the stack (assume no args on stack) 
    21752262            int npush = npushed * REGSIZE + stackpush; 
    21762263            if (npush & (STACKALIGN - 1)) 
    21772264            {   nalign = STACKALIGN - (npush & (STACKALIGN - 1)); 
    21782265                c = genc2(c,0x81,modregrm(3,5,SP),nalign); // SUB ESP,nalign 
     2266                if (I64) 
     2267                    code_orrex(c, REX_W); 
    21792268            } 
    21802269        } 
    21812270        c = gencs(c,(LARGECODE) ? 0x9A : 0xE8,0,FLfunc,s);      // CALL s 
    21822271        if (nalign) 
    2183             c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign 
     2272        {   c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign 
     2273            if (I64) 
     2274                code_orrex(c, REX_W); 
     2275        } 
    21842276        calledafunc = 1; 
    21852277 
    2186         if (!I32 &&                                     // bug in Optlink 
     2278        if (I16 &&                                   // bug in Optlink for weak references 
    21872279            config.flags3 & CFG3wkfloat && 
    21882280            (info[clib].flags & (INFfloat | INFwkdone)) == INFfloat) 
    21892281        {   info[clib].flags |= INFwkdone; 
    21902282            makeitextern(rtlsym[RTLSYM_INTONLY]); 
    21912283            obj_wkext(s,rtlsym[RTLSYM_INTONLY]); 
    21922284        } 
    2193  
    2194   if (!I32
     2285   
     2286    if (I16
    21952287        stackpush -= info[clib].pop; 
    2196   retregs = I32 ? info[clib].retregs32 : info[clib].retregs16
    2197   return cat(cat(c,cpop),fixresult(e,retregs,pretregs)); 
     2288    regm_t retregs = I16 ? info[clib].retregs16 : info[clib].retregs32
     2289    return cat(cat(c,cpop),fixresult(e,retregs,pretregs)); 
    21982290} 
    21992291 
    22002292 
    22012293/******************************* 
    22022294 * Generate code sequence for function call. 
    22032295 */ 
    22042296 
    22052297code *cdfunc(elem *e,regm_t *pretregs) 
    22062298{ unsigned numpara = 0; 
    22072299  unsigned stackpushsave; 
    22082300  unsigned preg; 
    22092301  regm_t keepmsk; 
    22102302  unsigned numalign = 0; 
    22112303  code *c; 
    22122304 
    22132305  //printf("cdfunc()\n"); elem_print(e); 
    22142306  assert(e); 
    22152307  stackpushsave = stackpush;            /* so we can compute # of parameters */ 
    22162308  cgstate.stackclean++; 
    22172309  c = CNIL; 
    22182310  keepmsk = 0; 
    22192311  if (OTbinary(e->Eoper))               // if parameters 
    22202312  {     unsigned stackalign = REGSIZE; 
    2221         elem *ep; 
    22222313        elem *en; 
    22232314        regm_t retregs; 
    2224         tym_t tyf; 
    2225  
    2226         if (I32) 
     2315 
     2316        if (!I16) 
    22272317        { 
    2228             tyf = tybasic(e->E1->Ety); 
     2318            tym_t tyf = tybasic(e->E1->Ety); 
    22292319 
    22302320            // First compute numpara, the total pushed on the stack 
    22312321            switch (tyf) 
    22322322            {   case TYf16func: 
    22332323                    stackalign = 2; 
    22342324                    goto Ldefault; 
    22352325                case TYmfunc: 
    22362326                case TYjfunc: 
    22372327                    // last parameter goes into register 
     2328                    elem *ep; 
    22382329                    for (ep = e->E2; ep->Eoper == OPparam; ep = ep->E2) 
    22392330                    { 
    22402331                        numpara += paramsize(ep->E1,stackalign); 
    22412332                    } 
    22422333                    if (tyf == TYjfunc && 
    22432334                        // This must match type_jparam() 
    22442335                        !(tyjparam(ep->Ety) || 
    22452336                          ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 
    22462337                         ) 
    22472338                        ) 
    22482339                    { 
    22492340                        numpara += paramsize(ep,stackalign); 
    22502341                    } 
    22512342                    break; 
    22522343                default: 
    22532344                Ldefault: 
    22542345                    numpara += paramsize(e->E2,stackalign); 
    22552346                    break; 
    22562347            } 
    22572348            assert((numpara & (REGSIZE - 1)) == 0); 
    22582349            assert((stackpush & (REGSIZE - 1)) == 0); 
    22592350 
    22602351            /* Adjust start of the stack so after all args are pushed, 
    22612352             * the stack will be aligned. 
    22622353             */ 
    22632354            if (STACKALIGN == 16 && (numpara + stackpush) & (STACKALIGN - 1)) 
    22642355            { 
    22652356                numalign = STACKALIGN - ((numpara + stackpush) & (STACKALIGN - 1)); 
    22662357                c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 
     2358                if (I64) 
     2359                    code_orrex(c, REX_W); 
    22672360                c = genadjesp(c, numalign); 
    22682361                stackpush += numalign; 
    22692362                stackpushsave += numalign; 
    22702363            } 
    22712364 
    22722365            switch (tyf) 
    22732366            {   case TYf16func: 
    22742367                    stackalign = 2; 
    22752368                    break; 
    22762369                case TYmfunc:   // last parameter goes into ECX 
    22772370                    preg = CX; 
    22782371                    goto L1; 
    22792372                case TYjfunc:   // last parameter goes into EAX 
    22802373                    preg = AX; 
    22812374                    goto L1; 
    22822375 
    22832376                L1: 
     2377                    elem *ep; 
    22842378                    for (ep = e->E2; ep->Eoper == OPparam; ep = en) 
    22852379                    { 
    22862380                        c = cat(c,params(ep->E1,stackalign)); 
    22872381                        en = ep->E2; 
    22882382                        freenode(ep); 
    22892383                        ep = en; 
    22902384                    } 
    22912385                    if (tyf == TYjfunc && 
    22922386                        // This must match type_jparam() 
    22932387                        !(tyjparam(ep->Ety) || 
    22942388                          ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 
    22952389                         ) 
    22962390                        ) 
    22972391                    { 
    22982392                        c = cat(c,params(ep,stackalign)); 
    22992393                        goto Lret; 
    23002394                    } 
    2301                     keepmsk = mask[preg]; 
     2395                    // preg is the register to put the parameter ep in 
     2396                    keepmsk = mask[preg];       // don't change preg when evaluating func address 
    23022397                    retregs = keepmsk; 
    23032398                    if (ep->Eoper == OPstrthis) 
    2304                     {   code *c1; 
    2305                         code *c2; 
    2306                         unsigned np; 
    2307  
    2308                         c1 = getregs(retregs); 
     2399                    {   code *c2; 
     2400 
     2401                        code *c1 = getregs(retregs); 
    23092402                        // LEA preg,np[ESP] 
    2310                         np = stackpush - ep->EV.Vuns;   // stack delta to parameter 
    2311                         c2 = genc1(CNIL,0x8D,modregrm(2,preg,4),FLconst,np); 
    2312                         c2->Isib = modregrm(0,4,SP); 
     2403                        unsigned np = stackpush - ep->EV.Vuns;   // stack delta to parameter 
     2404                        c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregrm(2,preg,4),FLconst,np); 
     2405                        if (I64) 
     2406                            code_orrex(c2, REX_W); 
    23132407                        c = cat3(c,c1,c2); 
    23142408                    } 
    23152409                    else 
    23162410                    {   code *cp = codelem(ep,&retregs,FALSE); 
    23172411                        c = cat(c,cp); 
    23182412                    } 
    23192413                    goto Lret; 
    23202414            } 
    23212415        } 
    23222416        c = cat(c, params(e->E2,stackalign));   // push parameters 
    23232417    } 
    23242418    else 
    23252419    { 
    23262420        /* Adjust start of the stack so 
    23272421         * the stack will be aligned. 
    23282422         */ 
    23292423        if (STACKALIGN == 16 && (stackpush) & (STACKALIGN - 1)) 
    23302424        { 
    23312425            numalign = STACKALIGN - ((stackpush) & (STACKALIGN - 1)); 
    23322426            c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 
     2427            if (I64) 
     2428                code_orrex(c, REX_W); 
    23332429            c = genadjesp(c, numalign); 
    23342430            stackpush += numalign; 
    23352431            stackpushsave += numalign; 
    23362432        } 
    23372433 
    23382434    } 
    23392435Lret: 
    23402436    cgstate.stackclean--; 
    2341     if (I32
     2437    if (!I16
    23422438    { 
    23432439        if (numpara != stackpush - stackpushsave) 
    23442440            printf("numpara = %d, stackpush = %d, stackpushsave = %d\n", numpara, stackpush, stackpushsave); 
    23452441        assert(numpara == stackpush - stackpushsave); 
    23462442    } 
    23472443    else 
    23482444        numpara = stackpush - stackpushsave; 
    23492445    return cat(c,funccall(e,numpara,numalign,pretregs,keepmsk)); 
    23502446} 
    23512447 
    23522448/*********************************** 
    23532449 */ 
    23542450 
    23552451code *cdstrthis(elem *e,regm_t *pretregs) 
    23562452{ 
    23572453    code *c1; 
    23582454    code *c2; 
    2359     unsigned np; 
    2360     unsigned reg; 
    23612455 
    23622456    assert(tysize(e->Ety) == REGSIZE); 
    2363     reg = findreg(*pretregs & allregs); 
     2457    unsigned reg = findreg(*pretregs & allregs); 
    23642458    c1 = getregs(mask[reg]); 
    23652459    // LEA reg,np[ESP] 
    2366     np = stackpush - e->EV.Vuns;        // stack delta to parameter 
    2367     c2 = genc1(CNIL,0x8D,modregrm(2,reg,4),FLconst,np); 
    2368     c2->Isib = modregrm(0,4,SP); 
     2460    unsigned np = stackpush - e->EV.Vuns;        // stack delta to parameter 
     2461    c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregxrm(2,reg,4),FLconst,np); 
     2462    if (I64) 
     2463        code_orrex(c2, REX_W); 
    23692464    return cat3(c1,c2,fixresult(e,mask[reg],pretregs)); 
    23702465} 
    23712466 
    23722467/****************************** 
    23732468 * Call function. All parameters are pushed onto the stack, numpara gives 
    23742469 * the size of them all. 
    23752470 */ 
    23762471 
    23772472STATIC code * funccall(elem *e,unsigned numpara,unsigned numalign,regm_t *pretregs,regm_t keepmsk) 
    23782473{ 
    23792474    elem *e1; 
    23802475    code *c,*ce,cs; 
    23812476    tym_t tym1; 
    23822477    char farfunc; 
    23832478    regm_t retregs; 
    23842479    symbol *s; 
    23852480 
    23862481    //printf("funccall(e = %p, *pretregs = x%x, numpara = %d, numalign = %d)\n",e,*pretregs,numpara,numalign); 
    23872482    calledafunc = 1; 
    23882483    /* Determine if we need frame for function prolog/epilog    */ 
     
    24082503        if (s->Sflags & SFLexit) 
    24092504            c = NULL; 
    24102505        else 
    24112506            c = save87();               // assume 8087 regs are all trashed 
    24122507        if (s->Sflags & SFLexit) 
    24132508            // Function doesn't return, so don't worry about registers 
    24142509            // it may use 
    24152510            c1 = NULL; 
    24162511        else if (!tyfunc(s->ty()) || !(config.flags4 & CFG4optimized)) 
    24172512            // so we can replace func at runtime 
    24182513            c1 = getregs(~fregsaved & (mBP | ALLREGS | mES)); 
    24192514        else 
    24202515            c1 = getregs(~s->Sregsaved & (mBP | ALLREGS | mES)); 
    24212516        if (strcmp(s->Sident,"alloca") == 0) 
    24222517        { 
    24232518#if 1 
    24242519            s = rtlsym[RTLSYM_ALLOCA]; 
    24252520            makeitextern(s); 
    24262521            c1 = cat(c1,getregs(mCX)); 
    24272522            c1 = genc(c1,0x8D,modregrm(2,CX,BPRM),FLallocatmp,0,0,0);  // LEA CX,&localsize[BP] 
     2523            if (I64) 
     2524                code_orrex(c1, REX_W); 
    24282525            usedalloca = 2;             // new way 
    24292526#else 
    24302527            usedalloca = 1;             // old way 
    24312528#endif 
    24322529        } 
    24332530        if (sytab[s->Sclass] & SCSS)    // if function is on stack (!) 
    24342531        { 
    24352532            retregs = allregs & ~keepmsk; 
    24362533            s->Sflags &= ~GTregcand; 
    24372534            s->Sflags |= SFLread; 
    24382535            ce = cat(c1,cdrelconst(e1,&retregs)); 
    24392536            if (farfunc) 
    24402537                goto LF1; 
    24412538            else 
    24422539                goto LF2; 
    24432540        } 
    24442541        else 
    24452542        {   int fl; 
    24462543 
    24472544            fl = FLfunc; 
     
    24622559                ce = gen1(ce, 0x90);            // NOP 
    24632560                code_orflag(ce, CFvolatile);    // don't schedule it 
    24642561            } 
    24652562#endif 
    24662563        } 
    24672564        ce = cat(c1,ce); 
    24682565  } 
    24692566  else 
    24702567  {     /* Call function via pointer    */ 
    24712568        elem *e11; 
    24722569        tym_t e11ty; 
    24732570 
    24742571#ifdef DEBUG 
    24752572        if (e1->Eoper != OPind 
    24762573                ) { WRFL((enum FL)el_fl(e1)); WROP(e1->Eoper); } 
    24772574#endif 
    24782575        c = save87();                   // assume 8087 regs are all trashed 
    24792576        assert(e1->Eoper == OPind); 
    24802577        e11 = e1->E1; 
    24812578        e11ty = tybasic(e11->Ety); 
    2482         assert(I32 || (e11ty == (farfunc ? TYfptr : TYnptr))); 
     2579        assert(!I16 || (e11ty == (farfunc ? TYfptr : TYnptr))); 
    24832580 
    24842581        /* if we can't use loadea()     */ 
    24852582        if ((EOP(e11) || e11->Eoper == OPconst) && 
    24862583            (e11->Eoper != OPind || e11->Ecount)) 
    24872584        { 
    24882585            unsigned reg; 
    24892586 
    24902587            retregs = allregs & ~keepmsk; 
    24912588            cgstate.stackclean++; 
    24922589            ce = scodelem(e11,&retregs,keepmsk,TRUE); 
    24932590            cgstate.stackclean--; 
    24942591            /* Kill registers destroyed by an arbitrary function call */ 
    24952592            ce = cat(ce,getregs((mBP | ALLREGS | mES) & ~fregsaved)); 
    24962593            if (e11ty == TYfptr) 
    24972594            {   unsigned lsreg; 
    24982595             LF1: 
    24992596                reg = findregmsw(retregs); 
    25002597                lsreg = findreglsw(retregs); 
    25012598                floatreg = TRUE;                /* use float register   */ 
    25022599                reflocal = TRUE; 
    25032600                ce = genc1(ce,0x89,             /* MOV floatreg+2,reg   */ 
    25042601                        modregrm(2,reg,BPRM),FLfltreg,REGSIZE); 
    25052602                genc1(ce,0x89,                  /* MOV floatreg,lsreg   */ 
    25062603                        modregrm(2,lsreg,BPRM),FLfltreg,0); 
    25072604                if (tym1 == TYifunc) 
    25082605                    gen1(ce,0x9C);              // PUSHF 
    25092606                genc1(ce,0xFF,                  /* CALL [floatreg]      */ 
    25102607                        modregrm(2,3,BPRM),FLfltreg,0); 
    25112608            } 
    25122609            else 
    25132610            { 
    25142611             LF2: 
    25152612                reg = findreg(retregs); 
    2516                 ce = gen2(ce,0xFF,modregrm(3,2,reg));   /* CALL reg     */ 
     2613                ce = gen2(ce,0xFF,modregrmx(3,2,reg));   /* CALL reg     */ 
    25172614            } 
    25182615        } 
    25192616        else 
    25202617        { 
    25212618            if (tym1 == TYifunc) 
    25222619                c = gen1(c,0x9C);               // PUSHF 
    25232620                                                // CALL [function] 
    25242621            cs.Iflags = 0; 
    25252622            cgstate.stackclean++; 
    25262623            ce = loadea(e11,&cs,0xFF,farfunc ? 3 : 2,0,keepmsk,(ALLREGS|mES|mBP) & ~fregsaved); 
    25272624            cgstate.stackclean--; 
    25282625            freenode(e11); 
    25292626        } 
    25302627        s = NULL; 
    25312628  } 
    25322629  c = cat(c,ce); 
    25332630  freenode(e1); 
    25342631 
    25352632  /* See if we will need the frame pointer. 
    25362633     Calculate it here so we can possibly use BP to fix the stack. 
     
    26782775  symbol *s; 
    26792776  int fl; 
    26802777 
    26812778  //printf("params(e = %p, stackalign = %d)\n", e, stackalign); 
    26822779  cp = NULL; 
    26832780  stackchanged = 1; 
    26842781  assert(e); 
    26852782  while (e->Eoper == OPparam)           /* if more params               */ 
    26862783  { 
    26872784        e2 = e->E2; 
    26882785        cp = cat(cp,params(e->E1,stackalign));  // push them backwards 
    26892786        freenode(e); 
    26902787        e = e2; 
    26912788  } 
    26922789  //printf("params()\n"); elem_print(e); 
    26932790 
    26942791  tym = tybasic(e->Ety); 
    26952792  if (tyfloating(tym)) 
    26962793        obj_fltused(); 
    26972794 
     2795  int grex = I64 ? REX_W << 16 : 0; 
     2796 
    26982797  /* sz = number of bytes pushed        */ 
    26992798  if (tyscalar(tym)) 
    27002799        szb = size(tym); 
    27012800  else if (tym == TYstruct) 
    27022801        szb = e->Enumbytes; 
    27032802  else 
    27042803  { 
    27052804#ifdef DEBUG 
    27062805        WRTYxx(tym); 
    27072806#endif 
    27082807        assert(0); 
    27092808  } 
    27102809  sz = align(stackalign,szb);           /* align on word stack boundary */ 
    27112810  assert((sz & (stackalign - 1)) == 0); /* ensure that alignment worked */ 
    27122811  assert((sz & (REGSIZE - 1)) == 0); 
    27132812 
    27142813  c = CNIL; 
    27152814  cs.Iflags = 0; 
    27162815  cs.Irex = 0; 
    27172816  switch (e->Eoper) 
    27182817  { 
    27192818#if SCPP 
    27202819    case OPstrctor: 
    27212820    { 
    27222821        e1 = e->E1; 
    27232822        c = docommas(&e1);              /* skip over any comma expressions */ 
    27242823 
    2725         c = genc2(c,0x81,modregrm(3,5,SP),sz); /* SUB SP,sizeof(struct) */ 
     2824        c = genc2(c,0x81,grex | modregrm(3,5,SP),sz); // SUB SP,sizeof(struct) 
    27262825        stackpush += sz; 
    27272826        genadjesp(c,sz); 
    27282827 
    27292828        // Find OPstrthis and set it to stackpush 
    27302829        exp2_setstrthis(e1,NULL,stackpush,NULL); 
    27312830 
    27322831        retregs = 0; 
    27332832        ce = codelem(e1,&retregs,TRUE); 
    27342833        goto L2; 
    27352834    } 
    27362835    case OPstrthis: 
    27372836        // This is the parameter for the 'this' pointer corresponding to 
    27382837        // OPstrctor. We push a pointer to an object that was already 
    27392838        // allocated on the stack by OPstrctor. 
    27402839    {   unsigned np; 
    27412840 
    27422841        retregs = allregs; 
    27432842        c = allocreg(&retregs,&reg,TYoffset); 
    27442843        c = genregs(c,0x89,SP,reg);             // MOV reg,SP 
     2844        if (I64) 
     2845            code_orrex(c, REX_W); 
    27452846        np = stackpush - e->EV.Vuns;            // stack delta to parameter 
    2746         c = genc2(c,0x81,modregrm(3,0,reg),np); // ADD reg,np 
     2847        c = genc2(c,0x81,grex | modregrmx(3,0,reg),np); // ADD reg,np 
    27472848        if (sz > REGSIZE) 
    27482849        {   c = gen1(c,0x16);                   // PUSH SS 
    27492850            stackpush += REGSIZE; 
    27502851        } 
    2751         c = gen1(c,0x50 + reg);                 // PUSH reg 
     2852        c = gen1(c,0x50 + (reg & 7));           // PUSH reg 
     2853        if (reg & 8) 
     2854            code_orrex(c, REX_B); 
    27522855        stackpush += REGSIZE; 
    27532856        genadjesp(c,sz); 
    27542857        ce = CNIL; 
    27552858        goto L2; 
    27562859    } 
    27572860#endif 
    27582861    case OPstrpar: 
    27592862        {       code *cc,*c1,*c2,*c3; 
    27602863                unsigned rm; 
    27612864                unsigned seg;           // segment override prefix flags 
    27622865                bool doneoff; 
    27632866                unsigned pushsize = REGSIZE; 
    27642867                unsigned op16 = 0; 
    27652868                unsigned npushes; 
    27662869 
    27672870                e1 = e->E1; 
    27682871                if (sz == 0) 
    27692872                { 
    27702873                    ce = docommas(&e1); /* skip over any commas         */ 
    27712874                    goto L2; 
    27722875                } 
    27732876                if ((sz & 3) == 0 && (sz / REGSIZE) <= 4 && e1->Eoper == OPvar) 
    27742877                {   freenode(e); 
    27752878                    e = e1; 
    27762879                    goto L1; 
    27772880                } 
    27782881                cc = docommas(&e1);     /* skip over any commas         */ 
    27792882                seg = 0;                /* assume no seg override       */ 
    27802883                retregs = sz ? IDXREGS : 0; 
    27812884                doneoff = FALSE; 
    2782                 if (I32 && sz & 2)      /* if odd number of words to push */ 
     2885                if (!I16 && sz & 2)     // if odd number of words to push 
    27832886                {   pushsize = 2; 
    27842887                    op16 = 1; 
    27852888                } 
    2786                 else if (!I32 && config.target_cpu >= TARGET_80386 && (sz & 3) == 0) 
     2889                else if (I16 && config.target_cpu >= TARGET_80386 && (sz & 3) == 0) 
    27872890                {   pushsize = 4;       // push DWORDs at a time 
    27882891                    op16 = 1; 
    27892892                } 
    27902893                npushes = sz / pushsize; 
    27912894                switch (e1->Eoper) 
    27922895                {   case OPind: 
    27932896                        if (sz) 
    27942897                        {   switch (tybasic(e1->E1->Ety)) 
    27952898                            { 
    27962899                                case TYfptr: 
    27972900                                case TYhptr: 
    27982901                                    seg = CFes; 
    27992902                                    retregs |= mES; 
    28002903                                    break; 
    28012904                                case TYsptr: 
    28022905                                    if (config.wflags & WFssneds) 
    28032906                                        seg = CFss; 
    28042907                                    break; 
    28052908                                case TYcptr: 
    28062909                                    seg = CFcs; 
     
    28502953                        /* Reverse the effect of the previous add       */ 
    28512954                        if (doneoff) 
    28522955                                e1->EV.sp.Voffset -= sz - pushsize; 
    28532956                        freenode(e1); 
    28542957                        break; 
    28552958                    case OPstreq: 
    28562959                    //case OPcond: 
    28572960                        if (!(config.exe & EX_flat)) 
    28582961                        {   seg = CFes; 
    28592962                            retregs |= mES; 
    28602963                        } 
    28612964                        c1 = codelem(e1,&retregs,FALSE); 
    28622965                        break; 
    28632966                    default: 
    28642967#ifdef DEBUG 
    28652968                        elem_print(e1); 
    28662969#endif 
    28672970                        assert(0); 
    28682971                } 
    28692972                reg = findreglsw(retregs); 
    2870                 rm = I32 ? regtorm32[reg] : regtorm[reg]; 
     2973                rm = I16 ? regtorm[reg] : regtorm32[reg]; 
    28712974                if (op16) 
    28722975                    seg |= CFopsize;            // operand size 
    28732976                if (npushes <= 4) 
    28742977                { 
    28752978                    assert(!doneoff); 
    28762979                    for (c2 = CNIL; npushes > 1; npushes--) 
    2877                     {   c2 = genc1(c2,0xFF,modregrm(2,6,rm),FLconst,pushsize * (npushes - 1));  // PUSH [reg] 
     2980                    {   c2 = genc1(c2,0xFF,modregrmx(2,6,rm),FLconst,pushsize * (npushes - 1));  // PUSH [reg] 
    28782981                        code_orflag(c2,seg); 
    28792982                        genadjesp(c2,pushsize); 
    28802983                    } 
    2881                     c3 = gen2(CNIL,0xFF,modregrm(0,6,rm));      // PUSH [reg] 
     2984                    c3 = gen2(CNIL,0xFF,modregrmx(0,6,rm));     // PUSH [reg] 
    28822985                    c3->Iflags |= seg; 
    28832986                    genadjesp(c3,pushsize); 
    28842987                    ce = cat4(cc,c1,c2,c3); 
    28852988                } 
    28862989                else if (sz) 
    28872990                {   int size; 
    28882991 
    28892992                    c2 = getregs_imm(mCX | retregs); 
    28902993                                                        /* MOV CX,sz/2  */ 
    28912994                    c2 = movregconst(c2,CX,npushes,0); 
    28922995                    if (!doneoff) 
    28932996                    {   /* This disgusting thing should be done when    */ 
    28942997                        /* reg is loaded. Too lazy to fix it now.       */ 
    28952998                                                        /* ADD reg,sz-2 */ 
    2896                         c2 = genc2(c2,0x81,modregrm(3,0,reg),sz-pushsize); 
     2999                        c2 = genc2(c2,0x81,grex | modregrmx(3,0,reg),sz-pushsize); 
    28973000                    } 
    2898                     c3 = gen2(CNIL,0xFF,modregrm(0,6,rm));      // PUSH [reg] 
     3001                    c3 = gen2(CNIL,0xFF,modregrmx(0,6,rm));      // PUSH [reg] 
    28993002                    c3->Iflags |= seg | CFtarg2; 
    2900                     genc2(c3,0x81,modregrm(3,5,reg),pushsize);  // SUB reg,2 
     3003                    genc2(c3,0x81,grex | modregrmx(3,5,reg),pushsize);  // SUB reg,2 
    29013004                    size = ((seg & CFSEG) ? -8 : -7) - op16; 
    29023005                    if (code_next(c3)->Iop != 0x81) 
    29033006                        size++; 
    29043007                    //genc2(c3,0xE2,0,size);    // LOOP .-7 or .-8 
    29053008                    genjmp(c3,0xE2,FLcode,(block *)c3);         // LOOP c3 
    29063009                    regimmed_set(CX,0); 
    29073010                    genadjesp(c3,sz); 
    29083011                    ce = cat4(cc,c1,c2,c3); 
    29093012                } 
    29103013                else 
    29113014                    ce = cat(cc,c1); 
    29123015                stackpush += sz; 
    29133016                goto L2; 
    29143017        } 
    29153018    case OPind: 
    29163019        if (!e->Ecount)                         /* if *e1       */ 
    29173020        {       if (sz <= REGSIZE) 
    29183021                {   // Watch out for single byte quantities being up 
    29193022                    // against the end of a segment or in memory-mapped I/O 
    29203023                    if (!(config.exe & EX_flat) && szb == 1) 
     
    29913094        if (tysize[tym] == tysize[TYfptr] && 
    29923095            (fl = s->Sfl) != FLfardata && 
    29933096            /* not a function that CS might not be the segment of       */ 
    29943097            (!((fl == FLfunc || s->ty() & mTYcs) && 
    29953098              (s->Sclass == SCcomdat || s->Sclass == SCextern || s->Sclass == SCinline || config.wflags & WFthunk)) || 
    29963099             (fl == FLfunc && config.exe == EX_DOSX) 
    29973100            ) 
    29983101           ) 
    29993102        { 
    30003103            stackpush += sz; 
    30013104            c = gen1(c,0x06 +           /* PUSH SEGREG                  */ 
    30023105                    (((fl == FLfunc || s->ty() & mTYcs) ? 1 : segfl[fl]) << 3)); 
    30033106            c = genadjesp(c,REGSIZE); 
    30043107 
    30053108            if (config.target_cpu >= TARGET_80286 && !e->Ecount) 
    30063109            {   ce = getoffset(e,STACK); 
    30073110                goto L2; 
    30083111            } 
    30093112            else 
    30103113            {   c = cat(c,offsetinreg(e,&retregs)); 
    3011                 c = gen1(c,0x50+findreg(retregs)); /* PUSH reg          */ 
     3114                unsigned reg = findreg(retregs); 
     3115                c = genpush(c,reg);             // PUSH reg 
    30123116                genadjesp(c,REGSIZE); 
    30133117            } 
    30143118            goto ret; 
    30153119        } 
    30163120        if (config.target_cpu >= TARGET_80286 && !e->Ecount) 
    30173121        { 
    30183122            stackpush += sz; 
    30193123            if (tysize[tym] == tysize[TYfptr]) 
    3020             {   code *c1; 
    3021  
     3124            { 
    30223125                /* PUSH SEG e   */ 
    3023                 c1 = gencs(CNIL,0x68,0,FLextern,s); 
     3126                code *c1 = gencs(CNIL,0x68,0,FLextern,s); 
    30243127                c1->Iflags = CFseg; 
    30253128                genadjesp(c1,REGSIZE); 
    30263129                c = cat(c,c1); 
    30273130            } 
    30283131            ce = getoffset(e,STACK); 
    30293132            goto L2; 
    30303133        } 
    30313134#endif 
    30323135        break;                          /* else must evaluate expression */ 
    30333136    case OPvar: 
    30343137    L1: 
    30353138        if (0 && I32 && sz == 2) 
    30363139        {   /* 32 bit code, but pushing 16 bit values anyway    */ 
    30373140            ce = loadea(e,&cs,0xFF,6,0,0,0);            /* PUSH EA      */ 
    30383141            // BUG: 0x66 fails with scheduler 
    30393142            ce = cat(gen1(CNIL,0x66),ce);               /* 16 bit override */ 
    30403143            stackpush += sz; 
    30413144            genadjesp(ce,sz); 
    30423145        } 
    30433146        else if (config.flags4 & CFG4speed && 
    30443147                 (config.target_cpu >= TARGET_80486 && 
    30453148                  config.target_cpu <= TARGET_PentiumMMX) && 
    30463149                 sz <= 2 * REGSIZE && 
    30473150                 !tyfloating(tym)) 
    30483151        {   // Avoid PUSH MEM on the Pentium when optimizing for speed 
    30493152            break; 
    30503153        } 
    30513154        else 
    30523155        {   int regsize = REGSIZE; 
    30533156            unsigned flag = 0; 
    30543157 
    3055             if (!I32 && config.target_cpu >= TARGET_80386 && sz > 2 && 
     3158            if (I16 && config.target_cpu >= TARGET_80386 && sz > 2 && 
    30563159                !e->Ecount) 
    30573160            {   regsize = 4; 
    30583161                flag |= CFopsize; 
    30593162            } 
    30603163            ce = loadea(e,&cs,0xFF,6,sz - regsize,RMload,0);    // PUSH EA+sz-2 
    30613164            code_orflag(ce,flag); 
    30623165            ce = genadjesp(ce,REGSIZE); 
    30633166            stackpush += sz; 
    30643167            while ((targ_int)(sz -= regsize) > 0) 
    30653168            {   ce = cat(ce,loadea(e,&cs,0xFF,6,sz - regsize,RMload,0)); 
    30663169                code_orflag(ce,flag); 
    30673170                ce = genadjesp(ce,REGSIZE); 
    30683171            } 
    30693172        } 
    30703173    L2: 
    30713174        freenode(e); 
    30723175        c = cat(c,ce); 
    30733176        goto ret; 
    30743177    case OPconst: 
    30753178    {   targ_int *pi; 
     
    30913194            ce = genadjesp(NULL,sz); 
    30923195            for (i = 2; i >= 0; i--) 
    30933196            { 
    30943197                if (reghasvalue(allregs, value, &reg)) 
    30953198                    ce = gen1(ce,0x50 + reg);           // PUSH reg 
    30963199                else 
    30973200                    ce = genc2(ce,0x68,0,value);        // PUSH value 
    30983201                value = ((unsigned *)&e->EV.Vldouble)[i - 1]; 
    30993202            } 
    31003203            goto L2; 
    31013204        } 
    31023205 
    31033206        assert(sz <= LNGDBLSIZE); 
    31043207        i = sz; 
    31053208        if (I32 && i == 2) 
    31063209            flag = CFopsize; 
    31073210 
    31083211        if (config.target_cpu >= TARGET_80286) 
    31093212//       && (e->Ecount == 0 || e->Ecount != e->Ecomsub)) 
    31103213        {   pushi = 1; 
    3111             if (!I32 && config.target_cpu >= TARGET_80386 && i >= 4) 
     3214            if (I16 && config.target_cpu >= TARGET_80386 && i >= 4) 
    31123215            {   regsize = 4; 
    31133216                flag = CFopsize; 
    31143217            } 
    31153218        } 
    31163219        else if (i == REGSIZE) 
    31173220            break; 
    31183221 
    31193222        stackpush += sz; 
    31203223        ce = genadjesp(NULL,sz); 
    31213224        pi = (targ_long *) &e->EV.Vdouble; 
    31223225        ps = (targ_short *) pi; 
    31233226        i /= regsize; 
    31243227        do 
    31253228        {   code *cp; 
    31263229 
    31273230            if (i)                      /* be careful not to go negative */ 
    31283231                i--; 
    31293232            value = (regsize == 4) ? pi[i] : ps[i]; 
    31303233            if (pushi) 
    31313234            { 
    31323235                if (regsize == REGSIZE && reghasvalue(allregs,value,&reg)) 
    31333236                    goto Preg; 
    31343237                ce = genc2(ce,(szb == 1) ? 0x6A : 0x68,0,value); // PUSH value 
    31353238            } 
    31363239            else 
    31373240            { 
    31383241                ce = regwithvalue(ce,allregs,value,&reg,0); 
    31393242            Preg: 
    3140                 ce = gen1(ce,0x50 + reg);               /* PUSH reg     */ 
     3243                ce = genpush(ce,reg);         // PUSH reg 
    31413244            } 
    31423245            code_orflag(ce,flag);                       /* operand size */ 
    31433246        } while (i); 
    31443247        goto L2; 
    31453248    } 
    31463249    default: 
    31473250        break; 
    31483251  } 
    31493252  retregs = tybyte(tym) ? BYTEREGS : allregs; 
    31503253  if (tyfloating(tym)) 
    31513254  {     if (config.inline8087) 
    31523255        {   code *c1,*c2; 
    31533256            unsigned op; 
    31543257            unsigned r; 
    31553258 
    31563259            retregs = tycomplex(tym) ? mST01 : mST0; 
    31573260            c = cat(c,codelem(e,&retregs,FALSE)); 
    31583261            stackpush += sz; 
    31593262            c = genadjesp(c,sz); 
    3160             c = genc2(c,0x81,modregrm(3,5,SP),sz);      /* SUB SP,sz    */ 
     3263            c = genc2(c,0x81,grex | modregrm(3,5,SP),sz);      // SUB SP,sz 
    31613264            switch (tym) 
    31623265            { 
    31633266                case TYfloat: 
    31643267                case TYifloat: 
    31653268                case TYcfloat: 
    31663269                    op = 0xD9; 
    31673270                    r = 3; 
    31683271                    break; 
    31693272 
    31703273                case TYdouble: 
    31713274                case TYidouble: 
    31723275                case TYdouble_alias: 
    31733276                case TYcdouble: 
    31743277                    op = 0xDD; 
    31753278                    r = 3; 
    31763279                    break; 
    31773280 
    31783281                case TYldouble: 
    31793282                case TYildouble: 
    31803283                case TYcldouble: 
    31813284                    op = 0xDB; 
    31823285                    r = 7; 
    31833286                    break; 
    31843287 
    31853288                default: 
    31863289                    assert(0); 
    31873290            } 
    3188             if (I32
     3291            if (!I16
    31893292            { 
    31903293                c1 = NULL; 
    31913294                c2 = NULL; 
    31923295                if (tycomplex(tym)) 
    31933296                { 
    31943297                    // FSTP sz/2[ESP] 
    3195                     c2 = genc1(CNIL,op,modregrm(2,r,4),FLconst,sz/2); 
    3196                     c2->Isib = modregrm(0,4,SP); 
     3298                    c2 = genc1(CNIL,op,(modregrm(0,4,SP) << 8) | modregxrm(2,r,4),FLconst,sz/2); 
    31973299                    pop87(); 
    31983300                } 
    31993301                pop87(); 
    32003302                c2 = gen2sib(c2,op,modregrm(0,r,4),modregrm(0,4,SP));   // FSTP [ESP] 
    32013303            } 
    32023304            else 
    32033305            { 
    32043306                retregs = IDXREGS;                      /* get an index reg */ 
    32053307                c1 = allocreg(&retregs,&reg,TYoffset); 
    32063308                c1 = genregs(c1,0x89,SP,reg);           /* MOV reg,SP    */ 
    32073309                pop87(); 
    32083310                c2 = gen2(CNIL,op,modregrm(0,r,regtorm[reg]));          // FSTP [reg] 
    32093311            } 
    32103312            if (LARGEDATA) 
    32113313                c2->Iflags |= CFss;     /* want to store into stack     */ 
    32123314            genfwait(c2);               // FWAIT 
    32133315            c = cat3(c,c1,c2); 
    32143316            goto ret; 
    32153317        } 
    32163318        else if (!I32 && (tym == TYdouble || tym == TYdouble_alias)) 
    32173319            retregs = mSTACK; 
    32183320  } 
    32193321#if LONGLONG 
    32203322  else if (!I32 && sz == 8)             // if long long 
    32213323        retregs = mSTACK; 
    32223324#endif 
    32233325  c = cat(c,scodelem(e,&retregs,0,TRUE)); 
    32243326  if (retregs != mSTACK)                /* if stackpush not already inc'd */ 
    32253327      stackpush += sz; 
    32263328  if (sz <= REGSIZE) 
    32273329  { 
    3228         c = gen1(c,0x50+findreg(retregs));      /* PUSH reg             */ 
     3330        c = genpush(c,findreg(retregs));        // PUSH reg 
    32293331        genadjesp(c,REGSIZE); 
    32303332  } 
    32313333  else if (sz == REGSIZE * 2) 
    3232   {     c = gen1(c,0x50+findregmsw(retregs)); /* PUSH msreg             */ 
    3233         gen1(c,0x50+findreglsw(retregs));         /* PUSH lsreg         */ 
     3334  {     c = genpush(c,findregmsw(retregs));     // PUSH msreg 
     3335        genpush(c,findreglsw(retregs));         // PUSH lsreg 
    32343336        genadjesp(c,sz); 
    32353337  } 
    32363338ret: 
    32373339  return cat(cp,c); 
    32383340} 
    32393341 
    32403342 
    32413343/******************************* 
    32423344 * Get offset portion of e, and store it in an index 
    32433345 * register. Return mask of index register in *pretregs. 
    32443346 */ 
    32453347 
    32463348code *offsetinreg( elem *e, regm_t *pretregs) 
    32473349{   regm_t retregs; 
    32483350    code *c; 
    32493351    unsigned reg; 
    32503352 
    32513353    retregs = mLSW;                     /* want only offset     */ 
    32523354    if (e->Ecount && e->Ecount != e->Ecomsub) 
    32533355    {   unsigned i; 
     
    33033405        if (config.inline8087) 
    33043406        {   if (*pretregs & mST0) 
    33053407                return load87(e,0,pretregs,NULL,-1); 
    33063408            else if (tycomplex(tym)) 
    33073409                return cload87(e, pretregs); 
    33083410        } 
    33093411  } 
    33103412  sz = tysize[tym]; 
    33113413  cs.Iflags = 0; 
    33123414  cs.Irex = 0; 
    33133415  if (*pretregs == mPSW) 
    33143416  { 
    33153417        regm = allregs; 
    33163418        if (e->Eoper == OPconst) 
    33173419        {       /* TRUE:        OR SP,SP        (SP is never 0)         */ 
    33183420                /* FALSE:       CMP SP,SP       (always equal)          */ 
    33193421                c = genregs(CNIL,(boolres(e)) ? 0x09 : 0x39,SP,SP); 
    33203422        } 
    33213423        else if (sz <= REGSIZE) 
    33223424        { 
    3323             if (I32 && (tym == TYfloat || tym == TYifloat)) 
     3425            if (!I16 && (tym == TYfloat || tym == TYifloat)) 
    33243426            {   c = allocreg(&regm,&reg,TYoffset);      /* get a register */ 
    33253427                ce = loadea(e,&cs,0x8B,reg,0,0,0);      // MOV reg,data 
    33263428                c = cat(c,ce); 
    3327                 ce = gen2(CNIL,0xD1,modregrm(3,4,reg)); /* SHL reg,1      */ 
     3429                ce = gen2(CNIL,0xD1,modregrmx(3,4,reg)); /* SHL reg,1      */ 
    33283430                c = cat(c,ce); 
    33293431            } 
    33303432            else 
    33313433            {   cs.IFL2 = FLconst; 
    33323434                cs.IEV2.Vint = 0; 
    33333435                op = (sz == 1) ? 0x80 : 0x81; 
    33343436                c = loadea(e,&cs,op,7,0,0,0);           /* CMP EA,0     */ 
    33353437 
    33363438                // Convert to TEST instruction if EA is a register 
    33373439                // (to avoid register contention on Pentium) 
    33383440                if ((c->Iop & 0xFE) == 0x38 && 
    33393441                    (c->Irm & modregrm(3,0,0)) == modregrm(3,0,0) 
    33403442                   ) 
    33413443                {   c->Iop = (c->Iop & 1) | 0x84; 
    3342                     c->Irm = (c->Irm & modregrm(3,0,7)) | modregrm(0,c->Irm & 7,0); 
     3444                    code_newreg(c, c->Irm & 7); 
     3445                    if (c->Irex & REX_B) 
     3446                        c->Irex = (c->Irex & ~REX_B) | REX_R; 
    33433447                } 
    33443448            } 
    33453449        } 
    33463450        else if (sz < 8) 
    33473451        { 
    33483452            c = allocreg(&regm,&reg,TYoffset);          /* get a register */ 
    33493453            if (I32)                                    // it's a 48 bit pointer 
    33503454                ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 
    33513455            else 
    33523456            {   ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 
    33533457                if (tym == TYfloat || tym == TYifloat)  // dump sign bit 
    33543458                    gen2(ce,0xD1,modregrm(3,4,reg));    /* SHL reg,1      */ 
    33553459            } 
    33563460            c = cat(c,ce); 
    33573461            ce = loadea(e,&cs,0x0B,reg,0,regm,0);       /* OR reg,data */ 
    33583462            c = cat(c,ce); 
    33593463        } 
    33603464        else if (sz == 8) 
    33613465        {   code *c1; 
    33623466            int i; 
     
    33833487        return c; 
    33843488  } 
    33853489  /* not for flags only */ 
    33863490  flags = *pretregs & mPSW;             /* save original                */ 
    33873491  forregs = *pretregs & (mBP | ALLREGS | mES); 
    33883492  if (*pretregs & mSTACK) 
    33893493        forregs |= DOUBLEREGS; 
    33903494  if (e->Eoper == OPconst) 
    33913495  {     regm_t save; 
    33923496 
    33933497        if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,&reg)) 
    33943498            forregs = mask[reg]; 
    33953499 
    33963500        save = regcon.immed.mval; 
    33973501        c = allocreg(&forregs,&reg,tym);        /* allocate registers   */ 
    33983502        regcon.immed.mval = save;               // KLUDGE! 
    33993503        if (sz <= REGSIZE) 
    34003504        { 
    34013505            if (sz == 1) 
    34023506                flags |= 1; 
    3403             else if (I32 && sz == SHORTSIZE && 
     3507            else if (!I16 && sz == SHORTSIZE && 
    34043508                     !(mask[reg] & regcon.mvar) && 
    34053509                     !(config.flags4 & CFG4speed) 
    34063510                    ) 
    34073511                flags |= 2; 
     3512            if (sz == 8) 
     3513                flags |= 64; 
    34083514            ce = movregconst(CNIL,reg,e->EV.Vint,flags); 
    34093515            flags = 0;                          // flags are already set 
    34103516        } 
    34113517        else if (sz < 8)        // far pointers, longs for 16 bit targets 
    34123518        { 
    34133519            targ_int msw,lsw; 
    34143520            regm_t mswflags; 
    34153521 
    34163522            msw = I32   ? e->EV.Vfp.Vseg 
    34173523                        : (e->EV.Vulong >> 16); 
    34183524            lsw = e->EV.Vfp.Voff; 
    34193525            mswflags = 0; 
    34203526            if (forregs & mES) 
    34213527            { 
    34223528                ce = movregconst(CNIL,reg,msw,0);       // MOV reg,segment 
    34233529                genregs(ce,0x8E,0,reg);                 // MOV ES,reg 
    34243530                msw = lsw;                              // MOV reg,offset 
    34253531            } 
    34263532            else 
    34273533            { 
     
    34673573    { 
    34683574        reg = e->EV.sp.Vsym->Spreg; 
    34693575        forregs = mask[reg]; 
    34703576        mfuncreg &= ~forregs; 
    34713577        regcon.used |= forregs; 
    34723578        return fixresult(e,forregs,pretregs); 
    34733579    } 
    34743580 
    34753581    c = allocreg(&forregs,&reg,tym);            /* allocate registers   */ 
    34763582 
    34773583    if (sz == 1) 
    34783584    {   regm_t nregm; 
    34793585 
    34803586#ifdef DEBUG 
    34813587        if (!(forregs & BYTEREGS)) 
    34823588        {       elem_print(e); 
    34833589                printf("forregs = x%x\n",forregs); 
    34843590        } 
    34853591#endif 
    34863592        assert(forregs & BYTEREGS); 
    3487         if (I32
     3593        if (!I16
    34883594            c = cat(c,loadea(e,&cs,0x8A,reg,0,0,0));    // MOV regL,data 
    34893595        else 
    34903596        {   nregm = tyuns(tym) ? BYTEREGS : mAX; 
    34913597            if (*pretregs & nregm) 
    34923598                nreg = reg;                     /* already allocated    */ 
    34933599            else 
    34943600                c = cat(c,allocreg(&nregm,&nreg,tym)); 
    34953601            ce = loadea(e,&cs,0x8A,nreg,0,0,0); /* MOV nregL,data       */ 
    34963602            c = cat(c,ce); 
    34973603            if (reg != nreg) 
    34983604            {   genmovreg(c,reg,nreg);          /* MOV reg,nreg         */ 
    34993605                cssave(e,mask[nreg],FALSE); 
    35003606            } 
    35013607        } 
    35023608    } 
    35033609    else if (sz <= REGSIZE) 
    35043610    { 
    35053611        ce = loadea(e,&cs,0x8B,reg,0,RMload,0); // MOV reg,data 
    35063612        c = cat(c,ce); 
    35073613    } 
  • branches/dmd-1.x/src/backend/cod2.c

    r552 r577  
    1919#include        "oper.h" 
    2020#include        "el.h" 
    2121#include        "code.h" 
    2222#include        "global.h" 
    2323#include        "type.h" 
    2424#if SCPP 
    2525#include        "exh.h" 
    2626#endif 
    2727 
    2828static char __file__[] = __FILE__;      /* for tassert.h                */ 
    2929#include        "tassert.h" 
    3030 
    3131int cdcmp_flag; 
    3232extern signed char regtorm[8]; 
    3333 
    3434/******************************** 
    3535 * Return mask of index registers used by addressing mode. 
    3636 * Index is rm of modregrm field. 
    3737 */ 
    3838 
    39 regm_t idxregm(unsigned rm,unsigned sib
     39regm_t idxregm(code *c
    4040{ 
    4141    static const unsigned char idxsib[8] = { mAX,mCX,mDX,mBX,0,mBP,mSI,mDI }; 
    4242    static const unsigned char idxrm[8] = {mBX|mSI,mBX|mDI,mSI,mDI,mSI,mDI,0,mBX}; 
    43     regm_t idxm; 
    44  
    45     idxm = 0; 
     43 
     44    unsigned rm = c->Irm; 
     45    regm_t idxm = 0; 
    4646    if ((rm & 0xC0) != 0xC0)            /* if register is not the destination */ 
    4747    { 
    48         if (I32) 
     48        if (I16) 
     49            idxm = idxrm[rm & 7]; 
     50        else 
    4951        { 
    5052            if ((rm & 7) == 4)          /* if sib byte                  */ 
    5153            { 
    52                 idxm = idxsib[(sib >> 3) & 7];  /* scaled index reg     */ 
     54                unsigned sib = c->Isib; 
     55                unsigned idxreg = (sib >> 3) & 7; 
     56                if (c->Irex & REX_X) 
     57                {   idxreg |= 8; 
     58                    idxm = mask[idxreg];  // scaled index reg 
     59                } 
     60                else 
     61                    idxm = idxsib[idxreg];  // scaled index reg 
    5362                if ((sib & 7) == 5 && (rm & 0xC0) == 0) 
    5463                    ; 
    5564                else 
    56                     idxm |= idxsib[sib & 7]; 
     65                {   unsigned base = sib & 7; 
     66                    if (c->Irex & REX_B) 
     67                        idxm |= mask[base | 8]; 
     68                    else 
     69                        idxm |= idxsib[base]; 
     70                } 
    5771            } 
    5872            else 
    59                 idxm |= idxsib[rm & 7]; 
    60         } 
    61         else 
    62             idxm = idxrm[rm & 7]; 
     73            {   unsigned base = rm & 7; 
     74                if (c->Irex & REX_B) 
     75                    idxm |= mask[base | 8]; 
     76                else 
     77                    idxm |= idxsib[base]; 
     78            } 
     79        } 
    6380    } 
    6481    return idxm; 
    6582} 
    6683 
    6784#if TARGET_WINDOS 
    6885/*************************** 
    6986 * Gen code for call to floating point routine. 
    7087 */ 
    7188 
    7289code *opdouble(elem *e,regm_t *pretregs,unsigned clib) 
    7390{ 
    7491    regm_t retregs1,retregs2; 
    7592    code *cl, *cr, *c; 
    7693 
    7794    if (config.inline8087) 
    7895        return orth87(e,pretregs); 
    7996 
    8097    if (tybasic(e->E1->Ety) == TYfloat) 
    8198    { 
    8299        clib += CLIBfadd - CLIBdadd;    /* convert to float operation   */ 
     
    95113        } 
    96114    } 
    97115    cl = codelem(e->E1, &retregs1,FALSE); 
    98116    if (retregs1 & mSTACK) 
    99117        cgstate.stackclean++; 
    100118    cr = scodelem(e->E2, &retregs2, retregs1 & ~mSTACK, FALSE); 
    101119    if (retregs1 & mSTACK) 
    102120        cgstate.stackclean--; 
    103121    c = callclib(e, clib, pretregs, 0); 
    104122    return cat3(cl, cr, c); 
    105123} 
    106124#endif 
    107125 
    108126 
    109127/***************************** 
    110128 * Handle operators which are more or less orthogonal 
    111129 * ( + - & | ^ ) 
    112130 */ 
    113131 
    114132code *cdorth(elem *e,regm_t *pretregs) 
    115 { tym_t ty,ty1,ty2
     133{ tym_t ty1
    116134  regm_t retregs,rretregs,posregs; 
    117   unsigned reg,rreg,op1,op2,mode,test,byte
     135  unsigned reg,rreg,op1,op2,mode
    118136  int rval; 
    119   code *c,*cg,*cl,*cr,cs
    120   targ_int i; 
     137  code *c,*cg,*cl
     138  targ_size_t i; 
    121139  elem *e1,*e2; 
    122140  int numwords;                         /* # of words to be operated on */ 
    123   unsigned char word;                   /* if word operands             */ 
    124   int e2oper; 
    125   unsigned sz; 
    126141  static int nest; 
    127142 
    128143  //printf("cdorth(e = %p, *pretregs = %s)\n",e,regm_str(*pretregs)); 
    129144  e1 = e->E1; 
    130145  e2 = e->E2; 
    131146  if (*pretregs == 0)                   /* if don't want result         */ 
    132147  {     c = codelem(e1,pretregs,FALSE); /* eval left leaf               */ 
    133148        *pretregs = 0;                  /* in case they got set         */ 
    134149        return cat(c,codelem(e2,pretregs,FALSE)); 
    135150  } 
    136151 
    137152  ty1 = tybasic(e1->Ety); 
    138153  if (tyfloating(ty1)) 
    139154#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    140155        return orth87(e,pretregs); 
    141156#else 
    142157        return opdouble(e,pretregs,(e->Eoper == OPadd) ? CLIBdadd 
    143158                                                       : CLIBdsub); 
    144159#endif 
    145   ty2 = tybasic(e2->Ety); 
    146   e2oper = e2->Eoper; 
    147   ty = tybasic(e->Ety); 
    148   sz = tysize[ty]; 
    149   byte = (sz == 1); 
    150   word = (I32 && sz == SHORTSIZE) ? CFopsize : 0; 
     160  tym_t ty2 = tybasic(e2->Ety); 
     161  int e2oper = e2->Eoper; 
     162  tym_t ty = tybasic(e->Ety); 
     163  unsigned sz = tysize[ty]; 
     164  unsigned byte = (sz == 1); 
     165  unsigned char word = (!I16 && sz == SHORTSIZE) ? CFopsize : 0; 
     166  unsigned test = FALSE;                // assume we destroyed lvalue 
     167  code cs; 
    151168  cs.Iflags = 0; 
    152169  cs.Irex = 0; 
    153   test = FALSE;                         /* assume we destroyed lvalue   */ 
    154   cr = CNIL;                            /* initialize                   */ 
     170  code *cr = CNIL; 
    155171 
    156172  switch (e->Eoper) 
    157173  {     case OPadd:     mode = 0; 
    158174                        op1 = 0x03; op2 = 0x13; break;  /* ADD, ADC     */ 
    159175        case OPmin:     mode = 5; 
    160176                        op1 = 0x2B; op2 = 0x1B; break;  /* SUB, SBB     */ 
    161177        case OPor:      mode = 1; 
    162178                        op1 = 0x0B; op2 = 0x0B; break;  /* OR , OR      */ 
    163179        case OPxor:     mode = 6; 
    164180                        op1 = 0x33; op2 = 0x33; break;  /* XOR, XOR     */ 
    165181        case OPand:     mode = 4; 
    166182                        op1 = 0x23; op2 = 0x23;         /* AND, AND     */ 
    167183                        if (tyreg(ty1) && 
    168184                            *pretregs == mPSW)          /* if flags only */ 
    169185                        {       test = TRUE; 
    170186                                op1 = 0x85;             /* TEST         */ 
    171187                                mode = 0; 
    172188                        } 
    173189                        break; 
    174190        default: 
    175191                assert(0); 
    176192  } 
    177193  op1 ^= byte;                                  /* if byte operation    */ 
    178194 
    179195  /* Compute number of words to operate on.                             */ 
    180196  numwords = 1; 
    181   if (I32
     197  if (!I16
    182198  {     /* Cannot operate on longs and then do a 'paint' to a far       */ 
    183199        /* pointer, because far pointers are 48 bits and longs are 32.  */ 
    184200        /* Therefore, numwords can never be 2.                          */ 
    185201        assert(!(tyfv(ty1) && tyfv(ty2))); 
    186202        if (sz == 2 * REGSIZE) 
    187203        { 
    188204            numwords++; 
    189205        } 
    190206  } 
    191207  else 
    192208  {     /* If ty is a TYfptr, but both operands are long, treat the     */ 
    193209        /* operation as a long.                                         */ 
    194210        if ((tylong(ty1) || ty1 == TYhptr) && 
    195211            (tylong(ty2) || ty2 == TYhptr)) 
    196212            numwords++; 
    197213  } 
    198214 
    199215  // Special cases where only flags are set 
    200216  if (test && tysize[ty1] <= REGSIZE && 
    201217      (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount))) 
    202218  { 
    203219        // Handle the case of (var & const) 
    204220        if (e2->Eoper == OPconst) 
    205         {   targ_int value; 
    206  
     221        { 
    207222            c = getlvalue(&cs,e1,0); 
    208             value = e2->EV.Vint
     223            targ_size_t value = e2->EV.Vpointer
    209224            if (sz == 2) 
    210225                value &= 0xFFFF; 
     226            else if (sz == 4) 
     227                value &= 0xFFFFFFFF; 
    211228            if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,&reg)) 
    212229                goto L11; 
     230            if (sz == 8) 
     231            { 
     232                assert(value == (int)value);    // sign extend imm32 
     233            } 
    213234            op1 = 0xF7; 
    214235            cs.IEV2.Vint = value; 
    215236            cs.IFL2 = FLconst; 
    216237            goto L10; 
    217238        } 
    218239 
    219240        // Handle (exp & reg) 
    220241        if (isregvar(e2,&retregs,&reg)) 
    221242        { 
    222243            c = getlvalue(&cs,e1,0); 
    223244        L11: 
    224             cs.Irm |= modregrm(0,reg,0); 
     245            code_newreg(&cs, reg); 
    225246        L10: 
    226247            cs.Iop = op1 ^ byte; 
    227248            cs.Iflags |= word | CFpsw; 
    228249            freenode(e1); 
    229250            freenode(e2); 
    230251            return gen(c,&cs); 
    231252        } 
    232253  } 
    233254 
    234255  // Look for possible uses of LEA 
    235256  if (e->Eoper == OPadd && 
    236257      !(*pretregs & mPSW) &&            /* flags aren't set by LEA      */ 
    237258      !nest &&                          // could cause infinite recursion if e->Ecount 
    238       sz == REGSIZE)                    // far pointers aren't handled 
    239   {     int e1oper; 
    240  
     259      (sz == REGSIZE || (I64 && sz == 4)))  // far pointers aren't handled 
     260  { 
    241261        // Handle the case of (e + &var) 
    242         e1oper = e1->Eoper; 
     262        int e1oper = e1->Eoper; 
    243263        if ((e2oper == OPrelconst && (config.target_cpu >= TARGET_Pentium || (!e2->Ecount && stackfl[el_fl(e2)]))) 
    244264                || // LEA costs too much for simple EAs on older CPUs 
    245265            (e2oper == OPconst && (e1->Eoper == OPcall || e1->Eoper == OPcallns) && !(*pretregs & mAX)) || 
    246             (I32 && (isscaledindex(e1) || isscaledindex(e2))) || 
    247             (I32 && e1oper == OPvar && e1->EV.sp.Vsym->Sfl == FLreg && (e2oper == OPconst || (e2oper == OPvar && e2->EV.sp.Vsym->Sfl == FLreg))) || 
     266            (!I16 && (isscaledindex(e1) || isscaledindex(e2))) || 
     267            (!I16 && e1oper == OPvar && e1->EV.sp.Vsym->Sfl == FLreg && (e2oper == OPconst || (e2oper == OPvar && e2->EV.sp.Vsym->Sfl == FLreg))) || 
    248268            (e2oper == OPconst && e1oper == OPeq && e1->E1->Eoper == OPvar) || 
    249             (I32 && e2oper == OPrelconst && !e1->Ecount && 
     269            (!I16 && e2oper == OPrelconst && !e1->Ecount && 
    250270             (e1oper == OPmul || e1oper == OPshl) && 
    251271             e1->E2->Eoper == OPconst && 
    252272             ssindex(e1oper,e1->E2->EV.Vuns) 
    253273            ) || 
    254             (I32 && e1->Ecount) 
     274            (!I16 && e1->Ecount) 
    255275           ) 
    256         {   int inc; 
    257  
    258             inc = e->Ecount != 0; 
     276        { 
     277            int inc = e->Ecount != 0; 
    259278            nest += inc; 
    260279            c = getlvalue(&cs,e,0); 
    261280            nest -= inc; 
     281            unsigned reg; 
    262282            c = cat(c,allocreg(pretregs,&reg,ty)); 
    263283            cs.Iop = 0x8D; 
    264             cs.Irm |= modregrm(0,reg,0); 
     284            code_newreg(&cs, reg); 
    265285            return gen(c,&cs);          /* LEA reg,EA                   */ 
    266286        } 
    267287 
    268288        // Handle the case of ((e + c) + e2) 
    269         if (I32 && 
     289        if (!I16 && 
    270290            e1oper == OPadd && 
    271291            (e1->E2->Eoper == OPconst || e2oper == OPconst) && 
    272292            !e1->Ecount 
    273293           ) 
    274294        {   elem *e11; 
    275295            elem *ebase; 
    276296            elem *edisp; 
    277297            int ss; 
    278298            int ss2; 
    279299            unsigned reg1,reg2; 
    280300            code *c1,*c2,*c3; 
    281301 
    282302            if (e2oper == OPconst) 
    283303            {   edisp = e2; 
    284304                ebase = e1->E2; 
    285305            } 
    286306            else 
    287307            {   edisp = e1->E2; 
    288308                ebase = e2; 
    289309            } 
    290310 
    291311            e11 = e1->E1; 
    292312            retregs = *pretregs & ALLREGS; 
    293313            if (!retregs) 
    294314                retregs = ALLREGS; 
    295315            ss = 0; 
    296316            ss2 = 0; 
    297317 
    298318            // Handle the case of (((e *  c1) + c2) + e2) 
    299319            // Handle the case of (((e << c1) + c2) + e2) 
    300320            if ((e11->Eoper == OPmul || e11->Eoper == OPshl) && 
    301321                e11->E2->Eoper == OPconst && 
    302322                !e11->Ecount 
    303323               ) 
    304             {   targ_size_t co1; 
    305  
    306                 co1 = el_tolong(e11->E2); 
     324            { 
     325                targ_size_t co1 = el_tolong(e11->E2); 
    307326                if (e11->Eoper == OPshl) 
    308327                { 
    309328                    if (co1 > 3) 
    310329                        goto L13; 
    311330                    ss = co1; 
    312331                } 
    313332                else 
    314333                { 
    315334                    ss2 = 1; 
    316335                    switch (co1) 
    317336                    { 
    318337                        case  6:        ss = 1;                 break; 
    319338                        case 12:        ss = 1; ss2 = 2;        break; 
    320339                        case 24:        ss = 1; ss2 = 3;        break; 
    321340                        case 10:        ss = 2;                 break; 
    322341                        case 20:        ss = 2; ss2 = 2;        break; 
    323342                        case 40:        ss = 2; ss2 = 3;        break; 
    324343                        case 18:        ss = 3;                 break; 
    325344                        case 36:        ss = 3; ss2 = 2;        break; 
    326345                        case 72:        ss = 3; ss2 = 3;        break; 
    327346                        default: 
    328347                            ss2 = 0; 
    329348                            goto L13; 
    330349                    } 
    331350                } 
    332351                freenode(e11->E2); 
    333352                freenode(e11); 
    334353                e11 = e11->E1; 
    335354                goto L13; 
    336355            } 
    337356            else 
    338             {   regm_t regm; 
     357            { 
    339358            L13: 
     359                regm_t regm; 
    340360                if (e11->Eoper == OPvar && isregvar(e11,&regm,&reg1)) 
    341361                { 
    342362                    retregs = regm; 
    343363                    c1 = NULL; 
    344364                    freenode(e11); 
    345365                } 
    346366                else 
    347367                    c1 = codelem(e11,&retregs,FALSE); 
    348368            } 
    349369            rretregs = ALLREGS & ~retregs; 
    350370            c2 = scodelem(ebase,&rretregs,retregs,TRUE); 
    351             {   regm_t sregs; 
    352  
    353                 sregs = *pretregs & ~rretregs; 
     371            { 
     372                regm_t sregs = *pretregs & ~rretregs; 
    354373                if (!sregs) 
    355374                    sregs = ALLREGS & ~rretregs; 
    356375                c3 = allocreg(&sregs,&reg,ty); 
    357376            } 
    358377 
    359378            reg1 = findreg(retregs); 
    360379            reg2 = findreg(rretregs); 
    361380 
    362381            if (ss2) 
    363382            { 
    364383                assert(reg != reg2); 
    365384                if (reg1 == BP) 
    366385                {   static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 
    367386 
    368387                    // IMUL reg,imm32 
    369                     c = genc2(CNIL,0x69,modregrm(3,reg,reg1),imm32[ss]); 
     388                    c = genc2(CNIL,0x69,modregxrm(3,reg,BP),imm32[ss]); 
    370389                } 
    371390                else 
    372391                {   // LEA reg,[reg1*ss][reg1] 
    373                     c = gen2sib(CNIL,0x8D,modregrm(0,reg,4),modregrm(ss,reg1,reg1)); 
     392                    c = gen2sib(CNIL,0x8D,modregxrm(0,reg,4),modregrm(ss,reg1 & 7,reg1 & 7)); 
     393                    if (reg1 & 8) 
     394                        code_orrex(c, REX_X | REX_B); 
    374395                } 
    375396                reg1 = reg; 
    376397                ss = ss2;                               // use *2 for scale 
    377398            } 
    378399            else 
    379400                c = NULL; 
    380401            c = cat4(c1,c2,c3,c); 
    381402 
    382403            cs.Iop = 0x8D;                      // LEA reg,c[reg1*ss][reg2] 
    383             cs.Irm = modregrm(2,reg,4); 
    384             cs.Isib = modregrm(ss,reg1,reg2); 
     404            cs.Irm = modregrm(2,reg & 7,4); 
     405            cs.Isib = modregrm(ss,reg1 & 7,reg2 & 7); 
    385406            cs.Iflags = CFoff; 
    386407            cs.Irex = 0; 
     408            if (reg & 8) 
     409                cs.Irex |= REX_R; 
     410            if (reg1 & 8) 
     411                cs.Irex |= REX_X; 
     412            if (reg2 & 8) 
     413                cs.Irex |= REX_B; 
    387414            cs.IFL1 = FLconst; 
    388415            cs.IEV1.Vuns = edisp->EV.Vuns; 
    389416 
    390417            freenode(edisp); 
    391418            freenode(e1); 
    392419            c = gen(c,&cs); 
    393420            return cat(c,fixresult(e,mask[reg],pretregs)); 
    394421        } 
    395422  } 
    396423 
    397424  posregs = (byte) ? BYTEREGS : (mES | ALLREGS | mBP); 
    398425  retregs = *pretregs & posregs; 
    399426  if (retregs == 0)                     /* if no return regs speced     */ 
    400427                                        /* (like if wanted flags only)  */ 
    401428        retregs = ALLREGS & posregs;    // give us some 
    402429 
    403430  if (tysize[ty1] > REGSIZE && numwords == 1) 
    404431  {     /* The only possibilities are (TYfptr + tyword) or (TYfptr - tyword) */ 
    405432#if DEBUG 
    406433        if (tysize[ty2] != REGSIZE) 
     
    489516 
    490517            /* if retregs doesn't have any regs in it that aren't reg vars */ 
    491518            if ((retregs & ~regcon.mvar) == 0) 
    492519                retregs |= mAX; 
    493520        } 
    494521        else if (numwords == 2 && retregs & mES) 
    495522            retregs = (retregs | mMSW) & ALLREGS; 
    496523 
    497524        // Determine if we should swap operands, because 
    498525        //      mov     EAX,x 
    499526        //      add     EAX,reg 
    500527        // is faster than: 
    501528        //      mov     EAX,reg 
    502529        //      add     EAX,x 
    503530        else if (e2oper == OPvar && 
    504531                 e1->Eoper == OPvar && 
    505532                 e->Eoper != OPmin && 
    506533                 isregvar(e1,&regm,NULL) && 
    507534                 regm != retregs && 
    508535                 tysize[ty1] == tysize[ty2]) 
    509         {   elem *es; 
    510  
    511             es = e1; 
     536        { 
     537            elem *es = e1; 
    512538            e1 = e2; 
    513539            e2 = es; 
    514540        } 
    515541        cl = codelem(e1,&retregs,test);         /* eval left leaf       */ 
    516542        reg = findreg(retregs); 
    517543  } 
    518544  switch (e2oper) 
    519545  { 
    520546    case OPind:                                 /* if addressing mode   */ 
    521547        if (!e2->Ecount)                        /* if not CSE           */ 
    522548                goto L1;                        /* try OP reg,EA        */ 
    523549        /* FALL-THROUGH */ 
    524550    default:                                    /* operator node        */ 
    525551    L2: 
    526552        rretregs = ALLREGS & ~retregs; 
    527553        /* Be careful not to do arithmetic on ES        */ 
    528554        if (tysize[ty1] == REGSIZE && tysize[ty2] > REGSIZE && *pretregs != mPSW) 
    529555            rretregs = *pretregs & (mES | ALLREGS | mBP) & ~retregs; 
    530556        else if (byte) 
    531557            rretregs &= BYTEREGS; 
    532558 
    533559        cr = scodelem(e2,&rretregs,retregs,TRUE);       /* get rvalue   */ 
    534560        rreg = (tysize[ty2] > REGSIZE) ? findreglsw(rretregs) : findreg(rretregs); 
    535561        c = CNIL; 
    536562        if (numwords == 1)                              /* ADD reg,rreg */ 
    537563        { 
    538564                /* reverse operands to avoid moving around the segment value */ 
    539565                if (tysize[ty2] > REGSIZE) 
    540566                {       c = cat(c,getregs(rretregs)); 
    541567                        c = genregs(c,op1,rreg,reg); 
    542568                        retregs = rretregs;     /* reverse operands     */ 
    543569                } 
    544570                else 
    545571                {   c = genregs(c,op1,reg,rreg); 
    546                     if (I32 && *pretregs & mPSW) 
     572                    if (!I16 && *pretregs & mPSW) 
    547573                        c->Iflags |= word; 
    548574                } 
     575                if (I64 && sz == 8) 
     576                    code_orrex(c, REX_W); 
    549577        } 
    550578        else /* numwords == 2 */                /* ADD lsreg,lsrreg     */ 
    551579        { 
    552580            reg = findreglsw(retregs); 
    553581            rreg = findreglsw(rretregs); 
    554582            c = genregs(c,op1,reg,rreg); 
    555583            if (e->Eoper == OPadd || e->Eoper == OPmin) 
    556584                code_orflag(c,CFpsw); 
    557585            reg = findregmsw(retregs); 
    558586            rreg = findregmsw(rretregs); 
    559587            if (!(e2oper == OPu16_32 && // if second operand is 0 
    560588                  (op2 == 0x0B || op2 == 0x33)) // and OR or XOR 
    561589               ) 
    562590                genregs(c,op2,reg,rreg);        // ADC msreg,msrreg 
    563591        } 
    564592        break; 
    565593 
    566594    case OPrelconst: 
    567595        if (sz != REGSIZE) 
    568596                goto L2; 
    569597        if (segfl[el_fl(e2)] != 3)              /* if not in data segment */ 
    570598                goto L2; 
    571599        if (evalinregister(e2)) 
    572600                goto L2; 
    573601        cs.IEVoffset2 = e2->EV.sp.Voffset; 
    574602        cs.IEVsym2 = e2->EV.sp.Vsym; 
    575603        cs.Iflags |= CFoff; 
    576604        i = 0;                          /* no INC or DEC opcode         */ 
    577605        rval = 0; 
    578606        goto L3; 
    579607 
    580608    case OPconst: 
    581609        if (tyfv(ty2)) 
    582610            goto L2; 
    583611        if (numwords == 1) 
    584612        { 
    585                 i = e2->EV.Vint
     613                i = e2->EV.Vpointer
    586614                if (word) 
    587615                { 
    588616                    if (!(*pretregs & mPSW) && 
    589617                        config.flags4 & CFG4speed && 
    590618                        (e->Eoper == OPor || e->Eoper == OPxor || test || 
    591619                         (e1->Eoper != OPvar && e1->Eoper != OPind))) 
    592620                    {   word = 0; 
    593621                        i &= 0xFFFF; 
    594622                    } 
    595623                } 
    596624                rval = reghasvalue(byte ? BYTEREGS : ALLREGS,i,&rreg); 
    597625                cs.IEV2.Vint = i; 
    598626        L3: 
    599627                op1 ^= byte; 
    600628                cs.Iflags |= word; 
    601629                if (rval) 
    602630                {   cs.Iop = op1 ^ 2; 
    603631                    mode = rreg; 
    604632                } 
    605633                else 
    606634                    cs.Iop = 0x81; 
    607                 cs.Irm = modregrm(3,mode,reg); 
     635                cs.Irm = modregrm(3,mode&7,reg&7); 
     636                if (mode & 8) 
     637                    cs.Irex |= REX_R; 
     638                if (reg & 8) 
     639                    cs.Irex |= REX_B; 
    608640                cs.IFL2 = (e2->Eoper == OPconst) ? FLconst : el_fl(e2); 
    609641                /* Modify instruction for special cases */ 
    610642                switch (e->Eoper) 
    611643                {   case OPadd: 
    612644                    {   int iop; 
    613645 
    614646                        if (i == 1) 
    615647                            iop = 0;                    /* INC reg      */ 
    616648                        else if (i == -1) 
    617649                            iop = 8;                    /* DEC reg      */ 
    618650                        else 
    619651                            break; 
    620652                        cs.Iop = (0x40 | iop | reg) ^ byte; 
    621                         if (byte && *pretregs & mPSW
    622                         {   cs.Irm = modregrm(3,0,reg) | iop; 
     653                        if ((byte && *pretregs & mPSW) || I64
     654                        {   cs.Irm = modregrm(3,0,reg & 7) | iop; 
    623655                            cs.Iop = 0xFF; 
    624656                        } 
    625657                        break; 
    626658                    } 
    627659                    case OPand: 
    628660                        if (test) 
    629661                            cs.Iop = rval ? op1 : 0xF7; // TEST 
    630662                        break; 
    631663                } 
    632664                if (*pretregs & mPSW) 
    633665                        cs.Iflags |= CFpsw; 
    634666                cs.Iop ^= byte; 
    635667                c = gen(CNIL,&cs); 
    636668                cs.Iflags &= ~CFpsw; 
    637669        } 
    638670        else if (numwords == 2) 
    639671        {       unsigned lsreg; 
    640672                targ_int msw; 
    641673 
    642674                c = getregs(retregs); 
     
    657689                cs.Iflags &= ~CFpsw; 
    658690 
    659691                cs.Irm = (cs.Irm & modregrm(3,7,0)) | reg; 
    660692                cs.IEV2.Vint = msw; 
    661693                if (e->Eoper == OPadd) 
    662694                        cs.Irm |= modregrm(0,2,0);      /* ADC          */ 
    663695                c = gen(c,&cs); 
    664696        } 
    665697        else 
    666698                assert(0); 
    667699        freenode(e2); 
    668700        break; 
    669701 
    670702    case OPvar: 
    671703    L1: 
    672704        if (tyfv(ty2)) 
    673705                goto L2; 
    674706        c = loadea(e2,&cs,op1, 
    675707                ((numwords == 2) ? findreglsw(retregs) : reg), 
    676708                0,retregs,retregs); 
    677         if (I32 && word) 
     709        if (!I16 && word) 
    678710        {   if (*pretregs & mPSW) 
    679711                code_orflag(c,word); 
    680712            else 
    681             {   code *ce; 
    682  
    683                 ce = code_last(c); 
     713            { 
     714                code *ce = code_last(c); 
    684715                ce->Iflags &= ~word; 
    685716            } 
    686717        } 
    687718        else if (numwords == 2) 
    688719        { 
    689720            if (e->Eoper == OPadd || e->Eoper == OPmin) 
    690721                code_orflag(c,CFpsw); 
    691722            reg = findregmsw(retregs); 
    692723            if (EOP(e2)) 
    693724            {   getlvalue_msw(&cs); 
    694725                cs.Iop = op2; 
    695726                NEWREG(cs.Irm,reg); 
    696727                c = gen(c,&cs);                 /* ADC reg,data+2 */ 
    697728            } 
    698729            else 
    699730                c = cat(c,loadea(e2,&cs,op2,reg,REGSIZE,retregs,0)); 
    700731        } 
    701732        freenode(e2); 
    702733        break; 
    703734  } 
     
    733764    int opunslng; 
    734765    int pow2; 
    735766 
    736767    if (*pretregs == 0)                         // if don't want result 
    737768    {   c = codelem(e->E1,pretregs,FALSE);      // eval left leaf 
    738769        *pretregs = 0;                          // in case they got set 
    739770        return cat(c,codelem(e->E2,pretregs,FALSE)); 
    740771    } 
    741772 
    742773    keepregs = 0; 
    743774    cs.Iflags = 0; 
    744775    cs.Irex = 0; 
    745776    c = cg = cr = CNIL;                         // initialize 
    746777    e2 = e->E2; 
    747778    e1 = e->E1; 
    748779    tyml = tybasic(e1->Ety); 
    749780    sz = tysize[tyml]; 
    750781    byte = tybyte(e->Ety) != 0; 
    751782    uns = tyuns(tyml) || tyuns(e2->Ety); 
    752783    oper = e->Eoper; 
     784    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     785    unsigned grex = rex << 16; 
    753786 
    754787    if (tyfloating(tyml)) 
    755788#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    756789        return orth87(e,pretregs); 
    757790#else 
    758791        return opdouble(e,pretregs,(oper == OPmul) ? CLIBdmul : CLIBddiv); 
    759792#endif 
    760793 
    761     opunslng = I32 ? OPu32_64 : OPu16_32
     794    opunslng = I16 ? OPu16_32 : OPu32_64
    762795    switch (oper) 
    763796    { 
    764797        case OPmul: 
    765798            resreg = mAX; 
    766799            op = 5 - uns; 
    767800            lib = CLIBlmul; 
    768801            break; 
    769802 
    770803        case OPdiv: 
    771804            resreg = mAX; 
    772805            op = 7 - uns; 
    773806            lib = uns ? CLIBuldiv : CLIBldiv; 
    774807            if (I32) 
    775808                keepregs |= mSI | mDI; 
    776809            break; 
    777810 
    778811        case OPmod: 
    779812            resreg = mDX; 
    780813            op = 7 - uns; 
    781814            lib = uns ? CLIBulmod : CLIBlmod; 
     
    815848    case OPulngllng: 
    816849    case OPlngllng: 
    817850        if (sz != 2 * REGSIZE || oper != OPmul || e1->Eoper != e2->Eoper || 
    818851            e1->Ecount || e2->Ecount) 
    819852            goto L2; 
    820853        op = (e2->Eoper == opunslng) ? 4 : 5; 
    821854        retregs = mAX; 
    822855        cl = codelem(e1->E1,&retregs,FALSE);    /* eval left leaf       */ 
    823856        if (e2->E1->Eoper == OPvar || 
    824857            (e2->E1->Eoper == OPind && !e2->E1->Ecount) 
    825858           ) 
    826859        { 
    827860            cr = loadea(e2->E1,&cs,0xF7,op,0,mAX,mAX | mDX); 
    828861        } 
    829862        else 
    830863        { 
    831864            rretregs = ALLREGS & ~mAX; 
    832865            cr = scodelem(e2->E1,&rretregs,retregs,TRUE); // get rvalue 
    833866            cg = getregs(mAX | mDX); 
    834867            rreg = findreg(rretregs); 
    835             cg = gen2(cg,0xF7,modregrm(3,op,rreg)); // OP AX,rreg 
     868            cg = gen2(cg,0xF7,grex | modregrmx(3,op,rreg)); // OP AX,rreg 
    836869        } 
    837870        freenode(e->E1); 
    838871        freenode(e2); 
    839872        c = fixresult(e,mAX | mDX,pretregs); 
    840873        break; 
    841874 
    842875    case OPconst: 
    843876        e2factor = el_tolong(e2); 
    844877 
    845878        if (oper == OPmul && I32 && sz == REGSIZE * 2) 
    846879        {   targ_int msw,lsw; 
    847880            regm_t scratch; 
    848881            unsigned reg; 
    849882            targ_llong e2factor; 
    850883 
    851884            cl = codelem(e1,&retregs,FALSE);    // eval left leaf 
    852885            /*  IMUL    EDX,EDX,lsw 
    853886                IMUL    reg,EAX,msw 
    854887                ADD     reg,EDX 
    855888                MOV     EDX,lsw 
     
    871904            msw = e2factor >> (REGSIZE * 8); 
    872905 
    873906            if (msw) 
    874907            {   cg = genmulimm(cg,DX,DX,lsw); 
    875908                cg = genmulimm(cg,reg,AX,msw); 
    876909                cg = gen2(cg,0x03,modregrm(3,reg,DX)); 
    877910            } 
    878911            else 
    879912                cg = genmulimm(cg,reg,DX,lsw); 
    880913 
    881914            cg = movregconst(cg,DX,lsw,0);              // MOV EDX,lsw 
    882915            cg = cat(cg,getregs(mDX)); 
    883916            cg = gen2(cg,0xF7,modregrm(3,4,DX));        // MUL EDX 
    884917            gen2(cg,0x03,modregrm(3,DX,reg));           // ADD EDX,reg 
    885918 
    886919            resreg = mDX | mAX; 
    887920            freenode(e2); 
    888921            goto L3; 
    889922        } 
    890923 
    891         if (oper != OPmul && e2factor == 10 && sz == REGSIZE && 
     924        if (oper != OPmul && e2factor == 10 && 
     925            (!I16 && sz == 4) && 
    892926            config.flags4 & CFG4speed && !uns) 
    893927        { 
    894928            /* R1 / 10 
    895929             * 
    896930             *  MOV     EAX,0x66666667 
    897931             *  IMUL    R1 
    898932             *  MOV     EAX,R1 
    899933             *  SAR     EAX,31 
    900934             *  SAR     EDX,2 
    901935             *  SUB     EDX,EAX 
    902936             *  IMUL    EAX,EDX,10 
    903937             *  SUB     R1,EAX 
    904938             * 
    905939             * EDX = quotient 
    906940             * R1 = remainder 
    907941             */ 
    908942            regm_t regm; 
    909943            unsigned reg; 
    910944 
    911945            regm = allregs & ~(mAX | mDX); 
    912946            cl = codelem(e1,&regm,FALSE);       // eval left leaf 
    913947            reg = findreg(regm); 
    914948            cg = getregs(regm | mDX | mAX); 
    915949 
    916950            cg = movregconst(cg, AX, 0x66666667, 0);    // MOV EAX,0x66666667 
    917             cg = gen2(cg,0xF7,modregrm(3,5,reg));       // IMUL R1 
     951            cg = gen2(cg,0xF7,modregrmx(3,5,reg));      // IMUL R1 
    918952            genmovreg(cg, AX, reg);                     // MOV EAX,R1 
    919953            genc2(cg,0xC1,modregrm(3,7,AX),31);         // SAR EAX,31 
    920954            genc2(cg,0xC1,modregrm(3,7,DX),2);          // SAR EDX,2 
    921955            gen2(cg,0x2B,modregrm(3,DX,AX));            // SUB EDX,EAX 
    922956 
    923957            switch (oper) 
    924958            {   case OPdiv: 
    925959                    resreg = mDX; 
    926960                    break; 
    927961 
    928962                case OPmod: 
    929963                    genmulimm(cg,AX,DX,10);             // IMUL EAX,EDX,10 
    930                     gen2(cg,0x2B,modregrm(3,reg,AX));   // SUB R1,EAX 
     964                    gen2(cg,0x2B,modregxrm(3,reg,AX));  // SUB R1,EAX 
    931965                    resreg = regm; 
    932966                    break; 
    933967 
    934968                case OPremquo: 
    935969                    genmulimm(cg,AX,DX,10);             // IMUL EAX,EDX,10 
    936                     gen2(cg,0x2B,modregrm(3,reg,AX));   // SUB R1,EAX 
     970                    gen2(cg,0x2B,modregxrm(3,reg,AX));  // SUB R1,EAX 
    937971                    genmovreg(cg, AX, DX);              // MOV EAX,EDX 
    938972                    genmovreg(cg, DX, reg);             // MOV EDX,R1 
    939973                    resreg = mDX | mAX; 
    940974                    break; 
    941975 
    942976                default: 
    943977                    assert(0); 
    944978            } 
    945979            freenode(e2); 
    946980            goto L3; 
    947981        } 
    948982 
    949983        if (sz > REGSIZE) 
    950984            goto L2; 
    951985 
    952986        if (oper == OPmul && config.target_cpu >= TARGET_80286) 
    953987        {   unsigned reg; 
    954988            int ss; 
    955989 
    956990            freenode(e2); 
    957991            retregs = byte ? BYTEREGS : ALLREGS; 
    958992            resreg = *pretregs & (ALLREGS | mBP); 
    959993            if (!resreg) 
    960994                resreg = retregs; 
    961995 
    962             if (I32
     996            if (!I16
    963997            {   // See if we can use an LEA instruction 
    964998                int ss2 = 0; 
    965999                int shift; 
    9661000 
    9671001                switch (e2factor) 
    9681002                { 
    9691003                    case 12:    ss = 1; ss2 = 2; goto L4; 
    9701004                    case 24:    ss = 1; ss2 = 3; goto L4; 
    9711005 
    9721006                    case 6: 
    9731007                    case 3:     ss = 1; goto L4; 
    9741008 
    9751009                    case 20:    ss = 2; ss2 = 2; goto L4; 
    9761010                    case 40:    ss = 2; ss2 = 3; goto L4; 
    9771011 
    9781012                    case 10: 
    9791013                    case 5:     ss = 2; goto L4; 
    9801014 
    9811015                    case 36:    ss = 3; ss2 = 2; goto L4; 
    9821016                    case 72:    ss = 3; ss2 = 3; goto L4; 
    9831017 
    9841018                    case 18: 
    9851019                    case 9:     ss = 3; goto L4; 
    9861020 
    9871021                    L4: 
    9881022                    { 
    9891023#if 1 
    990                         regm_t regm; 
    991                         int r; 
    992  
    993                         regm = byte ? BYTEREGS : ALLREGS;               // don't use EBP 
     1024                        regm_t regm = byte ? BYTEREGS : ALLREGS;        // don't use EBP 
    9941025                        cl = codelem(e->E1,&regm,TRUE); 
    995                         r = findreg(regm); 
     1026                        unsigned r = findreg(regm); 
    9961027 
    9971028                        if (ss2) 
    9981029                        {   // Don't use EBP 
    9991030                            resreg &= ~mBP; 
    10001031                            if (!resreg) 
    10011032                                resreg = retregs; 
    10021033                        } 
    10031034                        cg = allocreg(&resreg,&reg,tyml); 
    10041035 
    1005                         c = gen2sib(CNIL,0x8D,modregrm(0,reg,4), 
    1006                                               modregrm(ss,r,r)); 
     1036                        c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 
     1037                                              modregxrmx(ss,r,r)); 
    10071038                        if (ss2) 
    10081039                        { 
    1009                             gen2sib(c,0x8D,modregrm(0,reg,4), 
    1010                                            modregrm(ss2,reg,5)); 
     1040                            gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 
     1041                                           modregxrm(ss2,reg,5)); 
    10111042                            code_last(c)->IFL1 = FLconst; 
    10121043                            code_last(c)->IEV1.Vint = 0; 
    10131044                        } 
    10141045                        else if (!(e2factor & 1))    // if even factor 
    1015                             genregs(c,0x03,reg,reg); // ADD reg,reg 
     1046                        {   genregs(c,0x03,reg,reg); // ADD reg,reg 
     1047                            code_orrex(c,rex); 
     1048                        } 
    10161049                        cg = cat(cg,c); 
    10171050                        goto L3; 
    10181051#else 
    10191052 
    10201053                                // Don't use EBP 
    10211054                                resreg &= ~mBP; 
    10221055                                if (!resreg) 
    10231056                                    resreg = retregs; 
    10241057 
    10251058                                cl = codelem(e->E1,&resreg,FALSE); 
    10261059                                reg = findreg(resreg); 
    10271060                                cg = getregs(resreg); 
    10281061                                c = gen2sib(CNIL,0x8D,modregrm(0,reg,4), 
    10291062                                                      modregrm(ss,reg,reg)); 
    10301063                                if (ss2) 
    10311064                                { 
    10321065                                    gen2sib(c,0x8D,modregrm(0,reg,4), 
    10331066                                                   modregrm(ss2,reg,5)); 
    10341067                                    code_last(c)->IFL1 = FLconst; 
    10351068                                    code_last(c)->IEV1.Vint = 0; 
    10361069                                } 
    10371070                                else if (!(e2factor & 1))    // if even factor 
    10381071                                    genregs(c,0x03,reg,reg); // ADD reg,reg 
    10391072                                cg = cat(cg,c); 
    10401073                                goto L3; 
    10411074#endif 
    10421075                    } 
    10431076                    case 37: 
    10441077                    case 74:    shift = 2; 
    10451078                                goto L5; 
    10461079                    case 13: 
    10471080                    case 26:    shift = 0; 
    10481081                                goto L5; 
    10491082                    L5: 
    1050                     {           regm_t sregm; 
    1051                                 unsigned sreg; 
    1052  
     1083                    { 
    10531084                                // Don't use EBP 
    10541085                                resreg &= ~mBP; 
    10551086                                if (!resreg) 
    10561087                                    resreg = retregs; 
    10571088                                cl = allocreg(&resreg,&reg,TYint); 
    10581089 
    1059                                 sregm = ALLREGS & ~resreg; 
     1090                                regm_t sregm = ALLREGS & ~resreg; 
    10601091                                cl = cat(cl,codelem(e->E1,&sregm,FALSE)); 
    1061                                 sreg = findreg(sregm); 
     1092                                unsigned sreg = findreg(sregm); 
    10621093                                cg = getregs(resreg | sregm); 
    10631094                                // LEA reg,[sreg * 4][sreg] 
    10641095                                // SHL sreg,shift 
    10651096                                // LEA reg,[sreg * 8][reg] 
    1066                                 c = gen2sib(CNIL,0x8D,modregrm(0,reg,4), 
    1067                                                       modregrm(2,sreg,sreg)); 
     1097                                c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 
     1098                                                      modregxrmx(2,sreg,sreg)); 
    10681099                                if (shift) 
    1069                                     genc2(c,0xC1,modregrm(3,4,sreg),shift); 
    1070                                 gen2sib(c,0x8D,modregrm(0,reg,4), 
    1071                                                       modregrm(3,sreg,reg)); 
     1100                                    genc2(c,0xC1,grex | modregrmx(3,4,sreg),shift); 
     1101                                gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 
     1102                                                      modregxrmx(3,sreg,reg)); 
    10721103                                if (!(e2factor & 1))         // if even factor 
    1073                                     genregs(c,0x03,reg,reg); // ADD reg,reg 
     1104                                {   genregs(c,0x03,reg,reg); // ADD reg,reg 
     1105                                    code_orrex(c,rex); 
     1106                                } 
    10741107                                cg = cat(cg,c); 
    10751108                                goto L3; 
    10761109                    } 
    10771110                } 
    10781111            } 
    10791112 
    10801113            cl = scodelem(e->E1,&retregs,0,TRUE);       // eval left leaf 
    10811114            reg = findreg(retregs); 
    10821115            cg = allocreg(&resreg,&rreg,e->Ety); 
    10831116 
    10841117            /* IMUL reg,imm16   */ 
    1085             cg = genc2(cg,0x69,modregrm(3,rreg,reg),e2factor); 
     1118            cg = genc2(cg,0x69,grex | modregxrmx(3,rreg,reg),e2factor); 
    10861119            goto L3; 
    10871120        } 
    10881121 
    10891122        // Special code for signed divide or modulo by power of 2 
    1090         if (sz == REGSIZE && (oper == OPdiv || oper == OPmod) && !uns && 
     1123        if ((sz == REGSIZE || (I64 && sz == 4)) && 
     1124            (oper == OPdiv || oper == OPmod) && !uns && 
    10911125            (pow2 = ispow2(e2factor)) != -1 && 
    10921126            !(config.target_cpu < TARGET_80286 && pow2 != 1 && oper == OPdiv) 
    10931127           ) 
    10941128        { 
    10951129            if (pow2 == 1 && oper == OPdiv && config.target_cpu > TARGET_80386) 
    10961130            { 
    10971131                //     test    eax,eax 
    10981132                //     jns     L1 
    10991133                //     add     eax,1 
    11001134                // L1: sar     eax,1 
    11011135 
    11021136                code *cnop; 
    1103                 unsigned reg; 
    11041137 
    11051138                retregs = allregs; 
    11061139                cl = codelem(e->E1,&retregs,FALSE);     // eval left leaf 
    1107                 reg = findreg(retregs); 
     1140                unsigned reg = findreg(retregs); 
    11081141                freenode(e2); 
    11091142                cg = getregs(retregs); 
    11101143                cg = gentstreg(cg,reg);                 // TEST reg,reg 
     1144                code_orrex(cg, rex); 
    11111145                cnop = gennop(CNIL); 
    11121146                genjmp(cg,JNS,FLcode,(block *)cnop);    // JNS cnop 
    1113                 gen1(cg,0x40 + reg);                    // INC reg 
     1147                if (I64) 
     1148                { 
     1149                    gen2(cg,0xFF,modregrmx(3,0,reg));       // INC reg 
     1150                    code_orrex(cg,rex); 
     1151                } 
     1152                else 
     1153                    gen1(cg,0x40 + reg);                    // INC reg 
    11141154                cg = cat(cg,cnop); 
    1115                 gen2(cg,0xD1,modregrm(3,7,reg));        // SAR reg,1 
     1155                gen2(cg,0xD1,grex | modregrmx(3,7,reg));        // SAR reg,1 
    11161156                resreg = retregs; 
    11171157                goto L3; 
    11181158            } 
    11191159            cl = codelem(e->E1,&retregs,FALSE); // eval left leaf 
    11201160            freenode(e2); 
    11211161            cg = getregs(mAX | mDX);            // trash these regs 
    11221162            cg = gen1(cg,0x99);                         // CWD 
     1163            code_orrex(cg, rex); 
    11231164            if (pow2 == 1) 
    11241165            { 
    11251166                if (oper == OPdiv) 
    1126                 {   gen2(cg,0x2B,modregrm(3,AX,DX));    // SUB AX,DX 
    1127                     gen2(cg,0xD1,modregrm(3,7,AX));     // SAR AX,1 
     1167                {   gen2(cg,0x2B,grex | modregrm(3,AX,DX));    // SUB AX,DX 
     1168                    gen2(cg,0xD1,grex | modregrm(3,7,AX));     // SAR AX,1 
    11281169                } 
    11291170                else // OPmod 
    1130                 {   gen2(cg,0x33,modregrm(3,AX,DX));    // XOR AX,DX 
    1131                     genc2(cg,0x81,modregrm(3,4,AX),1);  // AND AX,1 
    1132                     gen2(cg,0x03,modregrm(3,DX,AX));    // ADD DX,AX 
     1171                {   gen2(cg,0x33,grex | modregrm(3,AX,DX));    // XOR AX,DX 
     1172                    genc2(cg,0x81,grex | modregrm(3,4,AX),1);  // AND AX,1 
     1173                    gen2(cg,0x03,grex | modregrm(3,DX,AX));    // ADD DX,AX 
    11331174                } 
    11341175            } 
    11351176            else 
    11361177            {   targ_ulong m; 
    11371178 
    11381179                m = (1 << pow2) - 1; 
    11391180                if (oper == OPdiv) 
    1140                 {   genc2(cg,0x81,modregrm(3,4,DX),m);  // AND DX,m 
    1141                     gen2(cg,0x03,modregrm(3,AX,DX));    // ADD AX,DX 
     1181                {   genc2(cg,0x81,grex | modregrm(3,4,DX),m);  // AND DX,m 
     1182                    gen2(cg,0x03,grex | modregrm(3,AX,DX));    // ADD AX,DX 
    11421183                    // Be careful not to generate this for 8088 
    11431184                    assert(config.target_cpu >= TARGET_80286); 
    1144                     genc2(cg,0xC1,modregrm(3,7,AX),pow2); // SAR AX,pow2 
     1185                    genc2(cg,0xC1,grex | modregrm(3,7,AX),pow2); // SAR AX,pow2 
    11451186                } 
    11461187                else // OPmod 
    1147                 {   gen2(cg,0x33,modregrm(3,AX,DX));    // XOR AX,DX 
    1148                     gen2(cg,0x2B,modregrm(3,AX,DX));    // SUB AX,DX 
    1149                     genc2(cg,0x81,modregrm(3,4,AX),m);  // AND AX,mask 
    1150                     gen2(cg,0x33,modregrm(3,AX,DX));    // XOR AX,DX 
    1151                     gen2(cg,0x2B,modregrm(3,AX,DX));    // SUB AX,DX 
     1188                {   gen2(cg,0x33,grex | modregrm(3,AX,DX));    // XOR AX,DX 
     1189                    gen2(cg,0x2B,grex | modregrm(3,AX,DX));    // SUB AX,DX 
     1190                    genc2(cg,0x81,grex | modregrm(3,4,AX),m);  // AND AX,mask 
     1191                    gen2(cg,0x33,grex | modregrm(3,AX,DX));    // XOR AX,DX 
     1192                    gen2(cg,0x2B,grex | modregrm(3,AX,DX));    // SUB AX,DX 
    11521193                    resreg = mAX; 
    11531194                } 
    11541195            } 
    11551196            goto L3; 
    11561197        } 
    11571198        goto L2; 
    11581199    case OPind: 
    11591200        if (!e2->Ecount)                        /* if not CSE           */ 
    11601201                goto L1;                        /* try OP reg,EA        */ 
    11611202        goto L2; 
    11621203    default:                                    /* OPconst and operators */ 
    11631204    L2: 
    11641205        cl = codelem(e1,&retregs,FALSE);        /* eval left leaf       */ 
    11651206        cr = scodelem(e2,&rretregs,retregs,TRUE);       /* get rvalue   */ 
    11661207        if (sz <= REGSIZE) 
    11671208        {   cg = getregs(mAX | mDX);            /* trash these regs     */ 
    11681209            if (op == 7)                        /* signed divide        */ 
    1169                 cg = gen1(cg,0x99);             /* CWD                  */ 
     1210            {   cg = gen1(cg,0x99);             // CWD 
     1211                code_orrex(cg,rex); 
     1212            } 
    11701213            else if (op == 6)                   /* unsigned divide      */ 
    1171             {   cg = movregconst(cg,DX,0,0);    // MOV DX,0 
     1214            { 
     1215                cg = movregconst(cg,DX,0,(sz == 8) ? 64 : 0);    // MOV DX,0 
    11721216                cg = cat(cg,getregs(mDX)); 
    11731217            } 
    11741218            rreg = findreg(rretregs); 
    1175             cg = gen2(cg,0xF7 ^ byte,modregrm(3,op,rreg)); /* OP AX,rreg */ 
     1219            cg = gen2(cg,0xF7 ^ byte,grex | modregrmx(3,op,rreg)); // OP AX,rreg 
    11761220        L3: 
    11771221            c = fixresult(e,resreg,pretregs); 
    11781222        } 
    11791223        else if (sz == 2 * REGSIZE) 
    11801224        { 
    11811225            if (config.target_cpu >= TARGET_PentiumPro && oper == OPmul) 
    11821226            { 
    11831227                /*  IMUL    ECX,EAX 
    11841228                    IMUL    EDX,EBX 
    11851229                    ADD     ECX,EDX 
    11861230                    MUL     EBX 
    11871231                    ADD     EDX,ECX 
    11881232                 */ 
    11891233                 cg = getregs(mAX|mDX|mCX); 
    11901234                 cg = gen2(cg,0x0FAF,modregrm(3,CX,AX)); 
    11911235                 gen2(cg,0x0FAF,modregrm(3,DX,BX)); 
    11921236                 gen2(cg,0x03,modregrm(3,CX,DX)); 
    11931237                 gen2(cg,0xF7,modregrm(3,4,BX)); 
    11941238                 gen2(cg,0x03,modregrm(3,DX,CX)); 
    11951239                 c = fixresult(e,mDX|mAX,pretregs); 
    11961240            } 
    11971241            else 
    11981242                c = callclib(e,lib,pretregs,keepregs); 
    11991243        } 
    12001244        else 
    12011245                assert(0); 
    12021246        break; 
    12031247    case OPvar: 
    12041248    L1: 
    1205         if (I32 && sz <= REGSIZE) 
     1249        if (!I16 && sz <= REGSIZE) 
    12061250        { 
    12071251            if (oper == OPmul && sz > 1)        /* no byte version      */ 
    12081252            { 
    12091253                /* Generate IMUL r32,r/m32      */ 
    12101254                retregs = *pretregs & (ALLREGS | mBP); 
    12111255                if (!retregs) 
    12121256                    retregs = ALLREGS; 
    12131257                cl = codelem(e1,&retregs,FALSE);        /* eval left leaf */ 
    12141258                resreg = retregs; 
    12151259                cr = loadea(e2,&cs,0x0FAF,findreg(resreg),0,retregs,retregs); 
    12161260                freenode(e2); 
    12171261                goto L3; 
    12181262            } 
    12191263        } 
    12201264        else 
    12211265        { 
    12221266            if (sz == 2 * REGSIZE) 
    12231267            {   int reg; 
    12241268 
    12251269                if (oper != OPmul || e->E1->Eoper != opunslng || 
     
    12781322code *cdnot(elem *e,regm_t *pretregs) 
    12791323{   unsigned reg; 
    12801324    tym_t forflags; 
    12811325    code *c1,*c,*cfalse,*ctrue,*cnop; 
    12821326    unsigned sz; 
    12831327    regm_t retregs; 
    12841328    elem *e1; 
    12851329    int op; 
    12861330 
    12871331    e1 = e->E1; 
    12881332    if (*pretregs == 0) 
    12891333        goto L1; 
    12901334    if (*pretregs == mPSW) 
    12911335    {   /*assert(e->Eoper != OPnot && e->Eoper != OPbool);*/ /* should've been optimized */ 
    12921336    L1: 
    12931337        return codelem(e1,pretregs,FALSE);      /* evaluate e1 for cc   */ 
    12941338    } 
    12951339 
    12961340    op = e->Eoper; 
    12971341    sz = tysize(e1->Ety); 
     1342    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1343    unsigned grex = rex << 16; 
    12981344    if (!tyfloating(e1->Ety)) 
    12991345    { 
    13001346    if (sz <= REGSIZE && e1->Eoper == OPvar) 
    13011347    {   code cs; 
    13021348 
    13031349        c = getlvalue(&cs,e1,0); 
    13041350        freenode(e1); 
    1305         if (I32 && sz == 2) 
     1351        if (!I16 && sz == 2) 
    13061352            cs.Iflags |= CFopsize; 
    13071353 
    13081354        retregs = *pretregs & (ALLREGS | mBP); 
    13091355        if (config.target_cpu >= TARGET_80486 && 
    13101356            tysize(e->Ety) == 1) 
    13111357        { 
    13121358            if (reghasvalue((sz == 1) ? BYTEREGS : ALLREGS,0,&reg)) 
    13131359                cs.Iop = 0x39; 
    13141360            else 
    13151361            {   cs.Iop = 0x81; 
    13161362                reg = 7; 
    13171363                cs.IFL2 = FLconst; 
    13181364                cs.IEV2.Vint = 0; 
    13191365            } 
    13201366            cs.Iop ^= (sz == 1); 
    1321             cs.Irm |= modregrm(0,reg,0); 
     1367            code_newreg(&cs,reg); 
    13221368            c = gen(c,&cs);                             // CMP e1,0 
    13231369 
    13241370            retregs &= BYTEREGS; 
    13251371            if (!retregs) 
    13261372                retregs = BYTEREGS; 
    13271373            c1 = allocreg(&retregs,&reg,TYint); 
    13281374 
    13291375            int iop; 
    13301376            if (op == OPbool) 
    13311377            { 
    13321378                iop = 0x0F95;   // SETNZ rm8 
    13331379            } 
    13341380            else 
    13351381            { 
    13361382                iop = 0x0F94;   // SETZ rm8 
    13371383            } 
    1338             c1 = gen2(c1,iop,modregrm(3,0,reg)); 
     1384            c1 = gen2(c1,iop,grex | modregrmx(3,0,reg)); 
    13391385            if (op == OPbool) 
    13401386                *pretregs &= ~mPSW; 
    13411387            goto L4; 
    13421388        } 
    13431389 
    13441390        if (reghasvalue((sz == 1) ? BYTEREGS : ALLREGS,1,&reg)) 
    13451391            cs.Iop = 0x39; 
    13461392        else 
    13471393        {   cs.Iop = 0x81; 
    13481394            reg = 7; 
    13491395            cs.IFL2 = FLconst; 
    13501396            cs.IEV2.Vint = 1; 
    13511397        } 
    13521398        cs.Iop ^= (sz == 1); 
    1353         cs.Irm |= modregrm(0,reg,0); 
     1399        code_newreg(&cs,reg); 
    13541400        c = gen(c,&cs);                         // CMP e1,1 
    13551401 
    13561402        c1 = allocreg(&retregs,&reg,TYint); 
    13571403        op ^= (OPbool ^ OPnot);                 // switch operators 
    13581404        goto L2; 
    13591405    } 
    13601406    else if (sz <= REGSIZE && 
    13611407        // NEG bytereg is too expensive 
    13621408        (sz != 1 || config.target_cpu < TARGET_PentiumPro)) 
    13631409    { 
    13641410        retregs = *pretregs & (ALLREGS | mBP); 
    13651411        if (sz == 1 && !(retregs &= BYTEREGS)) 
    13661412            retregs = BYTEREGS; 
    13671413        c = codelem(e->E1,&retregs,FALSE); 
    13681414        reg = findreg(retregs); 
    13691415        c1 = getregs(retregs); 
    1370         c1 = gen2(c1,0xF7 ^ (sz == 1),modregrm(3,3,reg));       // NEG reg 
     1416        c1 = gen2(c1,0xF7 ^ (sz == 1),grex | modregrmx(3,3,reg));   // NEG reg 
    13711417        code_orflag(c1,CFpsw); 
    13721418        if (I32 && sz == SHORTSIZE) 
    13731419            code_orflag(c1,CFopsize); 
    13741420    L2: 
    13751421        c1 = genregs(c1,0x19,reg,reg);                  // SBB reg,reg 
     1422        code_orrex(c1, rex); 
    13761423        // At this point, reg==0 if e1==0, reg==-1 if e1!=0 
    13771424        if (op == OPnot) 
    1378             gen1(c1,0x40 + reg);                        // INC reg 
     1425        { 
     1426            if (I64) 
     1427                gen2(c1,0xFF,grex | modregrmx(3,0,reg));    // INC reg 
     1428            else 
     1429                gen1(c1,0x40 + reg);                        // INC reg 
     1430        } 
    13791431        else 
    1380             gen2(c1,0xF7,modregrm(3,3,reg));            // NEG reg 
     1432            gen2(c1,0xF7,grex | modregrmx(3,3,reg));    // NEG reg 
    13811433        if (*pretregs & mPSW) 
    13821434        {   code_orflag(c1,CFpsw); 
    13831435            *pretregs &= ~mPSW;         // flags are always set anyway 
    13841436        } 
    13851437    L4: 
    13861438        return cat3(c,c1,fixresult(e,retregs,pretregs)); 
    13871439    } 
    13881440  } 
    13891441  cnop = gennop(CNIL); 
    13901442  ctrue = gennop(CNIL); 
    13911443  c = logexp(e->E1,(op == OPnot) ? FALSE : TRUE,FLcode,ctrue); 
    13921444  forflags = *pretregs & mPSW; 
     1445  if (I64 && sz == 8) 
     1446        forflags |= 64; 
    13931447  assert(tysize(e->Ety) <= REGSIZE);            // result better be int 
    13941448  cfalse = allocreg(pretregs,&reg,e->Ety);      // allocate reg for result 
    13951449  for (c1 = cfalse; c1; c1 = code_next(c1)) 
    13961450        gen(ctrue,c1);                          // duplicate reg save code 
    13971451  cfalse = movregconst(cfalse,reg,0,forflags);  // mov 0 into reg 
    13981452  regcon.immed.mval &= ~mask[reg];              // mark reg as unavail 
    13991453  ctrue = movregconst(ctrue,reg,1,forflags);    // mov 1 into reg 
    14001454  regcon.immed.mval &= ~mask[reg];              // mark reg as unavail 
    14011455  genjmp(cfalse,JMP,FLcode,(block *) cnop);     // skip over ctrue 
    14021456  c = cat4(c,cfalse,ctrue,cnop); 
    14031457  return c; 
    14041458} 
    14051459 
    14061460 
    14071461/************************ 
    14081462 * Complement operator 
    14091463 */ 
    14101464 
    14111465code *cdcom(elem *e,regm_t *pretregs) 
    14121466{ unsigned reg,op; 
    14131467  regm_t retregs,possregs; 
    14141468  code *c,*c1,*cg; 
    14151469  tym_t tym; 
    14161470  int sz; 
    14171471 
    14181472  if (*pretregs == 0) 
    14191473        return codelem(e->E1,pretregs,FALSE); 
    14201474  tym = tybasic(e->Ety); 
    14211475  sz = tysize[tym]; 
     1476  unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1477  unsigned grex = rex << 16; 
    14221478  possregs = (sz == 1) ? BYTEREGS : allregs; 
    14231479  retregs = *pretregs & possregs; 
    14241480  if (retregs == 0) 
    14251481        retregs = possregs; 
    14261482  c1 = codelem(e->E1,&retregs,FALSE); 
    14271483  cg = getregs(retregs);                /* retregs will be destroyed    */ 
    14281484#if 0 
    14291485  if (sz == 4 * REGSIZE) 
    14301486  { 
    14311487        c = gen2(CNIL,0xF7,modregrm(3,2,AX));   // NOT AX 
    14321488        gen2(c,0xF7,modregrm(3,2,BX));          // NOT BX 
    14331489        gen2(c,0xF7,modregrm(3,2,CX));          // NOT CX 
    14341490        gen2(c,0xF7,modregrm(3,2,DX));          // NOT DX 
    14351491  } 
    14361492  else 
    14371493#endif 
    14381494  { 
    14391495        reg = (sz <= REGSIZE) ? findreg(retregs) : findregmsw(retregs); 
    14401496        op = (sz == 1) ? 0xF6 : 0xF7; 
    14411497        c = genregs(CNIL,op,2,reg);             // NOT reg 
     1498        code_orrex(c, rex); 
    14421499        if (sz == 2 * REGSIZE) 
    14431500        {   reg = findreglsw(retregs); 
    14441501            genregs(c,op,2,reg);                // NOT reg+1 
    14451502        } 
    14461503  } 
    14471504  return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 
    14481505} 
    14491506 
    14501507/************************ 
    14511508 * Bswap operator 
    14521509 */ 
    14531510 
    14541511code *cdbswap(elem *e,regm_t *pretregs) 
    14551512{   unsigned reg,op; 
    14561513    regm_t retregs; 
    14571514    code *c,*c1,*cg; 
    14581515    tym_t tym; 
    14591516    int sz; 
    14601517 
    14611518    if (*pretregs == 0) 
    14621519        return codelem(e->E1,pretregs,FALSE); 
    14631520 
    14641521    tym = tybasic(e->Ety); 
    14651522    assert(tysize[tym] == 4); 
    14661523    retregs = *pretregs & allregs; 
    14671524    if (retregs == 0) 
    14681525        retregs = allregs; 
    14691526    c1 = codelem(e->E1,&retregs,FALSE); 
    14701527    cg = getregs(retregs);              // retregs will be destroyed 
    14711528    reg = findreg(retregs); 
    1472     c = gen2(CNIL,0x0FC8 + reg,0);      // BSWAP reg 
     1529    c = gen2(CNIL,0x0FC8 + (reg & 7),0);      // BSWAP reg 
     1530    if (reg & 8) 
     1531        code_orrex(c, REX_B); 
    14731532    return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 
    14741533} 
    14751534 
    14761535/************************* 
    14771536 * ?: operator 
    14781537 */ 
    14791538 
    14801539code *cdcond(elem *e,regm_t *pretregs) 
    14811540{ regm_t psw; 
    14821541  code *cc,*c,*c1,*cnop1,*c2,*cnop2; 
    14831542  con_t regconold,regconsave; 
    14841543  unsigned stackpushold,stackpushsave; 
    14851544  int ehindexold,ehindexsave; 
    14861545  unsigned jop; 
    14871546  unsigned op1; 
    14881547  unsigned sz1; 
    14891548  unsigned sz2; 
    14901549  elem *e1; 
    14911550  elem *e2; 
    14921551  elem *e21; 
    14931552  elem *e22; 
    14941553 
    14951554  /* vars to save state of 8087 */ 
    14961555  int stackusedold,stackusedsave; 
    14971556  NDP _8087old[arraysize(_8087elems)]; 
    14981557  NDP _8087save[arraysize(_8087elems)]; 
    14991558 
    15001559  _chkstack(); 
    15011560 
    15021561  //dbg_printf("cdcond(e = %p, *pretregs = x%x)\n",e,*pretregs); 
    15031562  e1 = e->E1; 
    15041563  e2 = e->E2; 
    15051564  e21 = e2->E1; 
    15061565  e22 = e2->E2; 
    15071566  cc = docommas(&e1); 
    15081567  cgstate.stackclean++; 
    15091568  psw = *pretregs & mPSW;               /* save PSW bit                 */ 
    15101569  op1 = e1->Eoper; 
    15111570  sz1 = tysize(e1->Ety); 
     1571  unsigned rex = (I64 && sz1 == 8) ? REX_W : 0; 
     1572  unsigned grex = rex << 16; 
    15121573  jop = jmpopcode(e1); 
    15131574 
    15141575  if (!OTrel(op1) && e1 == e21 && 
    15151576      sz1 <= REGSIZE && !tyfloating(e1->Ety)) 
    15161577  {     // Recognize (e ? e : f) 
    15171578        regm_t retregs; 
    15181579 
    15191580        cnop1 = gennop(CNIL); 
    15201581        retregs = *pretregs | mPSW; 
    15211582        c = codelem(e1,&retregs,FALSE); 
    15221583 
    15231584        c = cat(c,cse_flush(1));                // flush CSEs to memory 
    15241585        c = genjmp(c,jop,FLcode,(block *)cnop1); 
    15251586        freenode(e21); 
    15261587 
    15271588        regconsave = regcon; 
    15281589        stackpushsave = stackpush; 
    15291590 
    15301591        retregs |= psw; 
    15311592        if (retregs & (mBP | ALLREGS)) 
     
    15611622        reg = findreg(retregs); 
    15621623        v1 = e21->EV.Vlong; 
    15631624        v2 = e22->EV.Vlong; 
    15641625        if (jop == JNC) 
    15651626        {   v1 = v2; 
    15661627            v2 = e21->EV.Vlong; 
    15671628        } 
    15681629 
    15691630        opcode = 0x81; 
    15701631        switch (sz2) 
    15711632        {   case 1:     opcode--; 
    15721633                        v1 = (signed char) v1; 
    15731634                        v2 = (signed char) v2; 
    15741635                        break; 
    15751636            case 2:     v1 = (short) v1; 
    15761637                        v2 = (short) v2; 
    15771638                        break; 
    15781639        } 
    15791640 
    15801641        if (v1 == 0 && v2 == -1L) 
    1581             c = gen2(c,0xF6 + (opcode & 1),modregrm(3,2,reg));  // NOT reg 
     1642            c = gen2(c,0xF6 + (opcode & 1),grex | modregrmx(3,2,reg));  // NOT reg 
    15821643        else 
    15831644        { 
    15841645            v1 -= v2; 
    1585             c = genc2(c,opcode,modregrm(3,4,reg),v1);   // AND reg,v1-v2 
    1586             if (v2 == 1
     1646            c = genc2(c,opcode,grex | modregrmx(3,4,reg),v1);   // AND reg,v1-v2 
     1647            if (v2 == 1 && !I64
    15871648                gen1(c,0x40 + reg);                     // INC reg 
    1588             else if (v2 == -1L
     1649            else if (v2 == -1L && !I64
    15891650                gen1(c,0x48 + reg);                     // DEC reg 
    15901651            else 
    1591                 genc2(c,opcode,modregrm(3,0,reg),v2);   // ADD reg,v2 
     1652                genc2(c,opcode,grex | modregrmx(3,0,reg),v2);   // ADD reg,v2 
    15921653        } 
    15931654 
    15941655        freenode(e21); 
    15951656        freenode(e22); 
    15961657        freenode(e2); 
    15971658 
    15981659        c = cat(c,fixresult(e,retregs,pretregs)); 
    15991660        goto Lret; 
    16001661  } 
    16011662 
    16021663  if (op1 != OPcond && op1 != OPandand && op1 != OPoror && 
    16031664      op1 != OPnot && op1 != OPbool && 
    16041665      e21->Eoper == OPconst && 
    16051666      sz1 <= REGSIZE && 
    16061667      *pretregs & (mBP | ALLREGS) && 
    16071668      tysize(e21->Ety) <= REGSIZE && !tyfloating(e21->Ety)) 
    16081669  {     // Recognize (e ? c : f) 
    16091670        unsigned reg; 
    16101671        regm_t retregs; 
    16111672 
    16121673        cnop1 = gennop(CNIL); 
    16131674        retregs = mPSW; 
    16141675        jop = jmpopcode(e1);            // get jmp condition 
    16151676        c = codelem(e1,&retregs,FALSE); 
    16161677 
    16171678        // Set the register with e21 without affecting the flags 
    16181679        retregs = *pretregs & (ALLREGS | mBP); 
    16191680        if (retregs & ~regcon.mvar) 
    16201681            retregs &= ~regcon.mvar;    // don't disturb register variables 
    1621         c = regwithvalue(c,retregs,e21->EV.Vint,&reg,8); 
     1682        c = regwithvalue(c,retregs,e21->EV.Vint,&reg,sz1 == 8 ? 64|8 : 8); 
    16221683        retregs = mask[reg]; 
    16231684 
    16241685        c = cat(c,cse_flush(1));                // flush CSE's to memory 
    16251686        c = genjmp(c,jop,FLcode,(block *)cnop1); 
    16261687        freenode(e21); 
    16271688 
    16281689        regconsave = regcon; 
    16291690        stackpushsave = stackpush; 
    16301691 
    16311692        c2 = codelem(e22,&retregs,FALSE); 
    16321693 
    16331694        andregcon(&regconsave); 
    16341695        assert(stackpushsave == stackpush); 
    16351696 
    16361697        freenode(e2); 
    16371698        c = cat6(cc,c,c2,cnop1,fixresult(e,retregs,pretregs),NULL); 
    16381699        goto Lret; 
    16391700  } 
    16401701 
    16411702  cnop1 = gennop(CNIL); 
     
    17161777 *      cg:     [save reg code]         ;if we must preserve reg 
    17171778 *              CLR     reg             ;FALSE result (set Z also) 
    17181779 *              JMP     cnop2 
    17191780 * 
    17201781 *      cnop1:  NOP                     ;if e1 evaluates to TRUE 
    17211782 *              [save reg code]         ;preserve reg 
    17221783 * 
    17231784 *              MOV     reg,1           ;TRUE result 
    17241785 *                  or 
    17251786 *              CLR     reg             ;if return result in flags 
    17261787 *              INC     reg 
    17271788 * 
    17281789 *      cnop2:  NOP                     ;mark end of code 
    17291790 */ 
    17301791 
    17311792code *cdloglog(elem *e,regm_t *pretregs) 
    17321793{ regm_t retregs; 
    17331794  unsigned reg; 
    17341795  code *c; 
    17351796  code *cl,*cr,*cg,*cnop1,*cnop2,*cnop3; 
    1736   register code *c1; 
     1797  code *c1; 
    17371798  con_t regconsave; 
    17381799  unsigned stackpushsave; 
    17391800  int jcond; 
    17401801  elem *e2; 
     1802  unsigned sz = tysize(e->Ety); 
    17411803 
    17421804  /* We can trip the assert with the following:                         */ 
    17431805  /*    if ( (b<=a) ? (c<b || a<=c) : c>=a )                            */ 
    17441806  /* We'll generate ugly code for it, but it's too obscure a case       */ 
    17451807  /* to expend much effort on it.                                       */ 
    17461808  /*assert(*pretregs != mPSW);*/ 
    17471809 
    17481810  cgstate.stackclean++; 
    17491811  cnop1 = gennop(CNIL); 
    17501812  cnop3 = gennop(CNIL); 
    17511813  jcond = 0; 
    17521814  e2 = e->E2; 
    17531815  cl = (e->Eoper == OPoror) 
    17541816        ? logexp(e->E1,jcond | 1,FLcode,cnop1) 
    17551817        : logexp(e->E1,jcond,FLcode,cnop3); 
    17561818  regconsave = regcon; 
    17571819  stackpushsave = stackpush; 
    17581820  if (*pretregs == 0)                   /* if don't want result         */ 
    17591821  {     int noreturn = el_noreturn(e2); 
    17601822 
    17611823        cr = codelem(e2,pretregs,FALSE); 
    17621824        if (noreturn) 
    17631825        { 
    17641826            regconsave.used |= regcon.used; 
    17651827            regcon = regconsave; 
    17661828        } 
    17671829        else 
    17681830            andregcon(&regconsave); 
    17691831        assert(stackpush == stackpushsave); 
    17701832        c = cat4(cl,cr,cnop3,cnop1);    // eval code, throw away result 
    17711833        goto Lret; 
    17721834  } 
    17731835  cnop2 = gennop(CNIL); 
    17741836  if (tybasic(e2->Ety) == TYbool && 
    1775       tysize(e->Ety) == tysize(e2->Ety) && 
     1837      sz == tysize(e2->Ety) && 
    17761838      !(*pretregs & mPSW) && 
    17771839      e2->Eoper == OPcall) 
    17781840  { 
    17791841        cr = codelem(e2,pretregs,FALSE); 
    17801842 
    17811843        andregcon(&regconsave); 
    17821844 
    17831845        // stack depth should not change when evaluating E2 
    17841846        assert(stackpush == stackpushsave); 
    17851847 
    1786         assert(tysize(e->Ety) <= REGSIZE);      // result better be int 
     1848        assert(sz <= 4);                                        // result better be int 
    17871849        retregs = *pretregs & allregs; 
    17881850        cnop1 = cat(cnop1,allocreg(&retregs,&reg,TYint));       // allocate reg for result 
    17891851        cg = genjmp(NULL,JMP,FLcode,(block *) cnop2);           // JMP cnop2 
    17901852        cnop1 = movregconst(cnop1,reg,e->Eoper == OPoror,0);    // reg = 1 
    17911853        regcon.immed.mval &= ~mask[reg];                        // mark reg as unavail 
    17921854        *pretregs = retregs; 
    17931855        if (e->Eoper == OPoror) 
    17941856            c = cat6(cl,cr,cnop3,cg,cnop1,cnop2); 
    17951857        else 
    17961858            c = cat6(cl,cr,cg,cnop3,cnop1,cnop2); 
    17971859 
    17981860        goto Lret; 
    17991861  } 
    18001862  cr = logexp(e2,1,FLcode,cnop1); 
    18011863  andregcon(&regconsave); 
    18021864 
    18031865  /* stack depth should not change when evaluating E2   */ 
    18041866  assert(stackpush == stackpushsave); 
    18051867 
    1806   assert(tysize(e->Ety) <= REGSIZE);    // result better be int 
     1868  assert(sz <= 4);                      // result better be int 
    18071869  retregs = *pretregs & (ALLREGS | mBP); 
    18081870  if (!retregs) retregs = ALLREGS;      // if mPSW only 
    18091871  cg = allocreg(&retregs,&reg,TYint);   // allocate reg for result 
    18101872  for (c1 = cg; c1; c1 = code_next(c1)) // for each instruction 
    18111873        gen(cnop1,c1);                  // duplicate it 
    18121874  cg = movregconst(cg,reg,0,*pretregs & mPSW);  // MOV reg,0 
    18131875  regcon.immed.mval &= ~mask[reg];                      // mark reg as unavail 
    18141876  genjmp(cg,JMP,FLcode,(block *) cnop2);                // JMP cnop2 
    18151877  cnop1 = movregconst(cnop1,reg,1,*pretregs & mPSW);    // reg = 1 
    18161878  regcon.immed.mval &= ~mask[reg];                      // mark reg as unavail 
    18171879  *pretregs = retregs; 
    18181880  c = cat6(cl,cr,cnop3,cg,cnop1,cnop2); 
    18191881Lret: 
    18201882  cgstate.stackclean--; 
    18211883  return c; 
    18221884} 
    18231885 
    18241886 
    18251887/********************* 
    18261888 * Generate code for shift left or shift right (OPshl,OPshr,OPashr). 
     
    18341896  regm_t retregs,rretregs; 
    18351897  code *cg,*cl,*cr; 
    18361898  code *c; 
    18371899  elem *e1; 
    18381900  elem *e2; 
    18391901  regm_t forccs,forregs; 
    18401902  bool e2isconst; 
    18411903 
    18421904  e1 = e->E1; 
    18431905  if (*pretregs == 0)                   // if don't want result 
    18441906  {     c = codelem(e1,pretregs,FALSE); // eval left leaf 
    18451907        *pretregs = 0;                  // in case they got set 
    18461908        return cat(c,codelem(e->E2,pretregs,FALSE)); 
    18471909  } 
    18481910 
    18491911  tyml = tybasic(e1->Ety); 
    18501912  sz = tysize[tyml]; 
    18511913  assert(!tyfloating(tyml)); 
    18521914  uns = tyuns(tyml); 
    18531915  oper = e->Eoper; 
     1916    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1917    unsigned grex = rex << 16; 
    18541918 
    18551919#if SCPP 
    18561920  // Do this until the rest of the compiler does OPshr/OPashr correctly 
    18571921  if (oper == OPshr) 
    18581922        oper = (uns) ? OPshr : OPashr; 
    18591923#endif 
    18601924 
    18611925  switch (oper) 
    18621926  {     case OPshl: 
    18631927            s1 = 4;                     // SHL 
    18641928            s2 = 2;                     // RCL 
    18651929            break; 
    18661930        case OPshr: 
    18671931            s1 = 5;                     // SHR 
    18681932            s2 = 3;                     // RCR 
    18691933            break; 
    18701934        case OPashr: 
    18711935            s1 = 7;                     // SAR 
    18721936            s2 = 3;                     // RCR 
    18731937            break; 
    18741938        default: 
    18751939            assert(0); 
    18761940  } 
    18771941 
    18781942  c = cg = cr = CNIL;                   /* initialize                   */ 
    18791943  e2 = e->E2; 
    18801944  forccs = *pretregs & mPSW;            /* if return result in CCs      */ 
    18811945  forregs = *pretregs & (ALLREGS | mBP); // mask of possible return regs 
    18821946  e2isconst = FALSE;                    /* assume for the moment        */ 
    18831947  byte = (sz == 1); 
    18841948  switch (e2->Eoper) 
    18851949  { 
    18861950    case OPconst: 
    18871951        e2isconst = TRUE;               /* e2 is a constant             */ 
    18881952        shiftcnt = e2->EV.Vint;         /* get shift count              */ 
    1889         if ((I32 && sz <= REGSIZE) || 
     1953        if ((!I16 && sz <= REGSIZE) || 
    18901954            shiftcnt <= 4 ||            /* if sequence of shifts        */ 
    18911955            (sz == 2 && 
    18921956                (shiftcnt == 8 || config.target_cpu >= TARGET_80286)) || 
    18931957            (sz == 2 * REGSIZE && shiftcnt == 8 * REGSIZE) 
    18941958           ) 
    18951959        {       retregs = (forregs) ? forregs 
    18961960                                    : ALLREGS; 
    18971961                if (byte) 
    18981962                {   retregs &= BYTEREGS; 
    18991963                    if (!retregs) 
    19001964                        retregs = BYTEREGS; 
    19011965                } 
    19021966                else if (sz > REGSIZE && sz <= 2 * REGSIZE && 
    19031967                         !(retregs & mMSW)) 
    19041968                    retregs |= mMSW & ALLREGS; 
    19051969                if (s1 == 7)    /* if arithmetic right shift */ 
    19061970                { 
    19071971                    if (shiftcnt == 8) 
    19081972                        retregs = mAX; 
    19091973                    else if (sz == 2 * REGSIZE && shiftcnt == 8 * REGSIZE) 
     
    19181982                   ) 
    19191983                {   // Handle (shtlng)s << 16 
    19201984                    regm_t r; 
    19211985 
    19221986                    r = retregs & mMSW; 
    19231987                    cl = codelem(e1->E1,&r,FALSE);      // eval left leaf 
    19241988                    cl = regwithvalue(cl,retregs & mLSW,0,&resreg,0); 
    19251989                    cg = getregs(r); 
    19261990                    retregs = r | mask[resreg]; 
    19271991                    if (forccs) 
    19281992                    {   sreg = findreg(r); 
    19291993                        cg = gentstreg(cg,sreg); 
    19301994                        *pretregs &= ~mPSW;             // already set 
    19311995                    } 
    19321996                    freenode(e1); 
    19331997                    freenode(e2); 
    19341998                    break; 
    19351999                } 
    19362000 
    19372001                // See if we should use LEA reg,xxx instead of shift 
    1938                 if (I32 && shiftcnt >= 1 && shiftcnt <= 3 && 
    1939                     sz == REGSIZE && oper == OPshl && 
     2002                if (!I16 && shiftcnt >= 1 && shiftcnt <= 3 && 
     2003                    (sz == REGSIZE || (I64 && sz == 4)) && 
     2004                    oper == OPshl && 
    19402005                    e1->Eoper == OPvar && 
    19412006                    !(*pretregs & mPSW) && 
    19422007                    config.flags4 & CFG4speed 
    19432008                   ) 
    19442009                {   Symbol *s1 = e1->EV.sp.Vsym; 
    19452010                    unsigned reg; 
    19462011                    regm_t regm; 
    19472012                    code cs; 
    19482013 
    19492014                    if (isregvar(e1,&regm,&reg) && !(regm & retregs)) 
    19502015                    { 
    19512016                        cl = allocreg(&retregs,&resreg,e->Ety); 
    19522017                        buildEA(&cs,-1,reg,1 << shiftcnt,0); 
    19532018                        cs.Iop = 0x8D; 
    1954                         cs.Irm |= modregrm(0,resreg,0); 
     2019                        code_newreg(&cs,resreg); 
    19552020                        cs.Iflags = 0; 
    19562021                        cg = gen(NULL,&cs);             // LEA resreg,[reg * ss] 
    19572022                        freenode(e1); 
    19582023                        freenode(e2); 
    19592024                        break; 
    19602025                    } 
    19612026                } 
    19622027 
    19632028                cl = codelem(e1,&retregs,FALSE); // eval left leaf 
    19642029                //assert((retregs & regcon.mvar) == 0); 
    19652030                cg = getregs(retregs);          // trash these regs 
    19662031 
    19672032                { 
    19682033                    if (sz == 2 * REGSIZE) 
    19692034                    {   resreg = findregmsw(retregs); 
    19702035                        sreg = findreglsw(retregs); 
    19712036                    } 
    19722037                    else 
    19732038                        resreg = findreg(retregs); 
    19742039                    if (config.target_cpu >= TARGET_80286 && 
    19752040                        sz <= REGSIZE) 
    19762041                    { 
    19772042                        /* SHL resreg,shiftcnt  */ 
    19782043                        assert(!(sz == 1 && (mask[resreg] & ~BYTEREGS))); 
    1979                         c = genc2(CNIL,0xC1 ^ byte,modregrm(3,s1,resreg),shiftcnt); 
     2044                        c = genc2(CNIL,0xC1 ^ byte,grex | modregxrmx(3,s1,resreg),shiftcnt); 
    19802045                        if (shiftcnt == 1) 
    19812046                            c->Iop += 0x10;     /* short form of shift  */ 
    19822047                        // See if we need operand size prefix 
    1983                         if (I32 && oper != OPshl && sz == 2) 
     2048                        if (!I16 && oper != OPshl && sz == 2) 
    19842049                            c->Iflags |= CFopsize; 
    19852050                        if (forccs) 
    19862051                            c->Iflags |= CFpsw;         // need flags result 
    19872052                    } 
    19882053                    else if (shiftcnt == 8) 
    1989                     {   if (!(retregs & BYTEREGS)
     2054                    {   if (!(retregs & BYTEREGS) || resreg >= 4
    19902055                        { 
    19912056                            cl = cat(cl,cg); 
    19922057                            goto L1; 
    19932058                        } 
    19942059 
    19952060                        if (pass != PASSfinal && (!forregs || forregs & (mSI | mDI))) 
    19962061                        { 
    19972062                            // e1 might get into SI or DI in a later pass, 
    19982063                            // so don't put CX into a register 
    19992064                            cg = cat(cg, getregs(mCX)); 
    20002065                        } 
    20012066 
    20022067                        if (oper == OPshl) 
    20032068                        {       /* MOV regH,regL        XOR regL,regL   */ 
     2069                                assert(resreg < 4 && !rex); 
    20042070                                c = genregs(CNIL,0x8A,resreg+4,resreg); 
    20052071                                genregs(c,0x32,resreg,resreg); 
    20062072                        } 
    20072073                        else            // OPshr/OPashr 
    20082074                        { 
    20092075                            /* MOV regL,regH    */ 
    20102076                            c = genregs(CNIL,0x8A,resreg,resreg+4); 
    20112077                            if (oper == OPashr) 
    20122078                                gen1(c,0x98);           /* CBW          */ 
    20132079                            else 
    20142080                                genregs(c,0x32,resreg+4,resreg+4); /* CLR regH */ 
    20152081                        } 
    20162082                        if (forccs) 
    20172083                                gentstreg(c,resreg); 
    20182084                    } 
    20192085                    else if (shiftcnt == REGSIZE * 8)   // it's an lword 
    20202086                    { 
    20212087                        if (oper == OPshl) 
    20222088                            swap((int *) &resreg,(int *) &sreg); 
    20232089                        c = genmovreg(CNIL,sreg,resreg);        // MOV sreg,resreg 
     
    20662132        else 
    20672133        { 
    20682134            if (!(retregs & mMSW)) 
    20692135                retregs = ALLREGS & ~mCX; 
    20702136        } 
    20712137        cl = codelem(e->E1,&retregs,FALSE);     /* eval left leaf       */ 
    20722138 
    20732139        if (sz <= REGSIZE) 
    20742140            resreg = findreg(retregs); 
    20752141        else 
    20762142        { 
    20772143            resreg = findregmsw(retregs); 
    20782144            sreg = findreglsw(retregs); 
    20792145        } 
    20802146    L1: 
    20812147        rretregs = mCX;                 /* CX is shift count    */ 
    20822148        if (sz <= REGSIZE) 
    20832149        { 
    20842150            cr = scodelem(e2,&rretregs,retregs,FALSE); /* get rvalue */ 
    20852151            cg = getregs(retregs);      /* trash these regs             */ 
    2086             c = gen2(CNIL,0xD3 ^ byte,modregrm(3,s1,resreg)); /* Sxx resreg,CX */ 
     2152            c = gen2(CNIL,0xD3 ^ byte,grex | modregrmx(3,s1,resreg)); /* Sxx resreg,CX */ 
    20872153 
    20882154            // Note that a shift by CL does not set the flags if 
    20892155            // CL == 0. If e2 is a constant, we know it isn't 0 
    20902156            // (it would have been optimized out). 
    20912157            if (e2isconst) 
    20922158                *pretregs &= mBP | ALLREGS; // flags already set with result 
    20932159        } 
    20942160        else if (sz == 2 * REGSIZE && 
    20952161                 config.target_cpu >= TARGET_80386) 
    20962162        {   unsigned hreg,lreg; 
    20972163 
    20982164            hreg = resreg; 
    20992165            lreg = sreg; 
    21002166            if (e2isconst) 
    21012167            { 
    21022168                cr = NULL; 
    21032169                cg = getregs(retregs); 
    21042170                if (shiftcnt & (REGSIZE * 8)) 
    21052171                { 
    21062172                    if (oper == OPshr) 
     
    23092375                return cdind87(e, pretregs); 
    23102376        } 
    23112377  } 
    23122378 
    23132379  e1 = e->E1; 
    23142380  assert(e1); 
    23152381  switch (tym) 
    23162382  {     case TYstruct: 
    23172383        case TYarray: 
    23182384            // This case should never happen, why is it here? 
    23192385            tym = TYnptr;               // don't confuse allocreg() 
    23202386#if !TARGET_FLAT 
    23212387            if (*pretregs & (mES | mCX) || e->Ety & mTYfar) 
    23222388                    tym = TYfptr; 
    23232389#endif 
    23242390 
    23252391#if 0 
    23262392  c = getlvalue(&cs,e,RMload);          // get addressing mode 
    23272393  if (*pretregs == 0) 
    23282394        return c; 
    2329   idxregs = idxregm(cs.Irm,cs.Isib);    /* mask of index regs used      */ 
     2395  idxregs = idxregm(&cs);               // mask of index regs used 
    23302396  c = cat(c,fixresult(e,idxregs,pretregs)); 
    23312397  return c; 
    23322398#endif 
    23332399            break; 
    23342400  } 
    23352401  sz = tysize[tym]; 
    23362402  byte = tybyte(tym) != 0; 
    23372403 
    23382404  c = getlvalue(&cs,e,RMload);          // get addressing mode 
    23392405  /*fprintf(stderr,"cd2 :\n"); WRcodlst(c);*/ 
    23402406  if (*pretregs == 0) 
    23412407        return c; 
    23422408 
    2343   idxregs = idxregm(cs.Irm,cs.Isib);    /* mask of index regs used      */ 
     2409  idxregs = idxregm(&cs);               // mask of index regs used 
    23442410 
    23452411  if (*pretregs == mPSW) 
    23462412  { 
    2347         if (I32 && tym == TYfloat) 
     2413        if (!I16 && tym == TYfloat) 
    23482414        {       retregs = ALLREGS & ~idxregs; 
    23492415                c = cat(c,allocreg(&retregs,&reg,TYfloat)); 
    23502416                cs.Iop = 0x8B; 
    2351                 cs.Irm |= modregrm(0,reg,0); 
    2352                 ce = gen(CNIL,&cs);                     /* MOV reg,lsw  */ 
    2353                 gen2(ce,0xD1,modregrm(3,4,reg));        /* SHL reg,1    */ 
     2417                code_newreg(&cs,reg); 
     2418                ce = gen(CNIL,&cs);                     // MOV reg,lsw 
     2419                gen2(ce,0xD1,modregrmx(3,4,reg));       // SHL reg,1 
    23542420        } 
    23552421        else if (sz <= REGSIZE) 
    23562422        { 
    23572423                cs.Iop = 0x81 ^ byte; 
    23582424                cs.Irm |= modregrm(0,7,0); 
    23592425                cs.IFL2 = FLconst; 
    23602426                cs.IEV2.Vint = 0; 
    23612427                ce = gen(CNIL,&cs);             /* CMP [idx],0          */ 
    23622428        } 
    2363         else if (I32 && sz == REGSIZE + 2)      // if far pointer 
     2429        else if (!I16 && sz == REGSIZE + 2)      // if far pointer 
    23642430        {       retregs = ALLREGS & ~idxregs; 
    23652431                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    23662432                cs.Iop = 0x0F; 
    23672433                cs.Iop2 = 0xB7; 
    23682434                cs.Irm |= modregrm(0,reg,0); 
    23692435                getlvalue_msw(&cs); 
    23702436                ce = gen(CNIL,&cs);             /* MOVZX reg,msw        */ 
    23712437                goto L4; 
    23722438        } 
    23732439        else if (sz <= 2 * REGSIZE) 
    23742440        {       retregs = ALLREGS & ~idxregs; 
    23752441                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    23762442                cs.Iop = 0x8B; 
    23772443                cs.Irm |= modregrm(0,reg,0); 
    23782444                getlvalue_msw(&cs); 
    23792445                ce = gen(CNIL,&cs);             /* MOV reg,msw          */ 
    23802446                if (I32) 
    23812447                {   if (tym == TYdouble || tym == TYdouble_alias) 
    23822448                        gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 
    23832449                } 
     
    24072473 
    24082474            /* Optimizer should not CSE these, as the result is worse code! */ 
    24092475            assert(!e->Ecount); 
    24102476 
    24112477            cs.Iop = 0xFF; 
    24122478            cs.Irm |= modregrm(0,6,0); 
    24132479            cs.IEVoffset1 += 8 - REGSIZE; 
    24142480            stackchanged = 1; 
    24152481            i = 8 - REGSIZE; 
    24162482            do 
    24172483            { 
    24182484                c = gen(c,&cs);                         /* PUSH EA+i    */ 
    24192485                c = genadjesp(c,REGSIZE); 
    24202486                cs.IEVoffset1 -= REGSIZE; 
    24212487                stackpush += REGSIZE; 
    24222488                i -= REGSIZE; 
    24232489            } 
    24242490            while (i >= 0); 
    24252491            goto L3; 
    24262492        } 
    2427         if (!I32 && sz == 8) 
     2493        if (I16 && sz == 8) 
    24282494            retregs = DOUBLEREGS_16; 
    24292495 
    24302496        /* Watch out for loading an lptr from an lptr! We must have     */ 
    24312497        /* the offset loaded into a different register.                 */ 
    24322498        /*if (retregs & mES && (cs.Iflags & CFSEG) == CFes) 
    24332499                retregs = ALLREGS;*/ 
    24342500 
    24352501        { 
    24362502        assert(!byte || retregs & BYTEREGS); 
    24372503        c = cat(c,allocreg(&retregs,&reg,tym)); /* alloc registers */ 
    24382504        } 
    24392505        if (sz <= REGSIZE) 
    24402506        { 
    24412507                cs.Iop = 0x8B ^ byte; 
    2442         L2:     cs.Irm |= modregrm(0,reg,0); 
     2508        L2:     code_newreg(&cs,reg); 
    24432509                ce = gen(CNIL,&cs);     /* MOV reg,[idx]                */ 
    24442510        } 
    24452511        else if ((tym == TYfptr || tym == TYhptr) && retregs & mES) 
    24462512        { 
    24472513                cs.Iop = 0xC4;          /* LES reg,[idx]                */ 
    24482514                goto L2; 
    24492515        } 
    24502516        else if (sz <= 2 * REGSIZE) 
    24512517        {   unsigned lsreg; 
    24522518 
    24532519            cs.Iop = 0x8B; 
    24542520            /* Be careful not to interfere with index registers */ 
    24552521            if (I32) 
    24562522            { 
    24572523                /* Can't handle if both result registers are used in    */ 
    24582524                /* the addressing mode.                                 */ 
    24592525                if ((retregs & idxregs) == retregs) 
    24602526                { 
    24612527                    retregs = mMSW & allregs & ~idxregs; 
    24622528                    if (!retregs) 
     
    25012567                    ce = gen(CNIL,&cs);                 // MOV reg,msw 
    25022568                    if (sz == REGSIZE + 2) 
    25032569                        ce->Iflags |= CFopsize; 
    25042570                    getlvalue_lsw(&cs);                 // MOV lsreg,lsw 
    25052571                } 
    25062572                NEWREG(cs.Irm,lsreg); 
    25072573                gen(ce,&cs); 
    25082574            } 
    25092575            else 
    25102576            { 
    25112577                /* Index registers are always the lsw!                  */ 
    25122578                cs.Irm |= modregrm(0,reg,0); 
    25132579                getlvalue_msw(&cs); 
    25142580                ce = gen(CNIL,&cs);     /* MOV reg,msw          */ 
    25152581                lsreg = findreglsw(retregs); 
    25162582                NEWREG(cs.Irm,lsreg); 
    25172583                getlvalue_lsw(&cs);     /* MOV lsreg,lsw        */ 
    25182584                gen(ce,&cs); 
    25192585            } 
    25202586        } 
    2521         else if (!I32 && sz == 8) 
     2587        else if (I16 && sz == 8) 
    25222588        { 
    25232589                assert(reg == AX); 
    25242590                cs.Iop = 0x8B; 
    25252591                cs.IEVoffset1 += 6; 
    25262592                ce = gen(CNIL,&cs);             /* MOV AX,EA+6          */ 
    25272593                cs.Irm |= modregrm(0,CX,0); 
    25282594                cs.IEVoffset1 -= 4; 
    25292595                gen(ce,&cs);                    /* MOV CX,EA+2          */ 
    25302596                NEWREG(cs.Irm,DX); 
    25312597                cs.IEVoffset1 -= 2; 
    25322598                gen(ce,&cs);                    /* MOV DX,EA            */ 
    25332599                cs.IEVoffset1 += 4; 
    25342600                NEWREG(cs.Irm,BX); 
    25352601                gen(ce,&cs);                    /* MOV BX,EA+4          */ 
    25362602        } 
    25372603        else 
    25382604                assert(0); 
    25392605        c = cat(c,ce); 
    25402606    L3: 
    25412607        c = cat(c,fixresult(e,retregs,pretregs)); 
    25422608  } 
    25432609  /*fprintf(stderr,"cdafter :\n"); WRcodlst(c);*/ 
    25442610  return c; 
    25452611} 
    25462612 
    25472613 
    25482614 
    25492615#if TARGET_FLAT 
    25502616#define cod2_setES(ty) NULL 
    25512617#else 
    25522618/******************************** 
    25532619 * Generate code to load ES with the right segment value, 
    25542620 * do nothing if e is a far pointer. 
    25552621 */ 
    25562622 
    2557 STATIC code * cod2_setES(tym_t ty) 
     2623STATIC code *cod2_setES(tym_t ty) 
    25582624{   code *c2; 
    25592625    int push; 
    25602626 
    25612627    c2 = CNIL; 
    25622628    switch (tybasic(ty)) 
    25632629    { 
    25642630        case TYnptr: 
    25652631            if (!(config.flags3 & CFG3eseqds)) 
    25662632            {   push = 0x1E;            /* PUSH DS              */ 
    25672633                goto L1; 
    25682634            } 
    25692635            break; 
    25702636        case TYcptr: 
    25712637            push = 0x0E;                /* PUSH CS              */ 
    25722638            goto L1; 
    25732639        case TYsptr: 
    25742640            if ((config.wflags & WFssneds) || !(config.flags3 & CFG3eseqds)) 
    25752641            {   push = 0x16;            /* PUSH SS              */ 
    25762642            L1: 
    25772643                /* Must load ES */ 
    25782644                c2 = getregs(mES); 
    25792645                c2 = gen1(c2,push); 
    25802646                gen1(c2,0x07);          /* POP ES               */ 
    25812647            } 
    25822648            break; 
    25832649    } 
    25842650    return c2; 
    25852651} 
    25862652#endif 
    25872653 
    25882654/******************************** 
    25892655 * Generate code for intrinsic strlen(). 
    25902656 */ 
    25912657 
    25922658code *cdstrlen( elem *e, regm_t *pretregs) 
    25932659{   code *c1,*c2,*c3,*c4; 
    2594     regm_t retregs; 
    2595     tym_t ty1; 
    25962660 
    25972661    /* Generate strlen in CX: 
    25982662        LES     DI,e1 
    25992663        CLR     AX                      ;scan for 0 
    26002664        MOV     CX,-1                   ;largest possible string 
    26012665        REPNE   SCASB 
    26022666        NOT     CX 
    26032667        DEC     CX 
    26042668     */ 
    26052669 
    2606     retregs = mDI; 
    2607     ty1 = e->E1->Ety; 
     2670    regm_t retregs = mDI; 
     2671    tym_t ty1 = e->E1->Ety; 
    26082672    if (!tyreg(ty1)) 
    26092673        retregs |= mES; 
    26102674    c1 = codelem(e->E1,&retregs,FALSE); 
    26112675 
    26122676    /* Make sure ES contains proper segment value       */ 
    26132677    c2 = cod2_setES(ty1); 
    26142678 
     2679    unsigned char rex = I64 ? REX_W : 0; 
     2680 
    26152681    c3 = getregs_imm(mAX | mCX); 
    26162682    c3 = movregconst(c3,AX,0,1);                /* MOV AL,0             */ 
    2617     c3 = movregconst(c3,CX,-1,0);               /* MOV CX,-1            */ 
     2683    c3 = movregconst(c3,CX,-1LL,I64 ? 64 : 0);  // MOV CX,-1 
    26182684    c3 = cat(c3,getregs(mDI|mCX)); 
    26192685    c3 = gen1(c3,0xF2);                         /* REPNE                        */ 
    26202686    gen1(c3,0xAE);                              /* SCASB                */ 
    26212687    genregs(c3,0xF7,2,CX);                      /* NOT CX               */ 
    2622     c4 = gen1(CNIL,0x48 + CX);                  /* DEC CX               */ 
     2688    code_orrex(c3,rex); 
     2689    if (I64) 
     2690        c4 = gen2(CNIL,0xFF,(rex << 16) | modregrm(3,1,CX));  // DEC reg 
     2691    else 
     2692        c4 = gen1(CNIL,0x48 + CX);              // DEC CX 
    26232693 
    26242694    if (*pretregs & mPSW) 
    26252695    { 
    26262696        c4->Iflags |= CFpsw; 
    26272697        *pretregs &= ~mPSW; 
    26282698    } 
    26292699    return cat6(c1,c2,c3,c4,fixresult(e,mCX,pretregs),CNIL); 
    26302700} 
    26312701 
    26322702 
    26332703/********************************* 
    26342704 * Generate code for strcmp(s1,s2) intrinsic. 
    26352705 */ 
    26362706 
    26372707code *cdstrcmp( elem *e, regm_t *pretregs) 
    26382708{   code *c1,*c1a,*c2,*c3,*c4; 
    2639     regm_t retregs1; 
    2640     regm_t retregs; 
    2641     tym_t ty1,ty2; 
    26422709    char need_DS; 
    26432710    int segreg; 
    26442711 
    26452712    /* 
    26462713        MOV     SI,s1                   ;get destination pointer (s1) 
    26472714        MOV     CX,s1+2 
    26482715        LES     DI,s2                   ;get source pointer (s2) 
    26492716        PUSH    DS 
    26502717        MOV     DS,CX 
    26512718        CLR     AX                      ;scan for 0 
    26522719        MOV     CX,-1                   ;largest possible string 
    26532720        REPNE   SCASB 
    26542721        NOT     CX                      ;CX = string length of s2 
    26552722        SUB     DI,CX                   ;point DI back to beginning 
    26562723        REPE    CMPSB                   ;compare string 
    26572724        POP     DS 
    26582725        JE      L1                      ;strings are equal 
    26592726        SBB     AX,AX 
    26602727        SBB     AX,-1 
    26612728    L1: 
    26622729    */ 
    26632730 
    2664     retregs1 = mSI; 
    2665     ty1 = e->E1->Ety; 
     2731    regm_t retregs1 = mSI; 
     2732    tym_t ty1 = e->E1->Ety; 
    26662733    if (!tyreg(ty1)) 
    26672734        retregs1 |= mCX; 
    26682735    c1 = codelem(e->E1,&retregs1,FALSE); 
    26692736 
    2670     retregs = mDI; 
    2671     ty2 = e->E2->Ety; 
     2737    regm_t retregs = mDI; 
     2738    tym_t ty2 = e->E2->Ety; 
    26722739    if (!tyreg(ty2)) 
    26732740        retregs |= mES; 
    26742741    c1 = cat(c1,scodelem(e->E2,&retregs,retregs1,FALSE)); 
    26752742 
    26762743    /* Make sure ES contains proper segment value       */ 
    26772744    c2 = cod2_setES(ty2); 
    26782745    c3 = getregs_imm(mAX | mCX); 
     2746 
     2747    unsigned char rex = I64 ? REX_W : 0; 
    26792748 
    26802749    /* Load DS with right value */ 
    26812750    switch (tybasic(ty1)) 
    26822751    { 
    26832752        case TYnptr: 
    26842753            need_DS = FALSE; 
    26852754            break; 
    26862755        case TYsptr: 
    26872756            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    26882757                segreg = SEG_SS; 
    26892758            else 
    26902759                segreg = SEG_DS; 
    26912760            goto L1; 
    26922761        case TYcptr: 
    26932762            segreg = SEG_CS; 
    26942763        L1: 
    26952764            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    26962765            gen1(c3,0x06 + (segreg << 3));              /* PUSH segreg  */ 
    26972766            gen1(c3,0x1F);                              /* POP  DS      */ 
    26982767            need_DS = TRUE; 
    26992768            break; 
    27002769        case TYfptr: 
    27012770        case TYvptr: 
    27022771        case TYhptr: 
    27032772            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    27042773            gen2(c3,0x8E,modregrm(3,SEG_DS,CX));        /* MOV DS,CX    */ 
    27052774            need_DS = TRUE; 
    27062775            break; 
    27072776        default: 
    27082777            assert(0); 
    27092778    } 
    27102779 
    27112780    c3 = movregconst(c3,AX,0,0);                /* MOV AX,0             */ 
    2712     c3 = movregconst(c3,CX,-1,0);               /* MOV CX,-1            */ 
     2781    c3 = movregconst(c3,CX,-1LL,I64 ? 64 : 0);  // MOV CX,-1 
    27132782    c3 = cat(c3,getregs(mSI|mDI|mCX)); 
    27142783    c3 = gen1(c3,0xF2);                         /* REPNE                        */ 
    27152784    gen1(c3,0xAE);                              /* SCASB                */ 
    27162785    genregs(c3,0xF7,2,CX);                      /* NOT CX               */ 
     2786    code_orrex(c3,rex); 
    27172787    genregs(c3,0x2B,DI,CX);                     /* SUB DI,CX            */ 
     2788    code_orrex(c3,rex); 
    27182789    gen1(c3,0xF3);                              /* REPE                 */ 
    27192790    gen1(c3,0xA6);                              /* CMPSB                */ 
    27202791    if (need_DS) 
    27212792        gen1(c3,0x1F);                          /* POP DS               */ 
    27222793    c4 = gennop(CNIL); 
    27232794    if (*pretregs != mPSW)                      /* if not flags only    */ 
    27242795    { 
    27252796        genjmp(c3,JE,FLcode,(block *) c4);      /* JE L1                */ 
    27262797        c3 = cat(c3,getregs(mAX)); 
    27272798        genregs(c3,0x1B,AX,AX);                 /* SBB AX,AX            */ 
    2728         genc2(c3,0x81,modregrm(3,3,AX),(targ_uns)-1);   /* SBB AX,-1            */ 
     2799        code_orrex(c3,rex); 
     2800        genc2(c3,0x81,(rex << 16) | modregrm(3,3,AX),(targ_uns)-1);   // SBB AX,-1 
    27292801    } 
    27302802 
    27312803    *pretregs &= ~mPSW; 
    27322804    return cat6(c1,c2,c3,c4,fixresult(e,mAX,pretregs),CNIL); 
    27332805} 
    27342806 
    27352807/********************************* 
    27362808 * Generate code for memcmp(s1,s2,n) intrinsic. 
    27372809 */ 
    27382810 
    27392811code *cdmemcmp(elem *e,regm_t *pretregs) 
    27402812{   code *c1,*c2,*c3,*c4; 
    2741     regm_t retregs1; 
    2742     regm_t retregs; 
    2743     regm_t retregs3; 
    2744     tym_t ty1,ty2; 
    27452813    char need_DS; 
    27462814    int segreg; 
    2747     elem *e1; 
    27482815 
    27492816    /* 
    27502817        MOV     SI,s1                   ;get destination pointer (s1) 
    27512818        MOV     DX,s1+2 
    27522819        LES     DI,s2                   ;get source pointer (s2) 
    27532820        MOV     CX,n                    ;get number of bytes to compare 
    27542821        PUSH    DS 
    27552822        MOV     DS,DX 
    27562823        XOR     AX,AX 
    27572824        REPE    CMPSB                   ;compare string 
    27582825        POP     DS 
    27592826        JE      L1                      ;strings are equal 
    27602827        SBB     AX,AX 
    27612828        SBB     AX,-1 
    27622829    L1: 
    27632830    */ 
    27642831 
    2765     e1 = e->E1; 
     2832    elem *e1 = e->E1; 
    27662833    assert(e1->Eoper == OPparam); 
    27672834 
    27682835    // Get s1 into DX:SI 
    2769     retregs1 = mSI; 
    2770     ty1 = e1->E1->Ety; 
     2836    regm_t retregs1 = mSI; 
     2837    tym_t ty1 = e1->E1->Ety; 
    27712838    if (!tyreg(ty1)) 
    27722839        retregs1 |= mDX; 
    27732840    c1 = codelem(e1->E1,&retregs1,FALSE); 
    27742841 
    27752842    // Get s2 into ES:DI 
    2776     retregs = mDI; 
    2777     ty2 = e1->E2->Ety; 
     2843    regm_t retregs = mDI; 
     2844    tym_t ty2 = e1->E2->Ety; 
    27782845    if (!tyreg(ty2)) 
    27792846        retregs |= mES; 
    27802847    c1 = cat(c1,scodelem(e1->E2,&retregs,retregs1,FALSE)); 
    27812848    freenode(e1); 
    27822849 
    27832850    // Get nbytes into CX 
    2784     retregs3 = mCX; 
     2851    regm_t retregs3 = mCX; 
    27852852    c1 = cat(c1,scodelem(e->E2,&retregs3,retregs | retregs1,FALSE)); 
    27862853 
    27872854    /* Make sure ES contains proper segment value       */ 
    27882855    c2 = cod2_setES(ty2); 
    27892856 
    27902857    /* Load DS with right value */ 
    27912858    c3 = NULL; 
    27922859    switch (tybasic(ty1)) 
    27932860    { 
    27942861        case TYnptr: 
    27952862            need_DS = FALSE; 
    27962863            break; 
    27972864        case TYsptr: 
    27982865            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    27992866                segreg = SEG_SS; 
    28002867            else 
    28012868                segreg = SEG_DS; 
    28022869            goto L1; 
    28032870        case TYcptr: 
    28042871            segreg = SEG_CS; 
     
    28632930        CLR     AX                      ;scan for 0 
    28642931        MOV     CX,-1                   ;largest possible string 
    28652932        REPNE   SCASB                   ;find end of s2 
    28662933        NOT     CX                      ;CX = strlen(s2) + 1 (for EOS) 
    28672934        SUB     DI,CX 
    28682935        MOV     SI,DI 
    28692936        PUSH    DS 
    28702937        PUSH    ES 
    28712938        LES     DI,s1 
    28722939        POP     DS 
    28732940        MOV     AX,DI                   ;return value is s1 
    28742941        REP     MOVSB 
    28752942        POP     DS 
    28762943    */ 
    28772944 
    28782945    stackchanged = 1; 
    28792946    retregs = mDI; 
    28802947    ty2 = tybasic(e->E2->Ety); 
    28812948    if (!tyreg(ty2)) 
    28822949        retregs |= mES; 
     2950    unsigned char rex = I64 ? REX_W : 0; 
    28832951    c1 = codelem(e->E2,&retregs,FALSE); 
    28842952 
    28852953    /* Make sure ES contains proper segment value       */ 
    28862954    c2 = cod2_setES(ty2); 
    28872955    c3 = getregs_imm(mAX | mCX); 
    28882956    c3 = movregconst(c3,AX,0,1);                /* MOV AL,0             */ 
    2889     c3 = movregconst(c3,CX,-1,0);               /* MOV CX,-1            */ 
     2957    c3 = movregconst(c3,CX,-1,I64?64:0);        // MOV CX,-1 
    28902958    c3 = cat(c3,getregs(mAX|mCX|mSI|mDI)); 
    28912959    c3 = gen1(c3,0xF2);                         /* REPNE                        */ 
    28922960    gen1(c3,0xAE);                              /* SCASB                */ 
    28932961    genregs(c3,0xF7,2,CX);                      /* NOT CX               */ 
     2962    code_orrex(c3,rex); 
    28942963    genregs(c3,0x2B,DI,CX);                     /* SUB DI,CX            */ 
     2964    code_orrex(c3,rex); 
    28952965    genmovreg(c3,SI,DI);                        /* MOV SI,DI            */ 
     2966    code_orrex(c3,rex); 
    28962967 
    28972968    /* Load DS with right value */ 
    28982969    switch (ty2) 
    28992970    { 
    29002971        case TYnptr: 
    29012972            need_DS = FALSE; 
    29022973            break; 
    29032974        case TYsptr: 
    29042975            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    29052976                segreg = SEG_SS; 
    29062977            else 
    29072978                segreg = SEG_DS; 
    29082979            goto L1; 
    29092980        case TYcptr: 
    29102981            segreg = SEG_CS; 
    29112982        L1: 
    29122983            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    29132984            gen1(c3,0x06 + (segreg << 3));              /* PUSH segreg  */ 
    29142985            genadjesp(c3,REGSIZE * 2); 
    29152986            need_DS = TRUE; 
     
    29232994        default: 
    29242995            assert(0); 
    29252996    } 
    29262997 
    29272998    retregs = mDI; 
    29282999    ty1 = tybasic(e->E1->Ety); 
    29293000    if (!tyreg(ty1)) 
    29303001        retregs |= mES; 
    29313002    c3 = cat(c3,scodelem(e->E1,&retregs,mCX|mSI,FALSE)); 
    29323003    c3 = cat(c3,getregs(mAX|mCX|mSI|mDI)); 
    29333004 
    29343005    /* Make sure ES contains proper segment value       */ 
    29353006    if (ty2 != TYnptr || ty1 != ty2) 
    29363007        c4 = cod2_setES(ty1); 
    29373008    else 
    29383009        c4 = CNIL;                              /* ES is already same as DS */ 
    29393010 
    29403011    if (need_DS) 
    29413012        c4 = gen1(c4,0x1F);                     /* POP DS               */ 
    29423013    if (*pretregs) 
    2943         c4 = genmovreg(c4,AX,DI);               /* MOV AX,DI            */ 
     3014    {   c4 = genmovreg(c4,AX,DI);               /* MOV AX,DI            */ 
     3015        code_orrex(c4,rex); 
     3016    } 
    29443017    c4 = gen1(c4,0xF3);                         /* REP                  */ 
    29453018    gen1(c4,0xA4);                              /* MOVSB                */ 
    29463019 
    29473020    if (need_DS) 
    29483021    {   gen1(c4,0x1F);                          /* POP DS               */ 
    29493022        genadjesp(c4,-(REGSIZE * 2)); 
    29503023    } 
    29513024    return cat6(c1,c2,c3,c4,fixresult(e,mAX | mES,pretregs),CNIL); 
    29523025} 
    29533026 
    29543027/********************************* 
    29553028 * Generate code for memcpy(s1,s2,n) intrinsic. 
    29563029 *  OPmemcpy 
    29573030 *   /   \ 
    29583031 * s1   OPparam 
    29593032 *       /   \ 
    29603033 *      s2    n 
    29613034 */ 
    29623035 
    29633036code *cdmemcpy(elem *e,regm_t *pretregs) 
     
    29863059    assert(e2->Eoper == OPparam); 
    29873060 
    29883061    // Get s2 into DX:SI 
    29893062    retregs2 = mSI; 
    29903063    ty2 = e2->E1->Ety; 
    29913064    if (!tyreg(ty2)) 
    29923065        retregs2 |= mDX; 
    29933066    c1 = codelem(e2->E1,&retregs2,FALSE); 
    29943067 
    29953068    // Get nbytes into CX 
    29963069    retregs3 = mCX; 
    29973070    c1 = cat(c1,scodelem(e2->E2,&retregs3,retregs2,FALSE)); 
    29983071    freenode(e2); 
    29993072 
    30003073    // Get s1 into ES:DI 
    30013074    retregs1 = mDI; 
    30023075    ty1 = e->E1->Ety; 
    30033076    if (!tyreg(ty1)) 
    30043077        retregs1 |= mES; 
    30053078    c1 = cat(c1,scodelem(e->E1,&retregs1,retregs2 | retregs3,FALSE)); 
     3079 
     3080    unsigned char rex = I64 ? REX_W : 0; 
    30063081 
    30073082    /* Make sure ES contains proper segment value       */ 
    30083083    c2 = cod2_setES(ty1); 
    30093084 
    30103085    /* Load DS with right value */ 
    30113086    c3 = NULL; 
    30123087    switch (tybasic(ty2)) 
    30133088    { 
    30143089        case TYnptr: 
    30153090            need_DS = FALSE; 
    30163091            break; 
    30173092        case TYsptr: 
    30183093            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    30193094                segreg = SEG_SS; 
    30203095            else 
    30213096                segreg = SEG_DS; 
    30223097            goto L1; 
    30233098        case TYcptr: 
    30243099            segreg = SEG_CS; 
    30253100        L1: 
    30263101            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    30273102            gen1(c3,0x06 + (segreg << 3));              /* PUSH segreg  */ 
    30283103            gen1(c3,0x1F);                              /* POP  DS      */ 
    30293104            need_DS = TRUE; 
    30303105            break; 
    30313106        case TYfptr: 
    30323107        case TYvptr: 
    30333108        case TYhptr: 
    30343109            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    30353110            gen2(c3,0x8E,modregrm(3,SEG_DS,DX));        /* MOV DS,DX    */ 
    30363111            need_DS = TRUE; 
    30373112            break; 
    30383113        default: 
    30393114            assert(0); 
    30403115    } 
    30413116 
    30423117    if (*pretregs)                              // if need return value 
    30433118    {   c3 = cat(c3,getregs(mAX)); 
    30443119        c3 = genmovreg(c3,AX,DI); 
     3120        code_orrex(c3, rex); 
    30453121    } 
    30463122 
    30473123    if (0 && I32 && config.flags4 & CFG4speed) 
    30483124    { 
    30493125        /* This is only faster if the memory is dword aligned, if not 
    30503126         * it is significantly slower than just a rep movsb. 
    30513127         */ 
    30523128        /*      mov     EDX,ECX 
    30533129         *      shr     ECX,2 
    30543130         *      jz      L1 
    30553131         *      repe    movsd 
    30563132         * L1:  and     EDX,3 
    30573133         *      jz      L2 
    30583134         *      mov     ECX,EDX 
    30593135         *      repe    movsb 
    30603136         * L2:  nop 
    30613137         */ 
    30623138        c3 = cat(c3,getregs(mSI | mDI | mCX | mDX)); 
    30633139        c3 = genmovreg(c3,DX,CX);               // MOV EDX,ECX 
    30643140        c3 = genc2(c3,0xC1,modregrm(3,5,CX),2); // SHR ECX,2 
    30653141        code *cx = genc2(CNIL, 0x81, modregrm(3,4,DX),3);       // AND EDX,3 
    30663142        genjmp(c3, JE, FLcode, (block *)cx);                    // JZ L1 
    30673143        gen1(c3,0xF3);                                          // REPE 
    30683144        gen1(c3,0xA5);                                          // MOVSW 
    30693145        c3 = cat(c3,cx); 
    30703146 
    30713147        code *cnop = gennop(CNIL); 
    30723148        genjmp(c3, JE, FLcode, (block *)cnop);  // JZ L2 
    30733149        genmovreg(c3,CX,DX);                    // MOV ECX,EDX 
    30743150        gen1(c3,0xF3);                          // REPE 
    30753151        gen1(c3,0xA4);                          // MOVSB 
    30763152        c3 = cat(c3, cnop); 
    30773153    } 
    30783154    else 
    30793155    { 
    30803156        c3 = cat(c3,getregs(mSI | mDI | mCX)); 
    30813157        if (!I32 && config.flags4 & CFG4speed)          // if speed optimization 
    3082         {   c3 = gen2(c3,0xD1,modregrm(3,5,CX));        // SHR CX,1 
     3158        {   c3 = gen2(c3,0xD1,(rex << 16) | modregrm(3,5,CX));        // SHR CX,1 
    30833159            gen1(c3,0xF3);                              // REPE 
    30843160            gen1(c3,0xA5);                              // MOVSW 
    3085             gen2(c3,0x11,modregrm(3,CX,CX));            // ADC CX,CX 
     3161            gen2(c3,0x11,(rex << 16) | modregrm(3,CX,CX));            // ADC CX,CX 
    30863162        } 
    30873163        c3 = gen1(c3,0xF3);                             // REPE 
    30883164        gen1(c3,0xA4);                                  // MOVSB 
    30893165        if (need_DS) 
    30903166            gen1(c3,0x1F);                              // POP DS 
    30913167    } 
    30923168    return cat4(c1,c2,c3,fixresult(e,mES|mAX,pretregs)); 
    30933169} 
    30943170 
    30953171 
    30963172/********************************* 
    30973173 * Generate code for memset(s,val,n) intrinsic. 
    30983174 *      (s OPmemset (n OPparam val)) 
    30993175 */ 
    31003176 
    31013177#if 1 
    31023178code *cdmemset(elem *e,regm_t *pretregs) 
    31033179{   code *c1,*c2,*c3 = NULL,*c4; 
    31043180    regm_t retregs1; 
    31053181    regm_t retregs2; 
    31063182    regm_t retregs3; 
    31073183    unsigned reg,vreg; 
    31083184    tym_t ty1; 
    31093185    elem *e2,*e1; 
    31103186    int segreg; 
    31113187    unsigned remainder; 
    31123188    targ_uns numbytes,numwords; 
    31133189    int op; 
    3114     targ_uns value; 
     3190    targ_size_t value; 
    31153191 
    31163192    //printf("cdmemset(*pretregs = x%x)\n", *pretregs); 
    31173193    e1 = e->E1; 
    31183194    e2 = e->E2; 
    31193195    assert(e2->Eoper == OPparam); 
     3196 
     3197    unsigned char rex = I64 ? REX_W : 0; 
    31203198 
    31213199    if (e2->E2->Eoper == OPconst) 
    31223200    { 
    31233201        value = el_tolong(e2->E2); 
    31243202        value &= 0xFF; 
    31253203        value |= value << 8; 
    31263204        value |= value << 16; 
     3205        value |= value << 32; 
    31273206    } 
    31283207 
    31293208    if (e2->E1->Eoper == OPconst) 
    31303209    { 
    31313210        numbytes = el_tolong(e2->E1); 
    3132         if (numbytes <= REP_THRESHOLD && I32 && // doesn't work for 16 bits 
     3211        if (numbytes <= REP_THRESHOLD && 
     3212            !I16 &&                     // doesn't work for 16 bits 
    31333213            e2->E2->Eoper == OPconst) 
    31343214        { 
    31353215            targ_uns offset = 0; 
    31363216            retregs1 = *pretregs; 
    31373217            if (!retregs1) 
    31383218                retregs1 = ALLREGS; 
    31393219            c1 = codelem(e->E1,&retregs1,FALSE); 
    31403220            reg = findreg(retregs1); 
    31413221            if (e2->E2->Eoper == OPconst) 
    31423222            { 
    31433223                switch (numbytes) 
    31443224                { 
    31453225                    case 4:                     // MOV [reg],imm32 
    3146                         c3 = genc2(CNIL,0xC7,modregrm(0,0,reg),value); 
     3226                        c3 = genc2(CNIL,0xC7,modregrmx(0,0,reg),value); 
    31473227                        goto fixres; 
    31483228                    case 2:                     // MOV [reg],imm16 
    3149                         c3 = genc2(CNIL,0xC7,modregrm(0,0,reg),value); 
     3229                        c3 = genc2(CNIL,0xC7,modregrmx(0,0,reg),value); 
    31503230                        c3->Iflags = CFopsize; 
    31513231                        goto fixres; 
    31523232                    case 1:                     // MOV [reg],imm8 
    3153                         c3 = genc2(CNIL,0xC6,modregrm(0,0,reg),value); 
     3233                        c3 = genc2(CNIL,0xC6,modregrmx(0,0,reg),value); 
    31543234                        goto fixres; 
    31553235                } 
    31563236            } 
    31573237 
    3158             c1 = regwithvalue(c1, BYTEREGS & ~retregs1, value, &vreg, 0); 
     3238            c1 = regwithvalue(c1, BYTEREGS & ~retregs1, value, &vreg, I64 ? 64 : 0); 
    31593239            freenode(e2->E2); 
    31603240            freenode(e2); 
    31613241 
    31623242            while (numbytes >= REGSIZE) 
    31633243            {                           // MOV dword ptr offset[reg],vreg 
    3164                 c2 = gen2(CNIL,0x89,modregrm(2,vreg,reg)); 
     3244                c2 = gen2(CNIL,0x89,(rex << 16) | modregxrmx(2,vreg,reg)); 
    31653245                c2->IEVoffset1 = offset; 
    31663246                c2->IFL1 = FLconst; 
    31673247                numbytes -= REGSIZE; 
    31683248                offset += REGSIZE; 
    31693249                c3 = cat(c3,c2); 
    31703250            } 
     3251            if (numbytes & 4) 
     3252            {                           // MOV dword ptr offset[reg],vreg 
     3253                c2 = gen2(CNIL,0x89,modregxrmx(2,vreg,reg)); 
     3254                c2->IEVoffset1 = offset; 
     3255                c2->IFL1 = FLconst; 
     3256                offset += 4; 
     3257                c3 = cat(c3,c2); 
     3258            } 
    31713259            if (numbytes & 2) 
    31723260            {                           // MOV word ptr offset[reg],vreg 
    3173                 c2 = gen2(CNIL,0x89,modregrm(2,vreg,reg)); 
     3261                c2 = gen2(CNIL,0x89,modregxrmx(2,vreg,reg)); 
    31743262                c2->IEVoffset1 = offset; 
    31753263                c2->IFL1 = FLconst; 
    31763264                c2->Iflags = CFopsize; 
    31773265                offset += 2; 
    31783266                c3 = cat(c3,c2); 
    31793267            } 
    31803268            if (numbytes & 1) 
    31813269            {                           // MOV byte ptr offset[reg],vreg 
    3182                 c2 = gen2(CNIL,0x88,modregrm(2,vreg,reg)); 
     3270                c2 = gen2(CNIL,0x88,modregxrmx(2,vreg,reg)); 
    31833271                c2->IEVoffset1 = offset; 
    31843272                c2->IFL1 = FLconst; 
    31853273                c3 = cat(c3,c2); 
    31863274            } 
    31873275fixres: 
    31883276            return cat3(c1,c3,fixresult(e,retregs1,pretregs)); 
    31893277        } 
    31903278    } 
    31913279 
    31923280    // Get nbytes into CX 
    31933281    retregs2 = mCX; 
    3194     if (I32 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 
     3282    if (!I16 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 
    31953283    { 
    31963284        remainder = numbytes & (REGSIZE - 1); 
    31973285        numwords  = numbytes / REGSIZE;         // number of words 
    31983286        op = 0xAB;                              // moving by words 
    31993287        c1 = getregs(mCX); 
    3200         c1 = movregconst(c1,CX,numwords,0);     // # of bytes/words 
     3288        c1 = movregconst(c1,CX,numwords,I64?64:0);     // # of bytes/words 
    32013289    } 
    32023290    else 
    32033291    { 
    32043292        remainder = 0; 
    32053293        op = 0xAA;                              // must move by bytes 
    32063294        c1 = codelem(e2->E1,&retregs2,FALSE); 
    32073295    } 
    32083296 
    32093297    // Get val into AX 
    32103298 
    32113299    retregs3 = mAX; 
    3212     if (I32 && e2->E2->Eoper == OPconst) 
     3300    if (!I16 && e2->E2->Eoper == OPconst) 
    32133301    { 
    3214         c1 = regwithvalue(c1, mAX, value, NULL, 0); 
     3302        c1 = regwithvalue(c1, mAX, value, NULL, I64?64:0); 
    32153303        freenode(e2->E2); 
    32163304    } 
    32173305    else 
    32183306    { 
    32193307        c1 = cat(c1,scodelem(e2->E2,&retregs3,retregs2,FALSE)); 
    32203308#if 0 
    32213309        if (I32) 
    32223310        { 
    32233311            c1 = gen2(c1,0x8A,modregrm(3,AH,AL));       // MOV AH,AL 
    32243312            c1 = genc2(c1,0xC1,modregrm(3,4,AX),8);     // SHL EAX,8 
    32253313            c1 = gen2(c1,0x8A,modregrm(3,AL,AH));       // MOV AL,AH 
    32263314            c1 = genc2(c1,0xC1,modregrm(3,4,AX),8);     // SHL EAX,8 
    32273315            c1 = gen2(c1,0x8A,modregrm(3,AL,AH));       // MOV AL,AH 
    32283316        } 
    32293317#endif 
    32303318    } 
    32313319    freenode(e2); 
    32323320 
    32333321    // Get s into ES:DI 
    32343322    retregs1 = mDI; 
    32353323    ty1 = e->E1->Ety; 
    32363324    if (!tyreg(ty1)) 
    32373325        retregs1 |= mES; 
    32383326    c1 = cat(c1,scodelem(e->E1,&retregs1,retregs2 | retregs3,FALSE)); 
    32393327    reg = DI; //findreg(retregs1); 
    32403328 
    32413329    // Make sure ES contains proper segment value 
    32423330    c2 = cod2_setES(ty1); 
    32433331 
    32443332    c3 = NULL; 
    32453333    if (*pretregs)                              // if need return value 
    32463334    {   c3 = getregs(mBX); 
    32473335        c3 = genmovreg(c3,BX,DI); 
     3336        code_orrex(c3,rex); 
    32483337    } 
    32493338 
    32503339    c3 = cat(c3,getregs(mDI | mCX)); 
    3251     if (!I32 && config.flags4 & CFG4speed)      // if speed optimization 
     3340    if (I16 && config.flags4 & CFG4speed)      // if speed optimization 
    32523341    { 
    32533342        c3 = cat(c3,getregs(mAX)); 
    32543343        c3 = gen2(c3,0x8A,modregrm(3,AH,AL));   // MOV AH,AL 
    32553344        gen2(c3,0xD1,modregrm(3,5,CX));         // SHR CX,1 
    32563345        gen1(c3,0xF3);                          // REP 
    32573346        gen1(c3,0xAB);                          // STOSW 
    32583347        gen2(c3,0x11,modregrm(3,CX,CX));        // ADC CX,CX 
    32593348        op = 0xAA; 
    32603349    } 
    32613350 
    32623351    c3 = gen1(c3,0xF3);                         // REP 
    32633352    gen1(c3,op);                                // STOSD 
     3353    if (remainder & 4) 
     3354    { 
     3355        code *ctmp; 
     3356        ctmp = gen2(CNIL,0x89,modregrmx(2,AX,reg)); 
     3357        ctmp->IFL1 = FLconst; 
     3358        c3 = cat(c3,ctmp); 
     3359    } 
    32643360    if (remainder & 2) 
    32653361    { 
    32663362        code *ctmp; 
    3267         ctmp = gen2(CNIL,0x89,modregrm(2,AX,reg)); 
     3363        ctmp = gen2(CNIL,0x89,modregrmx(2,AX,reg)); 
    32683364        ctmp->Iflags = CFopsize; 
     3365        ctmp->IEVoffset1 = remainder & 4; 
    32693366        ctmp->IFL1 = FLconst; 
    32703367        c3 = cat(c3,ctmp); 
    32713368    } 
    32723369    if (remainder & 1) 
    32733370    { 
    32743371        code *ctmp; 
    3275         ctmp = gen2(CNIL,0x88,modregrm(2,AX,reg)); 
    3276         ctmp->IEVoffset1 = (remainder & 2) ? 2 : 0
     3372        ctmp = gen2(CNIL,0x88,modregrmx(2,AX,reg)); 
     3373        ctmp->IEVoffset1 = remainder & ~1
    32773374        ctmp->IFL1 = FLconst; 
    32783375        c3 = cat(c3,ctmp); 
    32793376    } 
    32803377    regimmed_set(CX,0); 
    32813378    return cat4(c1,c2,c3,fixresult(e,mES|mBX,pretregs)); 
    32823379} 
    32833380#else 
    32843381// BUG: Pat made many improvements in the linux version, I need 
    32853382// to verify they work for 16 bits and fold them in. -Walter 
    32863383 
    32873384code *cdmemset(elem *e,regm_t *pretregs) 
    32883385{   code *c1,*c2,*c3 = NULL,*c4; 
    32893386    regm_t retregs1; 
    32903387    regm_t retregs2; 
    32913388    regm_t retregs3; 
    32923389    tym_t ty1; 
    32933390    elem *e2; 
    32943391    targ_size_t value; 
    32953392 
    32963393    /* 
     
    33493445    return cat4(c1,c2,c3,fixresult(e,mES|mBX,pretregs)); 
    33503446} 
    33513447#endif 
    33523448 
    33533449 
    33543450/********************** 
    33553451 * Do structure assignments. 
    33563452 * This should be fixed so that (s1 = s2) is rewritten to (&s1 = &s2). 
    33573453 * Mebbe call cdstreq() for double assignments??? 
    33583454 */ 
    33593455 
    33603456code *cdstreq(elem *e,regm_t *pretregs) 
    33613457{ code *c1,*c2,*c3; 
    33623458  code *c1a; 
    33633459  regm_t srcregs,dstregs;               /* source & destination reg masks */ 
    33643460  targ_uns numbytes; 
    33653461  char need_DS = FALSE; 
    33663462  elem *e1 = e->E1,*e2 = e->E2; 
    33673463  int segreg; 
    33683464 
    3369   numbytes = e->Enumbytes;              /* # of bytes in structure/union */ 
     3465    numbytes = e->Enumbytes;              // # of bytes in structure/union 
     3466    unsigned char rex = I64 ? REX_W : 0; 
    33703467 
    33713468    //printf("cdstreq(e = %p, *pretregs = x%x)\n", e, *pretregs); 
    33723469 
    33733470    /* First, load pointer to rvalue into SI                            */ 
    33743471    srcregs = mSI;                      /* source is DS:SI              */ 
    33753472    c1 = docommas(&e2); 
    33763473    if (e2->Eoper == OPind)             /* if (.. = *p)                 */ 
    33773474    {   elem *e21 = e2->E1; 
    33783475 
    33793476        segreg = SEG_DS; 
    33803477        switch (tybasic(e21->Ety)) 
    33813478        { 
    33823479            case TYsptr: 
    33833480                if (config.wflags & WFssneds)   /* if sptr can't use DS segment */ 
    33843481                    segreg = SEG_SS; 
    33853482                break; 
    33863483            case TYcptr: 
    33873484                if (!(config.exe & EX_flat)) 
    33883485                    segreg = SEG_CS; 
    33893486                break; 
     
    34453542  if (e1->Eoper == OPind)               /* if (*p = ..)                 */ 
    34463543  { 
    34473544        if (tyreg(e1->E1->Ety)) 
    34483545            dstregs = mDI; 
    34493546        c2 = cod2_setES(e1->E1->Ety); 
    34503547        c2 = cat(c2,scodelem(e1->E1,&dstregs,srcregs,FALSE)); 
    34513548  } 
    34523549  else 
    34533550        c2 = cdrelconst(e1,&dstregs); 
    34543551  freenode(e1); 
    34553552 
    34563553  c3 = getregs((srcregs | dstregs) & (mLSW | mDI)); 
    34573554  if (need_DS) 
    34583555  {     assert(!(config.exe & EX_flat)); 
    34593556        c3 = gen1(c3,0x1E);                     /* PUSH DS              */ 
    34603557        gen2(c3,0x8E,modregrm(3,SEG_DS,CX));    /* MOV DS,CX            */ 
    34613558  } 
    34623559  if (numbytes <= REGSIZE * (6 + (REGSIZE == 4))) 
    34633560  {     while (numbytes >= REGSIZE) 
    34643561        {   c3 = gen1(c3,0xA5);         /* MOVSW                        */ 
     3562            code_orrex(c3, rex); 
    34653563            numbytes -= REGSIZE; 
    34663564        } 
    34673565        //if (numbytes) 
    34683566        //    printf("cdstreq numbytes %d\n",numbytes); 
    34693567        while (numbytes--) 
    34703568            c3 = gen1(c3,0xA4);         /* MOVSB                        */ 
    34713569  } 
    34723570    else 
    34733571    { 
    34743572#if 1 
    34753573        unsigned remainder; 
    34763574 
    34773575        remainder = numbytes & (REGSIZE - 1); 
    34783576        numbytes /= REGSIZE;            // number of words 
    34793577        c3 = cat(c3,getregs_imm(mCX)); 
    34803578        c3 = movregconst(c3,CX,numbytes,0);     // # of bytes/words 
    34813579        gen1(c3,0xF3);                          // REP 
    34823580        gen1(c3,0xA5);                  // REP MOVSD 
    34833581        regimmed_set(CX,0);             // note that CX == 0 
    34843582        for (; remainder; remainder--) 
     
    34913589        if (numbytes & (REGSIZE - 1))   /* if odd                       */ 
    34923590                movs = 0xA4;            /* MOVSB                        */ 
    34933591        else 
    34943592        {       movs = 0xA5;            /* MOVSW                        */ 
    34953593                numbytes /= REGSIZE;    /* # of words                   */ 
    34963594        } 
    34973595        c3 = cat(c3,getregs_imm(mCX)); 
    34983596        c3 = movregconst(c3,CX,numbytes,0);     /* # of bytes/words     */ 
    34993597        gen1(c3,0xF3);                          /* REP                  */ 
    35003598        gen1(c3,movs); 
    35013599        regimmed_set(CX,0);             /* note that CX == 0            */ 
    35023600#endif 
    35033601    } 
    35043602    if (need_DS) 
    35053603        gen1(c3,0x1F);                          // POP  DS 
    35063604    assert(!(*pretregs & mPSW)); 
    35073605    if (*pretregs) 
    35083606    {   /* ES:DI points past what we want       */ 
    35093607        regm_t retregs; 
    35103608 
    3511         genc2(c3,0x81,modregrm(3,5,DI),e->Enumbytes);   /* SUB DI,numbytes */ 
     3609        genc2(c3,0x81,(rex << 16) | modregrm(3,5,DI),e->Enumbytes);   // SUB DI,numbytes 
    35123610        retregs = mDI; 
    35133611        if (*pretregs & mMSW && !(config.exe & EX_flat)) 
    35143612            retregs |= mES; 
    35153613        c3 = cat(c3,fixresult(e,retregs,pretregs)); 
    35163614    } 
    35173615    return cat3(c1,c2,c3); 
    35183616} 
    35193617 
    35203618 
    35213619/********************** 
    35223620 * Get the address of. 
    35233621 * Is also called by cdstreq() to set up pointer to a structure. 
    35243622 */ 
    35253623 
    35263624code *cdrelconst(elem *e,regm_t *pretregs) 
    35273625{ code *c,*c1; 
    35283626  enum SC sclass; 
    35293627  unsigned mreg,                /* segment of the address (TYfptrs only) */ 
    35303628        lreg;                   /* offset of the address                */ 
    35313629  tym_t tym; 
     
    36203718            fl = s->Sfl; 
    36213719            if (s->ty() & mTYcs) 
    36223720                fl = FLcsdata; 
    36233721            c = gen2(c,0x8C,            /* MOV mreg,SEG REGISTER        */ 
    36243722                modregrm(3,segfl[fl],mreg)); 
    36253723        } 
    36263724        if (*pretregs & mES) 
    36273725                gen2(c,0x8E,modregrm(3,0,mreg));        /* MOV ES,mreg  */ 
    36283726  } 
    36293727  return cat(c,getoffset(e,lreg)); 
    36303728} 
    36313729 
    36323730/********************************* 
    36333731 * Load the offset portion of the address represented by e into 
    36343732 * reg. 
    36353733 */ 
    36363734 
    36373735code *getoffset(elem *e,unsigned reg) 
    36383736{ code cs; 
    36393737  code *c; 
    3640   enum FL fl; 
    36413738 
    36423739  cs.Iflags = 0; 
    3643   cs.Irex = 0; 
     3740  unsigned char rex = I64 ? REX_W : 0; 
     3741  cs.Irex = rex; 
    36443742  assert(e->Eoper == OPvar || e->Eoper == OPrelconst); 
    3645   fl = el_fl(e); 
     3743  enum FL fl = el_fl(e); 
    36463744  switch (fl) 
    36473745  { 
    36483746    case FLdatseg: 
    36493747        cs.IEV2._EP.Vpointer = e->EV.Vpointer; 
    36503748        goto L3; 
    36513749 
    36523750    case FLfardata: 
    36533751        assert(!TARGET_FLAT); 
    36543752        goto L4; 
    36553753 
    36563754    case FLtlsdata: 
    36573755#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    36583756    {   /* Generate: 
    36593757         *      MOV reg,GS:[00000000] 
    36603758         *      ADD reg, offset s@TLS_LE 
    36613759         * for locals, and for globals: 
    36623760         *      MOV reg,GS:[00000000] 
    36633761         *      ADD reg, s@TLS_IE 
    36643762         * note different fixup 
    36653763         */ 
    36663764      L5: 
    36673765        int stack = 0; 
    36683766        c = NULL; 
    36693767        if (reg == STACK) 
    36703768        {   regm_t retregs = ALLREGS; 
    36713769 
    36723770            c = allocreg(&retregs,&reg,TYoffset); 
    36733771            reg = findreg(retregs); 
    36743772            stack = 1; 
    36753773        } 
    36763774 
    36773775        code css; 
     3776        css.Irex = rex; 
    36783777        css.Iop = 0x8B; 
    3679         css.Irm = modregrm(0, reg, BPRM); 
     3778        css.Irm = modregrm(0, 0, BPRM); 
     3779        code_newreg(&css, reg); 
    36803780        css.Iflags = CFgs; 
    3681         css.Irex = 0; 
    36823781        css.IFL1 = FLconst; 
    36833782        css.IEV1.Vuns = 0; 
    36843783        c = gen(c, &css);               // MOV reg,GS:[00000000] 
    36853784 
    36863785        if (e->EV.sp.Vsym->Sclass == SCstatic || e->EV.sp.Vsym->Sclass == SClocstat) 
    36873786        {   // ADD reg, offset s 
     3787            cs.Irex = rex; 
    36883788            cs.Iop = 0x81; 
    3689             cs.Irm = modregrm(3,0,reg); 
     3789            cs.Irm = modregrm(3,0,reg & 7); 
     3790            if (reg & 8) 
     3791                cs.Irex |= REX_B; 
    36903792            cs.Iflags = CFoff; 
    3691             css.Irex = 0; 
    36923793            cs.IFL2 = fl; 
    36933794            cs.IEVsym2 = e->EV.sp.Vsym; 
    36943795            cs.IEVoffset2 = e->EV.sp.Voffset; 
    36953796        } 
    36963797        else 
    36973798        {   // ADD reg, s 
     3799            cs.Irex = rex; 
    36983800            cs.Iop = 0x03; 
    3699             cs.Irm = modregrm(0,reg,BPRM); 
     3801            cs.Irm = modregrm(0,0,BPRM); 
     3802            code_newreg(&cs, reg); 
    37003803            cs.Iflags = CFoff; 
    3701             css.Irex = 0; 
    37023804            cs.IFL1 = fl; 
    37033805            cs.IEVsym1 = e->EV.sp.Vsym; 
    37043806            cs.IEVoffset1 = e->EV.sp.Voffset; 
    37053807        } 
    37063808        c = gen(c, &cs);                // ADD reg, xxxx 
    37073809 
    37083810        if (stack) 
    37093811        { 
    3710             c = gen1(c,0x50 + reg);                     /* PUSH reg     */ 
     3812            c = gen1(c,0x50 + (reg & 7));      // PUSH reg 
     3813            if (reg & 8) 
     3814                code_orrex(c, REX_B); 
    37113815            c = genadjesp(c,REGSIZE); 
    37123816            stackchanged = 1; 
    37133817        } 
    37143818        break; 
    37153819    } 
    37163820#else 
    37173821        goto L4; 
    37183822#endif 
    37193823 
    37203824    case FLfunc: 
    37213825        fl = FLextern;                  /* don't want PC relative addresses */ 
    37223826        goto L4; 
    37233827 
    37243828    case FLextern: 
    37253829#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    37263830        if (e->EV.sp.Vsym->ty() & mTYthread) 
    37273831            goto L5; 
    37283832#endif 
    37293833    case FLdata: 
    37303834    case FLudata: 
    37313835#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    37323836    case FLgot: 
    37333837    case FLgotoff: 
    37343838#endif 
    37353839    case FLcsdata: 
    37363840    L4: 
    37373841        cs.IEVsym2 = e->EV.sp.Vsym; 
    37383842        cs.IEVoffset2 = e->EV.sp.Voffset; 
    37393843    L3: 
    37403844        if (reg == STACK) 
    37413845        {   stackchanged = 1; 
    37423846            cs.Iop = 0x68;              /* PUSH immed16                 */ 
    37433847            c = genadjesp(NULL,REGSIZE); 
    37443848        } 
    37453849        else 
    3746         {   cs.Iop = 0xB8 + reg;        /* MOV reg,immed16              */ 
     3850        {   cs.Iop = 0xB8 + (reg & 7);  // MOV reg,immed16 
     3851            if (reg & 8) 
     3852                cs.Irex |= REX_B; 
    37473853            c = NULL; 
    37483854        } 
    37493855        cs.Iflags = CFoff;              /* want offset only             */ 
    37503856        cs.IFL2 = fl; 
    37513857        c = gen(c,&cs); 
    37523858        break; 
    37533859 
    37543860#if 0 && TARGET_LINUX 
    37553861    case FLgot: 
    37563862    case FLgotoff: 
    37573863        { 
    37583864        gotref = 1; 
    37593865        symbol *s = e->EV.sp.Vsym; 
    37603866        // When using 8B (MOV), indicating that rm is used 
    37613867        // rm operands are always placed in IEV1 not IEV2 
    37623868        cs.IEVsym1 = s; 
    37633869        cs.IEVoffset1 = e->EV.sp.Voffset; 
    37643870        cs.Irm = modregrm(2,reg,BX);    // reg,disp32[EBX] 
    37653871        cs.IFL1 = fl; 
    37663872        cs.Iop = (fl == FLgotoff) 
     
    37743880 
    37753881    case FLreg: 
    37763882        /* Allow this since the tree optimizer puts & in front of       */ 
    37773883        /* register doubles.                                            */ 
    37783884        goto L2; 
    37793885    case FLauto: 
    37803886    case FLtmp: 
    37813887    case FLbprel: 
    37823888    case FLfltreg: 
    37833889        reflocal = TRUE; 
    37843890        goto L2; 
    37853891    case FLpara: 
    37863892        refparam = TRUE; 
    37873893    L2: 
    37883894        if (reg == STACK) 
    37893895        {   regm_t retregs = ALLREGS; 
    37903896 
    37913897            c = allocreg(&retregs,&reg,TYoffset); 
    37923898            reg = findreg(retregs); 
    37933899            c = cat(c,loadea(e,&cs,0x8D,reg,0,0,0));    /* LEA reg,EA   */ 
    3794             c = gen1(c,0x50 + reg);                     /* PUSH reg     */ 
     3900            c = gen1(c,0x50 + (reg & 7));               // PUSH reg 
     3901            if (reg & 8) 
     3902                code_orrex(c, REX_B); 
    37953903            c = genadjesp(c,REGSIZE); 
    37963904            stackchanged = 1; 
    37973905        } 
    37983906        else 
    37993907            c = loadea(e,&cs,0x8D,reg,0,0,0);   /* LEA reg,EA           */ 
    38003908        break; 
    38013909    default: 
    38023910#ifdef DEBUG 
    38033911        elem_print(e); 
    38043912        debugx(WRFL(fl)); 
    38053913#endif 
    38063914        assert(0); 
    38073915  } 
    38083916  return c; 
    38093917} 
    38103918 
    38113919 
    38123920/****************** 
    38133921 * Negate, sqrt operator 
    38143922 */ 
    38153923 
    38163924code *cdneg(elem *e,regm_t *pretregs) 
    38173925{ unsigned byte; 
    38183926  regm_t retregs,possregs; 
    38193927  int reg; 
    38203928  int sz; 
    38213929  tym_t tyml; 
    38223930  code *c,*c1,*cg; 
    38233931 
    38243932  //printf("cdneg()\n"); 
    38253933  //elem_print(e); 
    38263934  if (*pretregs == 0) 
    38273935        return codelem(e->E1,pretregs,FALSE); 
    38283936  tyml = tybasic(e->E1->Ety); 
    38293937  sz = tysize[tyml]; 
    38303938  if (tyfloating(tyml)) 
    38313939  {     if (tycomplex(tyml)) 
    38323940            return neg_complex87(e, pretregs); 
    3833         if (config.inline8087 && ((*pretregs & (ALLREGS | mBP)) == 0 || e->Eoper == OPsqrt)) 
     3941        if (config.inline8087 && 
     3942            ((*pretregs & (ALLREGS | mBP)) == 0 || e->Eoper == OPsqrt || I64)) 
    38343943                return neg87(e,pretregs); 
    3835         retregs = (!I32 && sz == 8) ? DOUBLEREGS_16 : ALLREGS; 
     3944        retregs = (I16 && sz == 8) ? DOUBLEREGS_16 : ALLREGS; 
    38363945        c1 = codelem(e->E1,&retregs,FALSE); 
    38373946        c1 = cat(c1,getregs(retregs)); 
    38383947        if (I32) 
    38393948        {   reg = (sz == 8) ? findregmsw(retregs) : findreg(retregs); 
    38403949            c1 = genc2(c1,0x81,modregrm(3,6,reg),0x80000000); /* XOR EDX,sign bit */ 
    38413950        } 
    38423951        else 
    38433952        {   reg = (sz == 8) ? AX : findregmsw(retregs); 
    38443953            c1 = genc2(c1,0x81,modregrm(3,6,reg),0x8000);     /* XOR AX,0x8000 */ 
    38453954        } 
    38463955        return cat(c1,fixresult(e,retregs,pretregs)); 
    38473956  } 
    38483957 
    38493958  byte = sz == 1; 
    38503959  possregs = (byte) ? BYTEREGS : allregs; 
    38513960  retregs = *pretregs & possregs; 
    38523961  if (retregs == 0) 
    38533962        retregs = possregs; 
    38543963  c1 = codelem(e->E1,&retregs,FALSE); 
    38553964  cg = getregs(retregs);                /* retregs will be destroyed    */ 
    38563965  if (sz <= REGSIZE) 
    3857   {     unsigned reg; 
    3858  
    3859         reg = findreg(retregs)
    3860         c = gen2(CNIL,0xF7 ^ byte,modregrm(3,3,reg));   /* NEG reg      */ 
    3861         if (I32 && tysize[tyml] == SHORTSIZE && *pretregs & mPSW) 
     3966  { 
     3967        unsigned reg = findreg(retregs); 
     3968        unsigned rex = (I64 && sz == 8) ? REX_W : 0
     3969        c = gen2(CNIL,0xF7 ^ byte,(rex << 16) | modregrmx(3,3,reg));   // NEG reg 
     3970        if (!I16 && tysize[tyml] == SHORTSIZE && *pretregs & mPSW) 
    38623971            c->Iflags |= CFopsize | CFpsw; 
    38633972        *pretregs &= mBP | ALLREGS;             // flags already set 
    38643973  } 
    38653974  else if (sz == 2 * REGSIZE) 
    38663975  {     unsigned msreg,lsreg; 
    38673976 
    38683977        msreg = findregmsw(retregs); 
    38693978        c = gen2(CNIL,0xF7,modregrm(3,3,msreg)); /* NEG msreg           */ 
    38703979        lsreg = findreglsw(retregs); 
    38713980        gen2(c,0xF7,modregrm(3,3,lsreg));       /* NEG lsreg            */ 
    38723981        genc2(c,0x81,modregrm(3,3,msreg),0);    /* SBB msreg,0          */ 
    38733982  } 
    38743983  else 
    38753984        assert(0); 
    38763985  return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 
    38773986} 
    38783987 
    38793988 
    38803989/****************** 
    38813990 * Absolute value operator 
    38823991 */ 
    38833992 
    38843993code *cdabs( elem *e, regm_t *pretregs) 
    38853994{ unsigned byte; 
    38863995  regm_t retregs,possregs; 
    38873996  int reg; 
    38883997  tym_t tyml; 
    38893998  code *c,*c1,*cg; 
    3890   int sz; 
    38913999 
    38924000  if (*pretregs == 0) 
    38934001        return codelem(e->E1,pretregs,FALSE); 
    38944002  tyml = tybasic(e->E1->Ety); 
    3895   sz = tysize[tyml]; 
     4003  int sz = tysize[tyml]; 
     4004  unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
    38964005  if (tyfloating(tyml)) 
    3897   {     if (config.inline8087 && (*pretregs & (ALLREGS | mBP)) == 0
     4006  {     if (config.inline8087 && ((*pretregs & (ALLREGS | mBP)) == 0 || I64)
    38984007                return neg87(e,pretregs); 
    38994008        retregs = (!I32 && sz == 8) ? DOUBLEREGS_16 : ALLREGS; 
    39004009        c1 = codelem(e->E1,&retregs,FALSE); 
    39014010        /*cg = callclib(e,CLIBdneg,pretregs,0);*/ 
    39024011        c1 = cat(c1,getregs(retregs)); 
    39034012        if (I32) 
    39044013        {   reg = (sz == 8) ? findregmsw(retregs) : findreg(retregs); 
    39054014            c1 = genc2(c1,0x81,modregrm(3,4,reg),0x7FFFFFFF); /* AND EDX,~sign bit */ 
    39064015        } 
    39074016        else 
    39084017        {   reg = (sz == 8) ? AX : findregmsw(retregs); 
    39094018            c1 = genc2(c1,0x81,modregrm(3,4,reg),0x7FFF);     /* AND AX,0x7FFF */ 
    39104019        } 
    39114020        return cat(c1,fixresult(e,retregs,pretregs)); 
    39124021  } 
    39134022 
    39144023  byte = sz == 1; 
    39154024  assert(byte == 0); 
    39164025  byte = 0; 
    39174026  possregs = (sz <= REGSIZE) ? mAX : allregs; 
    39184027  retregs = *pretregs & possregs; 
    39194028  if (retregs == 0) 
    39204029        retregs = possregs; 
    39214030  c1 = codelem(e->E1,&retregs,FALSE); 
    39224031  cg = getregs(retregs);                /* retregs will be destroyed    */ 
    39234032  if (sz <= REGSIZE) 
    39244033  {     unsigned reg; 
    39254034        code *c2; 
    39264035 
    39274036        /*      cwd 
    39284037                xor     AX,DX 
    39294038                sub     AX,DX 
    39304039         */ 
    39314040 
    39324041        cg = cat(cg,getregs(mDX)); 
    39334042        reg = findreg(retregs); 
    3934         if (I32 && sz == SHORTSIZE) 
     4043        if (!I16 && sz == SHORTSIZE) 
    39354044            cg = gen1(cg,0x98);                         // CWDE 
    39364045        cg = gen1(cg,0x99);                             // CWD 
    3937         gen2(cg,0x33 ^ byte,modregrm(3,AX,DX));         // XOR EAX,EDX 
    3938         c = gen2(CNIL,0x2B ^ byte,modregrm(3,AX,DX));   // SUB EAX,EDX 
    3939         if (I32 && sz == SHORTSIZE && *pretregs & mPSW) 
     4046        code_orrex(cg, rex); 
     4047        gen2(cg,0x33 ^ byte,(rex << 16) | modregrm(3,AX,DX));         // XOR EAX,EDX 
     4048        c = gen2(CNIL,0x2B ^ byte,(rex << 16) | modregrm(3,AX,DX));   // SUB EAX,EDX 
     4049        if (!I16 && sz == SHORTSIZE && *pretregs & mPSW) 
    39404050            c->Iflags |= CFopsize | CFpsw; 
    39414051        if (*pretregs & mPSW) 
    39424052            c->Iflags |= CFpsw; 
    39434053        *pretregs &= ~mPSW;                     // flags already set 
    39444054  } 
    39454055  else if (sz == 2 * REGSIZE) 
    39464056  {     unsigned msreg,lsreg; 
    39474057        code *cnop; 
    39484058 
    39494059        /*      tst     DX 
    39504060                jns     L2 
    39514061                neg     DX 
    39524062                neg     AX 
    39534063                sbb     DX,0 
    39544064            L2: 
    39554065         */ 
    39564066 
    39574067        cnop = gennop(CNIL); 
    39584068        msreg = findregmsw(retregs); 
    39594069        lsreg = findreglsw(retregs); 
     
    39754084 */ 
    39764085 
    39774086code *cdpost(elem *e,regm_t *pretregs) 
    39784087{ code cs,*c1,*c2,*c3,*c4,*c5,*c6; 
    39794088  unsigned reg,op,byte; 
    39804089  tym_t tyml; 
    39814090  regm_t retregs,possregs,idxregs; 
    39824091  targ_int n; 
    39834092  elem *e2; 
    39844093  int sz; 
    39854094  int stackpushsave; 
    39864095 
    39874096  retregs = *pretregs; 
    39884097  op = e->Eoper;                                /* OPxxxx               */ 
    39894098  if (retregs == 0)                             /* if nothing to return */ 
    39904099        return cdaddass(e,pretregs); 
    39914100  c4 = c5 = CNIL; 
    39924101  tyml = tybasic(e->E1->Ety); 
    39934102  sz = tysize[tyml]; 
    39944103  e2 = e->E2; 
     4104  unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
    39954105 
    39964106  if (tyfloating(tyml)) 
    39974107  { 
    39984108#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    39994109        return post87(e,pretregs); 
    40004110#else 
    40014111        if (config.inline8087) 
    40024112                return post87(e,pretregs); 
    40034113        assert(sz <= 8); 
    40044114        c1 = getlvalue(&cs,e->E1,DOUBLEREGS); 
    40054115        freenode(e->E1); 
    4006         idxregs = idxregm(cs.Irm,cs.Isib); /* mask of index regs used   */ 
     4116        idxregs = idxregm(&cs);         // mask of index regs used 
    40074117        cs.Iop = 0x8B;                  /* MOV DOUBLEREGS,EA            */ 
    40084118        c2 = fltregs(&cs,tyml); 
    40094119        stackchanged = 1; 
    40104120        stackpushsave = stackpush; 
    40114121        if (sz == 8) 
    40124122        { 
    40134123            if (I32) 
    40144124            { 
    40154125                gen1(c2,0x50 + DX);             /* PUSH DOUBLEREGS      */ 
    40164126                gen1(c2,0x50 + AX); 
    40174127                stackpush += DOUBLESIZE; 
    40184128                retregs = DOUBLEREGS2_32; 
    40194129            } 
    40204130            else 
    40214131            { 
    40224132                gen1(c2,0x50 + AX); 
    40234133                gen1(c2,0x50 + BX); 
    40244134                gen1(c2,0x50 + CX); 
    40254135                gen1(c2,0x50 + DX);             /* PUSH DOUBLEREGS      */ 
    40264136                stackpush += DOUBLESIZE + DOUBLESIZE; 
     
    40814191            } 
    40824192        } 
    40834193        else 
    40844194        {   gen1(c5,0x58 + AX); 
    40854195            if (!I32) 
    40864196                gen1(c5,0x58 + DX); 
    40874197            stackpush -= FLOATSIZE; 
    40884198            retregs = FLOATREGS; 
    40894199        } 
    40904200        c5 = genadjesp(c5,stackpush - stackpushsave); 
    40914201        c6 = fixresult(e,retregs,pretregs); 
    40924202        return cat6(c1,c2,c3,c4,c5,c6); 
    40934203#endif 
    40944204  } 
    40954205 
    40964206  assert(e2->Eoper == OPconst); 
    40974207  byte = (sz == 1); 
    40984208  possregs = byte ? BYTEREGS : allregs; 
    40994209  c1 = getlvalue(&cs,e->E1,0); 
    41004210  freenode(e->E1); 
    4101   idxregs = idxregm(cs.Irm,cs.Isib);    /* mask of index regs used      */ 
     4211  idxregs = idxregm(&cs);       // mask of index regs used 
    41024212  if (sz <= REGSIZE && *pretregs == mPSW && (cs.Irm & 0xC0) == 0xC0 && 
    4103       (I32 || (idxregs & (mBX | mSI | mDI | mBP)))) 
     4213      (!I16 || (idxregs & (mBX | mSI | mDI | mBP)))) 
    41044214  {     // Generate: 
    41054215        //      TEST    reg,reg 
    41064216        //      LEA     reg,n[reg]      // don't affect flags 
    41074217        int rm; 
    41084218 
    41094219        reg = cs.Irm & 7; 
     4220        if (cs.Irex & REX_B) 
     4221            reg |= 8; 
    41104222        cs.Iop = 0x85 ^ byte; 
    4111         cs.Irm |= modregrm(0,reg,0); 
     4223        code_newreg(&cs, reg); 
    41124224        cs.Iflags |= CFpsw; 
    41134225        c2 = gen(NULL,&cs);             // TEST reg,reg 
    41144226 
    41154227        // If lvalue is a register variable, we must mark it as modified 
    4116         c3 = modEA(cs.Irm); 
     4228        c3 = modEA(&cs); 
    41174229 
    41184230        n = e2->EV.Vint; 
    41194231        if (op == OPpostdec) 
    41204232            n = -n; 
    41214233        rm = reg; 
    4122         if (!I32
     4234        if (I16
    41234235            rm = regtorm[reg]; 
    4124         c4 = genc1(NULL,0x8D,modregrm(2,reg,rm),FLconst,n);    // LEA reg,n[reg] 
     4236        c4 = genc1(NULL,0x8D,(rex << 16) | modregxrmx(2,reg,rm),FLconst,n); // LEA reg,n[reg] 
    41254237        return cat4(c1,c2,c3,c4); 
    41264238  } 
    41274239  else if (sz <= REGSIZE || tyfv(tyml)) 
    41284240  {     code cs2; 
    41294241 
    41304242        cs.Iop = 0x8B ^ byte; 
    41314243        retregs = possregs & ~idxregs & *pretregs; 
    41324244        if (!tyfv(tyml)) 
    41334245        {       if (retregs == 0) 
    41344246                        retregs = possregs & ~idxregs; 
    41354247        } 
    41364248        else /* tyfv(tyml) */ 
    41374249        {       if ((retregs &= mLSW) == 0) 
    41384250                        retregs = mLSW & ~idxregs; 
    41394251                /* Can't use LES if the EA uses ES as a seg override    */ 
    41404252                if (*pretregs & mES && (cs.Iflags & CFSEG) != CFes) 
    41414253                {   cs.Iop = 0xC4;                      /* LES          */ 
    41424254                    c1 = cat(c1,getregs(mES));          /* allocate ES  */ 
    41434255                } 
    41444256        } 
    41454257        c2 = allocreg(&retregs,&reg,TYint); 
    4146         cs.Irm |= modregrm(0,reg,0); 
     4258        code_newreg(&cs, reg); 
    41474259        c3 = gen(CNIL,&cs);                     /* MOV reg,EA   */ 
    41484260        cs2 = cs; 
    41494261 
    41504262        /* If lvalue is a register variable, we must mark it as modified */ 
    4151         c3 = cat(c3,modEA(cs.Irm)); 
     4263        c3 = cat(c3,modEA(&cs)); 
    41524264 
    41534265        cs.Iop = 0x81 ^ byte; 
    41544266        cs.Irm &= ~modregrm(0,7,0);             /* reg field = 0        */ 
     4267        cs.Irex &= ~REX_R; 
    41554268        if (op == OPpostdec) 
    41564269                cs.Irm |= modregrm(0,5,0);      /* SUB                  */ 
    41574270        cs.IFL2 = FLconst; 
    41584271        n = e2->EV.Vint; 
    41594272        cs.IEV2.Vint = n; 
    41604273        if (n == 1)                     /* can use INC or DEC           */ 
    41614274        {       cs.Iop |= 0xFE;         /* xFE is dec byte, xFF is word */ 
    41624275                if (op == OPpostdec) 
    41634276                        NEWREG(cs.Irm,1);       // DEC EA 
    41644277                else 
    41654278                        NEWREG(cs.Irm,0);       // INC EA 
    41664279        } 
    41674280        else if (n == -1)               // can use INC or DEC 
    41684281        {       cs.Iop |= 0xFE;         // xFE is dec byte, xFF is word 
    41694282                if (op == OPpostinc) 
    41704283                        NEWREG(cs.Irm,1);       // DEC EA 
    41714284                else 
    41724285                        NEWREG(cs.Irm,0);       // INC EA 
    41734286        } 
    41744287 
    41754288        // For scheduling purposes, we wish to replace: 
    41764289        //      MOV     reg,EA 
    41774290        //      OP      EA 
    41784291        // with: 
    41794292        //      MOV     reg,EA 
    41804293        //      OP      reg 
    41814294        //      MOV     EA,reg 
    41824295        //      ~OP     reg 
    41834296        if (sz <= REGSIZE && (cs.Irm & 0xC0) != 0xC0 && 
    41844297            config.target_cpu >= TARGET_Pentium && 
    41854298            config.flags4 & CFG4speed) 
    41864299        { 
    41874300            // Replace EA in cs with reg 
    4188             cs.Irm = (cs.Irm & ~modregrm(3,0,7)) | modregrm(3,0,reg); 
     4301            cs.Irm = (cs.Irm & ~modregrm(3,0,7)) | modregrm(3,0,reg & 7); 
     4302            if (reg & 8) 
     4303            {   cs.Irex &= ~REX_R; 
     4304                cs.Irex |= REX_B; 
     4305            } 
    41894306            gen(c3,&cs);                        // ADD/SUB reg,const 
    41904307 
    41914308            // Reverse MOV direction 
    41924309            cs2.Iop ^= 2; 
    41934310            gen(c3,&cs2);                       // MOV EA,reg 
    41944311 
    41954312            // Toggle INC <-> DEC, ADD <-> SUB 
    41964313            cs.Irm ^= (n == 1 || n == -1) ? modregrm(0,1,0) : modregrm(0,5,0); 
    41974314            gen(c3,&cs); 
    41984315 
    41994316            if (*pretregs & mPSW) 
    42004317            {   *pretregs &= ~mPSW;             // flags already set 
    42014318                code_orflag(c3,CFpsw); 
    42024319            } 
    42034320        } 
    42044321        else 
    42054322            gen(c3,&cs);                        // ADD/SUB EA,const 
    42064323 
    42074324        freenode(e2); 
    42084325        if (tyfv(tyml)) 
     
    44964613/***************************************** 
    44974614 */ 
    44984615 
    44994616code *cdhalt(elem *e,regm_t *pretregs) 
    45004617{ 
    45014618    assert(*pretregs == 0); 
    45024619    return gen1(NULL, 0xF4);            // HLT 
    45034620} 
    45044621 
    45054622/**************************************** 
    45064623 * Check to see if pointer is NULL. 
    45074624 */ 
    45084625 
    45094626code *cdnullcheck(elem *e,regm_t *pretregs) 
    45104627{   regm_t retregs; 
    45114628    regm_t scratch; 
    45124629    unsigned reg; 
    45134630    code *c; 
    45144631    code *cs; 
    45154632 
    4516     assert(I32); 
     4633    assert(!I16); 
    45174634    retregs = *pretregs; 
    45184635    if ((retregs & allregs) == 0) 
    45194636        retregs |= allregs; 
    45204637    c = codelem(e->E1,&retregs,FALSE); 
    45214638    scratch = allregs & ~retregs; 
    45224639    cs = allocreg(&scratch,&reg,TYint); 
    4523     cs = genc1(cs,0x8B,modregrm(2,reg,findreg(retregs)),FLconst,0);     // MOV reg,0[e] 
     4640    unsigned rex = I64 ? REX_W : 0; 
     4641    cs = genc1(cs,0x8B,(rex << 16) | modregxrmx(2,reg,findreg(retregs)),FLconst,0); // MOV reg,0[e] 
    45244642    return cat3(c,cs,fixresult(e,retregs,pretregs)); 
    45254643} 
    45264644 
    45274645#endif // !SPP 
  • branches/dmd-1.x/src/backend/cod3.c

    r569 r577  
    269269        DOUBLEREGS = DOUBLEREGS_16; 
    270270    } 
    271271#endif 
    272272} 
    273273 
    274274/******************************** 
    275275 * Fix global variables for I64. 
    276276 */ 
    277277 
    278278void cod3_set64() 
    279279{ 
    280280    inssize[0xA0] = T|5;                // MOV AL,mem 
    281281    inssize[0xA1] = T|5;                // MOV RAX,mem 
    282282    inssize[0xA2] = T|5;                // MOV mem,AL 
    283283    inssize[0xA3] = T|5;                // MOV mem,RAX 
    284284    BPRM = 5;                           // [RBP] addressing mode 
    285285    fregsaved = mBP | mBX | mR12 | mR13 | mR14 | mR15 | mES;      // saved across function calls 
    286286    FLOATREGS = FLOATREGS_64; 
    287287    FLOATREGS2 = FLOATREGS2_64; 
    288288    DOUBLEREGS = DOUBLEREGS_64; 
     289    STACKALIGN = 16; 
    289290 
    290291    for (unsigned i = 0x80; i < 0x90; i++) 
    291292        inssize2[i] = W|T|6; 
    292293} 
    293294 
    294295/********************************* 
    295296 * Word or dword align start of function. 
    296297 */ 
    297298 
    298299void cod3_align() 
    299300{ 
    300301    static char nops[7] = { 0x90,0x90,0x90,0x90,0x90,0x90,0x90 }; 
    301302    unsigned nbytes; 
    302303#if OMFOBJ 
    303304    if (config.flags4 & CFG4speed)      // if optimized for speed 
    304305    { 
    305306        // Pick alignment based on CPU target 
    306307        if (config.target_cpu == TARGET_80486 || 
    307308            config.target_cpu >= TARGET_PentiumPro) 
    308309        {   // 486 does reads on 16 byte boundaries, so if we are near 
     
    353354 
    354355    e = b->Belem; 
    355356    elem_debug(e); 
    356357    cc = docommas(&e); 
    357358    cgstate.stackclean++; 
    358359    tys = tybasic(e->Ety); 
    359360    sz = tysize[tys]; 
    360361    dword = (sz == 2 * REGSIZE); 
    361362    mswsame = 1;                        // assume all msw's are the same 
    362363    p = b->BS.Bswitch;                  /* pointer to case data         */ 
    363364    assert(p); 
    364365    ncases = *p++;                      /* number of cases              */ 
    365366 
    366367    vmax = MINLL;                       // smallest possible llong 
    367368    vmin = MAXLL;                       // largest possible llong 
    368369    for (n = 0; n < ncases; n++)        // find max and min case values 
    369370    {   val = *p++; 
    370371        if (val > vmax) vmax = val; 
    371372        if (val < vmin) vmin = val; 
    372373        if (REGSIZE == 2) 
    373         {   unsigned short ms; 
    374  
    375 #if __DMC__ 
    376             ms = ((unsigned short *)&val)[1]; 
    377 #else 
    378             ms = (val >> 16) & 0xFFFF; 
    379 #endif 
     374        { 
     375            unsigned short ms = (val >> 16) & 0xFFFF; 
    380376            if (n == 0) 
    381377                msw = ms; 
    382378            else if (msw != ms) 
    383379                mswsame = 0; 
    384380        } 
    385381        else // REGSIZE == 4 
    386         {   targ_ulong ms; 
    387  
    388 #if __DMC__ 
    389             /* This statement generates garbage for ms under g++, 
    390              * I don't know why. 
    391              */ 
    392             ms = ((targ_ulong *)&val)[1]; 
    393 #else 
    394             ms = (val >> 32) & 0xFFFFFFFF; 
    395 #endif 
     382        { 
     383            targ_ulong ms = (val >> 32) & 0xFFFFFFFF; 
    396384            if (n == 0) 
    397385                msw = ms; 
    398386            else if (msw != ms) 
    399387                mswsame = 0; 
    400388        } 
    401389    } 
    402390    p -= ncases; 
    403391    //dbg_printf("vmax = x%lx, vmin = x%lx, vmax-vmin = x%lx\n",vmax,vmin,vmax - vmin); 
    404392    flags = (config.flags & CFGromable) ? CFcs : 0; // table is in code seg 
    405393 
     394    if (I64) 
     395    {   // For now, just generate basic if-then sequence to get us running 
     396        retregs = ALLREGS; 
     397        b->BC = BCifthen; 
     398        c = scodelem(e,&retregs,0,TRUE); 
     399        assert(!dword);                 // 128 bit switches not supported 
     400        reg = findreg(retregs);         // reg that result is in 
     401        bl = b->Bsucc; 
     402        for (n = 0; n < ncases; n++) 
     403        {   code *cx; 
     404            val = *p; 
     405            if (sz == 4) 
     406                cx = genc2(CNIL,0x81,modregrmx(3,7,reg),val);  // CMP reg,val 
     407            else if (sz == 8) 
     408            { 
     409                if (val == (int)val)    // if val is a 64 bit value sign-extended from 32 bits 
     410                { 
     411                    cx = genc2(CNIL,0x81,modregrmx(3,7,reg),val);  // CMP reg,value32 
     412                    cx->Irex |= REX_W;  // 64 bit operand 
     413                } 
     414                else 
     415                {   unsigned sreg; 
     416                                                                // MOV sreg,value64 
     417                    cx = regwithvalue(CNIL, ALLREGS & ~mask[reg], val, &sreg, 64); 
     418                    cx = genregs(cx,0x3B,reg,sreg);             // CMP reg,sreg 
     419                    code_orrex(cx, REX_W); 
     420                } 
     421            } 
     422            else 
     423                assert(0); 
     424            bl = list_next(bl); 
     425            genjmp(cx,JE,FLblock,list_block(bl));       // JE caseaddr 
     426            c = cat(c,cx); 
     427            p++; 
     428        } 
     429        if (list_block(b->Bsucc) != b->Bnext) /* if default is not next block */ 
     430                c = cat(c,genjmp(CNIL,JMP,FLblock,list_block(b->Bsucc))); 
     431        ce = NULL; 
     432    } 
    406433    // Need to do research on MACHOBJ to see about better methods 
    407     if (MACHOBJ || ncases <= 3)                 // generate if-then sequence 
    408     { 
     434    else if (MACHOBJ || ncases <= 3) 
     435    {   // generate if-then sequence 
    409436        retregs = ALLREGS; 
    410437    L1: 
    411438        b->BC = BCifthen; 
    412439        c = scodelem(e,&retregs,0,TRUE); 
    413440        if (dword) 
    414441        {   reg = findreglsw(retregs); 
    415442            reg2 = findregmsw(retregs); 
    416443        } 
    417444        else 
    418445            reg = findreg(retregs);     /* reg that result is in        */ 
    419446        bl = b->Bsucc; 
    420447        if (dword && mswsame) 
    421448        {   /* CMP reg2,MSW     */ 
    422449            c = genc2(c,0x81,modregrm(3,7,reg2),msw); 
    423450            genjmp(c,JNE,FLblock,list_block(b->Bsucc)); /* JNE default  */ 
    424451        } 
    425452        for (n = 0; n < ncases; n++) 
    426453        {   code *cnext = CNIL; 
    427454                                        /* CMP reg,casevalue            */ 
    428455            c = cat(c,ce = genc2(CNIL,0x81,modregrm(3,7,reg),(targ_int)*p)); 
     
    833860L1: 
    834861#if DEBUG 
    835862  if ((jp & 0xF0) != 0x70) 
    836863        WROP(op), 
    837864        printf("i %d zero %d op x%x jp x%x\n",i,zero,op,jp); 
    838865#endif 
    839866  assert((jp & 0xF0) == 0x70); 
    840867  return jp; 
    841868} 
    842869 
    843870 
    844871/********************************** 
    845872 * Append code to *pc which validates pointer described by 
    846873 * addressing mode in *pcs. Modify addressing mode in *pcs. 
    847874 * Input: 
    848875 *      keepmsk mask of registers we must not destroy or use 
    849876 *              if (keepmsk & RMstore), this will be only a store operation 
    850877 *              into the lvalue 
    851878 */ 
    852879 
    853 void cod3_ptrchk(code * __ss *pc,code __ss *pcs,regm_t keepmsk) 
     880void cod3_ptrchk(code **pc,code *pcs,regm_t keepmsk) 
    854881{   code *c; 
    855882    code *cs2; 
    856883    unsigned char rm,sib; 
    857884    unsigned reg; 
    858885    unsigned flagsave; 
    859886    unsigned opsave; 
    860887    regm_t idxregs; 
    861888    regm_t tosave; 
    862889    regm_t used; 
    863890    int i; 
    864891 
     892    assert(!I64); 
    865893    if (!I16 && pcs->Iflags & (CFes | CFss | CFcs | CFds | CFfs | CFgs)) 
    866894        return;         // not designed to deal with 48 bit far pointers 
    867895 
    868896    c = *pc; 
    869897 
    870898    rm = pcs->Irm; 
    871899    assert(!(rm & 0x40));       // no disp8 or reg addressing modes 
    872900 
    873901    // If the addressing mode is already a register 
    874902    reg = rm & 7; 
    875903    if (I16) 
    876904    {   static const unsigned char imode[8] = { BP,BP,BP,BP,SI,DI,BP,BX }; 
    877905 
    878906        reg = imode[reg];               // convert [SI] to SI, etc. 
    879907    } 
    880908    idxregs = mask[reg]; 
    881909    if ((rm & 0x80 && (pcs->IFL1 != FLoffset || pcs->IEV1.Vuns)) || 
    882910        !(idxregs & ALLREGS) 
    883911       ) 
    884912    { 
     
    937965            case CFcs:  segreg = 0x0E;  break; 
    938966            case 0:     segreg = 0x1E;  break;  // DS 
    939967            default: 
    940968                assert(0); 
    941969        } 
    942970 
    943971        // See if we should default to SS: 
    944972        // (Happens when BP is part of the addressing mode) 
    945973        if (segreg == 0x1E && (rm & 0xC0) != 0xC0 && 
    946974            rm & 2 && (rm & 7) != 7) 
    947975        {   segreg = 0x16; 
    948976            if (config.wflags & WFssneds) 
    949977                pcs->Iflags |= CFss;    // because BP won't be there anymore 
    950978        } 
    951979        c = gen1(c,segreg);             // PUSH segreg 
    952980    } 
    953981 
    954982    c = gen1(c,0x50 + reg);             // PUSH reg 
    955983 
    956984    // Rewrite the addressing mode in *pcs so it is just 0[reg] 
    957     pcs->Irm = getaddrmode(idxregs); 
     985    setaddrmode(pcs, idxregs); 
    958986    pcs->IFL1 = FLoffset; 
    959987    pcs->IEV1.Vuns = 0; 
    960988 
    961989    // Call the validation function 
    962990    { 
    963991        makeitextern(rtlsym[RTLSYM_PTRCHK]); 
    964992 
    965993        used &= ~(keepmsk | idxregs);           // regs destroyed by this exercise 
    966994        c = cat(c,getregs(used)); 
    967995                                                // CALL __ptrchk 
    968996        gencs(c,(LARGECODE) ? 0x9A : 0xE8,0,FLfunc,rtlsym[RTLSYM_PTRCHK]); 
    969997    } 
    970998 
    971999    *pc = cat(c,cs2); 
    9721000} 
    9731001 
    9741002 
    9751003 
    9761004/*********************************** 
    9771005 * Determine if BP can be used as a general purpose register. 
     
    10171045            config.flags & CFGstack || 
    10181046            localsize >= 0x100 ||       // arbitrary value < 0x1000 
    10191047            (usednteh & ~NTEHjmonitor) || 
    10201048            usedalloca 
    10211049           ) 
    10221050            goto Lcant; 
    10231051    } 
    10241052Lcan: 
    10251053    return mBP; 
    10261054 
    10271055Lcant: 
    10281056    return 0; 
    10291057} 
    10301058 
    10311059/*************************************** 
    10321060 * Gen code for OPframeptr 
    10331061 */ 
    10341062 
    10351063code *cdframeptr(elem *e, regm_t *pretregs) 
    10361064{ 
    1037     regm_t retregs; 
    10381065    unsigned reg; 
    1039     code *cg; 
    1040     code *c1; 
    10411066    code cs; 
    10421067 
    1043     retregs = *pretregs & allregs; 
     1068    regm_t retregs = *pretregs & allregs; 
    10441069    if  (!retregs) 
    10451070        retregs = allregs; 
    1046     cg = allocreg(&retregs, &reg, TYint); 
    1047     //c1 = genmovreg(cg, reg, BP); 
     1071    code *cg = allocreg(&retregs, &reg, TYint); 
    10481072 
    10491073    cs.Iop = ESCAPE; 
    10501074    cs.Iop2 = ESCframeptr; 
    10511075    cs.Iflags = 0; 
    10521076    cs.Irex = 0; 
    10531077    cs.Irm = reg; 
    1054     c1 = gen(cg,&cs); 
    1055  
    1056     return cat(c1,fixresult(e,retregs,pretregs)); 
     1078    cg = gen(cg,&cs); 
     1079 
     1080    return cat(cg,fixresult(e,retregs,pretregs)); 
    10571081} 
    10581082 
    10591083/*************************************** 
    10601084 * Gen code for load of _GLOBAL_OFFSET_TABLE_. 
    10611085 * This value gets cached in the local variable 'localgot'. 
    10621086 */ 
    10631087 
    10641088code *cdgot(elem *e, regm_t *pretregs) 
    10651089{ 
    10661090#if TARGET_OSX 
    10671091    regm_t retregs; 
    10681092    unsigned reg; 
    10691093    code *c; 
    10701094 
    10711095    retregs = *pretregs & allregs; 
    10721096    if  (!retregs) 
    10731097        retregs = allregs; 
    10741098    c = allocreg(&retregs, &reg, TYnptr); 
    10751099 
    10761100    c = genc(c,0xE8,0,0,0,FLgot,0);     //     CALL L1 
     
    18431867        static unsigned char ops0[] = { 0x07,0x1F,0x5F,0x5E, 
    18441868                                        0x5D,0x5B,0x5B,0x5A, 
    18451869                                        0x59,0x58,0xCF,0 }; 
    18461870        unsigned char *p; 
    18471871 
    18481872        c = genregs(c,0x8B,SP,BP);              // MOV SP,BP 
    18491873        p = (config.target_cpu >= TARGET_80286) ? ops2 : ops0; 
    18501874        do 
    18511875            gen1(c,*p); 
    18521876        while (*++p); 
    18531877        goto Lopt; 
    18541878    } 
    18551879 
    18561880    if (config.flags & CFGtrace && 
    18571881        (!(config.flags4 & CFG4allcomdat) || 
    18581882         funcsym_p->Sclass == SCcomdat || 
    18591883         funcsym_p->Sclass == SCglobal || 
    18601884         (config.flags2 & CFG2comdat && SymInline(funcsym_p)) 
    18611885        ) 
    18621886       ) 
    1863     {   symbol *s; 
    1864  
    1865         s = rtlsym[farfunc ? RTLSYM_TRACE_EPI_F : RTLSYM_TRACE_EPI_N]; 
     1887    { 
     1888        symbol *s = rtlsym[farfunc ? RTLSYM_TRACE_EPI_F : RTLSYM_TRACE_EPI_N]; 
    18661889        makeitextern(s); 
    18671890        c = gencs(c,I16 ? 0x9A : 0xE8,0,FLfunc,s);      // CALLF _trace 
    18681891        if (!I16) 
    18691892            code_orflag(c,CFoff | CFselfrel); 
    18701893        useregs((ALLREGS | mBP | mES) & ~s->Sregsaved); 
    18711894    } 
    18721895 
    18731896    if (usednteh & ~NTEHjmonitor && (config.exe == EX_NT || MARS)) 
    18741897        c = cat(c,nteh_epilog()); 
    18751898 
    18761899    cpopds = CNIL; 
    18771900    if (tyf & mTYloadds) 
    18781901    {   cpopds = gen1(cpopds,0x1F);             // POP DS 
    18791902        c = cat(c,cpopds); 
    18801903        spoff += intsize; 
    18811904    } 
    18821905 
    1883     reg = 7; 
    1884     regm = 1 << 7; 
     1906    /* Pop all the general purpose registers saved on the stack 
     1907     * by the prolog code. Remember to do them in the reverse 
     1908     * order they were pushed. 
     1909     */ 
     1910    reg = I64 ? R15 : DI; 
     1911    regm = 1 << reg; 
    18851912    topop = fregsaved & ~mfuncreg; 
    18861913#ifdef DEBUG 
    1887     if (topop & ~0xFF
     1914    if (topop & ~0xFFFF
    18881915        printf("fregsaved = x%x, mfuncreg = x%x\n",fregsaved,mfuncreg); 
    18891916#endif 
    1890     assert(!(topop & ~0xFF)); 
     1917    assert(!(topop & ~0xFFFF)); 
    18911918    while (topop) 
    18921919    {   if (topop & regm) 
    1893         {       c = gen1(c,0x58 + reg);         /* POP reg              */ 
    1894                 if (reg & 8) 
    1895                     code_orrex(c, REX_B); 
    1896                 topop &= ~regm; 
    1897                 spoff += intsize; 
     1920        {   c = gen1(c,0x58 + reg);         // POP reg 
     1921            if (reg & 8) 
     1922                code_orrex(c, REX_B); 
     1923            topop &= ~regm; 
     1924            spoff += intsize; 
    18981925        } 
    18991926        regm >>= 1; 
    19001927        reg--; 
    19011928    } 
    19021929 
    19031930#if MARS 
    19041931    if (usednteh & NTEHjmonitor) 
    19051932    { 
    19061933        regm_t retregs = 0; 
    19071934        if (b->BC == BCretexp) 
    19081935            retregs = regmask(b->Belem->Ety, tym); 
    19091936        code *cn = nteh_monitor_epilog(retregs); 
    19101937        c = cat(c,cn); 
    19111938        xlocalsize += 8; 
    19121939    } 
    19131940#endif 
    19141941 
    19151942    if (config.wflags & WFwindows && farfunc) 
    19161943    { 
    19171944        int wflags = config.wflags; 
     
    19832010        op = tyfarfunc(tym) ? 0xCA : 0xC2; 
    19842011        if (tym == TYhfunc) 
    19852012        { 
    19862013            c = genc2(c,0xC2,0,4);                      // RET 4 
    19872014        } 
    19882015        else if (!typfunc(tym) || Poffset == 0) 
    19892016        {   op++;                                       // to a regular RET 
    19902017            c = gen1(c,op); 
    19912018        } 
    19922019        else 
    19932020        {   // Stack is always aligned on register size boundary 
    19942021            Poffset = (Poffset + (REGSIZE - 1)) & ~(REGSIZE - 1); 
    19952022            c = genc2(c,op,0,Poffset);          // RET Poffset 
    19962023        } 
    19972024    } 
    19982025 
    19992026Lopt: 
    20002027    // If last instruction in ce is ADD SP,imm, and first instruction 
    20012028    // in c sets SP, we can dump the ADD. 
    20022029    cr = code_last(ce); 
    2003     if (cr && c
     2030    if (cr && c && !I64
    20042031    { 
    20052032        if (cr->Iop == 0x81 && cr->Irm == modregrm(3,0,SP))     // if ADD SP,imm 
    20062033        { 
    20072034            if ( 
    20082035                c->Iop == 0xC9 ||                                  // LEAVE 
    20092036                (c->Iop == 0x8B && c->Irm == modregrm(3,SP,BP)) || // MOV SP,BP 
    20102037                (c->Iop == 0x8D && c->Irm == modregrm(1,SP,6))     // LEA SP,-imm[BP] 
    20112038               ) 
    20122039                cr->Iop = NOP; 
    20132040            else if (c->Iop == 0x58 + BP)                       // if POP BP 
    20142041            {   cr->Iop = 0x8B; 
    20152042                cr->Irm = modregrm(3,SP,BP);                    // MOV SP,BP 
    20162043            } 
    20172044        } 
    20182045#if 0   // These optimizations don't work if the called function 
    20192046        // cleans off the stack. 
    20202047        else if (c->Iop == 0xC3 && cr->Iop == 0xE8)     // CALL near 
    20212048        {   cr->Iop = 0xE9;                             // JMP near 
    20222049            c->Iop = NOP; 
    20232050        } 
     
    23752401                    break; 
    23762402 
    23772403                default: 
    23782404                    goto L3; 
    23792405            } 
    23802406 
    23812407            if (disp == 0)                      // bra to next instruction 
    23822408            {   bytesaved += csize; 
    23832409                c->Iop = NOP;                   // del branch instruction 
    23842410                c->IEV2.Vcode = NULL; 
    23852411                c = cn; 
    23862412                if (!c) 
    23872413                    break; 
    23882414                continue; 
    23892415            } 
    23902416            else if ((targ_size_t)(targ_schar)(disp - 2) == (disp - 2) && 
    23912417                     (targ_size_t)(targ_schar)disp == disp) 
    23922418            { 
    23932419                if (op == JMP) 
    23942420                {   c->Iop = JMPS;              // JMP SHORT 
    2395                     bytesaved += I32 ? 3 : 1
     2421                    bytesaved += I16 ? 1 : 3
    23962422                } 
    23972423                else                            // else Jcond 
    23982424                {   c->Iflags &= ~CFjmp16;      // a branch is ok 
    2399                     bytesaved += I32 ? 4 : 3
     2425                    bytesaved += I16 ? 3 : 4
    24002426 
    24012427                    // Replace a cond jump around a call to a function that 
    24022428                    // never returns with a cond jump to that function. 
    24032429                    if (config.flags4 & CFG4optimized && 
    24042430                        config.target_cpu >= TARGET_80386 && 
    2405                         disp == (I32 ? 5 : 3) && 
     2431                        disp == (I16 ? 3 : 5) && 
    24062432                        cn && 
    24072433                        cn->Iop == 0xE8 && 
    24082434                        cn->IFL2 == FLfunc && 
    24092435                        cn->IEVsym2->Sflags & SFLexit && 
    24102436                        !(cn->Iflags & (CFtarg | CFtarg2)) 
    24112437                       ) 
    24122438                    { 
    24132439                        cn->Iop = 0x0F; 
    24142440                        cn->Iop2 = (c->Iop & 0x0F) ^ 0x81; 
    24152441                        c->Iop = NOP; 
    24162442                        c->IEV2.Vcode = NULL; 
    24172443                        bytesaved++; 
    24182444 
    24192445                        // If nobody else points to ct, we can remove the CFtarg 
    24202446                        if (flag && ct) 
    24212447                        {   code *cx; 
    24222448 
    24232449                            for (cx = bl->Bcode; 1; cx = code_next(cx)) 
    24242450                            { 
    24252451                                if (!cx) 
     
    25332559#ifdef DEBUG 
    25342560        if (0) 
    25352561        {       printf("assignaddrc()\n"); 
    25362562                c->print(); 
    25372563        } 
    25382564        if (code_next(c) && code_next(code_next(c)) == c) 
    25392565            assert(0); 
    25402566#endif 
    25412567        if (c->Iop == 0x0F) 
    25422568            ins = inssize2[c->Iop2]; 
    25432569        else if (c->Iop == ESCAPE) 
    25442570        { 
    25452571            if (c->Iop2 == ESCadjesp) 
    25462572            { 
    25472573                //printf("adjusting EBPtoESP (%d) by %ld\n",EBPtoESP,c->IEV2.Vint); 
    25482574                EBPtoESP += c->IEV2.Vint; 
    25492575                c->Iop = NOP; 
    25502576            } 
    25512577            if (c->Iop2 == ESCframeptr) 
    25522578            {   // Convert to load of frame pointer 
     2579                // c->Irm is the register to use 
    25532580                if (hasframe) 
    25542581                {   // MOV reg,EBP 
    25552582                    c->Iop = 0x89; 
    2556                     c->Irm = modregrm(3,BP,c->Irm); 
     2583                    if (c->Irm & 8) 
     2584                        c->Irex |= REX_B; 
     2585                    c->Irm = modregrm(3,BP,c->Irm & 7); 
    25572586                } 
    25582587                else 
    25592588                {   // LEA reg,EBPtoESP[ESP] 
    25602589                    c->Iop = 0x8D; 
    2561                     c->Irm = modregrm(2,c->Irm,4); 
     2590                    if (c->Irm & 8) 
     2591                        c->Irex |= REX_R; 
     2592                    c->Irm = modregrm(2,c->Irm & 7,4); 
    25622593                    c->Isib = modregrm(0,4,SP); 
    25632594                    c->Iflags = CFoff; 
    25642595                    c->IFL1 = FLconst; 
    25652596                    c->IEV1.Vuns = EBPtoESP; 
    25662597                } 
    25672598            } 
     2599            if (I64) 
     2600                c->Irex |= REX_W; 
    25682601            continue; 
    25692602        } 
    25702603        else 
    25712604            ins = inssize[c->Iop]; 
    25722605        if (!(ins & M) || 
    25732606            ((rm = c->Irm) & 0xC0) == 0xC0) 
    25742607            goto do2;           /* if no first operand          */ 
    25752608        if (is32bitaddr(I32,c->Iflags)) 
    25762609        { 
    25772610 
    25782611            if ( 
    25792612                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    25802613               ) 
    25812614                goto do2;       /* if no first operand  */ 
    25822615        } 
    25832616        else 
    25842617        { 
    25852618            if ( 
    25862619                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
    25872620               ) 
     
    26372670 
    26382671            case FLreg: 
    26392672            case FLauto: 
    26402673                soff = Aoff; 
    26412674            L1: 
    26422675                if (s->Sflags & SFLunambig && !(s->Sflags & SFLread) && // if never loaded 
    26432676                    !anyiasm && 
    26442677                    // if not optimized, leave it in for debuggability 
    26452678                    (config.flags4 & CFG4optimized || !config.fulltypes)) 
    26462679                {   c->Iop = NOP;               // remove references to it 
    26472680                    continue; 
    26482681                } 
    26492682                if (s->Sfl == FLreg && c->IEVpointer1 < 2) 
    26502683                {       int reg = s->Sreglsw; 
    26512684 
    26522685                        assert(!(s->Sregm & ~mask[reg])); 
    26532686                        if (c->IEVpointer1 == 1) 
    26542687                        {   assert(reg < 4);    /* must be a BYTEREGS   */ 
    26552688                            reg |= 4;           /* convert to high byte reg */ 
    26562689                        } 
     2690                        if (reg & 8) 
     2691                        {   assert(I64); 
     2692                            c->Irex |= REX_B; 
     2693                            reg &= 7; 
     2694                        } 
    26572695                        c->Irm = (c->Irm & modregrm(0,7,0)) 
    26582696                                | modregrm(3,0,reg); 
    26592697                        assert(c->Iop != LES && c->Iop != LEA); 
    26602698                        goto do2; 
    26612699                } 
    26622700                else 
    26632701                {   c->IEVpointer1 += s->Soffset + soff + BPoff; 
    26642702                    if (s->Sflags & SFLunambig) 
    26652703                        c->Iflags |= CFunambig; 
    26662704            L2: 
    26672705                    if (!hasframe) 
    26682706                    {   /* Convert to ESP relative address instead of EBP */ 
    26692707                        unsigned char rm; 
    26702708 
    2671                         assert(I32); 
     2709                        assert(!I16); 
    26722710                        c->IEVpointer1 += EBPtoESP; 
    26732711                        rm = c->Irm; 
    26742712                        if ((rm & 7) == 4)              // if SIB byte 
    26752713                        { 
    26762714                            assert((c->Isib & 7) == BP); 
    26772715                            assert((rm & 0xC0) != 0); 
    26782716                            c->Isib = (c->Isib & ~7) | modregrm(0,0,SP); 
    26792717                        } 
    26802718                        else 
    26812719                        { 
    26822720                            assert((rm & 7) == 5); 
    26832721                            c->Irm = (rm & modregrm(0,7,0)) 
    26842722                                    | modregrm(2,0,4); 
    26852723                            c->Isib = modregrm(0,4,SP); 
    26862724                        } 
    26872725                    } 
    26882726                } 
    26892727                break; 
    26902728            case FLpara: 
    26912729                soff = Poff - BPoff;    // cancel out add of BPoff 
     
    28772915void pinholeopt(code *c,block *b) 
    28782916{ targ_size_t a; 
    28792917  unsigned op,mod,rm,reg,ereg; 
    28802918  unsigned char ins; 
    28812919  int usespace; 
    28822920  int useopsize; 
    28832921  int space; 
    28842922  block *bn; 
    28852923 
    28862924#if 0 
    28872925  code *cstart = c; 
    28882926  if (debugc) 
    28892927  { 
    28902928      printf("+pinholeopt(%p)\n",c); 
    28912929  } 
    28922930#endif 
    28932931 
    28942932  if (b) 
    28952933  {     bn = b->Bnext; 
    28962934        usespace = (config.flags4 & CFG4space && b->BC != BCasm); 
    2897         useopsize = (!I32 || (config.flags4 & CFG4space && b->BC != BCasm)); 
     2935        useopsize = (I16 || (config.flags4 & CFG4space && b->BC != BCasm)); 
    28982936  } 
    28992937  else 
    29002938  {     bn = NULL; 
    29012939        usespace = (config.flags4 & CFG4space); 
    2902         useopsize = (!I32 || config.flags4 & CFG4space); 
     2940        useopsize = (I16 || config.flags4 & CFG4space); 
    29032941  } 
    29042942  for (; c; c = code_next(c)) 
    29052943  { 
    29062944    L1: 
    29072945        op = c->Iop; 
    29082946        if (op == 0x0F) 
    29092947            ins = inssize2[c->Iop2]; 
    29102948        else 
    29112949            ins = inssize[c->Iop]; 
    2912         if (ins & M)            /* if modregrm byte             */ 
    2913         {   int longop = (c->Iflags & CFopsize) ? !I32 : I32; 
     2950        if (!I64 && ins & M)            // if modregrm byte 
     2951        {   int longop = (c->Iflags & CFopsize) ? I16 : I32; 
    29142952            int local_BPRM = BPRM; 
    29152953 
    29162954            if (c->Iflags & CFaddrsize) 
    29172955                local_BPRM ^= 5 ^ 6;    // toggle between 5 and 6 
    29182956 
    29192957            rm = c->Irm; 
    29202958            reg = rm & (7<<3);          // isolate reg field 
    29212959            ereg = rm & 7; 
    29222960 
    29232961            /* If immediate second operand      */ 
    29242962            if ((ins & T || op == 0xF6 || op == 0xF7) && 
    29252963                c->IFL2 == FLconst) 
    29262964            {   int flags; 
    29272965                targ_long u; 
    29282966 
    29292967                flags = c->Iflags & CFpsw;      /* if want result in flags */ 
    29302968                u = c->IEV2.Vuns; 
    29312969                if (ins & E) 
    29322970                    u = (signed char) u; 
    29332971                else if (!longop) 
    29342972                    u = (short) u; 
    29352973 
    29362974                // Replace CMP reg,0 with TEST reg,reg 
    2937 #if 0 
    2938                 // BUG: is this the right one? 
    2939                 if ((op & 0xFC) == 0x80 && 
    2940 #else 
    29412975                if ((op & 0xFE) == 0x80 && 
    2942 #endif 
    29432976                    rm >= modregrm(3,7,AX) && 
    29442977                    u == 0) 
    29452978                {       c->Iop = (op & 1) | 0x84; 
    29462979                        c->Irm = modregrm(3,ereg,ereg); 
    29472980                        goto L1; 
    29482981                } 
    29492982 
    29502983                /* Optimize ANDs with an immediate constant             */ 
    29512984                if ((op == 0x81 || op == 0x80) && reg == modregrm(0,4,0)) 
    29522985                { 
    29532986                    if (rm >= modregrm(3,4,AX)) 
    29542987                    { 
    29552988                        if (u == 0) 
    29562989                        {       /* Replace with XOR reg,reg     */ 
    29572990                                c->Iop = 0x30 | (op & 1); 
    29582991                                NEWREG(c->Irm,rm & 7); 
    29592992                                goto L1; 
    29602993                        } 
    29612994                        if (u == 0xFFFFFFFF && !flags) 
    29622995                        {       c->Iop = NOP; 
     
    40234056    return offset;                      /* ending address               */ 
    40244057} 
    40254058 
    40264059 
    40274060STATIC void do64bit(enum FL fl,union evc *uev,int flags) 
    40284061{   char *p; 
    40294062    symbol *s; 
    40304063    targ_size_t ad; 
    40314064    long tmp; 
    40324065 
    40334066    assert(I64); 
    40344067    switch (fl) 
    40354068    { 
    40364069        case FLconst: 
    40374070            ad = * (targ_size_t *) uev; 
    40384071        L1: 
    40394072            GENP(8,&ad); 
    40404073            return; 
    40414074        case FLdatseg: 
    40424075            FLUSH(); 
    4043             reftodatseg(cseg,offset,uev->_EP.Vpointer,uev->_EP.Vseg,flags); 
     4076            reftodatseg(cseg,offset,uev->_EP.Vpointer,uev->_EP.Vseg,CFoffset64 | flags); 
    40444077            break; 
    40454078        case FLframehandler: 
    40464079            framehandleroffset = OFFSET(); 
    40474080            ad = 0; 
    40484081            goto L1; 
    40494082        case FLswitch: 
    40504083            FLUSH(); 
    40514084            ad = uev->Vswitch->Btableoffset; 
    40524085            if (config.flags & CFGromable) 
    40534086                    reftocodseg(cseg,offset,ad); 
    40544087            else 
    40554088                    reftodatseg(cseg,offset,ad,JMPSEG,CFoff); 
    40564089            break; 
    40574090        case FLcsdata: 
    40584091        case FLfardata: 
    40594092#if DEBUG 
    40604093            symbol_print(uev->sp.Vsym); 
    40614094#endif 
    40624095            assert(!TARGET_FLAT); 
    40634096            // NOTE: In ELFOBJ all symbol refs have been tagged FLextern 
    40644097            // strings and statics are treated like offsets from a 
    40654098            // un-named external with is the start of .rodata or .data 
    40664099        case FLextern:                      /* external data symbol         */ 
    40674100        case FLtlsdata: 
    40684101#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    40694102        case FLgot: 
    40704103        case FLgotoff: 
    40714104#endif 
    40724105            FLUSH(); 
    40734106            s = uev->sp.Vsym;               /* symbol pointer               */ 
    4074             reftoident(cseg,offset,s,uev->sp.Voffset,flags); 
     4107            reftoident(cseg,offset,s,uev->sp.Voffset,CFoffset64 | flags); 
    40754108            break; 
    40764109 
    40774110#if TARGET_OSX 
    40784111        case FLgot: 
    40794112            funcsym_p->Slocalgotoffset = OFFSET(); 
    40804113            ad = 0; 
    40814114            goto L1; 
    40824115#endif 
    40834116 
    40844117        case FLfunc:                        /* function call                */ 
    40854118            s = uev->sp.Vsym;               /* symbol pointer               */ 
    40864119            assert(!(TARGET_FLAT && tyfarfunc(s->ty()))); 
    40874120            FLUSH(); 
    4088             reftoident(cseg,offset,s,0,flags); 
     4121            reftoident(cseg,offset,s,0,CFoffset64 | flags); 
    40894122            break; 
    40904123 
    40914124        case FLblock:                       /* displacement to another block */ 
    40924125            ad = uev->Vblock->Boffset - OFFSET() - 4; 
    40934126            //printf("FLblock: funcoffset = %x, OFFSET = %x, Boffset = %x, ad = %x\n", funcoffset, OFFSET(), uev->Vblock->Boffset, ad); 
    40944127            goto L1; 
    40954128 
    40964129        case FLblockoff: 
    40974130            FLUSH(); 
    40984131            assert(uev->Vblock); 
    40994132            //printf("FLblockoff: offset = %x, Boffset = %x, funcoffset = %x\n", offset, uev->Vblock->Boffset, funcoffset); 
    41004133            reftocodseg(cseg,offset,uev->Vblock->Boffset); 
    41014134            break; 
    41024135 
    41034136        default: 
    41044137#ifdef DEBUG 
    41054138            WRFL(fl); 
    41064139#endif 
    41074140            assert(0); 
    41084141    } 
  • branches/dmd-1.x/src/backend/cod4.c

    r569 r577  
    3333 * Return number of times symbol s appears in tree e. 
    3434 */ 
    3535 
    3636STATIC int intree(symbol *s,elem *e) 
    3737{ 
    3838        if (EOP(e)) 
    3939            return intree(s,e->E1) + (EBIN(e) ? intree(s,e->E2) : 0); 
    4040        return e->Eoper == OPvar && e->EV.sp.Vsym == s; 
    4141} 
    4242 
    4343/*********************************** 
    4444 * Determine if expression e can be evaluated directly into register 
    4545 * variable s. 
    4646 * Have to be careful about things like x=x+x+x, and x=a+x. 
    4747 * Returns: 
    4848 *      !=0     can 
    4949 *      0       can't 
    5050 */ 
    5151 
    5252STATIC int doinreg(symbol *s, elem *e) 
    53 {   int in
     53{   int in = 0
    5454    int op; 
    5555 
    5656 L1: 
    5757    op = e->Eoper; 
    5858    if (op == OPind || 
    5959        OTcall(op)  || 
    6060        OTleaf(op) || 
    6161        (in = intree(s,e)) == 0 || 
    6262        (OTunary(op) && !EOP(e->E1)) 
    6363       ) 
    6464        return 1; 
    6565    if (in == 1) 
    6666    { 
    6767        switch (op) 
    6868        { 
    6969            case OPadd: 
    7070            case OPmin: 
    7171            case OPand: 
    7272            case OPor: 
    7373            case OPxor: 
    7474            case OPshl: 
    7575            case OPmul: 
    7676                if (!intree(s,e->E2)) 
    7777                { 
    7878                    e = e->E1; 
    7979                    goto L1; 
    8080                } 
    8181        } 
    8282    } 
    8383    return 0; 
    8484} 
    8585 
    8686/**************************** 
    8787 * Return code for saving common subexpressions if EA 
    8888 * turns out to be a register. 
    8989 * This is called just before modifying an EA. 
    9090 */ 
    9191 
    92 code *modEA(unsigned Irm
     92code *modEA(code *c
    9393{ 
    94     return ((Irm & 0xC0) == 0xC0) ? getregs(mask[Irm & 7]) : CNIL; 
     94    if ((c->Irm & 0xC0) == 0xC0)        // addressing mode refers to a register 
     95    { 
     96        unsigned reg = c->Irm & 7; 
     97        if (c->Irex & REX_B) 
     98        {   reg |= 8; 
     99            assert(I64); 
     100        } 
     101        return getregs(mask[reg]); 
     102    } 
     103    return CNIL; 
    95104} 
    96105 
    97106#if TARGET_WINDOS 
    98107// This code is for CPUs that do not support the 8087 
    99108 
    100109/**************************** 
    101110 * Gen code for op= for doubles. 
    102111 */ 
    103112 
    104113STATIC code * opassdbl(elem *e,regm_t *pretregs,unsigned op) 
    105114{ code *c1,*c2,*c3,*c4,*c5,*c6,cs; 
    106115  unsigned clib; 
    107116  regm_t retregs2,retregs,idxregs; 
    108117  tym_t tym; 
    109118  elem *e1; 
    110119 
    111120  static unsigned clibtab[OPdivass - OPpostinc + 1] = 
    112121  /* OPpostinc,OPpostdec,OPeq,OPaddass,OPminass,OPmulass,OPdivass       */ 
    113122  {  CLIBdadd, CLIBdsub, (unsigned)-1,  CLIBdadd,CLIBdsub,CLIBdmul,CLIBddiv }; 
    114123 
     
    121130 
    122131  if (tym == TYfloat) 
    123132  { 
    124133        clib += CLIBfadd - CLIBdadd;    /* convert to float operation   */ 
    125134 
    126135        /* Load EA into FLOATREGS       */ 
    127136        c1 = cat(c1,getregs(FLOATREGS)); 
    128137        cs.Iop = 0x8B; 
    129138        cs.Irm |= modregrm(0,AX,0); 
    130139        c1 = gen(c1,&cs); 
    131140 
    132141        if (!I32) 
    133142        { 
    134143            cs.Irm |= modregrm(0,DX,0); 
    135144            getlvalue_msw(&cs); 
    136145            c1 = gen(c1,&cs); 
    137146            getlvalue_lsw(&cs); 
    138147 
    139148        } 
    140149        retregs2 = FLOATREGS2; 
    141         idxregs = FLOATREGS | idxregm(cs.Irm,cs.Isib); 
     150        idxregs = FLOATREGS | idxregm(&cs); 
    142151        retregs = FLOATREGS; 
    143152  } 
    144153  else 
    145154  { 
    146155        if (I32) 
    147156        { 
    148157            /* Load EA into DOUBLEREGS  */ 
    149158            c1 = cat(c1,getregs(DOUBLEREGS_32)); 
    150159            cs.Iop = 0x8B; 
    151160            cs.Irm |= modregrm(0,AX,0); 
    152161            c1 = gen(c1,&cs); 
    153162            cs.Irm |= modregrm(0,DX,0); 
    154163            getlvalue_msw(&cs); 
    155164            c1 = gen(c1,&cs); 
    156165            getlvalue_lsw(&cs); 
    157166 
    158167            retregs2 = DOUBLEREGS2_32; 
    159             idxregs = DOUBLEREGS_32 | idxregm(cs.Irm,cs.Isib); 
     168            idxregs = DOUBLEREGS_32 | idxregm(&cs); 
    160169        } 
    161170        else 
    162171        { 
    163172            /* Push EA onto stack       */ 
    164173            cs.Iop = 0xFF; 
    165174            cs.Irm |= modregrm(0,6,0); 
    166175            cs.IEVoffset1 += DOUBLESIZE - REGSIZE; 
    167176            c1 = gen(c1,&cs); 
    168177            getlvalue_lsw(&cs); 
    169178            gen(c1,&cs); 
    170179            getlvalue_lsw(&cs); 
    171180            gen(c1,&cs); 
    172181            getlvalue_lsw(&cs); 
    173182            gen(c1,&cs); 
    174183            stackpush += DOUBLESIZE; 
    175184 
    176185            retregs2 = DOUBLEREGS_16; 
    177             idxregs = idxregm(cs.Irm,cs.Isib); 
     186            idxregs = idxregm(&cs); 
    178187        } 
    179188        retregs = DOUBLEREGS; 
    180189  } 
    181190 
    182191  if ((cs.Iflags & CFSEG) == CFes) 
    183192        idxregs |= mES; 
    184193  cgstate.stackclean++; 
    185194  c3 = scodelem(e->E2,&retregs2,idxregs,FALSE); 
    186195  cgstate.stackclean--; 
    187196  c4 = callclib(e,clib,&retregs,0); 
    188197  if (e1->Ecount) 
    189198        cssave(e1,retregs,EOP(e1));             /* if lvalue is a CSE   */ 
    190199  freenode(e1); 
    191200  cs.Iop = 0x89;                                /* MOV EA,DOUBLEREGS    */ 
    192201  c5 = fltregs(&cs,tym); 
    193202  c6 = fixresult(e,retregs,pretregs); 
    194203  return cat6(c1,CNIL,c3,c4,c5,c6); 
    195204} 
    196205 
    197206/**************************** 
    198207 * Gen code for OPnegass for doubles. 
    199208 */ 
    200209 
    201210STATIC code * opnegassdbl(elem *e,regm_t *pretregs) 
    202211{   code *c1,*c2,*c3,*c,*cl,*cr,cs; 
    203212    unsigned clib; 
    204213    regm_t retregs2,retregs,idxregs; 
    205214    tym_t tym; 
    206215    elem *e1; 
    207216    int sz; 
    208217 
    209218    if (config.inline8087) 
    210219        return cdnegass87(e,pretregs); 
    211220    e1 = e->E1; 
    212221    tym = tybasic(e1->Ety); 
    213222    sz = tysize[tym]; 
    214223 
    215224    cl = getlvalue(&cs,e1,*pretregs ? DOUBLEREGS | mBX | mCX : 0); 
    216     cr = modEA(cs.Irm); 
     225    cr = modEA(&cs); 
    217226    cs.Irm |= modregrm(0,6,0); 
    218227    cs.Iop = 0x80; 
    219228    cs.IEVoffset1 += sz - 1; 
    220229    cs.IFL2 = FLconst; 
    221230    cs.IEV2.Vuns = 0x80; 
    222231    c = gen(NULL,&cs);                  // XOR 7[EA],0x80 
    223232    if (tycomplex(tym)) 
    224233    { 
    225234        cs.IEVoffset1 -= sz / 2; 
    226235        gen(c,&cs);                     // XOR 7[EA],0x80 
    227236    } 
    228237    c = cat3(cl,cr,c); 
    229238 
    230239    if (*pretregs || e1->Ecount) 
    231240    { 
    232241        cs.IEVoffset1 -= sz - 1; 
    233242 
    234243        if (tym == TYfloat) 
    235244        { 
    236245            // Load EA into FLOATREGS 
     
    353362  sz = tysize[tyml]; 
    354363  assert((int)sz > 0); 
    355364 
    356365  if (retregs == 0)                     /* if no return value           */ 
    357366  {     int fl; 
    358367 
    359368        if ((e2oper == OPconst ||       /* if rvalue is a constant      */ 
    360369             e2oper == OPrelconst && 
    361370             ((fl = el_fl(e2)) == FLdata || 
    362371              fl==FLudata || fl == FLextern) && 
    363372             !(e2->EV.sp.Vsym->ty() & mTYcs) 
    364373            ) && 
    365374            !evalinregister(e2) && 
    366375            !e1->Ecount)        /* and no CSE headaches */ 
    367376        { 
    368377            // Look for special case of (*p++ = ...), where p is a register variable 
    369378            if (e1->Eoper == OPind && 
    370379                ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && 
    371380                e11->E1->Eoper == OPvar && 
    372381                e11->E1->EV.sp.Vsym->Sfl == FLreg && 
    373                 (I32 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
     382                (!I16 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
    374383               ) 
    375384            { 
    376385                postinc = e11->E2->EV.Vint; 
    377386                if (e11->Eoper == OPpostdec) 
    378387                    postinc = -postinc; 
    379388                cl = getlvalue(&cs,e11,RMstore); 
    380389                freenode(e11->E2); 
    381390            } 
    382391            else 
    383392            {   postinc = 0; 
    384393                cl = getlvalue(&cs,e1,RMstore); 
    385394 
    386395                if (e2oper == OPconst && 
    387396                    config.flags4 & CFG4speed && 
    388397                    (config.target_cpu == TARGET_Pentium || 
    389398                     config.target_cpu == TARGET_PentiumMMX) && 
    390399                    (cs.Irm & 0xC0) == 0x80 
    391400                   ) 
    392401                { 
    393                     if (sz == REGSIZE && e2->EV.Vint) 
    394                     {   regm_t rregm; 
    395                         unsigned rreg; 
    396  
     402                    if (I64 && sz == 8 && e2->EV.Vpointer) 
     403                    { 
     404                        // MOV reg,imm64 
     405                        // MOV EA,reg 
     406                        regm_t rregm = allregs & ~idxregm(&cs); 
     407                        unsigned reg; 
     408                        cl = regwithvalue(cl,rregm,e2->EV.Vpointer,&reg,CFoffset64); 
     409                        cs.Iop = 0x89; 
     410                        cs.Irm |= modregrm(0,reg & 7,0); 
     411                        if (reg & 8) 
     412                            cs.Irex |= REX_R; 
     413                        c = gen(cl,&cs); 
     414                        freenode(e2); 
     415                        goto Lp; 
     416                    } 
     417                    if ((sz == REGSIZE || (I64 && sz == 4)) && e2->EV.Vint) 
     418                    { 
    397419                        // MOV reg,imm 
    398420                        // MOV EA,reg 
    399                         rregm = allregs & ~idxregm(cs.Irm,cs.Isib); 
     421                        regm_t rregm = allregs & ~idxregm(&cs); 
     422                        unsigned reg; 
    400423                        cl = regwithvalue(cl,rregm,e2->EV.Vint,&reg,0); 
    401424                        cs.Iop = 0x89; 
    402                         cs.Irm |= modregrm(0,reg,0); 
     425                        cs.Irm |= modregrm(0,reg & 7,0); 
     426                        if (reg & 8) 
     427                            cs.Irex |= REX_R; 
    403428                        c = gen(cl,&cs); 
    404429                        freenode(e2); 
    405430                        goto Lp; 
    406431                    } 
    407432                    if (sz == 2 * REGSIZE && e2->EV.Vllong == 0) 
    408433                    {   regm_t rregm; 
    409                         unsigned rreg; 
     434                        unsigned reg; 
    410435 
    411436                        // MOV reg,imm 
    412437                        // MOV EA,reg 
    413438                        // MOV EA+2,reg 
    414                         rregm = getscratch() & ~idxregm(cs.Irm,cs.Isib); 
     439                        rregm = getscratch() & ~idxregm(&cs); 
    415440                        if (rregm) 
    416441                        {   cl = regwithvalue(cl,rregm,e2->EV.Vint,&reg,0); 
    417442                            cs.Iop = 0x89; 
    418443                            cs.Irm |= modregrm(0,reg,0); 
    419444                            c = gen(cl,&cs); 
    420445                            getlvalue_msw(&cs); 
    421446                            c = gen(c,&cs); 
    422447                            freenode(e2); 
    423448                            goto Lp; 
    424449                        } 
    425450                    } 
    426451                } 
    427452            } 
    428453 
    429454            /* If loading result into a register        */ 
    430455            if ((cs.Irm & 0xC0) == 0xC0) 
    431             {   cl = cat(cl,getregs(mask[cs.Irm & 7])); 
     456            {   cl = cat(cl,modEA(&cs)); 
    432457                if (sz == 2 * REGSIZE && cs.IFL1 == FLreg) 
    433458                    cl = cat(cl,getregs(cs.IEVsym1->Sregm)); 
    434459            } 
    435460            cs.Iop = (sz == 1) ? 0xC6 : 0xC7; 
    436461 
    437462            if (e2oper == OPrelconst) 
    438463            { 
    439464                cs.IEVoffset2 = e2->EV.sp.Voffset; 
    440465                cs.IFL2 = fl; 
    441466                cs.IEVsym2 = e2->EV.sp.Vsym; 
    442467                cs.Iflags |= CFoff; 
    443468                cl = gen(cl,&cs);       /* MOV EA,&variable     */ 
     469                if (I64 && sz == 8) 
     470                    code_orrex(cl, REX_W); 
    444471                if (sz > REGSIZE) 
    445472                { 
    446473                    cs.Iop = 0x8C; 
    447474                    getlvalue_msw(&cs); 
    448475                    cs.Irm |= modregrm(0,3,0); 
    449476                    cl = gen(cl,&cs);   /* MOV EA+2,DS  */ 
    450477                } 
    451478            } 
    452479            else 
    453             {   targ_int *p; 
    454  
     480            { 
     481                assert(e2oper == OPconst); 
    455482                cs.IFL2 = FLconst; 
    456                 p = (targ_int *) &(e2->EV); 
    457                 cs.IEV2.Vint = *p; 
     483                targ_size_t *p = (targ_size_t *) &(e2->EV); 
     484                cs.IEV2.Vsize_t = *p; 
    458485                // Look for loading a register variable 
    459486                if ((cs.Irm & 0xC0) == 0xC0) 
    460                 { 
    461                         cl = movregconst(cl,cs.Irm & 7,*p,1 ^ (cs.Iop & 1)); 
    462                         if (sz == 2 * REGSIZE) 
    463                         {   getlvalue_msw(&cs); 
    464                             cl = movregconst(cl,cs.Irm & 7,p[1],0); 
    465                         } 
     487                {   unsigned reg = cs.Irm & 7; 
     488 
     489                    if (cs.Irex & REX_B) 
     490                        reg |= 8; 
     491                    if (I64 && sz == 8) 
     492                        cl = movregconst(cl,reg,*p,CFoffset64); 
     493                    else 
     494                        cl = movregconst(cl,reg,*p,1 ^ (cs.Iop & 1)); 
     495                    if (sz == 2 * REGSIZE) 
     496                    {   getlvalue_msw(&cs); 
     497                        cl = movregconst(cl,cs.Irm & 7,p[1],0); 
     498                    } 
    466499                } 
    467500                else 
    468501                {   int regsize; 
    469502 
    470                         i = sz; 
    471                         do 
    472                         {   regsize = REGSIZE; 
    473                             retregs = (sz == 1) ? BYTEREGS : allregs; 
    474                             if (i >= 4 && !I32 && I386) 
     503                    i = sz; 
     504                    do 
     505                    {   regsize = REGSIZE; 
     506                        retregs = (sz == 1) ? BYTEREGS : allregs; 
     507                        if (i >= 4 && I16 && I386) 
     508                        { 
     509                            regsize = 4; 
     510                            cs.Iflags |= CFopsize;      // use opsize to do 32 bit operation 
     511                        } 
     512                        else 
     513                        { 
     514                            if (reghasvalue(retregs,*p,&reg)) 
    475515                            { 
    476                                 regsize = 4; 
     516                                cs.Iop = (cs.Iop & 1) | 0x88; 
     517                                cs.Irm |= modregrm(0,reg & 7,0); // MOV EA,reg 
     518                                if (reg & 8) 
     519                                    cs.Irex |= REX_R; 
     520                            } 
     521                            if (!I16 && i == 2)      // if 16 bit operand 
    477522                                cs.Iflags |= CFopsize; 
    478                             } 
    479                             else 
    480                             { 
    481                                 if (reghasvalue(retregs,*p,&reg)) 
    482                                 { 
    483                                     cs.Iop = (cs.Iop & 1) | 0x88; 
    484                                     cs.Irm |= reg << 3; /* MOV EA,reg   */ 
    485                                 } 
    486                                 if (I32 && i == 2)      // if 16 bit operand 
    487                                     cs.Iflags |= CFopsize; 
    488                             } 
    489                             cl = gen(cl,&cs);           /* MOV EA,const */ 
    490  
    491                             p = (targ_int *)((char *) p + regsize); 
    492                             cs.Iop = (cs.Iop & 1) | 0xC6; 
    493                             cs.Irm &= ~(7 << 3); 
    494                             cs.IEVoffset1 += regsize; 
    495                             cs.IEV2.Vint = *p; 
    496                             i -= regsize; 
    497                         } while (i > 0); 
     523                            if (I64 && sz == 8) 
     524                                assert(cs.Irex & REX_W); 
     525                        } 
     526                        cl = gen(cl,&cs);           /* MOV EA,const */ 
     527 
     528                        p = (targ_size_t *)((char *) p + regsize); 
     529                        cs.Iop = (cs.Iop & 1) | 0xC6; 
     530                        cs.Irm &= ~modregrm(0,7,0); 
     531                        cs.Irex &= ~REX_R; 
     532                        cs.IEVoffset1 += regsize; 
     533                        cs.IEV2.Vint = *p; 
     534                        i -= regsize; 
     535                    } while (i > 0); 
    498536                } 
    499537            } 
    500538            freenode(e2); 
    501539            c = cl; 
    502540            goto Lp; 
    503541        } 
    504542        retregs = allregs;              /* pick a reg, any reg          */ 
    505543  } 
    506544  if (retregs == mPSW) 
    507545        retregs = allregs; 
    508546  cs.Iop = 0x89; 
    509547  if (sz == 1)                  // must have byte regs 
    510548  {     cs.Iop = 0x88; 
    511549        retregs &= BYTEREGS; 
    512550        if (!retregs) 
    513551                retregs = BYTEREGS; 
    514552  } 
    515553  else if (retregs & mES && 
    516554            ((e1->Eoper == OPind && 
    517555                ((tymll = tybasic(e1->E1->Ety)) == TYfptr || tymll == TYhptr)) 
     
    542580                if (e1->EV.sp.Voffset) 
    543581                    retregs &= mMSW; 
    544582                else 
    545583                    retregs &= mLSW; 
    546584                reg = findreg(retregs); 
    547585            } 
    548586        } 
    549587  } 
    550588  if (*pretregs & mPSW && !EOP(e1))     /* if evaluating e1 couldn't change flags */ 
    551589  {     /* Be careful that this lines up with jmpopcode()       */ 
    552590        retregs |= mPSW; 
    553591        *pretregs &= ~mPSW; 
    554592  } 
    555593  cr = scodelem(e2,&retregs,0,TRUE);    /* get rvalue                   */ 
    556594 
    557595    // Look for special case of (*p++ = ...), where p is a register variable 
    558596    if (e1->Eoper == OPind && 
    559597        ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && 
    560598        e11->E1->Eoper == OPvar && 
    561599        e11->E1->EV.sp.Vsym->Sfl == FLreg && 
    562         (I32 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
     600        (!I16 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
    563601       ) 
    564602    { 
    565603        postinc = e11->E2->EV.Vint; 
    566604        if (e11->Eoper == OPpostdec) 
    567605            postinc = -postinc; 
    568606        cl = getlvalue(&cs,e11,RMstore | retregs); 
    569607        freenode(e11->E2); 
    570608    } 
    571609    else 
    572610    {   postinc = 0; 
    573611        cl = getlvalue(&cs,e1,RMstore | retregs);       // get lvalue (cl == CNIL if regvar) 
    574612    } 
    575613 
    576614  c = getregs_imm(varregm); 
    577615 
    578616  assert(!(retregs & mES && (cs.Iflags & CFSEG) == CFes)); 
    579617  if ((tyml == TYfptr || tyml == TYhptr) && retregs & mES) 
    580618  { 
    581619        reg = findreglsw(retregs); 
    582620        cs.Irm |= modregrm(0,reg,0); 
    583621        c = gen(c,&cs);                 /* MOV EA,reg                   */ 
    584622        getlvalue_msw(&cs);             // point to where segment goes 
    585623        cs.Iop = 0x8C; 
    586624        NEWREG(cs.Irm,0); 
    587625        gen(c,&cs);                     /* MOV EA+2,ES                  */ 
    588626  } 
    589627  else 
    590628  { 
    591         if (I32
     629        if (!I16
    592630        { 
    593631            reg = findreg(retregs & 
    594632                    ((sz > REGSIZE) ? mBP | mLSW : mBP | ALLREGS)); 
    595             cs.Irm |= modregrm(0,reg,0); 
     633            cs.Irm |= modregrm(0,reg & 7,0); 
     634            if (reg & 8) 
     635                cs.Irex |= REX_R; 
    596636            for (; TRUE; sz -= REGSIZE) 
    597637            { 
    598638                // Do not generate mov from register onto itself 
    599639                if (regvar && reg == (cs.Irm & 7)) 
    600640                    break; 
    601641                if (sz == 2)            // if 16 bit operand 
    602642                    cs.Iflags |= CFopsize; 
    603643                c = gen(c,&cs);         // MOV EA+offset,reg 
    604644                if (sz <= REGSIZE) 
    605645                    break; 
    606646                getlvalue_msw(&cs); 
    607647                reg = findregmsw(retregs); 
    608                 NEWREG(cs.Irm,reg); 
     648                code_newreg(&cs, reg); 
    609649            } 
    610650        } 
    611651        else 
    612652        { 
    613653            if (sz > REGSIZE) 
    614654                cs.IEVoffset1 += sz - REGSIZE;  /* 0,2,6        */ 
    615655            reg = findreg(retregs & 
    616656                    (sz > REGSIZE ? mMSW : ALLREGS)); 
    617657            if (tyml == TYdouble || tyml == TYdouble_alias) 
    618658                reg = AX; 
    619659            cs.Irm |= modregrm(0,reg,0); 
    620660            /* Do not generate mov from register onto itself            */ 
    621661            if (!regvar || reg != (cs.Irm & 7)) 
    622662                for (; TRUE; sz -= REGSIZE)             /* 1,2,4        */ 
    623663                { 
    624664                    c = gen(c,&cs);             /* MOV EA+offset,reg            */ 
    625665                    if (sz <= REGSIZE) 
    626666                        break; 
    627667                    cs.IEVoffset1 -= REGSIZE; 
    628668                    if (tyml == TYdouble || tyml == TYdouble_alias) 
    629669                            reg = dblreg[reg]; 
    630670                    else 
    631671                            reg = findreglsw(retregs); 
    632672                    NEWREG(cs.Irm,reg); 
    633673                } 
    634674        } 
    635675  } 
    636676  if (e1->Ecount ||                     /* if lvalue is a CSE or        */ 
    637677      regvar)                           /* rvalue can't be a CSE        */ 
    638678  { 
    639679        c = cat(c,getregs_imm(retregs));        // necessary if both lvalue and 
    640680                                        //  rvalue are CSEs (since a reg 
    641681                                        //  can hold only one e at a time) 
    642682        cssave(e1,retregs,EOP(e1));     /* if lvalue is a CSE           */ 
    643683  } 
    644684 
    645685    c = cat4(cr,cl,c,fixresult(e,retregs,pretregs)); 
    646686Lp: 
    647687    if (postinc) 
    648     {   int reg; 
    649  
    650         reg = findreg(idxregm(cs.Irm,cs.Isib)); 
     688    { 
     689        int reg = findreg(idxregm(&cs)); 
    651690        if (*pretregs & mPSW) 
    652691        {   // Use LEA to avoid touching the flags 
    653             c = genc1(c,0x8D,modregrm(2,reg,cs.Irm & 7),FLconst,postinc); 
     692            unsigned rm = cs.Irm & 7; 
     693            if (cs.Irex & REX_B) 
     694                rm |= 8; 
     695            c = genc1(c,0x8D,modregxrmx(2,reg,rm),FLconst,postinc); 
     696            if (sz == 8) 
     697                code_orrex(c, REX_W); 
     698        } 
     699        else if (I64) 
     700        { 
     701            c = genc2(c,0x81,modregrmx(3,0,reg),postinc); 
     702            if (sz == 8) 
     703                code_orrex(c, REX_W); 
    654704        } 
    655705        else 
    656706        { 
    657707            if (postinc == 1) 
    658708                c = gen1(c,0x40 + reg);         // INC reg 
    659709            else if (postinc == -(targ_int)1) 
    660710                c = gen1(c,0x48 + reg);         // DEC reg 
    661711            else 
    662712            { 
    663713                c = genc2(c,0x81,modregrm(3,0,reg),postinc); 
    664714            } 
    665715        } 
    666716    } 
    667717    freenode(e1); 
    668718    return c; 
    669719} 
    670720 
    671721 
    672722/************************ 
    673723 * Generate code for += -= &= |= ^= negass 
     
    695745  reverse = 0; 
    696746  e1 = e->E1; 
    697747  tyml = tybasic(e1->Ety);              // type of lvalue 
    698748  sz = tysize[tyml]; 
    699749  byte = (sz == 1);                     // 1 for byte operation, else 0 
    700750  if (tyfloating(tyml)) 
    701751  { 
    702752#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    703753      if (op == OPnegass) 
    704754            c = cdnegass87(e,pretregs); 
    705755        else 
    706756            c = opass87(e,pretregs); 
    707757#else 
    708758        if (op == OPnegass) 
    709759            c = opnegassdbl(e,pretregs); 
    710760        else 
    711761            c = opassdbl(e,pretregs,op); 
    712762#endif 
    713763        return c; 
    714764  } 
    715   opsize = (!I32 && tylong(tyml) && config.target_cpu >= TARGET_80386) 
     765  opsize = (I16 && tylong(tyml) && config.target_cpu >= TARGET_80386) 
    716766        ? CFopsize : 0; 
    717767  cflags = 0; 
    718768  forccs = *pretregs & mPSW;            // return result in flags 
    719   forregs = *pretregs & (mBP | ALLREGS | mES);  // return result in regs 
     769  forregs = *pretregs & ~mPSW;          // return result in regs 
    720770  /* TRUE if we want the result in a register   */ 
    721771  wantres = forregs || (e1->Ecount && EOP(e1)); 
    722772 
    723773  switch (op)                   /* select instruction opcodes           */ 
    724774  {     case OPpostinc: op = OPaddass;                  /* i++ => +=    */ 
    725775        case OPaddass:  op1 = 0x01; op2 = 0x11; 
    726776                        cflags = CFpsw; 
    727777                        mode = 0; break;                /* ADD, ADC     */ 
    728778        case OPpostdec: op = OPminass;                  /* i-- => -=    */ 
    729779        case OPminass:  op1 = 0x29; op2 = 0x19; 
    730780                        cflags = CFpsw; 
    731781                        mode = 5; break;                /* SUB, SBC     */ 
    732782        case OPandass:  op1 = op2 = 0x21; 
    733783                        mode = 4; break;                /* AND, AND     */ 
    734784        case OPorass:   op1 = op2 = 0x09; 
    735785                        mode = 1; break;                /* OR , OR      */ 
    736786        case OPxorass:  op1 = op2 = 0x31; 
    737787                        mode = 6; break;                /* XOR, XOR     */ 
    738788        case OPnegass:  op1 = 0xF7;                     // NEG 
    739789                        break; 
    740790        default: 
    741791                assert(0); 
    742792  } 
    743793  op1 ^= byte;                  /* bit 0 is 0 for byte operation        */ 
    744794 
    745795  if (op == OPnegass) 
    746796  { 
    747797        cl = getlvalue(&cs,e1,0); 
    748         cr = modEA(cs.Irm); 
     798        cr = modEA(&cs); 
    749799        cs.Irm |= modregrm(0,3,0); 
    750800        cs.Iop = op1; 
    751801        switch (tysize[tyml]) 
    752802        {   case CHARSIZE: 
    753803                c = gen(CNIL,&cs); 
    754804                break; 
    755805            case SHORTSIZE: 
    756806                c = gen(CNIL,&cs); 
    757                 if (I32 && *pretregs & mPSW) 
     808                if (!I16 && *pretregs & mPSW) 
    758809                    c->Iflags |= CFopsize | CFpsw; 
    759810                break; 
    760811            case LONGSIZE: 
    761                 if (I32 || opsize) 
     813                if (!I16 || opsize) 
    762814                {   c = gen(CNIL,&cs); 
    763815                    c->Iflags |= opsize; 
    764816                    break; 
    765817                } 
    766818            neg_2reg: 
    767819                getlvalue_msw(&cs); 
    768820                c = gen(CNIL,&cs);              // NEG EA+2 
    769821                getlvalue_lsw(&cs); 
    770822                gen(c,&cs);                     // NEG EA 
    771823                code_orflag(c,CFpsw); 
    772824                cs.Iop = 0x81; 
    773825                getlvalue_msw(&cs); 
    774826                cs.IFL2 = FLconst; 
    775827                cs.IEV2.Vuns = 0; 
    776828                gen(c,&cs);                     // SBB EA+2,0 
    777829                break; 
    778830            case LLONGSIZE: 
    779                 if (I32
    780                     goto neg_2reg; 
    781                 assert(0);                      // not implemented yet 
    782                 break; 
     832                if (I16
     833                    assert(0);                      // not implemented yet 
     834                goto neg_2reg; 
     835 
    783836            default: 
    784837                assert(0); 
    785838        } 
    786839        c = cat3(cl,cr,c); 
    787840        forccs = 0;             // flags already set by NEG 
    788841        *pretregs &= ~mPSW; 
    789842  } 
    790843  else if ((e2 = e->E2)->Eoper == OPconst &&    // if rvalue is a const 
    791844       // Don't evaluate e2 in register if we can use an INC or DEC 
    792845      (((sz <= REGSIZE || tyfv(tyml)) && 
    793846        (op == OPaddass || op == OPminass) && 
    794847        ((val = el_tolong(e2)) == 1 || val == -1) 
    795848       ) || 
    796849       (!evalinregister(e2) && tyml != TYhptr) 
    797850      ) 
    798851     ) 
    799852  { 
    800853        cl = getlvalue(&cs,e1,0); 
    801         cl = cat(cl,modEA(cs.Irm)); 
     854        cl = cat(cl,modEA(&cs)); 
    802855        cs.IFL2 = FLconst; 
    803856        cs.IEV2.Vint = e2->EV.Vint; 
    804857        if (sz <= REGSIZE || tyfv(tyml) || opsize) 
    805         {   targ_int i; 
    806  
    807             i = cs.IEV2.Vint; 
     858        { 
     859            targ_size_t i = cs.IEV2.Vsize_t; 
    808860 
    809861            /* Handle shortcuts. Watch out for if result has    */ 
    810862            /* to be in flags.                                  */ 
    811863 
    812864            if (reghasvalue(ALLREGS,i,&reg) && i != 1 && i != -1 && 
    813865                !opsize) 
    814866            { 
    815867                cs.Iop = op1; 
    816868                cs.Irm |= modregrm(0,reg,0); 
    817869            } 
    818870            else 
    819871            { 
    820872                cs.Iop = 0x81; 
    821873                cs.Irm |= modregrm(0,mode,0); 
    822874                switch (op) 
    823875                {   case OPminass:      /* convert to +=        */ 
    824876                        cs.Irm ^= modregrm(0,5,0); 
    825877                        i = -i; 
    826                         cs.IEV2.Vint = i; 
     878                        cs.IEV2.Vsize_t = i; 
    827879                        /* FALL-THROUGH */ 
    828880                    case OPaddass: 
    829881                        if (i == 1)             /* INC EA       */ 
    830882                                goto L1; 
    831883                        else if (i == -1)       /* DEC EA       */ 
    832884                        {       cs.Irm |= modregrm(0,1,0); 
    833885                           L1:  cs.Iop = 0xFF; 
    834886                        } 
    835887                        break; 
    836888                } 
    837889            } 
    838890            cs.Iop ^= byte;             /* for byte operations  */ 
    839891            cs.Iflags |= opsize; 
    840892            if (forccs) 
    841893                cs.Iflags |= CFpsw; 
    842             else if (I32 && cs.Iflags & CFopsize) 
     894            else if (!I16 && cs.Iflags & CFopsize) 
    843895            { 
    844896                switch (op) 
    845897                {   case OPorass: 
    846898                    case OPxorass: 
    847                         cs.IEV2.Vint &= 0xFFFF; 
     899                        cs.IEV2.Vsize_t &= 0xFFFF; 
    848900                        cs.Iflags &= ~CFopsize; // don't worry about MSW 
    849901                        break; 
    850902                    case OPandass: 
    851                         cs.IEV2.Vint |= ~0xFFFFL; 
     903                        cs.IEV2.Vsize_t |= ~0xFFFFLL; 
    852904                        cs.Iflags &= ~CFopsize; // don't worry about MSW 
    853905                        break; 
    854906                    case OPminass: 
    855907                    case OPaddass: 
    856908#if 1 
    857909                        if ((cs.Irm & 0xC0) == 0xC0)    // EA is register 
    858910                            cs.Iflags &= ~CFopsize; 
    859911#else 
    860912                        if ((cs.Irm & 0xC0) == 0xC0 &&  // EA is register and 
    861913                            e1->Eoper == OPind)         // not a register var 
    862914                            cs.Iflags &= ~CFopsize; 
    863915#endif 
    864916                        break; 
    865917                    default: 
    866918                        assert(0); 
    867919                        break; 
    868920                } 
    869921            } 
    870922 
    871923            // For scheduling purposes, we wish to replace: 
    872924            //    OP    EA 
    873925            // with: 
    874926            //    MOV   reg,EA 
    875927            //    OP    reg 
    876928            //    MOV   EA,reg 
    877929            if (forregs && sz <= REGSIZE && (cs.Irm & 0xC0) != 0xC0 && 
    878930                (config.target_cpu == TARGET_Pentium || 
    879931                 config.target_cpu == TARGET_PentiumMMX) && 
    880932                config.flags4 & CFG4speed) 
    881933            {   regm_t sregm; 
    882934                code cs2; 
    883935 
    884936                // Determine which registers to use 
    885                 sregm = allregs & ~idxregm(cs.Irm,cs.Isib); 
     937                sregm = allregs & ~idxregm(&cs); 
    886938                if (byte) 
    887939                    sregm &= BYTEREGS; 
    888940                if (sregm & forregs) 
    889941                    sregm &= forregs; 
    890942 
    891943                cr = allocreg(&sregm,&reg,tyml);        // allocate register 
    892944 
    893945                cs2 = cs; 
    894946                cs2.Iflags &= ~CFpsw; 
    895947                cs2.Iop = 0x8B ^ byte; 
    896                 cs2.Irm = (cs2.Irm & modregrm(3,0,7)) | modregrm(0,reg,0); 
     948                code_newreg(&cs2, reg); 
    897949                cr = gen(cr,&cs2);                      // MOV reg,EA 
    898950 
    899                 cs.Irm = (cs.Irm & modregrm(0,7,0)) | modregrm(3,0,reg); 
     951                cs.Irm = (cs.Irm & modregrm(0,7,0)) | modregrm(3,0,reg & 7); 
     952                if (reg & 8) 
     953                    cs.Irex |= REX_B; 
    900954                gen(cr,&cs);                            // OP reg 
    901955 
    902956                cs2.Iop ^= 2; 
    903957                gen(cr,&cs2);                           // MOV EA,reg 
    904958 
    905959                c = cat(cl,cr); 
    906960                retregs = sregm; 
    907961                wantres = 0; 
    908962                if (e1->Ecount) 
    909963                    cssave(e1,retregs,EOP(e1)); 
    910964            } 
    911965            else 
    912966            { 
    913967                c = gen(cl,&cs); 
    914968                cs.Iflags &= ~opsize; 
    915969                cs.Iflags &= ~CFpsw; 
    916                 if (!I32 && opsize)                     // if DWORD operand 
     970                if (I16 && opsize)                     // if DWORD operand 
    917971                    cs.IEVoffset1 += 2; // compensate for wantres code 
    918972            } 
    919973        } 
    920974        else if (sz == 2 * REGSIZE) 
    921975        {       targ_uns msw; 
    922976 
    923977                cs.Iop = 0x81; 
    924978                cs.Irm |= modregrm(0,mode,0); 
    925979                c = cl; 
    926980                cs.Iflags |= cflags; 
    927981                c = gen(c,&cs); 
    928982                cs.Iflags &= ~CFpsw; 
    929983 
    930984                getlvalue_msw(&cs);             // point to msw 
    931985                msw = MSREG(e->E2->EV.Vllong); 
    932986                cs.IEV2.Vuns = msw;             /* msw of constant      */ 
    933987                switch (op) 
    934988                {   case OPminass: 
    935989                        cs.Irm ^= modregrm(0,6,0);      /* SUB => SBB   */ 
    936990                        break; 
    937991                    case OPaddass: 
    938992                        cs.Irm |= modregrm(0,2,0);      /* ADD => ADC   */ 
    939993                        break; 
    940994                } 
    941995                c = gen(c,&cs); 
    942996        } 
    943997        freenode(e->E2);        /* don't need it anymore        */ 
    944998  } 
    945999  else if (isregvar(e1,&varregm,&varreg) && 
    9461000           (e2->Eoper == OPvar || e2->Eoper == OPind) && 
    9471001          !evalinregister(e2) && 
    9481002           sz <= REGSIZE)               // deal with later 
    9491003  { 
    9501004        cr = getlvalue(&cs,e2,0); 
    9511005        freenode(e2); 
    9521006        cl = getregs(varregm); 
    953         cs.Irm |= modregrm(0,varreg,0); 
     1007        code_newreg(&cs, varreg); 
    9541008        cs.Iop = op1 ^ 2;                       // toggle direction bit 
    9551009        if (forccs) 
    9561010            cs.Iflags |= CFpsw; 
    9571011        reverse = 2;                            // remember we toggled it 
    9581012        cl = gen(cl,&cs); 
    9591013        c = cat(cr,cl); 
    9601014        retregs = 0;            /* to trigger a bug if we attempt to use it */ 
    9611015  } 
    9621016  else // evaluate e2 into register 
    9631017  { 
    9641018        retregs = (byte) ? BYTEREGS : ALLREGS;  // pick working reg 
    9651019        if (tyml == TYhptr) 
    9661020            retregs &= ~mCX;                    // need CX for shift count 
    9671021        cr = scodelem(e->E2,&retregs,0,TRUE);   // get rvalue 
    9681022        cl = getlvalue(&cs,e1,retregs);         // get lvalue 
    969         cl = cat(cl,modEA(cs.Irm)); 
     1023        cl = cat(cl,modEA(&cs)); 
    9701024        cs.Iop = op1; 
    9711025        if (sz <= REGSIZE || tyfv(tyml)) 
    9721026        {   reg = findreg(retregs); 
    973             cs.Irm |= modregrm(0,reg,0);        // OP1 EA,reg 
     1027            code_newreg(&cs, reg);              // OP1 EA,reg 
    9741028        } 
    9751029        else if (tyml == TYhptr) 
    9761030        {   unsigned mreg,lreg; 
    9771031 
    9781032            mreg = findregmsw(retregs); 
    9791033            lreg = findreglsw(retregs); 
    9801034            cl = cat(cl,getregs(retregs | mCX)); 
    9811035 
    9821036            // If h -= l, convert to h += -l 
    9831037            if (e->Eoper == OPminass) 
    9841038            { 
    9851039                cl = gen2(cl,0xF7,modregrm(3,3,mreg));  // NEG mreg 
    9861040                gen2(cl,0xF7,modregrm(3,3,lreg));       // NEG lreg 
    9871041                code_orflag(cl,CFpsw); 
    9881042                genc2(cl,0x81,modregrm(3,3,mreg),0);    // SBB mreg,0 
    9891043            } 
    9901044            cs.Iop = 0x01; 
    9911045            cs.Irm |= modregrm(0,lreg,0); 
    9921046            cl = gen(cl,&cs);                           // ADD EA,lreg 
    9931047            code_orflag(cl,CFpsw); 
     
    10151069 
    10161070  /* See if we need to reload result into a register.   */ 
    10171071  /* Need result in registers in case we have a 32 bit  */ 
    10181072  /* result and we want the flags as a result.          */ 
    10191073  if (wantres || (sz > REGSIZE && forccs)) 
    10201074  { 
    10211075        if (sz <= REGSIZE) 
    10221076        {   regm_t possregs; 
    10231077 
    10241078            possregs = ALLREGS; 
    10251079            if (byte) 
    10261080                possregs = BYTEREGS; 
    10271081            retregs = forregs & possregs; 
    10281082            if (!retregs) 
    10291083                    retregs = possregs; 
    10301084 
    10311085            // If reg field is destination 
    10321086            if (cs.Iop & 2 && cs.Iop < 0x40 && (cs.Iop & 7) <= 5) 
    10331087            { 
    10341088                reg = (cs.Irm >> 3) & 7; 
     1089                if (cs.Irex & REX_R) 
     1090                    reg |= 8; 
    10351091                retregs = mask[reg]; 
    10361092                ce = allocreg(&retregs,&reg,tyml); 
    10371093            } 
    10381094            // If lvalue is a register, just use that register 
    10391095            else if ((cs.Irm & 0xC0) == 0xC0) 
    10401096            { 
    10411097                reg = cs.Irm & 7; 
     1098                if (cs.Irex & REX_B) 
     1099                    reg |= 8; 
    10421100                retregs = mask[reg]; 
    10431101                ce = allocreg(&retregs,&reg,tyml); 
    10441102            } 
    10451103            else 
    10461104            { 
    10471105                ce = allocreg(&retregs,&reg,tyml); 
    10481106                cs.Iop = 0x8B ^ byte ^ reverse; 
    1049                 NEWREG(cs.Irm,reg); 
     1107                code_newreg(&cs, reg); 
    10501108                ce = gen(ce,&cs);               // MOV reg,EA 
    10511109            } 
    10521110        } 
    10531111        else if (tyfv(tyml) || tyml == TYhptr) 
    10541112        {       regm_t idxregs; 
    10551113 
    10561114                if (tyml == TYhptr) 
    10571115                    getlvalue_lsw(&cs); 
    1058                 idxregs = idxregm(cs.Irm,cs.Isib); 
     1116                idxregs = idxregm(&cs); 
    10591117                retregs = forregs & ~idxregs; 
    10601118                if (!(retregs & IDXREGS)) 
    10611119                        retregs |= IDXREGS & ~idxregs; 
    10621120                if (!(retregs & mMSW)) 
    10631121                        retregs |= mMSW & ALLREGS; 
    10641122                ce = allocreg(&retregs,&reg,tyml); 
    10651123                NEWREG(cs.Irm,findreglsw(retregs)); 
    10661124                if (retregs & mES)              /* if want ES loaded    */ 
    10671125                {   cs.Iop = 0xC4; 
    10681126                    ce = gen(ce,&cs);           /* LES lreg,EA          */ 
    10691127                } 
    10701128                else 
    10711129                {   cs.Iop = 0x8B; 
    10721130                    ce = gen(ce,&cs);           /* MOV lreg,EA          */ 
    10731131                    getlvalue_msw(&cs); 
    10741132                    if (I32) 
    10751133                        cs.Iflags |= CFopsize; 
    10761134                    NEWREG(cs.Irm,reg); 
    10771135                    gen(ce,&cs);                /* MOV mreg,EA+2        */ 
    10781136                } 
    10791137        } 
    10801138        else if (sz == 2 * REGSIZE) 
    10811139        {       regm_t idx; 
    10821140                code *cm,*cl; 
    10831141 
    1084                 idx = idxregm(cs.Irm,cs.Isib); 
     1142                idx = idxregm(&cs); 
    10851143                retregs = forregs; 
    10861144                if (!retregs) 
    10871145                        retregs = ALLREGS; 
    10881146                ce = allocreg(&retregs,&reg,tyml); 
    10891147                cs.Iop = 0x8B; 
    10901148                NEWREG(cs.Irm,reg); 
    10911149                cm = gen(NULL,&cs);             // MOV reg,EA+2 
    10921150                NEWREG(cs.Irm,findreglsw(retregs)); 
    10931151                getlvalue_lsw(&cs); 
    10941152                cl = gen(NULL,&cs);             // MOV reg+1,EA 
    10951153                if (mask[reg] & idx) 
    10961154                    ce = cat3(ce,cl,cm); 
    10971155                else 
    10981156                    ce = cat3(ce,cm,cl); 
    10991157        } 
    11001158        c = cat(c,ce); 
    11011159        if (e1->Ecount)                 /* if we gen a CSE      */ 
    11021160                cssave(e1,retregs,EOP(e1)); 
    11031161  } 
    11041162  freenode(e1); 
    11051163  if (sz <= REGSIZE) 
    1106         *pretregs &= mES | ALLREGS | mBP;       // flags are already set 
     1164        *pretregs &= ~mPSW;            // flags are already set 
    11071165  return cat(c,fixresult(e,retregs,pretregs)); 
    11081166} 
    11091167 
    11101168 
    11111169/******************************** 
    11121170 * Generate code for *= /= %= 
    11131171 */ 
    11141172 
    11151173code *cdmulass(elem *e,regm_t *pretregs) 
    11161174{ elem *e1,*e2; 
    11171175  code *cr,*cl,*cg,*c,cs; 
    11181176  tym_t tym,tyml; 
    11191177  regm_t retregs; 
    11201178  char uns; 
    11211179  unsigned op,resreg,reg,opr,lib,byte; 
    11221180  unsigned sz; 
    11231181 
    11241182  e1 = e->E1; 
    11251183  e2 = e->E2; 
    11261184  op = e->Eoper;                        /* OPxxxx                       */ 
    11271185 
    11281186  tyml = tybasic(e1->Ety);              /* type of lvalue               */ 
    11291187  uns = tyuns(tyml) || tyuns(e2->Ety); 
    11301188  tym = tybasic(e->Ety);                /* type of result               */ 
    11311189  sz = tysize[tyml]; 
     1189 
     1190    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1191    unsigned grex = rex << 16;          // 64 bit operands 
     1192 
    11321193 
    11331194  if (tyfloating(tyml)) 
    11341195#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    11351196        return opass87(e,pretregs); 
    11361197#else 
    11371198        return opassdbl(e,pretregs,op); 
    11381199#endif 
    11391200 
    11401201  if (sz <= REGSIZE)                    /* if word or byte              */ 
    11411202  {     byte = (sz == 1);               /* 1 for byte operation         */ 
    11421203        resreg = AX;                    /* result register for * or /   */ 
    11431204        if (uns)                        /* if unsigned operation        */ 
    11441205                opr = 4;                /* MUL                          */ 
    11451206        else                            /* else signed                  */ 
    11461207                opr = 5;                /* IMUL                         */ 
    11471208        if (op != OPmulass)             /* if /= or %=                  */ 
    11481209        {       opr += 2;               /* MUL => DIV, IMUL => IDIV     */ 
    11491210                if (op == OPmodass) 
    11501211                        resreg = DX;    /* remainder is in DX           */ 
    11511212        } 
    11521213        if (op == OPmulass)             /* if multiply                  */ 
    11531214        { 
    11541215            if (config.target_cpu >= TARGET_80286 && 
    11551216                e2->Eoper == OPconst && !byte) 
    1156             {   targ_int e2factor; 
    1157                 regm_t idxregs
    1158  
    1159                 e2factor = el_tolong(e2)
     1217            { 
     1218                targ_size_t e2factor = el_tolong(e2)
     1219                if (I64 && sz == 8 && e2factor != (int)e2factor) 
     1220                    goto L1
    11601221                freenode(e2); 
    11611222                cr = CNIL; 
    11621223                cl = getlvalue(&cs,e1,0);       /* get EA               */ 
    1163                 idxregs = idxregm(cs.Irm,cs.Isib); 
     1224                regm_t idxregs = idxregm(&cs); 
    11641225                retregs = *pretregs & (ALLREGS | mBP) & ~idxregs; 
    11651226                if (!retregs) 
    11661227                    retregs = ALLREGS & ~idxregs; 
    11671228                cg = allocreg(&retregs,&resreg,tyml); 
    11681229                cs.Iop = 0x69;                  /* IMUL reg,EA,e2value  */ 
    11691230                cs.IFL2 = FLconst; 
    11701231                cs.IEV2.Vint = e2factor; 
    11711232                opr = resreg; 
    11721233            } 
    1173             else if (I32 && !byte) 
    1174             { 
     1234            else if (!I16 && !byte) 
     1235            { 
     1236             L1: 
    11751237                retregs = *pretregs & (ALLREGS | mBP); 
    11761238                if (!retregs) 
    11771239                    retregs = ALLREGS; 
    11781240                cr = codelem(e2,&retregs,FALSE); /* load rvalue in reg  */ 
    11791241                cl = getlvalue(&cs,e1,retregs); /* get EA               */ 
    11801242                cg = getregs(retregs);          /* destroy these regs   */ 
    11811243                cs.Iop = 0x0F;                  /* IMUL resreg,EA       */ 
    11821244                cs.Iop2 = 0xAF; 
    11831245                resreg = findreg(retregs); 
    11841246                opr = resreg; 
    11851247            } 
    11861248            else 
    11871249            { 
    11881250                retregs = mAX; 
    11891251                cr = codelem(e2,&retregs,FALSE); // load rvalue in AX 
    11901252                cl = getlvalue(&cs,e1,mAX);     // get EA 
    11911253                cg = getregs(byte ? mAX : mAX | mDX); // destroy these regs 
    11921254                cs.Iop = 0xF7 ^ byte;           // [I]MUL EA 
    11931255            } 
    11941256            cs.Irm |= modregrm(0,opr,0); 
    11951257            c = gen(CNIL,&cs); 
    11961258        } 
    11971259        else // /= or %= 
    1198         {   targ_int e2factor; 
     1260        {   targ_size_t e2factor; 
    11991261            int pow2; 
    12001262            targ_ulong m; 
    12011263 
    12021264            assert(!byte);                      // should never happen 
    1203             assert(!I32 || sz != SHORTSIZE); 
     1265            assert(I16 || sz != SHORTSIZE); 
    12041266            if (config.flags4 & CFG4speed && 
    1205                 e2->Eoper == OPconst && sz == REGSIZE && !uns && 
     1267                e2->Eoper == OPconst && !uns && 
     1268                (sz == REGSIZE || (I64 && sz == 4)) && 
    12061269                (pow2 = ispow2(e2factor = el_tolong(e2))) != -1 && 
     1270                e2factor == (int)e2factor && 
    12071271                !(config.target_cpu < TARGET_80286 && pow2 != 1 && op == OPdivass) 
    12081272               ) 
    12091273            { 
    12101274                // Signed divide or modulo by power of 2 
    12111275                cr = NULL; 
    12121276                c = NULL; 
    12131277                cl = getlvalue(&cs,e1,mAX | mDX); 
    12141278                cs.Iop = 0x8B; 
    1215                 NEWREG(cs.Irm,AX); 
     1279                code_newreg(&cs, AX); 
    12161280                cl = gen(cl,&cs);                       // MOV AX,EA 
    12171281                freenode(e2); 
    12181282                cg = getregs(mAX | mDX);                // trash these regs 
    12191283                cg = gen1(cg,0x99);                     // CWD 
     1284                code_orrex(cg, rex); 
    12201285                if (pow2 == 1) 
    12211286                { 
    12221287                    if (op == OPdivass) 
    1223                     {   gen2(cg,0x2B,modregrm(3,AX,DX));        // SUB AX,DX 
    1224                         gen2(cg,0xD1,modregrm(3,7,AX));         // SAR AX,1 
     1288                    {   gen2(cg,0x2B,grex | modregrm(3,AX,DX));        // SUB AX,DX 
     1289                        gen2(cg,0xD1,grex | modregrm(3,7,AX));         // SAR AX,1 
    12251290                        resreg = AX; 
    12261291                    } 
    12271292                    else // OPmod 
    1228                     {   gen2(cg,0x33,modregrm(3,AX,DX));        // XOR AX,DX 
    1229                         genc2(cg,0x81,modregrm(3,4,AX),1);      // AND AX,1 
    1230                         gen2(cg,0x03,modregrm(3,DX,AX));        // ADD DX,AX 
     1293                    {   gen2(cg,0x33,grex | modregrm(3,AX,DX));        // XOR AX,DX 
     1294                        genc2(cg,0x81,grex | modregrm(3,4,AX),1);      // AND AX,1 
     1295                        gen2(cg,0x03,grex | modregrm(3,DX,AX));        // ADD DX,AX 
    12311296                        resreg = DX; 
    12321297                    } 
    12331298                } 
    12341299                else 
    1235                 {   targ_ulong m; 
    1236  
    1237                     m = (1 << pow2) - 1; 
     1300                { 
     1301                    assert(pow2 < 32); 
     1302                    targ_ulong m = (1 << pow2) - 1; 
    12381303                    if (op == OPdivass) 
    1239                     {   genc2(cg,0x81,modregrm(3,4,DX),m);      // AND DX,m 
    1240                         gen2(cg,0x03,modregrm(3,AX,DX));        // ADD AX,DX 
     1304                    {   genc2(cg,0x81,grex | modregrm(3,4,DX),m);      // AND DX,m 
     1305                        gen2(cg,0x03,grex | modregrm(3,AX,DX));        // ADD AX,DX 
    12411306                        // Be careful not to generate this for 8088 
    12421307                        assert(config.target_cpu >= TARGET_80286); 
    1243                         genc2(cg,0xC1,modregrm(3,7,AX),pow2);   // SAR AX,pow2 
     1308                        genc2(cg,0xC1,grex | modregrm(3,7,AX),pow2);   // SAR AX,pow2 
    12441309                        resreg = AX; 
    12451310                    } 
    12461311                    else // OPmodass 
    1247                     {   gen2(cg,0x33,modregrm(3,AX,DX));        // XOR AX,DX 
    1248                         gen2(cg,0x2B,modregrm(3,AX,DX));        // SUB AX,DX 
    1249                         genc2(cg,0x81,modregrm(3,4,AX),m);      // AND AX,m 
    1250                         gen2(cg,0x33,modregrm(3,AX,DX));        // XOR AX,DX 
    1251                         gen2(cg,0x2B,modregrm(3,AX,DX));        // SUB AX,DX 
     1312                    {   gen2(cg,0x33,grex | modregrm(3,AX,DX));        // XOR AX,DX 
     1313                        gen2(cg,0x2B,grex | modregrm(3,AX,DX));        // SUB AX,DX 
     1314                        genc2(cg,0x81,grex | modregrm(3,4,AX),m);      // AND AX,m 
     1315                        gen2(cg,0x33,grex | modregrm(3,AX,DX));        // XOR AX,DX 
     1316                        gen2(cg,0x2B,grex | modregrm(3,AX,DX));        // SUB AX,DX 
    12521317                        resreg = AX; 
    12531318                    } 
    12541319                } 
    12551320            } 
    12561321            else 
    12571322            { 
    12581323                retregs = ALLREGS & ~(mAX|mDX);         // DX gets sign extension 
    12591324                cr = codelem(e2,&retregs,FALSE);        // load rvalue in retregs 
    12601325                reg = findreg(retregs); 
    12611326                cl = getlvalue(&cs,e1,mAX | mDX | retregs);     // get EA 
    12621327                cg = getregs(mAX | mDX);        // destroy these regs 
    12631328                cs.Irm |= modregrm(0,AX,0); 
    12641329                cs.Iop = 0x8B; 
    12651330                c = gen(CNIL,&cs);              // MOV AX,EA 
    12661331                if (uns)                        // if unsigned 
    12671332                    movregconst(c,DX,0,0);      // CLR DX 
    12681333                else                            // else signed 
    1269                     gen1(c,0x99);               // CWD 
     1334                {   gen1(c,0x99);               // CWD 
     1335                    code_orrex(c,rex); 
     1336                } 
    12701337                c = cat(c,getregs(mDX | mAX));  // DX and AX will be destroyed 
    12711338                genregs(c,0xF7,opr,reg);        // OPR reg 
     1339                code_orrex(c,rex); 
    12721340            } 
    12731341        } 
    12741342        cs.Iop = 0x89 ^ byte; 
    12751343        NEWREG(cs.Irm,resreg); 
    12761344        c = gen(c,&cs);                         // MOV EA,resreg 
    12771345        if (e1->Ecount)                         // if we gen a CSE 
    12781346                cssave(e1,mask[resreg],EOP(e1)); 
    12791347        freenode(e1); 
    12801348        c = cat(c,fixresult(e,mask[resreg],pretregs)); 
    12811349        return cat4(cr,cl,cg,c); 
    12821350  } 
    12831351  else if (sz == 2 * REGSIZE) 
    12841352  { 
    12851353        lib = CLIBlmul; 
    12861354        if (op == OPdivass || op == OPmodass) 
    12871355        {       lib = (uns) ? CLIBuldiv : CLIBldiv; 
    12881356                if (op == OPmodass) 
    12891357                        lib++; 
    12901358        } 
    12911359        retregs = mCX | mBX; 
     
    12991367        gen(cl,&cs);                    /* MOV DX,EA+2                  */ 
    13001368        getlvalue_lsw(&cs); 
    13011369        retregs = 0; 
    13021370        if (config.target_cpu >= TARGET_PentiumPro && op == OPmulass) 
    13031371        { 
    13041372            /*  IMUL    ECX,EAX 
    13051373                IMUL    EDX,EBX 
    13061374                ADD     ECX,EDX 
    13071375                MUL     EBX 
    13081376                ADD     EDX,ECX 
    13091377             */ 
    13101378             c = getregs(mAX|mDX|mCX); 
    13111379             c = gen2(c,0x0FAF,modregrm(3,CX,AX)); 
    13121380             gen2(c,0x0FAF,modregrm(3,DX,BX)); 
    13131381             gen2(c,0x03,modregrm(3,CX,DX)); 
    13141382             gen2(c,0xF7,modregrm(3,4,BX)); 
    13151383             gen2(c,0x03,modregrm(3,DX,CX)); 
    13161384             retregs = mDX | mAX; 
    13171385        } 
    13181386        else 
    1319             c = callclib(e,lib,&retregs,idxregm(cs.Irm,cs.Isib)); 
     1387            c = callclib(e,lib,&retregs,idxregm(&cs)); 
    13201388        reg = (op == OPmodass) ? BX : AX; 
    13211389        retregs = mask[reg]; 
    13221390        cs.Iop = 0x89; 
    13231391        NEWREG(cs.Irm,reg); 
    13241392        gen(c,&cs);                     /* MOV EA,lsreg                 */ 
    13251393        reg = (op == OPmodass) ? CX : DX; 
    13261394        retregs |= mask[reg]; 
    13271395        NEWREG(cs.Irm,reg); 
    13281396        getlvalue_msw(&cs); 
    13291397        gen(c,&cs);                     /* MOV EA+2,msreg               */ 
    13301398        if (e1->Ecount)         /* if we gen a CSE              */ 
    13311399                cssave(e1,retregs,EOP(e1)); 
    13321400        freenode(e1); 
    13331401        cg = fixresult(e,retregs,pretregs); 
    13341402        return cat4(cr,cl,c,cg); 
    13351403  } 
    13361404  else 
    13371405  {     assert(0); 
    13381406        /* NOTREACHED */ 
    13391407        return 0; 
     
    13481416code *cdshass(elem *e,regm_t *pretregs) 
    13491417{ elem *e1,*e2; 
    13501418  code *cr,*cl,*cg,*c,cs,*ce; 
    13511419  tym_t tym,tyml,uns; 
    13521420  regm_t retregs; 
    13531421  unsigned shiftcnt,op1,op2,reg,v,oper,byte,conste2; 
    13541422  unsigned loopcnt; 
    13551423  unsigned sz; 
    13561424 
    13571425  e1 = e->E1; 
    13581426  e2 = e->E2; 
    13591427 
    13601428  tyml = tybasic(e1->Ety);              /* type of lvalue               */ 
    13611429  sz = tysize[tyml]; 
    13621430  byte = tybyte(e->Ety) != 0;           /* 1 for byte operations        */ 
    13631431  uns = tyuns(tyml); 
    13641432  tym = tybasic(e->Ety);                /* type of result               */ 
    13651433  oper = e->Eoper; 
    13661434  assert(tysize(e2->Ety) <= REGSIZE); 
    13671435 
     1436    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1437    unsigned grex = rex << 16;          // 64 bit operands 
     1438 
    13681439  // if our lvalue is a cse, make sure we evaluate for result in register 
    13691440  if (e1->Ecount && !(*pretregs & (ALLREGS | mBP)) && !isregvar(e1,&retregs,&reg)) 
    13701441        *pretregs |= ALLREGS; 
    13711442 
    13721443#if SCPP 
    13731444  // Do this until the rest of the compiler does OPshr/OPashr correctly 
    13741445  if (oper == OPshrass) 
    13751446        oper = (uns) ? OPshrass : OPashrass; 
    13761447#endif 
    13771448 
    13781449  // Select opcodes. op2 is used for msw for long shifts. 
    13791450 
    13801451  switch (oper) 
    13811452  {     case OPshlass: 
    13821453            op1 = 4;                    // SHL 
    13831454            op2 = 2;                    // RCL 
    13841455            break; 
    13851456        case OPshrass: 
    13861457            op1 = 5;                    // SHR 
    13871458            op2 = 3;                    // RCR 
     
    14021473  if (cnst(e2)) 
    14031474  { 
    14041475        conste2 = TRUE;                 /* e2 is a constant             */ 
    14051476        shiftcnt = e2->EV.Vint;         /* byte ordering of host        */ 
    14061477        if (config.target_cpu >= TARGET_80286 && 
    14071478            sz <= REGSIZE && 
    14081479            shiftcnt != 1) 
    14091480            v = 0xC1;                   // SHIFT xx,shiftcnt 
    14101481        else if (shiftcnt <= 3) 
    14111482        {   loopcnt = shiftcnt; 
    14121483            v = 0xD1;                   // SHIFT xx,1 
    14131484        } 
    14141485  } 
    14151486  if (v == 0xD3)                        /* if COUNT == CL               */ 
    14161487  {     retregs = mCX; 
    14171488        cr = codelem(e2,&retregs,FALSE); 
    14181489  } 
    14191490  else 
    14201491        freenode(e2); 
    14211492  cl = getlvalue(&cs,e1,mCX);           /* get lvalue, preserve CX      */ 
    1422   cl = cat(cl,modEA(cs.Irm));           /* check for modifying register */ 
     1493  cl = cat(cl,modEA(&cs));              // check for modifying register 
    14231494 
    14241495  if (*pretregs == 0 ||                 /* if don't return result       */ 
    14251496      (*pretregs == mPSW && conste2 && tysize[tym] <= REGSIZE) || 
    14261497      sz > REGSIZE 
    14271498     ) 
    14281499  {     retregs = 0;            // value not returned in a register 
    14291500        cs.Iop = v ^ byte; 
    14301501        c = CNIL; 
    14311502        while (loopcnt--) 
    14321503        { 
    14331504          NEWREG(cs.Irm,op1);           /* make sure op1 is first       */ 
    14341505          if (sz <= REGSIZE) 
    14351506          {   cs.IFL2 = FLconst; 
    14361507              cs.IEV2.Vint = shiftcnt; 
    14371508              c = gen(c,&cs);           /* SHIFT EA,[CL|1]              */ 
    14381509              if (*pretregs & mPSW && !loopcnt && conste2) 
    14391510                code_orflag(c,CFpsw); 
    14401511          } 
    14411512          else /* TYlong */ 
    14421513          {   cs.Iop = 0xD1;            /* plain shift                  */ 
     
    14771548 
    14781549        if (sz == 2 * REGSIZE && *pretregs) 
    14791550        {   retregs = *pretregs & (ALLREGS | mBP); 
    14801551            if (retregs) 
    14811552            {   ce = allocreg(&retregs,&reg,tym); 
    14821553                cs.Iop = 0x8B; 
    14831554 
    14841555                /* be careful not to trash any index regs       */ 
    14851556                /* do MSW first (which can't be an index reg)   */ 
    14861557                getlvalue_msw(&cs); 
    14871558                NEWREG(cs.Irm,reg); 
    14881559                cg = gen(CNIL,&cs); 
    14891560                getlvalue_lsw(&cs); 
    14901561                reg = findreglsw(retregs); 
    14911562                NEWREG(cs.Irm,reg); 
    14921563                gen(cg,&cs); 
    14931564                if (*pretregs & mPSW) 
    14941565                    cg = cat(cg,tstresult(retregs,tyml,TRUE)); 
    14951566            } 
    14961567            else        /* flags only   */ 
    1497             {   retregs = ALLREGS & ~idxregm(cs.Irm,cs.Isib); 
     1568            {   retregs = ALLREGS & ~idxregm(&cs); 
    14981569                ce = allocreg(&retregs,&reg,TYint); 
    14991570                cs.Iop = 0x8B; 
    15001571                NEWREG(cs.Irm,reg); 
    15011572                cg = gen(CNIL,&cs);     /* MOV reg,EA           */ 
    15021573                cs.Iop = 0x0B;          /* OR reg,EA+2          */ 
    15031574                cs.Iflags |= CFpsw; 
    15041575                getlvalue_msw(&cs); 
    15051576                gen(cg,&cs); 
    15061577            } 
    15071578            c = cat3(c,ce,cg); 
    15081579        } 
    15091580        cg = CNIL; 
    15101581  } 
    15111582 
    15121583 
    15131584  else                                  /* else must evaluate in register */ 
    15141585  { 
    15151586        if (sz <= REGSIZE) 
    1516         {   regm_t possregs; 
    1517  
    1518             possregs = ALLREGS & ~mCX & ~idxregm(cs.Irm,cs.Isib); 
     1585        { 
     1586            regm_t possregs = ALLREGS & ~mCX & ~idxregm(&cs); 
    15191587            if (byte) 
    15201588                    possregs &= BYTEREGS; 
    15211589            retregs = *pretregs & possregs; 
    15221590            if (retregs == 0) 
    15231591                    retregs = possregs; 
    15241592            cg = allocreg(&retregs,&reg,tym); 
    15251593            cs.Iop = 0x8B ^ byte; 
    1526             cs.Irm |= modregrm(0,reg,0); 
     1594            code_newreg(&cs, reg); 
    15271595            c = ce = gen(CNIL,&cs);                     /* MOV reg,EA   */ 
    1528             if (I32
     1596            if (!I16
    15291597            { 
    15301598                assert(!byte || (mask[reg] & BYTEREGS)); 
    1531                 ce = genc2(CNIL,v ^ byte,modregrm(3,op1,reg),shiftcnt); 
     1599                ce = genc2(CNIL,v ^ byte,modregrmx(3,op1,reg),shiftcnt); 
     1600                code_orrex(ce, rex); 
    15321601                /* We can do a 32 bit shift on a 16 bit operand if      */ 
    15331602                /* it's a left shift and we're not concerned about      */ 
    15341603                /* the flags. Remember that flags are not set if        */ 
    15351604                /* a shift of 0 occurs.                         */ 
    15361605                if (tysize[tym] == SHORTSIZE && 
    15371606                    (oper == OPshrass || oper == OPashrass || 
    15381607                     (*pretregs & mPSW && conste2))) 
    15391608                     ce->Iflags |= CFopsize;            /* 16 bit operand */ 
    15401609                cat(c,ce); 
    15411610            } 
    15421611            else 
    15431612            { 
    15441613                while (loopcnt--) 
    15451614                {   /* Generate shift instructions.     */ 
    15461615                    genc2(ce,v ^ byte,modregrm(3,op1,reg),shiftcnt); 
    15471616                } 
    15481617            } 
    15491618            if (*pretregs & mPSW && conste2) 
    15501619            {   assert(shiftcnt); 
    15511620                *pretregs &= ~mPSW;     // result is already in flags 
     
    15961665  e1 = e->E1; 
    15971666  e2 = e->E2; 
    15981667  if (*pretregs == 0)                   /* if don't want result         */ 
    15991668  {     cl = codelem(e1,pretregs,FALSE); 
    16001669        *pretregs = 0;                  /* in case e1 changed it        */ 
    16011670        cr = codelem(e2,pretregs,FALSE); 
    16021671        return cat(cl,cr); 
    16031672  } 
    16041673 
    16051674  jop = jmpopcode(e);                   // must be computed before 
    16061675                                        // leaves are free'd 
    16071676  reverse = 0; 
    16081677  cl = cr = CNIL; 
    16091678  op = e->Eoper; 
    16101679  assert(OTrel(op)); 
    16111680  eqorne = (op == OPeqeq) || (op == OPne); 
    16121681 
    16131682  tym = tybasic(e1->Ety); 
    16141683  sz = tysize[tym]; 
    16151684  byte = sz == 1; 
     1685 
     1686    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1687    unsigned grex = rex << 16;          // 64 bit operands 
     1688 
    16161689#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    16171690  if (tyfloating(tym))                  /* if floating operation        */ 
    16181691  { 
    16191692        retregs = mPSW; 
    16201693        c = orth87(e,&retregs); 
    16211694        goto L3; 
    16221695  } 
    16231696#else 
    16241697  if (tyfloating(tym))                  /* if floating operation        */ 
    16251698  { 
    16261699        if (config.inline8087) 
    16271700        {   retregs = mPSW; 
    16281701            c = orth87(e,&retregs); 
    16291702        } 
    16301703        else 
    16311704        {   int clib; 
    16321705 
    16331706            retregs = 0;                /* skip result for now          */ 
    16341707            if (iffalse(e2))            /* second operand is constant 0 */ 
    16351708            {   assert(!eqorne);        /* should be OPbool or OPnot    */ 
     
    16461719                cl = codelem(e1,&retregs,FALSE); 
    16471720                retregs = 0; 
    16481721                c = callclib(e,clib,&retregs,0); 
    16491722                freenode(e2); 
    16501723            } 
    16511724            else 
    16521725            {   clib = CLIBdcmp; 
    16531726                if (rel_exception(op)) 
    16541727                    clib += CLIBdcmpexc - CLIBdcmp; 
    16551728                c = opdouble(e,&retregs,clib); 
    16561729            } 
    16571730        } 
    16581731        goto L3; 
    16591732  } 
    16601733#endif 
    16611734 
    16621735  /* If it's a signed comparison of longs, we have to call a library    */ 
    16631736  /* routine, because we don't know the target of the signed branch     */ 
    16641737  /* (have to set up flags so that jmpopcode() will do it right)        */ 
    16651738  if (!eqorne && 
    1666         (!I32 && tym == TYlong  && tybasic(e2->Ety) == TYlong || 
    1667           I32 && tym == TYllong && tybasic(e2->Ety) == TYllong) 
     1739        (I16 && tym == TYlong  && tybasic(e2->Ety) == TYlong || 
     1740         I32 && tym == TYllong && tybasic(e2->Ety) == TYllong) 
    16681741     ) 
    16691742  {     retregs = mDX | mAX; 
    16701743        cl = codelem(e1,&retregs,FALSE); 
    16711744        retregs = mCX | mBX; 
    16721745        cr = scodelem(e2,&retregs,mDX | mAX,FALSE); 
    16731746        retregs = 0; 
    16741747        c = callclib(e,CLIBlcmp,&retregs,0);    /* gross, but it works  */ 
    16751748        goto L3; 
    16761749  } 
    16771750 
    16781751  /* See if we should swap operands     */ 
    16791752  if (e1->Eoper == OPvar && e2->Eoper == OPvar && evalinregister(e2)) 
    16801753  {     e1 = e->E2; 
    16811754        e2 = e->E1; 
    16821755        reverse = 2; 
    16831756  } 
    16841757 
    16851758  retregs = allregs; 
    16861759  if (byte) 
    16871760        retregs = BYTEREGS; 
    16881761 
    16891762  c = CNIL; 
    16901763  ce = CNIL; 
    1691   cs.Iflags = (I32 && sz == SHORTSIZE) ? CFopsize : 0; 
    1692   cs.Irex = 0
     1764  cs.Iflags = (!I16 && sz == SHORTSIZE) ? CFopsize : 0; 
     1765  cs.Irex = rex
    16931766  if (sz > REGSIZE) 
    16941767        ce = gennop(ce); 
    16951768 
    16961769  switch (e2->Eoper) 
    16971770  { 
    16981771      default: 
    16991772      L2: 
    17001773        cl = scodelem(e1,&retregs,0,TRUE);      /* compute left leaf    */ 
    17011774      L1: 
    17021775        rretregs = allregs & ~retregs; 
    17031776        if (byte) 
    17041777                rretregs &= BYTEREGS; 
    17051778        cr = scodelem(e2,&rretregs,retregs,TRUE);       /* get right leaf */ 
    17061779        if (sz <= REGSIZE)                              /* CMP reg,rreg  */ 
    17071780        {   reg = findreg(retregs);             /* get reg that e1 is in */ 
    17081781            rreg = findreg(rretregs); 
    17091782            c = genregs(CNIL,0x3B ^ byte ^ reverse,reg,rreg); 
    1710             if (I32 && sz == SHORTSIZE) 
     1783            code_orrex(c, rex); 
     1784            if (!I16 && sz == SHORTSIZE) 
    17111785                c->Iflags |= CFopsize;          /* compare only 16 bits */ 
    17121786        } 
    17131787        else 
    17141788        {   assert(sz <= 2 * REGSIZE); 
    17151789 
    17161790            /* Compare MSW, if they're equal then compare the LSW       */ 
    17171791            reg = findregmsw(retregs); 
    17181792            rreg = findregmsw(rretregs); 
    17191793            c = genregs(CNIL,0x3B ^ reverse,reg,rreg);  /* CMP reg,rreg */ 
    1720             if (I32 && sz == 6) 
     1794            if (!I16 && sz == 6) 
    17211795                c->Iflags |= CFopsize;          /* seg is only 16 bits  */ 
    17221796            genjmp(c,JNE,FLcode,(block *) ce);          /* JNE nop      */ 
    17231797 
    17241798            reg = findreglsw(retregs); 
    17251799            rreg = findreglsw(rretregs); 
    17261800            genregs(c,0x3B ^ reverse,reg,rreg);         /* CMP reg,rreg */ 
    17271801        } 
    17281802        break; 
    17291803      case OPrelconst: 
    17301804        fl = el_fl(e2); 
    17311805        switch (fl) 
    17321806        {   case FLfunc: 
    17331807                fl = FLextern;          // so it won't be self-relative 
    17341808                break; 
    17351809            case FLdata: 
    17361810            case FLudata: 
    17371811            case FLextern: 
    17381812                if (sz > REGSIZE)       // compare against DS, not DGROUP 
    17391813                    goto L2; 
    17401814                break; 
     
    17471821        cs.IEVsym2 = e2->EV.sp.Vsym; 
    17481822        offset2 = e2->EV.sp.Voffset; 
    17491823        if (sz > REGSIZE) 
    17501824        {   cs.Iflags |= CFseg; 
    17511825            cs.IEVoffset2 = 0; 
    17521826        } 
    17531827        else 
    17541828        {   cs.Iflags |= CFoff; 
    17551829            cs.IEVoffset2 = offset2; 
    17561830        } 
    17571831        goto L4; 
    17581832 
    17591833      case OPconst: 
    17601834        // If compare against 0 
    17611835        if (sz <= REGSIZE && *pretregs == mPSW && !boolres(e2) && 
    17621836            isregvar(e1,&retregs,&reg) 
    17631837           ) 
    17641838        {   // Just do a TEST instruction 
    17651839            c = genregs(NULL,0x85 ^ byte,reg,reg);      // TEST reg,reg 
    17661840            c->Iflags |= (cs.Iflags & CFopsize) | CFpsw; 
     1841            code_orrex(c, rex); 
    17671842            retregs = mPSW; 
    17681843            break; 
    17691844        } 
    17701845 
    17711846        if (!tyuns(tym) && !tyuns(e2->Ety) && 
    1772             !boolres(e2) && !(*pretregs & mPSW) && sz == REGSIZE && 
    1773             (I32 || op == OPlt || op == OPge)) 
     1847            !boolres(e2) && !(*pretregs & mPSW) && 
     1848            (sz == REGSIZE || (I64 && sz == 4)) && 
     1849            (!I16 || op == OPlt || op == OPge)) 
    17741850        {   unsigned regi; 
    17751851 
    17761852            assert(*pretregs & (allregs)); 
    17771853            cl = codelem(e1,pretregs,FALSE); 
    17781854            reg = findreg(*pretregs); 
    17791855            c = getregs(mask[reg]); 
    17801856            switch (op) 
    17811857            {   case OPle: 
    1782                     c = genc2(c,0x81,modregrm(3,0,reg),(unsigned)-1);   /* ADD reg,-1   */ 
    1783                     genc2(c,0x81,modregrm(3,2,reg),0);          /* ADC reg,0    */ 
     1858                    c = genc2(c,0x81,grex | modregrmx(3,0,reg & 7),(unsigned)-1);   // ADD reg,-1 
     1859                    genc2(c,0x81,grex | modregrmx(3,2,reg & 7),0);          // ADC reg,0 
    17841860                    goto oplt; 
    17851861                case OPgt: 
    1786                     c = gen2(c,0xF7,modregrm(3,3,reg));         // NEG reg 
     1862                    c = gen2(c,0xF7,grex | modregrmx(3,3,reg & 7));         // NEG reg 
    17871863#if TARGET_WINDOS 
    17881864                    // What does the Windows platform do? 
    17891865                    //  lower INT_MIN by 1?   See test exe9.c 
    17901866                    // BUG: fix later 
    1791                     genc2(c,0x81,modregrm(3,3,reg),0);  // SBB reg,0 
     1867                    genc2(c,0x81,grex | modregrmx(3,3,reg & 7),0);  // SBB reg,0 
    17921868#endif 
    17931869                    goto oplt; 
    17941870                case OPlt: 
    17951871                oplt: 
    1796                     if (I32
    1797                         c = genc2(c,0xC1,modregrm(3,5,reg),31); /* SHR reg,31   */ 
     1872                    if (!I16
     1873                        c = genc2(c,0xC1,grex | modregrmx(3,5,reg & 7),sz * 8 - 1); // SHR reg,31 
    17981874                    else 
    17991875                    {   /* 8088-286 do not have a barrel shifter, so use this 
    18001876                           faster sequence 
    18011877                         */ 
    18021878                        c = genregs(c,0xD1,0,reg);              /* ROL reg,1    */ 
    18031879                        if (reghasvalue(allregs,1,&regi)) 
    18041880                            c = genregs(c,0x23,reg,regi);       /* AND reg,regi */ 
    18051881                        else 
    18061882                            c = genc2(c,0x81,modregrm(3,4,reg),1); /* AND reg,1 */ 
    18071883                    } 
    18081884                    break; 
    18091885                case OPge: 
    18101886                    c = genregs(c,0xD1,4,reg);          /* SHL reg,1    */ 
     1887                    code_orrex(c,rex); 
    18111888                    genregs(c,0x19,reg,reg);            /* SBB reg,reg  */ 
    1812                     gen1(c,0x40 + reg);                 /* INC reg      */ 
     1889                    code_orrex(c,rex); 
     1890                    if (I64) 
     1891                    { 
     1892                        c = gen2(c,0xFF,modregrmx(3,0,reg));    // INC reg 
     1893                        code_orrex(c, rex); 
     1894                    } 
     1895                    else 
     1896                        c = gen1(c,0x40 + reg);                 // INC reg 
    18131897                    break; 
    18141898                default: 
    18151899                    assert(0); 
    18161900            } 
    18171901            freenode(e2); 
    18181902            goto ret; 
    18191903        } 
    18201904 
    18211905        if (sz > REGSIZE) 
    18221906            cs.IEV2.Vint = MSREG(e2->EV.Vllong); 
    18231907        else 
    18241908            cs.IEV2.Vint = e2->EV.Vint; 
    18251909        cs.IFL2 = FLconst; 
    18261910      L4: 
    18271911        cs.Iop = 0x81 ^ byte; 
    18281912 
    18291913        /* if ((e1 is data or a '*' reference) and it's not a 
    18301914         * common subexpression 
    18311915         */ 
    18321916 
    18331917        if ((e1->Eoper == OPvar && datafl[el_fl(e1)] || 
    18341918             e1->Eoper == OPind) && 
    18351919            !evalinregister(e1)) 
    18361920        {       cl = getlvalue(&cs,e1,RMload); 
    18371921                freenode(e1); 
    18381922                if (evalinregister(e2)) 
    18391923                { 
    1840                     retregs = idxregm(cs.Irm,cs.Isib); 
     1925                    retregs = idxregm(&cs); 
    18411926                    if ((cs.Iflags & CFSEG) == CFes) 
    18421927                            retregs |= mES;             /* take no chances */ 
    18431928                    rretregs = allregs & ~retregs; 
    18441929                    if (byte) 
    18451930                            rretregs &= BYTEREGS; 
    18461931                    cr = scodelem(e2,&rretregs,retregs,TRUE); 
    18471932                    cs.Iop = 0x39 ^ byte ^ reverse; 
    18481933                    if (sz > REGSIZE) 
    18491934                    { 
    18501935                        rreg = findregmsw(rretregs); 
    18511936                        cs.Irm |= modregrm(0,rreg,0); 
    18521937                        getlvalue_msw(&cs); 
    18531938                        c = gen(CNIL,&cs);              /* CMP EA+2,rreg */ 
    18541939                        if (I32 && sz == 6) 
    18551940                            c->Iflags |= CFopsize;      /* seg is only 16 bits  */ 
    18561941                        genjmp(c,JNE,FLcode,(block *) ce); /* JNE nop   */ 
    18571942                        rreg = findreglsw(rretregs); 
    18581943                        NEWREG(cs.Irm,rreg); 
    18591944                        getlvalue_lsw(&cs); 
    18601945                    } 
    18611946                    else 
    18621947                    { 
    18631948                        rreg = findreg(rretregs); 
    1864                         cs.Irm |= modregrm(0,rreg,0); 
     1949                        code_newreg(&cs, rreg); 
    18651950                    } 
    18661951                } 
    18671952                else 
    18681953                { 
    18691954                    cs.Irm |= modregrm(0,7,0); 
    18701955                    if (sz > REGSIZE) 
    18711956                    { 
    18721957#if TARGET_FLAT 
    18731958                        if (sz == 6) 
    18741959                            assert(0); 
    18751960#endif 
    18761961                        if (e2->Eoper == OPrelconst) 
    18771962                        {   cs.Iflags = (cs.Iflags & ~(CFoff | CFseg)) | CFseg; 
    18781963                            cs.IEVoffset2 = 0; 
    18791964                        } 
    18801965                        getlvalue_msw(&cs); 
    18811966                        c = gen(CNIL,&cs);              /* CMP EA+2,const */ 
    1882                         if (I32 && sz == 6) 
     1967                        if (!I16 && sz == 6) 
    18831968                            c->Iflags |= CFopsize;      /* seg is only 16 bits  */ 
    18841969                        genjmp(c,JNE,FLcode,(block *) ce); /* JNE nop   */ 
    18851970                        if (e2->Eoper == OPconst) 
    18861971                            cs.IEV2.Vint = e2->EV.Vllong; 
    18871972                        else 
    18881973                        {   /* Turn off CFseg, on CFoff */ 
    18891974                            cs.Iflags ^= CFseg | CFoff; 
    18901975                            cs.IEVoffset2 = offset2; 
    18911976                        } 
    18921977                        getlvalue_lsw(&cs); 
    18931978                    } 
    18941979                    freenode(e2); 
    18951980                } 
    18961981                c = gen(c,&cs); 
    18971982                break; 
    18981983        } 
    18991984 
    19001985        if (evalinregister(e2) && !OTassign(e1->Eoper) && 
    19011986            !isregvar(e1,NULL,NULL)) 
    19021987        {   regm_t m; 
     
    19091994        } 
    19101995        if ((e1->Eoper == OPstrcmp || (OTassign(e1->Eoper) && sz <= REGSIZE)) && 
    19111996            !boolres(e2) && !evalinregister(e1)) 
    19121997        { 
    19131998            retregs = mPSW; 
    19141999            cl = scodelem(e1,&retregs,0,FALSE); 
    19152000            freenode(e2); 
    19162001            break; 
    19172002        } 
    19182003        if (sz <= REGSIZE && !boolres(e2) && e1->Eoper == OPadd && *pretregs == mPSW) 
    19192004        { 
    19202005            retregs |= mPSW; 
    19212006            cl = scodelem(e1,&retregs,0,FALSE); 
    19222007            freenode(e2); 
    19232008            break; 
    19242009        } 
    19252010        cl = scodelem(e1,&retregs,0,TRUE);      /* compute left leaf    */ 
    19262011        if (sz == 1) 
    19272012        { 
    19282013            reg = findreg(retregs & allregs);   // get reg that e1 is in 
    1929             cs.Irm = modregrm(3,7,reg); 
     2014            cs.Irm = modregrm(3,7,reg & 7); 
     2015            if (reg & 8) 
     2016                cs.Irex |= REX_B; 
    19302017            if (e1->Eoper == OPvar && e1->EV.sp.Voffset == 1 && e1->EV.sp.Vsym->Sfl == FLreg) 
     2018            {   assert(reg < 4); 
    19312019                cs.Irm |= 4;                    // use upper register half 
     2020            } 
    19322021        } 
    19332022        else if (sz <= REGSIZE) 
    19342023        {                                       /* CMP reg,const        */ 
    19352024            reg = findreg(retregs & allregs);   // get reg that e1 is in 
    19362025            rretregs = allregs & ~retregs; 
    19372026            if (cs.IFL2 == FLconst && reghasvalue(rretregs,cs.IEV2.Vint,&rreg)) 
    1938             {   code *cc; 
    1939  
    1940                 cc = genregs(CNIL,0x3B,reg,rreg); 
    1941                 if (I32
     2027            { 
     2028                code *cc = genregs(CNIL,0x3B,reg,rreg); 
     2029                code_orrex(cc, rex); 
     2030                if (!I16
    19422031                    cc->Iflags |= cs.Iflags & CFopsize; 
    19432032                c = cat(c,cc); 
    19442033                freenode(e2); 
    19452034                break; 
    19462035            } 
    1947             cs.Irm = modregrm(3,7,reg); 
     2036            cs.Irm = modregrm(3,7,reg & 7); 
     2037            if (reg & 8) 
     2038                cs.Irex |= REX_B; 
    19482039        } 
    19492040        else if (sz <= 2 * REGSIZE) 
    19502041        { 
    19512042            reg = findregmsw(retregs);          // get reg that e1 is in 
    19522043            cs.Irm = modregrm(3,7,reg); 
    19532044            c = gen(CNIL,&cs);                  /* CMP reg,MSW          */ 
    19542045            if (I32 && sz == 6) 
    19552046                c->Iflags |= CFopsize;          /* seg is only 16 bits  */ 
    19562047            genjmp(c,JNE,FLcode,(block *) ce);  /* JNE ce               */ 
    19572048 
    19582049            reg = findreglsw(retregs); 
    19592050            cs.Irm = modregrm(3,7,reg); 
    19602051            if (e2->Eoper == OPconst) 
    19612052                cs.IEV2.Vint = e2->EV.Vlong; 
    19622053            else 
    19632054            {   /* Turn off CFseg, on CFoff     */ 
    19642055                cs.Iflags ^= CFseg | CFoff; 
    19652056                cs.IEVoffset2 = offset2; 
    19662057            } 
    19672058        } 
     
    19752066        if (e2->Ecount) 
    19762067            goto L2; 
    19772068        goto L5; 
    19782069 
    19792070      case OPvar: 
    19802071        if ((e1->Eoper == OPvar && 
    19812072             isregvar(e2,&rretregs,&reg) && 
    19822073             sz <= REGSIZE 
    19832074            ) || 
    19842075            (e1->Eoper == OPind && 
    19852076             isregvar(e2,&rretregs,&reg) && 
    19862077             !evalinregister(e1) && 
    19872078             sz <= REGSIZE 
    19882079            ) 
    19892080           ) 
    19902081        { 
    19912082            // CMP EA,e2 
    19922083            cl = getlvalue(&cs,e1,RMload); 
    19932084            freenode(e1); 
    19942085            cs.Iop = 0x39 ^ byte ^ reverse; 
    1995             cs.Irm |= modregrm(0,reg,0); 
     2086            code_newreg(&cs,reg); 
    19962087            c = gen(c,&cs); 
    19972088            freenode(e2); 
    19982089            break; 
    19992090        } 
    20002091      L5: 
    20012092        cl = scodelem(e1,&retregs,0,TRUE);      /* compute left leaf    */ 
    20022093        if (sz <= REGSIZE)                      /* CMP reg,EA           */ 
    2003         {   unsigned opsize; 
    2004  
     2094        { 
    20052095            reg = findreg(retregs & allregs);   // get reg that e1 is in 
    2006             opsize = cs.Iflags & CFopsize; 
     2096            unsigned opsize = cs.Iflags & CFopsize; 
    20072097            c = cat(c,loadea(e2,&cs,0x3B ^ byte ^ reverse,reg,0,RMload | retregs,0)); 
    20082098            code_orflag(c,opsize); 
    20092099        } 
    20102100        else if (sz <= 2 * REGSIZE) 
    20112101        { 
    20122102            reg = findregmsw(retregs);   /* get reg that e1 is in */ 
    20132103            // CMP reg,EA 
    20142104            c = loadea(e2,&cs,0x3B ^ reverse,reg,REGSIZE,RMload | retregs,0); 
    20152105            if (I32 && sz == 6) 
    20162106                c->Iflags |= CFopsize;          /* seg is only 16 bits  */ 
    20172107            genjmp(c,JNE,FLcode,(block *) ce);          /* JNE ce       */ 
    20182108            reg = findreglsw(retregs); 
    20192109            if (e2->Eoper == OPind) 
    20202110            { 
    20212111                NEWREG(cs.Irm,reg); 
    20222112                getlvalue_lsw(&cs); 
    20232113                c = gen(c,&cs); 
    20242114            } 
    20252115            else 
    20262116                c = cat(c,loadea(e2,&cs,0x3B ^ reverse,reg,0,RMload | retregs,0)); 
    20272117        } 
    20282118        else 
    20292119            assert(0); 
    20302120        freenode(e2); 
    20312121        break; 
    20322122  } 
    20332123  c = cat(c,ce); 
    20342124 
    20352125L3: 
    2036   if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) /* if return result in register*/ 
    2037   {     code *nop; 
    2038         regm_t save; 
    2039  
    2040         nop = CNIL; 
    2041         save = regcon.immed.mval; 
     2126  if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register 
     2127  {     code *nop = CNIL; 
     2128        regm_t save = regcon.immed.mval; 
    20422129        cg = allocreg(&retregs,&reg,TYint); 
    20432130        regcon.immed.mval = save; 
    20442131        if ((*pretregs & mPSW) == 0 && 
    20452132            (jop == JC || jop == JNC)) 
    20462133        { 
    20472134            cg = cat(cg,getregs(retregs)); 
    20482135            cg = genregs(cg,0x19,reg,reg);              /* SBB reg,reg  */ 
     2136            if (rex) 
     2137                code_orrex(cg, rex); 
    20492138            if (flag) 
    20502139                ;                                       // cdcond() will handle it 
    20512140            else if (jop == JNC) 
    2052                 gen1(cg,0x40 + reg);                    /* INC reg      */ 
     2141            { 
     2142                if (I64) 
     2143                { 
     2144                    cg = gen2(cg,0xFF,modregrmx(3,0,reg));      // INC reg 
     2145                    code_orrex(cg, rex); 
     2146                } 
     2147                else 
     2148                    gen1(cg,0x40 + reg);                 // INC reg 
     2149            } 
    20532150            else 
    2054                 gen2(cg,0xF7,modregrm(3,3,reg));        /* NEG reg      */ 
     2151            {   gen2(cg,0xF7,modregrmx(3,3,reg));        /* NEG reg      */ 
     2152                code_orrex(cg, rex); 
     2153            } 
     2154        } 
     2155        else if (I64 && sz == 8) 
     2156        { 
     2157            assert(!flag); 
     2158            cg = movregconst(cg,reg,1,64|8);               // MOV reg,1 
     2159            nop = gennop(nop); 
     2160            cg = genjmp(cg,jop,FLcode,(block *) nop);   // Jtrue nop 
     2161                                                        // MOV reg,0 
     2162            movregconst(cg,reg,0,(*pretregs & mPSW) ? 64|8 : 64); 
     2163            regcon.immed.mval &= ~mask[reg]; 
    20552164        } 
    20562165        else 
    20572166        { 
    20582167            assert(!flag); 
    20592168            cg = movregconst(cg,reg,1,8);               // MOV reg,1 
    20602169            nop = gennop(nop); 
    20612170            cg = genjmp(cg,jop,FLcode,(block *) nop);   // Jtrue nop 
    20622171                                                        // MOV reg,0 
    20632172            movregconst(cg,reg,0,(*pretregs & mPSW) ? 8 : 0); 
    20642173            regcon.immed.mval &= ~mask[reg]; 
    20652174        } 
    20662175        *pretregs = retregs; 
    20672176        c = cat3(c,cg,nop); 
    20682177  } 
    20692178ret: 
    20702179  return cat3(cl,cr,c); 
    20712180} 
    20722181 
    20732182 
    20742183/********************************** 
     
    21202229        reg = findreglsw(retregs); 
    21212230        rreg = findreglsw(rretregs); 
    21222231        clsw = genregs(CNIL,0x3B,reg,rreg);             /* CMP reg,rreg */ 
    21232232        break; 
    21242233      case OPconst: 
    21252234        cs.IEV2.Vint = MSREG(e2->EV.Vllong);            // MSW first 
    21262235        cs.IFL2 = FLconst; 
    21272236        cs.Iop = 0x81; 
    21282237 
    21292238        /* if ((e1 is data or a '*' reference) and it's not a 
    21302239         * common subexpression 
    21312240         */ 
    21322241 
    21332242        if ((e1->Eoper == OPvar && datafl[el_fl(e1)] || 
    21342243             e1->Eoper == OPind) && 
    21352244            !evalinregister(e1)) 
    21362245        {       cl = getlvalue(&cs,e1,0); 
    21372246                freenode(e1); 
    21382247                if (evalinregister(e2)) 
    21392248                { 
    2140                         retregs = idxregm(cs.Irm,cs.Isib); 
     2249                        retregs = idxregm(&cs); 
    21412250                        if ((cs.Iflags & CFSEG) == CFes) 
    21422251                                retregs |= mES;         /* take no chances */ 
    21432252                        rretregs = ALLREGS & ~retregs; 
    21442253                        cr = scodelem(e2,&rretregs,retregs,TRUE); 
    21452254                        rreg = findregmsw(rretregs); 
    21462255                        cs.Iop = 0x39; 
    21472256                        cs.Irm |= modregrm(0,rreg,0); 
    21482257                        getlvalue_msw(&cs); 
    21492258                        cmsw = gen(CNIL,&cs);   /* CMP EA+2,rreg        */ 
    21502259                        rreg = findreglsw(rretregs); 
    21512260                        NEWREG(cs.Irm,rreg); 
    21522261                } 
    21532262                else 
    21542263                {       cs.Irm |= modregrm(0,7,0); 
    21552264                        getlvalue_msw(&cs); 
    21562265                        cmsw = gen(CNIL,&cs);   /* CMP EA+2,const       */ 
    21572266                        cs.IEV2.Vint = e2->EV.Vlong; 
    21582267                        freenode(e2); 
    21592268                } 
    21602269                getlvalue_lsw(&cs); 
     
    22802389                    retregs = regmask(e->E1->Ety, e->E1->E1->Ety); 
    22812390                    if (retregs & (mST01 | mST0))       // if return in ST0 
    22822391                    { 
    22832392                        c1 = codelem(e->E1,pretregs,FALSE); 
    22842393                        if (*pretregs & mST0) 
    22852394                            note87(e, 0, 0); 
    22862395                        return c1; 
    22872396                    } 
    22882397                    else 
    22892398                        break; 
    22902399                } 
    22912400                if (tycomplex(e->E1->Ety)) 
    22922401                    goto Lcomplex; 
    22932402                /* FALL-THROUGH */ 
    22942403            case OPs64_d: 
    22952404            case OPs32_d: 
    22962405            case OPs16_d: 
    22972406            case OPu16_d: 
    22982407                return load87(e,0,pretregs,NULL,-1); 
    22992408            case OPu32_d: 
    2300                 if (I32) 
    2301                 {   unsigned reg; 
    2302  
    2303                     retregs = ALLREGS; 
     2409                if (!I16) 
     2410                { 
     2411                    unsigned retregs = ALLREGS; 
    23042412                    c1 = codelem(e->E1, &retregs, FALSE); 
    2305                     reg = findreg(retregs); 
     2413                    unsigned reg = findreg(retregs); 
    23062414                    c1 = genfltreg(c1, 0x89, reg, 0); 
    23072415                    regwithvalue(c1,ALLREGS,0,&reg,0); 
    23082416                    genfltreg(c1, 0x89, reg, REGSIZE); 
    23092417 
    23102418                    cat(c1, push87()); 
    23112419                    genfltreg(c1,0xDF,5,0);     // FILD m64int 
    23122420 
    23132421                    retregs = mST0 | (*pretregs & mPSW); 
    23142422                    c2 = fixresult87(e, retregs, pretregs); 
    23152423                    return cat(c1, c2); 
    23162424                } 
    23172425                break; 
    23182426            case OPd_s16: 
    23192427            case OPd_s32: 
    23202428            case OPd_u16: 
    23212429            case OPd_s64: 
    23222430                return cnvt87(e,pretregs); 
    23232431            case OPd_u32:               // use subroutine, not 8087 
    23242432#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    23252433                retregs = mST0; 
     
    23462454                c2 = callclib(e,CLIBld_u64,pretregs,0); 
    23472455                return cat(c1,c2); 
    23482456        } 
    23492457  } 
    23502458  retregs = regmask(e->E1->Ety, TYnfunc); 
    23512459L1: 
    23522460  c1 = codelem(e->E1,&retregs,FALSE); 
    23532461  for (i = 0; 1; i++) 
    23542462  {     assert(i < arraysize(clib)); 
    23552463        if (clib[i][0] == e->Eoper) 
    23562464        {   c2 = callclib(e,clib[i][1],pretregs,0); 
    23572465            break; 
    23582466        } 
    23592467  } 
    23602468  return cat(c1,c2); 
    23612469} 
    23622470 
    23632471 
    23642472/*************************** 
    23652473 * Convert short to long. 
    2366  * For OPshtlng, OPu16_32, OPptrlptr, OPulngllng, OPlngllng 
     2474 * For OPs16_32, OPu16_32, OPptrlptr, OPu32_64, OPs32_64 
    23672475 */ 
    23682476 
    23692477code *cdshtlng(elem *e,regm_t *pretregs) 
    23702478{ code *c,*ce,*c1,*c2,*c3,*c4; 
    23712479  unsigned reg; 
    23722480  unsigned char op; 
    23732481  regm_t retregs; 
    23742482  int e1comsub; 
    23752483 
    23762484  e1comsub = e->E1->Ecount; 
    23772485  if ((*pretregs & (ALLREGS | mBP)) == 0)       // if don't need result in regs 
    23782486    c = codelem(e->E1,pretregs,FALSE);  /* then conversion isn't necessary */ 
    23792487 
    23802488  else if ((op = e->Eoper) == OPptrlptr || 
    2381            (!I32 && op == OPu16_32) || 
    2382            ( I32 && op == OPulngllng
     2489           (I16 && op == OPu16_32) || 
     2490           (I32 && op == OPu32_64
    23832491          ) 
    23842492  { 
    23852493        regm_t regm; 
    23862494        tym_t tym1; 
    23872495 
    23882496        retregs = *pretregs & mLSW; 
    23892497        assert(retregs); 
    23902498        tym1 = tybasic(e->E1->Ety); 
    23912499        c = codelem(e->E1,&retregs,FALSE); 
    23922500 
    23932501        regm = *pretregs & (mMSW & ALLREGS); 
    23942502        if (regm == 0)                  /* *pretregs could be mES       */ 
    23952503            regm = mMSW & ALLREGS; 
    23962504        ce = allocreg(&regm,&reg,TYint); 
    23972505        if (e1comsub) 
    23982506            ce = cat(ce,getregs(retregs)); 
    23992507        if (op == OPptrlptr) 
    24002508        {   int segreg; 
    24012509 
    24022510            /* BUG: what about pointers to functions?   */ 
    24032511            switch (tym1) 
    24042512            { 
    24052513                case TYnptr:    segreg = SEG_DS;        break; 
    24062514                case TYcptr:    segreg = SEG_CS;        break; 
    24072515                case TYsptr:    segreg = SEG_SS;        break; 
    24082516                default:        assert(0); 
    24092517            } 
    24102518            ce = gen2(ce,0x8C,modregrm(3,segreg,reg));  /* MOV reg,segreg */ 
    24112519        } 
    24122520        else 
    24132521            ce = movregconst(ce,reg,0,0);               /* 0 extend     */ 
    24142522 
    24152523        c = cat3(c,ce,fixresult(e,retregs | regm,pretregs)); 
    24162524  } 
    2417   else if (I32 && (op == OPshtlng || op == OPu16_32)) 
     2525  else if (!I16 && (op == OPs16_32 || op == OPu16_32)) 
    24182526  { 
    2419     /* OPshtlng || OPu16_32 */ 
    2420     elem *e1; 
    24212527    elem *e11; 
    24222528 
    2423     e1 = e->E1; 
     2529    elem *e1 = e->E1; 
    24242530 
    24252531    if (e1->Eoper == OPu8_16 && !e1->Ecount && 
    24262532        ((e11 = e1->E1)->Eoper == OPvar || (e11->Eoper == OPind && !e11->Ecount)) 
    24272533       ) 
    24282534    {   code cs; 
    24292535 
    24302536        retregs = *pretregs & BYTEREGS; 
    24312537        if (!retregs) 
    24322538            retregs = BYTEREGS; 
    24332539        c1 = allocreg(&retregs,&reg,TYint); 
    24342540        c2 = movregconst(NULL,reg,0,0);                         //  XOR reg,reg 
    24352541        c3 = loadea(e11,&cs,0x8A,reg,0,retregs,retregs);        //  MOV regL,EA 
    24362542        freenode(e11); 
    24372543        freenode(e1); 
    24382544    } 
    24392545    else if (e1->Eoper == OPvar || 
    24402546        (e1->Eoper == OPind && !e1->Ecount)) 
    24412547    {   code cs; 
    24422548        unsigned opcode; 
    24432549 
     
    24532559    else 
    24542560    { 
    24552561    L2: 
    24562562        retregs = *pretregs; 
    24572563        *pretregs &= ~mPSW;             /* flags are already set        */ 
    24582564        c1 = codelem(e1,&retregs,FALSE); 
    24592565        c2 = getregs(retregs); 
    24602566        if (op == OPu16_32 && c1) 
    24612567        {   code *cx; 
    24622568 
    24632569            cx = code_last(c1); 
    24642570            if (cx->Iop == 0x81 && (cx->Irm & modregrm(3,7,0)) == modregrm(3,4,0)) 
    24652571            { 
    24662572                // Convert AND of a word to AND of a dword, zeroing upper word 
    24672573                retregs = mask[cx->Irm & 7]; 
    24682574                cx->Iflags &= ~CFopsize; 
    24692575                cx->IEV2.Vint &= 0xFFFF; 
    24702576                goto L1; 
    24712577            } 
    24722578        } 
    2473         if (op == OPshtlng && retregs == mAX) 
     2579        if (op == OPs16_32 && retregs == mAX) 
    24742580            c2 = gen1(c2,0x98);         /* CWDE                         */ 
    24752581        else 
    24762582        { 
    24772583            reg = findreg(retregs); 
    24782584            if (config.flags4 & CFG4speed && op == OPu16_32) 
    24792585            {   // AND reg,0xFFFF 
    24802586                c3 = genc2(NULL,0x81,modregrm(3,4,reg),0xFFFFu); 
    24812587            } 
    24822588            else 
    24832589            { 
    24842590                c3 = genregs(CNIL,0x0F,reg,reg); 
    24852591                c3->Iop2 = (op == OPu16_32) ? 0xB7 : 0xBF; /* MOVZX/MOVSX reg,reg */ 
    24862592            } 
    24872593            c2 = cat(c2,c3); 
    24882594        } 
    24892595     L1: 
    24902596        c3 = e1comsub ? getregs(retregs) : CNIL; 
    24912597    } 
    24922598    c4 = fixresult(e,retregs,pretregs); 
    24932599    c = cat4(c1,c2,c3,c4); 
    24942600  } 
    24952601  else if (*pretregs & mPSW || config.target_cpu < TARGET_80286) 
    24962602  { 
    2497     // OPshtlng, OPlngllng 
     2603    // OPs16_32, OPs32_64 
    24982604    // CWD doesn't affect flags, so we can depend on the integer 
    24992605    // math to provide the flags. 
    25002606    retregs = mAX | mPSW;               // want integer result in AX 
    25012607    *pretregs &= ~mPSW;                 // flags are already set 
    25022608    c1 = codelem(e->E1,&retregs,FALSE); 
    25032609    c2 = getregs(mDX);                  // sign extend into DX 
    25042610    c2 = gen1(c2,0x99);                 // CWD/CDQ 
    25052611    c3 = e1comsub ? getregs(retregs) : CNIL; 
    25062612    c4 = fixresult(e,mDX | retregs,pretregs); 
    25072613    c = cat4(c1,c2,c3,c4); 
    25082614  } 
    25092615  else 
    25102616  { 
    2511     // OPshtlng, OPlngllng 
     2617    // OPs16_32, OPs32_64 
    25122618    unsigned msreg,lsreg; 
    25132619 
    25142620    retregs = *pretregs & mLSW; 
    25152621    assert(retregs); 
    25162622    c1 = codelem(e->E1,&retregs,FALSE); 
    25172623    retregs |= *pretregs & mMSW; 
    25182624    c2 = allocreg(&retregs,&reg,e->Ety); 
    25192625    msreg = findregmsw(retregs); 
    25202626    lsreg = findreglsw(retregs); 
    25212627    c3 = genmovreg(NULL,msreg,lsreg);                           // MOV msreg,lsreg 
    25222628    assert(config.target_cpu >= TARGET_80286);                  // 8088 can't handle SAR reg,imm8 
    25232629    c3 = genc2(c3,0xC1,modregrm(3,7,msreg),REGSIZE * 8 - 1);    // SAR msreg,31 
    25242630    c4 = fixresult(e,retregs,pretregs); 
    25252631    c = cat4(c1,c2,c3,c4); 
    25262632  } 
    25272633  return c; 
    25282634} 
    25292635 
    25302636 
    25312637/*************************** 
     
    25332639 * For OPu8int and OPs8int. 
    25342640 */ 
    25352641 
    25362642code *cdbyteint(elem *e,regm_t *pretregs) 
    25372643{   code *c,*ce,*c0,*c1,*c2,*c3,*c4; 
    25382644    regm_t retregs; 
    25392645    unsigned reg; 
    25402646    char op; 
    25412647    char size; 
    25422648    elem *e1; 
    25432649 
    25442650 
    25452651    if ((*pretregs & (ALLREGS | mBP)) == 0)     // if don't need result in regs 
    25462652        return codelem(e->E1,pretregs,FALSE); /* then conversion isn't necessary */ 
    25472653 
    25482654    op = e->Eoper; 
    25492655    e1 = e->E1; 
    25502656    c0 = NULL; 
    25512657    if (e1->Eoper == OPcomma) 
    25522658        c0 = docommas(&e1); 
    2553     if (I32
     2659    if (!I16
    25542660    { 
    25552661        if (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount)) 
    25562662        {   code cs; 
    25572663            unsigned opcode; 
    25582664 
    25592665            retregs = *pretregs; 
    25602666            c1 = allocreg(&retregs,&reg,TYint); 
    25612667            if (config.flags4 & CFG4speed && 
    25622668                op == OPu8int && mask[reg] & BYTEREGS && 
    25632669                config.target_cpu < TARGET_PentiumPro) 
    25642670            { 
    25652671                c2 = movregconst(NULL,reg,0,0);                 //  XOR reg,reg 
    25662672                c3 = loadea(e1,&cs,0x8A,reg,0,retregs,retregs); //  MOV regL,EA 
    25672673            } 
    25682674            else 
    25692675            { 
    25702676                opcode = (op == OPu8int) ? 0x0FB6 : 0x0FBE; // MOVZX/MOVSX reg,EA 
    25712677                c2 = loadea(e1,&cs,opcode,reg,0,0,retregs); 
    25722678                c3 = CNIL; 
    25732679            } 
     
    25902696                retregs = BYTEREGS; 
    25912697        } 
    25922698        else 
    25932699        { 
    25942700            /* CBW doesn't affect flags, so we can depend on the integer */ 
    25952701            /* math to provide the flags.                               */ 
    25962702            retregs = mAX | (*pretregs & mPSW); /* want integer result in AX */ 
    25972703        } 
    25982704    } 
    25992705 
    26002706    c3 = CNIL; 
    26012707    c1 = codelem(e1,&retregs,FALSE); 
    26022708    reg = findreg(retregs); 
    26032709    if (!c1) 
    26042710        goto L1; 
    26052711 
    26062712    for (c = c1; c->next; c = c->next) 
    26072713        ;                               /* find previous instruction    */ 
    26082714 
    26092715    /* If previous instruction is an AND bytereg,value  */ 
    2610     if (c->Iop == 0x80 && c->Irm == modregrm(3,4,reg) && 
     2716    if (c->Iop == 0x80 && c->Irm == modregrm(3,4,reg & 7) && 
    26112717        (op == OPu8int || (c->IEV2.Vuns & 0x80) == 0)) 
    26122718    { 
    26132719        if (*pretregs & mPSW) 
    26142720            c->Iflags |= CFpsw; 
    26152721        c->Iop |= 1;                    /* convert to word operation    */ 
    26162722        c->IEV2.Vuns &= 0xFF;           /* dump any high order bits     */ 
    26172723        *pretregs &= ~mPSW;             /* flags already set            */ 
    26182724    } 
    26192725    else 
    26202726    { 
    26212727     L1: 
    2622         if (I32
     2728        if (!I16
    26232729        { 
    26242730            if (op == OPs8int && reg == AX && size == 2) 
    26252731            {   c3 = gen1(c3,0x98);             /* CBW                  */ 
    26262732                c3->Iflags |= CFopsize;         /* don't do a CWDE      */ 
    26272733            } 
    26282734            else 
    26292735            { 
    26302736                /* We could do better by not forcing the src and dst    */ 
    26312737                /* registers to be the same.                            */ 
    26322738 
    26332739                if (config.flags4 & CFG4speed && op == OPu8_16) 
    26342740                {   // AND reg,0xFF 
    26352741                    c3 = genc2(c3,0x81,modregrm(3,4,reg),0xFF); 
    26362742                } 
    26372743                else 
    26382744                {   c3 = genregs(c3,0x0F,reg,reg); 
    26392745                    c3->Iop2 = (op == OPu8int) ? 0xB6 : 0xBE; /* MOVZX/MOVSX reg,reg */ 
    26402746                } 
    26412747            } 
    26422748        } 
    26432749        else 
    26442750        { 
    26452751            if (op == OPu8int) 
    26462752                c3 = genregs(c3,0x30,reg+4,reg+4);      // XOR regH,regH 
    26472753            else 
    26482754            { 
    26492755                c3 = gen1(c3,0x98);             /* CBW                  */ 
    26502756                *pretregs &= ~mPSW;             /* flags already set    */ 
    26512757            } 
    26522758        } 
    26532759    } 
    26542760    c2 = getregs(retregs); 
    26552761L2: 
    26562762    c4 = fixresult(e,retregs,pretregs); 
    26572763    return cat6(c0,c1,c2,c3,c4,NULL); 
    26582764} 
    26592765 
    26602766 
    26612767/*************************** 
    2662  * Convert long to short (OPlngsht). 
     2768 * Convert long to short (OP32_16). 
    26632769 * Get offset of far pointer (OPoffset). 
    2664  * Convert int to byte (OPint8). 
     2770 * Convert int to byte (OP16_8). 
    26652771 * Convert long long to long (OP64_32). 
    26662772 */ 
    26672773 
    26682774code *cdlngsht(elem *e,regm_t *pretregs) 
    26692775{ regm_t retregs; 
    26702776  code *c; 
    26712777 
    26722778#ifdef DEBUG 
    26732779    switch (e->Eoper) 
    26742780    { 
    2675         case OPlngsht
     2781        case OP32_16
    26762782        case OPoffset: 
    2677         case OPint8: 
     2783        case OP16_8: 
    26782784        case OP64_32: 
    26792785            break; 
    26802786 
    26812787        default: 
    26822788            assert(0); 
    26832789    } 
    26842790#endif 
    26852791 
    2686   if (e->Eoper == OPint8) 
     2792  if (e->Eoper == OP16_8) 
    26872793  {     retregs = *pretregs ? BYTEREGS : 0; 
    26882794        c = codelem(e->E1,&retregs,FALSE); 
    26892795  } 
    26902796  else 
    26912797  {     if (e->E1->Eoper == OPrelconst) 
    26922798            c = offsetinreg(e->E1,&retregs); 
    26932799        else 
    26942800        {   retregs = *pretregs ? ALLREGS : 0; 
    26952801            c = codelem(e->E1,&retregs,FALSE); 
    2696             if (!I32 || e->Eoper == OPoffset || e->Eoper == OP64_32
     2802            if (I16 || I32 && (e->Eoper == OPoffset || e->Eoper == OP64_32)
    26972803                retregs &= mLSW;                /* want LSW only        */ 
    26982804        } 
    26992805  } 
    27002806 
    27012807  /* We "destroy" a reg by assigning it the result of a new e, even     */ 
    27022808  /* though the values are the same. Weakness of our CSE strategy that  */ 
    27032809  /* a register can only hold the contents of one elem at a time.       */ 
    27042810  if (e->Ecount) 
    27052811        c = cat(c,getregs(retregs)); 
    27062812  else 
    27072813        useregs(retregs); 
    27082814 
    27092815#ifdef DEBUG 
    27102816  if (!(!*pretregs || retregs)) 
    27112817        WROP(e->Eoper), 
    27122818        printf(" *pretregs = x%x, retregs = x%x, e = %p\n",*pretregs,retregs,e); 
    27132819#endif 
    27142820  assert(!*pretregs || retregs); 
    27152821  return cat(c,fixresult(e,retregs,pretregs));  /* lsw only             */ 
    27162822} 
     
    27992905        c3->Iflags |= CFopsize; 
    28002906    retregs = mAX; 
    28012907    return cat4(c1,c2,c3,fixresult(e,retregs,pretregs)); 
    28022908} 
    28032909 
    28042910/************************ 
    28052911 * Generate code for an asm elem. 
    28062912 */ 
    28072913 
    28082914code *cdasm(elem *e,regm_t *pretregs) 
    28092915{   code *c; 
    28102916 
    28112917#if 1 
    28122918    /* Assume only regs normally destroyed by a function are destroyed  */ 
    28132919    c = getregs((ALLREGS | mES) & ~fregsaved); 
    28142920#else 
    28152921    /* Assume all regs are destroyed    */ 
    28162922    c = getregs(ALLREGS | mES); 
    28172923#endif 
    28182924    c = genasm(c,e->EV.ss.Vstring,e->EV.ss.Vstrlen); 
    2819     return cat(c,fixresult(e,(I32 ? mAX : mDX | mAX),pretregs)); 
     2925    return cat(c,fixresult(e,(I16 ? mDX | mAX : mAX),pretregs)); 
    28202926} 
    28212927 
    28222928/************************ 
    28232929 * Generate code for OPtofar16 and OPfromfar16. 
    28242930 */ 
    28252931 
    28262932code *cdfar16( elem *e, regm_t *pretregs) 
    28272933{   code *c; 
    28282934    code *c1; 
    28292935    code *c3; 
    28302936    code *cnop; 
    28312937    code cs; 
    28322938    unsigned reg; 
    28332939 
    28342940    assert(I32); 
    28352941    c = codelem(e->E1,pretregs,FALSE); 
    28362942    reg = findreg(*pretregs); 
    28372943    c = cat(c,getregs(*pretregs));      /* we will destroy the regs     */ 
    28382944 
    28392945    cs.Iop = 0xC1; 
     
    29213027 
    29223028    switch (e->Eoper) 
    29233029    { 
    29243030        case OPbt:      op = 0xA3; mode = 4; break; 
    29253031        case OPbtc:     op = 0xBB; mode = 7; break; 
    29263032        case OPbtr:     op = 0xB3; mode = 6; break; 
    29273033        case OPbts:     op = 0xAB; mode = 5; break; 
    29283034 
    29293035        default: 
    29303036            assert(0); 
    29313037    } 
    29323038 
    29333039    e1 = e->E1; 
    29343040    e2 = e->E2; 
    29353041    cs.Iflags = 0; 
    29363042    c = getlvalue(&cs, e, RMload);      // get addressing mode 
    29373043    if (e->Eoper == OPbt && *pretregs == 0) 
    29383044        return cat(c, codelem(e2,pretregs,FALSE)); 
    29393045 
    29403046    ty1 = tybasic(e1->Ety); 
    2941     word = (I32 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0; 
    2942     idxregs = idxregm(cs.Irm, cs.Isib);         // mask if index regs used 
     3047    word = (!I16 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0; 
     3048    idxregs = idxregm(&cs);         // mask if index regs used 
    29433049 
    29443050//    if (e2->Eoper == OPconst && e2->EV.Vuns < 0x100)  // should do this instead? 
    29453051    if (e2->Eoper == OPconst) 
    29463052    { 
    29473053        cs.Iop = 0x0F; 
    29483054        cs.Iop2 = 0xBA;                         // BT rm,imm8 
    29493055        cs.Irm |= modregrm(0,mode,0); 
    29503056        cs.Iflags |= CFpsw | word; 
    29513057        cs.IFL2 = FLconst; 
    29523058        if (tysize[ty1] == SHORTSIZE) 
    29533059        { 
    29543060            cs.IEVoffset1 += (e2->EV.Vuns & ~15) >> 3; 
    29553061            cs.IEV2.Vint = e2->EV.Vint & 15; 
    29563062        } 
    2957         else 
     3063        else if (tysize[ty1] == 4) 
    29583064        { 
    29593065            cs.IEVoffset1 += (e2->EV.Vuns & ~31) >> 3; 
    29603066            cs.IEV2.Vint = e2->EV.Vint & 31; 
     3067        } 
     3068        else 
     3069        { 
     3070            cs.IEVoffset1 += (e2->EV.Vuns & ~63) >> 3; 
     3071            cs.IEV2.Vint = e2->EV.Vint & 63; 
    29613072        } 
    29623073        c2 = gen(CNIL,&cs); 
    29633074    } 
    29643075    else 
    29653076    { 
    29663077        retregs = ALLREGS & ~idxregs; 
    29673078        c2 = scodelem(e2,&retregs,idxregs,TRUE); 
    29683079        reg = findreg(retregs); 
    29693080 
    29703081        cs.Iop = 0x0F; 
    29713082        cs.Iop2 = op;                           // BT rm,reg 
    2972         cs.Irm |= modregrm(0,reg,0); 
     3083        code_newreg(&cs,reg); 
    29733084        cs.Iflags |= CFpsw | word; 
    29743085        c2 = gen(c2,&cs); 
    29753086    } 
    29763087 
    29773088    if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register 
    2978     {   code *nop; 
    2979         regm_t save; 
    2980         code *cg; 
    2981  
    2982         nop = CNIL; 
    2983         save = regcon.immed.mval; 
    2984         cg = allocreg(&retregs,&reg,TYint); 
     3089    { 
     3090        code *nop = CNIL; 
     3091        regm_t save = regcon.immed.mval; 
     3092        code *cg = allocreg(&retregs,&reg,TYint); 
    29853093        regcon.immed.mval = save; 
    29863094        if ((*pretregs & mPSW) == 0) 
    29873095        { 
    29883096            cg = cat(cg,getregs(retregs)); 
    29893097            cg = genregs(cg,0x19,reg,reg);              // SBB reg,reg 
    29903098        } 
    29913099        else 
    29923100        { 
    29933101            cg = movregconst(cg,reg,1,8);               // MOV reg,1 
    29943102            nop = gennop(nop); 
    29953103            cg = genjmp(cg,JC,FLcode,(block *) nop);    // Jtrue nop 
    29963104                                                        // MOV reg,0 
    29973105            movregconst(cg,reg,0,8); 
    29983106            regcon.immed.mval &= ~mask[reg]; 
    29993107        } 
    30003108        *pretregs = retregs; 
    30013109        c2 = cat3(c2,cg,nop); 
    30023110    } 
    30033111 
    30043112    return cat(c,c2); 
     
    30173125    code *cl,*cg; 
    30183126    code cs; 
    30193127 
    30203128    //printf("cdbscan()\n"); 
    30213129    //elem_print(e); 
    30223130    if (*pretregs == 0) 
    30233131        return codelem(e->E1,pretregs,FALSE); 
    30243132    tyml = tybasic(e->E1->Ety); 
    30253133    sz = tysize[tyml]; 
    30263134    assert(sz == 2 || sz == 4); 
    30273135 
    30283136    if ((e->E1->Eoper == OPind && !e->E1->Ecount) || e->E1->Eoper == OPvar) 
    30293137    { 
    30303138        cl = getlvalue(&cs, e->E1, RMload);     // get addressing mode 
    30313139    } 
    30323140    else 
    30333141    { 
    30343142        retregs = allregs; 
    30353143        cl = codelem(e->E1, &retregs, FALSE); 
    30363144        reg = findreg(retregs); 
    3037         cs.Irm = modregrm(3,0,reg); 
     3145        cs.Irm = modregrm(3,0,reg & 7); 
    30383146        cs.Iflags = 0; 
    30393147        cs.Irex = 0; 
     3148        if (reg & 8) 
     3149            cs.Irex |= REX_B; 
    30403150    } 
    30413151 
    30423152    retregs = *pretregs & allregs; 
    30433153    if  (!retregs) 
    30443154        retregs = allregs; 
    30453155    cg = allocreg(&retregs, &reg, e->Ety); 
    30463156 
    30473157    cs.Iop = 0x0F; 
    30483158    cs.Iop2 = (e->Eoper == OPbsf) ? 0xBC : 0xBD;        // BSF/BSR reg,EA 
    3049     cs.Irm |= modregrm(0,reg,0); 
    3050     if (I32 && sz == SHORTSIZE) 
     3159    code_newreg(&cs, reg); 
     3160    if (!I16 && sz == SHORTSIZE) 
    30513161        cs.Iflags |= CFopsize; 
    30523162    cg = gen(cg,&cs); 
    30533163 
    30543164    return cat3(cl,cg,fixresult(e,retregs,pretregs)); 
    30553165} 
    30563166 
    30573167/******************************************* 
    30583168 * Generate code for OPpair, OPrpair. 
    30593169 */ 
    30603170 
    30613171code *cdpair(elem *e, regm_t *pretregs) 
    30623172{ 
    30633173    regm_t retregs; 
    30643174    regm_t regs1; 
    30653175    regm_t regs2; 
    30663176    unsigned reg; 
    30673177    code *cg; 
    30683178    code *c1; 
    30693179    code *c2; 
    30703180 
  • branches/dmd-1.x/src/backend/code.c

    r428 r577  
    1212 
    1313#if !SPP 
    1414 
    1515#include        <stdio.h> 
    1616#include        <time.h> 
    1717#include        "cc.h" 
    1818#include        "el.h" 
    1919#include        "code.h" 
    2020#include        "global.h" 
    2121 
    2222static code *code_list; 
    2323 
    2424/***************** 
    2525 * Allocate code 
    2626 */ 
    2727 
    2828#if SCPP && __SC__ && __INTSIZE == 4 && TX86 && !_DEBUG_TRACE && !MEM_DEBUG 
    2929 
    3030__declspec(naked) code *code_calloc() 
    3131{ 
    32     if (sizeof(code) != 0x20
     32    if (sizeof(code) != 0x24
    3333        util_assert("code",__LINE__); 
    3434    __asm 
    3535    { 
    3636        mov     EAX,code_list 
    3737        test    EAX,EAX 
    3838        je      L20 
    3939        mov     ECX,[EAX] 
    4040        mov     code_list,ECX 
    4141        jmp     L29 
    4242 
    4343L20:    push    sizeof(code) 
    4444        call    mem_fmalloc 
    4545        ;add    ESP,4 
    4646L29: 
    4747        xor     ECX,ECX 
    4848        mov     DWORD PTR [EAX],0 
    4949 
    5050        mov     4[EAX],ECX      ;these pair 
    5151        mov     8[EAX],ECX 
    5252 
    5353        mov     12[EAX],ECX 
    5454        mov     16[EAX],ECX 
    5555 
    5656        mov     20[EAX],ECX 
    5757        mov     24[EAX],ECX 
    5858 
    5959        mov     28[EAX],ECX 
     60        mov     32[EAX],ECX 
    6061        ret 
    6162    } 
    6263} 
    6364 
    6465#else 
    6566 
    6667code *code_calloc() 
    6768{   code *c; 
    6869    static code czero; 
    6970 
     71    //printf("code %x\n", sizeof(code)); 
    7072    c = code_list; 
    7173    if (c) 
    7274        code_list = code_next(c); 
    7375    else 
    7476        c = (code *)mem_fmalloc(sizeof(*c)); 
    7577    *c = czero;                         // zero it out 
    7678    //dbg_printf("code_calloc: %p\n",c); 
    7779    return c; 
    7880} 
    7981 
    8082#endif 
    8183 
    8284/***************** 
    8385 * Free code 
    8486 */ 
    8587 
    8688void code_free(code *cstart) 
    8789{   code **pc; 
    8890    code *c; 
    8991 
  • branches/dmd-1.x/src/backend/code.h

    r572 r577  
    8989 
    9090#define mXMM0   (1 << XMM0) 
    9191#define mXMM1   (1 << XMM1) 
    9292#define mXMM2   (1 << XMM2) 
    9393#define mXMM3   (1 << XMM3) 
    9494#define mXMM4   (1 << XMM4) 
    9595#define mXMM5   (1 << XMM5) 
    9696#define mXMM6   (1 << XMM6) 
    9797#define mXMM7   (1 << XMM7) 
    9898#define XMMREGS  (mXMM0 |mXMM1 |mXMM2 |mXMM3 |mXMM4 |mXMM5 |mXMM6 |mXMM7) 
    9999 
    100100#define mES     (1 << ES)       // 0x10000 
    101101#define mPSW    (1 << PSW)      // 0x20000 
    102102 
    103103#define mSTACK  (1 << STACK)    // 0x40000 
    104104 
    105105#define mST0    (1 << ST0)      // 0x200000 
    106106#define mST01   (1 << ST01)     // 0x400000 
    107107 
    108108// Flags for getlvalue (must fit in regm_t) 
    109 #define RMload  0x4000 
    110 #define RMstore 0x8000 
     109#define RMload  (1 << 30) 
     110#define RMstore (1 << 31) 
    111111 
    112112#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    113113    // To support positional independent code, 
    114114    // must be able to remove BX from available registers 
    115115extern regm_t ALLREGS; 
    116116#define ALLREGS_INIT            (mAX|mBX|mCX|mDX|mSI|mDI) 
    117117#define ALLREGS_INIT_PIC        (mAX|mCX|mDX|mSI|mDI) 
    118118extern regm_t BYTEREGS; 
    119119#define BYTEREGS_INIT           (mAX|mBX|mCX|mDX) 
    120120#define BYTEREGS_INIT_PIC       (mAX|mCX|mDX) 
    121121#else 
    122122#define ALLREGS                 (mAX|mBX|mCX|mDX|mSI|mDI) 
    123123#define ALLREGS_INIT            ALLREGS 
    124124#undef BYTEREGS 
    125125#define BYTEREGS                (mAX|mBX|mCX|mDX) 
    126126#endif 
    127127 
    128128/* We use the same IDXREGS for the 386 as the 8088, because if 
    129129   we used ALLREGS, it would interfere with mMSW 
    130130 */ 
     
    241241    #define ESCrelease2 9       // release eh stack 
    242242    #define ESCframeptr 10      // replace with load of frame pointer 
    243243 
    244244#define ASM     0x36    // string of asm bytes, actually an SS: opcode 
    245245 
    246246/********************************* 
    247247 * Macros to ease generating code 
    248248 * modregrm:    generate mod reg r/m field 
    249249 * modregxrm:   reg could be R8..R15 
    250250 * modregrmx:   rm could be R8..R15 
    251251 * modregxrmx:  reg or rm could be R8..R15 
    252252 * NEWREG:      change reg field of x to r 
    253253 * genorreg:    OR  t,f 
    254254 */ 
    255255 
    256256#define modregrm(m,r,rm)        (((m)<<6)|((r)<<3)|(rm)) 
    257257#define modregxrm(m,r,rm)       ((((r)&8)<<15)|modregrm((m),(r)&7,rm)) 
    258258#define modregrmx(m,r,rm)       ((((rm)&8)<<13)|modregrm((m),r,(rm)&7)) 
    259259#define modregxrmx(m,r,rm)      ((((r)&8)<<15)|(((rm)&8)<<13)|modregrm((m),(r)&7,(rm)&7)) 
    260260 
     261#define NEWREXR(x,r)            ((x)=((x)&~REX_R)|(((r)&8)>>1)) 
    261262#define NEWREG(x,r)             ((x)=((x)&~(7<<3))|((r)<<3)) 
     263#define code_newreg(c,r)        (NEWREG((c)->Irm,(r)&7),NEWREXR((c)->Irex,(r))) 
     264 
    262265#define genorreg(c,t,f)         genregs((c),0x09,(f),(t)) 
    263266 
    264267#define REX     0x40            // REX prefix byte, OR'd with the following bits: 
    265268#define REX_W   8               // 0 = default operand size, 1 = 64 bit operand size 
    266269#define REX_R   4               // high bit of reg field of modregrm 
    267270#define REX_X   2               // high bit of sib index reg 
    268271#define REX_B   1               // high bit of rm field, sib base reg, or opcode reg 
    269272 
    270273/********************** 
    271274 * C library routines. 
    272275 * See callclib(). 
    273276 */ 
    274277 
    275278enum CLIB 
    276279{ 
    277280        CLIBlcmp, 
    278281        CLIBlmul, 
    279282        CLIBldiv, 
    280283        CLIBlmod, 
    281284        CLIBuldiv, 
     
    374377                                // CFes at the same time, though!) 
    375378#define CFpsw          0x40     // we need the flags result after this instruction 
    376379#define CFopsize       0x80     // prefix with operand size 
    377380#define CFaddrsize    0x100     // prefix with address size 
    378381#define CFds          0x200     // need DS override (not with es, ss, or cs ) 
    379382#define CFcs          0x400     // need CS override 
    380383#define CFfs          0x800     // need FS override 
    381384#define CFgs    (CFcs | CFfs)   // need GS override 
    382385#define CFwait       0x1000     // If I32 it indicates when to output a WAIT 
    383386#define CFselfrel    0x2000     // if self-relative 
    384387#define CFunambig    0x4000     // indicates cannot be accessed by other addressing 
    385388                                // modes 
    386389#define CFtarg2      0x8000     // like CFtarg, but we can't optimize this away 
    387390#define CFvolatile  0x10000     // volatile reference, do not schedule 
    388391#define CFclassinit 0x20000     // class init code 
    389392#define CFoffset64  0x40000     // offset is 64 bits 
    390393 
    391394#define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 
    392395#define CFSEG   (CFes | CFss | CFds | CFcs | CFfs | CFgs) 
    393396 
    394     unsigned char Irex;         // REX prefix 
    395397 
    396398    unsigned char Iop; 
    397     unsigned char Irm;          // reg/mode 
    398  
    399399    unsigned char Iop2;         // second opcode byte 
    400     unsigned char Isib;         // SIB byte 
    401  
    402400    unsigned char Iop3;         // third opcode byte 
     401 
     402    union 
     403    {   unsigned _Iea; 
     404        struct 
     405        { 
     406            unsigned char _Irm;          // reg/mode 
     407            unsigned char _Isib;         // SIB byte 
     408            unsigned char _Irex;         // REX prefix 
     409        } _ea; 
     410    } _EA; 
     411 
     412#define Iea _EA._Iea 
     413#define Irm _EA._ea._Irm 
     414#define Isib _EA._ea._Isib 
     415#define Irex _EA._ea._Irex 
    403416 
    404417    unsigned char IFL1,IFL2;    // FLavors of 1st, 2nd operands 
    405418    union evc IEV1;             // 1st operand, if any 
    406419      #define IEVpointer1 IEV1._EP.Vpointer 
    407420      #define IEVseg1     IEV1._EP.Vseg 
    408421      #define IEVsym1     IEV1.sp.Vsym 
    409422      #define IEVdsym1    IEV1.dsp.Vsym 
    410423      #define IEVoffset1  IEV1.sp.Voffset 
    411424      #define IEVlsym1    IEV1.lab.Vsym 
    412425      #define IEVint1     IEV1.Vint 
    413426    union evc IEV2;             // 2nd operand, if any 
    414427      #define IEVpointer2 IEV2._EP.Vpointer 
    415428      #define IEVseg2     IEV2._EP.Vseg 
    416429      #define IEVsym2     IEV2.sp.Vsym 
    417430      #define IEVdsym2    IEV2.dsp.Vsym 
    418431      #define IEVoffset2  IEV2.sp.Voffset 
    419432      #define IEVlsym2    IEV2.lab.Vsym 
    420433      #define IEVint2     IEV2.Vint 
    421434    void print();               // pretty-printer 
    422435 
     
    528541/***********************************************************/ 
    529542 
    530543extern regm_t msavereg,mfuncreg,allregs; 
    531544 
    532545/*long cxmalloc,cxcalloc,cx1;*/ 
    533546 
    534547typedef code *cd_t (elem *e , regm_t *pretregs ); 
    535548 
    536549extern  int BPRM; 
    537550extern  regm_t FLOATREGS; 
    538551extern  regm_t FLOATREGS2; 
    539552extern  regm_t DOUBLEREGS; 
    540553extern  const char datafl[],stackfl[],segfl[],flinsymtab[]; 
    541554extern  char needframe,usedalloca,gotref; 
    542555extern  targ_size_t localsize,Toff,Poff,Aoff, 
    543556        Poffset,funcoffset, 
    544557        framehandleroffset, 
    545558        Aoffset,Toffset,EEoffset; 
    546559extern  int Aalign; 
    547560extern  int cseg; 
     561extern  int STACKALIGN; 
    548562#if TARGET_OSX 
    549563extern  targ_size_t localgotoffset; 
    550564#endif 
    551565 
    552566/* cgcod.c */ 
    553567extern int pass; 
    554568#define PASSinit        0       // initial pass through code generator 
    555569#define PASSreg         1       // register assignment pass 
    556570#define PASSfinal       2       // final pass 
    557571 
    558572extern  int dfoidx; 
    559573extern  struct CSE *csextab; 
    560574extern  unsigned cstop; 
    561575#if TX86 
    562576extern  bool floatreg; 
    563577#endif 
    564578extern  targ_size_t retoffset; 
    565579extern  unsigned stackpush; 
    566580extern  int stackchanged; 
    567581extern  int refparam; 
     
    581595#endif 
    582596#define findregmsw(regm) findreg((regm) & mMSW) 
    583597#define findreglsw(regm) findreg((regm) & (mLSW | mBP)) 
    584598void freenode (elem *e ); 
    585599int isregvar (elem *e , regm_t *pregm , unsigned *preg ); 
    586600#ifdef DEBUG 
    587601code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym , int line , const char *file ); 
    588602#define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__) 
    589603#else 
    590604code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym ); 
    591605#endif 
    592606void useregs (regm_t regm ); 
    593607code *getregs (regm_t r ); 
    594608code *getregs_imm (regm_t r ); 
    595609code *cse_flush(int); 
    596610void cssave (elem *e , regm_t regm , unsigned opsflag ); 
    597611bool evalinregister (elem *e ); 
    598612regm_t getscratch(); 
    599613code *codelem (elem *e , regm_t *pretregs , bool constflag ); 
    600614const char *regm_str(regm_t rm); 
     615int numbitsset(regm_t); 
    601616 
    602617/* cod1.c */ 
    603618extern int clib_inited; 
    604619 
    605620int isscaledindex(elem *); 
    606621int ssindex(int op,targ_uns product); 
    607622void buildEA(code *c,int base,int index,int scale,targ_size_t disp); 
    608623void andregcon (con_t *pregconsave); 
    609624code *docommas (elem **pe ); 
    610625code *gencodelem(code *c,elem *e,regm_t *pretregs,bool constflag); 
    611626void gensaverestore(regm_t, code **, code **); 
    612627code *genstackclean(code *c,unsigned numpara,regm_t keepmsk); 
    613628code *logexp (elem *e , int jcond , unsigned fltarg , code *targ ); 
    614 code *loadea (elem *e , code __ss *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk ); 
     629code *loadea (elem *e , code *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk ); 
    615630unsigned getaddrmode (regm_t idxregs ); 
     631void setaddrmode(code *c, regm_t idxregs); 
    616632void getlvalue_msw(code *); 
    617633void getlvalue_lsw(code *); 
    618 code *getlvalue (code __ss *pcs , elem *e , regm_t keepmsk ); 
     634code *getlvalue (code *pcs , elem *e , regm_t keepmsk ); 
    619635code *scodelem (elem *e , regm_t *pretregs , regm_t keepmsk , bool constflag ); 
    620 code *fltregs (code __ss *pcs , tym_t tym ); 
     636code *fltregs (code *pcs , tym_t tym ); 
    621637code *tstresult (regm_t regm , tym_t tym , unsigned saveflag ); 
    622638code *fixresult (elem *e , regm_t retregs , regm_t *pretregs ); 
    623639code *callclib (elem *e , unsigned clib , regm_t *pretregs , regm_t keepmask ); 
    624640cd_t cdfunc; 
    625641cd_t cdstrthis; 
    626642code *params(elem *, unsigned); 
    627643code *offsetinreg (elem *e , regm_t *pretregs ); 
    628644code *loaddata (elem *e , regm_t *pretregs ); 
    629645 
    630646/* cod2.c */ 
    631 regm_t idxregm (unsigned rm,unsigned sib); 
     647regm_t idxregm(code *c); 
    632648#if TARGET_WINDOS 
    633649code *opdouble (elem *e , regm_t *pretregs , unsigned clib ); 
    634650#endif 
    635651cd_t cdorth; 
    636652cd_t cdmul; 
    637653cd_t cdnot; 
    638654cd_t cdcom; 
    639655cd_t cdbswap; 
    640656cd_t cdcond; 
    641657void WRcodlst (code *c ); 
    642658cd_t cdcomma; 
    643659cd_t cdloglog; 
    644660cd_t cdshift; 
    645661#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    646662cd_t cdindpic; 
    647663#endif 
    648664cd_t cdind; 
    649665cd_t cdstrlen; 
    650666cd_t cdstrcmp; 
    651667cd_t cdstrcpy; 
     
    662678cd_t cderr; 
    663679cd_t cdinfo; 
    664680cd_t cdctor; 
    665681cd_t cddtor; 
    666682cd_t cdmark; 
    667683cd_t cdnullcheck; 
    668684cd_t cdclassinit; 
    669685 
    670686/* cod3.c */ 
    671687extern int BPoff; 
    672688 
    673689int cod3_EA(code *c); 
    674690regm_t cod3_useBP(); 
    675691void cod3_set386 (void ); 
    676692void cod3_set64 (void ); 
    677693void cod3_align (void ); 
    678694void doswitch (block *b ); 
    679695void outjmptab (block *b ); 
    680696void outswitab (block *b ); 
    681697int jmpopcode (elem *e ); 
    682 void cod3_ptrchk(code * __ss *pc,code __ss *pcs,regm_t keepmsk); 
     698void cod3_ptrchk(code **pc,code *pcs,regm_t keepmsk); 
    683699code *prolog (void ); 
    684700void epilog (block *b); 
    685701cd_t cdframeptr; 
    686702cd_t cdgot; 
    687703targ_size_t cod3_spoff(); 
    688704code *cod3_load_got(); 
    689705void makeitextern (symbol *s ); 
    690706void fltused(void); 
    691707int branch(block *bl, int flag); 
    692708void cod3_adjSymOffsets(); 
    693709void assignaddr (block *bl ); 
    694710void assignaddrc (code *c ); 
    695711targ_size_t cod3_bpoffset(symbol *s); 
    696712void pinholeopt (code *c , block *bn ); 
    697713void jmpaddr (code *c ); 
    698714int code_match(code *c1,code *c2); 
    699715unsigned calcblksize (code *c); 
    700716unsigned calccodsize(code *c); 
    701717unsigned codout (code *c ); 
    702718void addtofixlist (symbol *s , targ_size_t soffset , int seg , targ_size_t val , int flags ); 
    703719void searchfixlist (symbol *s ); 
    704720void outfixlist (void ); 
    705721void code_hydrate(code **pc); 
    706722void code_dehydrate(code **pc); 
    707723 
    708724/* cod4.c */ 
    709725extern  const unsigned dblreg[]; 
    710726extern int cdcmp_flag; 
    711727 
    712 code *modEA (unsigned Irm ); 
     728code *modEA(code *c); 
    713729cd_t cdeq; 
    714730cd_t cdaddass; 
    715731cd_t cdmulass; 
    716732cd_t cdshass; 
    717733cd_t cdcmp; 
    718734cd_t cdcnvt; 
    719735cd_t cdshtlng; 
    720736cd_t cdbyteint; 
    721737cd_t cdlngsht; 
    722738cd_t cdmsw; 
    723739cd_t cdport; 
    724740cd_t cdasm; 
    725741cd_t cdsetjmp; 
    726742cd_t cdvoid; 
    727743cd_t cdhalt; 
    728744cd_t cdfar16; 
    729745cd_t cdbt; 
    730746cd_t cdbscan; 
    731747cd_t cdpair; 
    732748code *longcmp (elem *,bool,unsigned,code *); 
     
    786802code *nteh_filter(block *b); 
    787803void nteh_framehandler(symbol *); 
    788804code *nteh_gensindex(int); 
    789805#define GENSINDEXSIZE 7 
    790806code *nteh_monitor_prolog(Symbol *shandle); 
    791807code *nteh_monitor_epilog(regm_t retregs); 
    792808 
    793809// cgen.c 
    794810code *code_last(code *c); 
    795811void code_orflag(code *c,unsigned flag); 
    796812void code_orrex(code *c,unsigned rex); 
    797813code * __pascal cat (code *c1 , code *c2 ); 
    798814code * cat3 (code *c1 , code *c2 , code *c3 ); 
    799815code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 ); 
    800816code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 ); 
    801817code *gen (code *c , code *cs ); 
    802818code *gen1 (code *c , unsigned op ); 
    803819code *gen2 (code *c , unsigned op , unsigned rm ); 
    804820code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib); 
    805821code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg ); 
     822code *genpush (code *c , unsigned reg ); 
     823code *genpop (code *c , unsigned reg ); 
    806824code *gentstreg (code *c , unsigned reg ); 
    807825code *genasm (code *c , char *s , unsigned slen ); 
    808826code *genmovreg (code *c , unsigned to , unsigned from ); 
    809827code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ ); 
    810828code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si ); 
    811829code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s ); 
    812830code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 ); 
    813831code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 ); 
    814832code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 ); 
    815833code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm); 
    816834code *genlinnum(code *,Srcpos); 
    817835void cgen_linnum(code **pc,Srcpos srcpos); 
    818836void cgen_prelinnum(code **pc,Srcpos srcpos); 
    819837code *genadjesp(code *c, int offset); 
    820838code *gennop(code *); 
    821839code *genshift(code *); 
    822840code *movregconst (code *c , unsigned reg , targ_size_t value , regm_t flags ); 
    823841bool reghasvalue (regm_t regm , targ_size_t value , unsigned *preg ); 
    824842code *regwithvalue (code *c , regm_t regm , targ_size_t value , unsigned *preg , regm_t flags ); 
    825843 
  • branches/dmd-1.x/src/backend/iasm.h

    r572 r577  
    7171// Operand flags - usOp1, usOp2, usOp3 
    7272// 
    7373 
    7474typedef unsigned opflag_t; 
    7575 
    7676// Operand flags for normal opcodes 
    7777 
    7878#define _r8     CONSTRUCT_FLAGS( _8, _reg, _normal, 0 ) 
    7979#define _r16    CONSTRUCT_FLAGS(_16, _reg, _normal, 0 ) 
    8080#define _r32    CONSTRUCT_FLAGS(_32, _reg, _normal, 0 ) 
    8181#define _r64    CONSTRUCT_FLAGS(_64, _reg, _normal, 0 ) 
    8282#define _m8     CONSTRUCT_FLAGS(_8, _m, _normal, 0 ) 
    8383#define _m16    CONSTRUCT_FLAGS(_16, _m, _normal, 0 ) 
    8484#define _m32    CONSTRUCT_FLAGS(_32, _m, _normal, 0 ) 
    8585#define _m48    CONSTRUCT_FLAGS( _48, _m, _normal, 0 ) 
    8686#define _m64    CONSTRUCT_FLAGS( _64, _m, _normal, 0 ) 
    8787#define _m128   CONSTRUCT_FLAGS( _anysize, _m, _normal, 0 ) 
    8888#define _rm8    CONSTRUCT_FLAGS(_8, _rm, _normal, 0 ) 
    8989#define _rm16   CONSTRUCT_FLAGS(_16, _rm, _normal, 0 ) 
    9090#define _rm32   CONSTRUCT_FLAGS(_32, _rm, _normal, 0) 
     91#define _rm64   CONSTRUCT_FLAGS(_64, _rm, _normal, 0) 
    9192#define _r32m16 CONSTRUCT_FLAGS(_32|_16, _rm, _normal, 0) 
    9293#define _imm8   CONSTRUCT_FLAGS(_8, _imm, _normal, 0 ) 
    9394#define _imm16  CONSTRUCT_FLAGS(_16, _imm, _normal, 0) 
    9495#define _imm32  CONSTRUCT_FLAGS(_32, _imm, _normal, 0) 
    9596#define _rel8   CONSTRUCT_FLAGS(_8, _rel, _normal, 0) 
    9697#define _rel16  CONSTRUCT_FLAGS(_16, _rel, _normal, 0) 
    9798#define _rel32  CONSTRUCT_FLAGS(_32, _rel, _normal, 0) 
    9899#define _p1616  CONSTRUCT_FLAGS(_32, _p, _normal, 0) 
    99100#define _m1616  CONSTRUCT_FLAGS(_32, _mnoi, _normal, 0) 
    100101#define _p1632  CONSTRUCT_FLAGS(_48, _p, _normal, 0 ) 
    101102#define _m1632  CONSTRUCT_FLAGS(_48, _mnoi, _normal, 0) 
    102103#define _special  CONSTRUCT_FLAGS( 0, 0, _rspecial, 0 ) 
    103104#define _seg    CONSTRUCT_FLAGS( 0, 0, _rseg, 0 ) 
    104105#define _a16    CONSTRUCT_FLAGS( 0, 0, _addr16, 0 ) 
    105106#define _a32    CONSTRUCT_FLAGS( 0, 0, _addr32, 0 ) 
    106107#define _f16    CONSTRUCT_FLAGS( 0, 0, _fn16, 0) 
    107108                                                // Near function pointer 
    108109#define _f32    CONSTRUCT_FLAGS( 0, 0, _fn32, 0) 
    109110                                                // Far function pointer 
    110111#define _lbl    CONSTRUCT_FLAGS( 0, 0, _flbl, 0 ) 
  • branches/dmd-1.x/src/backend/ptrntab.c

    r572 r577  
    500500PTRNTAB1 aptb1LOOPZ[] = /* LOOPZ */ { 
    501501        { 0xe1, _cb | _modcx,_rel8 }, 
    502502        { ASM_END, 0, 0 } 
    503503}; 
    504504PTRNTAB1 aptb1LOOPNE[] = /* LOOPNE */ { 
    505505        { 0xe0, _cb | _modcx,_rel8 }, 
    506506        { ASM_END, 0, 0 } 
    507507}; 
    508508PTRNTAB1 aptb1LOOPNZ[] = /* LOOPNZ */ { 
    509509        { 0xe0, _cb | _modcx,_rel8 }, 
    510510        { ASM_END, 0, 0 } 
    511511}; 
    512512PTRNTAB1 aptb1LTR[] = /* LTR */ { 
    513513        { 0x0f00,       _3|_modnot1,    _rm16 }, 
    514514        { ASM_END, 0, 0 } 
    515515}; 
    516516PTRNTAB1 aptb1NEG[] = /* NEG */ { 
    517517        { 0xf6, _3,     _rm8 }, 
    518518        { 0xf7, _3 | _16_bit,   _rm16 }, 
    519519        { 0xf7, _3 | _32_bit,   _rm32 }, 
     520        { 0xf7, _3 | _64_bit,   _rm64 }, 
    520521        { ASM_END, 0, 0 } 
    521522}; 
    522523PTRNTAB1 aptb1NOT[] = /* NOT */ { 
    523524        { 0xf6, _2,     _rm8 }, 
    524525        { 0xf7, _2 | _16_bit,   _rm16 }, 
    525526        { 0xf7, _2 | _32_bit,   _rm32 }, 
    526527        { ASM_END, 0, 0 } 
    527528}; 
    528529PTRNTAB1 aptb1POP[] = /* POP */ { 
    529530        { 0x8f, _0 | _16_bit, _m16 }, 
    530531        { 0x8f, _0 | _32_bit,   _m32}, 
    531532        { 0x58, _rw | _16_bit, _r16 | _plus_r }, 
    532533        { 0x58, _rd | _32_bit, _r32 | _plus_r }, 
     534        { 0x58, _r | _64_bit,   _r64 | _plus_r }, 
    533535        { 0x1f, 0,      _ds | _seg }, 
    534536        { 0x07, _modes, _es | _seg}, 
    535537        { 0x17, 0,      _ss | _seg}, 
    536538        { 0x0fa1,       0,      _fs | _seg}, 
    537539        { 0x0fa9,       0,      _gs | _seg}, 
    538540        { ASM_END, 0, 0 } 
    539541}; 
    540542PTRNTAB1 aptb1PUSH[] = /* PUSH */ { 
    541543        { 0xff, _6 | _16_bit,   _m16 }, 
    542544        { 0xff, _6 | _32_bit,   _m32 }, 
     545        { 0xff, _6 | _64_bit,   _m64 }, 
    543546        { 0x50, _r | _16_bit,   _r16 | _plus_r }, 
    544547        { 0x50, _r | _32_bit,   _r32 | _plus_r }, 
     548        { 0x50, _r | _64_bit,   _r64 | _plus_r }, 
    545549        { 0x6a, 0,_imm8 }, 
    546550        { 0x68, _16_bit,_imm16 }, 
    547551        { 0x68, _16_bit,_rel16 }, 
    548552        { 0x68, _32_bit,_imm32 }, 
    549553        { 0x68, _32_bit,_rel32 }, 
    550554        { 0x0e, 0,_cs | _seg}, 
    551555        { 0x16, 0,_ss | _seg}, 
    552556        { 0x1e, 0,_ds | _seg}, 
    553557        { 0x06, 0,_es | _seg}, 
    554558        { 0x0fa0,       0,_fs | _seg}, 
    555559        { 0x0fa8,       0,_gs | _seg}, 
    556560        { ASM_END, 0, 0 } 
    557561}; 
    558562PTRNTAB1 aptb1RET[] = /* RET */ { 
    559563        { 0xc3, 0,      0 }, 
    560564        { 0xc2, _iw,    _imm16 }, 
    561565        { ASM_END, 0, 0 } 
    562566}; 
    563567PTRNTAB1 aptb1RETF[] = /* RETF */ { 
    564568        { 0xcb, 0, 0 }, 
  • branches/dmd-1.x/src/freebsd.mak

    r532 r577  
    77 
    88#OPT=-g -g3 
    99#OPT=-O2 
    1010 
    1111#COV=-fprofile-arcs -ftest-coverage 
    1212 
    1313WARNINGS=-Wno-deprecated -Wstrict-aliasing 
    1414 
    1515#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 $(COV) 
    1616GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 
    1717 
    1818CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_FREEBSD=1 -D_DH 
    1919MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_FREEBSD=1 -D_DH 
    2020 
    2121CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    2222    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    2323TOTALH= 
    2424 
    2525DMD_OBJS = \ 
    2626    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    27     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     27    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    2828    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    2929    constfold.o irstate.o dchar.o cond.o debug.o \ 
    3030    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    3131    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    3232    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    3333    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    3434    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    3535    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    3636    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    3737    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    3838    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    3939    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    4040    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    4141    builtin.o clone.o aliasthis.o \ 
    4242    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    4343    imphint.o \ 
    4444    libelf.o elfobj.o 
    4545 
    4646SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    4747    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • branches/dmd-1.x/src/iasm.c

    r572 r577  
    9393    EM_num, 
    9494    EM_float, 
    9595    EM_char, 
    9696    EM_label_expected, 
    9797    EM_uplevel, 
    9898    EM_type_as_operand, 
    9999}; 
    100100 
    101101const char *asmerrmsgs[] = 
    102102{ 
    103103    "unknown operand for floating point instruction", 
    104104    "bad addr mode", 
    105105    "align %d must be a power of 2", 
    106106    "opcode expected, not %s", 
    107107    "prefix", 
    108108    "end of instruction", 
    109109    "bad operand", 
    110110    "bad integral operand", 
    111111    "identifier expected", 
    112112    "not struct", 
    113     "nops expected", 
     113    "%u operands found for %s instead of the expected %u", 
    114114    "bad type/size of operands '%s'", 
    115115    "constant initializer expected", 
    116116    "undefined identifier '%s'", 
    117117    "pointer", 
    118118    "colon", 
    119119    "] expected instead of '%s'", 
    120120    ") expected instead of '%s'", 
    121121    "ptr expected", 
    122122    "integer expected", 
    123123    "floating point expected", 
    124124    "character is truncated", 
    125125    "label expected", 
    126126    "uplevel nested reference to variable %s", 
    127127    "cannot use type %s as an operand" 
    128128}; 
    129129 
    130130// Additional tokens for the inline assembler 
    131131typedef enum 
    132132{ 
    133133    ASMTKlocalsize = TOKMAX + 1, 
     
    575575            { 
    576576                popnd2->usFlags = usFlags2 = asm_determine_operand_flags(popnd2); 
    577577                if (!popnd3) 
    578578                    usNumops = 2; 
    579579                else 
    580580                { 
    581581                    popnd3->usFlags = usFlags3 = asm_determine_operand_flags(popnd3); 
    582582                    usNumops = 3; 
    583583                } 
    584584            } 
    585585        } 
    586586 
    587587        // Now check to insure that the number of operands is correct 
    588588        usActual = (pop->usNumops & ITSIZE); 
    589589        if (usActual != usNumops && asmstate.ucItype != ITopt && 
    590590            asmstate.ucItype != ITfloat) 
    591591        { 
    592592PARAM_ERROR: 
    593593                asmerr(EM_nops_expected, usActual, asm_opstr(pop), usNumops); 
    594594        } 
    595         *pusNumops = asmstate.ucItype == ITfloat ? usActual : usNumops; 
    596595        if (usActual < usNumops) 
    597596            *pusNumops = usActual; 
    598597        else 
    599598            *pusNumops = usNumops; 
    600599// 
    601600//      The number of arguments matches, now check to find the opcode 
    602601//      in the associated opcode table 
    603602// 
    604603RETRY: 
    605604        //printf("usActual = %d\n", usActual); 
    606605        switch (usActual) 
    607606        { 
    608607            case 0: 
    609608                ptbRet = pop->ptb ; 
    610609                goto RETURN_IT; 
    611610 
    612611            case 1: 
    613612                //printf("usFlags1 = "); asm_output_flags(usFlags1); printf("\n"); 
    614613                for (pptb1 = pop->ptb.pptb1; pptb1->usOpcode != ASM_END; 
    615614                        pptb1++) 
     
    14771476                    if (usNumops == 1) 
    14781477                    {   pc->IFL2 = FLblock; 
    14791478                        pc->IEVlsym2 = label; 
    14801479                    } 
    14811480                    else 
    14821481                    {   pc->IFL1 = FLblock; 
    14831482                        pc->IEVlsym1 = label; 
    14841483                    } 
    14851484                } 
    14861485            } 
    14871486        } 
    14881487 
    14891488        switch (usNumops) 
    14901489        { 
    14911490            case 0: 
    14921491                break; 
    14931492            case 1: 
    14941493                if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    14951494                     amodTable1 == _normal && (uRegmaskTable1 & _rplus_r))) 
    14961495                { 
    1497                         if (asmstate.ucItype == ITfloat) 
    1498                                 pc->Irm += popnd1->base->val; 
    1499                         else if (pc->Iop == 0x0f) 
    1500                                 pc->Iop2 += popnd1->base->val; 
    1501                         else 
    1502                                 pc->Iop += popnd1->base->val; 
     1496                    unsigned reg = popnd1->base->val; 
     1497                    if (reg & 8) 
     1498                    {   reg &= 7; 
     1499                        pc->Irex |= REX_B; 
     1500                        assert(I64); 
     1501                    } 
     1502                    if (asmstate.ucItype == ITfloat) 
     1503                        pc->Irm += reg; 
     1504                    else if (pc->Iop == 0x0f) 
     1505                        pc->Iop2 += reg; 
     1506                    else 
     1507                        pc->Iop += reg; 
    15031508#ifdef DEBUG 
    1504                         auchOpcode[usIdx-1] += popnd1->base->val
     1509                    auchOpcode[usIdx-1] += reg
    15051510#endif 
    15061511                } 
    15071512                else 
    15081513                {       asm_make_modrm_byte( 
    15091514#ifdef DEBUG 
    15101515                                auchOpcode, &usIdx, 
    15111516#endif 
    15121517                                pc, 
    15131518                                ptb.pptb1->usFlags, 
    15141519                                popnd1, NULL); 
    15151520                } 
    15161521                popndTmp = popnd1; 
    15171522                aoptyTmp = aoptyTable1; 
    15181523                uSizemaskTmp = uSizemaskTable1; 
    15191524L1: 
    15201525                if (aoptyTmp == _imm) 
    15211526                { 
    15221527                    Declaration *d = popndTmp->s ? popndTmp->s->isDeclaration() 
    15231528                                                 : NULL; 
    15241529                    if (popndTmp->bSeg) 
     
    16081613                        else 
    16091614                        { 
    16101615                            asm_make_modrm_byte( 
    16111616#ifdef DEBUG 
    16121617                                auchOpcode, &usIdx, 
    16131618#endif 
    16141619                                pc, 
    16151620                                ptb.pptb1->usFlags, 
    16161621                                popnd2, popnd1); 
    16171622                        } 
    16181623                        popndTmp = popnd1; 
    16191624                        aoptyTmp = aoptyTable1; 
    16201625                        uSizemaskTmp = uSizemaskTable1; 
    16211626                } 
    16221627                else 
    16231628                { 
    16241629                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    16251630                             amodTable1 == _normal && 
    16261631                             (uRegmaskTable1 & _rplus_r))) 
    16271632                        { 
    1628                                 if (asmstate.ucItype == ITfloat) 
    1629                                         pc->Irm += popnd1->base->val; 
    1630                                 else 
    1631                                 if (pc->Iop == 0x0f) 
    1632                                         pc->Iop2 += popnd1->base->val; 
    1633                                 else 
    1634                                         pc->Iop += popnd1->base->val; 
     1633                            unsigned reg = popnd1->base->val; 
     1634                            if (reg & 8) 
     1635                            {   reg &= 7; 
     1636                                pc->Irex |= REX_B; 
     1637                                assert(I64); 
     1638                            } 
     1639                            if (asmstate.ucItype == ITfloat) 
     1640                                pc->Irm += reg; 
     1641                            else if (pc->Iop == 0x0f) 
     1642                                pc->Iop2 += reg; 
     1643                            else 
     1644                                pc->Iop += reg; 
    16351645#ifdef DEBUG 
    1636                                 auchOpcode[usIdx-1] += popnd1->base->val
     1646                            auchOpcode[usIdx-1] += reg
    16371647#endif 
    16381648                        } 
    16391649                        else 
    16401650                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    16411651                             amodTable2 == _normal && 
    16421652                             (uRegmaskTable2 & _rplus_r))) 
    16431653                        { 
    1644                                 if (asmstate.ucItype == ITfloat) 
    1645                                         pc->Irm += popnd2->base->val; 
    1646                                 else 
    1647                                 if (pc->Iop == 0x0f) 
    1648                                         pc->Iop2 += popnd2->base->val; 
    1649                                 else 
    1650                                         pc->Iop += popnd2->base->val; 
     1654                            unsigned reg = popnd2->base->val; 
     1655                            if (reg & 8) 
     1656                            {   reg &= 7; 
     1657                                pc->Irex |= REX_B; 
     1658                                assert(I64); 
     1659                            } 
     1660                            if (asmstate.ucItype == ITfloat) 
     1661                                pc->Irm += reg; 
     1662                            else if (pc->Iop == 0x0f) 
     1663                                pc->Iop2 += reg; 
     1664                            else 
     1665                                pc->Iop += reg; 
    16511666#ifdef DEBUG 
    1652                                 auchOpcode[usIdx-1] += popnd2->base->val
     1667                            auchOpcode[usIdx-1] += reg
    16531668#endif 
    16541669                        } 
    16551670                        else if (ptb.pptb0->usOpcode == 0xF30FD6 || 
    16561671                                 ptb.pptb0->usOpcode == 0x0F12 || 
    16571672                                 ptb.pptb0->usOpcode == 0x0F16 || 
    16581673                                 ptb.pptb0->usOpcode == 0x660F50 || 
    16591674                                 ptb.pptb0->usOpcode == 0x0F50 || 
    16601675                                 ptb.pptb0->usOpcode == 0x660FD7 || 
    16611676                                 ptb.pptb0->usOpcode == 0x0FD7) 
    16621677                        { 
    16631678                            asm_make_modrm_byte( 
    16641679#ifdef DEBUG 
    16651680                                    auchOpcode, &usIdx, 
    16661681#endif 
    16671682                                    pc, 
    16681683                                    ptb.pptb1->usFlags, 
    16691684                                    popnd2, popnd1); 
    16701685                        } 
    16711686                        else 
    16721687                        { 
     
    16981713                if (aoptyTable2 == _m || aoptyTable2 == _rm || 
    16991714                    usOpcode == 0x0FC5) // PEXTRW 
    17001715                { 
    17011716                    asm_make_modrm_byte( 
    17021717#ifdef DEBUG 
    17031718                                auchOpcode, &usIdx, 
    17041719#endif 
    17051720                                pc, 
    17061721                                ptb.pptb1->usFlags, 
    17071722                                popnd2, popnd1); 
    17081723                        popndTmp = popnd3; 
    17091724                        aoptyTmp = aoptyTable3; 
    17101725                        uSizemaskTmp = uSizemaskTable3; 
    17111726                } 
    17121727                else { 
    17131728 
    17141729                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    17151730                             amodTable1 == _normal && 
    17161731                             (uRegmaskTable1 &_rplus_r))) 
    17171732                        { 
    1718                                 if (asmstate.ucItype == ITfloat) 
    1719                                         pc->Irm += popnd1->base->val; 
    1720                                 else 
    1721                                 if (pc->Iop == 0x0f) 
    1722                                         pc->Iop2 += popnd1->base->val; 
    1723                                 else 
    1724                                         pc->Iop += popnd1->base->val; 
     1733                            unsigned reg = popnd1->base->val; 
     1734                            if (reg & 8) 
     1735                            {   reg &= 7; 
     1736                                pc->Irex |= REX_B; 
     1737                                assert(I64); 
     1738                            } 
     1739                            if (asmstate.ucItype == ITfloat) 
     1740                                pc->Irm += reg; 
     1741                            else if (pc->Iop == 0x0f) 
     1742                                pc->Iop2 += reg; 
     1743                            else 
     1744                                pc->Iop += reg; 
    17251745#ifdef DEBUG 
    1726                                 auchOpcode[usIdx-1] += popnd1->base->val
     1746                            auchOpcode[usIdx-1] += reg
    17271747#endif 
    17281748                        } 
    17291749                        else 
    17301750                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    17311751                             amodTable2 == _normal && 
    17321752                             (uRegmaskTable2 &_rplus_r))) 
    17331753                        { 
    1734                                 if (asmstate.ucItype == ITfloat) 
    1735                                         pc->Irm += popnd1->base->val; 
    1736                                 else 
    1737                                 if (pc->Iop == 0x0f) 
    1738                                         pc->Iop2 += popnd1->base->val; 
    1739                                 else 
    1740                                         pc->Iop += popnd2->base->val; 
     1754                            unsigned reg = popnd1->base->val; 
     1755                            if (reg & 8) 
     1756                            {   reg &= 7; 
     1757                                pc->Irex |= REX_B; 
     1758                                assert(I64); 
     1759                            } 
     1760                            if (asmstate.ucItype == ITfloat) 
     1761                                pc->Irm += reg; 
     1762                            else if (pc->Iop == 0x0f) 
     1763                                pc->Iop2 += reg; 
     1764                            else 
     1765                                pc->Iop += reg; 
    17411766#ifdef DEBUG 
    1742                                 auchOpcode[usIdx-1] += popnd2->base->val
     1767                            auchOpcode[usIdx-1] += reg
    17431768#endif 
    17441769                        } 
    17451770                        else 
    17461771                                asm_make_modrm_byte( 
    17471772#ifdef DEBUG 
    17481773                                        auchOpcode, &usIdx, 
    17491774#endif 
    17501775                                        pc, 
    17511776                                        ptb.pptb1->usFlags, 
    17521777                                        popnd1, popnd2); 
    17531778 
    17541779                        popndTmp = popnd3; 
    17551780                        aoptyTmp = aoptyTable3; 
    17561781                        uSizemaskTmp = uSizemaskTable3; 
    17571782 
    17581783                } 
    17591784                goto L1; 
    17601785        } 
    17611786L2: 
    17621787 
     
    26552680    case _modsidi: 
    26562681        usRet |= (mSI | mDI); 
    26572682        break; 
    26582683    case _modcx: 
    26592684        usRet |= mCX; 
    26602685        break; 
    26612686    case _modes: 
    26622687        /*usRet |= mES;*/ 
    26632688        break; 
    26642689    case _modall: 
    26652690        asmstate.bReturnax = TRUE; 
    26662691        return /*mES |*/ ALLREGS; 
    26672692    case _modsiax: 
    26682693        usRet |= (mSI | mAX); 
    26692694        break; 
    26702695    case _modsinot1: 
    26712696        usRet |= mSI; 
    26722697        popnd1 = NULL; 
    26732698        break; 
    26742699    } 
    2675     if (popnd1 && ASM_GET_aopty(popnd1->usFlags) == _reg) { 
    2676         switch (ASM_GET_amod(popnd1->usFlags)) { 
     2700    if (popnd1 && ASM_GET_aopty(popnd1->usFlags) == _reg) 
     2701    { 
     2702        switch (ASM_GET_amod(popnd1->usFlags)) 
     2703        { 
    26772704        default: 
    2678             if (ASM_GET_uSizemask(popnd1->usFlags) == _8) { 
    2679                 switch(popnd1->base->val) { 
    2680                     case _AL: 
    2681                     case _AH: 
    2682                         usRet |= mAX; 
    2683                         break; 
    2684                     case _BL: 
    2685                     case _BH: 
    2686                         usRet |= mBX; 
    2687                         break; 
    2688                     case _CL: 
    2689                     case _CH: 
    2690                         usRet |= mCX; 
    2691                         break; 
    2692                     case _DL: 
    2693                     case _DH: 
    2694                         usRet |= mDX; 
    2695                         break; 
    2696                     default: 
    2697                         assert(0); 
    2698                 } 
    2699             } 
    2700             else { 
    2701                 switch (popnd1->base->val) { 
    2702                     case _AX: 
    2703                         usRet |= mAX; 
    2704                         break; 
    2705                     case _BX: 
    2706                         usRet |= mBX; 
    2707                         break; 
    2708                     case _CX: 
    2709                         usRet |= mCX; 
    2710                         break; 
    2711                     case _DX: 
    2712                         usRet |= mDX; 
    2713                         break; 
    2714                     case _SI: 
    2715                         usRet |= mSI; 
    2716                         break; 
    2717                     case _DI: 
    2718                         usRet |= mDI; 
    2719                         break; 
    2720                 } 
    2721             } 
     2705            usRet |= 1 << popnd1->base->val; 
     2706            usRet &= ~(mBP | mSP);              // ignore changing these 
    27222707            break; 
    27232708        case _rseg: 
    27242709            //if (popnd1->base->val == _ES) 
    27252710                //usRet |= mES; 
    27262711            break; 
    27272712 
    27282713        case _rspecial: 
    27292714            break; 
    27302715        } 
    27312716    } 
    27322717    if (usRet & mAX) 
    27332718        asmstate.bReturnax = TRUE; 
    27342719 
    27352720    return usRet; 
    27362721} 
    27372722 
    27382723/******************************* 
    27392724 * Match flags in operand against flags in opcode table. 
    27402725 * Returns: 
    27412726 *      !=0 if match 
  • branches/dmd-1.x/src/linux.mak

    r569 r577  
    99 
    1010#OPT=-g -g3 
    1111#OPT=-O2 
    1212 
    1313#COV=-fprofile-arcs -ftest-coverage 
    1414 
    1515WARNINGS=-Wno-deprecated -Wstrict-aliasing 
    1616 
    1717#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 $(COV) 
    1818GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 
    1919 
    2020CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_LINUX=1 -D_DH 
    2121MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_LINUX=1 -D_DH 
    2222 
    2323CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    2424    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    2525TOTALH= 
    2626 
    2727DMD_OBJS = \ 
    2828    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    29     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     29    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    3030    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    3131    constfold.o irstate.o dchar.o cond.o debug.o \ 
    3232    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    3333    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    3434    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    3535    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    3636    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    3737    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    3838    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    3939    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    4040    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    4141    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    4242    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    4343    builtin.o clone.o aliasthis.o \ 
    4444    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    4545    imphint.o \ 
    4646    libelf.o elfobj.o 
    4747 
    4848SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    4949    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • branches/dmd-1.x/src/osx.mak

    r532 r577  
    1515 
    1616#OPT=-g -g3 
    1717#OPT=-O2 
    1818 
    1919#COV=-fprofile-arcs -ftest-coverage 
    2020 
    2121WARNINGS=-Wno-deprecated -Wstrict-aliasing 
    2222 
    2323#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) 
    2424GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 
    2525 
    2626CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_OSX=1 -D_DH 
    2727MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_OSX=1 -D_DH 
    2828 
    2929CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    3030    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    3131TOTALH= 
    3232 
    3333DMD_OBJS = \ 
    3434    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    35     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     35    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    3636    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    3737    constfold.o irstate.o dchar.o cond.o debug.o \ 
    3838    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    3939    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    4040    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    4141    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    4242    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    4343    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    4444    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    4545    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    4646    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    4747    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    4848    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    4949    builtin.o clone.o aliasthis.o \ 
    5050    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    5151    imphint.o \ 
    5252    libmach.o machobj.o 
    5353 
    5454SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    5555    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • branches/dmd-1.x/src/solaris.mak

    r473 r577  
    55 
    66CC=g++ -m32 
    77 
    88#OPT=-g -g3 
    99#OPT=-O2 
    1010 
    1111#COV=-fprofile-arcs -ftest-coverage 
    1212 
    1313#GFLAGS = -Wno-deprecated -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 $(COV) 
    1414GFLAGS = -Wno-deprecated -D__near= -D__pascal= -fno-exceptions -O2 
    1515 
    1616CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_SOLARIS=1 -D_DH 
    1717MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_SOLARIS=1 -D_DH 
    1818 
    1919CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    2020    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    2121TOTALH= 
    2222 
    2323DMD_OBJS = \ 
    2424    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    25     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     25    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    2626    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    2727    constfold.o irstate.o dchar.o cond.o debug.o \ 
    2828    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    2929    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    3030    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    3131    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    3232    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    3333    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    3434    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    3535    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    3636    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    3737    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    3838    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    3939    builtin.o clone.o aliasthis.o \ 
    4040    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    4141    imphint.o \ 
    4242    libelf.o elfobj.o 
    4343 
    4444SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    4545    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • trunk/src/backend/cdef.h

    r569 r577  
    542542#define LARGECODE       (config.memmodel & 5) 
    543543 
    544544#define Smodel 0        /* 64k code, 64k data           */ 
    545545#define Mmodel 1        /* large code, 64k data         */ 
    546546#define Cmodel 2        /* 64k code, large data         */ 
    547547#define Lmodel 3        /* large code, large data       */ 
    548548#define Vmodel 4        /* large code, large data, vcm  */ 
    549549#define MEMMODELS 5     /* number of memory models      */ 
    550550#endif 
    551551 
    552552/* Segments     */ 
    553553#define CODE    1       /* code segment                 */ 
    554554#define DATA    2       /* initialized data             */ 
    555555#define CDATA   3       /* constant data                */ 
    556556#define UDATA   4       /* uninitialized data           */ 
    557557#define UNKNOWN 0x7FFF  // unknown segment 
    558558#define DGROUPIDX 1     /* group index of DGROUP        */ 
    559559 
    560560#define KEEPBITFIELDS 0 /* 0 means code generator cannot handle bit fields, */ 
    561561                        /* so replace them with shifts and masks        */ 
    562  
    563 #if TARGET_OSX 
    564 #define STACKALIGN      16 
    565 #else 
    566 #define STACKALIGN      0 
    567 #endif 
    568562 
    569563#define REGMAX  29      // registers are numbered 0..10 
    570564 
    571565typedef unsigned        tym_t;          // data type big enough for type masks 
    572566typedef int             SYMIDX;         // symbol table index 
    573567 
    574568#if 0 
    575569#if defined(__DMC__) && __DMC__ < 0x81e 
    576570typedef int bool; 
    577571#endif 
    578572#define bool int 
    579573#endif 
    580574 
    581575#define _chkstack()     (void)0 
    582576 
    583577/* For 32 bit compilations, we don't need far keyword   */ 
    584578#if 1 
    585579#define far 
    586580#define _far 
    587581#define __far 
  • trunk/src/backend/cg87.c

    r569 r577  
    11// Copyright (C) 1987-1995 by Symantec 
    2 // Copyright (C) 2000-2009 by Digital Mars 
     2// Copyright (C) 2000-2010 by Digital Mars 
    33// All Rights Reserved 
    44// http://www.digitalmars.com 
    55// Written by Walter Bright 
    66/* 
    77 * This source file is made available for personal use 
    88 * only. The license is in /dmd/src/dmd/backendlicense.txt 
    99 * or /dm/src/dmd/backendlicense.txt 
    1010 * For any other uses, please contact Digital Mars. 
    1111 */ 
    1212 
    1313#if !SPP 
    1414 
    1515#include        <stdio.h> 
    1616#include        <string.h> 
    1717#include        <time.h> 
    1818#include        <math.h> 
    1919#include        "cc.h" 
    2020#include        "el.h" 
    2121#include        "oper.h" 
    2222#include        "code.h" 
     
    8080/********************************** 
    8181 * When we need to temporarilly save 8087 registers, we record information 
    8282 * about the save into an array of NDP structs: 
    8383 */ 
    8484 
    8585NDP *NDP::save = NULL; 
    8686int NDP::savemax = 0;           /* # of entries in NDP::save[]          */ 
    8787int NDP::savetop = 0;           /* # of entries used in NDP::save[]     */ 
    8888 
    8989#ifdef DEBUG 
    9090#define NDPSAVEINC 2            /* flush reallocation bugs              */ 
    9191#else 
    9292#define NDPSAVEINC 8            /* allocation chunk sizes               */ 
    9393#endif 
    9494 
    9595/**************************************** 
    9696 * Store/load to ndp save location i 
    9797 */ 
    9898 
    9999code *ndp_fstp(code *c, int i, tym_t ty) 
    100 { 
     100{   unsigned grex = I64 ? (REX_W << 16) : 0; 
    101101    switch (tybasic(ty)) 
    102102    { 
    103103        case TYfloat: 
    104104        case TYifloat: 
    105105        case TYcfloat: 
    106             c = genc1(c,0xD9,modregrm(2,3,BPRM),FLndp,i); // FSTP m32real i[BP] 
     106            c = genc1(c,0xD9,grex | modregrm(2,3,BPRM),FLndp,i); // FSTP m32real i[BP] 
    107107            break; 
    108108 
    109109        case TYdouble: 
    110110        case TYdouble_alias: 
    111111        case TYidouble: 
    112112        case TYcdouble: 
    113             c = genc1(c,0xDD,modregrm(2,3,BPRM),FLndp,i); // FSTP m64real i[BP] 
     113            c = genc1(c,0xDD,grex | modregrm(2,3,BPRM),FLndp,i); // FSTP m64real i[BP] 
    114114            break; 
    115115 
    116116        case TYldouble: 
    117117        case TYildouble: 
    118118        case TYcldouble: 
    119             c = genc1(c,0xDB,modregrm(2,7,BPRM),FLndp,i); // FSTP m80real i[BP] 
     119            c = genc1(c,0xDB,grex | modregrm(2,7,BPRM),FLndp,i); // FSTP m80real i[BP] 
    120120            break; 
    121121 
    122122        default: 
    123123            assert(0); 
    124124    } 
    125125    return c; 
    126126} 
    127127 
    128128code *ndp_fld(code *c, int i, tym_t ty) 
    129 { 
     129{   unsigned grex = I64 ? (REX_W << 16) : 0; 
    130130    switch (tybasic(ty)) 
    131131    { 
    132132        case TYfloat: 
    133133        case TYifloat: 
    134134        case TYcfloat: 
    135             c = genc1(c,0xD9,modregrm(2,0,BPRM),FLndp,i); 
     135            c = genc1(c,0xD9,grex | modregrm(2,0,BPRM),FLndp,i); 
    136136            break; 
    137137 
    138138        case TYdouble: 
    139139        case TYdouble_alias: 
    140140        case TYidouble: 
    141141        case TYcdouble: 
    142             c = genc1(c,0xDD,modregrm(2,0,BPRM),FLndp,i); 
     142            c = genc1(c,0xDD,grex | modregrm(2,0,BPRM),FLndp,i); 
    143143            break; 
    144144 
    145145        case TYldouble: 
    146146        case TYildouble: 
    147147        case TYcldouble: 
    148             c = genc1(c,0xDB,modregrm(2,5,BPRM),FLndp,i); // FLD m80real i[BP] 
     148            c = genc1(c,0xDB,grex | modregrm(2,5,BPRM),FLndp,i); // FLD m80real i[BP] 
    149149            break; 
    150150 
    151151        default: 
    152152            assert(0); 
    153153    } 
    154154    return c; 
    155155} 
    156156 
    157157/************************** 
    158158 * Return index of empty slot in NDP::save[]. 
    159159 */ 
    160160 
    161161STATIC int getemptyslot() 
    162162{       int i; 
    163163 
    164164        for (i = 0; i < NDP::savemax; i++) 
    165165                if (NDP::save[i].e == NULL) 
    166166                        goto L1; 
    167167        /* Out of room, reallocate NDP::save[]  */ 
    168168        NDP::save = (NDP *)mem_realloc(NDP::save, 
     
    428428            break; 
    429429        } 
    430430        if (_8087elems[i].e == e && 
    431431            _8087elems[i].offset == offset) 
    432432        {   //printf("cse found %d\n",i); 
    433433            //elem_print(e); 
    434434            break; 
    435435        } 
    436436    } 
    437437    return i; 
    438438} 
    439439 
    440440/************************************* 
    441441 * Reload common subexpression. 
    442442 */ 
    443443 
    444444code *comsub87(elem *e,regm_t *pretregs) 
    445445{   code *c; 
    446446 
    447447    // Look on 8087 stack 
    448     int i; 
    449  
    450     i = cse_get(e, 0); 
     448    int i = cse_get(e, 0); 
    451449 
    452450    if (tycomplex(e->Ety)) 
    453     {   unsigned sz; 
    454         int j; 
    455  
    456         sz = tysize(e->Ety); 
    457         j = cse_get(e, sz / 2); 
     451    { 
     452        unsigned sz = tysize(e->Ety); 
     453        int j = cse_get(e, sz / 2); 
    458454        if (i >= 0 && j >= 0) 
    459455        { 
    460456            c = push87(); 
    461457            c = cat(c, push87()); 
    462458            c = genf2(c,0xD9,0xC0 + i);         // FLD ST(i) 
    463459            c = genf2(c,0xD9,0xC0 + j + 1);     // FLD ST(j + 1) 
    464460            c = cat(c,fixresult_complex87(e,mST01,pretregs)); 
    465461        } 
    466462        else 
    467463            // Reload 
    468464            c = loaddata(e,pretregs); 
    469465    } 
    470466    else 
    471467    { 
    472468        if (i >= 0) 
    473469        { 
    474470            c = push87(); 
    475471            c = genf2(c,0xD9,0xC0 + i); // FLD ST(i) 
    476472            c = cat(c,fixresult(e,mST0,pretregs)); 
    477473        } 
    478474        else 
    479475            // Reload 
    480476            c = loaddata(e,pretregs); 
    481477    } 
    482478 
    483479    freenode(e); 
    484480    return c; 
    485481} 
    486482 
    487483 
    488484/************************** 
    489485 * Generate code to deal with floatreg. 
    490486 */ 
    491487 
    492488code * genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset) 
    493489{ 
    494490        floatreg = TRUE; 
    495491        reflocal = TRUE; 
    496492        if ((opcode & 0xF8) == 0xD8) 
    497493            c = genfwait(c); 
    498         return genc1(c,opcode,modregrm(2,reg,BPRM),FLfltreg,offset); 
     494        unsigned grex = I64 ? (REX_W << 16) : 0; 
     495        return genc1(c,opcode,grex | modregxrm(2,reg,BPRM),FLfltreg,offset); 
    499496} 
    500497 
    501498/******************************* 
    502499 * Decide if we need to gen an FWAIT. 
    503500 */ 
    504501 
    505502code *genfwait(code *c) 
    506503{ 
    507504    if (ADDFWAIT()) 
    508505        c = gen1(c,FWAIT); 
    509506    return c; 
    510507} 
    511508 
    512509/*************************************** 
    513510 * Generate floating point instruction. 
    514511 */ 
    515512 
    516513STATIC code * genf2(code *c,unsigned op,unsigned rm) 
    517514{ 
    518515    return gen2(genfwait(c),op,rm); 
     
    743740    tym_t tym; 
    744741    code *c1,*c2; 
    745742    unsigned sz; 
    746743 
    747744    //printf("fixresult87(e = %p, retregs = x%x, *pretregs = x%x)\n", e,retregs,*pretregs); 
    748745    //printf("fixresult87(e = %p, retregs = %s, *pretregs = %s)\n", e,regm_str(retregs),regm_str(*pretregs)); 
    749746    assert(!*pretregs || retregs); 
    750747    c1 = CNIL; 
    751748    c2 = CNIL; 
    752749    tym = tybasic(e->Ety); 
    753750    sz = tysize[tym]; 
    754751    //printf("tym = x%x, sz = %d\n", tym, sz); 
    755752 
    756753    if (*pretregs & mST01) 
    757754        return fixresult_complex87(e, retregs, pretregs); 
    758755 
    759756    /* if retregs needs to be transferred into the 8087 */ 
    760757    if (*pretregs & mST0 && retregs & (mBP | ALLREGS)) 
    761758    { 
    762759        assert(sz <= DOUBLESIZE); 
    763         if (I32
     760        if (!I16
    764761        { 
    765762 
    766763            if (*pretregs & mPSW) 
    767764            {   // Set flags 
    768                 regm_t r; 
    769  
    770                 r = retregs | mPSW; 
     765                regm_t r = retregs | mPSW; 
    771766                c1 = fixresult(e,retregs,&r); 
    772767            } 
    773768            c2 = push87(); 
    774             if (sz == REGSIZE) 
    775             {   unsigned reg; 
    776  
    777                 reg = findreg(retregs); 
     769            if (sz == REGSIZE || (I64 && sz == 4)) 
     770            { 
     771                unsigned reg = findreg(retregs); 
    778772                c2 = genfltreg(c2,0x89,reg,0);          // MOV fltreg,reg 
    779773                genfltreg(c2,0xD9,0,0);                 // FLD float ptr fltreg 
    780774            } 
    781775            else 
    782776            {   unsigned msreg,lsreg; 
    783777 
    784778                msreg = findregmsw(retregs); 
    785779                lsreg = findreglsw(retregs); 
    786780                c2 = genfltreg(c2,0x89,lsreg,0);        // MOV fltreg,lsreg 
    787781                genfltreg(c2,0x89,msreg,4);             // MOV fltreg+4,msreg 
    788782                genfltreg(c2,0xDD,0,0);                 // FLD double ptr fltreg 
    789783            } 
    790784        } 
    791785        else 
    792786        { 
    793787            regm = (sz == FLOATSIZE) ? FLOATREGS : DOUBLEREGS; 
    794788            regm |= *pretregs & mPSW; 
    795789            c1 = fixresult(e,retregs,&regm); 
    796790            regm = 0;           // don't worry about result from CLIBxxx 
    797791            c2 = callclib(e, 
    798792                    ((sz == FLOATSIZE) ? CLIBfltto87 : CLIBdblto87), 
    799793                    &regm,0); 
    800794        } 
    801795    } 
    802796    else if (*pretregs & (mBP | ALLREGS) && retregs & mST0) 
    803797    {   unsigned mf; 
    804798        unsigned reg; 
    805799 
    806800        assert(sz <= DOUBLESIZE); 
    807801        mf = (sz == FLOATSIZE) ? MFfloat : MFdouble; 
    808802        if (*pretregs & mPSW && !(retregs & mPSW)) 
    809803                c1 = genftst(c1,e,0); 
    810804        /* FSTP floatreg        */ 
    811805        pop87(); 
    812806        c1 = genfltreg(c1,ESC(mf,1),3,0); 
    813807        genfwait(c1); 
    814808        c2 = allocreg(pretregs,&reg,(sz == FLOATSIZE) ? TYfloat : TYdouble); 
    815809        if (sz == FLOATSIZE) 
    816810        { 
    817             if (I32
     811            if (!I16
    818812                c2 = genfltreg(c2,0x8B,reg,0); 
    819813            else 
    820814            {   c2 = genfltreg(c2,0x8B,reg,REGSIZE); 
    821815                genfltreg(c2,0x8B,findreglsw(*pretregs),0); 
    822816            } 
    823817        } 
    824818        else 
    825819        { 
    826             if (I32
     820            if (!I16
    827821            {   c2 = genfltreg(c2,0x8B,reg,REGSIZE); 
    828822                genfltreg(c2,0x8B,findreglsw(*pretregs),0); 
    829823            } 
    830824            else 
    831825            {   c2 = genfltreg(c2,0x8B,AX,6); 
    832826                genfltreg(c2,0x8B,BX,4); 
    833827                genfltreg(c2,0x8B,CX,2); 
    834828                genfltreg(c2,0x8B,DX,0); 
    835829            } 
    836830        } 
    837831    } 
    838832    else if (*pretregs == 0 && retregs == mST0) 
    839833    { 
    840834        c1 = genf2(c1,0xDD,modregrm(3,3,0));    // FPOP 
    841835        pop87(); 
    842836    } 
    843837    else 
    844838    {   if (*pretregs & mPSW) 
    845839        {   if (!(retregs & mPSW)) 
    846840            {   assert(retregs & mST0); 
     
    13821376            (e2->E1->Eoper == OPs32_d || e2->E1->Eoper == OPs64_d || e2->E1->Eoper == OPs16_d) && 
    13831377            e2->E1->E1->Eoper == OPvar 
    13841378          ) || 
    13851379          ((e2oper == OPs32_d || e2oper == OPs64_d || e2oper == OPs16_d) && 
    13861380            e2->E1->Eoper == OPvar 
    13871381          ) 
    13881382         ) 
    13891383        ) 
    13901384       ) 
    13911385    {   // Reverse order of evaluation 
    13921386        e1 = e->E2; 
    13931387        e2 = e->E1; 
    13941388        op = oprev[op + 1]; 
    13951389        reverse ^= 1; 
    13961390    } 
    13971391 
    13981392    c1 = codelem(e1,&retregs,FALSE); 
    13991393    note87(e1,0,0); 
    14001394 
    14011395    if (config.flags4 & CFG4fdivcall && e->Eoper == OPdiv) 
    1402     {   regm_t retregs; 
    1403  
    1404         retregs = mST0; 
     1396    { 
     1397        regm_t retregs = mST0; 
    14051398        c2 = load87(e2,0,&retregs,e1,-1); 
    14061399        c2 = cat(c2,makesure87(e1,0,1,0)); 
    14071400        if (op == 7)                    // if reverse divide 
    14081401            c2 = genf2(c2,0xD9,0xC8 + 1);       // FXCH ST(1) 
    14091402        c2 = cat(c2,callclib(e,CLIBfdiv87,&retregs,0)); 
    14101403        pop87(); 
    14111404        resregm = mST0; 
    14121405        freenode(e2); 
    14131406        c4 = fixresult87(e,resregm,pretregs); 
    14141407    } 
    14151408    else if (e->Eoper == OPmod) 
    14161409    { 
    14171410        /* 
    14181411         *              fld     tbyte ptr y 
    14191412         *              fld     tbyte ptr x             // ST = x, ST1 = y 
    14201413         *      FM1:    // We don't use fprem1 because for some inexplicable 
    14211414         *              // reason we get -5 when we do _modulo(15, 10) 
    14221415         *              fprem                           // ST = ST % ST1 
    14231416         *              fstsw   word ptr sw 
    14241417         *              fwait 
    14251418         *              mov     AH,byte ptr sw+1        // get msb of status word in AH 
    14261419         *              sahf                            // transfer to flags 
    14271420         *              jp      FM1                     // continue till ST < ST1 
    14281421         *              fstp    ST(1)                   // leave remainder on stack 
    14291422         */ 
    1430         regm_t retregs; 
    1431  
    1432         retregs = mST0; 
     1423        regm_t retregs = mST0; 
    14331424        c2 = load87(e2,0,&retregs,e1,-1); 
    14341425        c2 = cat(c2,makesure87(e1,0,1,0));      // now have x,y on stack; need y,x 
    14351426        if (!reverse)                           // if not reverse modulo 
    14361427            c2 = genf2(c2,0xD9,0xC8 + 1);       // FXCH ST(1) 
    14371428 
    14381429        c3 = gen2(NULL, 0xD9, 0xF8);            // FM1: FPREM 
    14391430        c3 = cg87_87topsw(c3); 
    14401431        c3 = genjmp(c3, JP, FLcode, (block *)c3); // JP FM1 
    14411432        c3 = genf2(c3,0xDD,0xD8 + 1);           // FSTP ST(1) 
    14421433 
    14431434        pop87(); 
    14441435        resregm = mST0; 
    14451436        freenode(e2); 
    14461437        c4 = fixresult87(e,resregm,pretregs); 
    14471438    } 
    14481439    else 
    14491440    {   c2 = load87(e2,0,pretregs,e1,op); 
    14501441        freenode(e2); 
    14511442    } 
    14521443    if (*pretregs & mST0) 
     
    15931584                            break; 
    15941585                    } 
    15951586                    note87(e,0,0); 
    15961587                } 
    15971588                break; 
    15981589            case OPd_f: 
    15991590            case OPf_d: 
    16001591            case OPd_ld: 
    16011592                mf1 = (tybasic(e->E1->Ety) == TYfloat || tybasic(e->E1->Ety) == TYifloat) 
    16021593                        ? MFfloat : MFdouble; 
    16031594                if (op != -1 && stackused) 
    16041595                    note87(eleft,eoffset,0);    // don't trash this value 
    16051596                if (e->E1->Eoper == OPvar || e->E1->Eoper == OPind) 
    16061597                { 
    16071598#if 1 
    16081599                L4: 
    16091600                    c = getlvalue(&cs,e->E1,0); 
    16101601                    cs.Iop = ESC(mf1,0); 
    16111602                    if (ADDFWAIT()) 
    16121603                        cs.Iflags |= CFwait; 
    1613                     if (I32
     1604                    if (!I16
    16141605                        cs.Iflags &= ~CFopsize; 
    16151606                    if (op != -1) 
    16161607                    {   cs.Irm |= modregrm(0,op,0); 
    16171608                        c = cat(c,makesure87(eleft,eoffset,0,0)); 
    16181609                    } 
    16191610                    else 
    16201611                    {   cs.Iop |= 1; 
    16211612                        c = cat(c,push87()); 
    16221613                    } 
    16231614                    c = gen(c,&cs);                     /* FLD / Fop    */ 
    16241615#else 
    16251616                    c = loadea(e->E1,&cs,ESC(mf1,1),0,0,0,0); /* FLD e->E1 */ 
    16261617#endif 
    16271618                    /* Variable cannot be put into a register anymore   */ 
    16281619                    if (e->E1->Eoper == OPvar) 
    16291620                        notreg(e->E1); 
    16301621                    freenode(e->E1); 
    16311622                } 
    16321623                else 
    16331624                { 
    16341625                    retregs = mST0; 
    16351626                    c = codelem(e->E1,&retregs,FALSE); 
    16361627                    if (op != -1) 
    16371628                    {   c = cat(c,makesure87(eleft,eoffset,1,0)); 
    16381629                        c = genf2(c,0xDE,modregrm(3,opr,1)); // FopRP 
    16391630                        pop87(); 
    16401631                    } 
    16411632                } 
    16421633                break; 
    16431634 
    16441635            case OPs64_d: 
    16451636                if (e->E1->Eoper == OPvar || 
    16461637                    (e->E1->Eoper == OPind && e->E1->Ecount == 0)) 
    16471638                { 
    16481639                    c = getlvalue(&cs,e->E1,0); 
    16491640                    cs.Iop = 0xDF; 
    16501641                    if (ADDFWAIT()) 
    16511642                        cs.Iflags |= CFwait; 
    1652                     if (I32
     1643                    if (!I16
    16531644                        cs.Iflags &= ~CFopsize; 
    16541645                    c = cat(c,push87()); 
    16551646                    cs.Irm |= modregrm(0,5,0); 
    16561647                    c = gen(c,&cs);                     // FILD m64 
    16571648                    // Variable cannot be put into a register anymore 
    16581649                    if (e->E1->Eoper == OPvar) 
    16591650                        notreg(e->E1); 
    16601651                    freenode(e->E1); 
    16611652                } 
    16621653                else 
    16631654                { 
    16641655                    retregs = ALLREGS; 
    16651656                    c = codelem(e->E1,&retregs,FALSE); 
    16661657                    reg = findreglsw(retregs); 
    16671658                    c = genfltreg(c,0x89,reg,0);        // MOV floatreg,reglsw 
    16681659                    reg = findregmsw(retregs); 
    16691660                    c = genfltreg(c,0x89,reg,4);        // MOV floatreg+4,regmsw 
    16701661                    c = cat(c,push87()); 
    16711662                    c = genfltreg(c,0xDF,5,0);          // FILD long long ptr floatreg 
    16721663                } 
     
    19081899        if (I32) 
    19091900            cs.Iflags &= ~CFopsize; 
    19101901        else if (ADDFWAIT()) 
    19111902            cs.Iflags |= CFwait; 
    19121903        c2 = gen(c2, &cs); 
    19131904#if LNGDBLSIZE == 12 
    19141905        /* This deals with the fact that 10 byte reals really 
    19151906         * occupy 12 bytes by zeroing the extra 2 bytes. 
    19161907         */ 
    19171908        if (op1 == 0xDB) 
    19181909        { 
    19191910            cs.Iop = 0xC7;                      // MOV EA+10,0 
    19201911            NEWREG(cs.Irm, 0); 
    19211912            cs.IEV1.sp.Voffset += 10; 
    19221913            cs.IFL2 = FLconst; 
    19231914            cs.IEV2.Vint = 0; 
    19241915            cs.Iflags |= CFopsize; 
    19251916            c2 = gen(c2, &cs); 
    19261917        } 
    19271918#endif 
    1928 #if LNGDBLSIZE == 16 
     1919        if (tysize[TYldouble] == 16) 
     1920        { 
    19291921        /* This deals with the fact that 10 byte reals really 
    19301922         * occupy 16 bytes by zeroing the extra 6 bytes. 
    19311923         */ 
    19321924        if (op1 == 0xDB) 
    19331925        { 
    19341926            cs.Iop = 0xC7;                      // MOV EA+10,0 
    19351927            NEWREG(cs.Irm, 0); 
    19361928            cs.IEV1.sp.Voffset += 10; 
    19371929            cs.IFL2 = FLconst; 
    19381930            cs.IEV2.Vint = 0; 
    19391931            cs.Iflags |= CFopsize; 
    19401932            c2 = gen(c2, &cs); 
    19411933 
    19421934            cs.IEV1.sp.Voffset += 2; 
    19431935            cs.Iflags &= ~CFopsize; 
    19441936            c2 = gen(c2, &cs); 
    19451937        } 
    1946 #endif 
     1938        } 
    19471939#endif 
    19481940        c2 = genfwait(c2); 
    19491941        freenode(e->E1); 
    19501942        c1 = cat3(c1,c2,fixresult87(e,mST0 | mPSW,pretregs)); 
    19511943        return c1; 
    19521944} 
    19531945 
    19541946/******************************* 
    19551947 * Perform an assignment to a long double/double/float. 
    19561948 */ 
    19571949 
    19581950code *complex_eq87(elem *e,regm_t *pretregs) 
    19591951{ 
    19601952        regm_t retregs; 
    19611953        code *c1,*c2; 
    19621954        code cs; 
    19631955        unsigned op1; 
    19641956        unsigned op2; 
    19651957        unsigned sz; 
    19661958        tym_t ty1; 
     
    20232015        if (fxch) 
    20242016            c2 = genf2(c2,0xD9,0xC8 + 1);       // FXCH ST(1) 
    20252017        cs.IEVoffset1 -= sz; 
    20262018        gen(c2, &cs); 
    20272019        if (fxch) 
    20282020            genf2(c2,0xD9,0xC8 + 1);            // FXCH ST(1) 
    20292021#if LNGDBLSIZE == 12 
    20302022        if (op1 == 0xDB) 
    20312023        { 
    20322024            cs.Iop = 0xC7;                      // MOV EA+10,0 
    20332025            NEWREG(cs.Irm, 0); 
    20342026            cs.IEV1.sp.Voffset += 10; 
    20352027            cs.IFL2 = FLconst; 
    20362028            cs.IEV2.Vint = 0; 
    20372029            cs.Iflags |= CFopsize; 
    20382030            c2 = gen(c2, &cs); 
    20392031            cs.IEVoffset1 += 12; 
    20402032            c2 = gen(c2, &cs);                  // MOV EA+22,0 
    20412033        } 
    20422034#endif 
    2043 #if LNGDBLSIZE == 16 
     2035        if (tysize[TYldouble] == 16) 
     2036        { 
    20442037        if (op1 == 0xDB) 
    20452038        { 
    20462039            cs.Iop = 0xC7;                      // MOV EA+10,0 
    20472040            NEWREG(cs.Irm, 0); 
    20482041            cs.IEV1.sp.Voffset += 10; 
    20492042            cs.IFL2 = FLconst; 
    20502043            cs.IEV2.Vint = 0; 
    20512044            cs.Iflags |= CFopsize; 
    20522045            c2 = gen(c2, &cs); 
    20532046 
    20542047            cs.IEV1.sp.Voffset += 2; 
    20552048            cs.Iflags &= ~CFopsize; 
    20562049            c2 = gen(c2, &cs); 
    20572050 
    20582051            cs.IEVoffset1 += 14; 
    20592052            cs.Iflags |= CFopsize; 
    20602053            c2 = gen(c2, &cs); 
    20612054 
    20622055            cs.IEV1.sp.Voffset += 2; 
    20632056            cs.Iflags &= ~CFopsize; 
    20642057            c2 = gen(c2, &cs); 
    20652058        } 
    2066 #endif 
     2059        } 
    20672060        c2 = genfwait(c2); 
    20682061        freenode(e->E1); 
    20692062        return cat3(c1,c2,fixresult_complex87(e,mST01 | mPSW,pretregs)); 
    20702063} 
    20712064 
    20722065/******************************* 
    20732066 * Perform an assignment while converting to integral type, 
    20742067 * i.e. handle (e1 = (int) e2) 
    20752068 */ 
    20762069 
    20772070code *cnvteq87(elem *e,regm_t *pretregs) 
    20782071{ 
    20792072        regm_t retregs; 
    20802073        code *c1,*c2; 
    20812074        code cs; 
    20822075        unsigned op1; 
    20832076        unsigned op2; 
    20842077        tym_t ty1; 
    20852078 
    20862079        assert(e->Eoper == OPeq); 
     
    22812274                jp      FM1 
    22822275                fxch    ST(1) 
    22832276                fld     E1.im 
    22842277        FM2:    fprem 
    22852278                fstsw   word ptr sw 
    22862279                fwait 
    22872280                mov     AH, byte ptr sw+1 
    22882281                jp      FM2 
    22892282                fstp    ST(1) 
    22902283     */ 
    22912284 
    22922285    ty1 = tybasic(e->E1->Ety); 
    22932286    sz2 = tysize[ty1] / 2; 
    22942287 
    22952288    retregs = mST0; 
    22962289    cr = codelem(e->E2,&retregs,FALSE);         // FLD E2 
    22972290    note87(e->E2,0,0); 
    22982291    cl = getlvalue(&cs,e->E1,0); 
    22992292    cl = cat(cl,makesure87(e->E2,0,0,0)); 
    23002293    cs.Iflags |= ADDFWAIT() ? CFwait : 0; 
    2301     if (I32
     2294    if (!I16
    23022295        cs.Iflags &= ~CFopsize; 
    23032296 
    23042297    c = push87(); 
    23052298    switch (ty1) 
    23062299    { 
    23072300        case TYcdouble:  cs.Iop = ESC(MFdouble,1);      break; 
    23082301        case TYcfloat:   cs.Iop = ESC(MFfloat,1);       break; 
    23092302        case TYcldouble: cs.Iop = 0xDB; cs.Irm |= modregrm(0, 5, 0); break; 
    23102303        default: 
    23112304            assert(0); 
    23122305    } 
    23132306    c = gen(c,&cs);                             // FLD E1.re 
    23142307 
    23152308    code *c1; 
    23162309 
    23172310    c1 = gen2(NULL, 0xD9, 0xF8);                // FPREM 
    23182311    c1 = cg87_87topsw(c1); 
    23192312    c1 = genjmp(c1, JP, FLcode, (block *)c1);   // JP FM1 
    23202313    c1 = genf2(c1, 0xD9, 0xC8 + 1);             // FXCH ST(1) 
    23212314    c = cat(c,c1); 
     
    23932386    if (!tycomplex(e->E2->Ety) && 
    23942387        (e->Eoper == OPmulass || e->Eoper == OPdivass)) 
    23952388    { 
    23962389        retregs = mST0; 
    23972390        cr = codelem(e->E2, &retregs, FALSE); 
    23982391        note87(e->E2, 0, 0); 
    23992392        cl = getlvalue(&cs, e->E1, 0); 
    24002393        cl = cat(cl,makesure87(e->E2,0,0,0)); 
    24012394        cl = cat(cl,push87()); 
    24022395        cl = genf2(cl,0xD9,0xC0);               // FLD ST(0) 
    24032396        goto L1; 
    24042397    } 
    24052398    else 
    24062399    { 
    24072400        cr = loadComplex(e->E2); 
    24082401        cl = getlvalue(&cs,e->E1,0); 
    24092402        cl = cat(cl,makesure87(e->E2,sz2,0,0)); 
    24102403        cl = cat(cl,makesure87(e->E2,0,1,0)); 
    24112404    } 
    24122405    cs.Iflags |= ADDFWAIT() ? CFwait : 0; 
    2413     if (I32
     2406    if (!I16
    24142407        cs.Iflags &= ~CFopsize; 
    24152408 
    24162409    switch (e->Eoper) 
    24172410    { 
    24182411        case OPpostinc: 
    24192412        case OPaddass: 
    24202413        case OPpostdec: 
    24212414        case OPminass: 
    24222415        L1: 
    24232416            if (ty1 == TYcldouble) 
    24242417            { 
    24252418                c = push87(); 
    24262419                c = cat(c, push87()); 
    24272420                cs.Iop = 0xDB; 
    24282421                cs.Irm |= modregrm(0, 5, 0);    // FLD tbyte ptr ... 
    24292422                c = gen(c,&cs);                 // FLD e->E1.re 
    24302423                cs.IEVoffset1 += sz2; 
    24312424                gen(c,&cs);                     // FLD e->E1.im 
    24322425                genf2(c, 0xDE, op2 + 2);        // FADDP/FSUBRP ST(2),ST 
    24332426                genf2(c, 0xDE, op2 + 2);        // FADDP/FSUBRP ST(2),ST 
     
    25812574                    cs.IEVoffset1 -= sz2; 
    25822575                    gen(c, &cs);                // FST mreal.re 
    25832576                    retregs = mST01; 
    25842577                } 
    25852578                else 
    25862579                { 
    25872580                    cs.Irm |= modregrm(0, 3, 0); 
    25882581                    gen(c, &cs);                // FSTP mreal.im 
    25892582                    cs.IEVoffset1 -= sz2; 
    25902583                    gen(c, &cs);                // FSTP mreal.re 
    25912584                    pop87(); 
    25922585                    pop87(); 
    25932586                    retregs = 0; 
    25942587                } 
    25952588                goto L3; 
    25962589            } 
    25972590 
    25982591        case OPdivass: 
    25992592            c = push87(); 
    26002593            c = cat(c, push87()); 
    2601             idxregs = idxregm(cs.Irm,cs.Isib);  // mask of index regs used 
     2594            idxregs = idxregm(&cs);             // mask of index regs used 
    26022595            if (ty1 == TYcldouble) 
    26032596            { 
    26042597                cs.Iop = 0xDB; 
    26052598                cs.Irm |= modregrm(0, 5, 0);    // FLD tbyte ptr ... 
    26062599                c = gen(c,&cs);                 // FLD e->E1.re 
    26072600                genf2(c,0xD9,0xC8 + 2);         // FXCH ST(2) 
    26082601                cs.IEVoffset1 += sz2; 
    26092602                gen(c,&cs);                     // FLD e->E1.im 
    26102603                genf2(c,0xD9,0xC8 + 2);         // FXCH ST(2) 
    26112604                retregs = mST01; 
    26122605                c = cat(c,callclib(e, CLIBcdiv, &retregs, idxregs)); 
    26132606                goto L2; 
    26142607            } 
    26152608            else 
    26162609            { 
    26172610                cs.Iop = (ty1 == TYcfloat) ? 0xD9 : 0xDD; 
    26182611                cs.Irm |= modregrm(0, 0, 0);    // FLD tbyte ptr ... 
    26192612                c = gen(c,&cs);                 // FLD e->E1.re 
    26202613                genf2(c,0xD9,0xC8 + 2);         // FXCH ST(2) 
    26212614                cs.IEVoffset1 += sz2; 
     
    26522645 
    26532646/************************** 
    26542647 * OPnegass 
    26552648 */ 
    26562649 
    26572650code *cdnegass87(elem *e,regm_t *pretregs) 
    26582651{   regm_t retregs; 
    26592652    tym_t tyml; 
    26602653    unsigned op; 
    26612654    targ_long val; 
    26622655    code *cl,*cr,*c,cs; 
    26632656    elem *e1; 
    26642657    int sz; 
    26652658 
    26662659    //printf("cdnegass87(e = %p, *pretregs = x%x)\n", e, *pretregs); 
    26672660    e1 = e->E1; 
    26682661    tyml = tybasic(e1->Ety);            // type of lvalue 
    26692662    sz = tysize[tyml]; 
    26702663 
    26712664    cl = getlvalue(&cs,e1,0); 
    2672     cr = modEA(cs.Irm); 
     2665    cr = modEA(&cs); 
    26732666    cs.Irm |= modregrm(0,6,0); 
    26742667    cs.Iop = 0x80; 
     2668    cs.Irex = 0; 
    26752669#if LNGDBLSIZE > 10 
    26762670    if (tyml == TYldouble || tyml == TYildouble) 
    26772671        cs.IEVoffset1 += 10 - 1; 
    26782672    else if (tyml == TYcldouble) 
    26792673        cs.IEVoffset1 += LNGDBLSIZE + 10 - 1; 
    26802674    else 
    26812675#endif 
    26822676        cs.IEVoffset1 += sz - 1; 
    26832677    cs.IFL2 = FLconst; 
    26842678    cs.IEV2.Vuns = 0x80; 
    26852679    c = gen(NULL,&cs);                  // XOR 7[EA],0x80 
    26862680    if (tycomplex(tyml)) 
    26872681    { 
    26882682        cs.IEVoffset1 -= sz / 2; 
    26892683        gen(c,&cs);                     // XOR 7[EA],0x80 
    26902684    } 
    26912685    c = cat3(cl,cr,c); 
    26922686 
    26932687    if (*pretregs) 
    26942688    { 
     
    27182712} 
    27192713 
    27202714/************************ 
    27212715 * Take care of OPpostinc and OPpostdec. 
    27222716 */ 
    27232717 
    27242718code *post87(elem *e,regm_t *pretregs) 
    27252719{ 
    27262720        regm_t retregs; 
    27272721        code *cl,*cr,*c; 
    27282722        code cs; 
    27292723        unsigned op; 
    27302724        unsigned op1; 
    27312725        unsigned reg; 
    27322726        tym_t ty1; 
    27332727 
    27342728        //printf("post87()\n"); 
    27352729        assert(*pretregs); 
    27362730        cl = getlvalue(&cs,e->E1,0); 
    27372731        cs.Iflags |= ADDFWAIT() ? CFwait : 0; 
    2738         if (I32
     2732        if (!I16
    27392733            cs.Iflags &= ~CFopsize; 
    27402734        ty1 = tybasic(e->E1->Ety); 
    27412735        switch (ty1) 
    27422736        {   case TYdouble_alias: 
    27432737            case TYidouble: 
    27442738            case TYdouble: 
    27452739            case TYcdouble:     op1 = ESC(MFdouble,1);  reg = 0;        break; 
    27462740            case TYifloat: 
    27472741            case TYfloat: 
    27482742            case TYcfloat:      op1 = ESC(MFfloat,1);   reg = 0;        break; 
    27492743            case TYildouble: 
    27502744            case TYldouble: 
    27512745            case TYcldouble:    op1 = 0xDB;             reg = 5;        break; 
    27522746            default: 
    27532747                assert(0); 
    27542748        } 
    27552749        NEWREG(cs.Irm, reg); 
    27562750        if (reg == 5) 
    27572751            reg = 7; 
    27582752        else 
     
    28052799 *      OPd_s32 
    28062800 *      OPd_u16 
    28072801 *      OPd_s64 
    28082802 */ 
    28092803 
    28102804code *cnvt87(elem *e,regm_t *pretregs) 
    28112805{ 
    28122806        regm_t retregs; 
    28132807        code *c1,*c2; 
    28142808        unsigned mf,rf,reg; 
    28152809        tym_t tym; 
    28162810        int clib; 
    28172811        int sz; 
    28182812        int szoff; 
    28192813 
    28202814        //printf("cnvt87(e = %p, *pretregs = x%x)\n", e, *pretregs); 
    28212815        assert(*pretregs); 
    28222816        tym = e->Ety; 
    28232817        sz = tysize(tym); 
    28242818        szoff = sz; 
     2819        unsigned grex = I64 ? REX_W << 16 : 0; 
    28252820 
    28262821        switch (e->Eoper) 
    28272822        {   case OPd_s16: 
    28282823                clib = CLIBdblint87; 
    28292824                mf = ESC(MFword,1); 
    28302825                rf = 3; 
    28312826                break; 
    28322827 
    28332828            case OPd_u16: 
    28342829                szoff = 4; 
    28352830            case OPd_s32: 
    28362831                clib = CLIBdbllng87; 
    28372832                mf = ESC(MFlong,1); 
    28382833                rf = 3; 
    28392834                break; 
    28402835 
    28412836            case OPd_s64: 
    28422837                clib = CLIBdblllng; 
    28432838                mf = 0xDF; 
    28442839                rf = 7; 
    28452840                break; 
    28462841 
    28472842            default: 
    28482843                assert(0); 
    28492844        } 
    28502845 
    2851         if (!I32)                       // C may change the default control word 
     2846        if (I16)                       // C may change the default control word 
    28522847        { 
    28532848            if (clib == CLIBdblllng) 
    28542849            {   retregs = I32 ? DOUBLEREGS_32 : DOUBLEREGS_16; 
    28552850                c1 = codelem(e->E1,&retregs,FALSE); 
    28562851                c2 = callclib(e,clib,pretregs,0); 
    28572852            } 
    28582853            else 
    28592854            {   retregs = mST0; //I32 ? DOUBLEREGS_32 : DOUBLEREGS_16; 
    28602855                c1 = codelem(e->E1,&retregs,FALSE); 
    28612856                c2 = callclib(e,clib,pretregs,0); 
    28622857                pop87(); 
    28632858            } 
    28642859        } 
    28652860        else if (1) 
    28662861        {   //  Generate: 
    28672862            //  sub     ESP,12 
    28682863            //  fstcw   8[ESP] 
    28692864            //  fldcw   roundto0 
    28702865            //  fistp   long64 ptr [ESP] 
    28712866            //  fldcw   8[ESP] 
    28722867            //  pop     lsw 
    28732868            //  pop     msw 
    28742869            //  add     ESP,4 
    28752870 
    28762871            unsigned szpush = szoff + 2; 
    28772872            if (config.flags3 & CFG3pic) 
    28782873                szpush += 2; 
    28792874            szpush = (szpush + REGSIZE - 1) & ~(REGSIZE - 1); 
    28802875 
    28812876            retregs = mST0; 
    28822877            c1 = codelem(e->E1,&retregs,FALSE); 
    28832878 
    28842879            if (szpush == REGSIZE) 
    28852880                c1 = gen1(c1,0x50 + AX);                // PUSH EAX 
    28862881            else 
    2887                 c1 = genc2(c1,0x81,modregrm(3,5,SP), szpush);   // SUB ESP,12 
     2882                c1 = genc2(c1,0x81,grex | modregrm(3,5,SP), szpush);   // SUB ESP,12 
    28882883            c1 = genfwait(c1); 
    2889             genc1(c1,0xD9,modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP] 
     2884            genc1(c1,0xD9,grex | modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP] 
    28902885 
    28912886            c1 = genfwait(c1); 
    28922887 
    28932888            if (config.flags3 & CFG3pic) 
    28942889            { 
    2895                 genc(c1,0xC7,modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto0 
     2890                genc(c1,0xC7,grex | modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto0 
    28962891                code_orflag(c1, CFopsize); 
    2897                 genc1(c1,0xD9,modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP] 
     2892                genc1(c1,0xD9,grex | modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP] 
    28982893            } 
    28992894            else 
    29002895                c1 = genrnd(c1, CW_roundto0);   // FLDCW roundto0 
    29012896 
    29022897            pop87(); 
    29032898 
    29042899            c1 = genfwait(c1); 
    2905             gen2sib(c1,mf,modregrm(0,rf,4),modregrm(0,4,SP));                   // FISTP [ESP] 
     2900            gen2sib(c1,mf,grex | modregrm(0,rf,4),modregrm(0,4,SP));                   // FISTP [ESP] 
    29062901 
    29072902            retregs = *pretregs & (ALLREGS | mBP); 
    29082903            if (!retregs) 
    29092904                    retregs = ALLREGS; 
    29102905            c2 = allocreg(&retregs,&reg,tym); 
    29112906 
    29122907            c2 = genfwait(c2);                                                          // FWAIT 
    2913             c2 = genc1(c2,0xD9,modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff);   // FLDCW szoff[ESP] 
     2908            c2 = genc1(c2,0xD9,grex | modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff);   // FLDCW szoff[ESP] 
    29142909 
    29152910            if (szoff > REGSIZE) 
    29162911            {   szpush -= REGSIZE; 
    2917                 c2 = gen1(c2,0x58 + findreglsw(retregs));       // POP lsw 
     2912                c2 = genpop(c2,findreglsw(retregs));       // POP lsw 
    29182913            } 
    29192914            szpush -= REGSIZE; 
    2920             c2 = gen1(c2,0x58 + reg);                           // POP reg 
     2915            c2 = genpop(c2,reg);                           // POP reg 
    29212916 
    29222917            if (szpush) 
    2923                 genc2(c2,0x81,modregrm(3,0,SP), szpush);        // ADD ESP,4 
     2918                genc2(c2,0x81,grex | modregrm(3,0,SP), szpush);        // ADD ESP,4 
    29242919            c2 = cat(c2,fixresult(e,retregs,pretregs)); 
    29252920        } 
    29262921        else 
    29272922        { 
    29282923            // This is incorrect. For -inf and nan, the 8087 returns the largest 
    29292924            // negative int (0x80000....). For -inf, 0x7FFFF... should be returned, 
    29302925            // and for nan, 0 should be returned. 
    29312926            retregs = mST0; 
    29322927            c1 = codelem(e->E1,&retregs,FALSE); 
    29332928 
    29342929            c1 = genfwait(c1); 
    29352930            c1 = genrnd(c1, CW_roundto0);       // FLDCW roundto0 
    29362931 
    29372932            pop87(); 
    29382933            c1 = genfltreg(c1,mf,rf,0);         // FISTP floatreg 
    29392934            retregs = *pretregs & (ALLREGS | mBP); 
    29402935            if (!retregs) 
    29412936                    retregs = ALLREGS; 
    29422937            c2 = allocreg(&retregs,&reg,tym); 
    29432938 
  • trunk/src/backend/cg.c

    r558 r577  
    3636                                // of the public name index of a COMDAT) 
    3737 
    3838/* Stack offsets        */ 
    3939targ_size_t localsize,          /* amt subtracted from SP for local vars */ 
    4040        Toff,                   /* base for temporaries                 */ 
    4141        Poff,Aoff;              // comsubexps, params, regs, autos 
    4242 
    4343/* The following are initialized for the 8088. cod3_set386() will 
    4444 * change them if generating code for the 386, cod3_set64() for 64 bit code. 
    4545 */ 
    4646int     BPRM = 6;               /* R/M value for [BP] or [EBP]          */ 
    4747regm_t  fregsaved = mBP | mSI | mDI;    // mask of registers saved across 
    4848                                        // function calls 
    4949                                        // (add in mBX for I32) 
    5050regm_t  FLOATREGS = FLOATREGS_16; 
    5151regm_t  FLOATREGS2 = FLOATREGS2_16; 
    5252regm_t  DOUBLEREGS = DOUBLEREGS_16; 
    5353 
    5454symbol *localgot;               // reference to GOT for this function 
    5555symbol *tls_get_addr_sym;       // function __tls_get_addr 
     56 
     57#if TARGET_OSX 
     58int STACKALIGN = 16; 
     59#else 
     60int STACKALIGN = 0; 
     61#endif 
  • trunk/src/backend/cgcod.c

    r558 r577  
    1919 
    2020#if __sun&&__SVR4 
    2121#include        <alloca.h> 
    2222#endif 
    2323 
    2424#include        "cc.h" 
    2525#include        "el.h" 
    2626#include        "oper.h" 
    2727#include        "code.h" 
    2828#include        "global.h" 
    2929#include        "type.h" 
    3030#include        "exh.h" 
    3131 
    3232static char __file__[] = __FILE__;      /* for tassert.h                */ 
    3333#include        "tassert.h" 
    3434 
    3535STATIC void resetEcomsub(elem *e); 
    3636STATIC code * loadcse(elem *,unsigned,regm_t); 
    3737STATIC void blcodgen(block *); 
    3838STATIC void cgcod_eh(); 
    39 STATIC int numbitsset(regm_t); 
    4039STATIC code * cse_save(regm_t ms); 
    4140STATIC int cse_simple(elem *e,int i); 
    4241STATIC code * comsub(elem *,regm_t *); 
    4342 
    4443bool floatreg;                  // !=0 if floating register is required 
    4544 
    4645targ_size_t Aoffset;            // offset of automatics and registers 
    4746targ_size_t Toffset;            // offset of temporaries 
    4847targ_size_t EEoffset;           // offset of SCstack variables from ESP 
    4948int Aalign;                     // alignment for Aoffset 
    5049 
    5150CGstate cgstate;                // state of code generator 
    5251 
    5352/************************************ 
    5453 * # of bytes that SP is beyond BP. 
    5554 */ 
    5655 
    5756unsigned stackpush; 
    5857 
    5958int stackchanged;               /* set to !=0 if any use of the stack 
     
    15611560        case TYcdouble: 
    15621561            if (I64) 
    15631562                return mXMM0 | mXMM1; 
    15641563        case TYcldouble: 
    15651564            return mST01; 
    15661565 
    15671566        default: 
    15681567#if DEBUG 
    15691568            WRTYxx(tym); 
    15701569#endif 
    15711570            assert(0); 
    15721571            return 0; 
    15731572    } 
    15741573} 
    15751574 
    15761575 
    15771576/****************************** 
    15781577 * Count the number of bits set in a register mask. 
    15791578 */ 
    15801579 
    1581 STATIC int numbitsset(regm_t regm) 
     1580int numbitsset(regm_t regm) 
    15821581{   int n; 
    15831582 
    15841583    n = 0; 
    15851584    if (regm) 
    15861585        do 
    15871586            n++; 
    15881587        while ((regm &= regm - 1) != 0); 
    15891588    return n; 
    15901589} 
    15911590 
    15921591/****************************** 
    15931592 * Given a register mask, find and return the number 
    15941593 * of the first register that fits. 
    15951594 */ 
    15961595 
    15971596#undef findreg 
    15981597 
    15991598unsigned findreg(regm_t regm 
    16001599#ifdef DEBUG 
    16011600        ,int line,const char *file 
  • trunk/src/backend/cgen.c

    r569 r577  
    147147    unsigned reg; 
    148148 
    149149#ifdef DEBUG                            /* this is a high usage routine */ 
    150150    assert(cs); 
    151151#endif 
    152152    assert(I64 || cs->Irex == 0); 
    153153    ce = code_calloc(); 
    154154    *ce = *cs; 
    155155    if (config.flags4 & CFG4optimized && 
    156156        ce->IFL2 == FLconst && 
    157157        (ce->Iop == 0x81 || ce->Iop == 0x80) && 
    158158        reghasvalue((ce->Iop == 0x80) ? BYTEREGS : ALLREGS,ce->IEV2.Vlong,&reg) && 
    159159        !(ce->Iflags & CFopsize && I16) 
    160160       ) 
    161161    {   // See if we can replace immediate instruction with register instruction 
    162162        static unsigned char regop[8] = 
    163163                { 0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38 }; 
    164164 
    165165//printf("replacing 0x%02x, val = x%lx\n",ce->Iop,ce->IEV2.Vlong); 
    166166        ce->Iop = regop[(ce->Irm & modregrm(0,7,0)) >> 3] | (ce->Iop & 1); 
    167         ce->Irm = (ce->Irm & modregrm(3,0,7)) | modregrm(0,reg,0); 
     167        code_newreg(ce, reg); 
    168168    } 
    169169    code_next(ce) = CNIL; 
    170170    if (c) 
    171171    {   cstart = c; 
    172172        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    173173        code_next(c) = ce;                      /* link into list       */ 
    174174        return cstart; 
    175175    } 
    176176    return ce; 
    177177} 
    178178 
    179179code *gen1(code *c,unsigned op) 
    180180{ code *ce,*cstart; 
    181181 
    182182  ce = code_calloc(); 
    183183  ce->Iop = op; 
    184184  if (c) 
    185185  {     cstart = c; 
    186186        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    187187        code_next(c) = ce;                      /* link into list       */ 
    188188        return cstart; 
    189189  } 
    190190  return ce; 
    191191} 
    192192 
    193193code *gen2(code *c,unsigned op,unsigned rm) 
    194194{ code *ce,*cstart; 
    195195 
    196196  cstart = ce = code_calloc(); 
    197197  /*cxcalloc++;*/ 
    198198  if (op > 0xFF) 
    199199  {     ce->Iop = op >> 8; 
    200200        ce->Iop2 = op & 0xFF; 
    201201  } 
    202202  else 
    203203        ce->Iop = op; 
    204   ce->Irm = rm; 
    205   ce->Irex = rm >> 16; 
     204  ce->Iea = rm; 
    206205  if (c) 
    207206  {     cstart = c; 
    208207        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    209208        code_next(c) = ce;                      /* link into list       */ 
    210209  } 
    211210  return cstart; 
    212211} 
    213212 
    214213code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 
    215214{ code *ce,*cstart; 
    216215 
    217216  cstart = ce = code_calloc(); 
    218217  /*cxcalloc++;*/ 
    219218  ce->Iop = op; 
    220219  ce->Irm = rm; 
    221220  ce->Isib = sib; 
    222   ce->Irex = rm >> 16; 
     221  ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 
     222  if (sib & (REX_R << 16)) 
     223        ce->Irex |= REX_X; 
    223224  if (c) 
    224225  {     cstart = c; 
    225226        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    226227        code_next(c) = ce;                      /* link into list       */ 
    227228  } 
    228229  return cstart; 
    229230} 
    230231 
    231232code *genregs(code *c,unsigned op,unsigned dstreg,unsigned srcreg) 
    232233{ return gen2(c,op,modregxrmx(3,dstreg,srcreg)); } 
    233234 
    234235code *gentstreg(code *c,unsigned t) 
    235236{ 
    236237    c = gen2(c,0x85,modregxrmx(3,t,t));   // TEST t,t 
    237238    code_orflag(c,CFpsw); 
     239    return c; 
     240} 
     241 
     242code *genpush(code *c, unsigned reg) 
     243{ 
     244    c = gen1(c, 0x50 + (reg & 7)); 
     245    if (reg & 8) 
     246        code_orrex(c, REX_B); 
     247    return c; 
     248} 
     249 
     250code *genpop(code *c, unsigned reg) 
     251{ 
     252    c = gen1(c, 0x58 + (reg & 7)); 
     253    if (reg & 8) 
     254        code_orrex(c, REX_B); 
    238255    return c; 
    239256} 
    240257 
    241258/******************************** 
    242259 * Generate an ASM sequence. 
    243260 */ 
    244261 
    245262code *genasm(code *c,char *s,unsigned slen) 
    246263{   code *ce; 
    247264 
    248265    ce = code_calloc(); 
    249266    ce->Iop = ASM; 
    250267    ce->IFL1 = FLasm; 
    251268    ce->IEV1.as.len = slen; 
    252269    ce->IEV1.as.bytes = (char *) mem_malloc(slen); 
    253270    memcpy(ce->IEV1.as.bytes,s,slen); 
    254271    return cat(c,ce); 
    255272} 
    256273 
    257274/************************** 
     
    310327            gen(cj,&cs); 
    311328            break; 
    312329        case JNP << 8: 
    313330            /* Do a JP around the jump instruction      */ 
    314331            cnop = gennop(CNIL); 
    315332            c = genjmp(c,JP,FLcode,(block *) cnop); 
    316333            cat(cj,cnop); 
    317334            break; 
    318335        case 1 << 8:                    /* toggled no jump              */ 
    319336        case 0 << 8: 
    320337            break; 
    321338        default: 
    322339#ifdef DEBUG 
    323340            printf("jop = x%x\n",op); 
    324341#endif 
    325342            assert(0); 
    326343    } 
    327344    return cat(c,cj); 
    328345} 
    329346 
    330 code *gencs(code *c,unsigned op,unsigned rm,unsigned FL2,symbol *s) 
     347code *gencs(code *c,unsigned op,unsigned ea,unsigned FL2,symbol *s) 
    331348{   code cs; 
    332349 
    333350    cs.Iop = op; 
    334     cs.Irm = rm
     351    cs.Iea = ea
    335352    cs.Iflags = 0; 
    336     cs.Irex = rm >> 16; 
    337353    cs.IFL2 = FL2; 
    338354    cs.IEVsym2 = s; 
    339355    cs.IEVoffset2 = 0; 
    340356 
    341357    return gen(c,&cs); 
    342358} 
    343359 
    344 code *genc2(code *c,unsigned op,unsigned rm,targ_size_t EV2) 
     360code *genc2(code *c,unsigned op,unsigned ea,targ_size_t EV2) 
    345361{   code cs; 
    346362 
    347363    if (op > 0xFF) 
    348364    {   cs.Iop = op >> 8; 
    349365        cs.Iop2 = op & 0xFF; 
    350366    } 
    351367    else 
    352368        cs.Iop = op; 
    353     cs.Irm = rm
     369    cs.Iea = ea
    354370    cs.Iflags = CFoff; 
    355     cs.Irex = rm >> 16; 
    356371    cs.IFL2 = FLconst; 
    357372    cs.IEV2.Vsize_t = EV2; 
    358373    return gen(c,&cs); 
    359374} 
    360375 
    361376/***************** 
    362377 * Generate code. 
    363378 */ 
    364379 
    365 code *genc1(code *c,unsigned op,unsigned rm,unsigned FL1,targ_size_t EV1) 
     380code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 
    366381{   code cs; 
    367382 
    368383    assert(FL1 < FLMAX); 
    369384    assert(op < 256); 
    370385    cs.Iop = op; 
    371     cs.Irm = rm; 
    372     cs.Isib = rm >> 8; 
    373     cs.Irex = rm >> 16; 
     386    cs.Iea = ea; 
    374387    cs.Iflags = CFoff; 
    375388    cs.IFL1 = FL1; 
    376389    cs.IEV1.Vsize_t = EV1; 
    377390    return gen(c,&cs); 
    378391} 
    379392 
    380393/***************** 
    381394 * Generate code. 
    382395 */ 
    383396 
    384 code *genc(code *c,unsigned op,unsigned rm,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
     397code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
    385398{   code cs; 
    386399 
    387400    assert(FL1 < FLMAX); 
    388401    assert(op < 256); 
    389402    cs.Iop = op; 
    390     cs.Irm = rm; 
    391     cs.Isib = rm >> 8; 
    392     cs.Irex = rm >> 16; 
     403    cs.Iea = ea; 
    393404    cs.Iflags = CFoff; 
    394405    cs.IFL1 = FL1; 
    395406    cs.IEV1.Vsize_t = EV1; 
    396407    assert(FL2 < FLMAX); 
    397408    cs.IFL2 = FL2; 
    398409    cs.IEV2.Vsize_t = EV2; 
    399410    return gen(c,&cs); 
    400411} 
    401412 
    402413/*************************************** 
    403414 * Generate immediate multiply instruction for r1=r2*imm. 
    404415 * Optimize it into LEA's if we can. 
    405416 */ 
    406417 
    407418code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm) 
    408419{   code cs; 
    409420 
    410421    // These optimizations should probably be put into pinholeopt() 
    411422    switch (imm) 
    412423    {   case 1: 
  • trunk/src/backend/cod1.c

    r552 r577  
    2626#include        "tassert.h" 
    2727 
    2828targ_size_t paramsize(elem *e,unsigned stackalign); 
    2929STATIC code * funccall (elem *,unsigned,unsigned,regm_t *,regm_t); 
    3030 
    3131/* array to convert from index register to r/m field    */ 
    3232                                       /* AX CX DX BX SP BP SI DI       */ 
    3333static const signed char regtorm32[8] = {  0, 1, 2, 3,-1, 5, 6, 7 }; 
    3434             signed char regtorm  [8] = { -1,-1,-1, 7,-1, 6, 4, 5 }; 
    3535 
    3636/************************** 
    3737 * Determine if e is a 32 bit scaled index addressing mode. 
    3838 * Returns: 
    3939 *      0       not a scaled index addressing mode 
    4040 *      !=0     the value for ss in the SIB byte 
    4141 */ 
    4242 
    4343int isscaledindex(elem *e) 
    4444{   targ_uns ss; 
    4545 
    46     assert(I32); 
     46    assert(!I16); 
    4747    while (e->Eoper == OPcomma) 
    4848        e = e->E2; 
    4949    if (!(e->Eoper == OPshl && !e->Ecount && 
    5050          e->E2->Eoper == OPconst && 
    5151          (ss = e->E2->EV.Vuns) <= 3 
    5252         ) 
    5353       ) 
    5454        ss = 0; 
    5555    return ss; 
    5656} 
    5757 
    5858/********************************************* 
    5959 * Generate code for which isscaledindex(e) returned a non-zero result. 
    6060 */ 
    6161 
    6262code *cdisscaledindex(elem *e,regm_t *pidxregs,regm_t keepmsk) 
    6363{   code *c; 
    6464    regm_t r; 
    6565 
    6666    // Load index register with result of e->E1 
     
    132132    { 
    133133        if (ssindex_array[i].product == product) 
    134134            return i; 
    135135    } 
    136136    return 0; 
    137137} 
    138138 
    139139/*************************************** 
    140140 * Build an EA of the form disp[base][index*scale]. 
    141141 * Input: 
    142142 *      c       struct to fill in 
    143143 *      base    base register (-1 if none) 
    144144 *      index   index register (-1 if none) 
    145145 *      scale   scale factor - 1,2,4,8 
    146146 *      disp    displacement 
    147147 */ 
    148148 
    149149void buildEA(code *c,int base,int index,int scale,targ_size_t disp) 
    150150{   unsigned char rm; 
    151151    unsigned char sib; 
     152    unsigned char rex = 0; 
    152153 
    153154    sib = 0; 
    154     if (I32
     155    if (!I16
    155156    {   unsigned ss; 
    156157 
    157158        assert(index != SP); 
    158159 
    159160        switch (scale) 
    160161        {   case 1:     ss = 0; break; 
    161162            case 2:     ss = 1; break; 
    162163            case 4:     ss = 2; break; 
    163164            case 8:     ss = 3; break; 
    164165            default:    assert(0); 
    165166        } 
    166167 
    167168        if (base == -1) 
    168169        { 
    169170            if (index == -1) 
    170171                rm = modregrm(0,0,5); 
    171172            else 
    172173            { 
    173174                rm  = modregrm(0,0,4); 
    174                 sib = modregrm(ss,index,5); 
     175                sib = modregrm(ss,index & 7,5); 
     176                if (index & 8) 
     177                    rex |= REX_X; 
    175178            } 
    176179        } 
    177180        else if (index == -1) 
    178181        { 
    179182            if (base == SP) 
    180183            { 
    181184                rm  = modregrm(2,0,4); 
    182185                sib = modregrm(0,4,SP); 
    183186            } 
    184187            else 
    185                 rm = modregrm(2,0,base); 
     188            {   rm = modregrm(2,0,base & 7); 
     189                if (base & 8) 
     190                    rex |= REX_B; 
     191            } 
    186192        } 
    187193        else 
    188194        { 
    189195            rm  = modregrm(2,0,4); 
    190             sib = modregrm(ss,index,base); 
     196            sib = modregrm(ss,index & 7,base & 7); 
     197            if (index & 8) 
     198                rex |= REX_X; 
     199            if (base & 8) 
     200                rex |= REX_B; 
    191201        } 
    192202    } 
    193203    else 
    194204    { 
    195205        // -1 AX CX DX BX SP BP SI DI 
    196206        static unsigned char EA16rm[9][9] = 
    197207        { 
    198208            {   0x06,0x09,0x09,0x09,0x87,0x09,0x86,0x84,0x85,   },      // -1 
    199209            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // AX 
    200210            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // CX 
    201211            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // DX 
    202212            {   0x87,0x09,0x09,0x09,0x09,0x09,0x09,0x80,0x81,   },      // BX 
    203213            {   0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,   },      // SP 
    204214            {   0x86,0x09,0x09,0x09,0x09,0x09,0x09,0x82,0x83,   },      // BP 
    205215            {   0x84,0x09,0x09,0x09,0x80,0x09,0x82,0x09,0x09,   },      // SI 
    206216            {   0x85,0x09,0x09,0x09,0x81,0x09,0x83,0x09,0x09,   }       // DI 
    207217        }; 
    208218 
    209219        assert(scale == 1); 
    210220        rm = EA16rm[base + 1][index + 1]; 
    211221        assert(rm != 9); 
    212222    } 
    213223    c->Irm = rm; 
    214224    c->Isib = sib; 
     225    c->Irex = rex; 
    215226    c->IFL1 = FLconst; 
    216227    c->IEV1.Vuns = disp; 
    217228} 
    218229 
    219230/************************** 
    220231 * For elems in regcon that don't match regconsave, 
    221232 * clear the corresponding bit in regcon.cse.mval. 
    222233 * Do same for regcon.immed. 
    223234 */ 
    224235 
    225236void andregcon(con_t *pregconsave) 
    226 {   int i; 
    227     regm_t m; 
    228  
    229     m = ~1; 
    230     for (i = 0; i < REGMAX; i++) 
     237
     238    regm_t m = ~1; 
     239    for (int i = 0; i < REGMAX; i++) 
    231240    {   if (pregconsave->cse.value[i] != regcon.cse.value[i]) 
    232241            regcon.cse.mval &= m; 
    233242        if (pregconsave->immed.value[i] != regcon.immed.value[i]) 
    234243            regcon.immed.mval &= m; 
    235244        m <<= 1; 
    236245        m |= 1; 
    237246    } 
    238247    //printf("regcon.cse.mval = x%x, regconsave->mval = x%x ",regcon.cse.mval,pregconsave->cse.mval); 
    239248    regcon.used |= pregconsave->used; 
    240249    regcon.cse.mval &= pregconsave->cse.mval; 
    241250    regcon.immed.mval &= pregconsave->immed.mval; 
    242251    regcon.params &= pregconsave->params; 
    243252    //printf("regcon.cse.mval&regcon.cse.mops = x%x, regcon.cse.mops = x%x\n",regcon.cse.mval & regcon.cse.mops,regcon.cse.mops); 
    244253    regcon.cse.mops &= regcon.cse.mval; 
    245254} 
    246255 
    247256/********************************* 
    248257 * Scan down comma-expressions. 
    249258 * Output: 
    250259 *      *pe = first elem down right side that is not an OPcomma 
     
    295304    if (e) 
    296305    { 
    297306        unsigned stackpushsave; 
    298307        int stackcleansave; 
    299308 
    300309        stackpushsave = stackpush; 
    301310        stackcleansave = cgstate.stackclean; 
    302311        cgstate.stackclean = 0;                         // defer cleaning of stack 
    303312        c = cat(c,codelem(e,pretregs,constflag)); 
    304313        assert(cgstate.stackclean == 0); 
    305314        cgstate.stackclean = stackcleansave; 
    306315        c = genstackclean(c,stackpush - stackpushsave,*pretregs);       // do defered cleaning 
    307316    } 
    308317    return c; 
    309318} 
    310319 
    311320/******************************************** 
    312321 * Gen a save/restore sequence for mask of registers. 
    313322 */ 
    314323 
    315 void gensaverestore(regm_t regm,code **csave,code **crestore) 
    316 {   code *cs1; 
    317     code *cs2; 
    318     int i; 
    319  
    320     cs1 = NULL; 
    321     cs2 = NULL; 
     324void gensaverestore2(regm_t regm,code **csave,code **crestore) 
     325
     326    code *cs1 = *csave; 
     327    code *cs2 = *crestore; 
     328 
    322329    regm &= mBP | mES | ALLREGS; 
    323     for (i = 0; regm; i++) 
     330    for (int i = 0; regm; i++) 
    324331    { 
    325332        if (regm & 1) 
    326333        { 
    327             assert(i != ES);                    // fix later 
    328             cs1 = gen1(cs1,0x50 + i); 
    329             cs2 = cat(gen1(NULL,0x58 + i),cs2); 
     334            if (i == ES) 
     335            { 
     336                cs1 = gen1(cs1, 0x06);                  // PUSH ES 
     337                cs2 = cat(gen1(CNIL, 0x07),cs2);        // POP  ES 
     338            } 
     339            else 
     340            { 
     341                cs1 = gen1(cs1,0x50 + (i & 7));         // PUSH i 
     342                code *c = gen1(NULL, 0x58 + (i & 7));   // POP  i 
     343                if (i & 8) 
     344                {   code_orrex(cs1, REX_B); 
     345                    code_orrex(c, REX_B); 
     346                } 
     347                cs2 = cat(c,cs2); 
     348            } 
    330349        } 
    331350        regm >>= 1; 
    332351    } 
    333352    *csave = cs1; 
    334353    *crestore = cs2; 
     354} 
     355 
     356void gensaverestore(regm_t regm,code **csave,code **crestore) 
     357{ 
     358    *csave = NULL; 
     359    *crestore = NULL; 
     360    gensaverestore2(regm, csave, crestore); 
    335361} 
    336362 
    337363/**************************************** 
    338364 * Clean parameters off stack. 
    339365 * Input: 
    340366 *      numpara         amount to adjust stack pointer 
    341367 *      keepmsk         mask of registers to not destroy 
    342368 */ 
    343369 
    344370code *genstackclean(code *c,unsigned numpara,regm_t keepmsk) 
    345371{ 
    346372    //dbg_printf("genstackclean(numpara = %d, stackclean = %d)\n",numpara,cgstate.stackclean); 
    347373    if (numpara && (cgstate.stackclean || STACKALIGN == 16)) 
    348374    { 
    349375#if 0       // won't work if operand of scodelem 
    350376        if (numpara == stackpush &&             // if this is all those pushed 
    351377            needframe &&                        // and there will be a BP 
    352378            !config.windows && 
    353379            !(regcon.mvar & fregsaved)          // and no registers will be pushed 
    354380        ) 
    355381            c = genregs(c,0x89,BP,SP);  // MOV SP,BP 
    356382        else 
    357383#endif 
    358384        {   regm_t scratchm = 0; 
    359             unsigned r; 
    360385 
    361386            if (numpara == REGSIZE && config.flags4 & CFG4space) 
    362387            { 
    363388                scratchm = ALLREGS & ~keepmsk & regcon.used & ~regcon.mvar; 
    364389            } 
    365390 
    366391            if (scratchm) 
    367             {   c = cat(c,allocreg(&scratchm,&r,TYint)); 
     392            {   unsigned r; 
     393                c = cat(c,allocreg(&scratchm,&r,TYint)); 
    368394                c = gen1(c,0x58 + r);           // POP r 
    369395            } 
    370396            else 
    371                 c = genc2(c,0x81,modregrm(3,0,SP),numpara); // ADD SP,numpara 
     397            {   c = genc2(c,0x81,modregrm(3,0,SP),numpara); // ADD SP,numpara 
     398                if (I64) 
     399                    code_orrex(c, REX_W); 
     400            } 
    372401        } 
    373402        stackpush -= numpara; 
    374403        c = genadjesp(c,-numpara); 
    375404    } 
    376405    return c; 
    377406} 
    378407 
    379408 
    380409/********************************* 
    381410 * Generate code for a logical expression. 
    382411 * Input: 
    383412 *      e       elem 
    384413 *      jcond 
    385414 *         bit 1 if TRUE then goto jump address if e 
    386415 *               if FALSE then goto jump address if !e 
    387416 *         2    don't call save87() 
    388417 *      fltarg   FLcode or FLblock, flavor of target if e evaluates to jcond 
    389418 *      targ    either code or block pointer to destination 
    390419 */ 
    391420 
    392421code *logexp(elem *e,int jcond,unsigned fltarg,code *targ) 
    393 { code *cc,*c,*ce,*cnop; 
     422{ code *c,*ce,*cnop; 
    394423  regm_t retregs; 
    395424  unsigned op; 
    396   int no87; 
    397425 
    398426  //printf("logexp(e = %p, jcond = %d)\n", e, jcond); 
    399   no87 = (jcond & 2) == 0; 
     427  int no87 = (jcond & 2) == 0; 
    400428  _chkstack(); 
    401   cc = docommas(&e);            /* scan down commas                     */ 
     429  code *cc = docommas(&e);            // scan down commas 
    402430  cgstate.stackclean++; 
    403431 
    404432  if (EOP(e) && !e->Ecount)     /* if operator and not common sub */ 
    405433  {     con_t regconsave; 
    406434 
    407435        switch (e->Eoper) 
    408436        {   case OPoror: 
    409437                if (jcond & 1) 
    410438                {       c = logexp(e->E1,jcond,fltarg,targ); 
    411439                        regconsave = regcon; 
    412440                        ce = logexp(e->E2,jcond,fltarg,targ); 
    413441                } 
    414442                else 
    415443                {       cnop = gennop(CNIL); 
    416444                        c = logexp(e->E1,jcond | 1,FLcode,cnop); 
    417445                        regconsave = regcon; 
    418446                        ce = logexp(e->E2,jcond,fltarg,targ); 
    419447                        ce = cat(ce,cnop); 
    420448                } 
    421449                cnop = CNIL; 
     
    438466                freenode(e); 
    439467                c = cat4(cc,c,ce,cnop); 
    440468                goto Lret; 
    441469 
    442470            case OPnot: 
    443471                jcond ^= 1; 
    444472            case OPbool: 
    445473            case OPs8int: 
    446474            case OPu8int: 
    447475            case OPs16_32: 
    448476            case OPu16_32: 
    449477            case OPs32_64: 
    450478            case OPu32_64: 
    451479            case OPu32_d: 
    452480            case OPd_ld: 
    453481                c = logexp(e->E1,jcond,fltarg,targ); 
    454482                freenode(e); 
    455483                goto Lretc; 
    456484 
    457485            case OPcond: 
    458             {   code *cnop2; 
    459                 con_t regconold; 
    460  
    461                 cnop2 = gennop(CNIL);   /* addresses of start of leaves */ 
     486            { 
     487                code *cnop2 = gennop(CNIL);   // addresses of start of leaves 
    462488                cnop = gennop(CNIL); 
    463489                c = logexp(e->E1,FALSE,FLcode,cnop2);   /* eval condition */ 
    464                 regconold = regcon; 
     490                con_t regconold = regcon; 
    465491                ce = logexp(e->E2->E1,jcond,fltarg,targ); 
    466492                ce = genjmp(ce,JMP,FLcode,(block *) cnop); /* skip second leaf */ 
    467493 
    468494                regconsave = regcon; 
    469495                regcon = regconold; 
    470496 
    471497                code_next(cnop2) = logexp(e->E2->E2,jcond,fltarg,targ); 
    472498                andregcon(&regconold); 
    473499                andregcon(&regconsave); 
    474500                freenode(e->E2); 
    475501                freenode(e); 
    476502                c = cat6(cc,c,NULL,ce,cnop2,cnop); 
    477503                goto Lret; 
    478504            } 
    479505        } 
    480506  } 
    481507 
    482   /* Special code for signed long compare       */ 
     508  /* Special code for signed long compare. 
     509   * Not necessary for I64 until we do cents. 
     510   */ 
    483511  if (OTrel2(e->Eoper) &&               /* if < <= >= >                 */ 
    484512      !e->Ecount && 
    485       ( (!I32 && tybasic(e->E1->Ety) == TYlong  && tybasic(e->E2->Ety) == TYlong) || 
    486         ( I32 && tybasic(e->E1->Ety) == TYllong && tybasic(e->E2->Ety) == TYllong)) 
     513      ( (I16 && tybasic(e->E1->Ety) == TYlong  && tybasic(e->E2->Ety) == TYlong) || 
     514        (I32 && tybasic(e->E1->Ety) == TYllong && tybasic(e->E2->Ety) == TYllong)) 
    487515     ) 
    488516  { 
    489517        c = longcmp(e,jcond,fltarg,targ); 
    490518        goto Lretc; 
    491519  } 
    492520 
    493521  retregs = mPSW;               /* return result in flags               */ 
    494522  op = jmpopcode(e);            /* get jump opcode                      */ 
    495523  if (!(jcond & 1)) 
    496524        op ^= 0x101;            // toggle jump condition(s) 
    497525  c = codelem(e,&retregs,TRUE); /* evaluate elem                        */ 
    498526  if (no87) 
    499527        c = cat(c,cse_flush(no87));     // flush CSE's to memory 
    500528  genjmp(c,op,fltarg,(block *) targ);   /* generate jmp instruction     */ 
    501529Lretc: 
    502530  c = cat(cc,c); 
    503531Lret: 
    504532  cgstate.stackclean--; 
    505533  return c; 
    506534} 
    507535 
    508536 
    509537/****************************** 
    510538 * Routine to aid in setting things up for gen(). 
    511539 * Look for common subexpression. 
    512540 * Can handle indirection operators, but not if they're common subs. 
    513541 * Input: 
    514542 *      e ->    elem where we get some of the data from 
    515543 *      cs ->   partially filled code to add 
    516544 *      op =    opcode 
    517545 *      reg =   reg field of (mod reg r/m) 
    518546 *      offset = data to be added to Voffset field 
    519547 *      keepmsk = mask of registers we must not destroy 
    520548 *      desmsk  = mask of registers destroyed by executing the instruction 
    521549 * Returns: 
    522550 *      pointer to code generated 
    523551 */ 
    524552 
    525 code *loadea(elem *e,code __ss *cs,unsigned op,unsigned reg,targ_size_t offset, 
     553code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    526554        regm_t keepmsk,regm_t desmsk) 
    527 { unsigned i; 
    528   regm_t rm; 
    529   tym_t tym; 
     555
    530556  code *c,*cg,*cd; 
    531557 
    532558#ifdef DEBUG 
    533559  if (debugw) 
    534560    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%ld keepmsk=x%x desmsk=x%x\n", 
    535561            e,cs,op,reg,offset,keepmsk,desmsk); 
    536562#endif 
    537563 
    538564  assert(e); 
    539565  cs->Iflags = 0; 
    540566  cs->Irex = 0; 
    541567  cs->Iop = op; 
    542   if (I32 && op >= 0x100)               /* if 2 byte opcode             */ 
     568  if (!I16 && op >= 0x100)               // if 2 byte opcode 
    543569  {     cs->Iop = op >> 8; 
    544570        cs->Iop2 = op; 
    545571  } 
    546   tym = e->Ety; 
     572  tym_t tym = e->Ety; 
     573  int sz = tysize(tym); 
    547574 
    548575  /* Determine if location we want to get is in a register. If so,      */ 
    549576  /* substitute the register for the EA.                                */ 
    550577  /* Note that operators don't go through this. CSE'd operators are     */ 
    551578  /* picked up by comsub().                                             */ 
    552579  if (e->Ecount &&                      /* if cse                       */ 
    553580      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    554581      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
    555582      (op != 0xFF || reg != 3) &&       /* and not CALLF MEM16          */ 
    556583      (op & 0xFFF8) != 0xD8)            // and not 8087 opcode 
    557   {     int sz; 
    558  
     584  { 
    559585        assert(!EOP(e));                /* can't handle this            */ 
    560         rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; /* possible regs                */ 
    561         sz = tysize(tym); 
    562         if (sz > REGSIZE) 
     586        regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 
     587        if (sz > REGSIZE)               // value is in 2 or 4 registers 
    563588        { 
    564                 if (!I32 && sz == 8) 
     589                if (I16 && sz == 8)     // value is in 4 registers 
    565590                {       static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 
    566591                        rm &= rmask[offset >> 1]; 
    567592                } 
    568593 
    569594                else if (offset) 
    570595                        rm &= mMSW;             /* only high words      */ 
    571596                else 
    572597                        rm &= mLSW;             /* only low words       */ 
    573598        } 
    574         for (i = 0; rm; i++) 
     599        for (unsigned i = 0; rm; i++) 
    575600        {       if (mask[i] & rm) 
    576601                {       if (regcon.cse.value[i] == e && // if register has elem 
    577602                            /* watch out for a CWD destroying DX        */ 
    578603                            !(i == DX && op == 0xF7 && desmsk & mDX)) 
    579604                        { 
    580605                                /* if ES, then it can only be a load    */ 
    581606                                if (i == ES) 
    582607                                {       if (op != 0x8B) 
    583608                                            goto L1;    /* not a load   */ 
    584609                                        cs->Iop = 0x8C; /* MOV reg,ES   */ 
    585                                         cs->Irm = modregrm(3,0,reg); 
     610                                        cs->Irm = modregrm(3,0,reg & 7); 
     611                                        if (reg & 8) 
     612                                            code_orrex(cs, REX_B); 
    586613                                } 
    587                                 else    /* XXX reg,i                    */ 
    588                                         cs->Irm = modregrm(3,reg,i); 
     614                                else    // XXX reg,i 
     615                                { 
     616                                    cs->Irm = modregrm(3,reg & 7,i & 7); 
     617                                    if (reg & 8) 
     618                                        code_orrex(cs, REX_R); 
     619                                    if (i & 8) 
     620                                        code_orrex(cs, REX_B); 
     621                                } 
    589622                                c = CNIL; 
    590623                                goto L2; 
    591624                        } 
    592625                        rm &= ~mask[i]; 
    593626                } 
    594627        } 
    595628  } 
    596629 
    597630L1: 
    598631  c = getlvalue(cs,e,keepmsk); 
    599632  if (offset == REGSIZE) 
    600633        getlvalue_msw(cs); 
    601634  else 
    602635        cs->IEVoffset1 += offset; 
    603   cs->Irm |= modregrm(0,reg,0);         /* OR in reg field              */ 
    604   if (I32
     636  code_newreg(cs, reg);                         // OR in reg field 
     637  if (!I16
    605638  { 
    606639      if (reg == 6 && op == 0xFF ||             /* don't PUSH a word    */ 
    607640          op == 0x0FB7 || op == 0x0FBF ||       /* MOVZX/MOVSX          */ 
    608641          (op & 0xFFF8) == 0xD8 ||              /* 8087 instructions    */ 
    609642          op == 0x8D)                           /* LEA                  */ 
    610643            cs->Iflags &= ~CFopsize; 
    611644  } 
    612645  else if ((op & 0xFFF8) == 0xD8 && ADDFWAIT()) 
    613646        cs->Iflags |= CFwait; 
    614647L2: 
    615648  cg = getregs(desmsk);                 /* save any regs we destroy     */ 
    616649 
    617650  /* KLUDGE! fix up DX for divide instructions */ 
    618651  cd = CNIL; 
    619652  if (op == 0xF7 && desmsk == (mAX|mDX))        /* if we need to fix DX */ 
    620653  {     if (reg == 7)                           /* if IDIV              */ 
    621                 cd = gen1(cd,0x99);             /* CWD                  */ 
    622         else if (reg == 6)                      /* if DIV               */ 
    623                 cd = genregs(cd,0x33,DX,DX);    /* CLR DX               */ 
     654        {   cd = gen1(cd,0x99);                 // CWD 
     655            if (I64 && sz == 8) 
     656                code_orrex(cd, REX_W); 
     657        } 
     658        else if (reg == 6)                      // if DIV 
     659        {   cd = genregs(cd,0x33,DX,DX);        // XOR DX,DX 
     660            if (I64 && sz == 8) 
     661                code_orrex(cd, REX_W); 
     662        } 
    624663  } 
    625664 
    626665  // Eliminate MOV reg,reg 
    627666  if ((cs->Iop & 0xFC) == 0x88 && 
    628       (cs->Irm & 0xC7) == modregrm(3,0,reg)) 
    629         cs->Iop = NOP; 
     667      (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 
     668  { 
     669        unsigned r = cs->Irm & 7; 
     670        if (cs->Irex & REX_B) 
     671            r |= 8; 
     672        if (r == reg) 
     673            cs->Iop = NOP; 
     674  } 
    630675 
    631676  return cat4(c,cg,cd,gen(CNIL,cs)); 
    632677} 
    633678 
    634679 
    635680/************************** 
    636681 * Get addressing mode. 
    637682 */ 
    638683 
    639684unsigned getaddrmode(regm_t idxregs) 
    640685{ 
    641     unsigned reg; 
    642685    unsigned mode; 
    643686 
    644     if (I32) 
    645     {   reg = findreg(idxregs & (ALLREGS | mBP)); 
    646         mode = modregrm(2,0,reg); 
    647     } 
    648     else 
     687    if (I16) 
    649688    { 
    650689        mode =  (idxregs & mBX) ? modregrm(2,0,7) :     /* [BX] */ 
    651690                (idxregs & mDI) ? modregrm(2,0,5):      /* [DI] */ 
    652691                (idxregs & mSI) ? modregrm(2,0,4):      /* [SI] */ 
    653692                                  (assert(0),1); 
    654693    } 
     694    else 
     695    {   unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 
     696        mode = modregrmx(2,0,reg); 
     697    } 
    655698    return mode; 
     699} 
     700 
     701void setaddrmode(code *c, regm_t idxregs) 
     702{ 
     703    unsigned mode = getaddrmode(idxregs); 
     704    c->Irm = mode & 0xFF; 
     705    c->Irex &= ~REX_B; 
     706    c->Irex |= mode >> 16; 
    656707} 
    657708 
    658709/********************************************** 
    659710 */ 
    660711 
    661712void getlvalue_msw(code *c) 
    662713{ 
    663714    if (c->IFL1 == FLreg) 
    664     {   unsigned regmsw; 
    665  
    666         regmsw = c->IEVsym1->Sregmsw; 
    667         c->Irm = (c->Irm & ~7) | regmsw; 
     715    { 
     716        unsigned regmsw = c->IEVsym1->Sregmsw; 
     717        c->Irm = (c->Irm & ~7) | (regmsw & 7); 
     718        if (regmsw & 8) 
     719            c->Irex |= REX_B; 
     720        else 
     721            c->Irex &= ~REX_B; 
    668722    } 
    669723    else 
    670724        c->IEVoffset1 += REGSIZE; 
    671725} 
    672726 
    673727/********************************************** 
    674728 */ 
    675729 
    676730void getlvalue_lsw(code *c) 
    677731{ 
    678732    if (c->IFL1 == FLreg) 
    679     {   unsigned reglsw; 
    680  
    681         reglsw = c->IEVsym1->Sreglsw; 
    682         c->Irm = (c->Irm & ~7) | reglsw; 
     733    { 
     734        unsigned reglsw = c->IEVsym1->Sreglsw; 
     735        c->Irm = (c->Irm & ~7) | (reglsw & 7); 
     736        if (reglsw & 8) 
     737            c->Irex |= REX_B; 
     738        else 
     739            c->Irex &= ~REX_B; 
    683740    } 
    684741    else 
    685742        c->IEVoffset1 -= REGSIZE; 
    686743} 
    687744 
    688745/****************** 
    689746 * Compute addressing mode. 
    690747 * Generate & return sequence of code (if any). 
    691748 * Return in cs the info on it. 
    692749 * Input: 
    693750 *      pcs ->  where to store data about addressing mode 
    694751 *      e ->    the lvalue elem 
    695752 *      keepmsk mask of registers we must not destroy or use 
    696753 *              if (keepmsk & RMstore), this will be only a store operation 
    697754 *              into the lvalue 
    698755 *              if (keepmsk & RMload), this will be a read operation only 
    699756 */ 
    700757 
    701 code *getlvalue(code __ss *pcs,elem *e,regm_t keepmsk) 
     758code *getlvalue(code *pcs,elem *e,regm_t keepmsk) 
    702759{ regm_t idxregs; 
    703760  unsigned fl,f,opsave; 
    704761  code *c; 
    705762  elem *e1; 
    706763  elem *e11; 
    707764  elem *e12; 
    708765  bool e1isadd,e1free; 
    709766  unsigned reg; 
    710   tym_t ty; 
    711767  tym_t e1ty; 
    712768  symbol *s; 
    713   unsigned sz; 
    714769 
    715770  //printf("getlvalue(e = %p)\n",e); 
    716771  //elem_print(e); 
    717772  assert(e); 
    718773  elem_debug(e); 
    719774  if (e->Eoper == OPvar || e->Eoper == OPrelconst) 
    720775  {     s = e->EV.sp.Vsym; 
    721776        fl = s->Sfl; 
    722777        if (tyfloating(s->ty())) 
    723778            obj_fltused(); 
    724779  } 
    725780  else 
    726781        fl = FLoper; 
    727782  pcs->IFL1 = fl; 
    728783  pcs->Iflags = CFoff;                  /* only want offsets            */ 
    729784  pcs->Irex = 0; 
    730785  pcs->IEVoffset1 = 0; 
    731   ty = e->Ety; 
     786 
     787  tym_t ty = e->Ety; 
     788  unsigned sz = tysize(ty); 
    732789  if (tyfloating(ty)) 
    733790        obj_fltused(); 
    734   sz = tysize(ty); 
    735   if (I32 && sz == SHORTSIZE) 
     791  else if (I64 && sz == 8) 
     792        pcs->Irex |= REX_W; 
     793  if (!I16 && sz == SHORTSIZE) 
    736794        pcs->Iflags |= CFopsize; 
    737795  if (ty & mTYvolatile) 
    738796        pcs->Iflags |= CFvolatile; 
    739797  c = CNIL; 
    740798  switch (fl) 
    741799  { 
    742800#if 0 && TARGET_LINUX 
    743801    case FLgot: 
    744802    case FLgotoff: 
    745803        gotref = 1; 
    746804        pcs->IEVsym1 = s; 
    747805        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    748806        if (e->Eoper == OPvar && fl == FLgot) 
    749807        { 
    750808            code *c1; 
    751809            int saveop = pcs->Iop; 
    752810            idxregs = allregs & ~keepmsk;       // get a scratch register 
    753811            c = allocreg(&idxregs,&reg,TYptr); 
    754812            pcs->Irm = modregrm(2,reg,BX);      // BX has GOT 
    755813            pcs->Isib = 0; 
     
    801859            e11 = e1->E1; 
    802860        } 
    803861 
    804862        /* First see if we can replace *(e+&v) with 
    805863         *      MOV     idxreg,e 
    806864         *      EA =    [ES:] &v+idxreg 
    807865         */ 
    808866 
    809867        if (e1isadd && 
    810868            e12->Eoper == OPrelconst && 
    811869            (f = el_fl(e12)) != FLfardata && 
    812870            e1->Ecount == e1->Ecomsub && 
    813871            (!e1->Ecount || (~keepmsk & ALLREGS & mMSW) || (e1ty != TYfptr && e1ty != TYhptr)) && 
    814872            tysize(e11->Ety) == REGSIZE 
    815873           ) 
    816874        {   unsigned char t;            /* component of r/m field */ 
    817875            int ss; 
    818876            int ssi; 
    819877 
    820878            /*assert(datafl[f]);*/              /* what if addr of func? */ 
    821             if (I32
     879            if (!I16
    822880            {   /* Any register can be an index register        */ 
    823                 idxregs = allregs & ~keepmsk; 
     881                regm_t idxregs = allregs & ~keepmsk; 
    824882                assert(idxregs); 
    825883 
    826884                /* See if e1->E1 can be a scaled index  */ 
    827885                ss = isscaledindex(e11); 
    828886                if (ss) 
    829887                { 
    830888                    /* Load index register with result of e11->E1       */ 
    831889                    c = cdisscaledindex(e11,&idxregs,keepmsk); 
    832890                    reg = findreg(idxregs); 
    833891#if 0 && TARGET_LINUX 
    834892                    if (f == FLgot || f == FLgotoff)    // config.flags3 & CFG3pic 
    835893                    { 
    836894                        gotref = 1; 
    837895                        pcs->Irm = modregrm(2,0,4); 
    838896                        pcs->Isib = modregrm(ss,reg,BX); 
    839897                    } 
    840898                    else 
    841899#endif 
    842900                    { 
    843901                        t = stackfl[f] ? 2 : 0; 
    844902                        pcs->Irm = modregrm(t,0,4); 
    845                         pcs->Isib = modregrm(ss,reg,5); 
     903                        pcs->Isib = modregrm(ss,reg & 7,5); 
     904                        if (reg & 8) 
     905                            pcs->Irex |= REX_X; 
    846906                    } 
    847907                } 
    848908                else if ((e11->Eoper == OPmul || e11->Eoper == OPshl) && 
    849909                         !e11->Ecount && 
    850910                         e11->E2->Eoper == OPconst && 
    851911                         (ssi = ssindex(e11->Eoper,e11->E2->EV.Vuns)) != 0 
    852912                        ) 
    853913                { 
    854914                    regm_t scratchm; 
    855                     unsigned r; 
    856                     int ss1; 
    857915                    int ss2; 
    858                     char ssflags; 
    859916 
    860917#if 0 && TARGET_LINUX 
    861918                    assert(f != FLgot && f != FLgotoff); 
    862919#endif 
    863                     ssflags = ssindex_array[ssi].ssflags; 
     920                    char ssflags = ssindex_array[ssi].ssflags; 
    864921                    if (ssflags & SSFLnobp && stackfl[f]) 
    865922                        goto L6; 
    866923 
    867924                    // Load index register with result of e11->E1 
    868925                    c = scodelem(e11->E1,&idxregs,keepmsk,TRUE); 
    869926                    reg = findreg(idxregs); 
    870927 
    871                     ss1 = ssindex_array[ssi].ss1; 
     928                    int ss1 = ssindex_array[ssi].ss1; 
    872929                    if (ssflags & SSFLlea) 
    873930                    { 
    874931                        assert(!stackfl[f]); 
    875932                        pcs->Irm = modregrm(2,0,4); 
    876                         pcs->Isib = modregrm(ss1,reg,reg); 
     933                        pcs->Isib = modregrm(ss1,reg & 7,reg & 7); 
     934                        if (reg & 8) 
     935                            pcs->Irex |= REX_X | REX_B; 
    877936                    } 
    878937                    else 
    879938                    {   int rbase; 
     939                        unsigned r; 
    880940 
    881941                        scratchm = ALLREGS & ~keepmsk; 
    882942                        c = cat(c,allocreg(&scratchm,&r,TYint)); 
    883943 
    884944                        if (ssflags & SSFLnobase1) 
    885945                        {   t = 0; 
    886946                            rbase = 5; 
    887947                        } 
    888948                        else 
    889949                        {   t = 0; 
    890950                            rbase = reg; 
    891951                            if (rbase == BP) 
    892952                            {   static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 
    893953 
    894954                                // IMUL r,BP,imm32 
    895                                 c = genc2(c,0x69,modregrm(3,r,BP),imm32[ss1]); 
     955                                c = genc2(c,0x69,modregxrm(3,r,BP),imm32[ss1]); 
    896956                                goto L7; 
    897957                            } 
    898958                        } 
    899959 
    900                         c = gen2sib(c,0x8D,modregrm(t,r,4),modregrm(ss1,reg,rbase)); 
     960                        c = gen2sib(c,0x8D,modregxrm(t,r,4),modregrm(ss1,reg & 7,rbase & 7)); 
     961                        if (reg & 8) 
     962                            code_orrex(c, REX_X); 
     963                        if (rbase & 8) 
     964                            code_orrex(c, REX_B); 
     965 
    901966                        if (ssflags & SSFLnobase1) 
    902967                        {   code_last(c)->IFL1 = FLconst; 
    903968                            code_last(c)->IEV1.Vuns = 0; 
    904969                        } 
    905970                    L7: 
    906971                        if (ssflags & SSFLnobase) 
    907972                        {   t = stackfl[f] ? 2 : 0; 
    908973                            rbase = 5; 
    909974                        } 
    910975                        else 
    911976                        {   t = 2; 
    912977                            rbase = r; 
    913978                            assert(rbase != BP); 
    914979                        } 
    915980                        pcs->Irm = modregrm(t,0,4); 
    916                         pcs->Isib = modregrm(ssindex_array[ssi].ss2,r,rbase); 
     981                        pcs->Isib = modregrm(ssindex_array[ssi].ss2,r & 7,rbase & 7); 
     982                        if (r & 8) 
     983                            code_orrex(pcs, REX_X); 
     984                        if (rbase & 8) 
     985                            code_orrex(pcs, REX_B); 
    917986                    } 
    918987                    freenode(e11->E2); 
    919988                    freenode(e11); 
    920989                } 
    921990                else 
    922991                { 
    923992                 L6: 
    924993                    /* Load index register with result of e11   */ 
    925994                    c = scodelem(e11,&idxregs,keepmsk,TRUE); 
    926                     pcs->Irm = getaddrmode(idxregs); 
     995                    setaddrmode(pcs, idxregs); 
    927996#if 0 && TARGET_LINUX 
    928997                    if (e12->EV.sp.Vsym->Sfl == FLgot || e12->EV.sp.Vsym->Sfl == FLgotoff) 
    929998                    { 
    930999                        gotref = 1; 
    9311000#if 1 
    9321001                        reg = findreg(idxregs & (ALLREGS | mBP)); 
    9331002                        pcs->Irm = modregrm(2,0,4); 
    9341003                        pcs->Isib = modregrm(0,reg,BX); 
    9351004#else 
    9361005                        pcs->Isib = modregrm(0,pcs->Irm,BX); 
    9371006                        pcs->Irm = modregrm(2,0,4); 
    9381007#endif 
    9391008                    } 
    9401009                    else 
    9411010#endif 
    9421011                    if (stackfl[f])             /* if we need [EBP] too */ 
    943                     { 
    944                         pcs->Isib = modregrm(0,pcs->Irm,BP); 
     1012                    {   unsigned idx = pcs->Irm & 7; 
     1013                        if (pcs->Irex & REX_B) 
     1014                            pcs->Irex = (pcs->Irex & ~REX_B) | REX_X; 
     1015                        pcs->Isib = modregrm(0,idx,BP); 
    9451016                        pcs->Irm = modregrm(2,0,4); 
    9461017                    } 
    9471018                } 
    9481019            } 
    9491020            else 
    9501021            { 
    9511022                idxregs = IDXREGS & ~keepmsk;   /* only these can be index regs */ 
    9521023                assert(idxregs); 
    9531024#if 0 && TARGET_LINUX 
    9541025                assert(f != FLgot && f != FLgotoff); 
    9551026#endif 
    9561027                if (stackfl[f])                 /* if stack data type   */ 
    9571028                {   idxregs &= mSI | mDI;       /* BX can't index off stack */ 
    9581029                    if (!idxregs) goto L1;      /* index regs aren't avail */ 
    9591030                    t = 6;                      /* [BP+SI+disp]         */ 
    9601031                } 
    9611032                else 
    9621033                    t = 0;                      /* [SI + disp]          */ 
    9631034                c = scodelem(e11,&idxregs,keepmsk,TRUE); /* load idx reg */ 
    9641035                pcs->Irm = getaddrmode(idxregs) ^ t; 
     
    9811052            {   unsigned flagsave; 
    9821053 
    9831054                idxregs = IDXREGS & ~keepmsk; 
    9841055                c = cat(c,allocreg(&idxregs,&reg,TYoffset)); 
    9851056 
    9861057                /* If desired result is a far pointer, we'll have       */ 
    9871058                /* to load another register with the segment of v       */ 
    9881059                if (e1ty == TYfptr) 
    9891060                { 
    9901061                    unsigned msreg; 
    9911062 
    9921063                    idxregs |= mMSW & ALLREGS & ~keepmsk; 
    9931064                    c = cat(c,allocreg(&idxregs,&msreg,TYfptr)); 
    9941065                    msreg = findregmsw(idxregs); 
    9951066                                                /* MOV msreg,segreg     */ 
    9961067                    c = genregs(c,0x8C,segfl[f],msreg); 
    9971068                } 
    9981069                opsave = pcs->Iop; 
    9991070                flagsave = pcs->Iflags; 
    10001071                pcs->Iop = 0x8D; 
    1001                 pcs->Irm |= modregrm(0,reg,0); 
    1002                 if (I32
     1072                code_newreg(pcs, reg); 
     1073                if (!I16
    10031074                    pcs->Iflags &= ~CFopsize; 
    10041075                c = gen(c,pcs);                 /* LEA idxreg,EA        */ 
    10051076                cssave(e1,idxregs,TRUE); 
    1006                 if (I32
     1077                if (!I16
    10071078                    pcs->Iflags = flagsave; 
    10081079                if (stackfl[f] && (config.wflags & WFssneds))   // if pointer into stack 
    10091080                    pcs->Iflags |= CFss;        // add SS: override 
    10101081                pcs->Iop = opsave; 
    10111082                pcs->IFL1 = FLoffset; 
    10121083                pcs->IEV1.Vuns = 0; 
    1013                 pcs->Irm = getaddrmode(idxregs); 
     1084                setaddrmode(pcs, idxregs); 
    10141085            } 
    10151086            freenode(e12); 
    10161087            if (e1free) 
    10171088                freenode(e1); 
    10181089            goto Lptr; 
    10191090        } 
    10201091 
    10211092        L1: 
    10221093 
    10231094        /* The rest of the cases could be a far pointer */ 
    10241095 
    1025         idxregs = (I32 ? allregs : IDXREGS) & ~keepmsk; /* only these can be index regs */ 
     1096        idxregs = (I16 ? IDXREGS : allregs) & ~keepmsk; // only these can be index regs 
    10261097        assert(idxregs); 
    1027         if (I32 && sz == REGSIZE && keepmsk & RMstore) 
     1098        if (!I16 && 
     1099            (sz == REGSIZE || (I64 && sz == 4)) && 
     1100            keepmsk & RMstore) 
    10281101            idxregs |= regcon.mvar; 
    10291102 
    10301103#if !TARGET_FLAT 
    10311104        switch (e1ty) 
    10321105        {   case TYfptr:                        /* if far pointer       */ 
    10331106            case TYhptr: 
    10341107                idxregs = (mES | IDXREGS) & ~keepmsk;   // need segment too 
    10351108                assert(idxregs & mES); 
    10361109                pcs->Iflags |= CFes;            /* ES segment override  */ 
    10371110                break; 
    10381111            case TYsptr:                        /* if pointer to stack  */ 
    10391112                if (config.wflags & WFssneds)   // if SS != DS 
    10401113                    pcs->Iflags |= CFss;        /* then need SS: override */ 
    10411114                break; 
    10421115            case TYcptr:                        /* if pointer to code   */ 
    10431116                pcs->Iflags |= CFcs;            /* then need CS: override */ 
    10441117                break; 
    10451118        } 
    10461119#endif 
    10471120        pcs->IFL1 = FLoffset; 
     
    10541127         */ 
    10551128 
    10561129        if (e1isadd && e12->Eoper == OPconst && 
    10571130            tysize(e12->Ety) == REGSIZE && 
    10581131            (!e1->Ecount || !e1free) 
    10591132           ) 
    10601133        {   int ss; 
    10611134 
    10621135            pcs->IEV1.Vuns = e12->EV.Vuns; 
    10631136            freenode(e12); 
    10641137            if (e1free) freenode(e1); 
    10651138            if (I32 && e11->Eoper == OPadd && !e11->Ecount && 
    10661139                tysize(e11->Ety) == REGSIZE) 
    10671140            { 
    10681141                e12 = e11->E2; 
    10691142                e11 = e11->E1; 
    10701143                e1 = e1->E1; 
    10711144                e1free = TRUE; 
    10721145                goto L4; 
    10731146            } 
    1074             if (I32 && (ss = isscaledindex(e11)) != 0) 
     1147            if (!I16 && (ss = isscaledindex(e11)) != 0) 
    10751148            {   // (v * scale) + const 
    10761149                c = cdisscaledindex(e11,&idxregs,keepmsk); 
    10771150                reg = findreg(idxregs); 
    10781151                pcs->Irm = modregrm(0,0,4); 
    1079                 pcs->Isib = modregrm(ss,reg,5); 
     1152                pcs->Isib = modregrm(ss,reg & 7,5); 
     1153                if (reg & 8) 
     1154                    pcs->Irex |= REX_X; 
    10801155            } 
    10811156            else 
    10821157            { 
    10831158                c = scodelem(e11,&idxregs,keepmsk,TRUE); // load index reg 
    1084                 pcs->Irm = getaddrmode(idxregs); 
     1159                setaddrmode(pcs, idxregs); 
    10851160            } 
    10861161            goto Lptr; 
    10871162        } 
    10881163 
    10891164        /* Look for *(v1 + v2) 
    10901165         *      EA = [v1][v2] 
    10911166         */ 
    10921167 
    1093         if (I32 && e1isadd && (!e1->Ecount || !e1free) && 
     1168        if (!I16 && e1isadd && (!e1->Ecount || !e1free) && 
    10941169            tysize[e1ty] == REGSIZE) 
    10951170        {   code *c2; 
    10961171            regm_t idxregs2; 
    10971172            unsigned base,index; 
    10981173            int ss; 
    10991174 
    11001175        L4: 
    11011176            // Look for *(v1 + v2 << scale) 
    11021177            ss = isscaledindex(e12); 
    11031178            if (ss) 
    11041179            { 
    11051180                c = scodelem(e11,&idxregs,keepmsk,TRUE); 
    11061181                idxregs2 = allregs & ~(idxregs | keepmsk); 
    11071182                c2 = cdisscaledindex(e12,&idxregs2,keepmsk | idxregs); 
    11081183            } 
    11091184 
    11101185            // Look for *(v1 << scale + v2) 
    11111186            else if ((ss = isscaledindex(e11)) != 0) 
    11121187            { 
    11131188                idxregs2 = idxregs; 
     
    11221197                    ) 
    11231198            { 
    11241199                pcs->IEV1.Vuns = e11->E2->EV.Vuns; 
    11251200                idxregs2 = idxregs; 
    11261201                c = cdisscaledindex(e11->E1,&idxregs2,keepmsk); 
    11271202                idxregs = allregs & ~(idxregs2 | keepmsk); 
    11281203                c2 = scodelem(e12,&idxregs,keepmsk | idxregs2,TRUE); 
    11291204                freenode(e11->E2); 
    11301205                freenode(e11); 
    11311206            } 
    11321207            else 
    11331208            { 
    11341209                c = scodelem(e11,&idxregs,keepmsk,TRUE); 
    11351210                idxregs2 = allregs & ~(idxregs | keepmsk); 
    11361211                c2 = scodelem(e12,&idxregs2,keepmsk | idxregs,TRUE); 
    11371212            } 
    11381213            c = cat(c,c2); 
    11391214            base = findreg(idxregs); 
    11401215            index = findreg(idxregs2); 
    11411216            pcs->Irm  = modregrm(2,0,4); 
    1142             pcs->Isib = modregrm(ss,index,base); 
     1217            pcs->Isib = modregrm(ss,index & 7,base & 7); 
     1218            if (index & 8) 
     1219                pcs->Irex |= REX_X; 
     1220            if (base & 8) 
     1221                pcs->Irex |= REX_B; 
    11431222            if (e1free) freenode(e1); 
    11441223            goto Lptr; 
    11451224        } 
    11461225 
    11471226        /* give up and replace *e1 with 
    11481227         *      MOV     idxreg,e 
    11491228         *      EA =    0[idxreg] 
    11501229         * pinholeopt() will usually correct the 0, we need it in case 
    11511230         * we have a pointer to a long and need an offset to the second 
    11521231         * word. 
    11531232         */ 
    11541233 
    11551234        assert(e1free); 
    11561235        c = scodelem(e1,&idxregs,keepmsk,TRUE); /* load index register  */ 
    1157         pcs->Irm = getaddrmode(idxregs); 
     1236        setaddrmode(pcs, idxregs); 
    11581237    Lptr: 
    11591238        if (config.flags3 & CFG3ptrchk) 
    11601239            cod3_ptrchk(&c,pcs,keepmsk);        // validate pointer code 
    11611240        break; 
    11621241    case FLdatseg: 
    11631242        assert(0); 
    11641243#if 0 
    11651244        pcs->Irm = modregrm(0,0,BPRM); 
    11661245        pcs->IEVpointer1 = e->EVpointer; 
    11671246        break; 
    11681247#endif 
    11691248    case FLfltreg: 
    11701249        reflocal = TRUE; 
    11711250        pcs->Irm = modregrm(2,0,BPRM); 
    11721251        pcs->IEV1.Vint = 0; 
    11731252        break; 
    11741253    case FLreg: 
    11751254        goto L2; 
    11761255    case FLpara: 
    11771256        refparam = TRUE; 
    11781257        pcs->Irm = modregrm(2,0,BPRM); 
    11791258        goto L2; 
    11801259 
    11811260    case FLauto: 
    11821261        if (s->Sclass == SCfastpar && regcon.params & mask[s->Spreg]) 
    11831262        { 
    11841263            if (keepmsk & RMload) 
    11851264            { 
    11861265                if (sz == REGSIZE)      // could this be (sz <= REGSIZE) ? 
    11871266                { 
    1188                     pcs->Irm = modregrm(3,0,s->Spreg); 
     1267                    pcs->Irm = modregrm(3,0,s->Spreg & 7); 
     1268                    if (s->Spreg & 8) 
     1269                        pcs->Irex |= REX_B; 
    11891270                    regcon.used |= mask[s->Spreg]; 
    11901271                    break; 
    11911272                } 
    11921273            } 
    11931274            else 
    11941275                regcon.params &= ~mask[s->Spreg]; 
    11951276        } 
    11961277    case FLtmp: 
    11971278    case FLbprel: 
    11981279        reflocal = TRUE; 
    11991280        pcs->Irm = modregrm(2,0,BPRM); 
    12001281        goto L2; 
    12011282    case FLextern: 
    12021283        if (s->Sident[0] == '_' && memcmp(s->Sident + 1,"tls_array",10) == 0) 
    12031284        { 
    12041285#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    12051286            // Rewrite as GS:[0000] 
    12061287            pcs->Irm = modregrm(0, 0, BPRM); 
    12071288            pcs->IFL1 = FLconst; 
    12081289            pcs->IEV1.Vuns = 0; 
     
    12161297        goto L3; 
    12171298    case FLdata: 
    12181299    case FLudata: 
    12191300    case FLcsdata: 
    12201301#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    12211302    case FLgot: 
    12221303    case FLgotoff: 
    12231304    case FLtlsdata: 
    12241305#endif 
    12251306    L3: 
    12261307        pcs->Irm = modregrm(0,0,BPRM); 
    12271308    L2: 
    12281309        if (fl == FLreg) 
    12291310        {   assert(s->Sregm & regcon.mvar); 
    12301311            if ( 
    12311312                s->Sclass == SCregpar || 
    12321313                s->Sclass == SCparameter) 
    12331314            {   refparam = TRUE; 
    12341315                reflocal = TRUE;        // kludge to set up prolog 
    12351316            } 
    1236             pcs->Irm = modregrm(3,0,s->Sreglsw); 
     1317            pcs->Irm = modregrm(3,0,s->Sreglsw & 7); 
     1318            if (s->Sreglsw & 8) 
     1319                pcs->Irex |= REX_B; 
    12371320            if (e->EV.sp.Voffset == 1 && sz == 1) 
    12381321            {   assert(s->Sregm & BYTEREGS); 
     1322                assert(s->Sreglsw < 4); 
    12391323                pcs->Irm |= 4;                  // use 2nd byte of register 
    12401324            } 
    12411325            else 
    12421326                assert(!e->EV.sp.Voffset); 
    12431327        } 
    12441328        else if (s->ty() & mTYcs && !(fl == FLextern && LARGECODE)) 
    12451329        { 
    12461330            pcs->Iflags |= CFcs | CFoff; 
    12471331        } 
    12481332#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    12491333//      if (fl == FLtlsdata || s->ty() & mTYthread) 
    12501334//          pcs->Iflags |= CFgs; 
    12511335#endif 
    12521336        pcs->IEVsym1 = s; 
    12531337        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    12541338        if (sz == 1) 
    12551339        {   /* Don't use SI or DI for this variable     */ 
    12561340            s->Sflags |= GTbyte; 
    12571341            if (e->EV.sp.Voffset > 1) 
    12581342                s->Sflags &= ~GTregcand; 
    12591343        } 
    12601344        else if (e->EV.sp.Voffset) 
    12611345            s->Sflags &= ~GTregcand; 
    12621346        if (!(keepmsk & RMstore))               // if not store only 
    12631347        {   s->Sflags |= SFLread;               // assume we are doing a read 
    12641348        } 
    12651349        break; 
    12661350    case FLpseudo: 
    12671351#if MARS 
    12681352        assert(0); 
    12691353#else 
    1270     {   unsigned u; 
    1271  
    1272         u = s->Sreglsw; 
     1354    { 
     1355        unsigned u = s->Sreglsw; 
    12731356        c = getregs(pseudomask[u]); 
    12741357        pcs->Irm = modregrm(3,0,pseudoreg[u] & 7); 
    12751358        break; 
    12761359    } 
    12771360#endif 
    12781361    case FLfardata: 
    12791362        assert(!TARGET_FLAT); 
    12801363    case FLfunc:                                /* reading from code seg */ 
    12811364        if (config.exe & EX_flat) 
    12821365            goto L3; 
    12831366    Lfardata: 
    1284     {   regm_t regm; 
    1285         code *c1; 
    1286  
    1287         regm = ALLREGS & ~keepmsk;              /* need scratch register */ 
    1288         c1 = allocreg(&regm,&reg,TYint); 
     1367    { 
     1368        regm_t regm = ALLREGS & ~keepmsk;       // need scratch register 
     1369        code *c1 = allocreg(&regm,&reg,TYint); 
    12891370        /* MOV mreg,seg of symbol       */ 
    12901371        c = gencs(CNIL,0xB8 + reg,0,FLextern,s); 
    12911372        c->Iflags = CFseg; 
    1292         c = gen2(c,0x8E,modregrm(3,0,reg));     /* MOV ES,reg           */ 
     1373        c = gen2(c,0x8E,modregrmx(3,0,reg));     /* MOV ES,reg           */ 
    12931374        c = cat3(c1,getregs(mES),c); 
    12941375        pcs->Iflags |= CFes | CFoff;            /* ES segment override  */ 
    12951376        goto L3; 
    12961377    } 
    12971378 
    12981379    case FLstack: 
    1299         assert(I32); 
     1380        assert(!I16); 
    13001381        pcs->Irm = modregrm(2,0,4); 
    13011382        pcs->Isib = modregrm(0,4,SP); 
    13021383        pcs->IEVsym1 = s; 
    13031384        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    13041385        break; 
    13051386 
    13061387    default: 
    13071388#ifdef DEBUG 
    13081389        WRFL((enum FL)fl); 
    13091390        symbol_print(s); 
    13101391#endif 
    13111392        assert(0); 
    13121393  } 
    13131394  return c; 
    13141395} 
    13151396 
    13161397 
    13171398/******************************* 
    13181399 * Same as codelem(), but do not destroy the registers in keepmsk. 
    13191400 * Use scratch registers as much as possible, then use stack. 
     
    14321512 
    14331513        assert(i < REGMAX); 
    14341514        if (mi & tosave)        /* i = register to save                 */ 
    14351515        { 
    14361516            if (touse)          /* if any scratch registers             */ 
    14371517            {   for (j = 0; j < 8; j++) 
    14381518                {   regm_t mj = mask[j]; 
    14391519 
    14401520                    if (touse & mj) 
    14411521                    {   cs1 = genmovreg(cs1,j,i); 
    14421522                        cs2 = cat(genmovreg(CNIL,i,j),cs2); 
    14431523                        touse &= ~mj; 
    14441524                        mfuncreg &= ~mj; 
    14451525                        regcon.used |= mj; 
    14461526                        break; 
    14471527                    } 
    14481528                } 
    14491529                assert(j < 8); 
    14501530            } 
    14511531            else                        /* else use stack               */ 
     1532#if 0 
    14521533            {   int push,pop; 
    14531534 
    14541535                stackchanged = 1; 
    14551536                adjesp += REGSIZE; 
    14561537                if (i == ES) 
    14571538                {       push = 0x06; 
    14581539                        pop = 0x07; 
    14591540                } 
    14601541                else 
    14611542                {       push = 0x50 + i; 
    14621543                        pop = push | 8; 
    14631544                } 
    14641545                cs1 = gen1(cs1,push);                   /* PUSH i       */ 
    14651546                cs2 = cat(gen1(CNIL,pop),cs2);          /* POP i        */ 
    14661547            } 
     1548#else 
     1549            { 
     1550                stackchanged = 1; 
     1551                adjesp += REGSIZE; 
     1552                gensaverestore2(mask[i], &cs1, &cs2); 
     1553            } 
     1554#endif 
    14671555            cs3 = cat(getregs(mi),cs3); 
    14681556            tosave &= ~mi; 
    14691557        } 
    14701558  } 
    14711559  if (adjesp) 
    14721560  { 
    14731561        // If this is done an odd number of times, it 
    14741562        // will throw off the 8 byte stack alignment. 
    14751563        // We should *only* worry about this if a function 
    14761564        // was called in the code generation by codelem(). 
    14771565        int sz; 
    14781566        if (STACKALIGN == 16) 
    14791567            sz = -(adjesp & (STACKALIGN - 1)) & (STACKALIGN - 1); 
    14801568        else 
    14811569            sz = -(adjesp & 7) & 7; 
    1482         if (calledafunc && I32 && sz && (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 
    1483         {   code *cx; 
    1484  
     1570        if (calledafunc && !I16 && sz && (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 
     1571        { 
     1572            unsigned grex = I64 ? REX_W << 16 : 0; 
    14851573            regm_t mval_save = regcon.immed.mval; 
    14861574            regcon.immed.mval = 0;      // prevent reghasvalue() optimizations 
    14871575                                        // because c hasn't been executed yet 
    1488             cs1 = genc2(cs1,0x81,modregrm(3,5,SP),sz);  // SUB ESP,sz 
     1576            cs1 = genc2(cs1,0x81,grex | modregrm(3,5,SP),sz);  // SUB ESP,sz 
    14891577            regcon.immed.mval = mval_save; 
    14901578            cs1 = genadjesp(cs1, sz); 
    14911579 
    1492             cx = genc2(CNIL,0x81,modregrm(3,0,SP),sz);  // ADD ESP,sz 
     1580            code *cx = genc2(CNIL,0x81,grex | modregrm(3,0,SP),sz);  // ADD ESP,sz 
    14931581            cx = genadjesp(cx, -sz); 
    14941582            cs2 = cat(cx, cs2); 
    14951583        } 
    14961584 
    14971585        cs1 = genadjesp(cs1,adjesp); 
    14981586        cs2 = genadjesp(cs2,-adjesp); 
    14991587  } 
    15001588 
    15011589  calledafunc |= calledafuncsave; 
    15021590  msavereg &= ~keepmsk | overlap; /* remove from mask of regs to save   */ 
    15031591  mfuncreg &= oldmfuncreg;      /* update original                      */ 
    15041592#ifdef DEBUG 
    15051593  if (debugw) 
    15061594        printf("-scodelem(e=%p *pretregs=x%x keepmsk=x%x constflag=%d\n", 
    15071595                e,*pretregs,keepmsk,constflag); 
    15081596#endif 
    15091597  return cat4(cs1,c,cs3,cs2); 
    15101598} 
    15111599 
    15121600 
    15131601/***************************** 
    15141602 * Given an opcode and EA in cs, generate code 
    15151603 * for each floating register in turn. 
    15161604 * Input: 
    15171605 *      tym     either TYdouble or TYfloat 
    15181606 */ 
    15191607 
    1520 code *fltregs(code __ss *pcs,tym_t tym) 
     1608code *fltregs(code *pcs,tym_t tym) 
    15211609{   code *c; 
    15221610 
     1611    assert(!I64); 
    15231612    tym = tybasic(tym); 
    15241613    if (I32) 
    15251614    { 
    15261615        c = getregs((tym == TYfloat) ? mAX : mAX | mDX); 
    15271616        if (tym != TYfloat) 
    15281617        { 
    15291618            pcs->IEVoffset1 += REGSIZE; 
    15301619            NEWREG(pcs->Irm,DX); 
    15311620            c = gen(c,pcs); 
    15321621            pcs->IEVoffset1 -= REGSIZE; 
    15331622        } 
    15341623        NEWREG(pcs->Irm,AX); 
    15351624        c = gen(c,pcs); 
    15361625    } 
    15371626    else 
    15381627    { 
    15391628        c = getregs((tym == TYfloat) ? FLOATREGS_16 : DOUBLEREGS_16); 
    15401629        pcs->IEVoffset1 += (tym == TYfloat) ? 2 : 6; 
    15411630        if (tym == TYfloat) 
    15421631            NEWREG(pcs->Irm,DX); 
     
    15531642        {     pcs->IEVoffset1 -= 2; 
    15541643              NEWREG(pcs->Irm,CX); 
    15551644              gen(c,pcs); 
    15561645              pcs->IEVoffset1 -= 2;     /* note that exit is with Voffset unaltered */ 
    15571646              NEWREG(pcs->Irm,DX); 
    15581647              gen(c,pcs); 
    15591648        } 
    15601649    } 
    15611650    return c; 
    15621651} 
    15631652 
    15641653 
    15651654/***************************** 
    15661655 * Given a result in registers, test it for TRUE or FALSE. 
    15671656 * Will fail if TYfptr and the reg is ES! 
    15681657 * If saveflag is TRUE, preserve the contents of the 
    15691658 * registers. 
    15701659 */ 
    15711660 
    15721661code *tstresult(regm_t regm,tym_t tym,unsigned saveflag) 
    1573 { code *ce; 
    1574   unsigned reg; 
     1662
    15751663  unsigned scrreg;                      /* scratch register             */ 
    1576   unsigned sz; 
    15771664  regm_t scrregm; 
    15781665 
    15791666#ifdef DEBUG 
    15801667  if (!(regm & (mBP | ALLREGS))) 
    15811668        printf("tstresult(regm = x%x, tym = x%lx, saveflag = %d)\n", 
    15821669            regm,tym,saveflag); 
    15831670#endif 
    15841671  assert(regm & (mBP | ALLREGS)); 
    15851672  tym = tybasic(tym); 
    1586   ce = CNIL; 
    1587   reg = findreg(regm); 
    1588   sz = tysize[tym]; 
     1673  code *ce = CNIL; 
     1674  unsigned reg = findreg(regm); 
     1675  unsigned sz = tysize[tym]; 
    15891676  if (sz == 1) 
    15901677  {     assert(regm & BYTEREGS); 
    15911678        return genregs(ce,0x84,reg,reg);        // TEST regL,regL 
    15921679  } 
    15931680  if (sz <= REGSIZE) 
    15941681  { 
    1595     if (I32
     1682    if (!I16
    15961683    { 
    15971684        if (tym == TYfloat) 
    15981685        {   if (saveflag) 
    15991686            { 
    16001687                scrregm = allregs & ~regm;              /* possible scratch regs */ 
    16011688                ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 
    16021689                ce = genmovreg(ce,scrreg,reg);  /* MOV scrreg,msreg     */ 
    16031690                reg = scrreg; 
    16041691            } 
    16051692            ce = cat(ce,getregs(mask[reg])); 
    1606             return gen2(ce,0xD1,modregrm(3,4,reg)); /* SHL reg,1        */ 
     1693            return gen2(ce,0xD1,modregrmx(3,4,reg)); // SHL reg,1 
    16071694        } 
    16081695        ce = gentstreg(ce,reg);                 // TEST reg,reg 
    1609         if (tysize[tym] == SHORTSIZE) 
     1696        if (sz == SHORTSIZE) 
    16101697            ce->Iflags |= CFopsize;             /* 16 bit operands      */ 
     1698        else if (sz == 8) 
     1699            code_orrex(ce, REX_W); 
    16111700    } 
    16121701    else 
    16131702        ce = gentstreg(ce,reg);                 // TEST reg,reg 
    16141703    return ce; 
    16151704  } 
    16161705  if (saveflag || tyfv(tym)) 
    16171706  { 
    16181707        scrregm = ALLREGS & ~regm;              /* possible scratch regs */ 
    16191708        ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 
    16201709        if (I32 || sz == REGSIZE * 2) 
    16211710        {   code *c; 
    16221711 
    16231712            assert(regm & mMSW && regm & mLSW); 
    16241713 
    16251714            reg = findregmsw(regm); 
    16261715            if (I32) 
    16271716            { 
    16281717                if (tyfv(tym)) 
    16291718                {   c = genregs(CNIL,0x0F,scrreg,reg); 
    16301719                    c->Iop2 = 0xB7;                     /* MOVZX scrreg,msreg   */ 
     
    17011790 
    17021791//  printf("fixresult(e = %p, retregs = %s, *pretregs = %s)\n", 
    17031792//      e,regm_str(retregs),regm_str(*pretregs)); 
    17041793  if (*pretregs == 0) return CNIL;      /* if don't want result         */ 
    17051794  assert(e && retregs);                 /* need something to work with  */ 
    17061795  forccs = *pretregs & mPSW; 
    17071796  forregs = *pretregs & (mST01 | mST0 | mBP | ALLREGS | mES | mSTACK); 
    17081797  tym = tybasic(e->Ety); 
    17091798#if 0 
    17101799  if (tym == TYstruct) 
    17111800        // Hack to support cdstreq() 
    17121801        tym = TYfptr; 
    17131802#else 
    17141803  if (tym == TYstruct) 
    17151804        // Hack to support cdstreq() 
    17161805        tym = (forregs & mMSW) ? TYfptr : TYnptr; 
    17171806#endif 
    17181807  c = CNIL; 
    17191808  sz = tysize[tym]; 
    17201809  if (sz == 1) 
    1721   {     unsigned reg; 
    1722  
     1810  { 
    17231811        assert(retregs & BYTEREGS); 
    1724         reg = findreg(retregs); 
     1812        unsigned reg = findreg(retregs); 
    17251813        if (e->Eoper == OPvar && 
    17261814            e->EV.sp.Voffset == 1 && 
    17271815            e->EV.sp.Vsym->Sfl == FLreg) 
    17281816        { 
     1817            assert(reg < 4); 
    17291818            if (forccs) 
    17301819                c = gen2(c,0x84,modregrm(3,reg | 4,reg | 4));   // TEST regH,regH 
    17311820            forccs = 0; 
    17321821        } 
    17331822  } 
    17341823  if ((retregs & forregs) == retregs)   /* if already in right registers */ 
    17351824        *pretregs = retregs; 
    17361825  else if (forregs)             /* if return the result in registers    */ 
    1737   {     unsigned opsflag; 
    1738  
     1826  { 
    17391827        if (forregs & (mST01 | mST0)) 
    17401828            return fixresult87(e,retregs,pretregs); 
    17411829        ce = CNIL; 
    1742         opsflag = FALSE; 
    1743         if (!I32 && sz == 8) 
     1830        unsigned opsflag = FALSE; 
     1831        if (I16 && sz == 8) 
    17441832        {   if (forregs & mSTACK) 
    17451833            {   assert(retregs == DOUBLEREGS_16); 
    17461834                /* Push floating regs   */ 
    17471835                c = CNIL; 
    17481836                ce = gen1(ce,0x50 + AX); 
    17491837                gen1(ce,0x50 + BX); 
    17501838                gen1(ce,0x50 + CX); 
    17511839                gen1(ce,0x50 + DX); 
    17521840                stackpush += DOUBLESIZE; 
    17531841            } 
    17541842            else if (retregs & mSTACK) 
    17551843            {   assert(forregs == DOUBLEREGS_16); 
    17561844                /* Pop floating regs    */ 
    17571845                c = getregs(forregs); 
    17581846                ce = gen1(ce,0x58 + DX); 
    17591847                gen1(ce,0x58 + CX); 
    17601848                gen1(ce,0x58 + BX); 
    17611849                gen1(ce,0x58 + AX); 
    17621850                stackpush -= DOUBLESIZE; 
    17631851                retregs = DOUBLEREGS_16; /* for tstresult() below       */ 
     
    17961884                                        /* cuz we have real result in rreg */ 
    17971885        retregs = *pretregs & ~mPSW; 
    17981886  } 
    17991887  if (forccs)                           /* if return result in flags    */ 
    18001888        c = cat(c,tstresult(retregs,tym,forregs)); 
    18011889  return c; 
    18021890} 
    18031891 
    18041892 
    18051893/******************************** 
    18061894 * Generate code sequence to call C runtime library support routine. 
    18071895 *      clib = CLIBxxxx 
    18081896 *      keepmask = mask of registers not to destroy. Currently can 
    18091897 *              handle only 1. Should use a temporary rather than 
    18101898 *              push/pop for speed. 
    18111899 */ 
    18121900 
    18131901int clib_inited = 0;            // != 0 if initialized 
    18141902 
    18151903code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask) 
    1816 { code *c,*cpop; 
    1817   regm_t retregs; 
    1818   symbol *s; 
    1819   int i; 
    1820  
     1904
    18211905#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    18221906  static symbol lib[] = 
    18231907  { 
    18241908/* Convert destroyed regs into saved regs       */ 
    18251909#define Z(desregs)      (~(desregs) & (mBP| mES | ALLREGS)) 
    18261910#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    18271911#define N(name) "_" name 
    18281912#else 
    18291913#define N(name) name 
    18301914#endif 
    18311915 
    18321916/* Shorthand to map onto SYMBOLY()              */ 
    18331917#define Y(desregs,name)  SYMBOLY(FLfunc,Z(desregs),N(name),0) 
    18341918 
    18351919    Y(0,"_LCMP__"),                     // CLIBlcmp 
    18361920    Y(mAX|mCX|mDX,"_LMUL__"),           // CLIBlmul 
    18371921#if 1 
    18381922    Y(mAX|mBX|mCX|mDX,"_LDIV__"),       // CLIBldiv 
    18391923    Y(mAX|mBX|mCX|mDX,"_LDIV__"),       // CLIBlmod 
    18401924    Y(mAX|mBX|mCX|mDX,"_ULDIV__"),      // CLIBuldiv 
     
    20722156    {mAX,mAX,0,2},                      // _DBLINT87@   dblint87 
    20732157    {mDX|mAX,mAX,0,2},                  // _DBLLNG87@   dbllng87 
    20742158    {0,0,0,2},                          // _FTST@ 
    20752159    {mPSW,mPSW,0,INFfloat,0,2},         // _FCOMPP@ 
    20762160    {mPSW,mPSW,0,2},                    // _FTEST@ 
    20772161    {mPSW,mPSW,0,2},                    // _FTEST0@ 
    20782162    {mST0,mST0,0,INFfloat,1,1},         // _FDIV@ 
    20792163 
    20802164    {mST01,mST01,0,INF32|INFfloat,3,5}, // _Cmul 
    20812165    {mST01,mST01,0,INF32|INFfloat,0,2}, // _Cdiv 
    20822166    {mPSW, mPSW, 0,INF32|INFfloat,0,4}, // _Ccmp 
    20832167 
    20842168    {mST0,mST0,0,INF32|INFfloat,2,1},   // _U64_LDBL 
    20852169    {0,mDX|mAX,0,INF32|INFfloat,1,2},   // __LDBLULLNG 
    20862170  }; 
    20872171 
    20882172  if (!clib_inited)                             /* if not initialized   */ 
    20892173  { 
    20902174        assert(sizeof(lib) / sizeof(lib[0]) == CLIBMAX); 
    20912175        assert(sizeof(info) / sizeof(info[0]) == CLIBMAX); 
    2092         for (i = 0; i < CLIBMAX; i++) 
     2176        for (int i = 0; i < CLIBMAX; i++) 
    20932177        {   lib[i].Stype = tsclib; 
    20942178#if MARS 
    20952179            lib[i].Sxtrnnum = 0; 
    20962180            lib[i].Stypidx = 0; 
    20972181#endif 
    20982182        } 
    20992183 
    2100         if (I32
     2184        if (!I16
    21012185        {   /* Adjust table for 386     */ 
    21022186            lib[CLIBdbllng].Sregsaved  = Z(DOUBLEREGS_32); 
    21032187            lib[CLIBlngdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21042188            lib[CLIBdblint].Sregsaved  = Z(DOUBLEREGS_32); 
    21052189            lib[CLIBintdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21062190#if TARGET_WINDOS 
    21072191            lib[CLIBfneg].Sregsaved    = Z(FLOATREGS_32); 
    21082192            lib[CLIBdneg].Sregsaved    = Z(DOUBLEREGS_32); 
    21092193            lib[CLIBdbluns].Sregsaved  = Z(DOUBLEREGS_32); 
    21102194            lib[CLIBunsdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21112195            lib[CLIBdblulng].Sregsaved = Z(DOUBLEREGS_32); 
    21122196            lib[CLIBulngdbl].Sregsaved = Z(DOUBLEREGS_32); 
    21132197#endif 
    21142198            lib[CLIBdblflt].Sregsaved  = Z(DOUBLEREGS_32); 
    21152199            lib[CLIBfltdbl].Sregsaved  = Z(DOUBLEREGS_32); 
    21162200 
    21172201            lib[CLIBdblllng].Sregsaved = Z(DOUBLEREGS_32); 
    21182202            lib[CLIBllngdbl].Sregsaved = Z(DOUBLEREGS_32); 
    21192203            lib[CLIBdblullng].Sregsaved = Z(DOUBLEREGS_32); 
    21202204            lib[CLIBullngdbl].Sregsaved = Z(DOUBLEREGS_32); 
    21212205        } 
    21222206        clib_inited++; 
    21232207  } 
    21242208#undef Z 
    21252209 
    21262210  assert(clib < CLIBMAX); 
    2127   s = &lib[clib]; 
     2211  symbol *s = &lib[clib]; 
    21282212  assert(I32 || !(info[clib].flags & INF32)); 
    2129   cpop = CNIL; 
    2130   c = getregs((~s->Sregsaved & (mES | mBP | ALLREGS)) & ~keepmask); // mask of regs destroyed 
     2213  code *cpop = CNIL; 
     2214  code *c = getregs((~s->Sregsaved & (mES | mBP | ALLREGS)) & ~keepmask); // mask of regs destroyed 
    21312215  keepmask &= ~s->Sregsaved; 
    2132   int npushed = 0; 
     2216    int npushed = numbitsset(keepmask); 
     2217    gensaverestore2(keepmask, &c, &cpop); 
     2218#if 0 
    21332219  while (keepmask) 
    21342220  {     unsigned keepreg; 
    21352221 
    21362222        if (keepmask & (mBP|ALLREGS)) 
    21372223        {       keepreg = findreg(keepmask & (mBP|ALLREGS)); 
    21382224                c = gen1(c,0x50 + keepreg);             /* PUSH keepreg */ 
    21392225                cpop = cat(gen1(CNIL,0x58 + keepreg),cpop);     // POP keepreg 
    21402226                keepmask &= ~mask[keepreg]; 
    21412227                npushed++; 
    21422228        } 
    21432229        if (keepmask & mES) 
    21442230        {       c = gen1(c,0x06);                       /* PUSH ES      */ 
    21452231                cpop = cat(gen1(CNIL,0x07),cpop);       /* POP ES       */ 
    21462232                keepmask &= ~mES; 
    21472233                npushed++; 
    21482234        } 
    21492235  } 
     2236#endif 
    21502237 
    21512238    c = cat(c, save87regs(info[clib].push87)); 
    2152     for (i = 0; i < info[clib].push87; i++) 
     2239    for (int i = 0; i < info[clib].push87; i++) 
    21532240        c = cat(c, push87()); 
    21542241 
    2155     for (i = 0; i < info[clib].pop87; i++) 
     2242    for (int i = 0; i < info[clib].pop87; i++) 
    21562243        pop87(); 
    21572244 
    21582245  if (config.target_cpu >= TARGET_80386 && clib == CLIBlmul && !I32) 
    21592246  {     static char lmul[] = { 
    21602247            0x66,0xc1,0xe1,0x10,        // shl  ECX,16 
    21612248            0x8b,0xcb,                  // mov  CX,BX           ;ECX = CX,BX 
    21622249            0x66,0xc1,0xe0,0x10,        // shl  EAX,16 
    21632250            0x66,0x0f,0xac,0xd0,0x10,   // shrd EAX,EDX,16      ;EAX = DX,AX 
    21642251            0x66,0xf7,0xe1,             // mul  ECX 
    21652252            0x66,0x0f,0xa4,0xc2,0x10,   // shld EDX,EAX,16      ;DX,AX = EAX 
    21662253        }; 
    21672254 
    21682255        c = genasm(c,lmul,sizeof(lmul)); 
    21692256  } 
    21702257  else 
    21712258  {     makeitextern(s); 
    21722259        int nalign = 0; 
    21732260        if (STACKALIGN == 16) 
    21742261        {   // Align the stack (assume no args on stack) 
    21752262            int npush = npushed * REGSIZE + stackpush; 
    21762263            if (npush & (STACKALIGN - 1)) 
    21772264            {   nalign = STACKALIGN - (npush & (STACKALIGN - 1)); 
    21782265                c = genc2(c,0x81,modregrm(3,5,SP),nalign); // SUB ESP,nalign 
     2266                if (I64) 
     2267                    code_orrex(c, REX_W); 
    21792268            } 
    21802269        } 
    21812270        c = gencs(c,(LARGECODE) ? 0x9A : 0xE8,0,FLfunc,s);      // CALL s 
    21822271        if (nalign) 
    2183             c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign 
     2272        {   c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign 
     2273            if (I64) 
     2274                code_orrex(c, REX_W); 
     2275        } 
    21842276        calledafunc = 1; 
    21852277 
    2186         if (!I32 &&                                     // bug in Optlink 
     2278        if (I16 &&                                   // bug in Optlink for weak references 
    21872279            config.flags3 & CFG3wkfloat && 
    21882280            (info[clib].flags & (INFfloat | INFwkdone)) == INFfloat) 
    21892281        {   info[clib].flags |= INFwkdone; 
    21902282            makeitextern(rtlsym[RTLSYM_INTONLY]); 
    21912283            obj_wkext(s,rtlsym[RTLSYM_INTONLY]); 
    21922284        } 
    2193  
    2194   if (!I32
     2285   
     2286    if (I16
    21952287        stackpush -= info[clib].pop; 
    2196   retregs = I32 ? info[clib].retregs32 : info[clib].retregs16
    2197   return cat(cat(c,cpop),fixresult(e,retregs,pretregs)); 
     2288    regm_t retregs = I16 ? info[clib].retregs16 : info[clib].retregs32
     2289    return cat(cat(c,cpop),fixresult(e,retregs,pretregs)); 
    21982290} 
    21992291 
    22002292 
    22012293/******************************* 
    22022294 * Generate code sequence for function call. 
    22032295 */ 
    22042296 
    22052297code *cdfunc(elem *e,regm_t *pretregs) 
    22062298{ unsigned numpara = 0; 
    22072299  unsigned stackpushsave; 
    22082300  unsigned preg; 
    22092301  regm_t keepmsk; 
    22102302  unsigned numalign = 0; 
    22112303  code *c; 
    22122304 
    22132305  //printf("cdfunc()\n"); elem_print(e); 
    22142306  assert(e); 
    22152307  stackpushsave = stackpush;            /* so we can compute # of parameters */ 
    22162308  cgstate.stackclean++; 
    22172309  c = CNIL; 
    22182310  keepmsk = 0; 
    22192311  if (OTbinary(e->Eoper))               // if parameters 
    22202312  {     unsigned stackalign = REGSIZE; 
    2221         elem *ep; 
    22222313        elem *en; 
    22232314        regm_t retregs; 
    2224         tym_t tyf; 
    2225  
    2226         if (I32) 
     2315 
     2316        if (!I16) 
    22272317        { 
    2228             tyf = tybasic(e->E1->Ety); 
     2318            tym_t tyf = tybasic(e->E1->Ety); 
    22292319 
    22302320            // First compute numpara, the total pushed on the stack 
    22312321            switch (tyf) 
    22322322            {   case TYf16func: 
    22332323                    stackalign = 2; 
    22342324                    goto Ldefault; 
    22352325                case TYmfunc: 
    22362326                case TYjfunc: 
    22372327                    // last parameter goes into register 
     2328                    elem *ep; 
    22382329                    for (ep = e->E2; ep->Eoper == OPparam; ep = ep->E2) 
    22392330                    { 
    22402331                        numpara += paramsize(ep->E1,stackalign); 
    22412332                    } 
    22422333                    if (tyf == TYjfunc && 
    22432334                        // This must match type_jparam() 
    22442335                        !(tyjparam(ep->Ety) || 
    22452336                          ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 
    22462337                         ) 
    22472338                        ) 
    22482339                    { 
    22492340                        numpara += paramsize(ep,stackalign); 
    22502341                    } 
    22512342                    break; 
    22522343                default: 
    22532344                Ldefault: 
    22542345                    numpara += paramsize(e->E2,stackalign); 
    22552346                    break; 
    22562347            } 
    22572348            assert((numpara & (REGSIZE - 1)) == 0); 
    22582349            assert((stackpush & (REGSIZE - 1)) == 0); 
    22592350 
    22602351            /* Adjust start of the stack so after all args are pushed, 
    22612352             * the stack will be aligned. 
    22622353             */ 
    22632354            if (STACKALIGN == 16 && (numpara + stackpush) & (STACKALIGN - 1)) 
    22642355            { 
    22652356                numalign = STACKALIGN - ((numpara + stackpush) & (STACKALIGN - 1)); 
    22662357                c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 
     2358                if (I64) 
     2359                    code_orrex(c, REX_W); 
    22672360                c = genadjesp(c, numalign); 
    22682361                stackpush += numalign; 
    22692362                stackpushsave += numalign; 
    22702363            } 
    22712364 
    22722365            switch (tyf) 
    22732366            {   case TYf16func: 
    22742367                    stackalign = 2; 
    22752368                    break; 
    22762369                case TYmfunc:   // last parameter goes into ECX 
    22772370                    preg = CX; 
    22782371                    goto L1; 
    22792372                case TYjfunc:   // last parameter goes into EAX 
    22802373                    preg = AX; 
    22812374                    goto L1; 
    22822375 
    22832376                L1: 
     2377                    elem *ep; 
    22842378                    for (ep = e->E2; ep->Eoper == OPparam; ep = en) 
    22852379                    { 
    22862380                        c = cat(c,params(ep->E1,stackalign)); 
    22872381                        en = ep->E2; 
    22882382                        freenode(ep); 
    22892383                        ep = en; 
    22902384                    } 
    22912385                    if (tyf == TYjfunc && 
    22922386                        // This must match type_jparam() 
    22932387                        !(tyjparam(ep->Ety) || 
    22942388                          ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 
    22952389                         ) 
    22962390                        ) 
    22972391                    { 
    22982392                        c = cat(c,params(ep,stackalign)); 
    22992393                        goto Lret; 
    23002394                    } 
    2301                     keepmsk = mask[preg]; 
     2395                    // preg is the register to put the parameter ep in 
     2396                    keepmsk = mask[preg];       // don't change preg when evaluating func address 
    23022397                    retregs = keepmsk; 
    23032398                    if (ep->Eoper == OPstrthis) 
    2304                     {   code *c1; 
    2305                         code *c2; 
    2306                         unsigned np; 
    2307  
    2308                         c1 = getregs(retregs); 
     2399                    {   code *c2; 
     2400 
     2401                        code *c1 = getregs(retregs); 
    23092402                        // LEA preg,np[ESP] 
    2310                         np = stackpush - ep->EV.Vuns;   // stack delta to parameter 
    2311                         c2 = genc1(CNIL,0x8D,modregrm(2,preg,4),FLconst,np); 
    2312                         c2->Isib = modregrm(0,4,SP); 
     2403                        unsigned np = stackpush - ep->EV.Vuns;   // stack delta to parameter 
     2404                        c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregrm(2,preg,4),FLconst,np); 
     2405                        if (I64) 
     2406                            code_orrex(c2, REX_W); 
    23132407                        c = cat3(c,c1,c2); 
    23142408                    } 
    23152409                    else 
    23162410                    {   code *cp = codelem(ep,&retregs,FALSE); 
    23172411                        c = cat(c,cp); 
    23182412                    } 
    23192413                    goto Lret; 
    23202414            } 
    23212415        } 
    23222416        c = cat(c, params(e->E2,stackalign));   // push parameters 
    23232417    } 
    23242418    else 
    23252419    { 
    23262420        /* Adjust start of the stack so 
    23272421         * the stack will be aligned. 
    23282422         */ 
    23292423        if (STACKALIGN == 16 && (stackpush) & (STACKALIGN - 1)) 
    23302424        { 
    23312425            numalign = STACKALIGN - ((stackpush) & (STACKALIGN - 1)); 
    23322426            c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 
     2427            if (I64) 
     2428                code_orrex(c, REX_W); 
    23332429            c = genadjesp(c, numalign); 
    23342430            stackpush += numalign; 
    23352431            stackpushsave += numalign; 
    23362432        } 
    23372433 
    23382434    } 
    23392435Lret: 
    23402436    cgstate.stackclean--; 
    2341     if (I32
     2437    if (!I16
    23422438    { 
    23432439        if (numpara != stackpush - stackpushsave) 
    23442440            printf("numpara = %d, stackpush = %d, stackpushsave = %d\n", numpara, stackpush, stackpushsave); 
    23452441        assert(numpara == stackpush - stackpushsave); 
    23462442    } 
    23472443    else 
    23482444        numpara = stackpush - stackpushsave; 
    23492445    return cat(c,funccall(e,numpara,numalign,pretregs,keepmsk)); 
    23502446} 
    23512447 
    23522448/*********************************** 
    23532449 */ 
    23542450 
    23552451code *cdstrthis(elem *e,regm_t *pretregs) 
    23562452{ 
    23572453    code *c1; 
    23582454    code *c2; 
    2359     unsigned np; 
    2360     unsigned reg; 
    23612455 
    23622456    assert(tysize(e->Ety) == REGSIZE); 
    2363     reg = findreg(*pretregs & allregs); 
     2457    unsigned reg = findreg(*pretregs & allregs); 
    23642458    c1 = getregs(mask[reg]); 
    23652459    // LEA reg,np[ESP] 
    2366     np = stackpush - e->EV.Vuns;        // stack delta to parameter 
    2367     c2 = genc1(CNIL,0x8D,modregrm(2,reg,4),FLconst,np); 
    2368     c2->Isib = modregrm(0,4,SP); 
     2460    unsigned np = stackpush - e->EV.Vuns;        // stack delta to parameter 
     2461    c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregxrm(2,reg,4),FLconst,np); 
     2462    if (I64) 
     2463        code_orrex(c2, REX_W); 
    23692464    return cat3(c1,c2,fixresult(e,mask[reg],pretregs)); 
    23702465} 
    23712466 
    23722467/****************************** 
    23732468 * Call function. All parameters are pushed onto the stack, numpara gives 
    23742469 * the size of them all. 
    23752470 */ 
    23762471 
    23772472STATIC code * funccall(elem *e,unsigned numpara,unsigned numalign,regm_t *pretregs,regm_t keepmsk) 
    23782473{ 
    23792474    elem *e1; 
    23802475    code *c,*ce,cs; 
    23812476    tym_t tym1; 
    23822477    char farfunc; 
    23832478    regm_t retregs; 
    23842479    symbol *s; 
    23852480 
    23862481    //printf("funccall(e = %p, *pretregs = x%x, numpara = %d, numalign = %d)\n",e,*pretregs,numpara,numalign); 
    23872482    calledafunc = 1; 
    23882483    /* Determine if we need frame for function prolog/epilog    */ 
     
    24082503        if (s->Sflags & SFLexit) 
    24092504            c = NULL; 
    24102505        else 
    24112506            c = save87();               // assume 8087 regs are all trashed 
    24122507        if (s->Sflags & SFLexit) 
    24132508            // Function doesn't return, so don't worry about registers 
    24142509            // it may use 
    24152510            c1 = NULL; 
    24162511        else if (!tyfunc(s->ty()) || !(config.flags4 & CFG4optimized)) 
    24172512            // so we can replace func at runtime 
    24182513            c1 = getregs(~fregsaved & (mBP | ALLREGS | mES)); 
    24192514        else 
    24202515            c1 = getregs(~s->Sregsaved & (mBP | ALLREGS | mES)); 
    24212516        if (strcmp(s->Sident,"alloca") == 0) 
    24222517        { 
    24232518#if 1 
    24242519            s = rtlsym[RTLSYM_ALLOCA]; 
    24252520            makeitextern(s); 
    24262521            c1 = cat(c1,getregs(mCX)); 
    24272522            c1 = genc(c1,0x8D,modregrm(2,CX,BPRM),FLallocatmp,0,0,0);  // LEA CX,&localsize[BP] 
     2523            if (I64) 
     2524                code_orrex(c1, REX_W); 
    24282525            usedalloca = 2;             // new way 
    24292526#else 
    24302527            usedalloca = 1;             // old way 
    24312528#endif 
    24322529        } 
    24332530        if (sytab[s->Sclass] & SCSS)    // if function is on stack (!) 
    24342531        { 
    24352532            retregs = allregs & ~keepmsk; 
    24362533            s->Sflags &= ~GTregcand; 
    24372534            s->Sflags |= SFLread; 
    24382535            ce = cat(c1,cdrelconst(e1,&retregs)); 
    24392536            if (farfunc) 
    24402537                goto LF1; 
    24412538            else 
    24422539                goto LF2; 
    24432540        } 
    24442541        else 
    24452542        {   int fl; 
    24462543 
    24472544            fl = FLfunc; 
     
    24622559                ce = gen1(ce, 0x90);            // NOP 
    24632560                code_orflag(ce, CFvolatile);    // don't schedule it 
    24642561            } 
    24652562#endif 
    24662563        } 
    24672564        ce = cat(c1,ce); 
    24682565  } 
    24692566  else 
    24702567  {     /* Call function via pointer    */ 
    24712568        elem *e11; 
    24722569        tym_t e11ty; 
    24732570 
    24742571#ifdef DEBUG 
    24752572        if (e1->Eoper != OPind 
    24762573                ) { WRFL((enum FL)el_fl(e1)); WROP(e1->Eoper); } 
    24772574#endif 
    24782575        c = save87();                   // assume 8087 regs are all trashed 
    24792576        assert(e1->Eoper == OPind); 
    24802577        e11 = e1->E1; 
    24812578        e11ty = tybasic(e11->Ety); 
    2482         assert(I32 || (e11ty == (farfunc ? TYfptr : TYnptr))); 
     2579        assert(!I16 || (e11ty == (farfunc ? TYfptr : TYnptr))); 
    24832580 
    24842581        /* if we can't use loadea()     */ 
    24852582        if ((EOP(e11) || e11->Eoper == OPconst) && 
    24862583            (e11->Eoper != OPind || e11->Ecount)) 
    24872584        { 
    24882585            unsigned reg; 
    24892586 
    24902587            retregs = allregs & ~keepmsk; 
    24912588            cgstate.stackclean++; 
    24922589            ce = scodelem(e11,&retregs,keepmsk,TRUE); 
    24932590            cgstate.stackclean--; 
    24942591            /* Kill registers destroyed by an arbitrary function call */ 
    24952592            ce = cat(ce,getregs((mBP | ALLREGS | mES) & ~fregsaved)); 
    24962593            if (e11ty == TYfptr) 
    24972594            {   unsigned lsreg; 
    24982595             LF1: 
    24992596                reg = findregmsw(retregs); 
    25002597                lsreg = findreglsw(retregs); 
    25012598                floatreg = TRUE;                /* use float register   */ 
    25022599                reflocal = TRUE; 
    25032600                ce = genc1(ce,0x89,             /* MOV floatreg+2,reg   */ 
    25042601                        modregrm(2,reg,BPRM),FLfltreg,REGSIZE); 
    25052602                genc1(ce,0x89,                  /* MOV floatreg,lsreg   */ 
    25062603                        modregrm(2,lsreg,BPRM),FLfltreg,0); 
    25072604                if (tym1 == TYifunc) 
    25082605                    gen1(ce,0x9C);              // PUSHF 
    25092606                genc1(ce,0xFF,                  /* CALL [floatreg]      */ 
    25102607                        modregrm(2,3,BPRM),FLfltreg,0); 
    25112608            } 
    25122609            else 
    25132610            { 
    25142611             LF2: 
    25152612                reg = findreg(retregs); 
    2516                 ce = gen2(ce,0xFF,modregrm(3,2,reg));   /* CALL reg     */ 
     2613                ce = gen2(ce,0xFF,modregrmx(3,2,reg));   /* CALL reg     */ 
    25172614            } 
    25182615        } 
    25192616        else 
    25202617        { 
    25212618            if (tym1 == TYifunc) 
    25222619                c = gen1(c,0x9C);               // PUSHF 
    25232620                                                // CALL [function] 
    25242621            cs.Iflags = 0; 
    25252622            cgstate.stackclean++; 
    25262623            ce = loadea(e11,&cs,0xFF,farfunc ? 3 : 2,0,keepmsk,(ALLREGS|mES|mBP) & ~fregsaved); 
    25272624            cgstate.stackclean--; 
    25282625            freenode(e11); 
    25292626        } 
    25302627        s = NULL; 
    25312628  } 
    25322629  c = cat(c,ce); 
    25332630  freenode(e1); 
    25342631 
    25352632  /* See if we will need the frame pointer. 
    25362633     Calculate it here so we can possibly use BP to fix the stack. 
     
    26782775  symbol *s; 
    26792776  int fl; 
    26802777 
    26812778  //printf("params(e = %p, stackalign = %d)\n", e, stackalign); 
    26822779  cp = NULL; 
    26832780  stackchanged = 1; 
    26842781  assert(e); 
    26852782  while (e->Eoper == OPparam)           /* if more params               */ 
    26862783  { 
    26872784        e2 = e->E2; 
    26882785        cp = cat(cp,params(e->E1,stackalign));  // push them backwards 
    26892786        freenode(e); 
    26902787        e = e2; 
    26912788  } 
    26922789  //printf("params()\n"); elem_print(e); 
    26932790 
    26942791  tym = tybasic(e->Ety); 
    26952792  if (tyfloating(tym)) 
    26962793        obj_fltused(); 
    26972794 
     2795  int grex = I64 ? REX_W << 16 : 0; 
     2796 
    26982797  /* sz = number of bytes pushed        */ 
    26992798  if (tyscalar(tym)) 
    27002799        szb = size(tym); 
    27012800  else if (tym == TYstruct) 
    27022801        szb = e->Enumbytes; 
    27032802  else 
    27042803  { 
    27052804#ifdef DEBUG 
    27062805        WRTYxx(tym); 
    27072806#endif 
    27082807        assert(0); 
    27092808  } 
    27102809  sz = align(stackalign,szb);           /* align on word stack boundary */ 
    27112810  assert((sz & (stackalign - 1)) == 0); /* ensure that alignment worked */ 
    27122811  assert((sz & (REGSIZE - 1)) == 0); 
    27132812 
    27142813  c = CNIL; 
    27152814  cs.Iflags = 0; 
    27162815  cs.Irex = 0; 
    27172816  switch (e->Eoper) 
    27182817  { 
    27192818#if SCPP 
    27202819    case OPstrctor: 
    27212820    { 
    27222821        e1 = e->E1; 
    27232822        c = docommas(&e1);              /* skip over any comma expressions */ 
    27242823 
    2725         c = genc2(c,0x81,modregrm(3,5,SP),sz); /* SUB SP,sizeof(struct) */ 
     2824        c = genc2(c,0x81,grex | modregrm(3,5,SP),sz); // SUB SP,sizeof(struct) 
    27262825        stackpush += sz; 
    27272826        genadjesp(c,sz); 
    27282827 
    27292828        // Find OPstrthis and set it to stackpush 
    27302829        exp2_setstrthis(e1,NULL,stackpush,NULL); 
    27312830 
    27322831        retregs = 0; 
    27332832        ce = codelem(e1,&retregs,TRUE); 
    27342833        goto L2; 
    27352834    } 
    27362835    case OPstrthis: 
    27372836        // This is the parameter for the 'this' pointer corresponding to 
    27382837        // OPstrctor. We push a pointer to an object that was already 
    27392838        // allocated on the stack by OPstrctor. 
    27402839    {   unsigned np; 
    27412840 
    27422841        retregs = allregs; 
    27432842        c = allocreg(&retregs,&reg,TYoffset); 
    27442843        c = genregs(c,0x89,SP,reg);             // MOV reg,SP 
     2844        if (I64) 
     2845            code_orrex(c, REX_W); 
    27452846        np = stackpush - e->EV.Vuns;            // stack delta to parameter 
    2746         c = genc2(c,0x81,modregrm(3,0,reg),np); // ADD reg,np 
     2847        c = genc2(c,0x81,grex | modregrmx(3,0,reg),np); // ADD reg,np 
    27472848        if (sz > REGSIZE) 
    27482849        {   c = gen1(c,0x16);                   // PUSH SS 
    27492850            stackpush += REGSIZE; 
    27502851        } 
    2751         c = gen1(c,0x50 + reg);                 // PUSH reg 
     2852        c = gen1(c,0x50 + (reg & 7));           // PUSH reg 
     2853        if (reg & 8) 
     2854            code_orrex(c, REX_B); 
    27522855        stackpush += REGSIZE; 
    27532856        genadjesp(c,sz); 
    27542857        ce = CNIL; 
    27552858        goto L2; 
    27562859    } 
    27572860#endif 
    27582861    case OPstrpar: 
    27592862        {       code *cc,*c1,*c2,*c3; 
    27602863                unsigned rm; 
    27612864                unsigned seg;           // segment override prefix flags 
    27622865                bool doneoff; 
    27632866                unsigned pushsize = REGSIZE; 
    27642867                unsigned op16 = 0; 
    27652868                unsigned npushes; 
    27662869 
    27672870                e1 = e->E1; 
    27682871                if (sz == 0) 
    27692872                { 
    27702873                    ce = docommas(&e1); /* skip over any commas         */ 
    27712874                    goto L2; 
    27722875                } 
    27732876                if ((sz & 3) == 0 && (sz / REGSIZE) <= 4 && e1->Eoper == OPvar) 
    27742877                {   freenode(e); 
    27752878                    e = e1; 
    27762879                    goto L1; 
    27772880                } 
    27782881                cc = docommas(&e1);     /* skip over any commas         */ 
    27792882                seg = 0;                /* assume no seg override       */ 
    27802883                retregs = sz ? IDXREGS : 0; 
    27812884                doneoff = FALSE; 
    2782                 if (I32 && sz & 2)      /* if odd number of words to push */ 
     2885                if (!I16 && sz & 2)     // if odd number of words to push 
    27832886                {   pushsize = 2; 
    27842887                    op16 = 1; 
    27852888                } 
    2786                 else if (!I32 && config.target_cpu >= TARGET_80386 && (sz & 3) == 0) 
     2889                else if (I16 && config.target_cpu >= TARGET_80386 && (sz & 3) == 0) 
    27872890                {   pushsize = 4;       // push DWORDs at a time 
    27882891                    op16 = 1; 
    27892892                } 
    27902893                npushes = sz / pushsize; 
    27912894                switch (e1->Eoper) 
    27922895                {   case OPind: 
    27932896                        if (sz) 
    27942897                        {   switch (tybasic(e1->E1->Ety)) 
    27952898                            { 
    27962899                                case TYfptr: 
    27972900                                case TYhptr: 
    27982901                                    seg = CFes; 
    27992902                                    retregs |= mES; 
    28002903                                    break; 
    28012904                                case TYsptr: 
    28022905                                    if (config.wflags & WFssneds) 
    28032906                                        seg = CFss; 
    28042907                                    break; 
    28052908                                case TYcptr: 
    28062909                                    seg = CFcs; 
     
    28502953                        /* Reverse the effect of the previous add       */ 
    28512954                        if (doneoff) 
    28522955                                e1->EV.sp.Voffset -= sz - pushsize; 
    28532956                        freenode(e1); 
    28542957                        break; 
    28552958                    case OPstreq: 
    28562959                    //case OPcond: 
    28572960                        if (!(config.exe & EX_flat)) 
    28582961                        {   seg = CFes; 
    28592962                            retregs |= mES; 
    28602963                        } 
    28612964                        c1 = codelem(e1,&retregs,FALSE); 
    28622965                        break; 
    28632966                    default: 
    28642967#ifdef DEBUG 
    28652968                        elem_print(e1); 
    28662969#endif 
    28672970                        assert(0); 
    28682971                } 
    28692972                reg = findreglsw(retregs); 
    2870                 rm = I32 ? regtorm32[reg] : regtorm[reg]; 
     2973                rm = I16 ? regtorm[reg] : regtorm32[reg]; 
    28712974                if (op16) 
    28722975                    seg |= CFopsize;            // operand size 
    28732976                if (npushes <= 4) 
    28742977                { 
    28752978                    assert(!doneoff); 
    28762979                    for (c2 = CNIL; npushes > 1; npushes--) 
    2877                     {   c2 = genc1(c2,0xFF,modregrm(2,6,rm),FLconst,pushsize * (npushes - 1));  // PUSH [reg] 
     2980                    {   c2 = genc1(c2,0xFF,modregrmx(2,6,rm),FLconst,pushsize * (npushes - 1));  // PUSH [reg] 
    28782981                        code_orflag(c2,seg); 
    28792982                        genadjesp(c2,pushsize); 
    28802983                    } 
    2881                     c3 = gen2(CNIL,0xFF,modregrm(0,6,rm));      // PUSH [reg] 
     2984                    c3 = gen2(CNIL,0xFF,modregrmx(0,6,rm));     // PUSH [reg] 
    28822985                    c3->Iflags |= seg; 
    28832986                    genadjesp(c3,pushsize); 
    28842987                    ce = cat4(cc,c1,c2,c3); 
    28852988                } 
    28862989                else if (sz) 
    28872990                {   int size; 
    28882991 
    28892992                    c2 = getregs_imm(mCX | retregs); 
    28902993                                                        /* MOV CX,sz/2  */ 
    28912994                    c2 = movregconst(c2,CX,npushes,0); 
    28922995                    if (!doneoff) 
    28932996                    {   /* This disgusting thing should be done when    */ 
    28942997                        /* reg is loaded. Too lazy to fix it now.       */ 
    28952998                                                        /* ADD reg,sz-2 */ 
    2896                         c2 = genc2(c2,0x81,modregrm(3,0,reg),sz-pushsize); 
     2999                        c2 = genc2(c2,0x81,grex | modregrmx(3,0,reg),sz-pushsize); 
    28973000                    } 
    2898                     c3 = gen2(CNIL,0xFF,modregrm(0,6,rm));      // PUSH [reg] 
     3001                    c3 = gen2(CNIL,0xFF,modregrmx(0,6,rm));      // PUSH [reg] 
    28993002                    c3->Iflags |= seg | CFtarg2; 
    2900                     genc2(c3,0x81,modregrm(3,5,reg),pushsize);  // SUB reg,2 
     3003                    genc2(c3,0x81,grex | modregrmx(3,5,reg),pushsize);  // SUB reg,2 
    29013004                    size = ((seg & CFSEG) ? -8 : -7) - op16; 
    29023005                    if (code_next(c3)->Iop != 0x81) 
    29033006                        size++; 
    29043007                    //genc2(c3,0xE2,0,size);    // LOOP .-7 or .-8 
    29053008                    genjmp(c3,0xE2,FLcode,(block *)c3);         // LOOP c3 
    29063009                    regimmed_set(CX,0); 
    29073010                    genadjesp(c3,sz); 
    29083011                    ce = cat4(cc,c1,c2,c3); 
    29093012                } 
    29103013                else 
    29113014                    ce = cat(cc,c1); 
    29123015                stackpush += sz; 
    29133016                goto L2; 
    29143017        } 
    29153018    case OPind: 
    29163019        if (!e->Ecount)                         /* if *e1       */ 
    29173020        {       if (sz <= REGSIZE) 
    29183021                {   // Watch out for single byte quantities being up 
    29193022                    // against the end of a segment or in memory-mapped I/O 
    29203023                    if (!(config.exe & EX_flat) && szb == 1) 
     
    29913094        if (tysize[tym] == tysize[TYfptr] && 
    29923095            (fl = s->Sfl) != FLfardata && 
    29933096            /* not a function that CS might not be the segment of       */ 
    29943097            (!((fl == FLfunc || s->ty() & mTYcs) && 
    29953098              (s->Sclass == SCcomdat || s->Sclass == SCextern || s->Sclass == SCinline || config.wflags & WFthunk)) || 
    29963099             (fl == FLfunc && config.exe == EX_DOSX) 
    29973100            ) 
    29983101           ) 
    29993102        { 
    30003103            stackpush += sz; 
    30013104            c = gen1(c,0x06 +           /* PUSH SEGREG                  */ 
    30023105                    (((fl == FLfunc || s->ty() & mTYcs) ? 1 : segfl[fl]) << 3)); 
    30033106            c = genadjesp(c,REGSIZE); 
    30043107 
    30053108            if (config.target_cpu >= TARGET_80286 && !e->Ecount) 
    30063109            {   ce = getoffset(e,STACK); 
    30073110                goto L2; 
    30083111            } 
    30093112            else 
    30103113            {   c = cat(c,offsetinreg(e,&retregs)); 
    3011                 c = gen1(c,0x50+findreg(retregs)); /* PUSH reg          */ 
     3114                unsigned reg = findreg(retregs); 
     3115                c = genpush(c,reg);             // PUSH reg 
    30123116                genadjesp(c,REGSIZE); 
    30133117            } 
    30143118            goto ret; 
    30153119        } 
    30163120        if (config.target_cpu >= TARGET_80286 && !e->Ecount) 
    30173121        { 
    30183122            stackpush += sz; 
    30193123            if (tysize[tym] == tysize[TYfptr]) 
    3020             {   code *c1; 
    3021  
     3124            { 
    30223125                /* PUSH SEG e   */ 
    3023                 c1 = gencs(CNIL,0x68,0,FLextern,s); 
     3126                code *c1 = gencs(CNIL,0x68,0,FLextern,s); 
    30243127                c1->Iflags = CFseg; 
    30253128                genadjesp(c1,REGSIZE); 
    30263129                c = cat(c,c1); 
    30273130            } 
    30283131            ce = getoffset(e,STACK); 
    30293132            goto L2; 
    30303133        } 
    30313134#endif 
    30323135        break;                          /* else must evaluate expression */ 
    30333136    case OPvar: 
    30343137    L1: 
    30353138        if (0 && I32 && sz == 2) 
    30363139        {   /* 32 bit code, but pushing 16 bit values anyway    */ 
    30373140            ce = loadea(e,&cs,0xFF,6,0,0,0);            /* PUSH EA      */ 
    30383141            // BUG: 0x66 fails with scheduler 
    30393142            ce = cat(gen1(CNIL,0x66),ce);               /* 16 bit override */ 
    30403143            stackpush += sz; 
    30413144            genadjesp(ce,sz); 
    30423145        } 
    30433146        else if (config.flags4 & CFG4speed && 
    30443147                 (config.target_cpu >= TARGET_80486 && 
    30453148                  config.target_cpu <= TARGET_PentiumMMX) && 
    30463149                 sz <= 2 * REGSIZE && 
    30473150                 !tyfloating(tym)) 
    30483151        {   // Avoid PUSH MEM on the Pentium when optimizing for speed 
    30493152            break; 
    30503153        } 
    30513154        else 
    30523155        {   int regsize = REGSIZE; 
    30533156            unsigned flag = 0; 
    30543157 
    3055             if (!I32 && config.target_cpu >= TARGET_80386 && sz > 2 && 
     3158            if (I16 && config.target_cpu >= TARGET_80386 && sz > 2 && 
    30563159                !e->Ecount) 
    30573160            {   regsize = 4; 
    30583161                flag |= CFopsize; 
    30593162            } 
    30603163            ce = loadea(e,&cs,0xFF,6,sz - regsize,RMload,0);    // PUSH EA+sz-2 
    30613164            code_orflag(ce,flag); 
    30623165            ce = genadjesp(ce,REGSIZE); 
    30633166            stackpush += sz; 
    30643167            while ((targ_int)(sz -= regsize) > 0) 
    30653168            {   ce = cat(ce,loadea(e,&cs,0xFF,6,sz - regsize,RMload,0)); 
    30663169                code_orflag(ce,flag); 
    30673170                ce = genadjesp(ce,REGSIZE); 
    30683171            } 
    30693172        } 
    30703173    L2: 
    30713174        freenode(e); 
    30723175        c = cat(c,ce); 
    30733176        goto ret; 
    30743177    case OPconst: 
    30753178    {   targ_int *pi; 
     
    30913194            ce = genadjesp(NULL,sz); 
    30923195            for (i = 2; i >= 0; i--) 
    30933196            { 
    30943197                if (reghasvalue(allregs, value, &reg)) 
    30953198                    ce = gen1(ce,0x50 + reg);           // PUSH reg 
    30963199                else 
    30973200                    ce = genc2(ce,0x68,0,value);        // PUSH value 
    30983201                value = ((unsigned *)&e->EV.Vldouble)[i - 1]; 
    30993202            } 
    31003203            goto L2; 
    31013204        } 
    31023205 
    31033206        assert(sz <= LNGDBLSIZE); 
    31043207        i = sz; 
    31053208        if (I32 && i == 2) 
    31063209            flag = CFopsize; 
    31073210 
    31083211        if (config.target_cpu >= TARGET_80286) 
    31093212//       && (e->Ecount == 0 || e->Ecount != e->Ecomsub)) 
    31103213        {   pushi = 1; 
    3111             if (!I32 && config.target_cpu >= TARGET_80386 && i >= 4) 
     3214            if (I16 && config.target_cpu >= TARGET_80386 && i >= 4) 
    31123215            {   regsize = 4; 
    31133216                flag = CFopsize; 
    31143217            } 
    31153218        } 
    31163219        else if (i == REGSIZE) 
    31173220            break; 
    31183221 
    31193222        stackpush += sz; 
    31203223        ce = genadjesp(NULL,sz); 
    31213224        pi = (targ_long *) &e->EV.Vdouble; 
    31223225        ps = (targ_short *) pi; 
    31233226        i /= regsize; 
    31243227        do 
    31253228        {   code *cp; 
    31263229 
    31273230            if (i)                      /* be careful not to go negative */ 
    31283231                i--; 
    31293232            value = (regsize == 4) ? pi[i] : ps[i]; 
    31303233            if (pushi) 
    31313234            { 
    31323235                if (regsize == REGSIZE && reghasvalue(allregs,value,&reg)) 
    31333236                    goto Preg; 
    31343237                ce = genc2(ce,(szb == 1) ? 0x6A : 0x68,0,value); // PUSH value 
    31353238            } 
    31363239            else 
    31373240            { 
    31383241                ce = regwithvalue(ce,allregs,value,&reg,0); 
    31393242            Preg: 
    3140                 ce = gen1(ce,0x50 + reg);               /* PUSH reg     */ 
     3243                ce = genpush(ce,reg);         // PUSH reg 
    31413244            } 
    31423245            code_orflag(ce,flag);                       /* operand size */ 
    31433246        } while (i); 
    31443247        goto L2; 
    31453248    } 
    31463249    default: 
    31473250        break; 
    31483251  } 
    31493252  retregs = tybyte(tym) ? BYTEREGS : allregs; 
    31503253  if (tyfloating(tym)) 
    31513254  {     if (config.inline8087) 
    31523255        {   code *c1,*c2; 
    31533256            unsigned op; 
    31543257            unsigned r; 
    31553258 
    31563259            retregs = tycomplex(tym) ? mST01 : mST0; 
    31573260            c = cat(c,codelem(e,&retregs,FALSE)); 
    31583261            stackpush += sz; 
    31593262            c = genadjesp(c,sz); 
    3160             c = genc2(c,0x81,modregrm(3,5,SP),sz);      /* SUB SP,sz    */ 
     3263            c = genc2(c,0x81,grex | modregrm(3,5,SP),sz);      // SUB SP,sz 
    31613264            switch (tym) 
    31623265            { 
    31633266                case TYfloat: 
    31643267                case TYifloat: 
    31653268                case TYcfloat: 
    31663269                    op = 0xD9; 
    31673270                    r = 3; 
    31683271                    break; 
    31693272 
    31703273                case TYdouble: 
    31713274                case TYidouble: 
    31723275                case TYdouble_alias: 
    31733276                case TYcdouble: 
    31743277                    op = 0xDD; 
    31753278                    r = 3; 
    31763279                    break; 
    31773280 
    31783281                case TYldouble: 
    31793282                case TYildouble: 
    31803283                case TYcldouble: 
    31813284                    op = 0xDB; 
    31823285                    r = 7; 
    31833286                    break; 
    31843287 
    31853288                default: 
    31863289                    assert(0); 
    31873290            } 
    3188             if (I32
     3291            if (!I16
    31893292            { 
    31903293                c1 = NULL; 
    31913294                c2 = NULL; 
    31923295                if (tycomplex(tym)) 
    31933296                { 
    31943297                    // FSTP sz/2[ESP] 
    3195                     c2 = genc1(CNIL,op,modregrm(2,r,4),FLconst,sz/2); 
    3196                     c2->Isib = modregrm(0,4,SP); 
     3298                    c2 = genc1(CNIL,op,(modregrm(0,4,SP) << 8) | modregxrm(2,r,4),FLconst,sz/2); 
    31973299                    pop87(); 
    31983300                } 
    31993301                pop87(); 
    32003302                c2 = gen2sib(c2,op,modregrm(0,r,4),modregrm(0,4,SP));   // FSTP [ESP] 
    32013303            } 
    32023304            else 
    32033305            { 
    32043306                retregs = IDXREGS;                      /* get an index reg */ 
    32053307                c1 = allocreg(&retregs,&reg,TYoffset); 
    32063308                c1 = genregs(c1,0x89,SP,reg);           /* MOV reg,SP    */ 
    32073309                pop87(); 
    32083310                c2 = gen2(CNIL,op,modregrm(0,r,regtorm[reg]));          // FSTP [reg] 
    32093311            } 
    32103312            if (LARGEDATA) 
    32113313                c2->Iflags |= CFss;     /* want to store into stack     */ 
    32123314            genfwait(c2);               // FWAIT 
    32133315            c = cat3(c,c1,c2); 
    32143316            goto ret; 
    32153317        } 
    32163318        else if (!I32 && (tym == TYdouble || tym == TYdouble_alias)) 
    32173319            retregs = mSTACK; 
    32183320  } 
    32193321#if LONGLONG 
    32203322  else if (!I32 && sz == 8)             // if long long 
    32213323        retregs = mSTACK; 
    32223324#endif 
    32233325  c = cat(c,scodelem(e,&retregs,0,TRUE)); 
    32243326  if (retregs != mSTACK)                /* if stackpush not already inc'd */ 
    32253327      stackpush += sz; 
    32263328  if (sz <= REGSIZE) 
    32273329  { 
    3228         c = gen1(c,0x50+findreg(retregs));      /* PUSH reg             */ 
     3330        c = genpush(c,findreg(retregs));        // PUSH reg 
    32293331        genadjesp(c,REGSIZE); 
    32303332  } 
    32313333  else if (sz == REGSIZE * 2) 
    3232   {     c = gen1(c,0x50+findregmsw(retregs)); /* PUSH msreg             */ 
    3233         gen1(c,0x50+findreglsw(retregs));         /* PUSH lsreg         */ 
     3334  {     c = genpush(c,findregmsw(retregs));     // PUSH msreg 
     3335        genpush(c,findreglsw(retregs));         // PUSH lsreg 
    32343336        genadjesp(c,sz); 
    32353337  } 
    32363338ret: 
    32373339  return cat(cp,c); 
    32383340} 
    32393341 
    32403342 
    32413343/******************************* 
    32423344 * Get offset portion of e, and store it in an index 
    32433345 * register. Return mask of index register in *pretregs. 
    32443346 */ 
    32453347 
    32463348code *offsetinreg( elem *e, regm_t *pretregs) 
    32473349{   regm_t retregs; 
    32483350    code *c; 
    32493351    unsigned reg; 
    32503352 
    32513353    retregs = mLSW;                     /* want only offset     */ 
    32523354    if (e->Ecount && e->Ecount != e->Ecomsub) 
    32533355    {   unsigned i; 
     
    33033405        if (config.inline8087) 
    33043406        {   if (*pretregs & mST0) 
    33053407                return load87(e,0,pretregs,NULL,-1); 
    33063408            else if (tycomplex(tym)) 
    33073409                return cload87(e, pretregs); 
    33083410        } 
    33093411  } 
    33103412  sz = tysize[tym]; 
    33113413  cs.Iflags = 0; 
    33123414  cs.Irex = 0; 
    33133415  if (*pretregs == mPSW) 
    33143416  { 
    33153417        regm = allregs; 
    33163418        if (e->Eoper == OPconst) 
    33173419        {       /* TRUE:        OR SP,SP        (SP is never 0)         */ 
    33183420                /* FALSE:       CMP SP,SP       (always equal)          */ 
    33193421                c = genregs(CNIL,(boolres(e)) ? 0x09 : 0x39,SP,SP); 
    33203422        } 
    33213423        else if (sz <= REGSIZE) 
    33223424        { 
    3323             if (I32 && (tym == TYfloat || tym == TYifloat)) 
     3425            if (!I16 && (tym == TYfloat || tym == TYifloat)) 
    33243426            {   c = allocreg(&regm,&reg,TYoffset);      /* get a register */ 
    33253427                ce = loadea(e,&cs,0x8B,reg,0,0,0);      // MOV reg,data 
    33263428                c = cat(c,ce); 
    3327                 ce = gen2(CNIL,0xD1,modregrm(3,4,reg)); /* SHL reg,1      */ 
     3429                ce = gen2(CNIL,0xD1,modregrmx(3,4,reg)); /* SHL reg,1      */ 
    33283430                c = cat(c,ce); 
    33293431            } 
    33303432            else 
    33313433            {   cs.IFL2 = FLconst; 
    33323434                cs.IEV2.Vint = 0; 
    33333435                op = (sz == 1) ? 0x80 : 0x81; 
    33343436                c = loadea(e,&cs,op,7,0,0,0);           /* CMP EA,0     */ 
    33353437 
    33363438                // Convert to TEST instruction if EA is a register 
    33373439                // (to avoid register contention on Pentium) 
    33383440                if ((c->Iop & 0xFE) == 0x38 && 
    33393441                    (c->Irm & modregrm(3,0,0)) == modregrm(3,0,0) 
    33403442                   ) 
    33413443                {   c->Iop = (c->Iop & 1) | 0x84; 
    3342                     c->Irm = (c->Irm & modregrm(3,0,7)) | modregrm(0,c->Irm & 7,0); 
     3444                    code_newreg(c, c->Irm & 7); 
     3445                    if (c->Irex & REX_B) 
     3446                        c->Irex = (c->Irex & ~REX_B) | REX_R; 
    33433447                } 
    33443448            } 
    33453449        } 
    33463450        else if (sz < 8) 
    33473451        { 
    33483452            c = allocreg(&regm,&reg,TYoffset);          /* get a register */ 
    33493453            if (I32)                                    // it's a 48 bit pointer 
    33503454                ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 
    33513455            else 
    33523456            {   ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 
    33533457                if (tym == TYfloat || tym == TYifloat)  // dump sign bit 
    33543458                    gen2(ce,0xD1,modregrm(3,4,reg));    /* SHL reg,1      */ 
    33553459            } 
    33563460            c = cat(c,ce); 
    33573461            ce = loadea(e,&cs,0x0B,reg,0,regm,0);       /* OR reg,data */ 
    33583462            c = cat(c,ce); 
    33593463        } 
    33603464        else if (sz == 8) 
    33613465        {   code *c1; 
    33623466            int i; 
     
    33833487        return c; 
    33843488  } 
    33853489  /* not for flags only */ 
    33863490  flags = *pretregs & mPSW;             /* save original                */ 
    33873491  forregs = *pretregs & (mBP | ALLREGS | mES); 
    33883492  if (*pretregs & mSTACK) 
    33893493        forregs |= DOUBLEREGS; 
    33903494  if (e->Eoper == OPconst) 
    33913495  {     regm_t save; 
    33923496 
    33933497        if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,&reg)) 
    33943498            forregs = mask[reg]; 
    33953499 
    33963500        save = regcon.immed.mval; 
    33973501        c = allocreg(&forregs,&reg,tym);        /* allocate registers   */ 
    33983502        regcon.immed.mval = save;               // KLUDGE! 
    33993503        if (sz <= REGSIZE) 
    34003504        { 
    34013505            if (sz == 1) 
    34023506                flags |= 1; 
    3403             else if (I32 && sz == SHORTSIZE && 
     3507            else if (!I16 && sz == SHORTSIZE && 
    34043508                     !(mask[reg] & regcon.mvar) && 
    34053509                     !(config.flags4 & CFG4speed) 
    34063510                    ) 
    34073511                flags |= 2; 
     3512            if (sz == 8) 
     3513                flags |= 64; 
    34083514            ce = movregconst(CNIL,reg,e->EV.Vint,flags); 
    34093515            flags = 0;                          // flags are already set 
    34103516        } 
    34113517        else if (sz < 8)        // far pointers, longs for 16 bit targets 
    34123518        { 
    34133519            targ_int msw,lsw; 
    34143520            regm_t mswflags; 
    34153521 
    34163522            msw = I32   ? e->EV.Vfp.Vseg 
    34173523                        : (e->EV.Vulong >> 16); 
    34183524            lsw = e->EV.Vfp.Voff; 
    34193525            mswflags = 0; 
    34203526            if (forregs & mES) 
    34213527            { 
    34223528                ce = movregconst(CNIL,reg,msw,0);       // MOV reg,segment 
    34233529                genregs(ce,0x8E,0,reg);                 // MOV ES,reg 
    34243530                msw = lsw;                              // MOV reg,offset 
    34253531            } 
    34263532            else 
    34273533            { 
     
    34673573    { 
    34683574        reg = e->EV.sp.Vsym->Spreg; 
    34693575        forregs = mask[reg]; 
    34703576        mfuncreg &= ~forregs; 
    34713577        regcon.used |= forregs; 
    34723578        return fixresult(e,forregs,pretregs); 
    34733579    } 
    34743580 
    34753581    c = allocreg(&forregs,&reg,tym);            /* allocate registers   */ 
    34763582 
    34773583    if (sz == 1) 
    34783584    {   regm_t nregm; 
    34793585 
    34803586#ifdef DEBUG 
    34813587        if (!(forregs & BYTEREGS)) 
    34823588        {       elem_print(e); 
    34833589                printf("forregs = x%x\n",forregs); 
    34843590        } 
    34853591#endif 
    34863592        assert(forregs & BYTEREGS); 
    3487         if (I32
     3593        if (!I16
    34883594            c = cat(c,loadea(e,&cs,0x8A,reg,0,0,0));    // MOV regL,data 
    34893595        else 
    34903596        {   nregm = tyuns(tym) ? BYTEREGS : mAX; 
    34913597            if (*pretregs & nregm) 
    34923598                nreg = reg;                     /* already allocated    */ 
    34933599            else 
    34943600                c = cat(c,allocreg(&nregm,&nreg,tym)); 
    34953601            ce = loadea(e,&cs,0x8A,nreg,0,0,0); /* MOV nregL,data       */ 
    34963602            c = cat(c,ce); 
    34973603            if (reg != nreg) 
    34983604            {   genmovreg(c,reg,nreg);          /* MOV reg,nreg         */ 
    34993605                cssave(e,mask[nreg],FALSE); 
    35003606            } 
    35013607        } 
    35023608    } 
    35033609    else if (sz <= REGSIZE) 
    35043610    { 
    35053611        ce = loadea(e,&cs,0x8B,reg,0,RMload,0); // MOV reg,data 
    35063612        c = cat(c,ce); 
    35073613    } 
  • trunk/src/backend/cod2.c

    r552 r577  
    1919#include        "oper.h" 
    2020#include        "el.h" 
    2121#include        "code.h" 
    2222#include        "global.h" 
    2323#include        "type.h" 
    2424#if SCPP 
    2525#include        "exh.h" 
    2626#endif 
    2727 
    2828static char __file__[] = __FILE__;      /* for tassert.h                */ 
    2929#include        "tassert.h" 
    3030 
    3131int cdcmp_flag; 
    3232extern signed char regtorm[8]; 
    3333 
    3434/******************************** 
    3535 * Return mask of index registers used by addressing mode. 
    3636 * Index is rm of modregrm field. 
    3737 */ 
    3838 
    39 regm_t idxregm(unsigned rm,unsigned sib
     39regm_t idxregm(code *c
    4040{ 
    4141    static const unsigned char idxsib[8] = { mAX,mCX,mDX,mBX,0,mBP,mSI,mDI }; 
    4242    static const unsigned char idxrm[8] = {mBX|mSI,mBX|mDI,mSI,mDI,mSI,mDI,0,mBX}; 
    43     regm_t idxm; 
    44  
    45     idxm = 0; 
     43 
     44    unsigned rm = c->Irm; 
     45    regm_t idxm = 0; 
    4646    if ((rm & 0xC0) != 0xC0)            /* if register is not the destination */ 
    4747    { 
    48         if (I32) 
     48        if (I16) 
     49            idxm = idxrm[rm & 7]; 
     50        else 
    4951        { 
    5052            if ((rm & 7) == 4)          /* if sib byte                  */ 
    5153            { 
    52                 idxm = idxsib[(sib >> 3) & 7];  /* scaled index reg     */ 
     54                unsigned sib = c->Isib; 
     55                unsigned idxreg = (sib >> 3) & 7; 
     56                if (c->Irex & REX_X) 
     57                {   idxreg |= 8; 
     58                    idxm = mask[idxreg];  // scaled index reg 
     59                } 
     60                else 
     61                    idxm = idxsib[idxreg];  // scaled index reg 
    5362                if ((sib & 7) == 5 && (rm & 0xC0) == 0) 
    5463                    ; 
    5564                else 
    56                     idxm |= idxsib[sib & 7]; 
     65                {   unsigned base = sib & 7; 
     66                    if (c->Irex & REX_B) 
     67                        idxm |= mask[base | 8]; 
     68                    else 
     69                        idxm |= idxsib[base]; 
     70                } 
    5771            } 
    5872            else 
    59                 idxm |= idxsib[rm & 7]; 
    60         } 
    61         else 
    62             idxm = idxrm[rm & 7]; 
     73            {   unsigned base = rm & 7; 
     74                if (c->Irex & REX_B) 
     75                    idxm |= mask[base | 8]; 
     76                else 
     77                    idxm |= idxsib[base]; 
     78            } 
     79        } 
    6380    } 
    6481    return idxm; 
    6582} 
    6683 
    6784#if TARGET_WINDOS 
    6885/*************************** 
    6986 * Gen code for call to floating point routine. 
    7087 */ 
    7188 
    7289code *opdouble(elem *e,regm_t *pretregs,unsigned clib) 
    7390{ 
    7491    regm_t retregs1,retregs2; 
    7592    code *cl, *cr, *c; 
    7693 
    7794    if (config.inline8087) 
    7895        return orth87(e,pretregs); 
    7996 
    8097    if (tybasic(e->E1->Ety) == TYfloat) 
    8198    { 
    8299        clib += CLIBfadd - CLIBdadd;    /* convert to float operation   */ 
     
    95113        } 
    96114    } 
    97115    cl = codelem(e->E1, &retregs1,FALSE); 
    98116    if (retregs1 & mSTACK) 
    99117        cgstate.stackclean++; 
    100118    cr = scodelem(e->E2, &retregs2, retregs1 & ~mSTACK, FALSE); 
    101119    if (retregs1 & mSTACK) 
    102120        cgstate.stackclean--; 
    103121    c = callclib(e, clib, pretregs, 0); 
    104122    return cat3(cl, cr, c); 
    105123} 
    106124#endif 
    107125 
    108126 
    109127/***************************** 
    110128 * Handle operators which are more or less orthogonal 
    111129 * ( + - & | ^ ) 
    112130 */ 
    113131 
    114132code *cdorth(elem *e,regm_t *pretregs) 
    115 { tym_t ty,ty1,ty2
     133{ tym_t ty1
    116134  regm_t retregs,rretregs,posregs; 
    117   unsigned reg,rreg,op1,op2,mode,test,byte
     135  unsigned reg,rreg,op1,op2,mode
    118136  int rval; 
    119   code *c,*cg,*cl,*cr,cs
    120   targ_int i; 
     137  code *c,*cg,*cl
     138  targ_size_t i; 
    121139  elem *e1,*e2; 
    122140  int numwords;                         /* # of words to be operated on */ 
    123   unsigned char word;                   /* if word operands             */ 
    124   int e2oper; 
    125   unsigned sz; 
    126141  static int nest; 
    127142 
    128143  //printf("cdorth(e = %p, *pretregs = %s)\n",e,regm_str(*pretregs)); 
    129144  e1 = e->E1; 
    130145  e2 = e->E2; 
    131146  if (*pretregs == 0)                   /* if don't want result         */ 
    132147  {     c = codelem(e1,pretregs,FALSE); /* eval left leaf               */ 
    133148        *pretregs = 0;                  /* in case they got set         */ 
    134149        return cat(c,codelem(e2,pretregs,FALSE)); 
    135150  } 
    136151 
    137152  ty1 = tybasic(e1->Ety); 
    138153  if (tyfloating(ty1)) 
    139154#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    140155        return orth87(e,pretregs); 
    141156#else 
    142157        return opdouble(e,pretregs,(e->Eoper == OPadd) ? CLIBdadd 
    143158                                                       : CLIBdsub); 
    144159#endif 
    145   ty2 = tybasic(e2->Ety); 
    146   e2oper = e2->Eoper; 
    147   ty = tybasic(e->Ety); 
    148   sz = tysize[ty]; 
    149   byte = (sz == 1); 
    150   word = (I32 && sz == SHORTSIZE) ? CFopsize : 0; 
     160  tym_t ty2 = tybasic(e2->Ety); 
     161  int e2oper = e2->Eoper; 
     162  tym_t ty = tybasic(e->Ety); 
     163  unsigned sz = tysize[ty]; 
     164  unsigned byte = (sz == 1); 
     165  unsigned char word = (!I16 && sz == SHORTSIZE) ? CFopsize : 0; 
     166  unsigned test = FALSE;                // assume we destroyed lvalue 
     167  code cs; 
    151168  cs.Iflags = 0; 
    152169  cs.Irex = 0; 
    153   test = FALSE;                         /* assume we destroyed lvalue   */ 
    154   cr = CNIL;                            /* initialize                   */ 
     170  code *cr = CNIL; 
    155171 
    156172  switch (e->Eoper) 
    157173  {     case OPadd:     mode = 0; 
    158174                        op1 = 0x03; op2 = 0x13; break;  /* ADD, ADC     */ 
    159175        case OPmin:     mode = 5; 
    160176                        op1 = 0x2B; op2 = 0x1B; break;  /* SUB, SBB     */ 
    161177        case OPor:      mode = 1; 
    162178                        op1 = 0x0B; op2 = 0x0B; break;  /* OR , OR      */ 
    163179        case OPxor:     mode = 6; 
    164180                        op1 = 0x33; op2 = 0x33; break;  /* XOR, XOR     */ 
    165181        case OPand:     mode = 4; 
    166182                        op1 = 0x23; op2 = 0x23;         /* AND, AND     */ 
    167183                        if (tyreg(ty1) && 
    168184                            *pretregs == mPSW)          /* if flags only */ 
    169185                        {       test = TRUE; 
    170186                                op1 = 0x85;             /* TEST         */ 
    171187                                mode = 0; 
    172188                        } 
    173189                        break; 
    174190        default: 
    175191                assert(0); 
    176192  } 
    177193  op1 ^= byte;                                  /* if byte operation    */ 
    178194 
    179195  /* Compute number of words to operate on.                             */ 
    180196  numwords = 1; 
    181   if (I32
     197  if (!I16
    182198  {     /* Cannot operate on longs and then do a 'paint' to a far       */ 
    183199        /* pointer, because far pointers are 48 bits and longs are 32.  */ 
    184200        /* Therefore, numwords can never be 2.                          */ 
    185201        assert(!(tyfv(ty1) && tyfv(ty2))); 
    186202        if (sz == 2 * REGSIZE) 
    187203        { 
    188204            numwords++; 
    189205        } 
    190206  } 
    191207  else 
    192208  {     /* If ty is a TYfptr, but both operands are long, treat the     */ 
    193209        /* operation as a long.                                         */ 
    194210        if ((tylong(ty1) || ty1 == TYhptr) && 
    195211            (tylong(ty2) || ty2 == TYhptr)) 
    196212            numwords++; 
    197213  } 
    198214 
    199215  // Special cases where only flags are set 
    200216  if (test && tysize[ty1] <= REGSIZE && 
    201217      (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount))) 
    202218  { 
    203219        // Handle the case of (var & const) 
    204220        if (e2->Eoper == OPconst) 
    205         {   targ_int value; 
    206  
     221        { 
    207222            c = getlvalue(&cs,e1,0); 
    208             value = e2->EV.Vint
     223            targ_size_t value = e2->EV.Vpointer
    209224            if (sz == 2) 
    210225                value &= 0xFFFF; 
     226            else if (sz == 4) 
     227                value &= 0xFFFFFFFF; 
    211228            if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,&reg)) 
    212229                goto L11; 
     230            if (sz == 8) 
     231            { 
     232                assert(value == (int)value);    // sign extend imm32 
     233            } 
    213234            op1 = 0xF7; 
    214235            cs.IEV2.Vint = value; 
    215236            cs.IFL2 = FLconst; 
    216237            goto L10; 
    217238        } 
    218239 
    219240        // Handle (exp & reg) 
    220241        if (isregvar(e2,&retregs,&reg)) 
    221242        { 
    222243            c = getlvalue(&cs,e1,0); 
    223244        L11: 
    224             cs.Irm |= modregrm(0,reg,0); 
     245            code_newreg(&cs, reg); 
    225246        L10: 
    226247            cs.Iop = op1 ^ byte; 
    227248            cs.Iflags |= word | CFpsw; 
    228249            freenode(e1); 
    229250            freenode(e2); 
    230251            return gen(c,&cs); 
    231252        } 
    232253  } 
    233254 
    234255  // Look for possible uses of LEA 
    235256  if (e->Eoper == OPadd && 
    236257      !(*pretregs & mPSW) &&            /* flags aren't set by LEA      */ 
    237258      !nest &&                          // could cause infinite recursion if e->Ecount 
    238       sz == REGSIZE)                    // far pointers aren't handled 
    239   {     int e1oper; 
    240  
     259      (sz == REGSIZE || (I64 && sz == 4)))  // far pointers aren't handled 
     260  { 
    241261        // Handle the case of (e + &var) 
    242         e1oper = e1->Eoper; 
     262        int e1oper = e1->Eoper; 
    243263        if ((e2oper == OPrelconst && (config.target_cpu >= TARGET_Pentium || (!e2->Ecount && stackfl[el_fl(e2)]))) 
    244264                || // LEA costs too much for simple EAs on older CPUs 
    245265            (e2oper == OPconst && (e1->Eoper == OPcall || e1->Eoper == OPcallns) && !(*pretregs & mAX)) || 
    246             (I32 && (isscaledindex(e1) || isscaledindex(e2))) || 
    247             (I32 && e1oper == OPvar && e1->EV.sp.Vsym->Sfl == FLreg && (e2oper == OPconst || (e2oper == OPvar && e2->EV.sp.Vsym->Sfl == FLreg))) || 
     266            (!I16 && (isscaledindex(e1) || isscaledindex(e2))) || 
     267            (!I16 && e1oper == OPvar && e1->EV.sp.Vsym->Sfl == FLreg && (e2oper == OPconst || (e2oper == OPvar && e2->EV.sp.Vsym->Sfl == FLreg))) || 
    248268            (e2oper == OPconst && e1oper == OPeq && e1->E1->Eoper == OPvar) || 
    249             (I32 && e2oper == OPrelconst && !e1->Ecount && 
     269            (!I16 && e2oper == OPrelconst && !e1->Ecount && 
    250270             (e1oper == OPmul || e1oper == OPshl) && 
    251271             e1->E2->Eoper == OPconst && 
    252272             ssindex(e1oper,e1->E2->EV.Vuns) 
    253273            ) || 
    254             (I32 && e1->Ecount) 
     274            (!I16 && e1->Ecount) 
    255275           ) 
    256         {   int inc; 
    257  
    258             inc = e->Ecount != 0; 
     276        { 
     277            int inc = e->Ecount != 0; 
    259278            nest += inc; 
    260279            c = getlvalue(&cs,e,0); 
    261280            nest -= inc; 
     281            unsigned reg; 
    262282            c = cat(c,allocreg(pretregs,&reg,ty)); 
    263283            cs.Iop = 0x8D; 
    264             cs.Irm |= modregrm(0,reg,0); 
     284            code_newreg(&cs, reg); 
    265285            return gen(c,&cs);          /* LEA reg,EA                   */ 
    266286        } 
    267287 
    268288        // Handle the case of ((e + c) + e2) 
    269         if (I32 && 
     289        if (!I16 && 
    270290            e1oper == OPadd && 
    271291            (e1->E2->Eoper == OPconst || e2oper == OPconst) && 
    272292            !e1->Ecount 
    273293           ) 
    274294        {   elem *e11; 
    275295            elem *ebase; 
    276296            elem *edisp; 
    277297            int ss; 
    278298            int ss2; 
    279299            unsigned reg1,reg2; 
    280300            code *c1,*c2,*c3; 
    281301 
    282302            if (e2oper == OPconst) 
    283303            {   edisp = e2; 
    284304                ebase = e1->E2; 
    285305            } 
    286306            else 
    287307            {   edisp = e1->E2; 
    288308                ebase = e2; 
    289309            } 
    290310 
    291311            e11 = e1->E1; 
    292312            retregs = *pretregs & ALLREGS; 
    293313            if (!retregs) 
    294314                retregs = ALLREGS; 
    295315            ss = 0; 
    296316            ss2 = 0; 
    297317 
    298318            // Handle the case of (((e *  c1) + c2) + e2) 
    299319            // Handle the case of (((e << c1) + c2) + e2) 
    300320            if ((e11->Eoper == OPmul || e11->Eoper == OPshl) && 
    301321                e11->E2->Eoper == OPconst && 
    302322                !e11->Ecount 
    303323               ) 
    304             {   targ_size_t co1; 
    305  
    306                 co1 = el_tolong(e11->E2); 
     324            { 
     325                targ_size_t co1 = el_tolong(e11->E2); 
    307326                if (e11->Eoper == OPshl) 
    308327                { 
    309328                    if (co1 > 3) 
    310329                        goto L13; 
    311330                    ss = co1; 
    312331                } 
    313332                else 
    314333                { 
    315334                    ss2 = 1; 
    316335                    switch (co1) 
    317336                    { 
    318337                        case  6:        ss = 1;                 break; 
    319338                        case 12:        ss = 1; ss2 = 2;        break; 
    320339                        case 24:        ss = 1; ss2 = 3;        break; 
    321340                        case 10:        ss = 2;                 break; 
    322341                        case 20:        ss = 2; ss2 = 2;        break; 
    323342                        case 40:        ss = 2; ss2 = 3;        break; 
    324343                        case 18:        ss = 3;                 break; 
    325344                        case 36:        ss = 3; ss2 = 2;        break; 
    326345                        case 72:        ss = 3; ss2 = 3;        break; 
    327346                        default: 
    328347                            ss2 = 0; 
    329348                            goto L13; 
    330349                    } 
    331350                } 
    332351                freenode(e11->E2); 
    333352                freenode(e11); 
    334353                e11 = e11->E1; 
    335354                goto L13; 
    336355            } 
    337356            else 
    338             {   regm_t regm; 
     357            { 
    339358            L13: 
     359                regm_t regm; 
    340360                if (e11->Eoper == OPvar && isregvar(e11,&regm,&reg1)) 
    341361                { 
    342362                    retregs = regm; 
    343363                    c1 = NULL; 
    344364                    freenode(e11); 
    345365                } 
    346366                else 
    347367                    c1 = codelem(e11,&retregs,FALSE); 
    348368            } 
    349369            rretregs = ALLREGS & ~retregs; 
    350370            c2 = scodelem(ebase,&rretregs,retregs,TRUE); 
    351             {   regm_t sregs; 
    352  
    353                 sregs = *pretregs & ~rretregs; 
     371            { 
     372                regm_t sregs = *pretregs & ~rretregs; 
    354373                if (!sregs) 
    355374                    sregs = ALLREGS & ~rretregs; 
    356375                c3 = allocreg(&sregs,&reg,ty); 
    357376            } 
    358377 
    359378            reg1 = findreg(retregs); 
    360379            reg2 = findreg(rretregs); 
    361380 
    362381            if (ss2) 
    363382            { 
    364383                assert(reg != reg2); 
    365384                if (reg1 == BP) 
    366385                {   static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 
    367386 
    368387                    // IMUL reg,imm32 
    369                     c = genc2(CNIL,0x69,modregrm(3,reg,reg1),imm32[ss]); 
     388                    c = genc2(CNIL,0x69,modregxrm(3,reg,BP),imm32[ss]); 
    370389                } 
    371390                else 
    372391                {   // LEA reg,[reg1*ss][reg1] 
    373                     c = gen2sib(CNIL,0x8D,modregrm(0,reg,4),modregrm(ss,reg1,reg1)); 
     392                    c = gen2sib(CNIL,0x8D,modregxrm(0,reg,4),modregrm(ss,reg1 & 7,reg1 & 7)); 
     393                    if (reg1 & 8) 
     394                        code_orrex(c, REX_X | REX_B); 
    374395                } 
    375396                reg1 = reg; 
    376397                ss = ss2;                               // use *2 for scale 
    377398            } 
    378399            else 
    379400                c = NULL; 
    380401            c = cat4(c1,c2,c3,c); 
    381402 
    382403            cs.Iop = 0x8D;                      // LEA reg,c[reg1*ss][reg2] 
    383             cs.Irm = modregrm(2,reg,4); 
    384             cs.Isib = modregrm(ss,reg1,reg2); 
     404            cs.Irm = modregrm(2,reg & 7,4); 
     405            cs.Isib = modregrm(ss,reg1 & 7,reg2 & 7); 
    385406            cs.Iflags = CFoff; 
    386407            cs.Irex = 0; 
     408            if (reg & 8) 
     409                cs.Irex |= REX_R; 
     410            if (reg1 & 8) 
     411                cs.Irex |= REX_X; 
     412            if (reg2 & 8) 
     413                cs.Irex |= REX_B; 
    387414            cs.IFL1 = FLconst; 
    388415            cs.IEV1.Vuns = edisp->EV.Vuns; 
    389416 
    390417            freenode(edisp); 
    391418            freenode(e1); 
    392419            c = gen(c,&cs); 
    393420            return cat(c,fixresult(e,mask[reg],pretregs)); 
    394421        } 
    395422  } 
    396423 
    397424  posregs = (byte) ? BYTEREGS : (mES | ALLREGS | mBP); 
    398425  retregs = *pretregs & posregs; 
    399426  if (retregs == 0)                     /* if no return regs speced     */ 
    400427                                        /* (like if wanted flags only)  */ 
    401428        retregs = ALLREGS & posregs;    // give us some 
    402429 
    403430  if (tysize[ty1] > REGSIZE && numwords == 1) 
    404431  {     /* The only possibilities are (TYfptr + tyword) or (TYfptr - tyword) */ 
    405432#if DEBUG 
    406433        if (tysize[ty2] != REGSIZE) 
     
    489516 
    490517            /* if retregs doesn't have any regs in it that aren't reg vars */ 
    491518            if ((retregs & ~regcon.mvar) == 0) 
    492519                retregs |= mAX; 
    493520        } 
    494521        else if (numwords == 2 && retregs & mES) 
    495522            retregs = (retregs | mMSW) & ALLREGS; 
    496523 
    497524        // Determine if we should swap operands, because 
    498525        //      mov     EAX,x 
    499526        //      add     EAX,reg 
    500527        // is faster than: 
    501528        //      mov     EAX,reg 
    502529        //      add     EAX,x 
    503530        else if (e2oper == OPvar && 
    504531                 e1->Eoper == OPvar && 
    505532                 e->Eoper != OPmin && 
    506533                 isregvar(e1,&regm,NULL) && 
    507534                 regm != retregs && 
    508535                 tysize[ty1] == tysize[ty2]) 
    509         {   elem *es; 
    510  
    511             es = e1; 
     536        { 
     537            elem *es = e1; 
    512538            e1 = e2; 
    513539            e2 = es; 
    514540        } 
    515541        cl = codelem(e1,&retregs,test);         /* eval left leaf       */ 
    516542        reg = findreg(retregs); 
    517543  } 
    518544  switch (e2oper) 
    519545  { 
    520546    case OPind:                                 /* if addressing mode   */ 
    521547        if (!e2->Ecount)                        /* if not CSE           */ 
    522548                goto L1;                        /* try OP reg,EA        */ 
    523549        /* FALL-THROUGH */ 
    524550    default:                                    /* operator node        */ 
    525551    L2: 
    526552        rretregs = ALLREGS & ~retregs; 
    527553        /* Be careful not to do arithmetic on ES        */ 
    528554        if (tysize[ty1] == REGSIZE && tysize[ty2] > REGSIZE && *pretregs != mPSW) 
    529555            rretregs = *pretregs & (mES | ALLREGS | mBP) & ~retregs; 
    530556        else if (byte) 
    531557            rretregs &= BYTEREGS; 
    532558 
    533559        cr = scodelem(e2,&rretregs,retregs,TRUE);       /* get rvalue   */ 
    534560        rreg = (tysize[ty2] > REGSIZE) ? findreglsw(rretregs) : findreg(rretregs); 
    535561        c = CNIL; 
    536562        if (numwords == 1)                              /* ADD reg,rreg */ 
    537563        { 
    538564                /* reverse operands to avoid moving around the segment value */ 
    539565                if (tysize[ty2] > REGSIZE) 
    540566                {       c = cat(c,getregs(rretregs)); 
    541567                        c = genregs(c,op1,rreg,reg); 
    542568                        retregs = rretregs;     /* reverse operands     */ 
    543569                } 
    544570                else 
    545571                {   c = genregs(c,op1,reg,rreg); 
    546                     if (I32 && *pretregs & mPSW) 
     572                    if (!I16 && *pretregs & mPSW) 
    547573                        c->Iflags |= word; 
    548574                } 
     575                if (I64 && sz == 8) 
     576                    code_orrex(c, REX_W); 
    549577        } 
    550578        else /* numwords == 2 */                /* ADD lsreg,lsrreg     */ 
    551579        { 
    552580            reg = findreglsw(retregs); 
    553581            rreg = findreglsw(rretregs); 
    554582            c = genregs(c,op1,reg,rreg); 
    555583            if (e->Eoper == OPadd || e->Eoper == OPmin) 
    556584                code_orflag(c,CFpsw); 
    557585            reg = findregmsw(retregs); 
    558586            rreg = findregmsw(rretregs); 
    559587            if (!(e2oper == OPu16_32 && // if second operand is 0 
    560588                  (op2 == 0x0B || op2 == 0x33)) // and OR or XOR 
    561589               ) 
    562590                genregs(c,op2,reg,rreg);        // ADC msreg,msrreg 
    563591        } 
    564592        break; 
    565593 
    566594    case OPrelconst: 
    567595        if (sz != REGSIZE) 
    568596                goto L2; 
    569597        if (segfl[el_fl(e2)] != 3)              /* if not in data segment */ 
    570598                goto L2; 
    571599        if (evalinregister(e2)) 
    572600                goto L2; 
    573601        cs.IEVoffset2 = e2->EV.sp.Voffset; 
    574602        cs.IEVsym2 = e2->EV.sp.Vsym; 
    575603        cs.Iflags |= CFoff; 
    576604        i = 0;                          /* no INC or DEC opcode         */ 
    577605        rval = 0; 
    578606        goto L3; 
    579607 
    580608    case OPconst: 
    581609        if (tyfv(ty2)) 
    582610            goto L2; 
    583611        if (numwords == 1) 
    584612        { 
    585                 i = e2->EV.Vint
     613                i = e2->EV.Vpointer
    586614                if (word) 
    587615                { 
    588616                    if (!(*pretregs & mPSW) && 
    589617                        config.flags4 & CFG4speed && 
    590618                        (e->Eoper == OPor || e->Eoper == OPxor || test || 
    591619                         (e1->Eoper != OPvar && e1->Eoper != OPind))) 
    592620                    {   word = 0; 
    593621                        i &= 0xFFFF; 
    594622                    } 
    595623                } 
    596624                rval = reghasvalue(byte ? BYTEREGS : ALLREGS,i,&rreg); 
    597625                cs.IEV2.Vint = i; 
    598626        L3: 
    599627                op1 ^= byte; 
    600628                cs.Iflags |= word; 
    601629                if (rval) 
    602630                {   cs.Iop = op1 ^ 2; 
    603631                    mode = rreg; 
    604632                } 
    605633                else 
    606634                    cs.Iop = 0x81; 
    607                 cs.Irm = modregrm(3,mode,reg); 
     635                cs.Irm = modregrm(3,mode&7,reg&7); 
     636                if (mode & 8) 
     637                    cs.Irex |= REX_R; 
     638                if (reg & 8) 
     639                    cs.Irex |= REX_B; 
    608640                cs.IFL2 = (e2->Eoper == OPconst) ? FLconst : el_fl(e2); 
    609641                /* Modify instruction for special cases */ 
    610642                switch (e->Eoper) 
    611643                {   case OPadd: 
    612644                    {   int iop; 
    613645 
    614646                        if (i == 1) 
    615647                            iop = 0;                    /* INC reg      */ 
    616648                        else if (i == -1) 
    617649                            iop = 8;                    /* DEC reg      */ 
    618650                        else 
    619651                            break; 
    620652                        cs.Iop = (0x40 | iop | reg) ^ byte; 
    621                         if (byte && *pretregs & mPSW
    622                         {   cs.Irm = modregrm(3,0,reg) | iop; 
     653                        if ((byte && *pretregs & mPSW) || I64
     654                        {   cs.Irm = modregrm(3,0,reg & 7) | iop; 
    623655                            cs.Iop = 0xFF; 
    624656                        } 
    625657                        break; 
    626658                    } 
    627659                    case OPand: 
    628660                        if (test) 
    629661                            cs.Iop = rval ? op1 : 0xF7; // TEST 
    630662                        break; 
    631663                } 
    632664                if (*pretregs & mPSW) 
    633665                        cs.Iflags |= CFpsw; 
    634666                cs.Iop ^= byte; 
    635667                c = gen(CNIL,&cs); 
    636668                cs.Iflags &= ~CFpsw; 
    637669        } 
    638670        else if (numwords == 2) 
    639671        {       unsigned lsreg; 
    640672                targ_int msw; 
    641673 
    642674                c = getregs(retregs); 
     
    657689                cs.Iflags &= ~CFpsw; 
    658690 
    659691                cs.Irm = (cs.Irm & modregrm(3,7,0)) | reg; 
    660692                cs.IEV2.Vint = msw; 
    661693                if (e->Eoper == OPadd) 
    662694                        cs.Irm |= modregrm(0,2,0);      /* ADC          */ 
    663695                c = gen(c,&cs); 
    664696        } 
    665697        else 
    666698                assert(0); 
    667699        freenode(e2); 
    668700        break; 
    669701 
    670702    case OPvar: 
    671703    L1: 
    672704        if (tyfv(ty2)) 
    673705                goto L2; 
    674706        c = loadea(e2,&cs,op1, 
    675707                ((numwords == 2) ? findreglsw(retregs) : reg), 
    676708                0,retregs,retregs); 
    677         if (I32 && word) 
     709        if (!I16 && word) 
    678710        {   if (*pretregs & mPSW) 
    679711                code_orflag(c,word); 
    680712            else 
    681             {   code *ce; 
    682  
    683                 ce = code_last(c); 
     713            { 
     714                code *ce = code_last(c); 
    684715                ce->Iflags &= ~word; 
    685716            } 
    686717        } 
    687718        else if (numwords == 2) 
    688719        { 
    689720            if (e->Eoper == OPadd || e->Eoper == OPmin) 
    690721                code_orflag(c,CFpsw); 
    691722            reg = findregmsw(retregs); 
    692723            if (EOP(e2)) 
    693724            {   getlvalue_msw(&cs); 
    694725                cs.Iop = op2; 
    695726                NEWREG(cs.Irm,reg); 
    696727                c = gen(c,&cs);                 /* ADC reg,data+2 */ 
    697728            } 
    698729            else 
    699730                c = cat(c,loadea(e2,&cs,op2,reg,REGSIZE,retregs,0)); 
    700731        } 
    701732        freenode(e2); 
    702733        break; 
    703734  } 
     
    733764    int opunslng; 
    734765    int pow2; 
    735766 
    736767    if (*pretregs == 0)                         // if don't want result 
    737768    {   c = codelem(e->E1,pretregs,FALSE);      // eval left leaf 
    738769        *pretregs = 0;                          // in case they got set 
    739770        return cat(c,codelem(e->E2,pretregs,FALSE)); 
    740771    } 
    741772 
    742773    keepregs = 0; 
    743774    cs.Iflags = 0; 
    744775    cs.Irex = 0; 
    745776    c = cg = cr = CNIL;                         // initialize 
    746777    e2 = e->E2; 
    747778    e1 = e->E1; 
    748779    tyml = tybasic(e1->Ety); 
    749780    sz = tysize[tyml]; 
    750781    byte = tybyte(e->Ety) != 0; 
    751782    uns = tyuns(tyml) || tyuns(e2->Ety); 
    752783    oper = e->Eoper; 
     784    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     785    unsigned grex = rex << 16; 
    753786 
    754787    if (tyfloating(tyml)) 
    755788#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    756789        return orth87(e,pretregs); 
    757790#else 
    758791        return opdouble(e,pretregs,(oper == OPmul) ? CLIBdmul : CLIBddiv); 
    759792#endif 
    760793 
    761     opunslng = I32 ? OPu32_64 : OPu16_32
     794    opunslng = I16 ? OPu16_32 : OPu32_64
    762795    switch (oper) 
    763796    { 
    764797        case OPmul: 
    765798            resreg = mAX; 
    766799            op = 5 - uns; 
    767800            lib = CLIBlmul; 
    768801            break; 
    769802 
    770803        case OPdiv: 
    771804            resreg = mAX; 
    772805            op = 7 - uns; 
    773806            lib = uns ? CLIBuldiv : CLIBldiv; 
    774807            if (I32) 
    775808                keepregs |= mSI | mDI; 
    776809            break; 
    777810 
    778811        case OPmod: 
    779812            resreg = mDX; 
    780813            op = 7 - uns; 
    781814            lib = uns ? CLIBulmod : CLIBlmod; 
     
    815848    case OPulngllng: 
    816849    case OPlngllng: 
    817850        if (sz != 2 * REGSIZE || oper != OPmul || e1->Eoper != e2->Eoper || 
    818851            e1->Ecount || e2->Ecount) 
    819852            goto L2; 
    820853        op = (e2->Eoper == opunslng) ? 4 : 5; 
    821854        retregs = mAX; 
    822855        cl = codelem(e1->E1,&retregs,FALSE);    /* eval left leaf       */ 
    823856        if (e2->E1->Eoper == OPvar || 
    824857            (e2->E1->Eoper == OPind && !e2->E1->Ecount) 
    825858           ) 
    826859        { 
    827860            cr = loadea(e2->E1,&cs,0xF7,op,0,mAX,mAX | mDX); 
    828861        } 
    829862        else 
    830863        { 
    831864            rretregs = ALLREGS & ~mAX; 
    832865            cr = scodelem(e2->E1,&rretregs,retregs,TRUE); // get rvalue 
    833866            cg = getregs(mAX | mDX); 
    834867            rreg = findreg(rretregs); 
    835             cg = gen2(cg,0xF7,modregrm(3,op,rreg)); // OP AX,rreg 
     868            cg = gen2(cg,0xF7,grex | modregrmx(3,op,rreg)); // OP AX,rreg 
    836869        } 
    837870        freenode(e->E1); 
    838871        freenode(e2); 
    839872        c = fixresult(e,mAX | mDX,pretregs); 
    840873        break; 
    841874 
    842875    case OPconst: 
    843876        e2factor = el_tolong(e2); 
    844877 
    845878        if (oper == OPmul && I32 && sz == REGSIZE * 2) 
    846879        {   targ_int msw,lsw; 
    847880            regm_t scratch; 
    848881            unsigned reg; 
    849882            targ_llong e2factor; 
    850883 
    851884            cl = codelem(e1,&retregs,FALSE);    // eval left leaf 
    852885            /*  IMUL    EDX,EDX,lsw 
    853886                IMUL    reg,EAX,msw 
    854887                ADD     reg,EDX 
    855888                MOV     EDX,lsw 
     
    871904            msw = e2factor >> (REGSIZE * 8); 
    872905 
    873906            if (msw) 
    874907            {   cg = genmulimm(cg,DX,DX,lsw); 
    875908                cg = genmulimm(cg,reg,AX,msw); 
    876909                cg = gen2(cg,0x03,modregrm(3,reg,DX)); 
    877910            } 
    878911            else 
    879912                cg = genmulimm(cg,reg,DX,lsw); 
    880913 
    881914            cg = movregconst(cg,DX,lsw,0);              // MOV EDX,lsw 
    882915            cg = cat(cg,getregs(mDX)); 
    883916            cg = gen2(cg,0xF7,modregrm(3,4,DX));        // MUL EDX 
    884917            gen2(cg,0x03,modregrm(3,DX,reg));           // ADD EDX,reg 
    885918 
    886919            resreg = mDX | mAX; 
    887920            freenode(e2); 
    888921            goto L3; 
    889922        } 
    890923 
    891         if (oper != OPmul && e2factor == 10 && sz == REGSIZE && 
     924        if (oper != OPmul && e2factor == 10 && 
     925            (!I16 && sz == 4) && 
    892926            config.flags4 & CFG4speed && !uns) 
    893927        { 
    894928            /* R1 / 10 
    895929             * 
    896930             *  MOV     EAX,0x66666667 
    897931             *  IMUL    R1 
    898932             *  MOV     EAX,R1 
    899933             *  SAR     EAX,31 
    900934             *  SAR     EDX,2 
    901935             *  SUB     EDX,EAX 
    902936             *  IMUL    EAX,EDX,10 
    903937             *  SUB     R1,EAX 
    904938             * 
    905939             * EDX = quotient 
    906940             * R1 = remainder 
    907941             */ 
    908942            regm_t regm; 
    909943            unsigned reg; 
    910944 
    911945            regm = allregs & ~(mAX | mDX); 
    912946            cl = codelem(e1,&regm,FALSE);       // eval left leaf 
    913947            reg = findreg(regm); 
    914948            cg = getregs(regm | mDX | mAX); 
    915949 
    916950            cg = movregconst(cg, AX, 0x66666667, 0);    // MOV EAX,0x66666667 
    917             cg = gen2(cg,0xF7,modregrm(3,5,reg));       // IMUL R1 
     951            cg = gen2(cg,0xF7,modregrmx(3,5,reg));      // IMUL R1 
    918952            genmovreg(cg, AX, reg);                     // MOV EAX,R1 
    919953            genc2(cg,0xC1,modregrm(3,7,AX),31);         // SAR EAX,31 
    920954            genc2(cg,0xC1,modregrm(3,7,DX),2);          // SAR EDX,2 
    921955            gen2(cg,0x2B,modregrm(3,DX,AX));            // SUB EDX,EAX 
    922956 
    923957            switch (oper) 
    924958            {   case OPdiv: 
    925959                    resreg = mDX; 
    926960                    break; 
    927961 
    928962                case OPmod: 
    929963                    genmulimm(cg,AX,DX,10);             // IMUL EAX,EDX,10 
    930                     gen2(cg,0x2B,modregrm(3,reg,AX));   // SUB R1,EAX 
     964                    gen2(cg,0x2B,modregxrm(3,reg,AX));  // SUB R1,EAX 
    931965                    resreg = regm; 
    932966                    break; 
    933967 
    934968                case OPremquo: 
    935969                    genmulimm(cg,AX,DX,10);             // IMUL EAX,EDX,10 
    936                     gen2(cg,0x2B,modregrm(3,reg,AX));   // SUB R1,EAX 
     970                    gen2(cg,0x2B,modregxrm(3,reg,AX));  // SUB R1,EAX 
    937971                    genmovreg(cg, AX, DX);              // MOV EAX,EDX 
    938972                    genmovreg(cg, DX, reg);             // MOV EDX,R1 
    939973                    resreg = mDX | mAX; 
    940974                    break; 
    941975 
    942976                default: 
    943977                    assert(0); 
    944978            } 
    945979            freenode(e2); 
    946980            goto L3; 
    947981        } 
    948982 
    949983        if (sz > REGSIZE) 
    950984            goto L2; 
    951985 
    952986        if (oper == OPmul && config.target_cpu >= TARGET_80286) 
    953987        {   unsigned reg; 
    954988            int ss; 
    955989 
    956990            freenode(e2); 
    957991            retregs = byte ? BYTEREGS : ALLREGS; 
    958992            resreg = *pretregs & (ALLREGS | mBP); 
    959993            if (!resreg) 
    960994                resreg = retregs; 
    961995 
    962             if (I32
     996            if (!I16
    963997            {   // See if we can use an LEA instruction 
    964998                int ss2 = 0; 
    965999                int shift; 
    9661000 
    9671001                switch (e2factor) 
    9681002                { 
    9691003                    case 12:    ss = 1; ss2 = 2; goto L4; 
    9701004                    case 24:    ss = 1; ss2 = 3; goto L4; 
    9711005 
    9721006                    case 6: 
    9731007                    case 3:     ss = 1; goto L4; 
    9741008 
    9751009                    case 20:    ss = 2; ss2 = 2; goto L4; 
    9761010                    case 40:    ss = 2; ss2 = 3; goto L4; 
    9771011 
    9781012                    case 10: 
    9791013                    case 5:     ss = 2; goto L4; 
    9801014 
    9811015                    case 36:    ss = 3; ss2 = 2; goto L4; 
    9821016                    case 72:    ss = 3; ss2 = 3; goto L4; 
    9831017 
    9841018                    case 18: 
    9851019                    case 9:     ss = 3; goto L4; 
    9861020 
    9871021                    L4: 
    9881022                    { 
    9891023#if 1 
    990                         regm_t regm; 
    991                         int r; 
    992  
    993                         regm = byte ? BYTEREGS : ALLREGS;               // don't use EBP 
     1024                        regm_t regm = byte ? BYTEREGS : ALLREGS;        // don't use EBP 
    9941025                        cl = codelem(e->E1,&regm,TRUE); 
    995                         r = findreg(regm); 
     1026                        unsigned r = findreg(regm); 
    9961027 
    9971028                        if (ss2) 
    9981029                        {   // Don't use EBP 
    9991030                            resreg &= ~mBP; 
    10001031                            if (!resreg) 
    10011032                                resreg = retregs; 
    10021033                        } 
    10031034                        cg = allocreg(&resreg,&reg,tyml); 
    10041035 
    1005                         c = gen2sib(CNIL,0x8D,modregrm(0,reg,4), 
    1006                                               modregrm(ss,r,r)); 
     1036                        c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 
     1037                                              modregxrmx(ss,r,r)); 
    10071038                        if (ss2) 
    10081039                        { 
    1009                             gen2sib(c,0x8D,modregrm(0,reg,4), 
    1010                                            modregrm(ss2,reg,5)); 
     1040                            gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 
     1041                                           modregxrm(ss2,reg,5)); 
    10111042                            code_last(c)->IFL1 = FLconst; 
    10121043                            code_last(c)->IEV1.Vint = 0; 
    10131044                        } 
    10141045                        else if (!(e2factor & 1))    // if even factor 
    1015                             genregs(c,0x03,reg,reg); // ADD reg,reg 
     1046                        {   genregs(c,0x03,reg,reg); // ADD reg,reg 
     1047                            code_orrex(c,rex); 
     1048                        } 
    10161049                        cg = cat(cg,c); 
    10171050                        goto L3; 
    10181051#else 
    10191052 
    10201053                                // Don't use EBP 
    10211054                                resreg &= ~mBP; 
    10221055                                if (!resreg) 
    10231056                                    resreg = retregs; 
    10241057 
    10251058                                cl = codelem(e->E1,&resreg,FALSE); 
    10261059                                reg = findreg(resreg); 
    10271060                                cg = getregs(resreg); 
    10281061                                c = gen2sib(CNIL,0x8D,modregrm(0,reg,4), 
    10291062                                                      modregrm(ss,reg,reg)); 
    10301063                                if (ss2) 
    10311064                                { 
    10321065                                    gen2sib(c,0x8D,modregrm(0,reg,4), 
    10331066                                                   modregrm(ss2,reg,5)); 
    10341067                                    code_last(c)->IFL1 = FLconst; 
    10351068                                    code_last(c)->IEV1.Vint = 0; 
    10361069                                } 
    10371070                                else if (!(e2factor & 1))    // if even factor 
    10381071                                    genregs(c,0x03,reg,reg); // ADD reg,reg 
    10391072                                cg = cat(cg,c); 
    10401073                                goto L3; 
    10411074#endif 
    10421075                    } 
    10431076                    case 37: 
    10441077                    case 74:    shift = 2; 
    10451078                                goto L5; 
    10461079                    case 13: 
    10471080                    case 26:    shift = 0; 
    10481081                                goto L5; 
    10491082                    L5: 
    1050                     {           regm_t sregm; 
    1051                                 unsigned sreg; 
    1052  
     1083                    { 
    10531084                                // Don't use EBP 
    10541085                                resreg &= ~mBP; 
    10551086                                if (!resreg) 
    10561087                                    resreg = retregs; 
    10571088                                cl = allocreg(&resreg,&reg,TYint); 
    10581089 
    1059                                 sregm = ALLREGS & ~resreg; 
     1090                                regm_t sregm = ALLREGS & ~resreg; 
    10601091                                cl = cat(cl,codelem(e->E1,&sregm,FALSE)); 
    1061                                 sreg = findreg(sregm); 
     1092                                unsigned sreg = findreg(sregm); 
    10621093                                cg = getregs(resreg | sregm); 
    10631094                                // LEA reg,[sreg * 4][sreg] 
    10641095                                // SHL sreg,shift 
    10651096                                // LEA reg,[sreg * 8][reg] 
    1066                                 c = gen2sib(CNIL,0x8D,modregrm(0,reg,4), 
    1067                                                       modregrm(2,sreg,sreg)); 
     1097                                c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 
     1098                                                      modregxrmx(2,sreg,sreg)); 
    10681099                                if (shift) 
    1069                                     genc2(c,0xC1,modregrm(3,4,sreg),shift); 
    1070                                 gen2sib(c,0x8D,modregrm(0,reg,4), 
    1071                                                       modregrm(3,sreg,reg)); 
     1100                                    genc2(c,0xC1,grex | modregrmx(3,4,sreg),shift); 
     1101                                gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 
     1102                                                      modregxrmx(3,sreg,reg)); 
    10721103                                if (!(e2factor & 1))         // if even factor 
    1073                                     genregs(c,0x03,reg,reg); // ADD reg,reg 
     1104                                {   genregs(c,0x03,reg,reg); // ADD reg,reg 
     1105                                    code_orrex(c,rex); 
     1106                                } 
    10741107                                cg = cat(cg,c); 
    10751108                                goto L3; 
    10761109                    } 
    10771110                } 
    10781111            } 
    10791112 
    10801113            cl = scodelem(e->E1,&retregs,0,TRUE);       // eval left leaf 
    10811114            reg = findreg(retregs); 
    10821115            cg = allocreg(&resreg,&rreg,e->Ety); 
    10831116 
    10841117            /* IMUL reg,imm16   */ 
    1085             cg = genc2(cg,0x69,modregrm(3,rreg,reg),e2factor); 
     1118            cg = genc2(cg,0x69,grex | modregxrmx(3,rreg,reg),e2factor); 
    10861119            goto L3; 
    10871120        } 
    10881121 
    10891122        // Special code for signed divide or modulo by power of 2 
    1090         if (sz == REGSIZE && (oper == OPdiv || oper == OPmod) && !uns && 
     1123        if ((sz == REGSIZE || (I64 && sz == 4)) && 
     1124            (oper == OPdiv || oper == OPmod) && !uns && 
    10911125            (pow2 = ispow2(e2factor)) != -1 && 
    10921126            !(config.target_cpu < TARGET_80286 && pow2 != 1 && oper == OPdiv) 
    10931127           ) 
    10941128        { 
    10951129            if (pow2 == 1 && oper == OPdiv && config.target_cpu > TARGET_80386) 
    10961130            { 
    10971131                //     test    eax,eax 
    10981132                //     jns     L1 
    10991133                //     add     eax,1 
    11001134                // L1: sar     eax,1 
    11011135 
    11021136                code *cnop; 
    1103                 unsigned reg; 
    11041137 
    11051138                retregs = allregs; 
    11061139                cl = codelem(e->E1,&retregs,FALSE);     // eval left leaf 
    1107                 reg = findreg(retregs); 
     1140                unsigned reg = findreg(retregs); 
    11081141                freenode(e2); 
    11091142                cg = getregs(retregs); 
    11101143                cg = gentstreg(cg,reg);                 // TEST reg,reg 
     1144                code_orrex(cg, rex); 
    11111145                cnop = gennop(CNIL); 
    11121146                genjmp(cg,JNS,FLcode,(block *)cnop);    // JNS cnop 
    1113                 gen1(cg,0x40 + reg);                    // INC reg 
     1147                if (I64) 
     1148                { 
     1149                    gen2(cg,0xFF,modregrmx(3,0,reg));       // INC reg 
     1150                    code_orrex(cg,rex); 
     1151                } 
     1152                else 
     1153                    gen1(cg,0x40 + reg);                    // INC reg 
    11141154                cg = cat(cg,cnop); 
    1115                 gen2(cg,0xD1,modregrm(3,7,reg));        // SAR reg,1 
     1155                gen2(cg,0xD1,grex | modregrmx(3,7,reg));        // SAR reg,1 
    11161156                resreg = retregs; 
    11171157                goto L3; 
    11181158            } 
    11191159            cl = codelem(e->E1,&retregs,FALSE); // eval left leaf 
    11201160            freenode(e2); 
    11211161            cg = getregs(mAX | mDX);            // trash these regs 
    11221162            cg = gen1(cg,0x99);                         // CWD 
     1163            code_orrex(cg, rex); 
    11231164            if (pow2 == 1) 
    11241165            { 
    11251166                if (oper == OPdiv) 
    1126                 {   gen2(cg,0x2B,modregrm(3,AX,DX));    // SUB AX,DX 
    1127                     gen2(cg,0xD1,modregrm(3,7,AX));     // SAR AX,1 
     1167                {   gen2(cg,0x2B,grex | modregrm(3,AX,DX));    // SUB AX,DX 
     1168                    gen2(cg,0xD1,grex | modregrm(3,7,AX));     // SAR AX,1 
    11281169                } 
    11291170                else // OPmod 
    1130                 {   gen2(cg,0x33,modregrm(3,AX,DX));    // XOR AX,DX 
    1131                     genc2(cg,0x81,modregrm(3,4,AX),1);  // AND AX,1 
    1132                     gen2(cg,0x03,modregrm(3,DX,AX));    // ADD DX,AX 
     1171                {   gen2(cg,0x33,grex | modregrm(3,AX,DX));    // XOR AX,DX 
     1172                    genc2(cg,0x81,grex | modregrm(3,4,AX),1);  // AND AX,1 
     1173                    gen2(cg,0x03,grex | modregrm(3,DX,AX));    // ADD DX,AX 
    11331174                } 
    11341175            } 
    11351176            else 
    11361177            {   targ_ulong m; 
    11371178 
    11381179                m = (1 << pow2) - 1; 
    11391180                if (oper == OPdiv) 
    1140                 {   genc2(cg,0x81,modregrm(3,4,DX),m);  // AND DX,m 
    1141                     gen2(cg,0x03,modregrm(3,AX,DX));    // ADD AX,DX 
     1181                {   genc2(cg,0x81,grex | modregrm(3,4,DX),m);  // AND DX,m 
     1182                    gen2(cg,0x03,grex | modregrm(3,AX,DX));    // ADD AX,DX 
    11421183                    // Be careful not to generate this for 8088 
    11431184                    assert(config.target_cpu >= TARGET_80286); 
    1144                     genc2(cg,0xC1,modregrm(3,7,AX),pow2); // SAR AX,pow2 
     1185                    genc2(cg,0xC1,grex | modregrm(3,7,AX),pow2); // SAR AX,pow2 
    11451186                } 
    11461187                else // OPmod 
    1147                 {   gen2(cg,0x33,modregrm(3,AX,DX));    // XOR AX,DX 
    1148                     gen2(cg,0x2B,modregrm(3,AX,DX));    // SUB AX,DX 
    1149                     genc2(cg,0x81,modregrm(3,4,AX),m);  // AND AX,mask 
    1150                     gen2(cg,0x33,modregrm(3,AX,DX));    // XOR AX,DX 
    1151                     gen2(cg,0x2B,modregrm(3,AX,DX));    // SUB AX,DX 
     1188                {   gen2(cg,0x33,grex | modregrm(3,AX,DX));    // XOR AX,DX 
     1189                    gen2(cg,0x2B,grex | modregrm(3,AX,DX));    // SUB AX,DX 
     1190                    genc2(cg,0x81,grex | modregrm(3,4,AX),m);  // AND AX,mask 
     1191                    gen2(cg,0x33,grex | modregrm(3,AX,DX));    // XOR AX,DX 
     1192                    gen2(cg,0x2B,grex | modregrm(3,AX,DX));    // SUB AX,DX 
    11521193                    resreg = mAX; 
    11531194                } 
    11541195            } 
    11551196            goto L3; 
    11561197        } 
    11571198        goto L2; 
    11581199    case OPind: 
    11591200        if (!e2->Ecount)                        /* if not CSE           */ 
    11601201                goto L1;                        /* try OP reg,EA        */ 
    11611202        goto L2; 
    11621203    default:                                    /* OPconst and operators */ 
    11631204    L2: 
    11641205        cl = codelem(e1,&retregs,FALSE);        /* eval left leaf       */ 
    11651206        cr = scodelem(e2,&rretregs,retregs,TRUE);       /* get rvalue   */ 
    11661207        if (sz <= REGSIZE) 
    11671208        {   cg = getregs(mAX | mDX);            /* trash these regs     */ 
    11681209            if (op == 7)                        /* signed divide        */ 
    1169                 cg = gen1(cg,0x99);             /* CWD                  */ 
     1210            {   cg = gen1(cg,0x99);             // CWD 
     1211                code_orrex(cg,rex); 
     1212            } 
    11701213            else if (op == 6)                   /* unsigned divide      */ 
    1171             {   cg = movregconst(cg,DX,0,0);    // MOV DX,0 
     1214            { 
     1215                cg = movregconst(cg,DX,0,(sz == 8) ? 64 : 0);    // MOV DX,0 
    11721216                cg = cat(cg,getregs(mDX)); 
    11731217            } 
    11741218            rreg = findreg(rretregs); 
    1175             cg = gen2(cg,0xF7 ^ byte,modregrm(3,op,rreg)); /* OP AX,rreg */ 
     1219            cg = gen2(cg,0xF7 ^ byte,grex | modregrmx(3,op,rreg)); // OP AX,rreg 
    11761220        L3: 
    11771221            c = fixresult(e,resreg,pretregs); 
    11781222        } 
    11791223        else if (sz == 2 * REGSIZE) 
    11801224        { 
    11811225            if (config.target_cpu >= TARGET_PentiumPro && oper == OPmul) 
    11821226            { 
    11831227                /*  IMUL    ECX,EAX 
    11841228                    IMUL    EDX,EBX 
    11851229                    ADD     ECX,EDX 
    11861230                    MUL     EBX 
    11871231                    ADD     EDX,ECX 
    11881232                 */ 
    11891233                 cg = getregs(mAX|mDX|mCX); 
    11901234                 cg = gen2(cg,0x0FAF,modregrm(3,CX,AX)); 
    11911235                 gen2(cg,0x0FAF,modregrm(3,DX,BX)); 
    11921236                 gen2(cg,0x03,modregrm(3,CX,DX)); 
    11931237                 gen2(cg,0xF7,modregrm(3,4,BX)); 
    11941238                 gen2(cg,0x03,modregrm(3,DX,CX)); 
    11951239                 c = fixresult(e,mDX|mAX,pretregs); 
    11961240            } 
    11971241            else 
    11981242                c = callclib(e,lib,pretregs,keepregs); 
    11991243        } 
    12001244        else 
    12011245                assert(0); 
    12021246        break; 
    12031247    case OPvar: 
    12041248    L1: 
    1205         if (I32 && sz <= REGSIZE) 
     1249        if (!I16 && sz <= REGSIZE) 
    12061250        { 
    12071251            if (oper == OPmul && sz > 1)        /* no byte version      */ 
    12081252            { 
    12091253                /* Generate IMUL r32,r/m32      */ 
    12101254                retregs = *pretregs & (ALLREGS | mBP); 
    12111255                if (!retregs) 
    12121256                    retregs = ALLREGS; 
    12131257                cl = codelem(e1,&retregs,FALSE);        /* eval left leaf */ 
    12141258                resreg = retregs; 
    12151259                cr = loadea(e2,&cs,0x0FAF,findreg(resreg),0,retregs,retregs); 
    12161260                freenode(e2); 
    12171261                goto L3; 
    12181262            } 
    12191263        } 
    12201264        else 
    12211265        { 
    12221266            if (sz == 2 * REGSIZE) 
    12231267            {   int reg; 
    12241268 
    12251269                if (oper != OPmul || e->E1->Eoper != opunslng || 
     
    12781322code *cdnot(elem *e,regm_t *pretregs) 
    12791323{   unsigned reg; 
    12801324    tym_t forflags; 
    12811325    code *c1,*c,*cfalse,*ctrue,*cnop; 
    12821326    unsigned sz; 
    12831327    regm_t retregs; 
    12841328    elem *e1; 
    12851329    int op; 
    12861330 
    12871331    e1 = e->E1; 
    12881332    if (*pretregs == 0) 
    12891333        goto L1; 
    12901334    if (*pretregs == mPSW) 
    12911335    {   /*assert(e->Eoper != OPnot && e->Eoper != OPbool);*/ /* should've been optimized */ 
    12921336    L1: 
    12931337        return codelem(e1,pretregs,FALSE);      /* evaluate e1 for cc   */ 
    12941338    } 
    12951339 
    12961340    op = e->Eoper; 
    12971341    sz = tysize(e1->Ety); 
     1342    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1343    unsigned grex = rex << 16; 
    12981344    if (!tyfloating(e1->Ety)) 
    12991345    { 
    13001346    if (sz <= REGSIZE && e1->Eoper == OPvar) 
    13011347    {   code cs; 
    13021348 
    13031349        c = getlvalue(&cs,e1,0); 
    13041350        freenode(e1); 
    1305         if (I32 && sz == 2) 
     1351        if (!I16 && sz == 2) 
    13061352            cs.Iflags |= CFopsize; 
    13071353 
    13081354        retregs = *pretregs & (ALLREGS | mBP); 
    13091355        if (config.target_cpu >= TARGET_80486 && 
    13101356            tysize(e->Ety) == 1) 
    13111357        { 
    13121358            if (reghasvalue((sz == 1) ? BYTEREGS : ALLREGS,0,&reg)) 
    13131359                cs.Iop = 0x39; 
    13141360            else 
    13151361            {   cs.Iop = 0x81; 
    13161362                reg = 7; 
    13171363                cs.IFL2 = FLconst; 
    13181364                cs.IEV2.Vint = 0; 
    13191365            } 
    13201366            cs.Iop ^= (sz == 1); 
    1321             cs.Irm |= modregrm(0,reg,0); 
     1367            code_newreg(&cs,reg); 
    13221368            c = gen(c,&cs);                             // CMP e1,0 
    13231369 
    13241370            retregs &= BYTEREGS; 
    13251371            if (!retregs) 
    13261372                retregs = BYTEREGS; 
    13271373            c1 = allocreg(&retregs,&reg,TYint); 
    13281374 
    13291375            int iop; 
    13301376            if (op == OPbool) 
    13311377            { 
    13321378                iop = 0x0F95;   // SETNZ rm8 
    13331379            } 
    13341380            else 
    13351381            { 
    13361382                iop = 0x0F94;   // SETZ rm8 
    13371383            } 
    1338             c1 = gen2(c1,iop,modregrm(3,0,reg)); 
     1384            c1 = gen2(c1,iop,grex | modregrmx(3,0,reg)); 
    13391385            if (op == OPbool) 
    13401386                *pretregs &= ~mPSW; 
    13411387            goto L4; 
    13421388        } 
    13431389 
    13441390        if (reghasvalue((sz == 1) ? BYTEREGS : ALLREGS,1,&reg)) 
    13451391            cs.Iop = 0x39; 
    13461392        else 
    13471393        {   cs.Iop = 0x81; 
    13481394            reg = 7; 
    13491395            cs.IFL2 = FLconst; 
    13501396            cs.IEV2.Vint = 1; 
    13511397        } 
    13521398        cs.Iop ^= (sz == 1); 
    1353         cs.Irm |= modregrm(0,reg,0); 
     1399        code_newreg(&cs,reg); 
    13541400        c = gen(c,&cs);                         // CMP e1,1 
    13551401 
    13561402        c1 = allocreg(&retregs,&reg,TYint); 
    13571403        op ^= (OPbool ^ OPnot);                 // switch operators 
    13581404        goto L2; 
    13591405    } 
    13601406    else if (sz <= REGSIZE && 
    13611407        // NEG bytereg is too expensive 
    13621408        (sz != 1 || config.target_cpu < TARGET_PentiumPro)) 
    13631409    { 
    13641410        retregs = *pretregs & (ALLREGS | mBP); 
    13651411        if (sz == 1 && !(retregs &= BYTEREGS)) 
    13661412            retregs = BYTEREGS; 
    13671413        c = codelem(e->E1,&retregs,FALSE); 
    13681414        reg = findreg(retregs); 
    13691415        c1 = getregs(retregs); 
    1370         c1 = gen2(c1,0xF7 ^ (sz == 1),modregrm(3,3,reg));       // NEG reg 
     1416        c1 = gen2(c1,0xF7 ^ (sz == 1),grex | modregrmx(3,3,reg));   // NEG reg 
    13711417        code_orflag(c1,CFpsw); 
    13721418        if (I32 && sz == SHORTSIZE) 
    13731419            code_orflag(c1,CFopsize); 
    13741420    L2: 
    13751421        c1 = genregs(c1,0x19,reg,reg);                  // SBB reg,reg 
     1422        code_orrex(c1, rex); 
    13761423        // At this point, reg==0 if e1==0, reg==-1 if e1!=0 
    13771424        if (op == OPnot) 
    1378             gen1(c1,0x40 + reg);                        // INC reg 
     1425        { 
     1426            if (I64) 
     1427                gen2(c1,0xFF,grex | modregrmx(3,0,reg));    // INC reg 
     1428            else 
     1429                gen1(c1,0x40 + reg);                        // INC reg 
     1430        } 
    13791431        else 
    1380             gen2(c1,0xF7,modregrm(3,3,reg));            // NEG reg 
     1432            gen2(c1,0xF7,grex | modregrmx(3,3,reg));    // NEG reg 
    13811433        if (*pretregs & mPSW) 
    13821434        {   code_orflag(c1,CFpsw); 
    13831435            *pretregs &= ~mPSW;         // flags are always set anyway 
    13841436        } 
    13851437    L4: 
    13861438        return cat3(c,c1,fixresult(e,retregs,pretregs)); 
    13871439    } 
    13881440  } 
    13891441  cnop = gennop(CNIL); 
    13901442  ctrue = gennop(CNIL); 
    13911443  c = logexp(e->E1,(op == OPnot) ? FALSE : TRUE,FLcode,ctrue); 
    13921444  forflags = *pretregs & mPSW; 
     1445  if (I64 && sz == 8) 
     1446        forflags |= 64; 
    13931447  assert(tysize(e->Ety) <= REGSIZE);            // result better be int 
    13941448  cfalse = allocreg(pretregs,&reg,e->Ety);      // allocate reg for result 
    13951449  for (c1 = cfalse; c1; c1 = code_next(c1)) 
    13961450        gen(ctrue,c1);                          // duplicate reg save code 
    13971451  cfalse = movregconst(cfalse,reg,0,forflags);  // mov 0 into reg 
    13981452  regcon.immed.mval &= ~mask[reg];              // mark reg as unavail 
    13991453  ctrue = movregconst(ctrue,reg,1,forflags);    // mov 1 into reg 
    14001454  regcon.immed.mval &= ~mask[reg];              // mark reg as unavail 
    14011455  genjmp(cfalse,JMP,FLcode,(block *) cnop);     // skip over ctrue 
    14021456  c = cat4(c,cfalse,ctrue,cnop); 
    14031457  return c; 
    14041458} 
    14051459 
    14061460 
    14071461/************************ 
    14081462 * Complement operator 
    14091463 */ 
    14101464 
    14111465code *cdcom(elem *e,regm_t *pretregs) 
    14121466{ unsigned reg,op; 
    14131467  regm_t retregs,possregs; 
    14141468  code *c,*c1,*cg; 
    14151469  tym_t tym; 
    14161470  int sz; 
    14171471 
    14181472  if (*pretregs == 0) 
    14191473        return codelem(e->E1,pretregs,FALSE); 
    14201474  tym = tybasic(e->Ety); 
    14211475  sz = tysize[tym]; 
     1476  unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1477  unsigned grex = rex << 16; 
    14221478  possregs = (sz == 1) ? BYTEREGS : allregs; 
    14231479  retregs = *pretregs & possregs; 
    14241480  if (retregs == 0) 
    14251481        retregs = possregs; 
    14261482  c1 = codelem(e->E1,&retregs,FALSE); 
    14271483  cg = getregs(retregs);                /* retregs will be destroyed    */ 
    14281484#if 0 
    14291485  if (sz == 4 * REGSIZE) 
    14301486  { 
    14311487        c = gen2(CNIL,0xF7,modregrm(3,2,AX));   // NOT AX 
    14321488        gen2(c,0xF7,modregrm(3,2,BX));          // NOT BX 
    14331489        gen2(c,0xF7,modregrm(3,2,CX));          // NOT CX 
    14341490        gen2(c,0xF7,modregrm(3,2,DX));          // NOT DX 
    14351491  } 
    14361492  else 
    14371493#endif 
    14381494  { 
    14391495        reg = (sz <= REGSIZE) ? findreg(retregs) : findregmsw(retregs); 
    14401496        op = (sz == 1) ? 0xF6 : 0xF7; 
    14411497        c = genregs(CNIL,op,2,reg);             // NOT reg 
     1498        code_orrex(c, rex); 
    14421499        if (sz == 2 * REGSIZE) 
    14431500        {   reg = findreglsw(retregs); 
    14441501            genregs(c,op,2,reg);                // NOT reg+1 
    14451502        } 
    14461503  } 
    14471504  return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 
    14481505} 
    14491506 
    14501507/************************ 
    14511508 * Bswap operator 
    14521509 */ 
    14531510 
    14541511code *cdbswap(elem *e,regm_t *pretregs) 
    14551512{   unsigned reg,op; 
    14561513    regm_t retregs; 
    14571514    code *c,*c1,*cg; 
    14581515    tym_t tym; 
    14591516    int sz; 
    14601517 
    14611518    if (*pretregs == 0) 
    14621519        return codelem(e->E1,pretregs,FALSE); 
    14631520 
    14641521    tym = tybasic(e->Ety); 
    14651522    assert(tysize[tym] == 4); 
    14661523    retregs = *pretregs & allregs; 
    14671524    if (retregs == 0) 
    14681525        retregs = allregs; 
    14691526    c1 = codelem(e->E1,&retregs,FALSE); 
    14701527    cg = getregs(retregs);              // retregs will be destroyed 
    14711528    reg = findreg(retregs); 
    1472     c = gen2(CNIL,0x0FC8 + reg,0);      // BSWAP reg 
     1529    c = gen2(CNIL,0x0FC8 + (reg & 7),0);      // BSWAP reg 
     1530    if (reg & 8) 
     1531        code_orrex(c, REX_B); 
    14731532    return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 
    14741533} 
    14751534 
    14761535/************************* 
    14771536 * ?: operator 
    14781537 */ 
    14791538 
    14801539code *cdcond(elem *e,regm_t *pretregs) 
    14811540{ regm_t psw; 
    14821541  code *cc,*c,*c1,*cnop1,*c2,*cnop2; 
    14831542  con_t regconold,regconsave; 
    14841543  unsigned stackpushold,stackpushsave; 
    14851544  int ehindexold,ehindexsave; 
    14861545  unsigned jop; 
    14871546  unsigned op1; 
    14881547  unsigned sz1; 
    14891548  unsigned sz2; 
    14901549  elem *e1; 
    14911550  elem *e2; 
    14921551  elem *e21; 
    14931552  elem *e22; 
    14941553 
    14951554  /* vars to save state of 8087 */ 
    14961555  int stackusedold,stackusedsave; 
    14971556  NDP _8087old[arraysize(_8087elems)]; 
    14981557  NDP _8087save[arraysize(_8087elems)]; 
    14991558 
    15001559  _chkstack(); 
    15011560 
    15021561  //dbg_printf("cdcond(e = %p, *pretregs = x%x)\n",e,*pretregs); 
    15031562  e1 = e->E1; 
    15041563  e2 = e->E2; 
    15051564  e21 = e2->E1; 
    15061565  e22 = e2->E2; 
    15071566  cc = docommas(&e1); 
    15081567  cgstate.stackclean++; 
    15091568  psw = *pretregs & mPSW;               /* save PSW bit                 */ 
    15101569  op1 = e1->Eoper; 
    15111570  sz1 = tysize(e1->Ety); 
     1571  unsigned rex = (I64 && sz1 == 8) ? REX_W : 0; 
     1572  unsigned grex = rex << 16; 
    15121573  jop = jmpopcode(e1); 
    15131574 
    15141575  if (!OTrel(op1) && e1 == e21 && 
    15151576      sz1 <= REGSIZE && !tyfloating(e1->Ety)) 
    15161577  {     // Recognize (e ? e : f) 
    15171578        regm_t retregs; 
    15181579 
    15191580        cnop1 = gennop(CNIL); 
    15201581        retregs = *pretregs | mPSW; 
    15211582        c = codelem(e1,&retregs,FALSE); 
    15221583 
    15231584        c = cat(c,cse_flush(1));                // flush CSEs to memory 
    15241585        c = genjmp(c,jop,FLcode,(block *)cnop1); 
    15251586        freenode(e21); 
    15261587 
    15271588        regconsave = regcon; 
    15281589        stackpushsave = stackpush; 
    15291590 
    15301591        retregs |= psw; 
    15311592        if (retregs & (mBP | ALLREGS)) 
     
    15611622        reg = findreg(retregs); 
    15621623        v1 = e21->EV.Vlong; 
    15631624        v2 = e22->EV.Vlong; 
    15641625        if (jop == JNC) 
    15651626        {   v1 = v2; 
    15661627            v2 = e21->EV.Vlong; 
    15671628        } 
    15681629 
    15691630        opcode = 0x81; 
    15701631        switch (sz2) 
    15711632        {   case 1:     opcode--; 
    15721633                        v1 = (signed char) v1; 
    15731634                        v2 = (signed char) v2; 
    15741635                        break; 
    15751636            case 2:     v1 = (short) v1; 
    15761637                        v2 = (short) v2; 
    15771638                        break; 
    15781639        } 
    15791640 
    15801641        if (v1 == 0 && v2 == -1L) 
    1581             c = gen2(c,0xF6 + (opcode & 1),modregrm(3,2,reg));  // NOT reg 
     1642            c = gen2(c,0xF6 + (opcode & 1),grex | modregrmx(3,2,reg));  // NOT reg 
    15821643        else 
    15831644        { 
    15841645            v1 -= v2; 
    1585             c = genc2(c,opcode,modregrm(3,4,reg),v1);   // AND reg,v1-v2 
    1586             if (v2 == 1
     1646            c = genc2(c,opcode,grex | modregrmx(3,4,reg),v1);   // AND reg,v1-v2 
     1647            if (v2 == 1 && !I64
    15871648                gen1(c,0x40 + reg);                     // INC reg 
    1588             else if (v2 == -1L
     1649            else if (v2 == -1L && !I64
    15891650                gen1(c,0x48 + reg);                     // DEC reg 
    15901651            else 
    1591                 genc2(c,opcode,modregrm(3,0,reg),v2);   // ADD reg,v2 
     1652                genc2(c,opcode,grex | modregrmx(3,0,reg),v2);   // ADD reg,v2 
    15921653        } 
    15931654 
    15941655        freenode(e21); 
    15951656        freenode(e22); 
    15961657        freenode(e2); 
    15971658 
    15981659        c = cat(c,fixresult(e,retregs,pretregs)); 
    15991660        goto Lret; 
    16001661  } 
    16011662 
    16021663  if (op1 != OPcond && op1 != OPandand && op1 != OPoror && 
    16031664      op1 != OPnot && op1 != OPbool && 
    16041665      e21->Eoper == OPconst && 
    16051666      sz1 <= REGSIZE && 
    16061667      *pretregs & (mBP | ALLREGS) && 
    16071668      tysize(e21->Ety) <= REGSIZE && !tyfloating(e21->Ety)) 
    16081669  {     // Recognize (e ? c : f) 
    16091670        unsigned reg; 
    16101671        regm_t retregs; 
    16111672 
    16121673        cnop1 = gennop(CNIL); 
    16131674        retregs = mPSW; 
    16141675        jop = jmpopcode(e1);            // get jmp condition 
    16151676        c = codelem(e1,&retregs,FALSE); 
    16161677 
    16171678        // Set the register with e21 without affecting the flags 
    16181679        retregs = *pretregs & (ALLREGS | mBP); 
    16191680        if (retregs & ~regcon.mvar) 
    16201681            retregs &= ~regcon.mvar;    // don't disturb register variables 
    1621         c = regwithvalue(c,retregs,e21->EV.Vint,&reg,8); 
     1682        c = regwithvalue(c,retregs,e21->EV.Vint,&reg,sz1 == 8 ? 64|8 : 8); 
    16221683        retregs = mask[reg]; 
    16231684 
    16241685        c = cat(c,cse_flush(1));                // flush CSE's to memory 
    16251686        c = genjmp(c,jop,FLcode,(block *)cnop1); 
    16261687        freenode(e21); 
    16271688 
    16281689        regconsave = regcon; 
    16291690        stackpushsave = stackpush; 
    16301691 
    16311692        c2 = codelem(e22,&retregs,FALSE); 
    16321693 
    16331694        andregcon(&regconsave); 
    16341695        assert(stackpushsave == stackpush); 
    16351696 
    16361697        freenode(e2); 
    16371698        c = cat6(cc,c,c2,cnop1,fixresult(e,retregs,pretregs),NULL); 
    16381699        goto Lret; 
    16391700  } 
    16401701 
    16411702  cnop1 = gennop(CNIL); 
     
    17161777 *      cg:     [save reg code]         ;if we must preserve reg 
    17171778 *              CLR     reg             ;FALSE result (set Z also) 
    17181779 *              JMP     cnop2 
    17191780 * 
    17201781 *      cnop1:  NOP                     ;if e1 evaluates to TRUE 
    17211782 *              [save reg code]         ;preserve reg 
    17221783 * 
    17231784 *              MOV     reg,1           ;TRUE result 
    17241785 *                  or 
    17251786 *              CLR     reg             ;if return result in flags 
    17261787 *              INC     reg 
    17271788 * 
    17281789 *      cnop2:  NOP                     ;mark end of code 
    17291790 */ 
    17301791 
    17311792code *cdloglog(elem *e,regm_t *pretregs) 
    17321793{ regm_t retregs; 
    17331794  unsigned reg; 
    17341795  code *c; 
    17351796  code *cl,*cr,*cg,*cnop1,*cnop2,*cnop3; 
    1736   register code *c1; 
     1797  code *c1; 
    17371798  con_t regconsave; 
    17381799  unsigned stackpushsave; 
    17391800  int jcond; 
    17401801  elem *e2; 
     1802  unsigned sz = tysize(e->Ety); 
    17411803 
    17421804  /* We can trip the assert with the following:                         */ 
    17431805  /*    if ( (b<=a) ? (c<b || a<=c) : c>=a )                            */ 
    17441806  /* We'll generate ugly code for it, but it's too obscure a case       */ 
    17451807  /* to expend much effort on it.                                       */ 
    17461808  /*assert(*pretregs != mPSW);*/ 
    17471809 
    17481810  cgstate.stackclean++; 
    17491811  cnop1 = gennop(CNIL); 
    17501812  cnop3 = gennop(CNIL); 
    17511813  jcond = 0; 
    17521814  e2 = e->E2; 
    17531815  cl = (e->Eoper == OPoror) 
    17541816        ? logexp(e->E1,jcond | 1,FLcode,cnop1) 
    17551817        : logexp(e->E1,jcond,FLcode,cnop3); 
    17561818  regconsave = regcon; 
    17571819  stackpushsave = stackpush; 
    17581820  if (*pretregs == 0)                   /* if don't want result         */ 
    17591821  {     int noreturn = el_noreturn(e2); 
    17601822 
    17611823        cr = codelem(e2,pretregs,FALSE); 
    17621824        if (noreturn) 
    17631825        { 
    17641826            regconsave.used |= regcon.used; 
    17651827            regcon = regconsave; 
    17661828        } 
    17671829        else 
    17681830            andregcon(&regconsave); 
    17691831        assert(stackpush == stackpushsave); 
    17701832        c = cat4(cl,cr,cnop3,cnop1);    // eval code, throw away result 
    17711833        goto Lret; 
    17721834  } 
    17731835  cnop2 = gennop(CNIL); 
    17741836  if (tybasic(e2->Ety) == TYbool && 
    1775       tysize(e->Ety) == tysize(e2->Ety) && 
     1837      sz == tysize(e2->Ety) && 
    17761838      !(*pretregs & mPSW) && 
    17771839      e2->Eoper == OPcall) 
    17781840  { 
    17791841        cr = codelem(e2,pretregs,FALSE); 
    17801842 
    17811843        andregcon(&regconsave); 
    17821844 
    17831845        // stack depth should not change when evaluating E2 
    17841846        assert(stackpush == stackpushsave); 
    17851847 
    1786         assert(tysize(e->Ety) <= REGSIZE);      // result better be int 
     1848        assert(sz <= 4);                                        // result better be int 
    17871849        retregs = *pretregs & allregs; 
    17881850        cnop1 = cat(cnop1,allocreg(&retregs,&reg,TYint));       // allocate reg for result 
    17891851        cg = genjmp(NULL,JMP,FLcode,(block *) cnop2);           // JMP cnop2 
    17901852        cnop1 = movregconst(cnop1,reg,e->Eoper == OPoror,0);    // reg = 1 
    17911853        regcon.immed.mval &= ~mask[reg];                        // mark reg as unavail 
    17921854        *pretregs = retregs; 
    17931855        if (e->Eoper == OPoror) 
    17941856            c = cat6(cl,cr,cnop3,cg,cnop1,cnop2); 
    17951857        else 
    17961858            c = cat6(cl,cr,cg,cnop3,cnop1,cnop2); 
    17971859 
    17981860        goto Lret; 
    17991861  } 
    18001862  cr = logexp(e2,1,FLcode,cnop1); 
    18011863  andregcon(&regconsave); 
    18021864 
    18031865  /* stack depth should not change when evaluating E2   */ 
    18041866  assert(stackpush == stackpushsave); 
    18051867 
    1806   assert(tysize(e->Ety) <= REGSIZE);    // result better be int 
     1868  assert(sz <= 4);                      // result better be int 
    18071869  retregs = *pretregs & (ALLREGS | mBP); 
    18081870  if (!retregs) retregs = ALLREGS;      // if mPSW only 
    18091871  cg = allocreg(&retregs,&reg,TYint);   // allocate reg for result 
    18101872  for (c1 = cg; c1; c1 = code_next(c1)) // for each instruction 
    18111873        gen(cnop1,c1);                  // duplicate it 
    18121874  cg = movregconst(cg,reg,0,*pretregs & mPSW);  // MOV reg,0 
    18131875  regcon.immed.mval &= ~mask[reg];                      // mark reg as unavail 
    18141876  genjmp(cg,JMP,FLcode,(block *) cnop2);                // JMP cnop2 
    18151877  cnop1 = movregconst(cnop1,reg,1,*pretregs & mPSW);    // reg = 1 
    18161878  regcon.immed.mval &= ~mask[reg];                      // mark reg as unavail 
    18171879  *pretregs = retregs; 
    18181880  c = cat6(cl,cr,cnop3,cg,cnop1,cnop2); 
    18191881Lret: 
    18201882  cgstate.stackclean--; 
    18211883  return c; 
    18221884} 
    18231885 
    18241886 
    18251887/********************* 
    18261888 * Generate code for shift left or shift right (OPshl,OPshr,OPashr). 
     
    18341896  regm_t retregs,rretregs; 
    18351897  code *cg,*cl,*cr; 
    18361898  code *c; 
    18371899  elem *e1; 
    18381900  elem *e2; 
    18391901  regm_t forccs,forregs; 
    18401902  bool e2isconst; 
    18411903 
    18421904  e1 = e->E1; 
    18431905  if (*pretregs == 0)                   // if don't want result 
    18441906  {     c = codelem(e1,pretregs,FALSE); // eval left leaf 
    18451907        *pretregs = 0;                  // in case they got set 
    18461908        return cat(c,codelem(e->E2,pretregs,FALSE)); 
    18471909  } 
    18481910 
    18491911  tyml = tybasic(e1->Ety); 
    18501912  sz = tysize[tyml]; 
    18511913  assert(!tyfloating(tyml)); 
    18521914  uns = tyuns(tyml); 
    18531915  oper = e->Eoper; 
     1916    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1917    unsigned grex = rex << 16; 
    18541918 
    18551919#if SCPP 
    18561920  // Do this until the rest of the compiler does OPshr/OPashr correctly 
    18571921  if (oper == OPshr) 
    18581922        oper = (uns) ? OPshr : OPashr; 
    18591923#endif 
    18601924 
    18611925  switch (oper) 
    18621926  {     case OPshl: 
    18631927            s1 = 4;                     // SHL 
    18641928            s2 = 2;                     // RCL 
    18651929            break; 
    18661930        case OPshr: 
    18671931            s1 = 5;                     // SHR 
    18681932            s2 = 3;                     // RCR 
    18691933            break; 
    18701934        case OPashr: 
    18711935            s1 = 7;                     // SAR 
    18721936            s2 = 3;                     // RCR 
    18731937            break; 
    18741938        default: 
    18751939            assert(0); 
    18761940  } 
    18771941 
    18781942  c = cg = cr = CNIL;                   /* initialize                   */ 
    18791943  e2 = e->E2; 
    18801944  forccs = *pretregs & mPSW;            /* if return result in CCs      */ 
    18811945  forregs = *pretregs & (ALLREGS | mBP); // mask of possible return regs 
    18821946  e2isconst = FALSE;                    /* assume for the moment        */ 
    18831947  byte = (sz == 1); 
    18841948  switch (e2->Eoper) 
    18851949  { 
    18861950    case OPconst: 
    18871951        e2isconst = TRUE;               /* e2 is a constant             */ 
    18881952        shiftcnt = e2->EV.Vint;         /* get shift count              */ 
    1889         if ((I32 && sz <= REGSIZE) || 
     1953        if ((!I16 && sz <= REGSIZE) || 
    18901954            shiftcnt <= 4 ||            /* if sequence of shifts        */ 
    18911955            (sz == 2 && 
    18921956                (shiftcnt == 8 || config.target_cpu >= TARGET_80286)) || 
    18931957            (sz == 2 * REGSIZE && shiftcnt == 8 * REGSIZE) 
    18941958           ) 
    18951959        {       retregs = (forregs) ? forregs 
    18961960                                    : ALLREGS; 
    18971961                if (byte) 
    18981962                {   retregs &= BYTEREGS; 
    18991963                    if (!retregs) 
    19001964                        retregs = BYTEREGS; 
    19011965                } 
    19021966                else if (sz > REGSIZE && sz <= 2 * REGSIZE && 
    19031967                         !(retregs & mMSW)) 
    19041968                    retregs |= mMSW & ALLREGS; 
    19051969                if (s1 == 7)    /* if arithmetic right shift */ 
    19061970                { 
    19071971                    if (shiftcnt == 8) 
    19081972                        retregs = mAX; 
    19091973                    else if (sz == 2 * REGSIZE && shiftcnt == 8 * REGSIZE) 
     
    19181982                   ) 
    19191983                {   // Handle (shtlng)s << 16 
    19201984                    regm_t r; 
    19211985 
    19221986                    r = retregs & mMSW; 
    19231987                    cl = codelem(e1->E1,&r,FALSE);      // eval left leaf 
    19241988                    cl = regwithvalue(cl,retregs & mLSW,0,&resreg,0); 
    19251989                    cg = getregs(r); 
    19261990                    retregs = r | mask[resreg]; 
    19271991                    if (forccs) 
    19281992                    {   sreg = findreg(r); 
    19291993                        cg = gentstreg(cg,sreg); 
    19301994                        *pretregs &= ~mPSW;             // already set 
    19311995                    } 
    19321996                    freenode(e1); 
    19331997                    freenode(e2); 
    19341998                    break; 
    19351999                } 
    19362000 
    19372001                // See if we should use LEA reg,xxx instead of shift 
    1938                 if (I32 && shiftcnt >= 1 && shiftcnt <= 3 && 
    1939                     sz == REGSIZE && oper == OPshl && 
     2002                if (!I16 && shiftcnt >= 1 && shiftcnt <= 3 && 
     2003                    (sz == REGSIZE || (I64 && sz == 4)) && 
     2004                    oper == OPshl && 
    19402005                    e1->Eoper == OPvar && 
    19412006                    !(*pretregs & mPSW) && 
    19422007                    config.flags4 & CFG4speed 
    19432008                   ) 
    19442009                {   Symbol *s1 = e1->EV.sp.Vsym; 
    19452010                    unsigned reg; 
    19462011                    regm_t regm; 
    19472012                    code cs; 
    19482013 
    19492014                    if (isregvar(e1,&regm,&reg) && !(regm & retregs)) 
    19502015                    { 
    19512016                        cl = allocreg(&retregs,&resreg,e->Ety); 
    19522017                        buildEA(&cs,-1,reg,1 << shiftcnt,0); 
    19532018                        cs.Iop = 0x8D; 
    1954                         cs.Irm |= modregrm(0,resreg,0); 
     2019                        code_newreg(&cs,resreg); 
    19552020                        cs.Iflags = 0; 
    19562021                        cg = gen(NULL,&cs);             // LEA resreg,[reg * ss] 
    19572022                        freenode(e1); 
    19582023                        freenode(e2); 
    19592024                        break; 
    19602025                    } 
    19612026                } 
    19622027 
    19632028                cl = codelem(e1,&retregs,FALSE); // eval left leaf 
    19642029                //assert((retregs & regcon.mvar) == 0); 
    19652030                cg = getregs(retregs);          // trash these regs 
    19662031 
    19672032                { 
    19682033                    if (sz == 2 * REGSIZE) 
    19692034                    {   resreg = findregmsw(retregs); 
    19702035                        sreg = findreglsw(retregs); 
    19712036                    } 
    19722037                    else 
    19732038                        resreg = findreg(retregs); 
    19742039                    if (config.target_cpu >= TARGET_80286 && 
    19752040                        sz <= REGSIZE) 
    19762041                    { 
    19772042                        /* SHL resreg,shiftcnt  */ 
    19782043                        assert(!(sz == 1 && (mask[resreg] & ~BYTEREGS))); 
    1979                         c = genc2(CNIL,0xC1 ^ byte,modregrm(3,s1,resreg),shiftcnt); 
     2044                        c = genc2(CNIL,0xC1 ^ byte,grex | modregxrmx(3,s1,resreg),shiftcnt); 
    19802045                        if (shiftcnt == 1) 
    19812046                            c->Iop += 0x10;     /* short form of shift  */ 
    19822047                        // See if we need operand size prefix 
    1983                         if (I32 && oper != OPshl && sz == 2) 
     2048                        if (!I16 && oper != OPshl && sz == 2) 
    19842049                            c->Iflags |= CFopsize; 
    19852050                        if (forccs) 
    19862051                            c->Iflags |= CFpsw;         // need flags result 
    19872052                    } 
    19882053                    else if (shiftcnt == 8) 
    1989                     {   if (!(retregs & BYTEREGS)
     2054                    {   if (!(retregs & BYTEREGS) || resreg >= 4
    19902055                        { 
    19912056                            cl = cat(cl,cg); 
    19922057                            goto L1; 
    19932058                        } 
    19942059 
    19952060                        if (pass != PASSfinal && (!forregs || forregs & (mSI | mDI))) 
    19962061                        { 
    19972062                            // e1 might get into SI or DI in a later pass, 
    19982063                            // so don't put CX into a register 
    19992064                            cg = cat(cg, getregs(mCX)); 
    20002065                        } 
    20012066 
    20022067                        if (oper == OPshl) 
    20032068                        {       /* MOV regH,regL        XOR regL,regL   */ 
     2069                                assert(resreg < 4 && !rex); 
    20042070                                c = genregs(CNIL,0x8A,resreg+4,resreg); 
    20052071                                genregs(c,0x32,resreg,resreg); 
    20062072                        } 
    20072073                        else            // OPshr/OPashr 
    20082074                        { 
    20092075                            /* MOV regL,regH    */ 
    20102076                            c = genregs(CNIL,0x8A,resreg,resreg+4); 
    20112077                            if (oper == OPashr) 
    20122078                                gen1(c,0x98);           /* CBW          */ 
    20132079                            else 
    20142080                                genregs(c,0x32,resreg+4,resreg+4); /* CLR regH */ 
    20152081                        } 
    20162082                        if (forccs) 
    20172083                                gentstreg(c,resreg); 
    20182084                    } 
    20192085                    else if (shiftcnt == REGSIZE * 8)   // it's an lword 
    20202086                    { 
    20212087                        if (oper == OPshl) 
    20222088                            swap((int *) &resreg,(int *) &sreg); 
    20232089                        c = genmovreg(CNIL,sreg,resreg);        // MOV sreg,resreg 
     
    20662132        else 
    20672133        { 
    20682134            if (!(retregs & mMSW)) 
    20692135                retregs = ALLREGS & ~mCX; 
    20702136        } 
    20712137        cl = codelem(e->E1,&retregs,FALSE);     /* eval left leaf       */ 
    20722138 
    20732139        if (sz <= REGSIZE) 
    20742140            resreg = findreg(retregs); 
    20752141        else 
    20762142        { 
    20772143            resreg = findregmsw(retregs); 
    20782144            sreg = findreglsw(retregs); 
    20792145        } 
    20802146    L1: 
    20812147        rretregs = mCX;                 /* CX is shift count    */ 
    20822148        if (sz <= REGSIZE) 
    20832149        { 
    20842150            cr = scodelem(e2,&rretregs,retregs,FALSE); /* get rvalue */ 
    20852151            cg = getregs(retregs);      /* trash these regs             */ 
    2086             c = gen2(CNIL,0xD3 ^ byte,modregrm(3,s1,resreg)); /* Sxx resreg,CX */ 
     2152            c = gen2(CNIL,0xD3 ^ byte,grex | modregrmx(3,s1,resreg)); /* Sxx resreg,CX */ 
    20872153 
    20882154            // Note that a shift by CL does not set the flags if 
    20892155            // CL == 0. If e2 is a constant, we know it isn't 0 
    20902156            // (it would have been optimized out). 
    20912157            if (e2isconst) 
    20922158                *pretregs &= mBP | ALLREGS; // flags already set with result 
    20932159        } 
    20942160        else if (sz == 2 * REGSIZE && 
    20952161                 config.target_cpu >= TARGET_80386) 
    20962162        {   unsigned hreg,lreg; 
    20972163 
    20982164            hreg = resreg; 
    20992165            lreg = sreg; 
    21002166            if (e2isconst) 
    21012167            { 
    21022168                cr = NULL; 
    21032169                cg = getregs(retregs); 
    21042170                if (shiftcnt & (REGSIZE * 8)) 
    21052171                { 
    21062172                    if (oper == OPshr) 
     
    23092375                return cdind87(e, pretregs); 
    23102376        } 
    23112377  } 
    23122378 
    23132379  e1 = e->E1; 
    23142380  assert(e1); 
    23152381  switch (tym) 
    23162382  {     case TYstruct: 
    23172383        case TYarray: 
    23182384            // This case should never happen, why is it here? 
    23192385            tym = TYnptr;               // don't confuse allocreg() 
    23202386#if !TARGET_FLAT 
    23212387            if (*pretregs & (mES | mCX) || e->Ety & mTYfar) 
    23222388                    tym = TYfptr; 
    23232389#endif 
    23242390 
    23252391#if 0 
    23262392  c = getlvalue(&cs,e,RMload);          // get addressing mode 
    23272393  if (*pretregs == 0) 
    23282394        return c; 
    2329   idxregs = idxregm(cs.Irm,cs.Isib);    /* mask of index regs used      */ 
     2395  idxregs = idxregm(&cs);               // mask of index regs used 
    23302396  c = cat(c,fixresult(e,idxregs,pretregs)); 
    23312397  return c; 
    23322398#endif 
    23332399            break; 
    23342400  } 
    23352401  sz = tysize[tym]; 
    23362402  byte = tybyte(tym) != 0; 
    23372403 
    23382404  c = getlvalue(&cs,e,RMload);          // get addressing mode 
    23392405  /*fprintf(stderr,"cd2 :\n"); WRcodlst(c);*/ 
    23402406  if (*pretregs == 0) 
    23412407        return c; 
    23422408 
    2343   idxregs = idxregm(cs.Irm,cs.Isib);    /* mask of index regs used      */ 
     2409  idxregs = idxregm(&cs);               // mask of index regs used 
    23442410 
    23452411  if (*pretregs == mPSW) 
    23462412  { 
    2347         if (I32 && tym == TYfloat) 
     2413        if (!I16 && tym == TYfloat) 
    23482414        {       retregs = ALLREGS & ~idxregs; 
    23492415                c = cat(c,allocreg(&retregs,&reg,TYfloat)); 
    23502416                cs.Iop = 0x8B; 
    2351                 cs.Irm |= modregrm(0,reg,0); 
    2352                 ce = gen(CNIL,&cs);                     /* MOV reg,lsw  */ 
    2353                 gen2(ce,0xD1,modregrm(3,4,reg));        /* SHL reg,1    */ 
     2417                code_newreg(&cs,reg); 
     2418                ce = gen(CNIL,&cs);                     // MOV reg,lsw 
     2419                gen2(ce,0xD1,modregrmx(3,4,reg));       // SHL reg,1 
    23542420        } 
    23552421        else if (sz <= REGSIZE) 
    23562422        { 
    23572423                cs.Iop = 0x81 ^ byte; 
    23582424                cs.Irm |= modregrm(0,7,0); 
    23592425                cs.IFL2 = FLconst; 
    23602426                cs.IEV2.Vint = 0; 
    23612427                ce = gen(CNIL,&cs);             /* CMP [idx],0          */ 
    23622428        } 
    2363         else if (I32 && sz == REGSIZE + 2)      // if far pointer 
     2429        else if (!I16 && sz == REGSIZE + 2)      // if far pointer 
    23642430        {       retregs = ALLREGS & ~idxregs; 
    23652431                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    23662432                cs.Iop = 0x0F; 
    23672433                cs.Iop2 = 0xB7; 
    23682434                cs.Irm |= modregrm(0,reg,0); 
    23692435                getlvalue_msw(&cs); 
    23702436                ce = gen(CNIL,&cs);             /* MOVZX reg,msw        */ 
    23712437                goto L4; 
    23722438        } 
    23732439        else if (sz <= 2 * REGSIZE) 
    23742440        {       retregs = ALLREGS & ~idxregs; 
    23752441                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    23762442                cs.Iop = 0x8B; 
    23772443                cs.Irm |= modregrm(0,reg,0); 
    23782444                getlvalue_msw(&cs); 
    23792445                ce = gen(CNIL,&cs);             /* MOV reg,msw          */ 
    23802446                if (I32) 
    23812447                {   if (tym == TYdouble || tym == TYdouble_alias) 
    23822448                        gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 
    23832449                } 
     
    24072473 
    24082474            /* Optimizer should not CSE these, as the result is worse code! */ 
    24092475            assert(!e->Ecount); 
    24102476 
    24112477            cs.Iop = 0xFF; 
    24122478            cs.Irm |= modregrm(0,6,0); 
    24132479            cs.IEVoffset1 += 8 - REGSIZE; 
    24142480            stackchanged = 1; 
    24152481            i = 8 - REGSIZE; 
    24162482            do 
    24172483            { 
    24182484                c = gen(c,&cs);                         /* PUSH EA+i    */ 
    24192485                c = genadjesp(c,REGSIZE); 
    24202486                cs.IEVoffset1 -= REGSIZE; 
    24212487                stackpush += REGSIZE; 
    24222488                i -= REGSIZE; 
    24232489            } 
    24242490            while (i >= 0); 
    24252491            goto L3; 
    24262492        } 
    2427         if (!I32 && sz == 8) 
     2493        if (I16 && sz == 8) 
    24282494            retregs = DOUBLEREGS_16; 
    24292495 
    24302496        /* Watch out for loading an lptr from an lptr! We must have     */ 
    24312497        /* the offset loaded into a different register.                 */ 
    24322498        /*if (retregs & mES && (cs.Iflags & CFSEG) == CFes) 
    24332499                retregs = ALLREGS;*/ 
    24342500 
    24352501        { 
    24362502        assert(!byte || retregs & BYTEREGS); 
    24372503        c = cat(c,allocreg(&retregs,&reg,tym)); /* alloc registers */ 
    24382504        } 
    24392505        if (sz <= REGSIZE) 
    24402506        { 
    24412507                cs.Iop = 0x8B ^ byte; 
    2442         L2:     cs.Irm |= modregrm(0,reg,0); 
     2508        L2:     code_newreg(&cs,reg); 
    24432509                ce = gen(CNIL,&cs);     /* MOV reg,[idx]                */ 
    24442510        } 
    24452511        else if ((tym == TYfptr || tym == TYhptr) && retregs & mES) 
    24462512        { 
    24472513                cs.Iop = 0xC4;          /* LES reg,[idx]                */ 
    24482514                goto L2; 
    24492515        } 
    24502516        else if (sz <= 2 * REGSIZE) 
    24512517        {   unsigned lsreg; 
    24522518 
    24532519            cs.Iop = 0x8B; 
    24542520            /* Be careful not to interfere with index registers */ 
    24552521            if (I32) 
    24562522            { 
    24572523                /* Can't handle if both result registers are used in    */ 
    24582524                /* the addressing mode.                                 */ 
    24592525                if ((retregs & idxregs) == retregs) 
    24602526                { 
    24612527                    retregs = mMSW & allregs & ~idxregs; 
    24622528                    if (!retregs) 
     
    25012567                    ce = gen(CNIL,&cs);                 // MOV reg,msw 
    25022568                    if (sz == REGSIZE + 2) 
    25032569                        ce->Iflags |= CFopsize; 
    25042570                    getlvalue_lsw(&cs);                 // MOV lsreg,lsw 
    25052571                } 
    25062572                NEWREG(cs.Irm,lsreg); 
    25072573                gen(ce,&cs); 
    25082574            } 
    25092575            else 
    25102576            { 
    25112577                /* Index registers are always the lsw!                  */ 
    25122578                cs.Irm |= modregrm(0,reg,0); 
    25132579                getlvalue_msw(&cs); 
    25142580                ce = gen(CNIL,&cs);     /* MOV reg,msw          */ 
    25152581                lsreg = findreglsw(retregs); 
    25162582                NEWREG(cs.Irm,lsreg); 
    25172583                getlvalue_lsw(&cs);     /* MOV lsreg,lsw        */ 
    25182584                gen(ce,&cs); 
    25192585            } 
    25202586        } 
    2521         else if (!I32 && sz == 8) 
     2587        else if (I16 && sz == 8) 
    25222588        { 
    25232589                assert(reg == AX); 
    25242590                cs.Iop = 0x8B; 
    25252591                cs.IEVoffset1 += 6; 
    25262592                ce = gen(CNIL,&cs);             /* MOV AX,EA+6          */ 
    25272593                cs.Irm |= modregrm(0,CX,0); 
    25282594                cs.IEVoffset1 -= 4; 
    25292595                gen(ce,&cs);                    /* MOV CX,EA+2          */ 
    25302596                NEWREG(cs.Irm,DX); 
    25312597                cs.IEVoffset1 -= 2; 
    25322598                gen(ce,&cs);                    /* MOV DX,EA            */ 
    25332599                cs.IEVoffset1 += 4; 
    25342600                NEWREG(cs.Irm,BX); 
    25352601                gen(ce,&cs);                    /* MOV BX,EA+4          */ 
    25362602        } 
    25372603        else 
    25382604                assert(0); 
    25392605        c = cat(c,ce); 
    25402606    L3: 
    25412607        c = cat(c,fixresult(e,retregs,pretregs)); 
    25422608  } 
    25432609  /*fprintf(stderr,"cdafter :\n"); WRcodlst(c);*/ 
    25442610  return c; 
    25452611} 
    25462612 
    25472613 
    25482614 
    25492615#if TARGET_FLAT 
    25502616#define cod2_setES(ty) NULL 
    25512617#else 
    25522618/******************************** 
    25532619 * Generate code to load ES with the right segment value, 
    25542620 * do nothing if e is a far pointer. 
    25552621 */ 
    25562622 
    2557 STATIC code * cod2_setES(tym_t ty) 
     2623STATIC code *cod2_setES(tym_t ty) 
    25582624{   code *c2; 
    25592625    int push; 
    25602626 
    25612627    c2 = CNIL; 
    25622628    switch (tybasic(ty)) 
    25632629    { 
    25642630        case TYnptr: 
    25652631            if (!(config.flags3 & CFG3eseqds)) 
    25662632            {   push = 0x1E;            /* PUSH DS              */ 
    25672633                goto L1; 
    25682634            } 
    25692635            break; 
    25702636        case TYcptr: 
    25712637            push = 0x0E;                /* PUSH CS              */ 
    25722638            goto L1; 
    25732639        case TYsptr: 
    25742640            if ((config.wflags & WFssneds) || !(config.flags3 & CFG3eseqds)) 
    25752641            {   push = 0x16;            /* PUSH SS              */ 
    25762642            L1: 
    25772643                /* Must load ES */ 
    25782644                c2 = getregs(mES); 
    25792645                c2 = gen1(c2,push); 
    25802646                gen1(c2,0x07);          /* POP ES               */ 
    25812647            } 
    25822648            break; 
    25832649    } 
    25842650    return c2; 
    25852651} 
    25862652#endif 
    25872653 
    25882654/******************************** 
    25892655 * Generate code for intrinsic strlen(). 
    25902656 */ 
    25912657 
    25922658code *cdstrlen( elem *e, regm_t *pretregs) 
    25932659{   code *c1,*c2,*c3,*c4; 
    2594     regm_t retregs; 
    2595     tym_t ty1; 
    25962660 
    25972661    /* Generate strlen in CX: 
    25982662        LES     DI,e1 
    25992663        CLR     AX                      ;scan for 0 
    26002664        MOV     CX,-1                   ;largest possible string 
    26012665        REPNE   SCASB 
    26022666        NOT     CX 
    26032667        DEC     CX 
    26042668     */ 
    26052669 
    2606     retregs = mDI; 
    2607     ty1 = e->E1->Ety; 
     2670    regm_t retregs = mDI; 
     2671    tym_t ty1 = e->E1->Ety; 
    26082672    if (!tyreg(ty1)) 
    26092673        retregs |= mES; 
    26102674    c1 = codelem(e->E1,&retregs,FALSE); 
    26112675 
    26122676    /* Make sure ES contains proper segment value       */ 
    26132677    c2 = cod2_setES(ty1); 
    26142678 
     2679    unsigned char rex = I64 ? REX_W : 0; 
     2680 
    26152681    c3 = getregs_imm(mAX | mCX); 
    26162682    c3 = movregconst(c3,AX,0,1);                /* MOV AL,0             */ 
    2617     c3 = movregconst(c3,CX,-1,0);               /* MOV CX,-1            */ 
     2683    c3 = movregconst(c3,CX,-1LL,I64 ? 64 : 0);  // MOV CX,-1 
    26182684    c3 = cat(c3,getregs(mDI|mCX)); 
    26192685    c3 = gen1(c3,0xF2);                         /* REPNE                        */ 
    26202686    gen1(c3,0xAE);                              /* SCASB                */ 
    26212687    genregs(c3,0xF7,2,CX);                      /* NOT CX               */ 
    2622     c4 = gen1(CNIL,0x48 + CX);                  /* DEC CX               */ 
     2688    code_orrex(c3,rex); 
     2689    if (I64) 
     2690        c4 = gen2(CNIL,0xFF,(rex << 16) | modregrm(3,1,CX));  // DEC reg 
     2691    else 
     2692        c4 = gen1(CNIL,0x48 + CX);              // DEC CX 
    26232693 
    26242694    if (*pretregs & mPSW) 
    26252695    { 
    26262696        c4->Iflags |= CFpsw; 
    26272697        *pretregs &= ~mPSW; 
    26282698    } 
    26292699    return cat6(c1,c2,c3,c4,fixresult(e,mCX,pretregs),CNIL); 
    26302700} 
    26312701 
    26322702 
    26332703/********************************* 
    26342704 * Generate code for strcmp(s1,s2) intrinsic. 
    26352705 */ 
    26362706 
    26372707code *cdstrcmp( elem *e, regm_t *pretregs) 
    26382708{   code *c1,*c1a,*c2,*c3,*c4; 
    2639     regm_t retregs1; 
    2640     regm_t retregs; 
    2641     tym_t ty1,ty2; 
    26422709    char need_DS; 
    26432710    int segreg; 
    26442711 
    26452712    /* 
    26462713        MOV     SI,s1                   ;get destination pointer (s1) 
    26472714        MOV     CX,s1+2 
    26482715        LES     DI,s2                   ;get source pointer (s2) 
    26492716        PUSH    DS 
    26502717        MOV     DS,CX 
    26512718        CLR     AX                      ;scan for 0 
    26522719        MOV     CX,-1                   ;largest possible string 
    26532720        REPNE   SCASB 
    26542721        NOT     CX                      ;CX = string length of s2 
    26552722        SUB     DI,CX                   ;point DI back to beginning 
    26562723        REPE    CMPSB                   ;compare string 
    26572724        POP     DS 
    26582725        JE      L1                      ;strings are equal 
    26592726        SBB     AX,AX 
    26602727        SBB     AX,-1 
    26612728    L1: 
    26622729    */ 
    26632730 
    2664     retregs1 = mSI; 
    2665     ty1 = e->E1->Ety; 
     2731    regm_t retregs1 = mSI; 
     2732    tym_t ty1 = e->E1->Ety; 
    26662733    if (!tyreg(ty1)) 
    26672734        retregs1 |= mCX; 
    26682735    c1 = codelem(e->E1,&retregs1,FALSE); 
    26692736 
    2670     retregs = mDI; 
    2671     ty2 = e->E2->Ety; 
     2737    regm_t retregs = mDI; 
     2738    tym_t ty2 = e->E2->Ety; 
    26722739    if (!tyreg(ty2)) 
    26732740        retregs |= mES; 
    26742741    c1 = cat(c1,scodelem(e->E2,&retregs,retregs1,FALSE)); 
    26752742 
    26762743    /* Make sure ES contains proper segment value       */ 
    26772744    c2 = cod2_setES(ty2); 
    26782745    c3 = getregs_imm(mAX | mCX); 
     2746 
     2747    unsigned char rex = I64 ? REX_W : 0; 
    26792748 
    26802749    /* Load DS with right value */ 
    26812750    switch (tybasic(ty1)) 
    26822751    { 
    26832752        case TYnptr: 
    26842753            need_DS = FALSE; 
    26852754            break; 
    26862755        case TYsptr: 
    26872756            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    26882757                segreg = SEG_SS; 
    26892758            else 
    26902759                segreg = SEG_DS; 
    26912760            goto L1; 
    26922761        case TYcptr: 
    26932762            segreg = SEG_CS; 
    26942763        L1: 
    26952764            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    26962765            gen1(c3,0x06 + (segreg << 3));              /* PUSH segreg  */ 
    26972766            gen1(c3,0x1F);                              /* POP  DS      */ 
    26982767            need_DS = TRUE; 
    26992768            break; 
    27002769        case TYfptr: 
    27012770        case TYvptr: 
    27022771        case TYhptr: 
    27032772            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    27042773            gen2(c3,0x8E,modregrm(3,SEG_DS,CX));        /* MOV DS,CX    */ 
    27052774            need_DS = TRUE; 
    27062775            break; 
    27072776        default: 
    27082777            assert(0); 
    27092778    } 
    27102779 
    27112780    c3 = movregconst(c3,AX,0,0);                /* MOV AX,0             */ 
    2712     c3 = movregconst(c3,CX,-1,0);               /* MOV CX,-1            */ 
     2781    c3 = movregconst(c3,CX,-1LL,I64 ? 64 : 0);  // MOV CX,-1 
    27132782    c3 = cat(c3,getregs(mSI|mDI|mCX)); 
    27142783    c3 = gen1(c3,0xF2);                         /* REPNE                        */ 
    27152784    gen1(c3,0xAE);                              /* SCASB                */ 
    27162785    genregs(c3,0xF7,2,CX);                      /* NOT CX               */ 
     2786    code_orrex(c3,rex); 
    27172787    genregs(c3,0x2B,DI,CX);                     /* SUB DI,CX            */ 
     2788    code_orrex(c3,rex); 
    27182789    gen1(c3,0xF3);                              /* REPE                 */ 
    27192790    gen1(c3,0xA6);                              /* CMPSB                */ 
    27202791    if (need_DS) 
    27212792        gen1(c3,0x1F);                          /* POP DS               */ 
    27222793    c4 = gennop(CNIL); 
    27232794    if (*pretregs != mPSW)                      /* if not flags only    */ 
    27242795    { 
    27252796        genjmp(c3,JE,FLcode,(block *) c4);      /* JE L1                */ 
    27262797        c3 = cat(c3,getregs(mAX)); 
    27272798        genregs(c3,0x1B,AX,AX);                 /* SBB AX,AX            */ 
    2728         genc2(c3,0x81,modregrm(3,3,AX),(targ_uns)-1);   /* SBB AX,-1            */ 
     2799        code_orrex(c3,rex); 
     2800        genc2(c3,0x81,(rex << 16) | modregrm(3,3,AX),(targ_uns)-1);   // SBB AX,-1 
    27292801    } 
    27302802 
    27312803    *pretregs &= ~mPSW; 
    27322804    return cat6(c1,c2,c3,c4,fixresult(e,mAX,pretregs),CNIL); 
    27332805} 
    27342806 
    27352807/********************************* 
    27362808 * Generate code for memcmp(s1,s2,n) intrinsic. 
    27372809 */ 
    27382810 
    27392811code *cdmemcmp(elem *e,regm_t *pretregs) 
    27402812{   code *c1,*c2,*c3,*c4; 
    2741     regm_t retregs1; 
    2742     regm_t retregs; 
    2743     regm_t retregs3; 
    2744     tym_t ty1,ty2; 
    27452813    char need_DS; 
    27462814    int segreg; 
    2747     elem *e1; 
    27482815 
    27492816    /* 
    27502817        MOV     SI,s1                   ;get destination pointer (s1) 
    27512818        MOV     DX,s1+2 
    27522819        LES     DI,s2                   ;get source pointer (s2) 
    27532820        MOV     CX,n                    ;get number of bytes to compare 
    27542821        PUSH    DS 
    27552822        MOV     DS,DX 
    27562823        XOR     AX,AX 
    27572824        REPE    CMPSB                   ;compare string 
    27582825        POP     DS 
    27592826        JE      L1                      ;strings are equal 
    27602827        SBB     AX,AX 
    27612828        SBB     AX,-1 
    27622829    L1: 
    27632830    */ 
    27642831 
    2765     e1 = e->E1; 
     2832    elem *e1 = e->E1; 
    27662833    assert(e1->Eoper == OPparam); 
    27672834 
    27682835    // Get s1 into DX:SI 
    2769     retregs1 = mSI; 
    2770     ty1 = e1->E1->Ety; 
     2836    regm_t retregs1 = mSI; 
     2837    tym_t ty1 = e1->E1->Ety; 
    27712838    if (!tyreg(ty1)) 
    27722839        retregs1 |= mDX; 
    27732840    c1 = codelem(e1->E1,&retregs1,FALSE); 
    27742841 
    27752842    // Get s2 into ES:DI 
    2776     retregs = mDI; 
    2777     ty2 = e1->E2->Ety; 
     2843    regm_t retregs = mDI; 
     2844    tym_t ty2 = e1->E2->Ety; 
    27782845    if (!tyreg(ty2)) 
    27792846        retregs |= mES; 
    27802847    c1 = cat(c1,scodelem(e1->E2,&retregs,retregs1,FALSE)); 
    27812848    freenode(e1); 
    27822849 
    27832850    // Get nbytes into CX 
    2784     retregs3 = mCX; 
     2851    regm_t retregs3 = mCX; 
    27852852    c1 = cat(c1,scodelem(e->E2,&retregs3,retregs | retregs1,FALSE)); 
    27862853 
    27872854    /* Make sure ES contains proper segment value       */ 
    27882855    c2 = cod2_setES(ty2); 
    27892856 
    27902857    /* Load DS with right value */ 
    27912858    c3 = NULL; 
    27922859    switch (tybasic(ty1)) 
    27932860    { 
    27942861        case TYnptr: 
    27952862            need_DS = FALSE; 
    27962863            break; 
    27972864        case TYsptr: 
    27982865            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    27992866                segreg = SEG_SS; 
    28002867            else 
    28012868                segreg = SEG_DS; 
    28022869            goto L1; 
    28032870        case TYcptr: 
    28042871            segreg = SEG_CS; 
     
    28632930        CLR     AX                      ;scan for 0 
    28642931        MOV     CX,-1                   ;largest possible string 
    28652932        REPNE   SCASB                   ;find end of s2 
    28662933        NOT     CX                      ;CX = strlen(s2) + 1 (for EOS) 
    28672934        SUB     DI,CX 
    28682935        MOV     SI,DI 
    28692936        PUSH    DS 
    28702937        PUSH    ES 
    28712938        LES     DI,s1 
    28722939        POP     DS 
    28732940        MOV     AX,DI                   ;return value is s1 
    28742941        REP     MOVSB 
    28752942        POP     DS 
    28762943    */ 
    28772944 
    28782945    stackchanged = 1; 
    28792946    retregs = mDI; 
    28802947    ty2 = tybasic(e->E2->Ety); 
    28812948    if (!tyreg(ty2)) 
    28822949        retregs |= mES; 
     2950    unsigned char rex = I64 ? REX_W : 0; 
    28832951    c1 = codelem(e->E2,&retregs,FALSE); 
    28842952 
    28852953    /* Make sure ES contains proper segment value       */ 
    28862954    c2 = cod2_setES(ty2); 
    28872955    c3 = getregs_imm(mAX | mCX); 
    28882956    c3 = movregconst(c3,AX,0,1);                /* MOV AL,0             */ 
    2889     c3 = movregconst(c3,CX,-1,0);               /* MOV CX,-1            */ 
     2957    c3 = movregconst(c3,CX,-1,I64?64:0);        // MOV CX,-1 
    28902958    c3 = cat(c3,getregs(mAX|mCX|mSI|mDI)); 
    28912959    c3 = gen1(c3,0xF2);                         /* REPNE                        */ 
    28922960    gen1(c3,0xAE);                              /* SCASB                */ 
    28932961    genregs(c3,0xF7,2,CX);                      /* NOT CX               */ 
     2962    code_orrex(c3,rex); 
    28942963    genregs(c3,0x2B,DI,CX);                     /* SUB DI,CX            */ 
     2964    code_orrex(c3,rex); 
    28952965    genmovreg(c3,SI,DI);                        /* MOV SI,DI            */ 
     2966    code_orrex(c3,rex); 
    28962967 
    28972968    /* Load DS with right value */ 
    28982969    switch (ty2) 
    28992970    { 
    29002971        case TYnptr: 
    29012972            need_DS = FALSE; 
    29022973            break; 
    29032974        case TYsptr: 
    29042975            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    29052976                segreg = SEG_SS; 
    29062977            else 
    29072978                segreg = SEG_DS; 
    29082979            goto L1; 
    29092980        case TYcptr: 
    29102981            segreg = SEG_CS; 
    29112982        L1: 
    29122983            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    29132984            gen1(c3,0x06 + (segreg << 3));              /* PUSH segreg  */ 
    29142985            genadjesp(c3,REGSIZE * 2); 
    29152986            need_DS = TRUE; 
     
    29232994        default: 
    29242995            assert(0); 
    29252996    } 
    29262997 
    29272998    retregs = mDI; 
    29282999    ty1 = tybasic(e->E1->Ety); 
    29293000    if (!tyreg(ty1)) 
    29303001        retregs |= mES; 
    29313002    c3 = cat(c3,scodelem(e->E1,&retregs,mCX|mSI,FALSE)); 
    29323003    c3 = cat(c3,getregs(mAX|mCX|mSI|mDI)); 
    29333004 
    29343005    /* Make sure ES contains proper segment value       */ 
    29353006    if (ty2 != TYnptr || ty1 != ty2) 
    29363007        c4 = cod2_setES(ty1); 
    29373008    else 
    29383009        c4 = CNIL;                              /* ES is already same as DS */ 
    29393010 
    29403011    if (need_DS) 
    29413012        c4 = gen1(c4,0x1F);                     /* POP DS               */ 
    29423013    if (*pretregs) 
    2943         c4 = genmovreg(c4,AX,DI);               /* MOV AX,DI            */ 
     3014    {   c4 = genmovreg(c4,AX,DI);               /* MOV AX,DI            */ 
     3015        code_orrex(c4,rex); 
     3016    } 
    29443017    c4 = gen1(c4,0xF3);                         /* REP                  */ 
    29453018    gen1(c4,0xA4);                              /* MOVSB                */ 
    29463019 
    29473020    if (need_DS) 
    29483021    {   gen1(c4,0x1F);                          /* POP DS               */ 
    29493022        genadjesp(c4,-(REGSIZE * 2)); 
    29503023    } 
    29513024    return cat6(c1,c2,c3,c4,fixresult(e,mAX | mES,pretregs),CNIL); 
    29523025} 
    29533026 
    29543027/********************************* 
    29553028 * Generate code for memcpy(s1,s2,n) intrinsic. 
    29563029 *  OPmemcpy 
    29573030 *   /   \ 
    29583031 * s1   OPparam 
    29593032 *       /   \ 
    29603033 *      s2    n 
    29613034 */ 
    29623035 
    29633036code *cdmemcpy(elem *e,regm_t *pretregs) 
     
    29863059    assert(e2->Eoper == OPparam); 
    29873060 
    29883061    // Get s2 into DX:SI 
    29893062    retregs2 = mSI; 
    29903063    ty2 = e2->E1->Ety; 
    29913064    if (!tyreg(ty2)) 
    29923065        retregs2 |= mDX; 
    29933066    c1 = codelem(e2->E1,&retregs2,FALSE); 
    29943067 
    29953068    // Get nbytes into CX 
    29963069    retregs3 = mCX; 
    29973070    c1 = cat(c1,scodelem(e2->E2,&retregs3,retregs2,FALSE)); 
    29983071    freenode(e2); 
    29993072 
    30003073    // Get s1 into ES:DI 
    30013074    retregs1 = mDI; 
    30023075    ty1 = e->E1->Ety; 
    30033076    if (!tyreg(ty1)) 
    30043077        retregs1 |= mES; 
    30053078    c1 = cat(c1,scodelem(e->E1,&retregs1,retregs2 | retregs3,FALSE)); 
     3079 
     3080    unsigned char rex = I64 ? REX_W : 0; 
    30063081 
    30073082    /* Make sure ES contains proper segment value       */ 
    30083083    c2 = cod2_setES(ty1); 
    30093084 
    30103085    /* Load DS with right value */ 
    30113086    c3 = NULL; 
    30123087    switch (tybasic(ty2)) 
    30133088    { 
    30143089        case TYnptr: 
    30153090            need_DS = FALSE; 
    30163091            break; 
    30173092        case TYsptr: 
    30183093            if (config.wflags & WFssneds)       /* if sptr can't use DS segment */ 
    30193094                segreg = SEG_SS; 
    30203095            else 
    30213096                segreg = SEG_DS; 
    30223097            goto L1; 
    30233098        case TYcptr: 
    30243099            segreg = SEG_CS; 
    30253100        L1: 
    30263101            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    30273102            gen1(c3,0x06 + (segreg << 3));              /* PUSH segreg  */ 
    30283103            gen1(c3,0x1F);                              /* POP  DS      */ 
    30293104            need_DS = TRUE; 
    30303105            break; 
    30313106        case TYfptr: 
    30323107        case TYvptr: 
    30333108        case TYhptr: 
    30343109            c3 = gen1(c3,0x1E);                         /* PUSH DS      */ 
    30353110            gen2(c3,0x8E,modregrm(3,SEG_DS,DX));        /* MOV DS,DX    */ 
    30363111            need_DS = TRUE; 
    30373112            break; 
    30383113        default: 
    30393114            assert(0); 
    30403115    } 
    30413116 
    30423117    if (*pretregs)                              // if need return value 
    30433118    {   c3 = cat(c3,getregs(mAX)); 
    30443119        c3 = genmovreg(c3,AX,DI); 
     3120        code_orrex(c3, rex); 
    30453121    } 
    30463122 
    30473123    if (0 && I32 && config.flags4 & CFG4speed) 
    30483124    { 
    30493125        /* This is only faster if the memory is dword aligned, if not 
    30503126         * it is significantly slower than just a rep movsb. 
    30513127         */ 
    30523128        /*      mov     EDX,ECX 
    30533129         *      shr     ECX,2 
    30543130         *      jz      L1 
    30553131         *      repe    movsd 
    30563132         * L1:  and     EDX,3 
    30573133         *      jz      L2 
    30583134         *      mov     ECX,EDX 
    30593135         *      repe    movsb 
    30603136         * L2:  nop 
    30613137         */ 
    30623138        c3 = cat(c3,getregs(mSI | mDI | mCX | mDX)); 
    30633139        c3 = genmovreg(c3,DX,CX);               // MOV EDX,ECX 
    30643140        c3 = genc2(c3,0xC1,modregrm(3,5,CX),2); // SHR ECX,2 
    30653141        code *cx = genc2(CNIL, 0x81, modregrm(3,4,DX),3);       // AND EDX,3 
    30663142        genjmp(c3, JE, FLcode, (block *)cx);                    // JZ L1 
    30673143        gen1(c3,0xF3);                                          // REPE 
    30683144        gen1(c3,0xA5);                                          // MOVSW 
    30693145        c3 = cat(c3,cx); 
    30703146 
    30713147        code *cnop = gennop(CNIL); 
    30723148        genjmp(c3, JE, FLcode, (block *)cnop);  // JZ L2 
    30733149        genmovreg(c3,CX,DX);                    // MOV ECX,EDX 
    30743150        gen1(c3,0xF3);                          // REPE 
    30753151        gen1(c3,0xA4);                          // MOVSB 
    30763152        c3 = cat(c3, cnop); 
    30773153    } 
    30783154    else 
    30793155    { 
    30803156        c3 = cat(c3,getregs(mSI | mDI | mCX)); 
    30813157        if (!I32 && config.flags4 & CFG4speed)          // if speed optimization 
    3082         {   c3 = gen2(c3,0xD1,modregrm(3,5,CX));        // SHR CX,1 
     3158        {   c3 = gen2(c3,0xD1,(rex << 16) | modregrm(3,5,CX));        // SHR CX,1 
    30833159            gen1(c3,0xF3);                              // REPE 
    30843160            gen1(c3,0xA5);                              // MOVSW 
    3085             gen2(c3,0x11,modregrm(3,CX,CX));            // ADC CX,CX 
     3161            gen2(c3,0x11,(rex << 16) | modregrm(3,CX,CX));            // ADC CX,CX 
    30863162        } 
    30873163        c3 = gen1(c3,0xF3);                             // REPE 
    30883164        gen1(c3,0xA4);                                  // MOVSB 
    30893165        if (need_DS) 
    30903166            gen1(c3,0x1F);                              // POP DS 
    30913167    } 
    30923168    return cat4(c1,c2,c3,fixresult(e,mES|mAX,pretregs)); 
    30933169} 
    30943170 
    30953171 
    30963172/********************************* 
    30973173 * Generate code for memset(s,val,n) intrinsic. 
    30983174 *      (s OPmemset (n OPparam val)) 
    30993175 */ 
    31003176 
    31013177#if 1 
    31023178code *cdmemset(elem *e,regm_t *pretregs) 
    31033179{   code *c1,*c2,*c3 = NULL,*c4; 
    31043180    regm_t retregs1; 
    31053181    regm_t retregs2; 
    31063182    regm_t retregs3; 
    31073183    unsigned reg,vreg; 
    31083184    tym_t ty1; 
    31093185    elem *e2,*e1; 
    31103186    int segreg; 
    31113187    unsigned remainder; 
    31123188    targ_uns numbytes,numwords; 
    31133189    int op; 
    3114     targ_uns value; 
     3190    targ_size_t value; 
    31153191 
    31163192    //printf("cdmemset(*pretregs = x%x)\n", *pretregs); 
    31173193    e1 = e->E1; 
    31183194    e2 = e->E2; 
    31193195    assert(e2->Eoper == OPparam); 
     3196 
     3197    unsigned char rex = I64 ? REX_W : 0; 
    31203198 
    31213199    if (e2->E2->Eoper == OPconst) 
    31223200    { 
    31233201        value = el_tolong(e2->E2); 
    31243202        value &= 0xFF; 
    31253203        value |= value << 8; 
    31263204        value |= value << 16; 
     3205        value |= value << 32; 
    31273206    } 
    31283207 
    31293208    if (e2->E1->Eoper == OPconst) 
    31303209    { 
    31313210        numbytes = el_tolong(e2->E1); 
    3132         if (numbytes <= REP_THRESHOLD && I32 && // doesn't work for 16 bits 
     3211        if (numbytes <= REP_THRESHOLD && 
     3212            !I16 &&                     // doesn't work for 16 bits 
    31333213            e2->E2->Eoper == OPconst) 
    31343214        { 
    31353215            targ_uns offset = 0; 
    31363216            retregs1 = *pretregs; 
    31373217            if (!retregs1) 
    31383218                retregs1 = ALLREGS; 
    31393219            c1 = codelem(e->E1,&retregs1,FALSE); 
    31403220            reg = findreg(retregs1); 
    31413221            if (e2->E2->Eoper == OPconst) 
    31423222            { 
    31433223                switch (numbytes) 
    31443224                { 
    31453225                    case 4:                     // MOV [reg],imm32 
    3146                         c3 = genc2(CNIL,0xC7,modregrm(0,0,reg),value); 
     3226                        c3 = genc2(CNIL,0xC7,modregrmx(0,0,reg),value); 
    31473227                        goto fixres; 
    31483228                    case 2:                     // MOV [reg],imm16 
    3149                         c3 = genc2(CNIL,0xC7,modregrm(0,0,reg),value); 
     3229                        c3 = genc2(CNIL,0xC7,modregrmx(0,0,reg),value); 
    31503230                        c3->Iflags = CFopsize; 
    31513231                        goto fixres; 
    31523232                    case 1:                     // MOV [reg],imm8 
    3153                         c3 = genc2(CNIL,0xC6,modregrm(0,0,reg),value); 
     3233                        c3 = genc2(CNIL,0xC6,modregrmx(0,0,reg),value); 
    31543234                        goto fixres; 
    31553235                } 
    31563236            } 
    31573237 
    3158             c1 = regwithvalue(c1, BYTEREGS & ~retregs1, value, &vreg, 0); 
     3238            c1 = regwithvalue(c1, BYTEREGS & ~retregs1, value, &vreg, I64 ? 64 : 0); 
    31593239            freenode(e2->E2); 
    31603240            freenode(e2); 
    31613241 
    31623242            while (numbytes >= REGSIZE) 
    31633243            {                           // MOV dword ptr offset[reg],vreg 
    3164                 c2 = gen2(CNIL,0x89,modregrm(2,vreg,reg)); 
     3244                c2 = gen2(CNIL,0x89,(rex << 16) | modregxrmx(2,vreg,reg)); 
    31653245                c2->IEVoffset1 = offset; 
    31663246                c2->IFL1 = FLconst; 
    31673247                numbytes -= REGSIZE; 
    31683248                offset += REGSIZE; 
    31693249                c3 = cat(c3,c2); 
    31703250            } 
     3251            if (numbytes & 4) 
     3252            {                           // MOV dword ptr offset[reg],vreg 
     3253                c2 = gen2(CNIL,0x89,modregxrmx(2,vreg,reg)); 
     3254                c2->IEVoffset1 = offset; 
     3255                c2->IFL1 = FLconst; 
     3256                offset += 4; 
     3257                c3 = cat(c3,c2); 
     3258            } 
    31713259            if (numbytes & 2) 
    31723260            {                           // MOV word ptr offset[reg],vreg 
    3173                 c2 = gen2(CNIL,0x89,modregrm(2,vreg,reg)); 
     3261                c2 = gen2(CNIL,0x89,modregxrmx(2,vreg,reg)); 
    31743262                c2->IEVoffset1 = offset; 
    31753263                c2->IFL1 = FLconst; 
    31763264                c2->Iflags = CFopsize; 
    31773265                offset += 2; 
    31783266                c3 = cat(c3,c2); 
    31793267            } 
    31803268            if (numbytes & 1) 
    31813269            {                           // MOV byte ptr offset[reg],vreg 
    3182                 c2 = gen2(CNIL,0x88,modregrm(2,vreg,reg)); 
     3270                c2 = gen2(CNIL,0x88,modregxrmx(2,vreg,reg)); 
    31833271                c2->IEVoffset1 = offset; 
    31843272                c2->IFL1 = FLconst; 
    31853273                c3 = cat(c3,c2); 
    31863274            } 
    31873275fixres: 
    31883276            return cat3(c1,c3,fixresult(e,retregs1,pretregs)); 
    31893277        } 
    31903278    } 
    31913279 
    31923280    // Get nbytes into CX 
    31933281    retregs2 = mCX; 
    3194     if (I32 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 
     3282    if (!I16 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 
    31953283    { 
    31963284        remainder = numbytes & (REGSIZE - 1); 
    31973285        numwords  = numbytes / REGSIZE;         // number of words 
    31983286        op = 0xAB;                              // moving by words 
    31993287        c1 = getregs(mCX); 
    3200         c1 = movregconst(c1,CX,numwords,0);     // # of bytes/words 
     3288        c1 = movregconst(c1,CX,numwords,I64?64:0);     // # of bytes/words 
    32013289    } 
    32023290    else 
    32033291    { 
    32043292        remainder = 0; 
    32053293        op = 0xAA;                              // must move by bytes 
    32063294        c1 = codelem(e2->E1,&retregs2,FALSE); 
    32073295    } 
    32083296 
    32093297    // Get val into AX 
    32103298 
    32113299    retregs3 = mAX; 
    3212     if (I32 && e2->E2->Eoper == OPconst) 
     3300    if (!I16 && e2->E2->Eoper == OPconst) 
    32133301    { 
    3214         c1 = regwithvalue(c1, mAX, value, NULL, 0); 
     3302        c1 = regwithvalue(c1, mAX, value, NULL, I64?64:0); 
    32153303        freenode(e2->E2); 
    32163304    } 
    32173305    else 
    32183306    { 
    32193307        c1 = cat(c1,scodelem(e2->E2,&retregs3,retregs2,FALSE)); 
    32203308#if 0 
    32213309        if (I32) 
    32223310        { 
    32233311            c1 = gen2(c1,0x8A,modregrm(3,AH,AL));       // MOV AH,AL 
    32243312            c1 = genc2(c1,0xC1,modregrm(3,4,AX),8);     // SHL EAX,8 
    32253313            c1 = gen2(c1,0x8A,modregrm(3,AL,AH));       // MOV AL,AH 
    32263314            c1 = genc2(c1,0xC1,modregrm(3,4,AX),8);     // SHL EAX,8 
    32273315            c1 = gen2(c1,0x8A,modregrm(3,AL,AH));       // MOV AL,AH 
    32283316        } 
    32293317#endif 
    32303318    } 
    32313319    freenode(e2); 
    32323320 
    32333321    // Get s into ES:DI 
    32343322    retregs1 = mDI; 
    32353323    ty1 = e->E1->Ety; 
    32363324    if (!tyreg(ty1)) 
    32373325        retregs1 |= mES; 
    32383326    c1 = cat(c1,scodelem(e->E1,&retregs1,retregs2 | retregs3,FALSE)); 
    32393327    reg = DI; //findreg(retregs1); 
    32403328 
    32413329    // Make sure ES contains proper segment value 
    32423330    c2 = cod2_setES(ty1); 
    32433331 
    32443332    c3 = NULL; 
    32453333    if (*pretregs)                              // if need return value 
    32463334    {   c3 = getregs(mBX); 
    32473335        c3 = genmovreg(c3,BX,DI); 
     3336        code_orrex(c3,rex); 
    32483337    } 
    32493338 
    32503339    c3 = cat(c3,getregs(mDI | mCX)); 
    3251     if (!I32 && config.flags4 & CFG4speed)      // if speed optimization 
     3340    if (I16 && config.flags4 & CFG4speed)      // if speed optimization 
    32523341    { 
    32533342        c3 = cat(c3,getregs(mAX)); 
    32543343        c3 = gen2(c3,0x8A,modregrm(3,AH,AL));   // MOV AH,AL 
    32553344        gen2(c3,0xD1,modregrm(3,5,CX));         // SHR CX,1 
    32563345        gen1(c3,0xF3);                          // REP 
    32573346        gen1(c3,0xAB);                          // STOSW 
    32583347        gen2(c3,0x11,modregrm(3,CX,CX));        // ADC CX,CX 
    32593348        op = 0xAA; 
    32603349    } 
    32613350 
    32623351    c3 = gen1(c3,0xF3);                         // REP 
    32633352    gen1(c3,op);                                // STOSD 
     3353    if (remainder & 4) 
     3354    { 
     3355        code *ctmp; 
     3356        ctmp = gen2(CNIL,0x89,modregrmx(2,AX,reg)); 
     3357        ctmp->IFL1 = FLconst; 
     3358        c3 = cat(c3,ctmp); 
     3359    } 
    32643360    if (remainder & 2) 
    32653361    { 
    32663362        code *ctmp; 
    3267         ctmp = gen2(CNIL,0x89,modregrm(2,AX,reg)); 
     3363        ctmp = gen2(CNIL,0x89,modregrmx(2,AX,reg)); 
    32683364        ctmp->Iflags = CFopsize; 
     3365        ctmp->IEVoffset1 = remainder & 4; 
    32693366        ctmp->IFL1 = FLconst; 
    32703367        c3 = cat(c3,ctmp); 
    32713368    } 
    32723369    if (remainder & 1) 
    32733370    { 
    32743371        code *ctmp; 
    3275         ctmp = gen2(CNIL,0x88,modregrm(2,AX,reg)); 
    3276         ctmp->IEVoffset1 = (remainder & 2) ? 2 : 0
     3372        ctmp = gen2(CNIL,0x88,modregrmx(2,AX,reg)); 
     3373        ctmp->IEVoffset1 = remainder & ~1
    32773374        ctmp->IFL1 = FLconst; 
    32783375        c3 = cat(c3,ctmp); 
    32793376    } 
    32803377    regimmed_set(CX,0); 
    32813378    return cat4(c1,c2,c3,fixresult(e,mES|mBX,pretregs)); 
    32823379} 
    32833380#else 
    32843381// BUG: Pat made many improvements in the linux version, I need 
    32853382// to verify they work for 16 bits and fold them in. -Walter 
    32863383 
    32873384code *cdmemset(elem *e,regm_t *pretregs) 
    32883385{   code *c1,*c2,*c3 = NULL,*c4; 
    32893386    regm_t retregs1; 
    32903387    regm_t retregs2; 
    32913388    regm_t retregs3; 
    32923389    tym_t ty1; 
    32933390    elem *e2; 
    32943391    targ_size_t value; 
    32953392 
    32963393    /* 
     
    33493445    return cat4(c1,c2,c3,fixresult(e,mES|mBX,pretregs)); 
    33503446} 
    33513447#endif 
    33523448 
    33533449 
    33543450/********************** 
    33553451 * Do structure assignments. 
    33563452 * This should be fixed so that (s1 = s2) is rewritten to (&s1 = &s2). 
    33573453 * Mebbe call cdstreq() for double assignments??? 
    33583454 */ 
    33593455 
    33603456code *cdstreq(elem *e,regm_t *pretregs) 
    33613457{ code *c1,*c2,*c3; 
    33623458  code *c1a; 
    33633459  regm_t srcregs,dstregs;               /* source & destination reg masks */ 
    33643460  targ_uns numbytes; 
    33653461  char need_DS = FALSE; 
    33663462  elem *e1 = e->E1,*e2 = e->E2; 
    33673463  int segreg; 
    33683464 
    3369   numbytes = e->Enumbytes;              /* # of bytes in structure/union */ 
     3465    numbytes = e->Enumbytes;              // # of bytes in structure/union 
     3466    unsigned char rex = I64 ? REX_W : 0; 
    33703467 
    33713468    //printf("cdstreq(e = %p, *pretregs = x%x)\n", e, *pretregs); 
    33723469 
    33733470    /* First, load pointer to rvalue into SI                            */ 
    33743471    srcregs = mSI;                      /* source is DS:SI              */ 
    33753472    c1 = docommas(&e2); 
    33763473    if (e2->Eoper == OPind)             /* if (.. = *p)                 */ 
    33773474    {   elem *e21 = e2->E1; 
    33783475 
    33793476        segreg = SEG_DS; 
    33803477        switch (tybasic(e21->Ety)) 
    33813478        { 
    33823479            case TYsptr: 
    33833480                if (config.wflags & WFssneds)   /* if sptr can't use DS segment */ 
    33843481                    segreg = SEG_SS; 
    33853482                break; 
    33863483            case TYcptr: 
    33873484                if (!(config.exe & EX_flat)) 
    33883485                    segreg = SEG_CS; 
    33893486                break; 
     
    34453542  if (e1->Eoper == OPind)               /* if (*p = ..)                 */ 
    34463543  { 
    34473544        if (tyreg(e1->E1->Ety)) 
    34483545            dstregs = mDI; 
    34493546        c2 = cod2_setES(e1->E1->Ety); 
    34503547        c2 = cat(c2,scodelem(e1->E1,&dstregs,srcregs,FALSE)); 
    34513548  } 
    34523549  else 
    34533550        c2 = cdrelconst(e1,&dstregs); 
    34543551  freenode(e1); 
    34553552 
    34563553  c3 = getregs((srcregs | dstregs) & (mLSW | mDI)); 
    34573554  if (need_DS) 
    34583555  {     assert(!(config.exe & EX_flat)); 
    34593556        c3 = gen1(c3,0x1E);                     /* PUSH DS              */ 
    34603557        gen2(c3,0x8E,modregrm(3,SEG_DS,CX));    /* MOV DS,CX            */ 
    34613558  } 
    34623559  if (numbytes <= REGSIZE * (6 + (REGSIZE == 4))) 
    34633560  {     while (numbytes >= REGSIZE) 
    34643561        {   c3 = gen1(c3,0xA5);         /* MOVSW                        */ 
     3562            code_orrex(c3, rex); 
    34653563            numbytes -= REGSIZE; 
    34663564        } 
    34673565        //if (numbytes) 
    34683566        //    printf("cdstreq numbytes %d\n",numbytes); 
    34693567        while (numbytes--) 
    34703568            c3 = gen1(c3,0xA4);         /* MOVSB                        */ 
    34713569  } 
    34723570    else 
    34733571    { 
    34743572#if 1 
    34753573        unsigned remainder; 
    34763574 
    34773575        remainder = numbytes & (REGSIZE - 1); 
    34783576        numbytes /= REGSIZE;            // number of words 
    34793577        c3 = cat(c3,getregs_imm(mCX)); 
    34803578        c3 = movregconst(c3,CX,numbytes,0);     // # of bytes/words 
    34813579        gen1(c3,0xF3);                          // REP 
    34823580        gen1(c3,0xA5);                  // REP MOVSD 
    34833581        regimmed_set(CX,0);             // note that CX == 0 
    34843582        for (; remainder; remainder--) 
     
    34913589        if (numbytes & (REGSIZE - 1))   /* if odd                       */ 
    34923590                movs = 0xA4;            /* MOVSB                        */ 
    34933591        else 
    34943592        {       movs = 0xA5;            /* MOVSW                        */ 
    34953593                numbytes /= REGSIZE;    /* # of words                   */ 
    34963594        } 
    34973595        c3 = cat(c3,getregs_imm(mCX)); 
    34983596        c3 = movregconst(c3,CX,numbytes,0);     /* # of bytes/words     */ 
    34993597        gen1(c3,0xF3);                          /* REP                  */ 
    35003598        gen1(c3,movs); 
    35013599        regimmed_set(CX,0);             /* note that CX == 0            */ 
    35023600#endif 
    35033601    } 
    35043602    if (need_DS) 
    35053603        gen1(c3,0x1F);                          // POP  DS 
    35063604    assert(!(*pretregs & mPSW)); 
    35073605    if (*pretregs) 
    35083606    {   /* ES:DI points past what we want       */ 
    35093607        regm_t retregs; 
    35103608 
    3511         genc2(c3,0x81,modregrm(3,5,DI),e->Enumbytes);   /* SUB DI,numbytes */ 
     3609        genc2(c3,0x81,(rex << 16) | modregrm(3,5,DI),e->Enumbytes);   // SUB DI,numbytes 
    35123610        retregs = mDI; 
    35133611        if (*pretregs & mMSW && !(config.exe & EX_flat)) 
    35143612            retregs |= mES; 
    35153613        c3 = cat(c3,fixresult(e,retregs,pretregs)); 
    35163614    } 
    35173615    return cat3(c1,c2,c3); 
    35183616} 
    35193617 
    35203618 
    35213619/********************** 
    35223620 * Get the address of. 
    35233621 * Is also called by cdstreq() to set up pointer to a structure. 
    35243622 */ 
    35253623 
    35263624code *cdrelconst(elem *e,regm_t *pretregs) 
    35273625{ code *c,*c1; 
    35283626  enum SC sclass; 
    35293627  unsigned mreg,                /* segment of the address (TYfptrs only) */ 
    35303628        lreg;                   /* offset of the address                */ 
    35313629  tym_t tym; 
     
    36203718            fl = s->Sfl; 
    36213719            if (s->ty() & mTYcs) 
    36223720                fl = FLcsdata; 
    36233721            c = gen2(c,0x8C,            /* MOV mreg,SEG REGISTER        */ 
    36243722                modregrm(3,segfl[fl],mreg)); 
    36253723        } 
    36263724        if (*pretregs & mES) 
    36273725                gen2(c,0x8E,modregrm(3,0,mreg));        /* MOV ES,mreg  */ 
    36283726  } 
    36293727  return cat(c,getoffset(e,lreg)); 
    36303728} 
    36313729 
    36323730/********************************* 
    36333731 * Load the offset portion of the address represented by e into 
    36343732 * reg. 
    36353733 */ 
    36363734 
    36373735code *getoffset(elem *e,unsigned reg) 
    36383736{ code cs; 
    36393737  code *c; 
    3640   enum FL fl; 
    36413738 
    36423739  cs.Iflags = 0; 
    3643   cs.Irex = 0; 
     3740  unsigned char rex = I64 ? REX_W : 0; 
     3741  cs.Irex = rex; 
    36443742  assert(e->Eoper == OPvar || e->Eoper == OPrelconst); 
    3645   fl = el_fl(e); 
     3743  enum FL fl = el_fl(e); 
    36463744  switch (fl) 
    36473745  { 
    36483746    case FLdatseg: 
    36493747        cs.IEV2._EP.Vpointer = e->EV.Vpointer; 
    36503748        goto L3; 
    36513749 
    36523750    case FLfardata: 
    36533751        assert(!TARGET_FLAT); 
    36543752        goto L4; 
    36553753 
    36563754    case FLtlsdata: 
    36573755#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    36583756    {   /* Generate: 
    36593757         *      MOV reg,GS:[00000000] 
    36603758         *      ADD reg, offset s@TLS_LE 
    36613759         * for locals, and for globals: 
    36623760         *      MOV reg,GS:[00000000] 
    36633761         *      ADD reg, s@TLS_IE 
    36643762         * note different fixup 
    36653763         */ 
    36663764      L5: 
    36673765        int stack = 0; 
    36683766        c = NULL; 
    36693767        if (reg == STACK) 
    36703768        {   regm_t retregs = ALLREGS; 
    36713769 
    36723770            c = allocreg(&retregs,&reg,TYoffset); 
    36733771            reg = findreg(retregs); 
    36743772            stack = 1; 
    36753773        } 
    36763774 
    36773775        code css; 
     3776        css.Irex = rex; 
    36783777        css.Iop = 0x8B; 
    3679         css.Irm = modregrm(0, reg, BPRM); 
     3778        css.Irm = modregrm(0, 0, BPRM); 
     3779        code_newreg(&css, reg); 
    36803780        css.Iflags = CFgs; 
    3681         css.Irex = 0; 
    36823781        css.IFL1 = FLconst; 
    36833782        css.IEV1.Vuns = 0; 
    36843783        c = gen(c, &css);               // MOV reg,GS:[00000000] 
    36853784 
    36863785        if (e->EV.sp.Vsym->Sclass == SCstatic || e->EV.sp.Vsym->Sclass == SClocstat) 
    36873786        {   // ADD reg, offset s 
     3787            cs.Irex = rex; 
    36883788            cs.Iop = 0x81; 
    3689             cs.Irm = modregrm(3,0,reg); 
     3789            cs.Irm = modregrm(3,0,reg & 7); 
     3790            if (reg & 8) 
     3791                cs.Irex |= REX_B; 
    36903792            cs.Iflags = CFoff; 
    3691             css.Irex = 0; 
    36923793            cs.IFL2 = fl; 
    36933794            cs.IEVsym2 = e->EV.sp.Vsym; 
    36943795            cs.IEVoffset2 = e->EV.sp.Voffset; 
    36953796        } 
    36963797        else 
    36973798        {   // ADD reg, s 
     3799            cs.Irex = rex; 
    36983800            cs.Iop = 0x03; 
    3699             cs.Irm = modregrm(0,reg,BPRM); 
     3801            cs.Irm = modregrm(0,0,BPRM); 
     3802            code_newreg(&cs, reg); 
    37003803            cs.Iflags = CFoff; 
    3701             css.Irex = 0; 
    37023804            cs.IFL1 = fl; 
    37033805            cs.IEVsym1 = e->EV.sp.Vsym; 
    37043806            cs.IEVoffset1 = e->EV.sp.Voffset; 
    37053807        } 
    37063808        c = gen(c, &cs);                // ADD reg, xxxx 
    37073809 
    37083810        if (stack) 
    37093811        { 
    3710             c = gen1(c,0x50 + reg);                     /* PUSH reg     */ 
     3812            c = gen1(c,0x50 + (reg & 7));      // PUSH reg 
     3813            if (reg & 8) 
     3814                code_orrex(c, REX_B); 
    37113815            c = genadjesp(c,REGSIZE); 
    37123816            stackchanged = 1; 
    37133817        } 
    37143818        break; 
    37153819    } 
    37163820#else 
    37173821        goto L4; 
    37183822#endif 
    37193823 
    37203824    case FLfunc: 
    37213825        fl = FLextern;                  /* don't want PC relative addresses */ 
    37223826        goto L4; 
    37233827 
    37243828    case FLextern: 
    37253829#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    37263830        if (e->EV.sp.Vsym->ty() & mTYthread) 
    37273831            goto L5; 
    37283832#endif 
    37293833    case FLdata: 
    37303834    case FLudata: 
    37313835#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    37323836    case FLgot: 
    37333837    case FLgotoff: 
    37343838#endif 
    37353839    case FLcsdata: 
    37363840    L4: 
    37373841        cs.IEVsym2 = e->EV.sp.Vsym; 
    37383842        cs.IEVoffset2 = e->EV.sp.Voffset; 
    37393843    L3: 
    37403844        if (reg == STACK) 
    37413845        {   stackchanged = 1; 
    37423846            cs.Iop = 0x68;              /* PUSH immed16                 */ 
    37433847            c = genadjesp(NULL,REGSIZE); 
    37443848        } 
    37453849        else 
    3746         {   cs.Iop = 0xB8 + reg;        /* MOV reg,immed16              */ 
     3850        {   cs.Iop = 0xB8 + (reg & 7);  // MOV reg,immed16 
     3851            if (reg & 8) 
     3852                cs.Irex |= REX_B; 
    37473853            c = NULL; 
    37483854        } 
    37493855        cs.Iflags = CFoff;              /* want offset only             */ 
    37503856        cs.IFL2 = fl; 
    37513857        c = gen(c,&cs); 
    37523858        break; 
    37533859 
    37543860#if 0 && TARGET_LINUX 
    37553861    case FLgot: 
    37563862    case FLgotoff: 
    37573863        { 
    37583864        gotref = 1; 
    37593865        symbol *s = e->EV.sp.Vsym; 
    37603866        // When using 8B (MOV), indicating that rm is used 
    37613867        // rm operands are always placed in IEV1 not IEV2 
    37623868        cs.IEVsym1 = s; 
    37633869        cs.IEVoffset1 = e->EV.sp.Voffset; 
    37643870        cs.Irm = modregrm(2,reg,BX);    // reg,disp32[EBX] 
    37653871        cs.IFL1 = fl; 
    37663872        cs.Iop = (fl == FLgotoff) 
     
    37743880 
    37753881    case FLreg: 
    37763882        /* Allow this since the tree optimizer puts & in front of       */ 
    37773883        /* register doubles.                                            */ 
    37783884        goto L2; 
    37793885    case FLauto: 
    37803886    case FLtmp: 
    37813887    case FLbprel: 
    37823888    case FLfltreg: 
    37833889        reflocal = TRUE; 
    37843890        goto L2; 
    37853891    case FLpara: 
    37863892        refparam = TRUE; 
    37873893    L2: 
    37883894        if (reg == STACK) 
    37893895        {   regm_t retregs = ALLREGS; 
    37903896 
    37913897            c = allocreg(&retregs,&reg,TYoffset); 
    37923898            reg = findreg(retregs); 
    37933899            c = cat(c,loadea(e,&cs,0x8D,reg,0,0,0));    /* LEA reg,EA   */ 
    3794             c = gen1(c,0x50 + reg);                     /* PUSH reg     */ 
     3900            c = gen1(c,0x50 + (reg & 7));               // PUSH reg 
     3901            if (reg & 8) 
     3902                code_orrex(c, REX_B); 
    37953903            c = genadjesp(c,REGSIZE); 
    37963904            stackchanged = 1; 
    37973905        } 
    37983906        else 
    37993907            c = loadea(e,&cs,0x8D,reg,0,0,0);   /* LEA reg,EA           */ 
    38003908        break; 
    38013909    default: 
    38023910#ifdef DEBUG 
    38033911        elem_print(e); 
    38043912        debugx(WRFL(fl)); 
    38053913#endif 
    38063914        assert(0); 
    38073915  } 
    38083916  return c; 
    38093917} 
    38103918 
    38113919 
    38123920/****************** 
    38133921 * Negate, sqrt operator 
    38143922 */ 
    38153923 
    38163924code *cdneg(elem *e,regm_t *pretregs) 
    38173925{ unsigned byte; 
    38183926  regm_t retregs,possregs; 
    38193927  int reg; 
    38203928  int sz; 
    38213929  tym_t tyml; 
    38223930  code *c,*c1,*cg; 
    38233931 
    38243932  //printf("cdneg()\n"); 
    38253933  //elem_print(e); 
    38263934  if (*pretregs == 0) 
    38273935        return codelem(e->E1,pretregs,FALSE); 
    38283936  tyml = tybasic(e->E1->Ety); 
    38293937  sz = tysize[tyml]; 
    38303938  if (tyfloating(tyml)) 
    38313939  {     if (tycomplex(tyml)) 
    38323940            return neg_complex87(e, pretregs); 
    3833         if (config.inline8087 && ((*pretregs & (ALLREGS | mBP)) == 0 || e->Eoper == OPsqrt)) 
     3941        if (config.inline8087 && 
     3942            ((*pretregs & (ALLREGS | mBP)) == 0 || e->Eoper == OPsqrt || I64)) 
    38343943                return neg87(e,pretregs); 
    3835         retregs = (!I32 && sz == 8) ? DOUBLEREGS_16 : ALLREGS; 
     3944        retregs = (I16 && sz == 8) ? DOUBLEREGS_16 : ALLREGS; 
    38363945        c1 = codelem(e->E1,&retregs,FALSE); 
    38373946        c1 = cat(c1,getregs(retregs)); 
    38383947        if (I32) 
    38393948        {   reg = (sz == 8) ? findregmsw(retregs) : findreg(retregs); 
    38403949            c1 = genc2(c1,0x81,modregrm(3,6,reg),0x80000000); /* XOR EDX,sign bit */ 
    38413950        } 
    38423951        else 
    38433952        {   reg = (sz == 8) ? AX : findregmsw(retregs); 
    38443953            c1 = genc2(c1,0x81,modregrm(3,6,reg),0x8000);     /* XOR AX,0x8000 */ 
    38453954        } 
    38463955        return cat(c1,fixresult(e,retregs,pretregs)); 
    38473956  } 
    38483957 
    38493958  byte = sz == 1; 
    38503959  possregs = (byte) ? BYTEREGS : allregs; 
    38513960  retregs = *pretregs & possregs; 
    38523961  if (retregs == 0) 
    38533962        retregs = possregs; 
    38543963  c1 = codelem(e->E1,&retregs,FALSE); 
    38553964  cg = getregs(retregs);                /* retregs will be destroyed    */ 
    38563965  if (sz <= REGSIZE) 
    3857   {     unsigned reg; 
    3858  
    3859         reg = findreg(retregs)
    3860         c = gen2(CNIL,0xF7 ^ byte,modregrm(3,3,reg));   /* NEG reg      */ 
    3861         if (I32 && tysize[tyml] == SHORTSIZE && *pretregs & mPSW) 
     3966  { 
     3967        unsigned reg = findreg(retregs); 
     3968        unsigned rex = (I64 && sz == 8) ? REX_W : 0
     3969        c = gen2(CNIL,0xF7 ^ byte,(rex << 16) | modregrmx(3,3,reg));   // NEG reg 
     3970        if (!I16 && tysize[tyml] == SHORTSIZE && *pretregs & mPSW) 
    38623971            c->Iflags |= CFopsize | CFpsw; 
    38633972        *pretregs &= mBP | ALLREGS;             // flags already set 
    38643973  } 
    38653974  else if (sz == 2 * REGSIZE) 
    38663975  {     unsigned msreg,lsreg; 
    38673976 
    38683977        msreg = findregmsw(retregs); 
    38693978        c = gen2(CNIL,0xF7,modregrm(3,3,msreg)); /* NEG msreg           */ 
    38703979        lsreg = findreglsw(retregs); 
    38713980        gen2(c,0xF7,modregrm(3,3,lsreg));       /* NEG lsreg            */ 
    38723981        genc2(c,0x81,modregrm(3,3,msreg),0);    /* SBB msreg,0          */ 
    38733982  } 
    38743983  else 
    38753984        assert(0); 
    38763985  return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 
    38773986} 
    38783987 
    38793988 
    38803989/****************** 
    38813990 * Absolute value operator 
    38823991 */ 
    38833992 
    38843993code *cdabs( elem *e, regm_t *pretregs) 
    38853994{ unsigned byte; 
    38863995  regm_t retregs,possregs; 
    38873996  int reg; 
    38883997  tym_t tyml; 
    38893998  code *c,*c1,*cg; 
    3890   int sz; 
    38913999 
    38924000  if (*pretregs == 0) 
    38934001        return codelem(e->E1,pretregs,FALSE); 
    38944002  tyml = tybasic(e->E1->Ety); 
    3895   sz = tysize[tyml]; 
     4003  int sz = tysize[tyml]; 
     4004  unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
    38964005  if (tyfloating(tyml)) 
    3897   {     if (config.inline8087 && (*pretregs & (ALLREGS | mBP)) == 0
     4006  {     if (config.inline8087 && ((*pretregs & (ALLREGS | mBP)) == 0 || I64)
    38984007                return neg87(e,pretregs); 
    38994008        retregs = (!I32 && sz == 8) ? DOUBLEREGS_16 : ALLREGS; 
    39004009        c1 = codelem(e->E1,&retregs,FALSE); 
    39014010        /*cg = callclib(e,CLIBdneg,pretregs,0);*/ 
    39024011        c1 = cat(c1,getregs(retregs)); 
    39034012        if (I32) 
    39044013        {   reg = (sz == 8) ? findregmsw(retregs) : findreg(retregs); 
    39054014            c1 = genc2(c1,0x81,modregrm(3,4,reg),0x7FFFFFFF); /* AND EDX,~sign bit */ 
    39064015        } 
    39074016        else 
    39084017        {   reg = (sz == 8) ? AX : findregmsw(retregs); 
    39094018            c1 = genc2(c1,0x81,modregrm(3,4,reg),0x7FFF);     /* AND AX,0x7FFF */ 
    39104019        } 
    39114020        return cat(c1,fixresult(e,retregs,pretregs)); 
    39124021  } 
    39134022 
    39144023  byte = sz == 1; 
    39154024  assert(byte == 0); 
    39164025  byte = 0; 
    39174026  possregs = (sz <= REGSIZE) ? mAX : allregs; 
    39184027  retregs = *pretregs & possregs; 
    39194028  if (retregs == 0) 
    39204029        retregs = possregs; 
    39214030  c1 = codelem(e->E1,&retregs,FALSE); 
    39224031  cg = getregs(retregs);                /* retregs will be destroyed    */ 
    39234032  if (sz <= REGSIZE) 
    39244033  {     unsigned reg; 
    39254034        code *c2; 
    39264035 
    39274036        /*      cwd 
    39284037                xor     AX,DX 
    39294038                sub     AX,DX 
    39304039         */ 
    39314040 
    39324041        cg = cat(cg,getregs(mDX)); 
    39334042        reg = findreg(retregs); 
    3934         if (I32 && sz == SHORTSIZE) 
     4043        if (!I16 && sz == SHORTSIZE) 
    39354044            cg = gen1(cg,0x98);                         // CWDE 
    39364045        cg = gen1(cg,0x99);                             // CWD 
    3937         gen2(cg,0x33 ^ byte,modregrm(3,AX,DX));         // XOR EAX,EDX 
    3938         c = gen2(CNIL,0x2B ^ byte,modregrm(3,AX,DX));   // SUB EAX,EDX 
    3939         if (I32 && sz == SHORTSIZE && *pretregs & mPSW) 
     4046        code_orrex(cg, rex); 
     4047        gen2(cg,0x33 ^ byte,(rex << 16) | modregrm(3,AX,DX));         // XOR EAX,EDX 
     4048        c = gen2(CNIL,0x2B ^ byte,(rex << 16) | modregrm(3,AX,DX));   // SUB EAX,EDX 
     4049        if (!I16 && sz == SHORTSIZE && *pretregs & mPSW) 
    39404050            c->Iflags |= CFopsize | CFpsw; 
    39414051        if (*pretregs & mPSW) 
    39424052            c->Iflags |= CFpsw; 
    39434053        *pretregs &= ~mPSW;                     // flags already set 
    39444054  } 
    39454055  else if (sz == 2 * REGSIZE) 
    39464056  {     unsigned msreg,lsreg; 
    39474057        code *cnop; 
    39484058 
    39494059        /*      tst     DX 
    39504060                jns     L2 
    39514061                neg     DX 
    39524062                neg     AX 
    39534063                sbb     DX,0 
    39544064            L2: 
    39554065         */ 
    39564066 
    39574067        cnop = gennop(CNIL); 
    39584068        msreg = findregmsw(retregs); 
    39594069        lsreg = findreglsw(retregs); 
     
    39754084 */ 
    39764085 
    39774086code *cdpost(elem *e,regm_t *pretregs) 
    39784087{ code cs,*c1,*c2,*c3,*c4,*c5,*c6; 
    39794088  unsigned reg,op,byte; 
    39804089  tym_t tyml; 
    39814090  regm_t retregs,possregs,idxregs; 
    39824091  targ_int n; 
    39834092  elem *e2; 
    39844093  int sz; 
    39854094  int stackpushsave; 
    39864095 
    39874096  retregs = *pretregs; 
    39884097  op = e->Eoper;                                /* OPxxxx               */ 
    39894098  if (retregs == 0)                             /* if nothing to return */ 
    39904099        return cdaddass(e,pretregs); 
    39914100  c4 = c5 = CNIL; 
    39924101  tyml = tybasic(e->E1->Ety); 
    39934102  sz = tysize[tyml]; 
    39944103  e2 = e->E2; 
     4104  unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
    39954105 
    39964106  if (tyfloating(tyml)) 
    39974107  { 
    39984108#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    39994109        return post87(e,pretregs); 
    40004110#else 
    40014111        if (config.inline8087) 
    40024112                return post87(e,pretregs); 
    40034113        assert(sz <= 8); 
    40044114        c1 = getlvalue(&cs,e->E1,DOUBLEREGS); 
    40054115        freenode(e->E1); 
    4006         idxregs = idxregm(cs.Irm,cs.Isib); /* mask of index regs used   */ 
     4116        idxregs = idxregm(&cs);         // mask of index regs used 
    40074117        cs.Iop = 0x8B;                  /* MOV DOUBLEREGS,EA            */ 
    40084118        c2 = fltregs(&cs,tyml); 
    40094119        stackchanged = 1; 
    40104120        stackpushsave = stackpush; 
    40114121        if (sz == 8) 
    40124122        { 
    40134123            if (I32) 
    40144124            { 
    40154125                gen1(c2,0x50 + DX);             /* PUSH DOUBLEREGS      */ 
    40164126                gen1(c2,0x50 + AX); 
    40174127                stackpush += DOUBLESIZE; 
    40184128                retregs = DOUBLEREGS2_32; 
    40194129            } 
    40204130            else 
    40214131            { 
    40224132                gen1(c2,0x50 + AX); 
    40234133                gen1(c2,0x50 + BX); 
    40244134                gen1(c2,0x50 + CX); 
    40254135                gen1(c2,0x50 + DX);             /* PUSH DOUBLEREGS      */ 
    40264136                stackpush += DOUBLESIZE + DOUBLESIZE; 
     
    40814191            } 
    40824192        } 
    40834193        else 
    40844194        {   gen1(c5,0x58 + AX); 
    40854195            if (!I32) 
    40864196                gen1(c5,0x58 + DX); 
    40874197            stackpush -= FLOATSIZE; 
    40884198            retregs = FLOATREGS; 
    40894199        } 
    40904200        c5 = genadjesp(c5,stackpush - stackpushsave); 
    40914201        c6 = fixresult(e,retregs,pretregs); 
    40924202        return cat6(c1,c2,c3,c4,c5,c6); 
    40934203#endif 
    40944204  } 
    40954205 
    40964206  assert(e2->Eoper == OPconst); 
    40974207  byte = (sz == 1); 
    40984208  possregs = byte ? BYTEREGS : allregs; 
    40994209  c1 = getlvalue(&cs,e->E1,0); 
    41004210  freenode(e->E1); 
    4101   idxregs = idxregm(cs.Irm,cs.Isib);    /* mask of index regs used      */ 
     4211  idxregs = idxregm(&cs);       // mask of index regs used 
    41024212  if (sz <= REGSIZE && *pretregs == mPSW && (cs.Irm & 0xC0) == 0xC0 && 
    4103       (I32 || (idxregs & (mBX | mSI | mDI | mBP)))) 
     4213      (!I16 || (idxregs & (mBX | mSI | mDI | mBP)))) 
    41044214  {     // Generate: 
    41054215        //      TEST    reg,reg 
    41064216        //      LEA     reg,n[reg]      // don't affect flags 
    41074217        int rm; 
    41084218 
    41094219        reg = cs.Irm & 7; 
     4220        if (cs.Irex & REX_B) 
     4221            reg |= 8; 
    41104222        cs.Iop = 0x85 ^ byte; 
    4111         cs.Irm |= modregrm(0,reg,0); 
     4223        code_newreg(&cs, reg); 
    41124224        cs.Iflags |= CFpsw; 
    41134225        c2 = gen(NULL,&cs);             // TEST reg,reg 
    41144226 
    41154227        // If lvalue is a register variable, we must mark it as modified 
    4116         c3 = modEA(cs.Irm); 
     4228        c3 = modEA(&cs); 
    41174229 
    41184230        n = e2->EV.Vint; 
    41194231        if (op == OPpostdec) 
    41204232            n = -n; 
    41214233        rm = reg; 
    4122         if (!I32
     4234        if (I16
    41234235            rm = regtorm[reg]; 
    4124         c4 = genc1(NULL,0x8D,modregrm(2,reg,rm),FLconst,n);    // LEA reg,n[reg] 
     4236        c4 = genc1(NULL,0x8D,(rex << 16) | modregxrmx(2,reg,rm),FLconst,n); // LEA reg,n[reg] 
    41254237        return cat4(c1,c2,c3,c4); 
    41264238  } 
    41274239  else if (sz <= REGSIZE || tyfv(tyml)) 
    41284240  {     code cs2; 
    41294241 
    41304242        cs.Iop = 0x8B ^ byte; 
    41314243        retregs = possregs & ~idxregs & *pretregs; 
    41324244        if (!tyfv(tyml)) 
    41334245        {       if (retregs == 0) 
    41344246                        retregs = possregs & ~idxregs; 
    41354247        } 
    41364248        else /* tyfv(tyml) */ 
    41374249        {       if ((retregs &= mLSW) == 0) 
    41384250                        retregs = mLSW & ~idxregs; 
    41394251                /* Can't use LES if the EA uses ES as a seg override    */ 
    41404252                if (*pretregs & mES && (cs.Iflags & CFSEG) != CFes) 
    41414253                {   cs.Iop = 0xC4;                      /* LES          */ 
    41424254                    c1 = cat(c1,getregs(mES));          /* allocate ES  */ 
    41434255                } 
    41444256        } 
    41454257        c2 = allocreg(&retregs,&reg,TYint); 
    4146         cs.Irm |= modregrm(0,reg,0); 
     4258        code_newreg(&cs, reg); 
    41474259        c3 = gen(CNIL,&cs);                     /* MOV reg,EA   */ 
    41484260        cs2 = cs; 
    41494261 
    41504262        /* If lvalue is a register variable, we must mark it as modified */ 
    4151         c3 = cat(c3,modEA(cs.Irm)); 
     4263        c3 = cat(c3,modEA(&cs)); 
    41524264 
    41534265        cs.Iop = 0x81 ^ byte; 
    41544266        cs.Irm &= ~modregrm(0,7,0);             /* reg field = 0        */ 
     4267        cs.Irex &= ~REX_R; 
    41554268        if (op == OPpostdec) 
    41564269                cs.Irm |= modregrm(0,5,0);      /* SUB                  */ 
    41574270        cs.IFL2 = FLconst; 
    41584271        n = e2->EV.Vint; 
    41594272        cs.IEV2.Vint = n; 
    41604273        if (n == 1)                     /* can use INC or DEC           */ 
    41614274        {       cs.Iop |= 0xFE;         /* xFE is dec byte, xFF is word */ 
    41624275                if (op == OPpostdec) 
    41634276                        NEWREG(cs.Irm,1);       // DEC EA 
    41644277                else 
    41654278                        NEWREG(cs.Irm,0);       // INC EA 
    41664279        } 
    41674280        else if (n == -1)               // can use INC or DEC 
    41684281        {       cs.Iop |= 0xFE;         // xFE is dec byte, xFF is word 
    41694282                if (op == OPpostinc) 
    41704283                        NEWREG(cs.Irm,1);       // DEC EA 
    41714284                else 
    41724285                        NEWREG(cs.Irm,0);       // INC EA 
    41734286        } 
    41744287 
    41754288        // For scheduling purposes, we wish to replace: 
    41764289        //      MOV     reg,EA 
    41774290        //      OP      EA 
    41784291        // with: 
    41794292        //      MOV     reg,EA 
    41804293        //      OP      reg 
    41814294        //      MOV     EA,reg 
    41824295        //      ~OP     reg 
    41834296        if (sz <= REGSIZE && (cs.Irm & 0xC0) != 0xC0 && 
    41844297            config.target_cpu >= TARGET_Pentium && 
    41854298            config.flags4 & CFG4speed) 
    41864299        { 
    41874300            // Replace EA in cs with reg 
    4188             cs.Irm = (cs.Irm & ~modregrm(3,0,7)) | modregrm(3,0,reg); 
     4301            cs.Irm = (cs.Irm & ~modregrm(3,0,7)) | modregrm(3,0,reg & 7); 
     4302            if (reg & 8) 
     4303            {   cs.Irex &= ~REX_R; 
     4304                cs.Irex |= REX_B; 
     4305            } 
    41894306            gen(c3,&cs);                        // ADD/SUB reg,const 
    41904307 
    41914308            // Reverse MOV direction 
    41924309            cs2.Iop ^= 2; 
    41934310            gen(c3,&cs2);                       // MOV EA,reg 
    41944311 
    41954312            // Toggle INC <-> DEC, ADD <-> SUB 
    41964313            cs.Irm ^= (n == 1 || n == -1) ? modregrm(0,1,0) : modregrm(0,5,0); 
    41974314            gen(c3,&cs); 
    41984315 
    41994316            if (*pretregs & mPSW) 
    42004317            {   *pretregs &= ~mPSW;             // flags already set 
    42014318                code_orflag(c3,CFpsw); 
    42024319            } 
    42034320        } 
    42044321        else 
    42054322            gen(c3,&cs);                        // ADD/SUB EA,const 
    42064323 
    42074324        freenode(e2); 
    42084325        if (tyfv(tyml)) 
     
    44964613/***************************************** 
    44974614 */ 
    44984615 
    44994616code *cdhalt(elem *e,regm_t *pretregs) 
    45004617{ 
    45014618    assert(*pretregs == 0); 
    45024619    return gen1(NULL, 0xF4);            // HLT 
    45034620} 
    45044621 
    45054622/**************************************** 
    45064623 * Check to see if pointer is NULL. 
    45074624 */ 
    45084625 
    45094626code *cdnullcheck(elem *e,regm_t *pretregs) 
    45104627{   regm_t retregs; 
    45114628    regm_t scratch; 
    45124629    unsigned reg; 
    45134630    code *c; 
    45144631    code *cs; 
    45154632 
    4516     assert(I32); 
     4633    assert(!I16); 
    45174634    retregs = *pretregs; 
    45184635    if ((retregs & allregs) == 0) 
    45194636        retregs |= allregs; 
    45204637    c = codelem(e->E1,&retregs,FALSE); 
    45214638    scratch = allregs & ~retregs; 
    45224639    cs = allocreg(&scratch,&reg,TYint); 
    4523     cs = genc1(cs,0x8B,modregrm(2,reg,findreg(retregs)),FLconst,0);     // MOV reg,0[e] 
     4640    unsigned rex = I64 ? REX_W : 0; 
     4641    cs = genc1(cs,0x8B,(rex << 16) | modregxrmx(2,reg,findreg(retregs)),FLconst,0); // MOV reg,0[e] 
    45244642    return cat3(c,cs,fixresult(e,retregs,pretregs)); 
    45254643} 
    45264644 
    45274645#endif // !SPP 
  • trunk/src/backend/cod3.c

    r569 r577  
    269269        DOUBLEREGS = DOUBLEREGS_16; 
    270270    } 
    271271#endif 
    272272} 
    273273 
    274274/******************************** 
    275275 * Fix global variables for I64. 
    276276 */ 
    277277 
    278278void cod3_set64() 
    279279{ 
    280280    inssize[0xA0] = T|5;                // MOV AL,mem 
    281281    inssize[0xA1] = T|5;                // MOV RAX,mem 
    282282    inssize[0xA2] = T|5;                // MOV mem,AL 
    283283    inssize[0xA3] = T|5;                // MOV mem,RAX 
    284284    BPRM = 5;                           // [RBP] addressing mode 
    285285    fregsaved = mBP | mBX | mR12 | mR13 | mR14 | mR15 | mES;      // saved across function calls 
    286286    FLOATREGS = FLOATREGS_64; 
    287287    FLOATREGS2 = FLOATREGS2_64; 
    288288    DOUBLEREGS = DOUBLEREGS_64; 
     289    STACKALIGN = 16; 
    289290 
    290291    for (unsigned i = 0x80; i < 0x90; i++) 
    291292        inssize2[i] = W|T|6; 
    292293} 
    293294 
    294295/********************************* 
    295296 * Word or dword align start of function. 
    296297 */ 
    297298 
    298299void cod3_align() 
    299300{ 
    300301    static char nops[7] = { 0x90,0x90,0x90,0x90,0x90,0x90,0x90 }; 
    301302    unsigned nbytes; 
    302303#if OMFOBJ 
    303304    if (config.flags4 & CFG4speed)      // if optimized for speed 
    304305    { 
    305306        // Pick alignment based on CPU target 
    306307        if (config.target_cpu == TARGET_80486 || 
    307308            config.target_cpu >= TARGET_PentiumPro) 
    308309        {   // 486 does reads on 16 byte boundaries, so if we are near 
     
    353354 
    354355    e = b->Belem; 
    355356    elem_debug(e); 
    356357    cc = docommas(&e); 
    357358    cgstate.stackclean++; 
    358359    tys = tybasic(e->Ety); 
    359360    sz = tysize[tys]; 
    360361    dword = (sz == 2 * REGSIZE); 
    361362    mswsame = 1;                        // assume all msw's are the same 
    362363    p = b->BS.Bswitch;                  /* pointer to case data         */ 
    363364    assert(p); 
    364365    ncases = *p++;                      /* number of cases              */ 
    365366 
    366367    vmax = MINLL;                       // smallest possible llong 
    367368    vmin = MAXLL;                       // largest possible llong 
    368369    for (n = 0; n < ncases; n++)        // find max and min case values 
    369370    {   val = *p++; 
    370371        if (val > vmax) vmax = val; 
    371372        if (val < vmin) vmin = val; 
    372373        if (REGSIZE == 2) 
    373         {   unsigned short ms; 
    374  
    375 #if __DMC__ 
    376             ms = ((unsigned short *)&val)[1]; 
    377 #else 
    378             ms = (val >> 16) & 0xFFFF; 
    379 #endif 
     374        { 
     375            unsigned short ms = (val >> 16) & 0xFFFF; 
    380376            if (n == 0) 
    381377                msw = ms; 
    382378            else if (msw != ms) 
    383379                mswsame = 0; 
    384380        } 
    385381        else // REGSIZE == 4 
    386         {   targ_ulong ms; 
    387  
    388 #if __DMC__ 
    389             /* This statement generates garbage for ms under g++, 
    390              * I don't know why. 
    391              */ 
    392             ms = ((targ_ulong *)&val)[1]; 
    393 #else 
    394             ms = (val >> 32) & 0xFFFFFFFF; 
    395 #endif 
     382        { 
     383            targ_ulong ms = (val >> 32) & 0xFFFFFFFF; 
    396384            if (n == 0) 
    397385                msw = ms; 
    398386            else if (msw != ms) 
    399387                mswsame = 0; 
    400388        } 
    401389    } 
    402390    p -= ncases; 
    403391    //dbg_printf("vmax = x%lx, vmin = x%lx, vmax-vmin = x%lx\n",vmax,vmin,vmax - vmin); 
    404392    flags = (config.flags & CFGromable) ? CFcs : 0; // table is in code seg 
    405393 
     394    if (I64) 
     395    {   // For now, just generate basic if-then sequence to get us running 
     396        retregs = ALLREGS; 
     397        b->BC = BCifthen; 
     398        c = scodelem(e,&retregs,0,TRUE); 
     399        assert(!dword);                 // 128 bit switches not supported 
     400        reg = findreg(retregs);         // reg that result is in 
     401        bl = b->Bsucc; 
     402        for (n = 0; n < ncases; n++) 
     403        {   code *cx; 
     404            val = *p; 
     405            if (sz == 4) 
     406                cx = genc2(CNIL,0x81,modregrmx(3,7,reg),val);  // CMP reg,val 
     407            else if (sz == 8) 
     408            { 
     409                if (val == (int)val)    // if val is a 64 bit value sign-extended from 32 bits 
     410                { 
     411                    cx = genc2(CNIL,0x81,modregrmx(3,7,reg),val);  // CMP reg,value32 
     412                    cx->Irex |= REX_W;  // 64 bit operand 
     413                } 
     414                else 
     415                {   unsigned sreg; 
     416                                                                // MOV sreg,value64 
     417                    cx = regwithvalue(CNIL, ALLREGS & ~mask[reg], val, &sreg, 64); 
     418                    cx = genregs(cx,0x3B,reg,sreg);             // CMP reg,sreg 
     419                    code_orrex(cx, REX_W); 
     420                } 
     421            } 
     422            else 
     423                assert(0); 
     424            bl = list_next(bl); 
     425            genjmp(cx,JE,FLblock,list_block(bl));       // JE caseaddr 
     426            c = cat(c,cx); 
     427            p++; 
     428        } 
     429        if (list_block(b->Bsucc) != b->Bnext) /* if default is not next block */ 
     430                c = cat(c,genjmp(CNIL,JMP,FLblock,list_block(b->Bsucc))); 
     431        ce = NULL; 
     432    } 
    406433    // Need to do research on MACHOBJ to see about better methods 
    407     if (MACHOBJ || ncases <= 3)                 // generate if-then sequence 
    408     { 
     434    else if (MACHOBJ || ncases <= 3) 
     435    {   // generate if-then sequence 
    409436        retregs = ALLREGS; 
    410437    L1: 
    411438        b->BC = BCifthen; 
    412439        c = scodelem(e,&retregs,0,TRUE); 
    413440        if (dword) 
    414441        {   reg = findreglsw(retregs); 
    415442            reg2 = findregmsw(retregs); 
    416443        } 
    417444        else 
    418445            reg = findreg(retregs);     /* reg that result is in        */ 
    419446        bl = b->Bsucc; 
    420447        if (dword && mswsame) 
    421448        {   /* CMP reg2,MSW     */ 
    422449            c = genc2(c,0x81,modregrm(3,7,reg2),msw); 
    423450            genjmp(c,JNE,FLblock,list_block(b->Bsucc)); /* JNE default  */ 
    424451        } 
    425452        for (n = 0; n < ncases; n++) 
    426453        {   code *cnext = CNIL; 
    427454                                        /* CMP reg,casevalue            */ 
    428455            c = cat(c,ce = genc2(CNIL,0x81,modregrm(3,7,reg),(targ_int)*p)); 
     
    833860L1: 
    834861#if DEBUG 
    835862  if ((jp & 0xF0) != 0x70) 
    836863        WROP(op), 
    837864        printf("i %d zero %d op x%x jp x%x\n",i,zero,op,jp); 
    838865#endif 
    839866  assert((jp & 0xF0) == 0x70); 
    840867  return jp; 
    841868} 
    842869 
    843870 
    844871/********************************** 
    845872 * Append code to *pc which validates pointer described by 
    846873 * addressing mode in *pcs. Modify addressing mode in *pcs. 
    847874 * Input: 
    848875 *      keepmsk mask of registers we must not destroy or use 
    849876 *              if (keepmsk & RMstore), this will be only a store operation 
    850877 *              into the lvalue 
    851878 */ 
    852879 
    853 void cod3_ptrchk(code * __ss *pc,code __ss *pcs,regm_t keepmsk) 
     880void cod3_ptrchk(code **pc,code *pcs,regm_t keepmsk) 
    854881{   code *c; 
    855882    code *cs2; 
    856883    unsigned char rm,sib; 
    857884    unsigned reg; 
    858885    unsigned flagsave; 
    859886    unsigned opsave; 
    860887    regm_t idxregs; 
    861888    regm_t tosave; 
    862889    regm_t used; 
    863890    int i; 
    864891 
     892    assert(!I64); 
    865893    if (!I16 && pcs->Iflags & (CFes | CFss | CFcs | CFds | CFfs | CFgs)) 
    866894        return;         // not designed to deal with 48 bit far pointers 
    867895 
    868896    c = *pc; 
    869897 
    870898    rm = pcs->Irm; 
    871899    assert(!(rm & 0x40));       // no disp8 or reg addressing modes 
    872900 
    873901    // If the addressing mode is already a register 
    874902    reg = rm & 7; 
    875903    if (I16) 
    876904    {   static const unsigned char imode[8] = { BP,BP,BP,BP,SI,DI,BP,BX }; 
    877905 
    878906        reg = imode[reg];               // convert [SI] to SI, etc. 
    879907    } 
    880908    idxregs = mask[reg]; 
    881909    if ((rm & 0x80 && (pcs->IFL1 != FLoffset || pcs->IEV1.Vuns)) || 
    882910        !(idxregs & ALLREGS) 
    883911       ) 
    884912    { 
     
    937965            case CFcs:  segreg = 0x0E;  break; 
    938966            case 0:     segreg = 0x1E;  break;  // DS 
    939967            default: 
    940968                assert(0); 
    941969        } 
    942970 
    943971        // See if we should default to SS: 
    944972        // (Happens when BP is part of the addressing mode) 
    945973        if (segreg == 0x1E && (rm & 0xC0) != 0xC0 && 
    946974            rm & 2 && (rm & 7) != 7) 
    947975        {   segreg = 0x16; 
    948976            if (config.wflags & WFssneds) 
    949977                pcs->Iflags |= CFss;    // because BP won't be there anymore 
    950978        } 
    951979        c = gen1(c,segreg);             // PUSH segreg 
    952980    } 
    953981 
    954982    c = gen1(c,0x50 + reg);             // PUSH reg 
    955983 
    956984    // Rewrite the addressing mode in *pcs so it is just 0[reg] 
    957     pcs->Irm = getaddrmode(idxregs); 
     985    setaddrmode(pcs, idxregs); 
    958986    pcs->IFL1 = FLoffset; 
    959987    pcs->IEV1.Vuns = 0; 
    960988 
    961989    // Call the validation function 
    962990    { 
    963991        makeitextern(rtlsym[RTLSYM_PTRCHK]); 
    964992 
    965993        used &= ~(keepmsk | idxregs);           // regs destroyed by this exercise 
    966994        c = cat(c,getregs(used)); 
    967995                                                // CALL __ptrchk 
    968996        gencs(c,(LARGECODE) ? 0x9A : 0xE8,0,FLfunc,rtlsym[RTLSYM_PTRCHK]); 
    969997    } 
    970998 
    971999    *pc = cat(c,cs2); 
    9721000} 
    9731001 
    9741002 
    9751003 
    9761004/*********************************** 
    9771005 * Determine if BP can be used as a general purpose register. 
     
    10171045            config.flags & CFGstack || 
    10181046            localsize >= 0x100 ||       // arbitrary value < 0x1000 
    10191047            (usednteh & ~NTEHjmonitor) || 
    10201048            usedalloca 
    10211049           ) 
    10221050            goto Lcant; 
    10231051    } 
    10241052Lcan: 
    10251053    return mBP; 
    10261054 
    10271055Lcant: 
    10281056    return 0; 
    10291057} 
    10301058 
    10311059/*************************************** 
    10321060 * Gen code for OPframeptr 
    10331061 */ 
    10341062 
    10351063code *cdframeptr(elem *e, regm_t *pretregs) 
    10361064{ 
    1037     regm_t retregs; 
    10381065    unsigned reg; 
    1039     code *cg; 
    1040     code *c1; 
    10411066    code cs; 
    10421067 
    1043     retregs = *pretregs & allregs; 
     1068    regm_t retregs = *pretregs & allregs; 
    10441069    if  (!retregs) 
    10451070        retregs = allregs; 
    1046     cg = allocreg(&retregs, &reg, TYint); 
    1047     //c1 = genmovreg(cg, reg, BP); 
     1071    code *cg = allocreg(&retregs, &reg, TYint); 
    10481072 
    10491073    cs.Iop = ESCAPE; 
    10501074    cs.Iop2 = ESCframeptr; 
    10511075    cs.Iflags = 0; 
    10521076    cs.Irex = 0; 
    10531077    cs.Irm = reg; 
    1054     c1 = gen(cg,&cs); 
    1055  
    1056     return cat(c1,fixresult(e,retregs,pretregs)); 
     1078    cg = gen(cg,&cs); 
     1079 
     1080    return cat(cg,fixresult(e,retregs,pretregs)); 
    10571081} 
    10581082 
    10591083/*************************************** 
    10601084 * Gen code for load of _GLOBAL_OFFSET_TABLE_. 
    10611085 * This value gets cached in the local variable 'localgot'. 
    10621086 */ 
    10631087 
    10641088code *cdgot(elem *e, regm_t *pretregs) 
    10651089{ 
    10661090#if TARGET_OSX 
    10671091    regm_t retregs; 
    10681092    unsigned reg; 
    10691093    code *c; 
    10701094 
    10711095    retregs = *pretregs & allregs; 
    10721096    if  (!retregs) 
    10731097        retregs = allregs; 
    10741098    c = allocreg(&retregs, &reg, TYnptr); 
    10751099 
    10761100    c = genc(c,0xE8,0,0,0,FLgot,0);     //     CALL L1 
     
    18431867        static unsigned char ops0[] = { 0x07,0x1F,0x5F,0x5E, 
    18441868                                        0x5D,0x5B,0x5B,0x5A, 
    18451869                                        0x59,0x58,0xCF,0 }; 
    18461870        unsigned char *p; 
    18471871 
    18481872        c = genregs(c,0x8B,SP,BP);              // MOV SP,BP 
    18491873        p = (config.target_cpu >= TARGET_80286) ? ops2 : ops0; 
    18501874        do 
    18511875            gen1(c,*p); 
    18521876        while (*++p); 
    18531877        goto Lopt; 
    18541878    } 
    18551879 
    18561880    if (config.flags & CFGtrace && 
    18571881        (!(config.flags4 & CFG4allcomdat) || 
    18581882         funcsym_p->Sclass == SCcomdat || 
    18591883         funcsym_p->Sclass == SCglobal || 
    18601884         (config.flags2 & CFG2comdat && SymInline(funcsym_p)) 
    18611885        ) 
    18621886       ) 
    1863     {   symbol *s; 
    1864  
    1865         s = rtlsym[farfunc ? RTLSYM_TRACE_EPI_F : RTLSYM_TRACE_EPI_N]; 
     1887    { 
     1888        symbol *s = rtlsym[farfunc ? RTLSYM_TRACE_EPI_F : RTLSYM_TRACE_EPI_N]; 
    18661889        makeitextern(s); 
    18671890        c = gencs(c,I16 ? 0x9A : 0xE8,0,FLfunc,s);      // CALLF _trace 
    18681891        if (!I16) 
    18691892            code_orflag(c,CFoff | CFselfrel); 
    18701893        useregs((ALLREGS | mBP | mES) & ~s->Sregsaved); 
    18711894    } 
    18721895 
    18731896    if (usednteh & ~NTEHjmonitor && (config.exe == EX_NT || MARS)) 
    18741897        c = cat(c,nteh_epilog()); 
    18751898 
    18761899    cpopds = CNIL; 
    18771900    if (tyf & mTYloadds) 
    18781901    {   cpopds = gen1(cpopds,0x1F);             // POP DS 
    18791902        c = cat(c,cpopds); 
    18801903        spoff += intsize; 
    18811904    } 
    18821905 
    1883     reg = 7; 
    1884     regm = 1 << 7; 
     1906    /* Pop all the general purpose registers saved on the stack 
     1907     * by the prolog code. Remember to do them in the reverse 
     1908     * order they were pushed. 
     1909     */ 
     1910    reg = I64 ? R15 : DI; 
     1911    regm = 1 << reg; 
    18851912    topop = fregsaved & ~mfuncreg; 
    18861913#ifdef DEBUG 
    1887     if (topop & ~0xFF
     1914    if (topop & ~0xFFFF
    18881915        printf("fregsaved = x%x, mfuncreg = x%x\n",fregsaved,mfuncreg); 
    18891916#endif 
    1890     assert(!(topop & ~0xFF)); 
     1917    assert(!(topop & ~0xFFFF)); 
    18911918    while (topop) 
    18921919    {   if (topop & regm) 
    1893         {       c = gen1(c,0x58 + reg);         /* POP reg              */ 
    1894                 if (reg & 8) 
    1895                     code_orrex(c, REX_B); 
    1896                 topop &= ~regm; 
    1897                 spoff += intsize; 
     1920        {   c = gen1(c,0x58 + reg);         // POP reg 
     1921            if (reg & 8) 
     1922                code_orrex(c, REX_B); 
     1923            topop &= ~regm; 
     1924            spoff += intsize; 
    18981925        } 
    18991926        regm >>= 1; 
    19001927        reg--; 
    19011928    } 
    19021929 
    19031930#if MARS 
    19041931    if (usednteh & NTEHjmonitor) 
    19051932    { 
    19061933        regm_t retregs = 0; 
    19071934        if (b->BC == BCretexp) 
    19081935            retregs = regmask(b->Belem->Ety, tym); 
    19091936        code *cn = nteh_monitor_epilog(retregs); 
    19101937        c = cat(c,cn); 
    19111938        xlocalsize += 8; 
    19121939    } 
    19131940#endif 
    19141941 
    19151942    if (config.wflags & WFwindows && farfunc) 
    19161943    { 
    19171944        int wflags = config.wflags; 
     
    19832010        op = tyfarfunc(tym) ? 0xCA : 0xC2; 
    19842011        if (tym == TYhfunc) 
    19852012        { 
    19862013            c = genc2(c,0xC2,0,4);                      // RET 4 
    19872014        } 
    19882015        else if (!typfunc(tym) || Poffset == 0) 
    19892016        {   op++;                                       // to a regular RET 
    19902017            c = gen1(c,op); 
    19912018        } 
    19922019        else 
    19932020        {   // Stack is always aligned on register size boundary 
    19942021            Poffset = (Poffset + (REGSIZE - 1)) & ~(REGSIZE - 1); 
    19952022            c = genc2(c,op,0,Poffset);          // RET Poffset 
    19962023        } 
    19972024    } 
    19982025 
    19992026Lopt: 
    20002027    // If last instruction in ce is ADD SP,imm, and first instruction 
    20012028    // in c sets SP, we can dump the ADD. 
    20022029    cr = code_last(ce); 
    2003     if (cr && c
     2030    if (cr && c && !I64
    20042031    { 
    20052032        if (cr->Iop == 0x81 && cr->Irm == modregrm(3,0,SP))     // if ADD SP,imm 
    20062033        { 
    20072034            if ( 
    20082035                c->Iop == 0xC9 ||                                  // LEAVE 
    20092036                (c->Iop == 0x8B && c->Irm == modregrm(3,SP,BP)) || // MOV SP,BP 
    20102037                (c->Iop == 0x8D && c->Irm == modregrm(1,SP,6))     // LEA SP,-imm[BP] 
    20112038               ) 
    20122039                cr->Iop = NOP; 
    20132040            else if (c->Iop == 0x58 + BP)                       // if POP BP 
    20142041            {   cr->Iop = 0x8B; 
    20152042                cr->Irm = modregrm(3,SP,BP);                    // MOV SP,BP 
    20162043            } 
    20172044        } 
    20182045#if 0   // These optimizations don't work if the called function 
    20192046        // cleans off the stack. 
    20202047        else if (c->Iop == 0xC3 && cr->Iop == 0xE8)     // CALL near 
    20212048        {   cr->Iop = 0xE9;                             // JMP near 
    20222049            c->Iop = NOP; 
    20232050        } 
     
    23752401                    break; 
    23762402 
    23772403                default: 
    23782404                    goto L3; 
    23792405            } 
    23802406 
    23812407            if (disp == 0)                      // bra to next instruction 
    23822408            {   bytesaved += csize; 
    23832409                c->Iop = NOP;                   // del branch instruction 
    23842410                c->IEV2.Vcode = NULL; 
    23852411                c = cn; 
    23862412                if (!c) 
    23872413                    break; 
    23882414                continue; 
    23892415            } 
    23902416            else if ((targ_size_t)(targ_schar)(disp - 2) == (disp - 2) && 
    23912417                     (targ_size_t)(targ_schar)disp == disp) 
    23922418            { 
    23932419                if (op == JMP) 
    23942420                {   c->Iop = JMPS;              // JMP SHORT 
    2395                     bytesaved += I32 ? 3 : 1
     2421                    bytesaved += I16 ? 1 : 3
    23962422                } 
    23972423                else                            // else Jcond 
    23982424                {   c->Iflags &= ~CFjmp16;      // a branch is ok 
    2399                     bytesaved += I32 ? 4 : 3
     2425                    bytesaved += I16 ? 3 : 4
    24002426 
    24012427                    // Replace a cond jump around a call to a function that 
    24022428                    // never returns with a cond jump to that function. 
    24032429                    if (config.flags4 & CFG4optimized && 
    24042430                        config.target_cpu >= TARGET_80386 && 
    2405                         disp == (I32 ? 5 : 3) && 
     2431                        disp == (I16 ? 3 : 5) && 
    24062432                        cn && 
    24072433                        cn->Iop == 0xE8 && 
    24082434                        cn->IFL2 == FLfunc && 
    24092435                        cn->IEVsym2->Sflags & SFLexit && 
    24102436                        !(cn->Iflags & (CFtarg | CFtarg2)) 
    24112437                       ) 
    24122438                    { 
    24132439                        cn->Iop = 0x0F; 
    24142440                        cn->Iop2 = (c->Iop & 0x0F) ^ 0x81; 
    24152441                        c->Iop = NOP; 
    24162442                        c->IEV2.Vcode = NULL; 
    24172443                        bytesaved++; 
    24182444 
    24192445                        // If nobody else points to ct, we can remove the CFtarg 
    24202446                        if (flag && ct) 
    24212447                        {   code *cx; 
    24222448 
    24232449                            for (cx = bl->Bcode; 1; cx = code_next(cx)) 
    24242450                            { 
    24252451                                if (!cx) 
     
    25332559#ifdef DEBUG 
    25342560        if (0) 
    25352561        {       printf("assignaddrc()\n"); 
    25362562                c->print(); 
    25372563        } 
    25382564        if (code_next(c) && code_next(code_next(c)) == c) 
    25392565            assert(0); 
    25402566#endif 
    25412567        if (c->Iop == 0x0F) 
    25422568            ins = inssize2[c->Iop2]; 
    25432569        else if (c->Iop == ESCAPE) 
    25442570        { 
    25452571            if (c->Iop2 == ESCadjesp) 
    25462572            { 
    25472573                //printf("adjusting EBPtoESP (%d) by %ld\n",EBPtoESP,c->IEV2.Vint); 
    25482574                EBPtoESP += c->IEV2.Vint; 
    25492575                c->Iop = NOP; 
    25502576            } 
    25512577            if (c->Iop2 == ESCframeptr) 
    25522578            {   // Convert to load of frame pointer 
     2579                // c->Irm is the register to use 
    25532580                if (hasframe) 
    25542581                {   // MOV reg,EBP 
    25552582                    c->Iop = 0x89; 
    2556                     c->Irm = modregrm(3,BP,c->Irm); 
     2583                    if (c->Irm & 8) 
     2584                        c->Irex |= REX_B; 
     2585                    c->Irm = modregrm(3,BP,c->Irm & 7); 
    25572586                } 
    25582587                else 
    25592588                {   // LEA reg,EBPtoESP[ESP] 
    25602589                    c->Iop = 0x8D; 
    2561                     c->Irm = modregrm(2,c->Irm,4); 
     2590                    if (c->Irm & 8) 
     2591                        c->Irex |= REX_R; 
     2592                    c->Irm = modregrm(2,c->Irm & 7,4); 
    25622593                    c->Isib = modregrm(0,4,SP); 
    25632594                    c->Iflags = CFoff; 
    25642595                    c->IFL1 = FLconst; 
    25652596                    c->IEV1.Vuns = EBPtoESP; 
    25662597                } 
    25672598            } 
     2599            if (I64) 
     2600                c->Irex |= REX_W; 
    25682601            continue; 
    25692602        } 
    25702603        else 
    25712604            ins = inssize[c->Iop]; 
    25722605        if (!(ins & M) || 
    25732606            ((rm = c->Irm) & 0xC0) == 0xC0) 
    25742607            goto do2;           /* if no first operand          */ 
    25752608        if (is32bitaddr(I32,c->Iflags)) 
    25762609        { 
    25772610 
    25782611            if ( 
    25792612                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    25802613               ) 
    25812614                goto do2;       /* if no first operand  */ 
    25822615        } 
    25832616        else 
    25842617        { 
    25852618            if ( 
    25862619                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
    25872620               ) 
     
    26372670 
    26382671            case FLreg: 
    26392672            case FLauto: 
    26402673                soff = Aoff; 
    26412674            L1: 
    26422675                if (s->Sflags & SFLunambig && !(s->Sflags & SFLread) && // if never loaded 
    26432676                    !anyiasm && 
    26442677                    // if not optimized, leave it in for debuggability 
    26452678                    (config.flags4 & CFG4optimized || !config.fulltypes)) 
    26462679                {   c->Iop = NOP;               // remove references to it 
    26472680                    continue; 
    26482681                } 
    26492682                if (s->Sfl == FLreg && c->IEVpointer1 < 2) 
    26502683                {       int reg = s->Sreglsw; 
    26512684 
    26522685                        assert(!(s->Sregm & ~mask[reg])); 
    26532686                        if (c->IEVpointer1 == 1) 
    26542687                        {   assert(reg < 4);    /* must be a BYTEREGS   */ 
    26552688                            reg |= 4;           /* convert to high byte reg */ 
    26562689                        } 
     2690                        if (reg & 8) 
     2691                        {   assert(I64); 
     2692                            c->Irex |= REX_B; 
     2693                            reg &= 7; 
     2694                        } 
    26572695                        c->Irm = (c->Irm & modregrm(0,7,0)) 
    26582696                                | modregrm(3,0,reg); 
    26592697                        assert(c->Iop != LES && c->Iop != LEA); 
    26602698                        goto do2; 
    26612699                } 
    26622700                else 
    26632701                {   c->IEVpointer1 += s->Soffset + soff + BPoff; 
    26642702                    if (s->Sflags & SFLunambig) 
    26652703                        c->Iflags |= CFunambig; 
    26662704            L2: 
    26672705                    if (!hasframe) 
    26682706                    {   /* Convert to ESP relative address instead of EBP */ 
    26692707                        unsigned char rm; 
    26702708 
    2671                         assert(I32); 
     2709                        assert(!I16); 
    26722710                        c->IEVpointer1 += EBPtoESP; 
    26732711                        rm = c->Irm; 
    26742712                        if ((rm & 7) == 4)              // if SIB byte 
    26752713                        { 
    26762714                            assert((c->Isib & 7) == BP); 
    26772715                            assert((rm & 0xC0) != 0); 
    26782716                            c->Isib = (c->Isib & ~7) | modregrm(0,0,SP); 
    26792717                        } 
    26802718                        else 
    26812719                        { 
    26822720                            assert((rm & 7) == 5); 
    26832721                            c->Irm = (rm & modregrm(0,7,0)) 
    26842722                                    | modregrm(2,0,4); 
    26852723                            c->Isib = modregrm(0,4,SP); 
    26862724                        } 
    26872725                    } 
    26882726                } 
    26892727                break; 
    26902728            case FLpara: 
    26912729                soff = Poff - BPoff;    // cancel out add of BPoff 
     
    28772915void pinholeopt(code *c,block *b) 
    28782916{ targ_size_t a; 
    28792917  unsigned op,mod,rm,reg,ereg; 
    28802918  unsigned char ins; 
    28812919  int usespace; 
    28822920  int useopsize; 
    28832921  int space; 
    28842922  block *bn; 
    28852923 
    28862924#if 0 
    28872925  code *cstart = c; 
    28882926  if (debugc) 
    28892927  { 
    28902928      printf("+pinholeopt(%p)\n",c); 
    28912929  } 
    28922930#endif 
    28932931 
    28942932  if (b) 
    28952933  {     bn = b->Bnext; 
    28962934        usespace = (config.flags4 & CFG4space && b->BC != BCasm); 
    2897         useopsize = (!I32 || (config.flags4 & CFG4space && b->BC != BCasm)); 
     2935        useopsize = (I16 || (config.flags4 & CFG4space && b->BC != BCasm)); 
    28982936  } 
    28992937  else 
    29002938  {     bn = NULL; 
    29012939        usespace = (config.flags4 & CFG4space); 
    2902         useopsize = (!I32 || config.flags4 & CFG4space); 
     2940        useopsize = (I16 || config.flags4 & CFG4space); 
    29032941  } 
    29042942  for (; c; c = code_next(c)) 
    29052943  { 
    29062944    L1: 
    29072945        op = c->Iop; 
    29082946        if (op == 0x0F) 
    29092947            ins = inssize2[c->Iop2]; 
    29102948        else 
    29112949            ins = inssize[c->Iop]; 
    2912         if (ins & M)            /* if modregrm byte             */ 
    2913         {   int longop = (c->Iflags & CFopsize) ? !I32 : I32; 
     2950        if (!I64 && ins & M)            // if modregrm byte 
     2951        {   int longop = (c->Iflags & CFopsize) ? I16 : I32; 
    29142952            int local_BPRM = BPRM; 
    29152953 
    29162954            if (c->Iflags & CFaddrsize) 
    29172955                local_BPRM ^= 5 ^ 6;    // toggle between 5 and 6 
    29182956 
    29192957            rm = c->Irm; 
    29202958            reg = rm & (7<<3);          // isolate reg field 
    29212959            ereg = rm & 7; 
    29222960 
    29232961            /* If immediate second operand      */ 
    29242962            if ((ins & T || op == 0xF6 || op == 0xF7) && 
    29252963                c->IFL2 == FLconst) 
    29262964            {   int flags; 
    29272965                targ_long u; 
    29282966 
    29292967                flags = c->Iflags & CFpsw;      /* if want result in flags */ 
    29302968                u = c->IEV2.Vuns; 
    29312969                if (ins & E) 
    29322970                    u = (signed char) u; 
    29332971                else if (!longop) 
    29342972                    u = (short) u; 
    29352973 
    29362974                // Replace CMP reg,0 with TEST reg,reg 
    2937 #if 0 
    2938                 // BUG: is this the right one? 
    2939                 if ((op & 0xFC) == 0x80 && 
    2940 #else 
    29412975                if ((op & 0xFE) == 0x80 && 
    2942 #endif 
    29432976                    rm >= modregrm(3,7,AX) && 
    29442977                    u == 0) 
    29452978                {       c->Iop = (op & 1) | 0x84; 
    29462979                        c->Irm = modregrm(3,ereg,ereg); 
    29472980                        goto L1; 
    29482981                } 
    29492982 
    29502983                /* Optimize ANDs with an immediate constant             */ 
    29512984                if ((op == 0x81 || op == 0x80) && reg == modregrm(0,4,0)) 
    29522985                { 
    29532986                    if (rm >= modregrm(3,4,AX)) 
    29542987                    { 
    29552988                        if (u == 0) 
    29562989                        {       /* Replace with XOR reg,reg     */ 
    29572990                                c->Iop = 0x30 | (op & 1); 
    29582991                                NEWREG(c->Irm,rm & 7); 
    29592992                                goto L1; 
    29602993                        } 
    29612994                        if (u == 0xFFFFFFFF && !flags) 
    29622995                        {       c->Iop = NOP; 
     
    40234056    return offset;                      /* ending address               */ 
    40244057} 
    40254058 
    40264059 
    40274060STATIC void do64bit(enum FL fl,union evc *uev,int flags) 
    40284061{   char *p; 
    40294062    symbol *s; 
    40304063    targ_size_t ad; 
    40314064    long tmp; 
    40324065 
    40334066    assert(I64); 
    40344067    switch (fl) 
    40354068    { 
    40364069        case FLconst: 
    40374070            ad = * (targ_size_t *) uev; 
    40384071        L1: 
    40394072            GENP(8,&ad); 
    40404073            return; 
    40414074        case FLdatseg: 
    40424075            FLUSH(); 
    4043             reftodatseg(cseg,offset,uev->_EP.Vpointer,uev->_EP.Vseg,flags); 
     4076            reftodatseg(cseg,offset,uev->_EP.Vpointer,uev->_EP.Vseg,CFoffset64 | flags); 
    40444077            break; 
    40454078        case FLframehandler: 
    40464079            framehandleroffset = OFFSET(); 
    40474080            ad = 0; 
    40484081            goto L1; 
    40494082        case FLswitch: 
    40504083            FLUSH(); 
    40514084            ad = uev->Vswitch->Btableoffset; 
    40524085            if (config.flags & CFGromable) 
    40534086                    reftocodseg(cseg,offset,ad); 
    40544087            else 
    40554088                    reftodatseg(cseg,offset,ad,JMPSEG,CFoff); 
    40564089            break; 
    40574090        case FLcsdata: 
    40584091        case FLfardata: 
    40594092#if DEBUG 
    40604093            symbol_print(uev->sp.Vsym); 
    40614094#endif 
    40624095            assert(!TARGET_FLAT); 
    40634096            // NOTE: In ELFOBJ all symbol refs have been tagged FLextern 
    40644097            // strings and statics are treated like offsets from a 
    40654098            // un-named external with is the start of .rodata or .data 
    40664099        case FLextern:                      /* external data symbol         */ 
    40674100        case FLtlsdata: 
    40684101#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    40694102        case FLgot: 
    40704103        case FLgotoff: 
    40714104#endif 
    40724105            FLUSH(); 
    40734106            s = uev->sp.Vsym;               /* symbol pointer               */ 
    4074             reftoident(cseg,offset,s,uev->sp.Voffset,flags); 
     4107            reftoident(cseg,offset,s,uev->sp.Voffset,CFoffset64 | flags); 
    40754108            break; 
    40764109 
    40774110#if TARGET_OSX 
    40784111        case FLgot: 
    40794112            funcsym_p->Slocalgotoffset = OFFSET(); 
    40804113            ad = 0; 
    40814114            goto L1; 
    40824115#endif 
    40834116 
    40844117        case FLfunc:                        /* function call                */ 
    40854118            s = uev->sp.Vsym;               /* symbol pointer               */ 
    40864119            assert(!(TARGET_FLAT && tyfarfunc(s->ty()))); 
    40874120            FLUSH(); 
    4088             reftoident(cseg,offset,s,0,flags); 
     4121            reftoident(cseg,offset,s,0,CFoffset64 | flags); 
    40894122            break; 
    40904123 
    40914124        case FLblock:                       /* displacement to another block */ 
    40924125            ad = uev->Vblock->Boffset - OFFSET() - 4; 
    40934126            //printf("FLblock: funcoffset = %x, OFFSET = %x, Boffset = %x, ad = %x\n", funcoffset, OFFSET(), uev->Vblock->Boffset, ad); 
    40944127            goto L1; 
    40954128 
    40964129        case FLblockoff: 
    40974130            FLUSH(); 
    40984131            assert(uev->Vblock); 
    40994132            //printf("FLblockoff: offset = %x, Boffset = %x, funcoffset = %x\n", offset, uev->Vblock->Boffset, funcoffset); 
    41004133            reftocodseg(cseg,offset,uev->Vblock->Boffset); 
    41014134            break; 
    41024135 
    41034136        default: 
    41044137#ifdef DEBUG 
    41054138            WRFL(fl); 
    41064139#endif 
    41074140            assert(0); 
    41084141    } 
  • trunk/src/backend/cod4.c

    r569 r577  
    3333 * Return number of times symbol s appears in tree e. 
    3434 */ 
    3535 
    3636STATIC int intree(symbol *s,elem *e) 
    3737{ 
    3838        if (EOP(e)) 
    3939            return intree(s,e->E1) + (EBIN(e) ? intree(s,e->E2) : 0); 
    4040        return e->Eoper == OPvar && e->EV.sp.Vsym == s; 
    4141} 
    4242 
    4343/*********************************** 
    4444 * Determine if expression e can be evaluated directly into register 
    4545 * variable s. 
    4646 * Have to be careful about things like x=x+x+x, and x=a+x. 
    4747 * Returns: 
    4848 *      !=0     can 
    4949 *      0       can't 
    5050 */ 
    5151 
    5252STATIC int doinreg(symbol *s, elem *e) 
    53 {   int in
     53{   int in = 0
    5454    int op; 
    5555 
    5656 L1: 
    5757    op = e->Eoper; 
    5858    if (op == OPind || 
    5959        OTcall(op)  || 
    6060        OTleaf(op) || 
    6161        (in = intree(s,e)) == 0 || 
    6262        (OTunary(op) && !EOP(e->E1)) 
    6363       ) 
    6464        return 1; 
    6565    if (in == 1) 
    6666    { 
    6767        switch (op) 
    6868        { 
    6969            case OPadd: 
    7070            case OPmin: 
    7171            case OPand: 
    7272            case OPor: 
    7373            case OPxor: 
    7474            case OPshl: 
    7575            case OPmul: 
    7676                if (!intree(s,e->E2)) 
    7777                { 
    7878                    e = e->E1; 
    7979                    goto L1; 
    8080                } 
    8181        } 
    8282    } 
    8383    return 0; 
    8484} 
    8585 
    8686/**************************** 
    8787 * Return code for saving common subexpressions if EA 
    8888 * turns out to be a register. 
    8989 * This is called just before modifying an EA. 
    9090 */ 
    9191 
    92 code *modEA(unsigned Irm
     92code *modEA(code *c
    9393{ 
    94     return ((Irm & 0xC0) == 0xC0) ? getregs(mask[Irm & 7]) : CNIL; 
     94    if ((c->Irm & 0xC0) == 0xC0)        // addressing mode refers to a register 
     95    { 
     96        unsigned reg = c->Irm & 7; 
     97        if (c->Irex & REX_B) 
     98        {   reg |= 8; 
     99            assert(I64); 
     100        } 
     101        return getregs(mask[reg]); 
     102    } 
     103    return CNIL; 
    95104} 
    96105 
    97106#if TARGET_WINDOS 
    98107// This code is for CPUs that do not support the 8087 
    99108 
    100109/**************************** 
    101110 * Gen code for op= for doubles. 
    102111 */ 
    103112 
    104113STATIC code * opassdbl(elem *e,regm_t *pretregs,unsigned op) 
    105114{ code *c1,*c2,*c3,*c4,*c5,*c6,cs; 
    106115  unsigned clib; 
    107116  regm_t retregs2,retregs,idxregs; 
    108117  tym_t tym; 
    109118  elem *e1; 
    110119 
    111120  static unsigned clibtab[OPdivass - OPpostinc + 1] = 
    112121  /* OPpostinc,OPpostdec,OPeq,OPaddass,OPminass,OPmulass,OPdivass       */ 
    113122  {  CLIBdadd, CLIBdsub, (unsigned)-1,  CLIBdadd,CLIBdsub,CLIBdmul,CLIBddiv }; 
    114123 
     
    121130 
    122131  if (tym == TYfloat) 
    123132  { 
    124133        clib += CLIBfadd - CLIBdadd;    /* convert to float operation   */ 
    125134 
    126135        /* Load EA into FLOATREGS       */ 
    127136        c1 = cat(c1,getregs(FLOATREGS)); 
    128137        cs.Iop = 0x8B; 
    129138        cs.Irm |= modregrm(0,AX,0); 
    130139        c1 = gen(c1,&cs); 
    131140 
    132141        if (!I32) 
    133142        { 
    134143            cs.Irm |= modregrm(0,DX,0); 
    135144            getlvalue_msw(&cs); 
    136145            c1 = gen(c1,&cs); 
    137146            getlvalue_lsw(&cs); 
    138147 
    139148        } 
    140149        retregs2 = FLOATREGS2; 
    141         idxregs = FLOATREGS | idxregm(cs.Irm,cs.Isib); 
     150        idxregs = FLOATREGS | idxregm(&cs); 
    142151        retregs = FLOATREGS; 
    143152  } 
    144153  else 
    145154  { 
    146155        if (I32) 
    147156        { 
    148157            /* Load EA into DOUBLEREGS  */ 
    149158            c1 = cat(c1,getregs(DOUBLEREGS_32)); 
    150159            cs.Iop = 0x8B; 
    151160            cs.Irm |= modregrm(0,AX,0); 
    152161            c1 = gen(c1,&cs); 
    153162            cs.Irm |= modregrm(0,DX,0); 
    154163            getlvalue_msw(&cs); 
    155164            c1 = gen(c1,&cs); 
    156165            getlvalue_lsw(&cs); 
    157166 
    158167            retregs2 = DOUBLEREGS2_32; 
    159             idxregs = DOUBLEREGS_32 | idxregm(cs.Irm,cs.Isib); 
     168            idxregs = DOUBLEREGS_32 | idxregm(&cs); 
    160169        } 
    161170        else 
    162171        { 
    163172            /* Push EA onto stack       */ 
    164173            cs.Iop = 0xFF; 
    165174            cs.Irm |= modregrm(0,6,0); 
    166175            cs.IEVoffset1 += DOUBLESIZE - REGSIZE; 
    167176            c1 = gen(c1,&cs); 
    168177            getlvalue_lsw(&cs); 
    169178            gen(c1,&cs); 
    170179            getlvalue_lsw(&cs); 
    171180            gen(c1,&cs); 
    172181            getlvalue_lsw(&cs); 
    173182            gen(c1,&cs); 
    174183            stackpush += DOUBLESIZE; 
    175184 
    176185            retregs2 = DOUBLEREGS_16; 
    177             idxregs = idxregm(cs.Irm,cs.Isib); 
     186            idxregs = idxregm(&cs); 
    178187        } 
    179188        retregs = DOUBLEREGS; 
    180189  } 
    181190 
    182191  if ((cs.Iflags & CFSEG) == CFes) 
    183192        idxregs |= mES; 
    184193  cgstate.stackclean++; 
    185194  c3 = scodelem(e->E2,&retregs2,idxregs,FALSE); 
    186195  cgstate.stackclean--; 
    187196  c4 = callclib(e,clib,&retregs,0); 
    188197  if (e1->Ecount) 
    189198        cssave(e1,retregs,EOP(e1));             /* if lvalue is a CSE   */ 
    190199  freenode(e1); 
    191200  cs.Iop = 0x89;                                /* MOV EA,DOUBLEREGS    */ 
    192201  c5 = fltregs(&cs,tym); 
    193202  c6 = fixresult(e,retregs,pretregs); 
    194203  return cat6(c1,CNIL,c3,c4,c5,c6); 
    195204} 
    196205 
    197206/**************************** 
    198207 * Gen code for OPnegass for doubles. 
    199208 */ 
    200209 
    201210STATIC code * opnegassdbl(elem *e,regm_t *pretregs) 
    202211{   code *c1,*c2,*c3,*c,*cl,*cr,cs; 
    203212    unsigned clib; 
    204213    regm_t retregs2,retregs,idxregs; 
    205214    tym_t tym; 
    206215    elem *e1; 
    207216    int sz; 
    208217 
    209218    if (config.inline8087) 
    210219        return cdnegass87(e,pretregs); 
    211220    e1 = e->E1; 
    212221    tym = tybasic(e1->Ety); 
    213222    sz = tysize[tym]; 
    214223 
    215224    cl = getlvalue(&cs,e1,*pretregs ? DOUBLEREGS | mBX | mCX : 0); 
    216     cr = modEA(cs.Irm); 
     225    cr = modEA(&cs); 
    217226    cs.Irm |= modregrm(0,6,0); 
    218227    cs.Iop = 0x80; 
    219228    cs.IEVoffset1 += sz - 1; 
    220229    cs.IFL2 = FLconst; 
    221230    cs.IEV2.Vuns = 0x80; 
    222231    c = gen(NULL,&cs);                  // XOR 7[EA],0x80 
    223232    if (tycomplex(tym)) 
    224233    { 
    225234        cs.IEVoffset1 -= sz / 2; 
    226235        gen(c,&cs);                     // XOR 7[EA],0x80 
    227236    } 
    228237    c = cat3(cl,cr,c); 
    229238 
    230239    if (*pretregs || e1->Ecount) 
    231240    { 
    232241        cs.IEVoffset1 -= sz - 1; 
    233242 
    234243        if (tym == TYfloat) 
    235244        { 
    236245            // Load EA into FLOATREGS 
     
    353362  sz = tysize[tyml]; 
    354363  assert((int)sz > 0); 
    355364 
    356365  if (retregs == 0)                     /* if no return value           */ 
    357366  {     int fl; 
    358367 
    359368        if ((e2oper == OPconst ||       /* if rvalue is a constant      */ 
    360369             e2oper == OPrelconst && 
    361370             ((fl = el_fl(e2)) == FLdata || 
    362371              fl==FLudata || fl == FLextern) && 
    363372             !(e2->EV.sp.Vsym->ty() & mTYcs) 
    364373            ) && 
    365374            !evalinregister(e2) && 
    366375            !e1->Ecount)        /* and no CSE headaches */ 
    367376        { 
    368377            // Look for special case of (*p++ = ...), where p is a register variable 
    369378            if (e1->Eoper == OPind && 
    370379                ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && 
    371380                e11->E1->Eoper == OPvar && 
    372381                e11->E1->EV.sp.Vsym->Sfl == FLreg && 
    373                 (I32 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
     382                (!I16 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
    374383               ) 
    375384            { 
    376385                postinc = e11->E2->EV.Vint; 
    377386                if (e11->Eoper == OPpostdec) 
    378387                    postinc = -postinc; 
    379388                cl = getlvalue(&cs,e11,RMstore); 
    380389                freenode(e11->E2); 
    381390            } 
    382391            else 
    383392            {   postinc = 0; 
    384393                cl = getlvalue(&cs,e1,RMstore); 
    385394 
    386395                if (e2oper == OPconst && 
    387396                    config.flags4 & CFG4speed && 
    388397                    (config.target_cpu == TARGET_Pentium || 
    389398                     config.target_cpu == TARGET_PentiumMMX) && 
    390399                    (cs.Irm & 0xC0) == 0x80 
    391400                   ) 
    392401                { 
    393                     if (sz == REGSIZE && e2->EV.Vint) 
    394                     {   regm_t rregm; 
    395                         unsigned rreg; 
    396  
     402                    if (I64 && sz == 8 && e2->EV.Vpointer) 
     403                    { 
     404                        // MOV reg,imm64 
     405                        // MOV EA,reg 
     406                        regm_t rregm = allregs & ~idxregm(&cs); 
     407                        unsigned reg; 
     408                        cl = regwithvalue(cl,rregm,e2->EV.Vpointer,&reg,CFoffset64); 
     409                        cs.Iop = 0x89; 
     410                        cs.Irm |= modregrm(0,reg & 7,0); 
     411                        if (reg & 8) 
     412                            cs.Irex |= REX_R; 
     413                        c = gen(cl,&cs); 
     414                        freenode(e2); 
     415                        goto Lp; 
     416                    } 
     417                    if ((sz == REGSIZE || (I64 && sz == 4)) && e2->EV.Vint) 
     418                    { 
    397419                        // MOV reg,imm 
    398420                        // MOV EA,reg 
    399                         rregm = allregs & ~idxregm(cs.Irm,cs.Isib); 
     421                        regm_t rregm = allregs & ~idxregm(&cs); 
     422                        unsigned reg; 
    400423                        cl = regwithvalue(cl,rregm,e2->EV.Vint,&reg,0); 
    401424                        cs.Iop = 0x89; 
    402                         cs.Irm |= modregrm(0,reg,0); 
     425                        cs.Irm |= modregrm(0,reg & 7,0); 
     426                        if (reg & 8) 
     427                            cs.Irex |= REX_R; 
    403428                        c = gen(cl,&cs); 
    404429                        freenode(e2); 
    405430                        goto Lp; 
    406431                    } 
    407432                    if (sz == 2 * REGSIZE && e2->EV.Vllong == 0) 
    408433                    {   regm_t rregm; 
    409                         unsigned rreg; 
     434                        unsigned reg; 
    410435 
    411436                        // MOV reg,imm 
    412437                        // MOV EA,reg 
    413438                        // MOV EA+2,reg 
    414                         rregm = getscratch() & ~idxregm(cs.Irm,cs.Isib); 
     439                        rregm = getscratch() & ~idxregm(&cs); 
    415440                        if (rregm) 
    416441                        {   cl = regwithvalue(cl,rregm,e2->EV.Vint,&reg,0); 
    417442                            cs.Iop = 0x89; 
    418443                            cs.Irm |= modregrm(0,reg,0); 
    419444                            c = gen(cl,&cs); 
    420445                            getlvalue_msw(&cs); 
    421446                            c = gen(c,&cs); 
    422447                            freenode(e2); 
    423448                            goto Lp; 
    424449                        } 
    425450                    } 
    426451                } 
    427452            } 
    428453 
    429454            /* If loading result into a register        */ 
    430455            if ((cs.Irm & 0xC0) == 0xC0) 
    431             {   cl = cat(cl,getregs(mask[cs.Irm & 7])); 
     456            {   cl = cat(cl,modEA(&cs)); 
    432457                if (sz == 2 * REGSIZE && cs.IFL1 == FLreg) 
    433458                    cl = cat(cl,getregs(cs.IEVsym1->Sregm)); 
    434459            } 
    435460            cs.Iop = (sz == 1) ? 0xC6 : 0xC7; 
    436461 
    437462            if (e2oper == OPrelconst) 
    438463            { 
    439464                cs.IEVoffset2 = e2->EV.sp.Voffset; 
    440465                cs.IFL2 = fl; 
    441466                cs.IEVsym2 = e2->EV.sp.Vsym; 
    442467                cs.Iflags |= CFoff; 
    443468                cl = gen(cl,&cs);       /* MOV EA,&variable     */ 
     469                if (I64 && sz == 8) 
     470                    code_orrex(cl, REX_W); 
    444471                if (sz > REGSIZE) 
    445472                { 
    446473                    cs.Iop = 0x8C; 
    447474                    getlvalue_msw(&cs); 
    448475                    cs.Irm |= modregrm(0,3,0); 
    449476                    cl = gen(cl,&cs);   /* MOV EA+2,DS  */ 
    450477                } 
    451478            } 
    452479            else 
    453             {   targ_int *p; 
    454  
     480            { 
     481                assert(e2oper == OPconst); 
    455482                cs.IFL2 = FLconst; 
    456                 p = (targ_int *) &(e2->EV); 
    457                 cs.IEV2.Vint = *p; 
     483                targ_size_t *p = (targ_size_t *) &(e2->EV); 
     484                cs.IEV2.Vsize_t = *p; 
    458485                // Look for loading a register variable 
    459486                if ((cs.Irm & 0xC0) == 0xC0) 
    460                 { 
    461                         cl = movregconst(cl,cs.Irm & 7,*p,1 ^ (cs.Iop & 1)); 
    462                         if (sz == 2 * REGSIZE) 
    463                         {   getlvalue_msw(&cs); 
    464                             cl = movregconst(cl,cs.Irm & 7,p[1],0); 
    465                         } 
     487                {   unsigned reg = cs.Irm & 7; 
     488 
     489                    if (cs.Irex & REX_B) 
     490                        reg |= 8; 
     491                    if (I64 && sz == 8) 
     492                        cl = movregconst(cl,reg,*p,CFoffset64); 
     493                    else 
     494                        cl = movregconst(cl,reg,*p,1 ^ (cs.Iop & 1)); 
     495                    if (sz == 2 * REGSIZE) 
     496                    {   getlvalue_msw(&cs); 
     497                        cl = movregconst(cl,cs.Irm & 7,p[1],0); 
     498                    } 
    466499                } 
    467500                else 
    468501                {   int regsize; 
    469502 
    470                         i = sz; 
    471                         do 
    472                         {   regsize = REGSIZE; 
    473                             retregs = (sz == 1) ? BYTEREGS : allregs; 
    474                             if (i >= 4 && !I32 && I386) 
     503                    i = sz; 
     504                    do 
     505                    {   regsize = REGSIZE; 
     506                        retregs = (sz == 1) ? BYTEREGS : allregs; 
     507                        if (i >= 4 && I16 && I386) 
     508                        { 
     509                            regsize = 4; 
     510                            cs.Iflags |= CFopsize;      // use opsize to do 32 bit operation 
     511                        } 
     512                        else 
     513                        { 
     514                            if (reghasvalue(retregs,*p,&reg)) 
    475515                            { 
    476                                 regsize = 4; 
     516                                cs.Iop = (cs.Iop & 1) | 0x88; 
     517                                cs.Irm |= modregrm(0,reg & 7,0); // MOV EA,reg 
     518                                if (reg & 8) 
     519                                    cs.Irex |= REX_R; 
     520                            } 
     521                            if (!I16 && i == 2)      // if 16 bit operand 
    477522                                cs.Iflags |= CFopsize; 
    478                             } 
    479                             else 
    480                             { 
    481                                 if (reghasvalue(retregs,*p,&reg)) 
    482                                 { 
    483                                     cs.Iop = (cs.Iop & 1) | 0x88; 
    484                                     cs.Irm |= reg << 3; /* MOV EA,reg   */ 
    485                                 } 
    486                                 if (I32 && i == 2)      // if 16 bit operand 
    487                                     cs.Iflags |= CFopsize; 
    488                             } 
    489                             cl = gen(cl,&cs);           /* MOV EA,const */ 
    490  
    491                             p = (targ_int *)((char *) p + regsize); 
    492                             cs.Iop = (cs.Iop & 1) | 0xC6; 
    493                             cs.Irm &= ~(7 << 3); 
    494                             cs.IEVoffset1 += regsize; 
    495                             cs.IEV2.Vint = *p; 
    496                             i -= regsize; 
    497                         } while (i > 0); 
     523                            if (I64 && sz == 8) 
     524                                assert(cs.Irex & REX_W); 
     525                        } 
     526                        cl = gen(cl,&cs);           /* MOV EA,const */ 
     527 
     528                        p = (targ_size_t *)((char *) p + regsize); 
     529                        cs.Iop = (cs.Iop & 1) | 0xC6; 
     530                        cs.Irm &= ~modregrm(0,7,0); 
     531                        cs.Irex &= ~REX_R; 
     532                        cs.IEVoffset1 += regsize; 
     533                        cs.IEV2.Vint = *p; 
     534                        i -= regsize; 
     535                    } while (i > 0); 
    498536                } 
    499537            } 
    500538            freenode(e2); 
    501539            c = cl; 
    502540            goto Lp; 
    503541        } 
    504542        retregs = allregs;              /* pick a reg, any reg          */ 
    505543  } 
    506544  if (retregs == mPSW) 
    507545        retregs = allregs; 
    508546  cs.Iop = 0x89; 
    509547  if (sz == 1)                  // must have byte regs 
    510548  {     cs.Iop = 0x88; 
    511549        retregs &= BYTEREGS; 
    512550        if (!retregs) 
    513551                retregs = BYTEREGS; 
    514552  } 
    515553  else if (retregs & mES && 
    516554            ((e1->Eoper == OPind && 
    517555                ((tymll = tybasic(e1->E1->Ety)) == TYfptr || tymll == TYhptr)) 
     
    542580                if (e1->EV.sp.Voffset) 
    543581                    retregs &= mMSW; 
    544582                else 
    545583                    retregs &= mLSW; 
    546584                reg = findreg(retregs); 
    547585            } 
    548586        } 
    549587  } 
    550588  if (*pretregs & mPSW && !EOP(e1))     /* if evaluating e1 couldn't change flags */ 
    551589  {     /* Be careful that this lines up with jmpopcode()       */ 
    552590        retregs |= mPSW; 
    553591        *pretregs &= ~mPSW; 
    554592  } 
    555593  cr = scodelem(e2,&retregs,0,TRUE);    /* get rvalue                   */ 
    556594 
    557595    // Look for special case of (*p++ = ...), where p is a register variable 
    558596    if (e1->Eoper == OPind && 
    559597        ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && 
    560598        e11->E1->Eoper == OPvar && 
    561599        e11->E1->EV.sp.Vsym->Sfl == FLreg && 
    562         (I32 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
     600        (!I16 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 
    563601       ) 
    564602    { 
    565603        postinc = e11->E2->EV.Vint; 
    566604        if (e11->Eoper == OPpostdec) 
    567605            postinc = -postinc; 
    568606        cl = getlvalue(&cs,e11,RMstore | retregs); 
    569607        freenode(e11->E2); 
    570608    } 
    571609    else 
    572610    {   postinc = 0; 
    573611        cl = getlvalue(&cs,e1,RMstore | retregs);       // get lvalue (cl == CNIL if regvar) 
    574612    } 
    575613 
    576614  c = getregs_imm(varregm); 
    577615 
    578616  assert(!(retregs & mES && (cs.Iflags & CFSEG) == CFes)); 
    579617  if ((tyml == TYfptr || tyml == TYhptr) && retregs & mES) 
    580618  { 
    581619        reg = findreglsw(retregs); 
    582620        cs.Irm |= modregrm(0,reg,0); 
    583621        c = gen(c,&cs);                 /* MOV EA,reg                   */ 
    584622        getlvalue_msw(&cs);             // point to where segment goes 
    585623        cs.Iop = 0x8C; 
    586624        NEWREG(cs.Irm,0); 
    587625        gen(c,&cs);                     /* MOV EA+2,ES                  */ 
    588626  } 
    589627  else 
    590628  { 
    591         if (I32
     629        if (!I16
    592630        { 
    593631            reg = findreg(retregs & 
    594632                    ((sz > REGSIZE) ? mBP | mLSW : mBP | ALLREGS)); 
    595             cs.Irm |= modregrm(0,reg,0); 
     633            cs.Irm |= modregrm(0,reg & 7,0); 
     634            if (reg & 8) 
     635                cs.Irex |= REX_R; 
    596636            for (; TRUE; sz -= REGSIZE) 
    597637            { 
    598638                // Do not generate mov from register onto itself 
    599639                if (regvar && reg == (cs.Irm & 7)) 
    600640                    break; 
    601641                if (sz == 2)            // if 16 bit operand 
    602642                    cs.Iflags |= CFopsize; 
    603643                c = gen(c,&cs);         // MOV EA+offset,reg 
    604644                if (sz <= REGSIZE) 
    605645                    break; 
    606646                getlvalue_msw(&cs); 
    607647                reg = findregmsw(retregs); 
    608                 NEWREG(cs.Irm,reg); 
     648                code_newreg(&cs, reg); 
    609649            } 
    610650        } 
    611651        else 
    612652        { 
    613653            if (sz > REGSIZE) 
    614654                cs.IEVoffset1 += sz - REGSIZE;  /* 0,2,6        */ 
    615655            reg = findreg(retregs & 
    616656                    (sz > REGSIZE ? mMSW : ALLREGS)); 
    617657            if (tyml == TYdouble || tyml == TYdouble_alias) 
    618658                reg = AX; 
    619659            cs.Irm |= modregrm(0,reg,0); 
    620660            /* Do not generate mov from register onto itself            */ 
    621661            if (!regvar || reg != (cs.Irm & 7)) 
    622662                for (; TRUE; sz -= REGSIZE)             /* 1,2,4        */ 
    623663                { 
    624664                    c = gen(c,&cs);             /* MOV EA+offset,reg            */ 
    625665                    if (sz <= REGSIZE) 
    626666                        break; 
    627667                    cs.IEVoffset1 -= REGSIZE; 
    628668                    if (tyml == TYdouble || tyml == TYdouble_alias) 
    629669                            reg = dblreg[reg]; 
    630670                    else 
    631671                            reg = findreglsw(retregs); 
    632672                    NEWREG(cs.Irm,reg); 
    633673                } 
    634674        } 
    635675  } 
    636676  if (e1->Ecount ||                     /* if lvalue is a CSE or        */ 
    637677      regvar)                           /* rvalue can't be a CSE        */ 
    638678  { 
    639679        c = cat(c,getregs_imm(retregs));        // necessary if both lvalue and 
    640680                                        //  rvalue are CSEs (since a reg 
    641681                                        //  can hold only one e at a time) 
    642682        cssave(e1,retregs,EOP(e1));     /* if lvalue is a CSE           */ 
    643683  } 
    644684 
    645685    c = cat4(cr,cl,c,fixresult(e,retregs,pretregs)); 
    646686Lp: 
    647687    if (postinc) 
    648     {   int reg; 
    649  
    650         reg = findreg(idxregm(cs.Irm,cs.Isib)); 
     688    { 
     689        int reg = findreg(idxregm(&cs)); 
    651690        if (*pretregs & mPSW) 
    652691        {   // Use LEA to avoid touching the flags 
    653             c = genc1(c,0x8D,modregrm(2,reg,cs.Irm & 7),FLconst,postinc); 
     692            unsigned rm = cs.Irm & 7; 
     693            if (cs.Irex & REX_B) 
     694                rm |= 8; 
     695            c = genc1(c,0x8D,modregxrmx(2,reg,rm),FLconst,postinc); 
     696            if (sz == 8) 
     697                code_orrex(c, REX_W); 
     698        } 
     699        else if (I64) 
     700        { 
     701            c = genc2(c,0x81,modregrmx(3,0,reg),postinc); 
     702            if (sz == 8) 
     703                code_orrex(c, REX_W); 
    654704        } 
    655705        else 
    656706        { 
    657707            if (postinc == 1) 
    658708                c = gen1(c,0x40 + reg);         // INC reg 
    659709            else if (postinc == -(targ_int)1) 
    660710                c = gen1(c,0x48 + reg);         // DEC reg 
    661711            else 
    662712            { 
    663713                c = genc2(c,0x81,modregrm(3,0,reg),postinc); 
    664714            } 
    665715        } 
    666716    } 
    667717    freenode(e1); 
    668718    return c; 
    669719} 
    670720 
    671721 
    672722/************************ 
    673723 * Generate code for += -= &= |= ^= negass 
     
    695745  reverse = 0; 
    696746  e1 = e->E1; 
    697747  tyml = tybasic(e1->Ety);              // type of lvalue 
    698748  sz = tysize[tyml]; 
    699749  byte = (sz == 1);                     // 1 for byte operation, else 0 
    700750  if (tyfloating(tyml)) 
    701751  { 
    702752#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    703753      if (op == OPnegass) 
    704754            c = cdnegass87(e,pretregs); 
    705755        else 
    706756            c = opass87(e,pretregs); 
    707757#else 
    708758        if (op == OPnegass) 
    709759            c = opnegassdbl(e,pretregs); 
    710760        else 
    711761            c = opassdbl(e,pretregs,op); 
    712762#endif 
    713763        return c; 
    714764  } 
    715   opsize = (!I32 && tylong(tyml) && config.target_cpu >= TARGET_80386) 
     765  opsize = (I16 && tylong(tyml) && config.target_cpu >= TARGET_80386) 
    716766        ? CFopsize : 0; 
    717767  cflags = 0; 
    718768  forccs = *pretregs & mPSW;            // return result in flags 
    719   forregs = *pretregs & (mBP | ALLREGS | mES);  // return result in regs 
     769  forregs = *pretregs & ~mPSW;          // return result in regs 
    720770  /* TRUE if we want the result in a register   */ 
    721771  wantres = forregs || (e1->Ecount && EOP(e1)); 
    722772 
    723773  switch (op)                   /* select instruction opcodes           */ 
    724774  {     case OPpostinc: op = OPaddass;                  /* i++ => +=    */ 
    725775        case OPaddass:  op1 = 0x01; op2 = 0x11; 
    726776                        cflags = CFpsw; 
    727777                        mode = 0; break;                /* ADD, ADC     */ 
    728778        case OPpostdec: op = OPminass;                  /* i-- => -=    */ 
    729779        case OPminass:  op1 = 0x29; op2 = 0x19; 
    730780                        cflags = CFpsw; 
    731781                        mode = 5; break;                /* SUB, SBC     */ 
    732782        case OPandass:  op1 = op2 = 0x21; 
    733783                        mode = 4; break;                /* AND, AND     */ 
    734784        case OPorass:   op1 = op2 = 0x09; 
    735785                        mode = 1; break;                /* OR , OR      */ 
    736786        case OPxorass:  op1 = op2 = 0x31; 
    737787                        mode = 6; break;                /* XOR, XOR     */ 
    738788        case OPnegass:  op1 = 0xF7;                     // NEG 
    739789                        break; 
    740790        default: 
    741791                assert(0); 
    742792  } 
    743793  op1 ^= byte;                  /* bit 0 is 0 for byte operation        */ 
    744794 
    745795  if (op == OPnegass) 
    746796  { 
    747797        cl = getlvalue(&cs,e1,0); 
    748         cr = modEA(cs.Irm); 
     798        cr = modEA(&cs); 
    749799        cs.Irm |= modregrm(0,3,0); 
    750800        cs.Iop = op1; 
    751801        switch (tysize[tyml]) 
    752802        {   case CHARSIZE: 
    753803                c = gen(CNIL,&cs); 
    754804                break; 
    755805            case SHORTSIZE: 
    756806                c = gen(CNIL,&cs); 
    757                 if (I32 && *pretregs & mPSW) 
     808                if (!I16 && *pretregs & mPSW) 
    758809                    c->Iflags |= CFopsize | CFpsw; 
    759810                break; 
    760811            case LONGSIZE: 
    761                 if (I32 || opsize) 
     813                if (!I16 || opsize) 
    762814                {   c = gen(CNIL,&cs); 
    763815                    c->Iflags |= opsize; 
    764816                    break; 
    765817                } 
    766818            neg_2reg: 
    767819                getlvalue_msw(&cs); 
    768820                c = gen(CNIL,&cs);              // NEG EA+2 
    769821                getlvalue_lsw(&cs); 
    770822                gen(c,&cs);                     // NEG EA 
    771823                code_orflag(c,CFpsw); 
    772824                cs.Iop = 0x81; 
    773825                getlvalue_msw(&cs); 
    774826                cs.IFL2 = FLconst; 
    775827                cs.IEV2.Vuns = 0; 
    776828                gen(c,&cs);                     // SBB EA+2,0 
    777829                break; 
    778830            case LLONGSIZE: 
    779                 if (I32
    780                     goto neg_2reg; 
    781                 assert(0);                      // not implemented yet 
    782                 break; 
     832                if (I16
     833                    assert(0);                      // not implemented yet 
     834                goto neg_2reg; 
     835 
    783836            default: 
    784837                assert(0); 
    785838        } 
    786839        c = cat3(cl,cr,c); 
    787840        forccs = 0;             // flags already set by NEG 
    788841        *pretregs &= ~mPSW; 
    789842  } 
    790843  else if ((e2 = e->E2)->Eoper == OPconst &&    // if rvalue is a const 
    791844       // Don't evaluate e2 in register if we can use an INC or DEC 
    792845      (((sz <= REGSIZE || tyfv(tyml)) && 
    793846        (op == OPaddass || op == OPminass) && 
    794847        ((val = el_tolong(e2)) == 1 || val == -1) 
    795848       ) || 
    796849       (!evalinregister(e2) && tyml != TYhptr) 
    797850      ) 
    798851     ) 
    799852  { 
    800853        cl = getlvalue(&cs,e1,0); 
    801         cl = cat(cl,modEA(cs.Irm)); 
     854        cl = cat(cl,modEA(&cs)); 
    802855        cs.IFL2 = FLconst; 
    803856        cs.IEV2.Vint = e2->EV.Vint; 
    804857        if (sz <= REGSIZE || tyfv(tyml) || opsize) 
    805         {   targ_int i; 
    806  
    807             i = cs.IEV2.Vint; 
     858        { 
     859            targ_size_t i = cs.IEV2.Vsize_t; 
    808860 
    809861            /* Handle shortcuts. Watch out for if result has    */ 
    810862            /* to be in flags.                                  */ 
    811863 
    812864            if (reghasvalue(ALLREGS,i,&reg) && i != 1 && i != -1 && 
    813865                !opsize) 
    814866            { 
    815867                cs.Iop = op1; 
    816868                cs.Irm |= modregrm(0,reg,0); 
    817869            } 
    818870            else 
    819871            { 
    820872                cs.Iop = 0x81; 
    821873                cs.Irm |= modregrm(0,mode,0); 
    822874                switch (op) 
    823875                {   case OPminass:      /* convert to +=        */ 
    824876                        cs.Irm ^= modregrm(0,5,0); 
    825877                        i = -i; 
    826                         cs.IEV2.Vint = i; 
     878                        cs.IEV2.Vsize_t = i; 
    827879                        /* FALL-THROUGH */ 
    828880                    case OPaddass: 
    829881                        if (i == 1)             /* INC EA       */ 
    830882                                goto L1; 
    831883                        else if (i == -1)       /* DEC EA       */ 
    832884                        {       cs.Irm |= modregrm(0,1,0); 
    833885                           L1:  cs.Iop = 0xFF; 
    834886                        } 
    835887                        break; 
    836888                } 
    837889            } 
    838890            cs.Iop ^= byte;             /* for byte operations  */ 
    839891            cs.Iflags |= opsize; 
    840892            if (forccs) 
    841893                cs.Iflags |= CFpsw; 
    842             else if (I32 && cs.Iflags & CFopsize) 
     894            else if (!I16 && cs.Iflags & CFopsize) 
    843895            { 
    844896                switch (op) 
    845897                {   case OPorass: 
    846898                    case OPxorass: 
    847                         cs.IEV2.Vint &= 0xFFFF; 
     899                        cs.IEV2.Vsize_t &= 0xFFFF; 
    848900                        cs.Iflags &= ~CFopsize; // don't worry about MSW 
    849901                        break; 
    850902                    case OPandass: 
    851                         cs.IEV2.Vint |= ~0xFFFFL; 
     903                        cs.IEV2.Vsize_t |= ~0xFFFFLL; 
    852904                        cs.Iflags &= ~CFopsize; // don't worry about MSW 
    853905                        break; 
    854906                    case OPminass: 
    855907                    case OPaddass: 
    856908#if 1 
    857909                        if ((cs.Irm & 0xC0) == 0xC0)    // EA is register 
    858910                            cs.Iflags &= ~CFopsize; 
    859911#else 
    860912                        if ((cs.Irm & 0xC0) == 0xC0 &&  // EA is register and 
    861913                            e1->Eoper == OPind)         // not a register var 
    862914                            cs.Iflags &= ~CFopsize; 
    863915#endif 
    864916                        break; 
    865917                    default: 
    866918                        assert(0); 
    867919                        break; 
    868920                } 
    869921            } 
    870922 
    871923            // For scheduling purposes, we wish to replace: 
    872924            //    OP    EA 
    873925            // with: 
    874926            //    MOV   reg,EA 
    875927            //    OP    reg 
    876928            //    MOV   EA,reg 
    877929            if (forregs && sz <= REGSIZE && (cs.Irm & 0xC0) != 0xC0 && 
    878930                (config.target_cpu == TARGET_Pentium || 
    879931                 config.target_cpu == TARGET_PentiumMMX) && 
    880932                config.flags4 & CFG4speed) 
    881933            {   regm_t sregm; 
    882934                code cs2; 
    883935 
    884936                // Determine which registers to use 
    885                 sregm = allregs & ~idxregm(cs.Irm,cs.Isib); 
     937                sregm = allregs & ~idxregm(&cs); 
    886938                if (byte) 
    887939                    sregm &= BYTEREGS; 
    888940                if (sregm & forregs) 
    889941                    sregm &= forregs; 
    890942 
    891943                cr = allocreg(&sregm,&reg,tyml);        // allocate register 
    892944 
    893945                cs2 = cs; 
    894946                cs2.Iflags &= ~CFpsw; 
    895947                cs2.Iop = 0x8B ^ byte; 
    896                 cs2.Irm = (cs2.Irm & modregrm(3,0,7)) | modregrm(0,reg,0); 
     948                code_newreg(&cs2, reg); 
    897949                cr = gen(cr,&cs2);                      // MOV reg,EA 
    898950 
    899                 cs.Irm = (cs.Irm & modregrm(0,7,0)) | modregrm(3,0,reg); 
     951                cs.Irm = (cs.Irm & modregrm(0,7,0)) | modregrm(3,0,reg & 7); 
     952                if (reg & 8) 
     953                    cs.Irex |= REX_B; 
    900954                gen(cr,&cs);                            // OP reg 
    901955 
    902956                cs2.Iop ^= 2; 
    903957                gen(cr,&cs2);                           // MOV EA,reg 
    904958 
    905959                c = cat(cl,cr); 
    906960                retregs = sregm; 
    907961                wantres = 0; 
    908962                if (e1->Ecount) 
    909963                    cssave(e1,retregs,EOP(e1)); 
    910964            } 
    911965            else 
    912966            { 
    913967                c = gen(cl,&cs); 
    914968                cs.Iflags &= ~opsize; 
    915969                cs.Iflags &= ~CFpsw; 
    916                 if (!I32 && opsize)                     // if DWORD operand 
     970                if (I16 && opsize)                     // if DWORD operand 
    917971                    cs.IEVoffset1 += 2; // compensate for wantres code 
    918972            } 
    919973        } 
    920974        else if (sz == 2 * REGSIZE) 
    921975        {       targ_uns msw; 
    922976 
    923977                cs.Iop = 0x81; 
    924978                cs.Irm |= modregrm(0,mode,0); 
    925979                c = cl; 
    926980                cs.Iflags |= cflags; 
    927981                c = gen(c,&cs); 
    928982                cs.Iflags &= ~CFpsw; 
    929983 
    930984                getlvalue_msw(&cs);             // point to msw 
    931985                msw = MSREG(e->E2->EV.Vllong); 
    932986                cs.IEV2.Vuns = msw;             /* msw of constant      */ 
    933987                switch (op) 
    934988                {   case OPminass: 
    935989                        cs.Irm ^= modregrm(0,6,0);      /* SUB => SBB   */ 
    936990                        break; 
    937991                    case OPaddass: 
    938992                        cs.Irm |= modregrm(0,2,0);      /* ADD => ADC   */ 
    939993                        break; 
    940994                } 
    941995                c = gen(c,&cs); 
    942996        } 
    943997        freenode(e->E2);        /* don't need it anymore        */ 
    944998  } 
    945999  else if (isregvar(e1,&varregm,&varreg) && 
    9461000           (e2->Eoper == OPvar || e2->Eoper == OPind) && 
    9471001          !evalinregister(e2) && 
    9481002           sz <= REGSIZE)               // deal with later 
    9491003  { 
    9501004        cr = getlvalue(&cs,e2,0); 
    9511005        freenode(e2); 
    9521006        cl = getregs(varregm); 
    953         cs.Irm |= modregrm(0,varreg,0); 
     1007        code_newreg(&cs, varreg); 
    9541008        cs.Iop = op1 ^ 2;                       // toggle direction bit 
    9551009        if (forccs) 
    9561010            cs.Iflags |= CFpsw; 
    9571011        reverse = 2;                            // remember we toggled it 
    9581012        cl = gen(cl,&cs); 
    9591013        c = cat(cr,cl); 
    9601014        retregs = 0;            /* to trigger a bug if we attempt to use it */ 
    9611015  } 
    9621016  else // evaluate e2 into register 
    9631017  { 
    9641018        retregs = (byte) ? BYTEREGS : ALLREGS;  // pick working reg 
    9651019        if (tyml == TYhptr) 
    9661020            retregs &= ~mCX;                    // need CX for shift count 
    9671021        cr = scodelem(e->E2,&retregs,0,TRUE);   // get rvalue 
    9681022        cl = getlvalue(&cs,e1,retregs);         // get lvalue 
    969         cl = cat(cl,modEA(cs.Irm)); 
     1023        cl = cat(cl,modEA(&cs)); 
    9701024        cs.Iop = op1; 
    9711025        if (sz <= REGSIZE || tyfv(tyml)) 
    9721026        {   reg = findreg(retregs); 
    973             cs.Irm |= modregrm(0,reg,0);        // OP1 EA,reg 
     1027            code_newreg(&cs, reg);              // OP1 EA,reg 
    9741028        } 
    9751029        else if (tyml == TYhptr) 
    9761030        {   unsigned mreg,lreg; 
    9771031 
    9781032            mreg = findregmsw(retregs); 
    9791033            lreg = findreglsw(retregs); 
    9801034            cl = cat(cl,getregs(retregs | mCX)); 
    9811035 
    9821036            // If h -= l, convert to h += -l 
    9831037            if (e->Eoper == OPminass) 
    9841038            { 
    9851039                cl = gen2(cl,0xF7,modregrm(3,3,mreg));  // NEG mreg 
    9861040                gen2(cl,0xF7,modregrm(3,3,lreg));       // NEG lreg 
    9871041                code_orflag(cl,CFpsw); 
    9881042                genc2(cl,0x81,modregrm(3,3,mreg),0);    // SBB mreg,0 
    9891043            } 
    9901044            cs.Iop = 0x01; 
    9911045            cs.Irm |= modregrm(0,lreg,0); 
    9921046            cl = gen(cl,&cs);                           // ADD EA,lreg 
    9931047            code_orflag(cl,CFpsw); 
     
    10151069 
    10161070  /* See if we need to reload result into a register.   */ 
    10171071  /* Need result in registers in case we have a 32 bit  */ 
    10181072  /* result and we want the flags as a result.          */ 
    10191073  if (wantres || (sz > REGSIZE && forccs)) 
    10201074  { 
    10211075        if (sz <= REGSIZE) 
    10221076        {   regm_t possregs; 
    10231077 
    10241078            possregs = ALLREGS; 
    10251079            if (byte) 
    10261080                possregs = BYTEREGS; 
    10271081            retregs = forregs & possregs; 
    10281082            if (!retregs) 
    10291083                    retregs = possregs; 
    10301084 
    10311085            // If reg field is destination 
    10321086            if (cs.Iop & 2 && cs.Iop < 0x40 && (cs.Iop & 7) <= 5) 
    10331087            { 
    10341088                reg = (cs.Irm >> 3) & 7; 
     1089                if (cs.Irex & REX_R) 
     1090                    reg |= 8; 
    10351091                retregs = mask[reg]; 
    10361092                ce = allocreg(&retregs,&reg,tyml); 
    10371093            } 
    10381094            // If lvalue is a register, just use that register 
    10391095            else if ((cs.Irm & 0xC0) == 0xC0) 
    10401096            { 
    10411097                reg = cs.Irm & 7; 
     1098                if (cs.Irex & REX_B) 
     1099                    reg |= 8; 
    10421100                retregs = mask[reg]; 
    10431101                ce = allocreg(&retregs,&reg,tyml); 
    10441102            } 
    10451103            else 
    10461104            { 
    10471105                ce = allocreg(&retregs,&reg,tyml); 
    10481106                cs.Iop = 0x8B ^ byte ^ reverse; 
    1049                 NEWREG(cs.Irm,reg); 
     1107                code_newreg(&cs, reg); 
    10501108                ce = gen(ce,&cs);               // MOV reg,EA 
    10511109            } 
    10521110        } 
    10531111        else if (tyfv(tyml) || tyml == TYhptr) 
    10541112        {       regm_t idxregs; 
    10551113 
    10561114                if (tyml == TYhptr) 
    10571115                    getlvalue_lsw(&cs); 
    1058                 idxregs = idxregm(cs.Irm,cs.Isib); 
     1116                idxregs = idxregm(&cs); 
    10591117                retregs = forregs & ~idxregs; 
    10601118                if (!(retregs & IDXREGS)) 
    10611119                        retregs |= IDXREGS & ~idxregs; 
    10621120                if (!(retregs & mMSW)) 
    10631121                        retregs |= mMSW & ALLREGS; 
    10641122                ce = allocreg(&retregs,&reg,tyml); 
    10651123                NEWREG(cs.Irm,findreglsw(retregs)); 
    10661124                if (retregs & mES)              /* if want ES loaded    */ 
    10671125                {   cs.Iop = 0xC4; 
    10681126                    ce = gen(ce,&cs);           /* LES lreg,EA          */ 
    10691127                } 
    10701128                else 
    10711129                {   cs.Iop = 0x8B; 
    10721130                    ce = gen(ce,&cs);           /* MOV lreg,EA          */ 
    10731131                    getlvalue_msw(&cs); 
    10741132                    if (I32) 
    10751133                        cs.Iflags |= CFopsize; 
    10761134                    NEWREG(cs.Irm,reg); 
    10771135                    gen(ce,&cs);                /* MOV mreg,EA+2        */ 
    10781136                } 
    10791137        } 
    10801138        else if (sz == 2 * REGSIZE) 
    10811139        {       regm_t idx; 
    10821140                code *cm,*cl; 
    10831141 
    1084                 idx = idxregm(cs.Irm,cs.Isib); 
     1142                idx = idxregm(&cs); 
    10851143                retregs = forregs; 
    10861144                if (!retregs) 
    10871145                        retregs = ALLREGS; 
    10881146                ce = allocreg(&retregs,&reg,tyml); 
    10891147                cs.Iop = 0x8B; 
    10901148                NEWREG(cs.Irm,reg); 
    10911149                cm = gen(NULL,&cs);             // MOV reg,EA+2 
    10921150                NEWREG(cs.Irm,findreglsw(retregs)); 
    10931151                getlvalue_lsw(&cs); 
    10941152                cl = gen(NULL,&cs);             // MOV reg+1,EA 
    10951153                if (mask[reg] & idx) 
    10961154                    ce = cat3(ce,cl,cm); 
    10971155                else 
    10981156                    ce = cat3(ce,cm,cl); 
    10991157        } 
    11001158        c = cat(c,ce); 
    11011159        if (e1->Ecount)                 /* if we gen a CSE      */ 
    11021160                cssave(e1,retregs,EOP(e1)); 
    11031161  } 
    11041162  freenode(e1); 
    11051163  if (sz <= REGSIZE) 
    1106         *pretregs &= mES | ALLREGS | mBP;       // flags are already set 
     1164        *pretregs &= ~mPSW;            // flags are already set 
    11071165  return cat(c,fixresult(e,retregs,pretregs)); 
    11081166} 
    11091167 
    11101168 
    11111169/******************************** 
    11121170 * Generate code for *= /= %= 
    11131171 */ 
    11141172 
    11151173code *cdmulass(elem *e,regm_t *pretregs) 
    11161174{ elem *e1,*e2; 
    11171175  code *cr,*cl,*cg,*c,cs; 
    11181176  tym_t tym,tyml; 
    11191177  regm_t retregs; 
    11201178  char uns; 
    11211179  unsigned op,resreg,reg,opr,lib,byte; 
    11221180  unsigned sz; 
    11231181 
    11241182  e1 = e->E1; 
    11251183  e2 = e->E2; 
    11261184  op = e->Eoper;                        /* OPxxxx                       */ 
    11271185 
    11281186  tyml = tybasic(e1->Ety);              /* type of lvalue               */ 
    11291187  uns = tyuns(tyml) || tyuns(e2->Ety); 
    11301188  tym = tybasic(e->Ety);                /* type of result               */ 
    11311189  sz = tysize[tyml]; 
     1189 
     1190    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1191    unsigned grex = rex << 16;          // 64 bit operands 
     1192 
    11321193 
    11331194  if (tyfloating(tyml)) 
    11341195#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    11351196        return opass87(e,pretregs); 
    11361197#else 
    11371198        return opassdbl(e,pretregs,op); 
    11381199#endif 
    11391200 
    11401201  if (sz <= REGSIZE)                    /* if word or byte              */ 
    11411202  {     byte = (sz == 1);               /* 1 for byte operation         */ 
    11421203        resreg = AX;                    /* result register for * or /   */ 
    11431204        if (uns)                        /* if unsigned operation        */ 
    11441205                opr = 4;                /* MUL                          */ 
    11451206        else                            /* else signed                  */ 
    11461207                opr = 5;                /* IMUL                         */ 
    11471208        if (op != OPmulass)             /* if /= or %=                  */ 
    11481209        {       opr += 2;               /* MUL => DIV, IMUL => IDIV     */ 
    11491210                if (op == OPmodass) 
    11501211                        resreg = DX;    /* remainder is in DX           */ 
    11511212        } 
    11521213        if (op == OPmulass)             /* if multiply                  */ 
    11531214        { 
    11541215            if (config.target_cpu >= TARGET_80286 && 
    11551216                e2->Eoper == OPconst && !byte) 
    1156             {   targ_int e2factor; 
    1157                 regm_t idxregs
    1158  
    1159                 e2factor = el_tolong(e2)
     1217            { 
     1218                targ_size_t e2factor = el_tolong(e2)
     1219                if (I64 && sz == 8 && e2factor != (int)e2factor) 
     1220                    goto L1
    11601221                freenode(e2); 
    11611222                cr = CNIL; 
    11621223                cl = getlvalue(&cs,e1,0);       /* get EA               */ 
    1163                 idxregs = idxregm(cs.Irm,cs.Isib); 
     1224                regm_t idxregs = idxregm(&cs); 
    11641225                retregs = *pretregs & (ALLREGS | mBP) & ~idxregs; 
    11651226                if (!retregs) 
    11661227                    retregs = ALLREGS & ~idxregs; 
    11671228                cg = allocreg(&retregs,&resreg,tyml); 
    11681229                cs.Iop = 0x69;                  /* IMUL reg,EA,e2value  */ 
    11691230                cs.IFL2 = FLconst; 
    11701231                cs.IEV2.Vint = e2factor; 
    11711232                opr = resreg; 
    11721233            } 
    1173             else if (I32 && !byte) 
    1174             { 
     1234            else if (!I16 && !byte) 
     1235            { 
     1236             L1: 
    11751237                retregs = *pretregs & (ALLREGS | mBP); 
    11761238                if (!retregs) 
    11771239                    retregs = ALLREGS; 
    11781240                cr = codelem(e2,&retregs,FALSE); /* load rvalue in reg  */ 
    11791241                cl = getlvalue(&cs,e1,retregs); /* get EA               */ 
    11801242                cg = getregs(retregs);          /* destroy these regs   */ 
    11811243                cs.Iop = 0x0F;                  /* IMUL resreg,EA       */ 
    11821244                cs.Iop2 = 0xAF; 
    11831245                resreg = findreg(retregs); 
    11841246                opr = resreg; 
    11851247            } 
    11861248            else 
    11871249            { 
    11881250                retregs = mAX; 
    11891251                cr = codelem(e2,&retregs,FALSE); // load rvalue in AX 
    11901252                cl = getlvalue(&cs,e1,mAX);     // get EA 
    11911253                cg = getregs(byte ? mAX : mAX | mDX); // destroy these regs 
    11921254                cs.Iop = 0xF7 ^ byte;           // [I]MUL EA 
    11931255            } 
    11941256            cs.Irm |= modregrm(0,opr,0); 
    11951257            c = gen(CNIL,&cs); 
    11961258        } 
    11971259        else // /= or %= 
    1198         {   targ_int e2factor; 
     1260        {   targ_size_t e2factor; 
    11991261            int pow2; 
    12001262            targ_ulong m; 
    12011263 
    12021264            assert(!byte);                      // should never happen 
    1203             assert(!I32 || sz != SHORTSIZE); 
     1265            assert(I16 || sz != SHORTSIZE); 
    12041266            if (config.flags4 & CFG4speed && 
    1205                 e2->Eoper == OPconst && sz == REGSIZE && !uns && 
     1267                e2->Eoper == OPconst && !uns && 
     1268                (sz == REGSIZE || (I64 && sz == 4)) && 
    12061269                (pow2 = ispow2(e2factor = el_tolong(e2))) != -1 && 
     1270                e2factor == (int)e2factor && 
    12071271                !(config.target_cpu < TARGET_80286 && pow2 != 1 && op == OPdivass) 
    12081272               ) 
    12091273            { 
    12101274                // Signed divide or modulo by power of 2 
    12111275                cr = NULL; 
    12121276                c = NULL; 
    12131277                cl = getlvalue(&cs,e1,mAX | mDX); 
    12141278                cs.Iop = 0x8B; 
    1215                 NEWREG(cs.Irm,AX); 
     1279                code_newreg(&cs, AX); 
    12161280                cl = gen(cl,&cs);                       // MOV AX,EA 
    12171281                freenode(e2); 
    12181282                cg = getregs(mAX | mDX);                // trash these regs 
    12191283                cg = gen1(cg,0x99);                     // CWD 
     1284                code_orrex(cg, rex); 
    12201285                if (pow2 == 1) 
    12211286                { 
    12221287                    if (op == OPdivass) 
    1223                     {   gen2(cg,0x2B,modregrm(3,AX,DX));        // SUB AX,DX 
    1224                         gen2(cg,0xD1,modregrm(3,7,AX));         // SAR AX,1 
     1288                    {   gen2(cg,0x2B,grex | modregrm(3,AX,DX));        // SUB AX,DX 
     1289                        gen2(cg,0xD1,grex | modregrm(3,7,AX));         // SAR AX,1 
    12251290                        resreg = AX; 
    12261291                    } 
    12271292                    else // OPmod 
    1228                     {   gen2(cg,0x33,modregrm(3,AX,DX));        // XOR AX,DX 
    1229                         genc2(cg,0x81,modregrm(3,4,AX),1);      // AND AX,1 
    1230                         gen2(cg,0x03,modregrm(3,DX,AX));        // ADD DX,AX 
     1293                    {   gen2(cg,0x33,grex | modregrm(3,AX,DX));        // XOR AX,DX 
     1294                        genc2(cg,0x81,grex | modregrm(3,4,AX),1);      // AND AX,1 
     1295                        gen2(cg,0x03,grex | modregrm(3,DX,AX));        // ADD DX,AX 
    12311296                        resreg = DX; 
    12321297                    } 
    12331298                } 
    12341299                else 
    1235                 {   targ_ulong m; 
    1236  
    1237                     m = (1 << pow2) - 1; 
     1300                { 
     1301                    assert(pow2 < 32); 
     1302                    targ_ulong m = (1 << pow2) - 1; 
    12381303                    if (op == OPdivass) 
    1239                     {   genc2(cg,0x81,modregrm(3,4,DX),m);      // AND DX,m 
    1240                         gen2(cg,0x03,modregrm(3,AX,DX));        // ADD AX,DX 
     1304                    {   genc2(cg,0x81,grex | modregrm(3,4,DX),m);      // AND DX,m 
     1305                        gen2(cg,0x03,grex | modregrm(3,AX,DX));        // ADD AX,DX 
    12411306                        // Be careful not to generate this for 8088 
    12421307                        assert(config.target_cpu >= TARGET_80286); 
    1243                         genc2(cg,0xC1,modregrm(3,7,AX),pow2);   // SAR AX,pow2 
     1308                        genc2(cg,0xC1,grex | modregrm(3,7,AX),pow2);   // SAR AX,pow2 
    12441309                        resreg = AX; 
    12451310                    } 
    12461311                    else // OPmodass 
    1247                     {   gen2(cg,0x33,modregrm(3,AX,DX));        // XOR AX,DX 
    1248                         gen2(cg,0x2B,modregrm(3,AX,DX));        // SUB AX,DX 
    1249                         genc2(cg,0x81,modregrm(3,4,AX),m);      // AND AX,m 
    1250                         gen2(cg,0x33,modregrm(3,AX,DX));        // XOR AX,DX 
    1251                         gen2(cg,0x2B,modregrm(3,AX,DX));        // SUB AX,DX 
     1312                    {   gen2(cg,0x33,grex | modregrm(3,AX,DX));        // XOR AX,DX 
     1313                        gen2(cg,0x2B,grex | modregrm(3,AX,DX));        // SUB AX,DX 
     1314                        genc2(cg,0x81,grex | modregrm(3,4,AX),m);      // AND AX,m 
     1315                        gen2(cg,0x33,grex | modregrm(3,AX,DX));        // XOR AX,DX 
     1316                        gen2(cg,0x2B,grex | modregrm(3,AX,DX));        // SUB AX,DX 
    12521317                        resreg = AX; 
    12531318                    } 
    12541319                } 
    12551320            } 
    12561321            else 
    12571322            { 
    12581323                retregs = ALLREGS & ~(mAX|mDX);         // DX gets sign extension 
    12591324                cr = codelem(e2,&retregs,FALSE);        // load rvalue in retregs 
    12601325                reg = findreg(retregs); 
    12611326                cl = getlvalue(&cs,e1,mAX | mDX | retregs);     // get EA 
    12621327                cg = getregs(mAX | mDX);        // destroy these regs 
    12631328                cs.Irm |= modregrm(0,AX,0); 
    12641329                cs.Iop = 0x8B; 
    12651330                c = gen(CNIL,&cs);              // MOV AX,EA 
    12661331                if (uns)                        // if unsigned 
    12671332                    movregconst(c,DX,0,0);      // CLR DX 
    12681333                else                            // else signed 
    1269                     gen1(c,0x99);               // CWD 
     1334                {   gen1(c,0x99);               // CWD 
     1335                    code_orrex(c,rex); 
     1336                } 
    12701337                c = cat(c,getregs(mDX | mAX));  // DX and AX will be destroyed 
    12711338                genregs(c,0xF7,opr,reg);        // OPR reg 
     1339                code_orrex(c,rex); 
    12721340            } 
    12731341        } 
    12741342        cs.Iop = 0x89 ^ byte; 
    12751343        NEWREG(cs.Irm,resreg); 
    12761344        c = gen(c,&cs);                         // MOV EA,resreg 
    12771345        if (e1->Ecount)                         // if we gen a CSE 
    12781346                cssave(e1,mask[resreg],EOP(e1)); 
    12791347        freenode(e1); 
    12801348        c = cat(c,fixresult(e,mask[resreg],pretregs)); 
    12811349        return cat4(cr,cl,cg,c); 
    12821350  } 
    12831351  else if (sz == 2 * REGSIZE) 
    12841352  { 
    12851353        lib = CLIBlmul; 
    12861354        if (op == OPdivass || op == OPmodass) 
    12871355        {       lib = (uns) ? CLIBuldiv : CLIBldiv; 
    12881356                if (op == OPmodass) 
    12891357                        lib++; 
    12901358        } 
    12911359        retregs = mCX | mBX; 
     
    12991367        gen(cl,&cs);                    /* MOV DX,EA+2                  */ 
    13001368        getlvalue_lsw(&cs); 
    13011369        retregs = 0; 
    13021370        if (config.target_cpu >= TARGET_PentiumPro && op == OPmulass) 
    13031371        { 
    13041372            /*  IMUL    ECX,EAX 
    13051373                IMUL    EDX,EBX 
    13061374                ADD     ECX,EDX 
    13071375                MUL     EBX 
    13081376                ADD     EDX,ECX 
    13091377             */ 
    13101378             c = getregs(mAX|mDX|mCX); 
    13111379             c = gen2(c,0x0FAF,modregrm(3,CX,AX)); 
    13121380             gen2(c,0x0FAF,modregrm(3,DX,BX)); 
    13131381             gen2(c,0x03,modregrm(3,CX,DX)); 
    13141382             gen2(c,0xF7,modregrm(3,4,BX)); 
    13151383             gen2(c,0x03,modregrm(3,DX,CX)); 
    13161384             retregs = mDX | mAX; 
    13171385        } 
    13181386        else 
    1319             c = callclib(e,lib,&retregs,idxregm(cs.Irm,cs.Isib)); 
     1387            c = callclib(e,lib,&retregs,idxregm(&cs)); 
    13201388        reg = (op == OPmodass) ? BX : AX; 
    13211389        retregs = mask[reg]; 
    13221390        cs.Iop = 0x89; 
    13231391        NEWREG(cs.Irm,reg); 
    13241392        gen(c,&cs);                     /* MOV EA,lsreg                 */ 
    13251393        reg = (op == OPmodass) ? CX : DX; 
    13261394        retregs |= mask[reg]; 
    13271395        NEWREG(cs.Irm,reg); 
    13281396        getlvalue_msw(&cs); 
    13291397        gen(c,&cs);                     /* MOV EA+2,msreg               */ 
    13301398        if (e1->Ecount)         /* if we gen a CSE              */ 
    13311399                cssave(e1,retregs,EOP(e1)); 
    13321400        freenode(e1); 
    13331401        cg = fixresult(e,retregs,pretregs); 
    13341402        return cat4(cr,cl,c,cg); 
    13351403  } 
    13361404  else 
    13371405  {     assert(0); 
    13381406        /* NOTREACHED */ 
    13391407        return 0; 
     
    13481416code *cdshass(elem *e,regm_t *pretregs) 
    13491417{ elem *e1,*e2; 
    13501418  code *cr,*cl,*cg,*c,cs,*ce; 
    13511419  tym_t tym,tyml,uns; 
    13521420  regm_t retregs; 
    13531421  unsigned shiftcnt,op1,op2,reg,v,oper,byte,conste2; 
    13541422  unsigned loopcnt; 
    13551423  unsigned sz; 
    13561424 
    13571425  e1 = e->E1; 
    13581426  e2 = e->E2; 
    13591427 
    13601428  tyml = tybasic(e1->Ety);              /* type of lvalue               */ 
    13611429  sz = tysize[tyml]; 
    13621430  byte = tybyte(e->Ety) != 0;           /* 1 for byte operations        */ 
    13631431  uns = tyuns(tyml); 
    13641432  tym = tybasic(e->Ety);                /* type of result               */ 
    13651433  oper = e->Eoper; 
    13661434  assert(tysize(e2->Ety) <= REGSIZE); 
    13671435 
     1436    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1437    unsigned grex = rex << 16;          // 64 bit operands 
     1438 
    13681439  // if our lvalue is a cse, make sure we evaluate for result in register 
    13691440  if (e1->Ecount && !(*pretregs & (ALLREGS | mBP)) && !isregvar(e1,&retregs,&reg)) 
    13701441        *pretregs |= ALLREGS; 
    13711442 
    13721443#if SCPP 
    13731444  // Do this until the rest of the compiler does OPshr/OPashr correctly 
    13741445  if (oper == OPshrass) 
    13751446        oper = (uns) ? OPshrass : OPashrass; 
    13761447#endif 
    13771448 
    13781449  // Select opcodes. op2 is used for msw for long shifts. 
    13791450 
    13801451  switch (oper) 
    13811452  {     case OPshlass: 
    13821453            op1 = 4;                    // SHL 
    13831454            op2 = 2;                    // RCL 
    13841455            break; 
    13851456        case OPshrass: 
    13861457            op1 = 5;                    // SHR 
    13871458            op2 = 3;                    // RCR 
     
    14021473  if (cnst(e2)) 
    14031474  { 
    14041475        conste2 = TRUE;                 /* e2 is a constant             */ 
    14051476        shiftcnt = e2->EV.Vint;         /* byte ordering of host        */ 
    14061477        if (config.target_cpu >= TARGET_80286 && 
    14071478            sz <= REGSIZE && 
    14081479            shiftcnt != 1) 
    14091480            v = 0xC1;                   // SHIFT xx,shiftcnt 
    14101481        else if (shiftcnt <= 3) 
    14111482        {   loopcnt = shiftcnt; 
    14121483            v = 0xD1;                   // SHIFT xx,1 
    14131484        } 
    14141485  } 
    14151486  if (v == 0xD3)                        /* if COUNT == CL               */ 
    14161487  {     retregs = mCX; 
    14171488        cr = codelem(e2,&retregs,FALSE); 
    14181489  } 
    14191490  else 
    14201491        freenode(e2); 
    14211492  cl = getlvalue(&cs,e1,mCX);           /* get lvalue, preserve CX      */ 
    1422   cl = cat(cl,modEA(cs.Irm));           /* check for modifying register */ 
     1493  cl = cat(cl,modEA(&cs));              // check for modifying register 
    14231494 
    14241495  if (*pretregs == 0 ||                 /* if don't return result       */ 
    14251496      (*pretregs == mPSW && conste2 && tysize[tym] <= REGSIZE) || 
    14261497      sz > REGSIZE 
    14271498     ) 
    14281499  {     retregs = 0;            // value not returned in a register 
    14291500        cs.Iop = v ^ byte; 
    14301501        c = CNIL; 
    14311502        while (loopcnt--) 
    14321503        { 
    14331504          NEWREG(cs.Irm,op1);           /* make sure op1 is first       */ 
    14341505          if (sz <= REGSIZE) 
    14351506          {   cs.IFL2 = FLconst; 
    14361507              cs.IEV2.Vint = shiftcnt; 
    14371508              c = gen(c,&cs);           /* SHIFT EA,[CL|1]              */ 
    14381509              if (*pretregs & mPSW && !loopcnt && conste2) 
    14391510                code_orflag(c,CFpsw); 
    14401511          } 
    14411512          else /* TYlong */ 
    14421513          {   cs.Iop = 0xD1;            /* plain shift                  */ 
     
    14771548 
    14781549        if (sz == 2 * REGSIZE && *pretregs) 
    14791550        {   retregs = *pretregs & (ALLREGS | mBP); 
    14801551            if (retregs) 
    14811552            {   ce = allocreg(&retregs,&reg,tym); 
    14821553                cs.Iop = 0x8B; 
    14831554 
    14841555                /* be careful not to trash any index regs       */ 
    14851556                /* do MSW first (which can't be an index reg)   */ 
    14861557                getlvalue_msw(&cs); 
    14871558                NEWREG(cs.Irm,reg); 
    14881559                cg = gen(CNIL,&cs); 
    14891560                getlvalue_lsw(&cs); 
    14901561                reg = findreglsw(retregs); 
    14911562                NEWREG(cs.Irm,reg); 
    14921563                gen(cg,&cs); 
    14931564                if (*pretregs & mPSW) 
    14941565                    cg = cat(cg,tstresult(retregs,tyml,TRUE)); 
    14951566            } 
    14961567            else        /* flags only   */ 
    1497             {   retregs = ALLREGS & ~idxregm(cs.Irm,cs.Isib); 
     1568            {   retregs = ALLREGS & ~idxregm(&cs); 
    14981569                ce = allocreg(&retregs,&reg,TYint); 
    14991570                cs.Iop = 0x8B; 
    15001571                NEWREG(cs.Irm,reg); 
    15011572                cg = gen(CNIL,&cs);     /* MOV reg,EA           */ 
    15021573                cs.Iop = 0x0B;          /* OR reg,EA+2          */ 
    15031574                cs.Iflags |= CFpsw; 
    15041575                getlvalue_msw(&cs); 
    15051576                gen(cg,&cs); 
    15061577            } 
    15071578            c = cat3(c,ce,cg); 
    15081579        } 
    15091580        cg = CNIL; 
    15101581  } 
    15111582 
    15121583 
    15131584  else                                  /* else must evaluate in register */ 
    15141585  { 
    15151586        if (sz <= REGSIZE) 
    1516         {   regm_t possregs; 
    1517  
    1518             possregs = ALLREGS & ~mCX & ~idxregm(cs.Irm,cs.Isib); 
     1585        { 
     1586            regm_t possregs = ALLREGS & ~mCX & ~idxregm(&cs); 
    15191587            if (byte) 
    15201588                    possregs &= BYTEREGS; 
    15211589            retregs = *pretregs & possregs; 
    15221590            if (retregs == 0) 
    15231591                    retregs = possregs; 
    15241592            cg = allocreg(&retregs,&reg,tym); 
    15251593            cs.Iop = 0x8B ^ byte; 
    1526             cs.Irm |= modregrm(0,reg,0); 
     1594            code_newreg(&cs, reg); 
    15271595            c = ce = gen(CNIL,&cs);                     /* MOV reg,EA   */ 
    1528             if (I32
     1596            if (!I16
    15291597            { 
    15301598                assert(!byte || (mask[reg] & BYTEREGS)); 
    1531                 ce = genc2(CNIL,v ^ byte,modregrm(3,op1,reg),shiftcnt); 
     1599                ce = genc2(CNIL,v ^ byte,modregrmx(3,op1,reg),shiftcnt); 
     1600                code_orrex(ce, rex); 
    15321601                /* We can do a 32 bit shift on a 16 bit operand if      */ 
    15331602                /* it's a left shift and we're not concerned about      */ 
    15341603                /* the flags. Remember that flags are not set if        */ 
    15351604                /* a shift of 0 occurs.                         */ 
    15361605                if (tysize[tym] == SHORTSIZE && 
    15371606                    (oper == OPshrass || oper == OPashrass || 
    15381607                     (*pretregs & mPSW && conste2))) 
    15391608                     ce->Iflags |= CFopsize;            /* 16 bit operand */ 
    15401609                cat(c,ce); 
    15411610            } 
    15421611            else 
    15431612            { 
    15441613                while (loopcnt--) 
    15451614                {   /* Generate shift instructions.     */ 
    15461615                    genc2(ce,v ^ byte,modregrm(3,op1,reg),shiftcnt); 
    15471616                } 
    15481617            } 
    15491618            if (*pretregs & mPSW && conste2) 
    15501619            {   assert(shiftcnt); 
    15511620                *pretregs &= ~mPSW;     // result is already in flags 
     
    15961665  e1 = e->E1; 
    15971666  e2 = e->E2; 
    15981667  if (*pretregs == 0)                   /* if don't want result         */ 
    15991668  {     cl = codelem(e1,pretregs,FALSE); 
    16001669        *pretregs = 0;                  /* in case e1 changed it        */ 
    16011670        cr = codelem(e2,pretregs,FALSE); 
    16021671        return cat(cl,cr); 
    16031672  } 
    16041673 
    16051674  jop = jmpopcode(e);                   // must be computed before 
    16061675                                        // leaves are free'd 
    16071676  reverse = 0; 
    16081677  cl = cr = CNIL; 
    16091678  op = e->Eoper; 
    16101679  assert(OTrel(op)); 
    16111680  eqorne = (op == OPeqeq) || (op == OPne); 
    16121681 
    16131682  tym = tybasic(e1->Ety); 
    16141683  sz = tysize[tym]; 
    16151684  byte = sz == 1; 
     1685 
     1686    unsigned rex = (I64 && sz == 8) ? REX_W : 0; 
     1687    unsigned grex = rex << 16;          // 64 bit operands 
     1688 
    16161689#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    16171690  if (tyfloating(tym))                  /* if floating operation        */ 
    16181691  { 
    16191692        retregs = mPSW; 
    16201693        c = orth87(e,&retregs); 
    16211694        goto L3; 
    16221695  } 
    16231696#else 
    16241697  if (tyfloating(tym))                  /* if floating operation        */ 
    16251698  { 
    16261699        if (config.inline8087) 
    16271700        {   retregs = mPSW; 
    16281701            c = orth87(e,&retregs); 
    16291702        } 
    16301703        else 
    16311704        {   int clib; 
    16321705 
    16331706            retregs = 0;                /* skip result for now          */ 
    16341707            if (iffalse(e2))            /* second operand is constant 0 */ 
    16351708            {   assert(!eqorne);        /* should be OPbool or OPnot    */ 
     
    16461719                cl = codelem(e1,&retregs,FALSE); 
    16471720                retregs = 0; 
    16481721                c = callclib(e,clib,&retregs,0); 
    16491722                freenode(e2); 
    16501723            } 
    16511724            else 
    16521725            {   clib = CLIBdcmp; 
    16531726                if (rel_exception(op)) 
    16541727                    clib += CLIBdcmpexc - CLIBdcmp; 
    16551728                c = opdouble(e,&retregs,clib); 
    16561729            } 
    16571730        } 
    16581731        goto L3; 
    16591732  } 
    16601733#endif 
    16611734 
    16621735  /* If it's a signed comparison of longs, we have to call a library    */ 
    16631736  /* routine, because we don't know the target of the signed branch     */ 
    16641737  /* (have to set up flags so that jmpopcode() will do it right)        */ 
    16651738  if (!eqorne && 
    1666         (!I32 && tym == TYlong  && tybasic(e2->Ety) == TYlong || 
    1667           I32 && tym == TYllong && tybasic(e2->Ety) == TYllong) 
     1739        (I16 && tym == TYlong  && tybasic(e2->Ety) == TYlong || 
     1740         I32 && tym == TYllong && tybasic(e2->Ety) == TYllong) 
    16681741     ) 
    16691742  {     retregs = mDX | mAX; 
    16701743        cl = codelem(e1,&retregs,FALSE); 
    16711744        retregs = mCX | mBX; 
    16721745        cr = scodelem(e2,&retregs,mDX | mAX,FALSE); 
    16731746        retregs = 0; 
    16741747        c = callclib(e,CLIBlcmp,&retregs,0);    /* gross, but it works  */ 
    16751748        goto L3; 
    16761749  } 
    16771750 
    16781751  /* See if we should swap operands     */ 
    16791752  if (e1->Eoper == OPvar && e2->Eoper == OPvar && evalinregister(e2)) 
    16801753  {     e1 = e->E2; 
    16811754        e2 = e->E1; 
    16821755        reverse = 2; 
    16831756  } 
    16841757 
    16851758  retregs = allregs; 
    16861759  if (byte) 
    16871760        retregs = BYTEREGS; 
    16881761 
    16891762  c = CNIL; 
    16901763  ce = CNIL; 
    1691   cs.Iflags = (I32 && sz == SHORTSIZE) ? CFopsize : 0; 
    1692   cs.Irex = 0
     1764  cs.Iflags = (!I16 && sz == SHORTSIZE) ? CFopsize : 0; 
     1765  cs.Irex = rex
    16931766  if (sz > REGSIZE) 
    16941767        ce = gennop(ce); 
    16951768 
    16961769  switch (e2->Eoper) 
    16971770  { 
    16981771      default: 
    16991772      L2: 
    17001773        cl = scodelem(e1,&retregs,0,TRUE);      /* compute left leaf    */ 
    17011774      L1: 
    17021775        rretregs = allregs & ~retregs; 
    17031776        if (byte) 
    17041777                rretregs &= BYTEREGS; 
    17051778        cr = scodelem(e2,&rretregs,retregs,TRUE);       /* get right leaf */ 
    17061779        if (sz <= REGSIZE)                              /* CMP reg,rreg  */ 
    17071780        {   reg = findreg(retregs);             /* get reg that e1 is in */ 
    17081781            rreg = findreg(rretregs); 
    17091782            c = genregs(CNIL,0x3B ^ byte ^ reverse,reg,rreg); 
    1710             if (I32 && sz == SHORTSIZE) 
     1783            code_orrex(c, rex); 
     1784            if (!I16 && sz == SHORTSIZE) 
    17111785                c->Iflags |= CFopsize;          /* compare only 16 bits */ 
    17121786        } 
    17131787        else 
    17141788        {   assert(sz <= 2 * REGSIZE); 
    17151789 
    17161790            /* Compare MSW, if they're equal then compare the LSW       */ 
    17171791            reg = findregmsw(retregs); 
    17181792            rreg = findregmsw(rretregs); 
    17191793            c = genregs(CNIL,0x3B ^ reverse,reg,rreg);  /* CMP reg,rreg */ 
    1720             if (I32 && sz == 6) 
     1794            if (!I16 && sz == 6) 
    17211795                c->Iflags |= CFopsize;          /* seg is only 16 bits  */ 
    17221796            genjmp(c,JNE,FLcode,(block *) ce);          /* JNE nop      */ 
    17231797 
    17241798            reg = findreglsw(retregs); 
    17251799            rreg = findreglsw(rretregs); 
    17261800            genregs(c,0x3B ^ reverse,reg,rreg);         /* CMP reg,rreg */ 
    17271801        } 
    17281802        break; 
    17291803      case OPrelconst: 
    17301804        fl = el_fl(e2); 
    17311805        switch (fl) 
    17321806        {   case FLfunc: 
    17331807                fl = FLextern;          // so it won't be self-relative 
    17341808                break; 
    17351809            case FLdata: 
    17361810            case FLudata: 
    17371811            case FLextern: 
    17381812                if (sz > REGSIZE)       // compare against DS, not DGROUP 
    17391813                    goto L2; 
    17401814                break; 
     
    17471821        cs.IEVsym2 = e2->EV.sp.Vsym; 
    17481822        offset2 = e2->EV.sp.Voffset; 
    17491823        if (sz > REGSIZE) 
    17501824        {   cs.Iflags |= CFseg; 
    17511825            cs.IEVoffset2 = 0; 
    17521826        } 
    17531827        else 
    17541828        {   cs.Iflags |= CFoff; 
    17551829            cs.IEVoffset2 = offset2; 
    17561830        } 
    17571831        goto L4; 
    17581832 
    17591833      case OPconst: 
    17601834        // If compare against 0 
    17611835        if (sz <= REGSIZE && *pretregs == mPSW && !boolres(e2) && 
    17621836            isregvar(e1,&retregs,&reg) 
    17631837           ) 
    17641838        {   // Just do a TEST instruction 
    17651839            c = genregs(NULL,0x85 ^ byte,reg,reg);      // TEST reg,reg 
    17661840            c->Iflags |= (cs.Iflags & CFopsize) | CFpsw; 
     1841            code_orrex(c, rex); 
    17671842            retregs = mPSW; 
    17681843            break; 
    17691844        } 
    17701845 
    17711846        if (!tyuns(tym) && !tyuns(e2->Ety) && 
    1772             !boolres(e2) && !(*pretregs & mPSW) && sz == REGSIZE && 
    1773             (I32 || op == OPlt || op == OPge)) 
     1847            !boolres(e2) && !(*pretregs & mPSW) && 
     1848            (sz == REGSIZE || (I64 && sz == 4)) && 
     1849            (!I16 || op == OPlt || op == OPge)) 
    17741850        {   unsigned regi; 
    17751851 
    17761852            assert(*pretregs & (allregs)); 
    17771853            cl = codelem(e1,pretregs,FALSE); 
    17781854            reg = findreg(*pretregs); 
    17791855            c = getregs(mask[reg]); 
    17801856            switch (op) 
    17811857            {   case OPle: 
    1782                     c = genc2(c,0x81,modregrm(3,0,reg),(unsigned)-1);   /* ADD reg,-1   */ 
    1783                     genc2(c,0x81,modregrm(3,2,reg),0);          /* ADC reg,0    */ 
     1858                    c = genc2(c,0x81,grex | modregrmx(3,0,reg & 7),(unsigned)-1);   // ADD reg,-1 
     1859                    genc2(c,0x81,grex | modregrmx(3,2,reg & 7),0);          // ADC reg,0 
    17841860                    goto oplt; 
    17851861                case OPgt: 
    1786                     c = gen2(c,0xF7,modregrm(3,3,reg));         // NEG reg 
     1862                    c = gen2(c,0xF7,grex | modregrmx(3,3,reg & 7));         // NEG reg 
    17871863#if TARGET_WINDOS 
    17881864                    // What does the Windows platform do? 
    17891865                    //  lower INT_MIN by 1?   See test exe9.c 
    17901866                    // BUG: fix later 
    1791                     genc2(c,0x81,modregrm(3,3,reg),0);  // SBB reg,0 
     1867                    genc2(c,0x81,grex | modregrmx(3,3,reg & 7),0);  // SBB reg,0 
    17921868#endif 
    17931869                    goto oplt; 
    17941870                case OPlt: 
    17951871                oplt: 
    1796                     if (I32
    1797                         c = genc2(c,0xC1,modregrm(3,5,reg),31); /* SHR reg,31   */ 
     1872                    if (!I16
     1873                        c = genc2(c,0xC1,grex | modregrmx(3,5,reg & 7),sz * 8 - 1); // SHR reg,31 
    17981874                    else 
    17991875                    {   /* 8088-286 do not have a barrel shifter, so use this 
    18001876                           faster sequence 
    18011877                         */ 
    18021878                        c = genregs(c,0xD1,0,reg);              /* ROL reg,1    */ 
    18031879                        if (reghasvalue(allregs,1,&regi)) 
    18041880                            c = genregs(c,0x23,reg,regi);       /* AND reg,regi */ 
    18051881                        else 
    18061882                            c = genc2(c,0x81,modregrm(3,4,reg),1); /* AND reg,1 */ 
    18071883                    } 
    18081884                    break; 
    18091885                case OPge: 
    18101886                    c = genregs(c,0xD1,4,reg);          /* SHL reg,1    */ 
     1887                    code_orrex(c,rex); 
    18111888                    genregs(c,0x19,reg,reg);            /* SBB reg,reg  */ 
    1812                     gen1(c,0x40 + reg);                 /* INC reg      */ 
     1889                    code_orrex(c,rex); 
     1890                    if (I64) 
     1891                    { 
     1892                        c = gen2(c,0xFF,modregrmx(3,0,reg));    // INC reg 
     1893                        code_orrex(c, rex); 
     1894                    } 
     1895                    else 
     1896                        c = gen1(c,0x40 + reg);                 // INC reg 
    18131897                    break; 
    18141898                default: 
    18151899                    assert(0); 
    18161900            } 
    18171901            freenode(e2); 
    18181902            goto ret; 
    18191903        } 
    18201904 
    18211905        if (sz > REGSIZE) 
    18221906            cs.IEV2.Vint = MSREG(e2->EV.Vllong); 
    18231907        else 
    18241908            cs.IEV2.Vint = e2->EV.Vint; 
    18251909        cs.IFL2 = FLconst; 
    18261910      L4: 
    18271911        cs.Iop = 0x81 ^ byte; 
    18281912 
    18291913        /* if ((e1 is data or a '*' reference) and it's not a 
    18301914         * common subexpression 
    18311915         */ 
    18321916 
    18331917        if ((e1->Eoper == OPvar && datafl[el_fl(e1)] || 
    18341918             e1->Eoper == OPind) && 
    18351919            !evalinregister(e1)) 
    18361920        {       cl = getlvalue(&cs,e1,RMload); 
    18371921                freenode(e1); 
    18381922                if (evalinregister(e2)) 
    18391923                { 
    1840                     retregs = idxregm(cs.Irm,cs.Isib); 
     1925                    retregs = idxregm(&cs); 
    18411926                    if ((cs.Iflags & CFSEG) == CFes) 
    18421927                            retregs |= mES;             /* take no chances */ 
    18431928                    rretregs = allregs & ~retregs; 
    18441929                    if (byte) 
    18451930                            rretregs &= BYTEREGS; 
    18461931                    cr = scodelem(e2,&rretregs,retregs,TRUE); 
    18471932                    cs.Iop = 0x39 ^ byte ^ reverse; 
    18481933                    if (sz > REGSIZE) 
    18491934                    { 
    18501935                        rreg = findregmsw(rretregs); 
    18511936                        cs.Irm |= modregrm(0,rreg,0); 
    18521937                        getlvalue_msw(&cs); 
    18531938                        c = gen(CNIL,&cs);              /* CMP EA+2,rreg */ 
    18541939                        if (I32 && sz == 6) 
    18551940                            c->Iflags |= CFopsize;      /* seg is only 16 bits  */ 
    18561941                        genjmp(c,JNE,FLcode,(block *) ce); /* JNE nop   */ 
    18571942                        rreg = findreglsw(rretregs); 
    18581943                        NEWREG(cs.Irm,rreg); 
    18591944                        getlvalue_lsw(&cs); 
    18601945                    } 
    18611946                    else 
    18621947                    { 
    18631948                        rreg = findreg(rretregs); 
    1864                         cs.Irm |= modregrm(0,rreg,0); 
     1949                        code_newreg(&cs, rreg); 
    18651950                    } 
    18661951                } 
    18671952                else 
    18681953                { 
    18691954                    cs.Irm |= modregrm(0,7,0); 
    18701955                    if (sz > REGSIZE) 
    18711956                    { 
    18721957#if TARGET_FLAT 
    18731958                        if (sz == 6) 
    18741959                            assert(0); 
    18751960#endif 
    18761961                        if (e2->Eoper == OPrelconst) 
    18771962                        {   cs.Iflags = (cs.Iflags & ~(CFoff | CFseg)) | CFseg; 
    18781963                            cs.IEVoffset2 = 0; 
    18791964                        } 
    18801965                        getlvalue_msw(&cs); 
    18811966                        c = gen(CNIL,&cs);              /* CMP EA+2,const */ 
    1882                         if (I32 && sz == 6) 
     1967                        if (!I16 && sz == 6) 
    18831968                            c->Iflags |= CFopsize;      /* seg is only 16 bits  */ 
    18841969                        genjmp(c,JNE,FLcode,(block *) ce); /* JNE nop   */ 
    18851970                        if (e2->Eoper == OPconst) 
    18861971                            cs.IEV2.Vint = e2->EV.Vllong; 
    18871972                        else 
    18881973                        {   /* Turn off CFseg, on CFoff */ 
    18891974                            cs.Iflags ^= CFseg | CFoff; 
    18901975                            cs.IEVoffset2 = offset2; 
    18911976                        } 
    18921977                        getlvalue_lsw(&cs); 
    18931978                    } 
    18941979                    freenode(e2); 
    18951980                } 
    18961981                c = gen(c,&cs); 
    18971982                break; 
    18981983        } 
    18991984 
    19001985        if (evalinregister(e2) && !OTassign(e1->Eoper) && 
    19011986            !isregvar(e1,NULL,NULL)) 
    19021987        {   regm_t m; 
     
    19091994        } 
    19101995        if ((e1->Eoper == OPstrcmp || (OTassign(e1->Eoper) && sz <= REGSIZE)) && 
    19111996            !boolres(e2) && !evalinregister(e1)) 
    19121997        { 
    19131998            retregs = mPSW; 
    19141999            cl = scodelem(e1,&retregs,0,FALSE); 
    19152000            freenode(e2); 
    19162001            break; 
    19172002        } 
    19182003        if (sz <= REGSIZE && !boolres(e2) && e1->Eoper == OPadd && *pretregs == mPSW) 
    19192004        { 
    19202005            retregs |= mPSW; 
    19212006            cl = scodelem(e1,&retregs,0,FALSE); 
    19222007            freenode(e2); 
    19232008            break; 
    19242009        } 
    19252010        cl = scodelem(e1,&retregs,0,TRUE);      /* compute left leaf    */ 
    19262011        if (sz == 1) 
    19272012        { 
    19282013            reg = findreg(retregs & allregs);   // get reg that e1 is in 
    1929             cs.Irm = modregrm(3,7,reg); 
     2014            cs.Irm = modregrm(3,7,reg & 7); 
     2015            if (reg & 8) 
     2016                cs.Irex |= REX_B; 
    19302017            if (e1->Eoper == OPvar && e1->EV.sp.Voffset == 1 && e1->EV.sp.Vsym->Sfl == FLreg) 
     2018            {   assert(reg < 4); 
    19312019                cs.Irm |= 4;                    // use upper register half 
     2020            } 
    19322021        } 
    19332022        else if (sz <= REGSIZE) 
    19342023        {                                       /* CMP reg,const        */ 
    19352024            reg = findreg(retregs & allregs);   // get reg that e1 is in 
    19362025            rretregs = allregs & ~retregs; 
    19372026            if (cs.IFL2 == FLconst && reghasvalue(rretregs,cs.IEV2.Vint,&rreg)) 
    1938             {   code *cc; 
    1939  
    1940                 cc = genregs(CNIL,0x3B,reg,rreg); 
    1941                 if (I32
     2027            { 
     2028                code *cc = genregs(CNIL,0x3B,reg,rreg); 
     2029                code_orrex(cc, rex); 
     2030                if (!I16
    19422031                    cc->Iflags |= cs.Iflags & CFopsize; 
    19432032                c = cat(c,cc); 
    19442033                freenode(e2); 
    19452034                break; 
    19462035            } 
    1947             cs.Irm = modregrm(3,7,reg); 
     2036            cs.Irm = modregrm(3,7,reg & 7); 
     2037            if (reg & 8) 
     2038                cs.Irex |= REX_B; 
    19482039        } 
    19492040        else if (sz <= 2 * REGSIZE) 
    19502041        { 
    19512042            reg = findregmsw(retregs);          // get reg that e1 is in 
    19522043            cs.Irm = modregrm(3,7,reg); 
    19532044            c = gen(CNIL,&cs);                  /* CMP reg,MSW          */ 
    19542045            if (I32 && sz == 6) 
    19552046                c->Iflags |= CFopsize;          /* seg is only 16 bits  */ 
    19562047            genjmp(c,JNE,FLcode,(block *) ce);  /* JNE ce               */ 
    19572048 
    19582049            reg = findreglsw(retregs); 
    19592050            cs.Irm = modregrm(3,7,reg); 
    19602051            if (e2->Eoper == OPconst) 
    19612052                cs.IEV2.Vint = e2->EV.Vlong; 
    19622053            else 
    19632054            {   /* Turn off CFseg, on CFoff     */ 
    19642055                cs.Iflags ^= CFseg | CFoff; 
    19652056                cs.IEVoffset2 = offset2; 
    19662057            } 
    19672058        } 
     
    19752066        if (e2->Ecount) 
    19762067            goto L2; 
    19772068        goto L5; 
    19782069 
    19792070      case OPvar: 
    19802071        if ((e1->Eoper == OPvar && 
    19812072             isregvar(e2,&rretregs,&reg) && 
    19822073             sz <= REGSIZE 
    19832074            ) || 
    19842075            (e1->Eoper == OPind && 
    19852076             isregvar(e2,&rretregs,&reg) && 
    19862077             !evalinregister(e1) && 
    19872078             sz <= REGSIZE 
    19882079            ) 
    19892080           ) 
    19902081        { 
    19912082            // CMP EA,e2 
    19922083            cl = getlvalue(&cs,e1,RMload); 
    19932084            freenode(e1); 
    19942085            cs.Iop = 0x39 ^ byte ^ reverse; 
    1995             cs.Irm |= modregrm(0,reg,0); 
     2086            code_newreg(&cs,reg); 
    19962087            c = gen(c,&cs); 
    19972088            freenode(e2); 
    19982089            break; 
    19992090        } 
    20002091      L5: 
    20012092        cl = scodelem(e1,&retregs,0,TRUE);      /* compute left leaf    */ 
    20022093        if (sz <= REGSIZE)                      /* CMP reg,EA           */ 
    2003         {   unsigned opsize; 
    2004  
     2094        { 
    20052095            reg = findreg(retregs & allregs);   // get reg that e1 is in 
    2006             opsize = cs.Iflags & CFopsize; 
     2096            unsigned opsize = cs.Iflags & CFopsize; 
    20072097            c = cat(c,loadea(e2,&cs,0x3B ^ byte ^ reverse,reg,0,RMload | retregs,0)); 
    20082098            code_orflag(c,opsize); 
    20092099        } 
    20102100        else if (sz <= 2 * REGSIZE) 
    20112101        { 
    20122102            reg = findregmsw(retregs);   /* get reg that e1 is in */ 
    20132103            // CMP reg,EA 
    20142104            c = loadea(e2,&cs,0x3B ^ reverse,reg,REGSIZE,RMload | retregs,0); 
    20152105            if (I32 && sz == 6) 
    20162106                c->Iflags |= CFopsize;          /* seg is only 16 bits  */ 
    20172107            genjmp(c,JNE,FLcode,(block *) ce);          /* JNE ce       */ 
    20182108            reg = findreglsw(retregs); 
    20192109            if (e2->Eoper == OPind) 
    20202110            { 
    20212111                NEWREG(cs.Irm,reg); 
    20222112                getlvalue_lsw(&cs); 
    20232113                c = gen(c,&cs); 
    20242114            } 
    20252115            else 
    20262116                c = cat(c,loadea(e2,&cs,0x3B ^ reverse,reg,0,RMload | retregs,0)); 
    20272117        } 
    20282118        else 
    20292119            assert(0); 
    20302120        freenode(e2); 
    20312121        break; 
    20322122  } 
    20332123  c = cat(c,ce); 
    20342124 
    20352125L3: 
    2036   if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) /* if return result in register*/ 
    2037   {     code *nop; 
    2038         regm_t save; 
    2039  
    2040         nop = CNIL; 
    2041         save = regcon.immed.mval; 
     2126  if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register 
     2127  {     code *nop = CNIL; 
     2128        regm_t save = regcon.immed.mval; 
    20422129        cg = allocreg(&retregs,&reg,TYint); 
    20432130        regcon.immed.mval = save; 
    20442131        if ((*pretregs & mPSW) == 0 && 
    20452132            (jop == JC || jop == JNC)) 
    20462133        { 
    20472134            cg = cat(cg,getregs(retregs)); 
    20482135            cg = genregs(cg,0x19,reg,reg);              /* SBB reg,reg  */ 
     2136            if (rex) 
     2137                code_orrex(cg, rex); 
    20492138            if (flag) 
    20502139                ;                                       // cdcond() will handle it 
    20512140            else if (jop == JNC) 
    2052                 gen1(cg,0x40 + reg);                    /* INC reg      */ 
     2141            { 
     2142                if (I64) 
     2143                { 
     2144                    cg = gen2(cg,0xFF,modregrmx(3,0,reg));      // INC reg 
     2145                    code_orrex(cg, rex); 
     2146                } 
     2147                else 
     2148                    gen1(cg,0x40 + reg);                 // INC reg 
     2149            } 
    20532150            else 
    2054                 gen2(cg,0xF7,modregrm(3,3,reg));        /* NEG reg      */ 
     2151            {   gen2(cg,0xF7,modregrmx(3,3,reg));        /* NEG reg      */ 
     2152                code_orrex(cg, rex); 
     2153            } 
     2154        } 
     2155        else if (I64 && sz == 8) 
     2156        { 
     2157            assert(!flag); 
     2158            cg = movregconst(cg,reg,1,64|8);               // MOV reg,1 
     2159            nop = gennop(nop); 
     2160            cg = genjmp(cg,jop,FLcode,(block *) nop);   // Jtrue nop 
     2161                                                        // MOV reg,0 
     2162            movregconst(cg,reg,0,(*pretregs & mPSW) ? 64|8 : 64); 
     2163            regcon.immed.mval &= ~mask[reg]; 
    20552164        } 
    20562165        else 
    20572166        { 
    20582167            assert(!flag); 
    20592168            cg = movregconst(cg,reg,1,8);               // MOV reg,1 
    20602169            nop = gennop(nop); 
    20612170            cg = genjmp(cg,jop,FLcode,(block *) nop);   // Jtrue nop 
    20622171                                                        // MOV reg,0 
    20632172            movregconst(cg,reg,0,(*pretregs & mPSW) ? 8 : 0); 
    20642173            regcon.immed.mval &= ~mask[reg]; 
    20652174        } 
    20662175        *pretregs = retregs; 
    20672176        c = cat3(c,cg,nop); 
    20682177  } 
    20692178ret: 
    20702179  return cat3(cl,cr,c); 
    20712180} 
    20722181 
    20732182 
    20742183/********************************** 
     
    21202229        reg = findreglsw(retregs); 
    21212230        rreg = findreglsw(rretregs); 
    21222231        clsw = genregs(CNIL,0x3B,reg,rreg);             /* CMP reg,rreg */ 
    21232232        break; 
    21242233      case OPconst: 
    21252234        cs.IEV2.Vint = MSREG(e2->EV.Vllong);            // MSW first 
    21262235        cs.IFL2 = FLconst; 
    21272236        cs.Iop = 0x81; 
    21282237 
    21292238        /* if ((e1 is data or a '*' reference) and it's not a 
    21302239         * common subexpression 
    21312240         */ 
    21322241 
    21332242        if ((e1->Eoper == OPvar && datafl[el_fl(e1)] || 
    21342243             e1->Eoper == OPind) && 
    21352244            !evalinregister(e1)) 
    21362245        {       cl = getlvalue(&cs,e1,0); 
    21372246                freenode(e1); 
    21382247                if (evalinregister(e2)) 
    21392248                { 
    2140                         retregs = idxregm(cs.Irm,cs.Isib); 
     2249                        retregs = idxregm(&cs); 
    21412250                        if ((cs.Iflags & CFSEG) == CFes) 
    21422251                                retregs |= mES;         /* take no chances */ 
    21432252                        rretregs = ALLREGS & ~retregs; 
    21442253                        cr = scodelem(e2,&rretregs,retregs,TRUE); 
    21452254                        rreg = findregmsw(rretregs); 
    21462255                        cs.Iop = 0x39; 
    21472256                        cs.Irm |= modregrm(0,rreg,0); 
    21482257                        getlvalue_msw(&cs); 
    21492258                        cmsw = gen(CNIL,&cs);   /* CMP EA+2,rreg        */ 
    21502259                        rreg = findreglsw(rretregs); 
    21512260                        NEWREG(cs.Irm,rreg); 
    21522261                } 
    21532262                else 
    21542263                {       cs.Irm |= modregrm(0,7,0); 
    21552264                        getlvalue_msw(&cs); 
    21562265                        cmsw = gen(CNIL,&cs);   /* CMP EA+2,const       */ 
    21572266                        cs.IEV2.Vint = e2->EV.Vlong; 
    21582267                        freenode(e2); 
    21592268                } 
    21602269                getlvalue_lsw(&cs); 
     
    22802389                    retregs = regmask(e->E1->Ety, e->E1->E1->Ety); 
    22812390                    if (retregs & (mST01 | mST0))       // if return in ST0 
    22822391                    { 
    22832392                        c1 = codelem(e->E1,pretregs,FALSE); 
    22842393                        if (*pretregs & mST0) 
    22852394                            note87(e, 0, 0); 
    22862395                        return c1; 
    22872396                    } 
    22882397                    else 
    22892398                        break; 
    22902399                } 
    22912400                if (tycomplex(e->E1->Ety)) 
    22922401                    goto Lcomplex; 
    22932402                /* FALL-THROUGH */ 
    22942403            case OPs64_d: 
    22952404            case OPs32_d: 
    22962405            case OPs16_d: 
    22972406            case OPu16_d: 
    22982407                return load87(e,0,pretregs,NULL,-1); 
    22992408            case OPu32_d: 
    2300                 if (I32) 
    2301                 {   unsigned reg; 
    2302  
    2303                     retregs = ALLREGS; 
     2409                if (!I16) 
     2410                { 
     2411                    unsigned retregs = ALLREGS; 
    23042412                    c1 = codelem(e->E1, &retregs, FALSE); 
    2305                     reg = findreg(retregs); 
     2413                    unsigned reg = findreg(retregs); 
    23062414                    c1 = genfltreg(c1, 0x89, reg, 0); 
    23072415                    regwithvalue(c1,ALLREGS,0,&reg,0); 
    23082416                    genfltreg(c1, 0x89, reg, REGSIZE); 
    23092417 
    23102418                    cat(c1, push87()); 
    23112419                    genfltreg(c1,0xDF,5,0);     // FILD m64int 
    23122420 
    23132421                    retregs = mST0 | (*pretregs & mPSW); 
    23142422                    c2 = fixresult87(e, retregs, pretregs); 
    23152423                    return cat(c1, c2); 
    23162424                } 
    23172425                break; 
    23182426            case OPd_s16: 
    23192427            case OPd_s32: 
    23202428            case OPd_u16: 
    23212429            case OPd_s64: 
    23222430                return cnvt87(e,pretregs); 
    23232431            case OPd_u32:               // use subroutine, not 8087 
    23242432#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    23252433                retregs = mST0; 
     
    23462454                c2 = callclib(e,CLIBld_u64,pretregs,0); 
    23472455                return cat(c1,c2); 
    23482456        } 
    23492457  } 
    23502458  retregs = regmask(e->E1->Ety, TYnfunc); 
    23512459L1: 
    23522460  c1 = codelem(e->E1,&retregs,FALSE); 
    23532461  for (i = 0; 1; i++) 
    23542462  {     assert(i < arraysize(clib)); 
    23552463        if (clib[i][0] == e->Eoper) 
    23562464        {   c2 = callclib(e,clib[i][1],pretregs,0); 
    23572465            break; 
    23582466        } 
    23592467  } 
    23602468  return cat(c1,c2); 
    23612469} 
    23622470 
    23632471 
    23642472/*************************** 
    23652473 * Convert short to long. 
    2366  * For OPshtlng, OPu16_32, OPptrlptr, OPulngllng, OPlngllng 
     2474 * For OPs16_32, OPu16_32, OPptrlptr, OPu32_64, OPs32_64 
    23672475 */ 
    23682476 
    23692477code *cdshtlng(elem *e,regm_t *pretregs) 
    23702478{ code *c,*ce,*c1,*c2,*c3,*c4; 
    23712479  unsigned reg; 
    23722480  unsigned char op; 
    23732481  regm_t retregs; 
    23742482  int e1comsub; 
    23752483 
    23762484  e1comsub = e->E1->Ecount; 
    23772485  if ((*pretregs & (ALLREGS | mBP)) == 0)       // if don't need result in regs 
    23782486    c = codelem(e->E1,pretregs,FALSE);  /* then conversion isn't necessary */ 
    23792487 
    23802488  else if ((op = e->Eoper) == OPptrlptr || 
    2381            (!I32 && op == OPu16_32) || 
    2382            ( I32 && op == OPulngllng
     2489           (I16 && op == OPu16_32) || 
     2490           (I32 && op == OPu32_64
    23832491          ) 
    23842492  { 
    23852493        regm_t regm; 
    23862494        tym_t tym1; 
    23872495 
    23882496        retregs = *pretregs & mLSW; 
    23892497        assert(retregs); 
    23902498        tym1 = tybasic(e->E1->Ety); 
    23912499        c = codelem(e->E1,&retregs,FALSE); 
    23922500 
    23932501        regm = *pretregs & (mMSW & ALLREGS); 
    23942502        if (regm == 0)                  /* *pretregs could be mES       */ 
    23952503            regm = mMSW & ALLREGS; 
    23962504        ce = allocreg(&regm,&reg,TYint); 
    23972505        if (e1comsub) 
    23982506            ce = cat(ce,getregs(retregs)); 
    23992507        if (op == OPptrlptr) 
    24002508        {   int segreg; 
    24012509 
    24022510            /* BUG: what about pointers to functions?   */ 
    24032511            switch (tym1) 
    24042512            { 
    24052513                case TYnptr:    segreg = SEG_DS;        break; 
    24062514                case TYcptr:    segreg = SEG_CS;        break; 
    24072515                case TYsptr:    segreg = SEG_SS;        break; 
    24082516                default:        assert(0); 
    24092517            } 
    24102518            ce = gen2(ce,0x8C,modregrm(3,segreg,reg));  /* MOV reg,segreg */ 
    24112519        } 
    24122520        else 
    24132521            ce = movregconst(ce,reg,0,0);               /* 0 extend     */ 
    24142522 
    24152523        c = cat3(c,ce,fixresult(e,retregs | regm,pretregs)); 
    24162524  } 
    2417   else if (I32 && (op == OPshtlng || op == OPu16_32)) 
     2525  else if (!I16 && (op == OPs16_32 || op == OPu16_32)) 
    24182526  { 
    2419     /* OPshtlng || OPu16_32 */ 
    2420     elem *e1; 
    24212527    elem *e11; 
    24222528 
    2423     e1 = e->E1; 
     2529    elem *e1 = e->E1; 
    24242530 
    24252531    if (e1->Eoper == OPu8_16 && !e1->Ecount && 
    24262532        ((e11 = e1->E1)->Eoper == OPvar || (e11->Eoper == OPind && !e11->Ecount)) 
    24272533       ) 
    24282534    {   code cs; 
    24292535 
    24302536        retregs = *pretregs & BYTEREGS; 
    24312537        if (!retregs) 
    24322538            retregs = BYTEREGS; 
    24332539        c1 = allocreg(&retregs,&reg,TYint); 
    24342540        c2 = movregconst(NULL,reg,0,0);                         //  XOR reg,reg 
    24352541        c3 = loadea(e11,&cs,0x8A,reg,0,retregs,retregs);        //  MOV regL,EA 
    24362542        freenode(e11); 
    24372543        freenode(e1); 
    24382544    } 
    24392545    else if (e1->Eoper == OPvar || 
    24402546        (e1->Eoper == OPind && !e1->Ecount)) 
    24412547    {   code cs; 
    24422548        unsigned opcode; 
    24432549 
     
    24532559    else 
    24542560    { 
    24552561    L2: 
    24562562        retregs = *pretregs; 
    24572563        *pretregs &= ~mPSW;             /* flags are already set        */ 
    24582564        c1 = codelem(e1,&retregs,FALSE); 
    24592565        c2 = getregs(retregs); 
    24602566        if (op == OPu16_32 && c1) 
    24612567        {   code *cx; 
    24622568 
    24632569            cx = code_last(c1); 
    24642570            if (cx->Iop == 0x81 && (cx->Irm & modregrm(3,7,0)) == modregrm(3,4,0)) 
    24652571            { 
    24662572                // Convert AND of a word to AND of a dword, zeroing upper word 
    24672573                retregs = mask[cx->Irm & 7]; 
    24682574                cx->Iflags &= ~CFopsize; 
    24692575                cx->IEV2.Vint &= 0xFFFF; 
    24702576                goto L1; 
    24712577            } 
    24722578        } 
    2473         if (op == OPshtlng && retregs == mAX) 
     2579        if (op == OPs16_32 && retregs == mAX) 
    24742580            c2 = gen1(c2,0x98);         /* CWDE                         */ 
    24752581        else 
    24762582        { 
    24772583            reg = findreg(retregs); 
    24782584            if (config.flags4 & CFG4speed && op == OPu16_32) 
    24792585            {   // AND reg,0xFFFF 
    24802586                c3 = genc2(NULL,0x81,modregrm(3,4,reg),0xFFFFu); 
    24812587            } 
    24822588            else 
    24832589            { 
    24842590                c3 = genregs(CNIL,0x0F,reg,reg); 
    24852591                c3->Iop2 = (op == OPu16_32) ? 0xB7 : 0xBF; /* MOVZX/MOVSX reg,reg */ 
    24862592            } 
    24872593            c2 = cat(c2,c3); 
    24882594        } 
    24892595     L1: 
    24902596        c3 = e1comsub ? getregs(retregs) : CNIL; 
    24912597    } 
    24922598    c4 = fixresult(e,retregs,pretregs); 
    24932599    c = cat4(c1,c2,c3,c4); 
    24942600  } 
    24952601  else if (*pretregs & mPSW || config.target_cpu < TARGET_80286) 
    24962602  { 
    2497     // OPshtlng, OPlngllng 
     2603    // OPs16_32, OPs32_64 
    24982604    // CWD doesn't affect flags, so we can depend on the integer 
    24992605    // math to provide the flags. 
    25002606    retregs = mAX | mPSW;               // want integer result in AX 
    25012607    *pretregs &= ~mPSW;                 // flags are already set 
    25022608    c1 = codelem(e->E1,&retregs,FALSE); 
    25032609    c2 = getregs(mDX);                  // sign extend into DX 
    25042610    c2 = gen1(c2,0x99);                 // CWD/CDQ 
    25052611    c3 = e1comsub ? getregs(retregs) : CNIL; 
    25062612    c4 = fixresult(e,mDX | retregs,pretregs); 
    25072613    c = cat4(c1,c2,c3,c4); 
    25082614  } 
    25092615  else 
    25102616  { 
    2511     // OPshtlng, OPlngllng 
     2617    // OPs16_32, OPs32_64 
    25122618    unsigned msreg,lsreg; 
    25132619 
    25142620    retregs = *pretregs & mLSW; 
    25152621    assert(retregs); 
    25162622    c1 = codelem(e->E1,&retregs,FALSE); 
    25172623    retregs |= *pretregs & mMSW; 
    25182624    c2 = allocreg(&retregs,&reg,e->Ety); 
    25192625    msreg = findregmsw(retregs); 
    25202626    lsreg = findreglsw(retregs); 
    25212627    c3 = genmovreg(NULL,msreg,lsreg);                           // MOV msreg,lsreg 
    25222628    assert(config.target_cpu >= TARGET_80286);                  // 8088 can't handle SAR reg,imm8 
    25232629    c3 = genc2(c3,0xC1,modregrm(3,7,msreg),REGSIZE * 8 - 1);    // SAR msreg,31 
    25242630    c4 = fixresult(e,retregs,pretregs); 
    25252631    c = cat4(c1,c2,c3,c4); 
    25262632  } 
    25272633  return c; 
    25282634} 
    25292635 
    25302636 
    25312637/*************************** 
     
    25332639 * For OPu8int and OPs8int. 
    25342640 */ 
    25352641 
    25362642code *cdbyteint(elem *e,regm_t *pretregs) 
    25372643{   code *c,*ce,*c0,*c1,*c2,*c3,*c4; 
    25382644    regm_t retregs; 
    25392645    unsigned reg; 
    25402646    char op; 
    25412647    char size; 
    25422648    elem *e1; 
    25432649 
    25442650 
    25452651    if ((*pretregs & (ALLREGS | mBP)) == 0)     // if don't need result in regs 
    25462652        return codelem(e->E1,pretregs,FALSE); /* then conversion isn't necessary */ 
    25472653 
    25482654    op = e->Eoper; 
    25492655    e1 = e->E1; 
    25502656    c0 = NULL; 
    25512657    if (e1->Eoper == OPcomma) 
    25522658        c0 = docommas(&e1); 
    2553     if (I32
     2659    if (!I16
    25542660    { 
    25552661        if (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount)) 
    25562662        {   code cs; 
    25572663            unsigned opcode; 
    25582664 
    25592665            retregs = *pretregs; 
    25602666            c1 = allocreg(&retregs,&reg,TYint); 
    25612667            if (config.flags4 & CFG4speed && 
    25622668                op == OPu8int && mask[reg] & BYTEREGS && 
    25632669                config.target_cpu < TARGET_PentiumPro) 
    25642670            { 
    25652671                c2 = movregconst(NULL,reg,0,0);                 //  XOR reg,reg 
    25662672                c3 = loadea(e1,&cs,0x8A,reg,0,retregs,retregs); //  MOV regL,EA 
    25672673            } 
    25682674            else 
    25692675            { 
    25702676                opcode = (op == OPu8int) ? 0x0FB6 : 0x0FBE; // MOVZX/MOVSX reg,EA 
    25712677                c2 = loadea(e1,&cs,opcode,reg,0,0,retregs); 
    25722678                c3 = CNIL; 
    25732679            } 
     
    25902696                retregs = BYTEREGS; 
    25912697        } 
    25922698        else 
    25932699        { 
    25942700            /* CBW doesn't affect flags, so we can depend on the integer */ 
    25952701            /* math to provide the flags.                               */ 
    25962702            retregs = mAX | (*pretregs & mPSW); /* want integer result in AX */ 
    25972703        } 
    25982704    } 
    25992705 
    26002706    c3 = CNIL; 
    26012707    c1 = codelem(e1,&retregs,FALSE); 
    26022708    reg = findreg(retregs); 
    26032709    if (!c1) 
    26042710        goto L1; 
    26052711 
    26062712    for (c = c1; c->next; c = c->next) 
    26072713        ;                               /* find previous instruction    */ 
    26082714 
    26092715    /* If previous instruction is an AND bytereg,value  */ 
    2610     if (c->Iop == 0x80 && c->Irm == modregrm(3,4,reg) && 
     2716    if (c->Iop == 0x80 && c->Irm == modregrm(3,4,reg & 7) && 
    26112717        (op == OPu8int || (c->IEV2.Vuns & 0x80) == 0)) 
    26122718    { 
    26132719        if (*pretregs & mPSW) 
    26142720            c->Iflags |= CFpsw; 
    26152721        c->Iop |= 1;                    /* convert to word operation    */ 
    26162722        c->IEV2.Vuns &= 0xFF;           /* dump any high order bits     */ 
    26172723        *pretregs &= ~mPSW;             /* flags already set            */ 
    26182724    } 
    26192725    else 
    26202726    { 
    26212727     L1: 
    2622         if (I32
     2728        if (!I16
    26232729        { 
    26242730            if (op == OPs8int && reg == AX && size == 2) 
    26252731            {   c3 = gen1(c3,0x98);             /* CBW                  */ 
    26262732                c3->Iflags |= CFopsize;         /* don't do a CWDE      */ 
    26272733            } 
    26282734            else 
    26292735            { 
    26302736                /* We could do better by not forcing the src and dst    */ 
    26312737                /* registers to be the same.                            */ 
    26322738 
    26332739                if (config.flags4 & CFG4speed && op == OPu8_16) 
    26342740                {   // AND reg,0xFF 
    26352741                    c3 = genc2(c3,0x81,modregrm(3,4,reg),0xFF); 
    26362742                } 
    26372743                else 
    26382744                {   c3 = genregs(c3,0x0F,reg,reg); 
    26392745                    c3->Iop2 = (op == OPu8int) ? 0xB6 : 0xBE; /* MOVZX/MOVSX reg,reg */ 
    26402746                } 
    26412747            } 
    26422748        } 
    26432749        else 
    26442750        { 
    26452751            if (op == OPu8int) 
    26462752                c3 = genregs(c3,0x30,reg+4,reg+4);      // XOR regH,regH 
    26472753            else 
    26482754            { 
    26492755                c3 = gen1(c3,0x98);             /* CBW                  */ 
    26502756                *pretregs &= ~mPSW;             /* flags already set    */ 
    26512757            } 
    26522758        } 
    26532759    } 
    26542760    c2 = getregs(retregs); 
    26552761L2: 
    26562762    c4 = fixresult(e,retregs,pretregs); 
    26572763    return cat6(c0,c1,c2,c3,c4,NULL); 
    26582764} 
    26592765 
    26602766 
    26612767/*************************** 
    2662  * Convert long to short (OPlngsht). 
     2768 * Convert long to short (OP32_16). 
    26632769 * Get offset of far pointer (OPoffset). 
    2664  * Convert int to byte (OPint8). 
     2770 * Convert int to byte (OP16_8). 
    26652771 * Convert long long to long (OP64_32). 
    26662772 */ 
    26672773 
    26682774code *cdlngsht(elem *e,regm_t *pretregs) 
    26692775{ regm_t retregs; 
    26702776  code *c; 
    26712777 
    26722778#ifdef DEBUG 
    26732779    switch (e->Eoper) 
    26742780    { 
    2675         case OPlngsht
     2781        case OP32_16
    26762782        case OPoffset: 
    2677         case OPint8: 
     2783        case OP16_8: 
    26782784        case OP64_32: 
    26792785            break; 
    26802786 
    26812787        default: 
    26822788            assert(0); 
    26832789    } 
    26842790#endif 
    26852791 
    2686   if (e->Eoper == OPint8) 
     2792  if (e->Eoper == OP16_8) 
    26872793  {     retregs = *pretregs ? BYTEREGS : 0; 
    26882794        c = codelem(e->E1,&retregs,FALSE); 
    26892795  } 
    26902796  else 
    26912797  {     if (e->E1->Eoper == OPrelconst) 
    26922798            c = offsetinreg(e->E1,&retregs); 
    26932799        else 
    26942800        {   retregs = *pretregs ? ALLREGS : 0; 
    26952801            c = codelem(e->E1,&retregs,FALSE); 
    2696             if (!I32 || e->Eoper == OPoffset || e->Eoper == OP64_32
     2802            if (I16 || I32 && (e->Eoper == OPoffset || e->Eoper == OP64_32)
    26972803                retregs &= mLSW;                /* want LSW only        */ 
    26982804        } 
    26992805  } 
    27002806 
    27012807  /* We "destroy" a reg by assigning it the result of a new e, even     */ 
    27022808  /* though the values are the same. Weakness of our CSE strategy that  */ 
    27032809  /* a register can only hold the contents of one elem at a time.       */ 
    27042810  if (e->Ecount) 
    27052811        c = cat(c,getregs(retregs)); 
    27062812  else 
    27072813        useregs(retregs); 
    27082814 
    27092815#ifdef DEBUG 
    27102816  if (!(!*pretregs || retregs)) 
    27112817        WROP(e->Eoper), 
    27122818        printf(" *pretregs = x%x, retregs = x%x, e = %p\n",*pretregs,retregs,e); 
    27132819#endif 
    27142820  assert(!*pretregs || retregs); 
    27152821  return cat(c,fixresult(e,retregs,pretregs));  /* lsw only             */ 
    27162822} 
     
    27992905        c3->Iflags |= CFopsize; 
    28002906    retregs = mAX; 
    28012907    return cat4(c1,c2,c3,fixresult(e,retregs,pretregs)); 
    28022908} 
    28032909 
    28042910/************************ 
    28052911 * Generate code for an asm elem. 
    28062912 */ 
    28072913 
    28082914code *cdasm(elem *e,regm_t *pretregs) 
    28092915{   code *c; 
    28102916 
    28112917#if 1 
    28122918    /* Assume only regs normally destroyed by a function are destroyed  */ 
    28132919    c = getregs((ALLREGS | mES) & ~fregsaved); 
    28142920#else 
    28152921    /* Assume all regs are destroyed    */ 
    28162922    c = getregs(ALLREGS | mES); 
    28172923#endif 
    28182924    c = genasm(c,e->EV.ss.Vstring,e->EV.ss.Vstrlen); 
    2819     return cat(c,fixresult(e,(I32 ? mAX : mDX | mAX),pretregs)); 
     2925    return cat(c,fixresult(e,(I16 ? mDX | mAX : mAX),pretregs)); 
    28202926} 
    28212927 
    28222928/************************ 
    28232929 * Generate code for OPtofar16 and OPfromfar16. 
    28242930 */ 
    28252931 
    28262932code *cdfar16( elem *e, regm_t *pretregs) 
    28272933{   code *c; 
    28282934    code *c1; 
    28292935    code *c3; 
    28302936    code *cnop; 
    28312937    code cs; 
    28322938    unsigned reg; 
    28332939 
    28342940    assert(I32); 
    28352941    c = codelem(e->E1,pretregs,FALSE); 
    28362942    reg = findreg(*pretregs); 
    28372943    c = cat(c,getregs(*pretregs));      /* we will destroy the regs     */ 
    28382944 
    28392945    cs.Iop = 0xC1; 
     
    29213027 
    29223028    switch (e->Eoper) 
    29233029    { 
    29243030        case OPbt:      op = 0xA3; mode = 4; break; 
    29253031        case OPbtc:     op = 0xBB; mode = 7; break; 
    29263032        case OPbtr:     op = 0xB3; mode = 6; break; 
    29273033        case OPbts:     op = 0xAB; mode = 5; break; 
    29283034 
    29293035        default: 
    29303036            assert(0); 
    29313037    } 
    29323038 
    29333039    e1 = e->E1; 
    29343040    e2 = e->E2; 
    29353041    cs.Iflags = 0; 
    29363042    c = getlvalue(&cs, e, RMload);      // get addressing mode 
    29373043    if (e->Eoper == OPbt && *pretregs == 0) 
    29383044        return cat(c, codelem(e2,pretregs,FALSE)); 
    29393045 
    29403046    ty1 = tybasic(e1->Ety); 
    2941     word = (I32 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0; 
    2942     idxregs = idxregm(cs.Irm, cs.Isib);         // mask if index regs used 
     3047    word = (!I16 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0; 
     3048    idxregs = idxregm(&cs);         // mask if index regs used 
    29433049 
    29443050//    if (e2->Eoper == OPconst && e2->EV.Vuns < 0x100)  // should do this instead? 
    29453051    if (e2->Eoper == OPconst) 
    29463052    { 
    29473053        cs.Iop = 0x0F; 
    29483054        cs.Iop2 = 0xBA;                         // BT rm,imm8 
    29493055        cs.Irm |= modregrm(0,mode,0); 
    29503056        cs.Iflags |= CFpsw | word; 
    29513057        cs.IFL2 = FLconst; 
    29523058        if (tysize[ty1] == SHORTSIZE) 
    29533059        { 
    29543060            cs.IEVoffset1 += (e2->EV.Vuns & ~15) >> 3; 
    29553061            cs.IEV2.Vint = e2->EV.Vint & 15; 
    29563062        } 
    2957         else 
     3063        else if (tysize[ty1] == 4) 
    29583064        { 
    29593065            cs.IEVoffset1 += (e2->EV.Vuns & ~31) >> 3; 
    29603066            cs.IEV2.Vint = e2->EV.Vint & 31; 
     3067        } 
     3068        else 
     3069        { 
     3070            cs.IEVoffset1 += (e2->EV.Vuns & ~63) >> 3; 
     3071            cs.IEV2.Vint = e2->EV.Vint & 63; 
    29613072        } 
    29623073        c2 = gen(CNIL,&cs); 
    29633074    } 
    29643075    else 
    29653076    { 
    29663077        retregs = ALLREGS & ~idxregs; 
    29673078        c2 = scodelem(e2,&retregs,idxregs,TRUE); 
    29683079        reg = findreg(retregs); 
    29693080 
    29703081        cs.Iop = 0x0F; 
    29713082        cs.Iop2 = op;                           // BT rm,reg 
    2972         cs.Irm |= modregrm(0,reg,0); 
     3083        code_newreg(&cs,reg); 
    29733084        cs.Iflags |= CFpsw | word; 
    29743085        c2 = gen(c2,&cs); 
    29753086    } 
    29763087 
    29773088    if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register 
    2978     {   code *nop; 
    2979         regm_t save; 
    2980         code *cg; 
    2981  
    2982         nop = CNIL; 
    2983         save = regcon.immed.mval; 
    2984         cg = allocreg(&retregs,&reg,TYint); 
     3089    { 
     3090        code *nop = CNIL; 
     3091        regm_t save = regcon.immed.mval; 
     3092        code *cg = allocreg(&retregs,&reg,TYint); 
    29853093        regcon.immed.mval = save; 
    29863094        if ((*pretregs & mPSW) == 0) 
    29873095        { 
    29883096            cg = cat(cg,getregs(retregs)); 
    29893097            cg = genregs(cg,0x19,reg,reg);              // SBB reg,reg 
    29903098        } 
    29913099        else 
    29923100        { 
    29933101            cg = movregconst(cg,reg,1,8);               // MOV reg,1 
    29943102            nop = gennop(nop); 
    29953103            cg = genjmp(cg,JC,FLcode,(block *) nop);    // Jtrue nop 
    29963104                                                        // MOV reg,0 
    29973105            movregconst(cg,reg,0,8); 
    29983106            regcon.immed.mval &= ~mask[reg]; 
    29993107        } 
    30003108        *pretregs = retregs; 
    30013109        c2 = cat3(c2,cg,nop); 
    30023110    } 
    30033111 
    30043112    return cat(c,c2); 
     
    30173125    code *cl,*cg; 
    30183126    code cs; 
    30193127 
    30203128    //printf("cdbscan()\n"); 
    30213129    //elem_print(e); 
    30223130    if (*pretregs == 0) 
    30233131        return codelem(e->E1,pretregs,FALSE); 
    30243132    tyml = tybasic(e->E1->Ety); 
    30253133    sz = tysize[tyml]; 
    30263134    assert(sz == 2 || sz == 4); 
    30273135 
    30283136    if ((e->E1->Eoper == OPind && !e->E1->Ecount) || e->E1->Eoper == OPvar) 
    30293137    { 
    30303138        cl = getlvalue(&cs, e->E1, RMload);     // get addressing mode 
    30313139    } 
    30323140    else 
    30333141    { 
    30343142        retregs = allregs; 
    30353143        cl = codelem(e->E1, &retregs, FALSE); 
    30363144        reg = findreg(retregs); 
    3037         cs.Irm = modregrm(3,0,reg); 
     3145        cs.Irm = modregrm(3,0,reg & 7); 
    30383146        cs.Iflags = 0; 
    30393147        cs.Irex = 0; 
     3148        if (reg & 8) 
     3149            cs.Irex |= REX_B; 
    30403150    } 
    30413151 
    30423152    retregs = *pretregs & allregs; 
    30433153    if  (!retregs) 
    30443154        retregs = allregs; 
    30453155    cg = allocreg(&retregs, &reg, e->Ety); 
    30463156 
    30473157    cs.Iop = 0x0F; 
    30483158    cs.Iop2 = (e->Eoper == OPbsf) ? 0xBC : 0xBD;        // BSF/BSR reg,EA 
    3049     cs.Irm |= modregrm(0,reg,0); 
    3050     if (I32 && sz == SHORTSIZE) 
     3159    code_newreg(&cs, reg); 
     3160    if (!I16 && sz == SHORTSIZE) 
    30513161        cs.Iflags |= CFopsize; 
    30523162    cg = gen(cg,&cs); 
    30533163 
    30543164    return cat3(cl,cg,fixresult(e,retregs,pretregs)); 
    30553165} 
    30563166 
    30573167/******************************************* 
    30583168 * Generate code for OPpair, OPrpair. 
    30593169 */ 
    30603170 
    30613171code *cdpair(elem *e, regm_t *pretregs) 
    30623172{ 
    30633173    regm_t retregs; 
    30643174    regm_t regs1; 
    30653175    regm_t regs2; 
    30663176    unsigned reg; 
    30673177    code *cg; 
    30683178    code *c1; 
    30693179    code *c2; 
    30703180 
  • trunk/src/backend/code.c

    r428 r577  
    1212 
    1313#if !SPP 
    1414 
    1515#include        <stdio.h> 
    1616#include        <time.h> 
    1717#include        "cc.h" 
    1818#include        "el.h" 
    1919#include        "code.h" 
    2020#include        "global.h" 
    2121 
    2222static code *code_list; 
    2323 
    2424/***************** 
    2525 * Allocate code 
    2626 */ 
    2727 
    2828#if SCPP && __SC__ && __INTSIZE == 4 && TX86 && !_DEBUG_TRACE && !MEM_DEBUG 
    2929 
    3030__declspec(naked) code *code_calloc() 
    3131{ 
    32     if (sizeof(code) != 0x20
     32    if (sizeof(code) != 0x24
    3333        util_assert("code",__LINE__); 
    3434    __asm 
    3535    { 
    3636        mov     EAX,code_list 
    3737        test    EAX,EAX 
    3838        je      L20 
    3939        mov     ECX,[EAX] 
    4040        mov     code_list,ECX 
    4141        jmp     L29 
    4242 
    4343L20:    push    sizeof(code) 
    4444        call    mem_fmalloc 
    4545        ;add    ESP,4 
    4646L29: 
    4747        xor     ECX,ECX 
    4848        mov     DWORD PTR [EAX],0 
    4949 
    5050        mov     4[EAX],ECX      ;these pair 
    5151        mov     8[EAX],ECX 
    5252 
    5353        mov     12[EAX],ECX 
    5454        mov     16[EAX],ECX 
    5555 
    5656        mov     20[EAX],ECX 
    5757        mov     24[EAX],ECX 
    5858 
    5959        mov     28[EAX],ECX 
     60        mov     32[EAX],ECX 
    6061        ret 
    6162    } 
    6263} 
    6364 
    6465#else 
    6566 
    6667code *code_calloc() 
    6768{   code *c; 
    6869    static code czero; 
    6970 
     71    //printf("code %x\n", sizeof(code)); 
    7072    c = code_list; 
    7173    if (c) 
    7274        code_list = code_next(c); 
    7375    else 
    7476        c = (code *)mem_fmalloc(sizeof(*c)); 
    7577    *c = czero;                         // zero it out 
    7678    //dbg_printf("code_calloc: %p\n",c); 
    7779    return c; 
    7880} 
    7981 
    8082#endif 
    8183 
    8284/***************** 
    8385 * Free code 
    8486 */ 
    8587 
    8688void code_free(code *cstart) 
    8789{   code **pc; 
    8890    code *c; 
    8991 
  • trunk/src/backend/code.h

    r572 r577  
    8989 
    9090#define mXMM0   (1 << XMM0) 
    9191#define mXMM1   (1 << XMM1) 
    9292#define mXMM2   (1 << XMM2) 
    9393#define mXMM3   (1 << XMM3) 
    9494#define mXMM4   (1 << XMM4) 
    9595#define mXMM5   (1 << XMM5) 
    9696#define mXMM6   (1 << XMM6) 
    9797#define mXMM7   (1 << XMM7) 
    9898#define XMMREGS  (mXMM0 |mXMM1 |mXMM2 |mXMM3 |mXMM4 |mXMM5 |mXMM6 |mXMM7) 
    9999 
    100100#define mES     (1 << ES)       // 0x10000 
    101101#define mPSW    (1 << PSW)      // 0x20000 
    102102 
    103103#define mSTACK  (1 << STACK)    // 0x40000 
    104104 
    105105#define mST0    (1 << ST0)      // 0x200000 
    106106#define mST01   (1 << ST01)     // 0x400000 
    107107 
    108108// Flags for getlvalue (must fit in regm_t) 
    109 #define RMload  0x4000 
    110 #define RMstore 0x8000 
     109#define RMload  (1 << 30) 
     110#define RMstore (1 << 31) 
    111111 
    112112#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    113113    // To support positional independent code, 
    114114    // must be able to remove BX from available registers 
    115115extern regm_t ALLREGS; 
    116116#define ALLREGS_INIT            (mAX|mBX|mCX|mDX|mSI|mDI) 
    117117#define ALLREGS_INIT_PIC        (mAX|mCX|mDX|mSI|mDI) 
    118118extern regm_t BYTEREGS; 
    119119#define BYTEREGS_INIT           (mAX|mBX|mCX|mDX) 
    120120#define BYTEREGS_INIT_PIC       (mAX|mCX|mDX) 
    121121#else 
    122122#define ALLREGS                 (mAX|mBX|mCX|mDX|mSI|mDI) 
    123123#define ALLREGS_INIT            ALLREGS 
    124124#undef BYTEREGS 
    125125#define BYTEREGS                (mAX|mBX|mCX|mDX) 
    126126#endif 
    127127 
    128128/* We use the same IDXREGS for the 386 as the 8088, because if 
    129129   we used ALLREGS, it would interfere with mMSW 
    130130 */ 
     
    241241    #define ESCrelease2 9       // release eh stack 
    242242    #define ESCframeptr 10      // replace with load of frame pointer 
    243243 
    244244#define ASM     0x36    // string of asm bytes, actually an SS: opcode 
    245245 
    246246/********************************* 
    247247 * Macros to ease generating code 
    248248 * modregrm:    generate mod reg r/m field 
    249249 * modregxrm:   reg could be R8..R15 
    250250 * modregrmx:   rm could be R8..R15 
    251251 * modregxrmx:  reg or rm could be R8..R15 
    252252 * NEWREG:      change reg field of x to r 
    253253 * genorreg:    OR  t,f 
    254254 */ 
    255255 
    256256#define modregrm(m,r,rm)        (((m)<<6)|((r)<<3)|(rm)) 
    257257#define modregxrm(m,r,rm)       ((((r)&8)<<15)|modregrm((m),(r)&7,rm)) 
    258258#define modregrmx(m,r,rm)       ((((rm)&8)<<13)|modregrm((m),r,(rm)&7)) 
    259259#define modregxrmx(m,r,rm)      ((((r)&8)<<15)|(((rm)&8)<<13)|modregrm((m),(r)&7,(rm)&7)) 
    260260 
     261#define NEWREXR(x,r)            ((x)=((x)&~REX_R)|(((r)&8)>>1)) 
    261262#define NEWREG(x,r)             ((x)=((x)&~(7<<3))|((r)<<3)) 
     263#define code_newreg(c,r)        (NEWREG((c)->Irm,(r)&7),NEWREXR((c)->Irex,(r))) 
     264 
    262265#define genorreg(c,t,f)         genregs((c),0x09,(f),(t)) 
    263266 
    264267#define REX     0x40            // REX prefix byte, OR'd with the following bits: 
    265268#define REX_W   8               // 0 = default operand size, 1 = 64 bit operand size 
    266269#define REX_R   4               // high bit of reg field of modregrm 
    267270#define REX_X   2               // high bit of sib index reg 
    268271#define REX_B   1               // high bit of rm field, sib base reg, or opcode reg 
    269272 
    270273/********************** 
    271274 * C library routines. 
    272275 * See callclib(). 
    273276 */ 
    274277 
    275278enum CLIB 
    276279{ 
    277280        CLIBlcmp, 
    278281        CLIBlmul, 
    279282        CLIBldiv, 
    280283        CLIBlmod, 
    281284        CLIBuldiv, 
     
    374377                                // CFes at the same time, though!) 
    375378#define CFpsw          0x40     // we need the flags result after this instruction 
    376379#define CFopsize       0x80     // prefix with operand size 
    377380#define CFaddrsize    0x100     // prefix with address size 
    378381#define CFds          0x200     // need DS override (not with es, ss, or cs ) 
    379382#define CFcs          0x400     // need CS override 
    380383#define CFfs          0x800     // need FS override 
    381384#define CFgs    (CFcs | CFfs)   // need GS override 
    382385#define CFwait       0x1000     // If I32 it indicates when to output a WAIT 
    383386#define CFselfrel    0x2000     // if self-relative 
    384387#define CFunambig    0x4000     // indicates cannot be accessed by other addressing 
    385388                                // modes 
    386389#define CFtarg2      0x8000     // like CFtarg, but we can't optimize this away 
    387390#define CFvolatile  0x10000     // volatile reference, do not schedule 
    388391#define CFclassinit 0x20000     // class init code 
    389392#define CFoffset64  0x40000     // offset is 64 bits 
    390393 
    391394#define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 
    392395#define CFSEG   (CFes | CFss | CFds | CFcs | CFfs | CFgs) 
    393396 
    394     unsigned char Irex;         // REX prefix 
    395397 
    396398    unsigned char Iop; 
    397     unsigned char Irm;          // reg/mode 
    398  
    399399    unsigned char Iop2;         // second opcode byte 
    400     unsigned char Isib;         // SIB byte 
    401  
    402400    unsigned char Iop3;         // third opcode byte 
     401 
     402    union 
     403    {   unsigned _Iea; 
     404        struct 
     405        { 
     406            unsigned char _Irm;          // reg/mode 
     407            unsigned char _Isib;         // SIB byte 
     408            unsigned char _Irex;         // REX prefix 
     409        } _ea; 
     410    } _EA; 
     411 
     412#define Iea _EA._Iea 
     413#define Irm _EA._ea._Irm 
     414#define Isib _EA._ea._Isib 
     415#define Irex _EA._ea._Irex 
    403416 
    404417    unsigned char IFL1,IFL2;    // FLavors of 1st, 2nd operands 
    405418    union evc IEV1;             // 1st operand, if any 
    406419      #define IEVpointer1 IEV1._EP.Vpointer 
    407420      #define IEVseg1     IEV1._EP.Vseg 
    408421      #define IEVsym1     IEV1.sp.Vsym 
    409422      #define IEVdsym1    IEV1.dsp.Vsym 
    410423      #define IEVoffset1  IEV1.sp.Voffset 
    411424      #define IEVlsym1    IEV1.lab.Vsym 
    412425      #define IEVint1     IEV1.Vint 
    413426    union evc IEV2;             // 2nd operand, if any 
    414427      #define IEVpointer2 IEV2._EP.Vpointer 
    415428      #define IEVseg2     IEV2._EP.Vseg 
    416429      #define IEVsym2     IEV2.sp.Vsym 
    417430      #define IEVdsym2    IEV2.dsp.Vsym 
    418431      #define IEVoffset2  IEV2.sp.Voffset 
    419432      #define IEVlsym2    IEV2.lab.Vsym 
    420433      #define IEVint2     IEV2.Vint 
    421434    void print();               // pretty-printer 
    422435 
     
    528541/***********************************************************/ 
    529542 
    530543extern regm_t msavereg,mfuncreg,allregs; 
    531544 
    532545/*long cxmalloc,cxcalloc,cx1;*/ 
    533546 
    534547typedef code *cd_t (elem *e , regm_t *pretregs ); 
    535548 
    536549extern  int BPRM; 
    537550extern  regm_t FLOATREGS; 
    538551extern  regm_t FLOATREGS2; 
    539552extern  regm_t DOUBLEREGS; 
    540553extern  const char datafl[],stackfl[],segfl[],flinsymtab[]; 
    541554extern  char needframe,usedalloca,gotref; 
    542555extern  targ_size_t localsize,Toff,Poff,Aoff, 
    543556        Poffset,funcoffset, 
    544557        framehandleroffset, 
    545558        Aoffset,Toffset,EEoffset; 
    546559extern  int Aalign; 
    547560extern  int cseg; 
     561extern  int STACKALIGN; 
    548562#if TARGET_OSX 
    549563extern  targ_size_t localgotoffset; 
    550564#endif 
    551565 
    552566/* cgcod.c */ 
    553567extern int pass; 
    554568#define PASSinit        0       // initial pass through code generator 
    555569#define PASSreg         1       // register assignment pass 
    556570#define PASSfinal       2       // final pass 
    557571 
    558572extern  int dfoidx; 
    559573extern  struct CSE *csextab; 
    560574extern  unsigned cstop; 
    561575#if TX86 
    562576extern  bool floatreg; 
    563577#endif 
    564578extern  targ_size_t retoffset; 
    565579extern  unsigned stackpush; 
    566580extern  int stackchanged; 
    567581extern  int refparam; 
     
    581595#endif 
    582596#define findregmsw(regm) findreg((regm) & mMSW) 
    583597#define findreglsw(regm) findreg((regm) & (mLSW | mBP)) 
    584598void freenode (elem *e ); 
    585599int isregvar (elem *e , regm_t *pregm , unsigned *preg ); 
    586600#ifdef DEBUG 
    587601code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym , int line , const char *file ); 
    588602#define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__) 
    589603#else 
    590604code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym ); 
    591605#endif 
    592606void useregs (regm_t regm ); 
    593607code *getregs (regm_t r ); 
    594608code *getregs_imm (regm_t r ); 
    595609code *cse_flush(int); 
    596610void cssave (elem *e , regm_t regm , unsigned opsflag ); 
    597611bool evalinregister (elem *e ); 
    598612regm_t getscratch(); 
    599613code *codelem (elem *e , regm_t *pretregs , bool constflag ); 
    600614const char *regm_str(regm_t rm); 
     615int numbitsset(regm_t); 
    601616 
    602617/* cod1.c */ 
    603618extern int clib_inited; 
    604619 
    605620int isscaledindex(elem *); 
    606621int ssindex(int op,targ_uns product); 
    607622void buildEA(code *c,int base,int index,int scale,targ_size_t disp); 
    608623void andregcon (con_t *pregconsave); 
    609624code *docommas (elem **pe ); 
    610625code *gencodelem(code *c,elem *e,regm_t *pretregs,bool constflag); 
    611626void gensaverestore(regm_t, code **, code **); 
    612627code *genstackclean(code *c,unsigned numpara,regm_t keepmsk); 
    613628code *logexp (elem *e , int jcond , unsigned fltarg , code *targ ); 
    614 code *loadea (elem *e , code __ss *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk ); 
     629code *loadea (elem *e , code *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk ); 
    615630unsigned getaddrmode (regm_t idxregs ); 
     631void setaddrmode(code *c, regm_t idxregs); 
    616632void getlvalue_msw(code *); 
    617633void getlvalue_lsw(code *); 
    618 code *getlvalue (code __ss *pcs , elem *e , regm_t keepmsk ); 
     634code *getlvalue (code *pcs , elem *e , regm_t keepmsk ); 
    619635code *scodelem (elem *e , regm_t *pretregs , regm_t keepmsk , bool constflag ); 
    620 code *fltregs (code __ss *pcs , tym_t tym ); 
     636code *fltregs (code *pcs , tym_t tym ); 
    621637code *tstresult (regm_t regm , tym_t tym , unsigned saveflag ); 
    622638code *fixresult (elem *e , regm_t retregs , regm_t *pretregs ); 
    623639code *callclib (elem *e , unsigned clib , regm_t *pretregs , regm_t keepmask ); 
    624640cd_t cdfunc; 
    625641cd_t cdstrthis; 
    626642code *params(elem *, unsigned); 
    627643code *offsetinreg (elem *e , regm_t *pretregs ); 
    628644code *loaddata (elem *e , regm_t *pretregs ); 
    629645 
    630646/* cod2.c */ 
    631 regm_t idxregm (unsigned rm,unsigned sib); 
     647regm_t idxregm(code *c); 
    632648#if TARGET_WINDOS 
    633649code *opdouble (elem *e , regm_t *pretregs , unsigned clib ); 
    634650#endif 
    635651cd_t cdorth; 
    636652cd_t cdmul; 
    637653cd_t cdnot; 
    638654cd_t cdcom; 
    639655cd_t cdbswap; 
    640656cd_t cdcond; 
    641657void WRcodlst (code *c ); 
    642658cd_t cdcomma; 
    643659cd_t cdloglog; 
    644660cd_t cdshift; 
    645661#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    646662cd_t cdindpic; 
    647663#endif 
    648664cd_t cdind; 
    649665cd_t cdstrlen; 
    650666cd_t cdstrcmp; 
    651667cd_t cdstrcpy; 
     
    662678cd_t cderr; 
    663679cd_t cdinfo; 
    664680cd_t cdctor; 
    665681cd_t cddtor; 
    666682cd_t cdmark; 
    667683cd_t cdnullcheck; 
    668684cd_t cdclassinit; 
    669685 
    670686/* cod3.c */ 
    671687extern int BPoff; 
    672688 
    673689int cod3_EA(code *c); 
    674690regm_t cod3_useBP(); 
    675691void cod3_set386 (void ); 
    676692void cod3_set64 (void ); 
    677693void cod3_align (void ); 
    678694void doswitch (block *b ); 
    679695void outjmptab (block *b ); 
    680696void outswitab (block *b ); 
    681697int jmpopcode (elem *e ); 
    682 void cod3_ptrchk(code * __ss *pc,code __ss *pcs,regm_t keepmsk); 
     698void cod3_ptrchk(code **pc,code *pcs,regm_t keepmsk); 
    683699code *prolog (void ); 
    684700void epilog (block *b); 
    685701cd_t cdframeptr; 
    686702cd_t cdgot; 
    687703targ_size_t cod3_spoff(); 
    688704code *cod3_load_got(); 
    689705void makeitextern (symbol *s ); 
    690706void fltused(void); 
    691707int branch(block *bl, int flag); 
    692708void cod3_adjSymOffsets(); 
    693709void assignaddr (block *bl ); 
    694710void assignaddrc (code *c ); 
    695711targ_size_t cod3_bpoffset(symbol *s); 
    696712void pinholeopt (code *c , block *bn ); 
    697713void jmpaddr (code *c ); 
    698714int code_match(code *c1,code *c2); 
    699715unsigned calcblksize (code *c); 
    700716unsigned calccodsize(code *c); 
    701717unsigned codout (code *c ); 
    702718void addtofixlist (symbol *s , targ_size_t soffset , int seg , targ_size_t val , int flags ); 
    703719void searchfixlist (symbol *s ); 
    704720void outfixlist (void ); 
    705721void code_hydrate(code **pc); 
    706722void code_dehydrate(code **pc); 
    707723 
    708724/* cod4.c */ 
    709725extern  const unsigned dblreg[]; 
    710726extern int cdcmp_flag; 
    711727 
    712 code *modEA (unsigned Irm ); 
     728code *modEA(code *c); 
    713729cd_t cdeq; 
    714730cd_t cdaddass; 
    715731cd_t cdmulass; 
    716732cd_t cdshass; 
    717733cd_t cdcmp; 
    718734cd_t cdcnvt; 
    719735cd_t cdshtlng; 
    720736cd_t cdbyteint; 
    721737cd_t cdlngsht; 
    722738cd_t cdmsw; 
    723739cd_t cdport; 
    724740cd_t cdasm; 
    725741cd_t cdsetjmp; 
    726742cd_t cdvoid; 
    727743cd_t cdhalt; 
    728744cd_t cdfar16; 
    729745cd_t cdbt; 
    730746cd_t cdbscan; 
    731747cd_t cdpair; 
    732748code *longcmp (elem *,bool,unsigned,code *); 
     
    786802code *nteh_filter(block *b); 
    787803void nteh_framehandler(symbol *); 
    788804code *nteh_gensindex(int); 
    789805#define GENSINDEXSIZE 7 
    790806code *nteh_monitor_prolog(Symbol *shandle); 
    791807code *nteh_monitor_epilog(regm_t retregs); 
    792808 
    793809// cgen.c 
    794810code *code_last(code *c); 
    795811void code_orflag(code *c,unsigned flag); 
    796812void code_orrex(code *c,unsigned rex); 
    797813code * __pascal cat (code *c1 , code *c2 ); 
    798814code * cat3 (code *c1 , code *c2 , code *c3 ); 
    799815code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 ); 
    800816code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 ); 
    801817code *gen (code *c , code *cs ); 
    802818code *gen1 (code *c , unsigned op ); 
    803819code *gen2 (code *c , unsigned op , unsigned rm ); 
    804820code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib); 
    805821code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg ); 
     822code *genpush (code *c , unsigned reg ); 
     823code *genpop (code *c , unsigned reg ); 
    806824code *gentstreg (code *c , unsigned reg ); 
    807825code *genasm (code *c , char *s , unsigned slen ); 
    808826code *genmovreg (code *c , unsigned to , unsigned from ); 
    809827code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ ); 
    810828code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si ); 
    811829code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s ); 
    812830code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 ); 
    813831code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 ); 
    814832code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 ); 
    815833code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm); 
    816834code *genlinnum(code *,Srcpos); 
    817835void cgen_linnum(code **pc,Srcpos srcpos); 
    818836void cgen_prelinnum(code **pc,Srcpos srcpos); 
    819837code *genadjesp(code *c, int offset); 
    820838code *gennop(code *); 
    821839code *genshift(code *); 
    822840code *movregconst (code *c , unsigned reg , targ_size_t value , regm_t flags ); 
    823841bool reghasvalue (regm_t regm , targ_size_t value , unsigned *preg ); 
    824842code *regwithvalue (code *c , regm_t regm , targ_size_t value , unsigned *preg , regm_t flags ); 
    825843 
  • trunk/src/backend/iasm.h

    r572 r577  
    7171// Operand flags - usOp1, usOp2, usOp3 
    7272// 
    7373 
    7474typedef unsigned opflag_t; 
    7575 
    7676// Operand flags for normal opcodes 
    7777 
    7878#define _r8     CONSTRUCT_FLAGS( _8, _reg, _normal, 0 ) 
    7979#define _r16    CONSTRUCT_FLAGS(_16, _reg, _normal, 0 ) 
    8080#define _r32    CONSTRUCT_FLAGS(_32, _reg, _normal, 0 ) 
    8181#define _r64    CONSTRUCT_FLAGS(_64, _reg, _normal, 0 ) 
    8282#define _m8     CONSTRUCT_FLAGS(_8, _m, _normal, 0 ) 
    8383#define _m16    CONSTRUCT_FLAGS(_16, _m, _normal, 0 ) 
    8484#define _m32    CONSTRUCT_FLAGS(_32, _m, _normal, 0 ) 
    8585#define _m48    CONSTRUCT_FLAGS( _48, _m, _normal, 0 ) 
    8686#define _m64    CONSTRUCT_FLAGS( _64, _m, _normal, 0 ) 
    8787#define _m128   CONSTRUCT_FLAGS( _anysize, _m, _normal, 0 ) 
    8888#define _rm8    CONSTRUCT_FLAGS(_8, _rm, _normal, 0 ) 
    8989#define _rm16   CONSTRUCT_FLAGS(_16, _rm, _normal, 0 ) 
    9090#define _rm32   CONSTRUCT_FLAGS(_32, _rm, _normal, 0) 
     91#define _rm64   CONSTRUCT_FLAGS(_64, _rm, _normal, 0) 
    9192#define _r32m16 CONSTRUCT_FLAGS(_32|_16, _rm, _normal, 0) 
    9293#define _imm8   CONSTRUCT_FLAGS(_8, _imm, _normal, 0 ) 
    9394#define _imm16  CONSTRUCT_FLAGS(_16, _imm, _normal, 0) 
    9495#define _imm32  CONSTRUCT_FLAGS(_32, _imm, _normal, 0) 
    9596#define _rel8   CONSTRUCT_FLAGS(_8, _rel, _normal, 0) 
    9697#define _rel16  CONSTRUCT_FLAGS(_16, _rel, _normal, 0) 
    9798#define _rel32  CONSTRUCT_FLAGS(_32, _rel, _normal, 0) 
    9899#define _p1616  CONSTRUCT_FLAGS(_32, _p, _normal, 0) 
    99100#define _m1616  CONSTRUCT_FLAGS(_32, _mnoi, _normal, 0) 
    100101#define _p1632  CONSTRUCT_FLAGS(_48, _p, _normal, 0 ) 
    101102#define _m1632  CONSTRUCT_FLAGS(_48, _mnoi, _normal, 0) 
    102103#define _special  CONSTRUCT_FLAGS( 0, 0, _rspecial, 0 ) 
    103104#define _seg    CONSTRUCT_FLAGS( 0, 0, _rseg, 0 ) 
    104105#define _a16    CONSTRUCT_FLAGS( 0, 0, _addr16, 0 ) 
    105106#define _a32    CONSTRUCT_FLAGS( 0, 0, _addr32, 0 ) 
    106107#define _f16    CONSTRUCT_FLAGS( 0, 0, _fn16, 0) 
    107108                                                // Near function pointer 
    108109#define _f32    CONSTRUCT_FLAGS( 0, 0, _fn32, 0) 
    109110                                                // Far function pointer 
    110111#define _lbl    CONSTRUCT_FLAGS( 0, 0, _flbl, 0 ) 
  • trunk/src/backend/ptrntab.c

    r572 r577  
    500500PTRNTAB1 aptb1LOOPZ[] = /* LOOPZ */ { 
    501501        { 0xe1, _cb | _modcx,_rel8 }, 
    502502        { ASM_END, 0, 0 } 
    503503}; 
    504504PTRNTAB1 aptb1LOOPNE[] = /* LOOPNE */ { 
    505505        { 0xe0, _cb | _modcx,_rel8 }, 
    506506        { ASM_END, 0, 0 } 
    507507}; 
    508508PTRNTAB1 aptb1LOOPNZ[] = /* LOOPNZ */ { 
    509509        { 0xe0, _cb | _modcx,_rel8 }, 
    510510        { ASM_END, 0, 0 } 
    511511}; 
    512512PTRNTAB1 aptb1LTR[] = /* LTR */ { 
    513513        { 0x0f00,       _3|_modnot1,    _rm16 }, 
    514514        { ASM_END, 0, 0 } 
    515515}; 
    516516PTRNTAB1 aptb1NEG[] = /* NEG */ { 
    517517        { 0xf6, _3,     _rm8 }, 
    518518        { 0xf7, _3 | _16_bit,   _rm16 }, 
    519519        { 0xf7, _3 | _32_bit,   _rm32 }, 
     520        { 0xf7, _3 | _64_bit,   _rm64 }, 
    520521        { ASM_END, 0, 0 } 
    521522}; 
    522523PTRNTAB1 aptb1NOT[] = /* NOT */ { 
    523524        { 0xf6, _2,     _rm8 }, 
    524525        { 0xf7, _2 | _16_bit,   _rm16 }, 
    525526        { 0xf7, _2 | _32_bit,   _rm32 }, 
    526527        { ASM_END, 0, 0 } 
    527528}; 
    528529PTRNTAB1 aptb1POP[] = /* POP */ { 
    529530        { 0x8f, _0 | _16_bit, _m16 }, 
    530531        { 0x8f, _0 | _32_bit,   _m32}, 
    531532        { 0x58, _rw | _16_bit, _r16 | _plus_r }, 
    532533        { 0x58, _rd | _32_bit, _r32 | _plus_r }, 
     534        { 0x58, _r | _64_bit,   _r64 | _plus_r }, 
    533535        { 0x1f, 0,      _ds | _seg }, 
    534536        { 0x07, _modes, _es | _seg}, 
    535537        { 0x17, 0,      _ss | _seg}, 
    536538        { 0x0fa1,       0,      _fs | _seg}, 
    537539        { 0x0fa9,       0,      _gs | _seg}, 
    538540        { ASM_END, 0, 0 } 
    539541}; 
    540542PTRNTAB1 aptb1PUSH[] = /* PUSH */ { 
    541543        { 0xff, _6 | _16_bit,   _m16 }, 
    542544        { 0xff, _6 | _32_bit,   _m32 }, 
     545        { 0xff, _6 | _64_bit,   _m64 }, 
    543546        { 0x50, _r | _16_bit,   _r16 | _plus_r }, 
    544547        { 0x50, _r | _32_bit,   _r32 | _plus_r }, 
     548        { 0x50, _r | _64_bit,   _r64 | _plus_r }, 
    545549        { 0x6a, 0,_imm8 }, 
    546550        { 0x68, _16_bit,_imm16 }, 
    547551        { 0x68, _16_bit,_rel16 }, 
    548552        { 0x68, _32_bit,_imm32 }, 
    549553        { 0x68, _32_bit,_rel32 }, 
    550554        { 0x0e, 0,_cs | _seg}, 
    551555        { 0x16, 0,_ss | _seg}, 
    552556        { 0x1e, 0,_ds | _seg}, 
    553557        { 0x06, 0,_es | _seg}, 
    554558        { 0x0fa0,       0,_fs | _seg}, 
    555559        { 0x0fa8,       0,_gs | _seg}, 
    556560        { ASM_END, 0, 0 } 
    557561}; 
    558562PTRNTAB1 aptb1RET[] = /* RET */ { 
    559563        { 0xc3, 0,      0 }, 
    560564        { 0xc2, _iw,    _imm16 }, 
    561565        { ASM_END, 0, 0 } 
    562566}; 
    563567PTRNTAB1 aptb1RETF[] = /* RETF */ { 
    564568        { 0xcb, 0, 0 }, 
  • trunk/src/freebsd.mak

    r473 r577  
    55 
    66CC=g++ -m32 
    77 
    88#OPT=-g -g3 
    99#OPT=-O2 
    1010 
    1111#COV=-fprofile-arcs -ftest-coverage 
    1212 
    1313#GFLAGS = -Wno-deprecated -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 $(COV) 
    1414GFLAGS = -Wno-deprecated -D__near= -D__pascal= -fno-exceptions -O2 
    1515 
    1616CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_FREEBSD=1 -D_DH 
    1717MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_FREEBSD=1 -D_DH 
    1818 
    1919CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    2020    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    2121TOTALH= 
    2222 
    2323DMD_OBJS = \ 
    2424    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    25     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     25    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    2626    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    2727    constfold.o irstate.o dchar.o cond.o debug.o \ 
    2828    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    2929    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    3030    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    3131    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    3232    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    3333    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    3434    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    3535    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    3636    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    3737    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    3838    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    3939    builtin.o clone.o aliasthis.o \ 
    4040    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    4141    imphint.o \ 
    4242    libelf.o elfobj.o 
    4343 
    4444SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    4545    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • trunk/src/iasm.c

    r572 r577  
    9393    EM_num, 
    9494    EM_float, 
    9595    EM_char, 
    9696    EM_label_expected, 
    9797    EM_uplevel, 
    9898    EM_type_as_operand, 
    9999}; 
    100100 
    101101const char *asmerrmsgs[] = 
    102102{ 
    103103    "unknown operand for floating point instruction", 
    104104    "bad addr mode", 
    105105    "align %d must be a power of 2", 
    106106    "opcode expected, not %s", 
    107107    "prefix", 
    108108    "end of instruction", 
    109109    "bad operand", 
    110110    "bad integral operand", 
    111111    "identifier expected", 
    112112    "not struct", 
    113     "nops expected", 
     113    "%u operands found for %s instead of the expected %u", 
    114114    "bad type/size of operands '%s'", 
    115115    "constant initializer expected", 
    116116    "undefined identifier '%s'", 
    117117    "pointer", 
    118118    "colon", 
    119119    "] expected instead of '%s'", 
    120120    ") expected instead of '%s'", 
    121121    "ptr expected", 
    122122    "integer expected", 
    123123    "floating point expected", 
    124124    "character is truncated", 
    125125    "label expected", 
    126126    "uplevel nested reference to variable %s", 
    127127    "cannot use type %s as an operand" 
    128128}; 
    129129 
    130130// Additional tokens for the inline assembler 
    131131typedef enum 
    132132{ 
    133133    ASMTKlocalsize = TOKMAX + 1, 
     
    14761476                    if (usNumops == 1) 
    14771477                    {   pc->IFL2 = FLblock; 
    14781478                        pc->IEVlsym2 = label; 
    14791479                    } 
    14801480                    else 
    14811481                    {   pc->IFL1 = FLblock; 
    14821482                        pc->IEVlsym1 = label; 
    14831483                    } 
    14841484                } 
    14851485            } 
    14861486        } 
    14871487 
    14881488        switch (usNumops) 
    14891489        { 
    14901490            case 0: 
    14911491                break; 
    14921492            case 1: 
    14931493                if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    14941494                     amodTable1 == _normal && (uRegmaskTable1 & _rplus_r))) 
    14951495                { 
    1496                         if (asmstate.ucItype == ITfloat) 
    1497                                 pc->Irm += popnd1->base->val; 
    1498                         else if (pc->Iop == 0x0f) 
    1499                                 pc->Iop2 += popnd1->base->val; 
    1500                         else 
    1501                                 pc->Iop += popnd1->base->val; 
     1496                    unsigned reg = popnd1->base->val; 
     1497                    if (reg & 8) 
     1498                    {   reg &= 7; 
     1499                        pc->Irex |= REX_B; 
     1500                        assert(I64); 
     1501                    } 
     1502                    if (asmstate.ucItype == ITfloat) 
     1503                        pc->Irm += reg; 
     1504                    else if (pc->Iop == 0x0f) 
     1505                        pc->Iop2 += reg; 
     1506                    else 
     1507                        pc->Iop += reg; 
    15021508#ifdef DEBUG 
    1503                         auchOpcode[usIdx-1] += popnd1->base->val
     1509                    auchOpcode[usIdx-1] += reg
    15041510#endif 
    15051511                } 
    15061512                else 
    15071513                {       asm_make_modrm_byte( 
    15081514#ifdef DEBUG 
    15091515                                auchOpcode, &usIdx, 
    15101516#endif 
    15111517                                pc, 
    15121518                                ptb.pptb1->usFlags, 
    15131519                                popnd1, NULL); 
    15141520                } 
    15151521                popndTmp = popnd1; 
    15161522                aoptyTmp = aoptyTable1; 
    15171523                uSizemaskTmp = uSizemaskTable1; 
    15181524L1: 
    15191525                if (aoptyTmp == _imm) 
    15201526                { 
    15211527                    Declaration *d = popndTmp->s ? popndTmp->s->isDeclaration() 
    15221528                                                 : NULL; 
    15231529                    if (popndTmp->bSeg) 
     
    16071613                        else 
    16081614                        { 
    16091615                            asm_make_modrm_byte( 
    16101616#ifdef DEBUG 
    16111617                                auchOpcode, &usIdx, 
    16121618#endif 
    16131619                                pc, 
    16141620                                ptb.pptb1->usFlags, 
    16151621                                popnd2, popnd1); 
    16161622                        } 
    16171623                        popndTmp = popnd1; 
    16181624                        aoptyTmp = aoptyTable1; 
    16191625                        uSizemaskTmp = uSizemaskTable1; 
    16201626                } 
    16211627                else 
    16221628                { 
    16231629                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    16241630                             amodTable1 == _normal && 
    16251631                             (uRegmaskTable1 & _rplus_r))) 
    16261632                        { 
    1627                                 if (asmstate.ucItype == ITfloat) 
    1628                                         pc->Irm += popnd1->base->val; 
    1629                                 else 
    1630                                 if (pc->Iop == 0x0f) 
    1631                                         pc->Iop2 += popnd1->base->val; 
    1632                                 else 
    1633                                         pc->Iop += popnd1->base->val; 
     1633                            unsigned reg = popnd1->base->val; 
     1634                            if (reg & 8) 
     1635                            {   reg &= 7; 
     1636                                pc->Irex |= REX_B; 
     1637                                assert(I64); 
     1638                            } 
     1639                            if (asmstate.ucItype == ITfloat) 
     1640                                pc->Irm += reg; 
     1641                            else if (pc->Iop == 0x0f) 
     1642                                pc->Iop2 += reg; 
     1643                            else 
     1644                                pc->Iop += reg; 
    16341645#ifdef DEBUG 
    1635                                 auchOpcode[usIdx-1] += popnd1->base->val
     1646                            auchOpcode[usIdx-1] += reg
    16361647#endif 
    16371648                        } 
    16381649                        else 
    16391650                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    16401651                             amodTable2 == _normal && 
    16411652                             (uRegmaskTable2 & _rplus_r))) 
    16421653                        { 
    1643                                 if (asmstate.ucItype == ITfloat) 
    1644                                         pc->Irm += popnd2->base->val; 
    1645                                 else 
    1646                                 if (pc->Iop == 0x0f) 
    1647                                         pc->Iop2 += popnd2->base->val; 
    1648                                 else 
    1649                                         pc->Iop += popnd2->base->val; 
     1654                            unsigned reg = popnd2->base->val; 
     1655                            if (reg & 8) 
     1656                            {   reg &= 7; 
     1657                                pc->Irex |= REX_B; 
     1658                                assert(I64); 
     1659                            } 
     1660                            if (asmstate.ucItype == ITfloat) 
     1661                                pc->Irm += reg; 
     1662                            else if (pc->Iop == 0x0f) 
     1663                                pc->Iop2 += reg; 
     1664                            else 
     1665                                pc->Iop += reg; 
    16501666#ifdef DEBUG 
    1651                                 auchOpcode[usIdx-1] += popnd2->base->val
     1667                            auchOpcode[usIdx-1] += reg
    16521668#endif 
    16531669                        } 
    16541670                        else if (ptb.pptb0->usOpcode == 0xF30FD6 || 
    16551671                                 ptb.pptb0->usOpcode == 0x0F12 || 
    16561672                                 ptb.pptb0->usOpcode == 0x0F16 || 
    16571673                                 ptb.pptb0->usOpcode == 0x660F50 || 
    16581674                                 ptb.pptb0->usOpcode == 0x0F50 || 
    16591675                                 ptb.pptb0->usOpcode == 0x660FD7 || 
    16601676                                 ptb.pptb0->usOpcode == 0x0FD7) 
    16611677                        { 
    16621678                            asm_make_modrm_byte( 
    16631679#ifdef DEBUG 
    16641680                                    auchOpcode, &usIdx, 
    16651681#endif 
    16661682                                    pc, 
    16671683                                    ptb.pptb1->usFlags, 
    16681684                                    popnd2, popnd1); 
    16691685                        } 
    16701686                        else 
    16711687                        { 
     
    16971713                if (aoptyTable2 == _m || aoptyTable2 == _rm || 
    16981714                    usOpcode == 0x0FC5) // PEXTRW 
    16991715                { 
    17001716                    asm_make_modrm_byte( 
    17011717#ifdef DEBUG 
    17021718                                auchOpcode, &usIdx, 
    17031719#endif 
    17041720                                pc, 
    17051721                                ptb.pptb1->usFlags, 
    17061722                                popnd2, popnd1); 
    17071723                        popndTmp = popnd3; 
    17081724                        aoptyTmp = aoptyTable3; 
    17091725                        uSizemaskTmp = uSizemaskTable3; 
    17101726                } 
    17111727                else { 
    17121728 
    17131729                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    17141730                             amodTable1 == _normal && 
    17151731                             (uRegmaskTable1 &_rplus_r))) 
    17161732                        { 
    1717                                 if (asmstate.ucItype == ITfloat) 
    1718                                         pc->Irm += popnd1->base->val; 
    1719                                 else 
    1720                                 if (pc->Iop == 0x0f) 
    1721                                         pc->Iop2 += popnd1->base->val; 
    1722                                 else 
    1723                                         pc->Iop += popnd1->base->val; 
     1733                            unsigned reg = popnd1->base->val; 
     1734                            if (reg & 8) 
     1735                            {   reg &= 7; 
     1736                                pc->Irex |= REX_B; 
     1737                                assert(I64); 
     1738                            } 
     1739                            if (asmstate.ucItype == ITfloat) 
     1740                                pc->Irm += reg; 
     1741                            else if (pc->Iop == 0x0f) 
     1742                                pc->Iop2 += reg; 
     1743                            else 
     1744                                pc->Iop += reg; 
    17241745#ifdef DEBUG 
    1725                                 auchOpcode[usIdx-1] += popnd1->base->val
     1746                            auchOpcode[usIdx-1] += reg
    17261747#endif 
    17271748                        } 
    17281749                        else 
    17291750                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    17301751                             amodTable2 == _normal && 
    17311752                             (uRegmaskTable2 &_rplus_r))) 
    17321753                        { 
    1733                                 if (asmstate.ucItype == ITfloat) 
    1734                                         pc->Irm += popnd1->base->val; 
    1735                                 else 
    1736                                 if (pc->Iop == 0x0f) 
    1737                                         pc->Iop2 += popnd1->base->val; 
    1738                                 else 
    1739                                         pc->Iop += popnd2->base->val; 
     1754                            unsigned reg = popnd1->base->val; 
     1755                            if (reg & 8) 
     1756                            {   reg &= 7; 
     1757                                pc->Irex |= REX_B; 
     1758                                assert(I64); 
     1759                            } 
     1760                            if (asmstate.ucItype == ITfloat) 
     1761                                pc->Irm += reg; 
     1762                            else if (pc->Iop == 0x0f) 
     1763                                pc->Iop2 += reg; 
     1764                            else 
     1765                                pc->Iop += reg; 
    17401766#ifdef DEBUG 
    1741                                 auchOpcode[usIdx-1] += popnd2->base->val
     1767                            auchOpcode[usIdx-1] += reg
    17421768#endif 
    17431769                        } 
    17441770                        else 
    17451771                                asm_make_modrm_byte( 
    17461772#ifdef DEBUG 
    17471773                                        auchOpcode, &usIdx, 
    17481774#endif 
    17491775                                        pc, 
    17501776                                        ptb.pptb1->usFlags, 
    17511777                                        popnd1, popnd2); 
    17521778 
    17531779                        popndTmp = popnd3; 
    17541780                        aoptyTmp = aoptyTable3; 
    17551781                        uSizemaskTmp = uSizemaskTable3; 
    17561782 
    17571783                } 
    17581784                goto L1; 
    17591785        } 
    17601786L2: 
    17611787 
     
    26542680    case _modsidi: 
    26552681        usRet |= (mSI | mDI); 
    26562682        break; 
    26572683    case _modcx: 
    26582684        usRet |= mCX; 
    26592685        break; 
    26602686    case _modes: 
    26612687        /*usRet |= mES;*/ 
    26622688        break; 
    26632689    case _modall: 
    26642690        asmstate.bReturnax = TRUE; 
    26652691        return /*mES |*/ ALLREGS; 
    26662692    case _modsiax: 
    26672693        usRet |= (mSI | mAX); 
    26682694        break; 
    26692695    case _modsinot1: 
    26702696        usRet |= mSI; 
    26712697        popnd1 = NULL; 
    26722698        break; 
    26732699    } 
    2674     if (popnd1 && ASM_GET_aopty(popnd1->usFlags) == _reg) { 
    2675         switch (ASM_GET_amod(popnd1->usFlags)) { 
     2700    if (popnd1 && ASM_GET_aopty(popnd1->usFlags) == _reg) 
     2701    { 
     2702        switch (ASM_GET_amod(popnd1->usFlags)) 
     2703        { 
    26762704        default: 
    2677             if (ASM_GET_uSizemask(popnd1->usFlags) == _8) { 
    2678                 switch(popnd1->base->val) { 
    2679                     case _AL: 
    2680                     case _AH: 
    2681                         usRet |= mAX; 
    2682                         break; 
    2683                     case _BL: 
    2684                     case _BH: 
    2685                         usRet |= mBX; 
    2686                         break; 
    2687                     case _CL: 
    2688                     case _CH: 
    2689                         usRet |= mCX; 
    2690                         break; 
    2691                     case _DL: 
    2692                     case _DH: 
    2693                         usRet |= mDX; 
    2694                         break; 
    2695                     default: 
    2696                         assert(0); 
    2697                 } 
    2698             } 
    2699             else { 
    2700                 switch (popnd1->base->val) { 
    2701                     case _AX: 
    2702                         usRet |= mAX; 
    2703                         break; 
    2704                     case _BX: 
    2705                         usRet |= mBX; 
    2706                         break; 
    2707                     case _CX: 
    2708                         usRet |= mCX; 
    2709                         break; 
    2710                     case _DX: 
    2711                         usRet |= mDX; 
    2712                         break; 
    2713                     case _SI: 
    2714                         usRet |= mSI; 
    2715                         break; 
    2716                     case _DI: 
    2717                         usRet |= mDI; 
    2718                         break; 
    2719                 } 
    2720             } 
     2705            usRet |= 1 << popnd1->base->val; 
     2706            usRet &= ~(mBP | mSP);              // ignore changing these 
    27212707            break; 
    27222708        case _rseg: 
    27232709            //if (popnd1->base->val == _ES) 
    27242710                //usRet |= mES; 
    27252711            break; 
    27262712 
    27272713        case _rspecial: 
    27282714            break; 
    27292715        } 
    27302716    } 
    27312717    if (usRet & mAX) 
    27322718        asmstate.bReturnax = TRUE; 
    27332719 
    27342720    return usRet; 
    27352721} 
    27362722 
    27372723/******************************* 
    27382724 * Match flags in operand against flags in opcode table. 
    27392725 * Returns: 
    27402726 *      !=0 if match 
  • trunk/src/linux.mak

    r569 r577  
    99 
    1010#OPT=-g -g3 
    1111#OPT=-O2 
    1212 
    1313#COV=-fprofile-arcs -ftest-coverage 
    1414 
    1515WARNINGS=-Wno-deprecated -Wstrict-aliasing 
    1616 
    1717#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) 
    1818GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 
    1919 
    2020CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_LINUX=1 -D_DH 
    2121MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_LINUX=1 -D_DH 
    2222 
    2323CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    2424    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    2525TOTALH= 
    2626 
    2727DMD_OBJS = \ 
    2828    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    29     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     29    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    3030    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    3131    constfold.o irstate.o dchar.o cond.o debug.o \ 
    3232    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    3333    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    3434    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    3535    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    3636    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    3737    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    3838    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    3939    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    4040    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    4141    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    4242    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    4343    builtin.o clone.o aliasthis.o \ 
    4444    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    4545    imphint.o \ 
    4646    libelf.o elfobj.o 
    4747 
    4848SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    4949    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • trunk/src/osx.mak

    r532 r577  
    1515 
    1616#OPT=-g -g3 
    1717#OPT=-O2 
    1818 
    1919#COV=-fprofile-arcs -ftest-coverage 
    2020 
    2121WARNINGS=-Wno-deprecated -Wstrict-aliasing 
    2222 
    2323#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) 
    2424GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 
    2525 
    2626CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_OSX=1 -D_DH 
    2727MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_OSX=1 -D_DH 
    2828 
    2929CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    3030    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    3131TOTALH= 
    3232 
    3333DMD_OBJS = \ 
    3434    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    35     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     35    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    3636    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    3737    constfold.o irstate.o dchar.o cond.o debug.o \ 
    3838    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    3939    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    4040    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    4141    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    4242    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    4343    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    4444    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    4545    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    4646    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    4747    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    4848    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    4949    builtin.o clone.o aliasthis.o \ 
    5050    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    5151    imphint.o \ 
    5252    libmach.o machobj.o 
    5353 
    5454SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    5555    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \ 
  • trunk/src/solaris.mak

    r473 r577  
    55 
    66CC=g++ -m32 
    77 
    88#OPT=-g -g3 
    99#OPT=-O2 
    1010 
    1111#COV=-fprofile-arcs -ftest-coverage 
    1212 
    1313#GFLAGS = -Wno-deprecated -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 $(COV) 
    1414GFLAGS = -Wno-deprecated -D__near= -D__pascal= -fno-exceptions -O2 
    1515 
    1616CFLAGS = $(GFLAGS) -I$(ROOT) -D__I86__=1 -DMARS=1 -DTARGET_SOLARIS=1 -D_DH 
    1717MFLAGS = $(GFLAGS) -I$C -I$(TK) -D__I86__=1 -DMARS=1 -DTARGET_SOLARIS=1 -D_DH 
    1818 
    1919CH= $C/cc.h $C/global.h $C/parser.h $C/oper.h $C/code.h $C/type.h \ 
    2020    $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h 
    2121TOTALH= 
    2222 
    2323DMD_OBJS = \ 
    2424    access.o array.o attrib.o bcomplex.o bit.o blockopt.o \ 
    25     cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgcv.o cgelem.o cgen.o \ 
     25    cast.o code.o cg.o cg87.o cgcod.o cgcs.o cgelem.o cgen.o \ 
    2626    cgreg.o cgsched.o class.o cod1.o cod2.o cod3.o cod4.o cod5.o \ 
    2727    constfold.o irstate.o dchar.o cond.o debug.o \ 
    2828    declaration.o dsymbol.o dt.o dump.o e2ir.o ee.o eh.o el.o \ 
    2929    dwarf.o enum.o evalu8.o expression.o func.o gdag.o gflow.o \ 
    3030    glocal.o gloop.o glue.o gnuc.o go.o gother.o html.o iasm.o id.o \ 
    3131    identifier.o impcnvtab.o import.o inifile.o init.o inline.o \ 
    3232    lexer.o link.o lstring.o mangle.o mars.o rmem.o module.o msc.o mtype.o \ 
    3333    nteh.o cppmangle.o opover.o optimize.o os.o out.o outbuf.o \ 
    3434    parse.o ph.o ptrntab.o root.o rtlsym.o s2ir.o scope.o statement.o \ 
    3535    stringtable.o struct.o csymbol.o template.o tk.o tocsym.o todt.o \ 
    3636    type.o typinf.o util.o var.o version.o strtold.o utf.o staticassert.o \ 
    3737    unialpha.o toobj.o toctype.o toelfdebug.o entity.o doc.o macro.o \ 
    3838    hdrgen.o delegatize.o aa.o ti_achar.o toir.o interpret.o traits.o \ 
    3939    builtin.o clone.o aliasthis.o \ 
    4040    man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \ 
    4141    imphint.o \ 
    4242    libelf.o elfobj.o 
    4343 
    4444SRC = win32.mak linux.mak osx.mak freebsd.mak solaris.mak \ 
    4545    mars.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c \