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

Changeset 581

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

64 bit pic and tls

Files:

Legend:

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

    r580 r581  
    13271327                s->Sclass == SCparameter) 
    13281328            {   refparam = TRUE; 
    13291329                reflocal = TRUE;        // kludge to set up prolog 
    13301330            } 
    13311331            pcs->Irm = modregrm(3,0,s->Sreglsw & 7); 
    13321332            if (s->Sreglsw & 8) 
    13331333                pcs->Irex |= REX_B; 
    13341334            if (e->EV.sp.Voffset == 1 && sz == 1) 
    13351335            {   assert(s->Sregm & BYTEREGS); 
    13361336                assert(s->Sreglsw < 4); 
    13371337                pcs->Irm |= 4;                  // use 2nd byte of register 
    13381338            } 
    13391339            else 
    13401340                assert(!e->EV.sp.Voffset); 
    13411341        } 
    13421342        else if (s->ty() & mTYcs && !(fl == FLextern && LARGECODE)) 
    13431343        { 
    13441344            pcs->Iflags |= CFcs | CFoff; 
    13451345        } 
    13461346#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    1347 //      if (fl == FLtlsdata || s->ty() & mTYthread) 
    1348 //          pcs->Iflags |= CFgs; 
     1347        if (I64 && config.flags3 & CFG3pic && 
     1348            (fl == FLtlsdata || s->ty() & mTYthread)) 
     1349        { 
     1350            pcs->Iflags |= CFopsize; 
     1351            pcs->Irex = 0x48; 
     1352        } 
    13491353#endif 
    13501354        pcs->IEVsym1 = s; 
    13511355        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    13521356        if (sz == 1) 
    13531357        {   /* Don't use SI or DI for this variable     */ 
    13541358            s->Sflags |= GTbyte; 
    13551359            if (e->EV.sp.Voffset > 1) 
    13561360                s->Sflags &= ~GTregcand; 
    13571361        } 
    13581362        else if (e->EV.sp.Voffset) 
    13591363            s->Sflags &= ~GTregcand; 
    13601364        if (!(keepmsk & RMstore))               // if not store only 
    13611365        {   s->Sflags |= SFLread;               // assume we are doing a read 
    13621366        } 
    13631367        break; 
    13641368    case FLpseudo: 
    13651369#if MARS 
    13661370        assert(0); 
    13671371#else 
    13681372    { 
     
    26762680                goto LF1; 
    26772681            else 
    26782682                goto LF2; 
    26792683        } 
    26802684        else 
    26812685        {   int fl; 
    26822686 
    26832687            fl = FLfunc; 
    26842688            if (!tyfunc(s->ty())) 
    26852689                fl = el_fl(e1); 
    26862690            if (tym1 == TYifunc) 
    26872691                c1 = gen1(c1,0x9C);                             // PUSHF 
    26882692#if 0 && TARGET_LINUX 
    26892693            if (s->Sfl == FLgot || s->Sfl == FLgotoff) 
    26902694                fl = s->Sfl; 
    26912695#endif 
    26922696            ce = gencs(CNIL,farfunc ? 0x9A : 0xE8,0,fl,s);      // CALL extern 
    26932697            ce->Iflags |= farfunc ? (CFseg | CFoff) : (CFselfrel | CFoff); 
    26942698#if TARGET_LINUX 
    26952699            if (s == tls_get_addr_sym) 
    2696             {   /* Append a NOP so GNU linker has patch room 
    2697                  */ 
    2698                 ce = gen1(ce, 0x90);            // NOP 
    2699                 code_orflag(ce, CFvolatile);    // don't schedule it 
     2700            { 
     2701                if (I32) 
     2702                { 
     2703                    /* Append a NOP so GNU linker has patch room 
     2704                     */ 
     2705                    ce = gen1(ce, 0x90);        // NOP 
     2706                    code_orflag(ce, CFvolatile);    // don't schedule it 
     2707                } 
     2708                else 
     2709                {   /* Prepend 66 66 48 so GNU linker has patch room 
     2710                     */ 
     2711                    assert(I64); 
     2712                    ce->Irex = REX | REX_W; 
     2713                    ce = cat(gen1(CNIL, 0x66), ce); 
     2714                    ce = cat(gen1(CNIL, 0x66), ce); 
     2715                } 
    27002716            } 
    27012717#endif 
    27022718        } 
    27032719        ce = cat(c1,ce); 
    27042720  } 
    27052721  else 
    27062722  {     /* Call function via pointer    */ 
    27072723        elem *e11; 
    27082724        tym_t e11ty; 
    27092725 
    27102726#ifdef DEBUG 
    27112727        if (e1->Eoper != OPind 
    27122728                ) { WRFL((enum FL)el_fl(e1)); WROP(e1->Eoper); } 
    27132729#endif 
    27142730        c = save87();                   // assume 8087 regs are all trashed 
    27152731        assert(e1->Eoper == OPind); 
    27162732        e11 = e1->E1; 
    27172733        e11ty = tybasic(e11->Ety); 
    27182734        assert(!I16 || (e11ty == (farfunc ? TYfptr : TYnptr))); 
    27192735 
  • branches/dmd-1.x/src/backend/cod2.c

    r579 r581  
    37363736{ code cs; 
    37373737  code *c; 
    37383738 
    37393739  cs.Iflags = 0; 
    37403740  unsigned char rex = 0; 
    37413741  cs.Irex = rex; 
    37423742  assert(e->Eoper == OPvar || e->Eoper == OPrelconst); 
    37433743  enum FL fl = el_fl(e); 
    37443744  switch (fl) 
    37453745  { 
    37463746    case FLdatseg: 
    37473747        cs.IEV2._EP.Vpointer = e->EV.Vpointer; 
    37483748        goto L3; 
    37493749 
    37503750    case FLfardata: 
    37513751        assert(!TARGET_FLAT); 
    37523752        goto L4; 
    37533753 
    37543754    case FLtlsdata: 
    37553755#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    3756     {   /* Generate: 
     3756    { 
     3757      L5: 
     3758        if (I64 && config.flags3 & CFG3pic) 
     3759        { 
     3760            /* Generate: 
     3761             *   LEA DI,s@TLSGD[RIP] 
     3762             */ 
     3763            assert(reg == DI); 
     3764            code css; 
     3765            css.Irex = REX | REX_W; 
     3766            css.Iop = 0x8D;             // LEA 
     3767            css.Irm = modregrm(0,DI,5); 
     3768            css.Iflags = CFopsize; 
     3769            css.IFL1 = fl; 
     3770            css.IEVsym1 = e->EV.sp.Vsym; 
     3771            css.IEVoffset1 = e->EV.sp.Voffset; 
     3772            c = gen(NULL, &css); 
     3773            return c; 
     3774        } 
     3775        /* Generate: 
    37573776         *      MOV reg,GS:[00000000] 
    37583777         *      ADD reg, offset s@TLS_LE 
    37593778         * for locals, and for globals: 
    37603779         *      MOV reg,GS:[00000000] 
    37613780         *      ADD reg, s@TLS_IE 
    37623781         * note different fixup 
    37633782         */ 
    3764       L5: 
    37653783        int stack = 0; 
    37663784        c = NULL; 
    37673785        if (reg == STACK) 
    37683786        {   regm_t retregs = ALLREGS; 
    37693787 
    37703788            c = allocreg(&retregs,&reg,TYoffset); 
    37713789            reg = findreg(retregs); 
    37723790            stack = 1; 
    37733791        } 
    37743792 
    37753793        code css; 
    37763794        css.Irex = rex; 
    37773795        css.Iop = 0x8B; 
    37783796        css.Irm = modregrm(0, 0, BPRM); 
    37793797        code_newreg(&css, reg); 
    37803798        css.Iflags = CFgs; 
    37813799        css.IFL1 = FLconst; 
    37823800        css.IEV1.Vuns = 0; 
    37833801        c = gen(c, &css);               // MOV reg,GS:[00000000] 
    37843802 
  • branches/dmd-1.x/src/backend/cod3.c

    r580 r581  
    1919#include        "cc.h" 
    2020#include        "el.h" 
    2121#include        "code.h" 
    2222#include        "oper.h" 
    2323#include        "global.h" 
    2424#include        "type.h" 
    2525#include        "parser.h" 
    2626#if SCPP 
    2727#include        "cpp.h" 
    2828#include        "exh.h" 
    2929#endif 
    3030 
    3131static char __file__[] = __FILE__;      /* for tassert.h                */ 
    3232#include        "tassert.h" 
    3333 
    3434#if MARS 
    3535#define tstrace NULL 
    3636#endif 
    3737 
    3838extern targ_size_t retsize; 
     39STATIC void pinholeopt_unittest(); 
    3940STATIC void do8bit (enum FL,union evc *); 
    4041STATIC void do16bit (enum FL,union evc *,int); 
    4142STATIC void do32bit (enum FL,union evc *,int); 
    4243STATIC void do64bit (enum FL,union evc *,int); 
    4344 
    4445static int hasframe;            /* !=0 if this function has a stack frame */ 
    4546static targ_size_t Foff;        // BP offset of floating register 
    4647static targ_size_t CSoff;       // offset of common sub expressions 
    4748static targ_size_t NDPoff;      // offset of saved 8087 registers 
    4849int BPoff;                      // offset from BP 
    4950static int EBPtoESP;            // add to EBP offset to get ESP offset 
    5051static int AAoff;               // offset of alloca temporary 
    5152 
    5253#if ELFOBJ || MACHOBJ 
    5354#define JMPSEG  CDATA 
    5455#define JMPOFF  CDoffset 
    5556#else 
    5657#define JMPSEG  DATA 
    5758#define JMPOFF  Doffset 
    5859#endif 
     
    28932894    return offset; 
    28942895} 
    28952896 
    28962897 
    28972898 
    28982899/******************************* 
    28992900 * Find shorter versions of the same instructions. 
    29002901 * Does these optimizations: 
    29012902 *      replaces jmps to the next instruction with NOPs 
    29022903 *      sign extension of modregrm displacement 
    29032904 *      sign extension of immediate data (can't do it for OR, AND, XOR 
    29042905 *              as the opcodes are not defined) 
    29052906 *      short versions for AX EA 
    29062907 *      short versions for reg EA 
    29072908 * Input: 
    29082909 *      b -> block for code (or NULL) 
    29092910 */ 
    29102911 
    29112912void pinholeopt(code *c,block *b) 
    29122913{ targ_size_t a; 
    2913   unsigned op,mod,rm,reg,ereg
     2914  unsigned op,mod
    29142915  unsigned char ins; 
    29152916  int usespace; 
    29162917  int useopsize; 
    29172918  int space; 
    29182919  block *bn; 
     2920 
     2921#ifdef DEBUG 
     2922    static int tested; if (!tested) { tested++; pinholeopt_unittest(); } 
     2923#endif 
    29192924 
    29202925#if 0 
    29212926  code *cstart = c; 
    29222927  if (debugc) 
    29232928  { 
    29242929      printf("+pinholeopt(%p)\n",c); 
    29252930  } 
    29262931#endif 
    29272932 
    29282933  if (b) 
    29292934  {     bn = b->Bnext; 
    29302935        usespace = (config.flags4 & CFG4space && b->BC != BCasm); 
    29312936        useopsize = (I16 || (config.flags4 & CFG4space && b->BC != BCasm)); 
    29322937  } 
    29332938  else 
    29342939  {     bn = NULL; 
    29352940        usespace = (config.flags4 & CFG4space); 
    29362941        useopsize = (I16 || config.flags4 & CFG4space); 
    29372942  } 
    29382943  for (; c; c = code_next(c)) 
    29392944  { 
    29402945    L1: 
    29412946        op = c->Iop; 
    29422947        if (op == 0x0F) 
    29432948            ins = inssize2[c->Iop2]; 
    29442949        else 
    29452950            ins = inssize[c->Iop]; 
    2946         if (!I64 && ins & M)            // if modregrm byte 
    2947         {   int longop = (c->Iflags & CFopsize) ? I16 : I32
     2951        if (ins & M)            // if modregrm byte 
     2952        {   int shortop = (c->Iflags & CFopsize) ? !I16 : I16
    29482953            int local_BPRM = BPRM; 
    29492954 
    29502955            if (c->Iflags & CFaddrsize) 
    29512956                local_BPRM ^= 5 ^ 6;    // toggle between 5 and 6 
    29522957 
    2953             rm = c->Irm; 
    2954             reg = rm & (7<<3);          // isolate reg field 
    2955             ereg = rm & 7; 
     2958            unsigned rm = c->Irm; 
     2959            unsigned reg = rm & modregrm(0,7,0);          // isolate reg field 
     2960            unsigned ereg = rm & 7; 
     2961            //printf("c = %p, op = %02x rm = %02x\n", c, op, rm); 
    29562962 
    29572963            /* If immediate second operand      */ 
    29582964            if ((ins & T || op == 0xF6 || op == 0xF7) && 
    29592965                c->IFL2 == FLconst) 
    2960             {   int flags; 
    2961                 targ_long u; 
    2962  
    2963                 flags = c->Iflags & CFpsw;      /* if want result in flags */ 
    2964                 u = c->IEV2.Vuns; 
     2966            { 
     2967                int flags = c->Iflags & CFpsw;      /* if want result in flags */ 
     2968                targ_long u = c->IEV2.Vuns; 
    29652969                if (ins & E) 
    29662970                    u = (signed char) u; 
    2967                 else if (!longop) 
     2971                else if (shortop) 
    29682972                    u = (short) u; 
    29692973 
    29702974                // Replace CMP reg,0 with TEST reg,reg 
    2971                 if ((op & 0xFE) == 0x80 && 
     2975                if ((op & 0xFE) == 0x80 &&              // 80 is CMP R8,imm8; 81 is CMP reg,imm 
    29722976                    rm >= modregrm(3,7,AX) && 
    29732977                    u == 0) 
    29742978                {       c->Iop = (op & 1) | 0x84; 
    29752979                        c->Irm = modregrm(3,ereg,ereg); 
     2980                        if (c->Irex & REX_B) 
     2981                            c->Irex |= REX_R; 
    29762982                        goto L1; 
    29772983                } 
    29782984 
    29792985                /* Optimize ANDs with an immediate constant             */ 
    29802986                if ((op == 0x81 || op == 0x80) && reg == modregrm(0,4,0)) 
    29812987                { 
    2982                     if (rm >= modregrm(3,4,AX)) 
     2988                    if (rm >= modregrm(3,4,AX))         // AND reg,imm 
    29832989                    { 
    29842990                        if (u == 0) 
    29852991                        {       /* Replace with XOR reg,reg     */ 
    29862992                                c->Iop = 0x30 | (op & 1); 
    2987                                 NEWREG(c->Irm,rm & 7); 
     2993                                c->Irm = modregrm(3,ereg,ereg); 
     2994                                if (c->Irex & REX_B) 
     2995                                    c->Irex |= REX_R; 
    29882996                                goto L1; 
    29892997                        } 
    29902998                        if (u == 0xFFFFFFFF && !flags) 
    29912999                        {       c->Iop = NOP; 
    29923000                                goto L1; 
    29933001                        } 
    29943002                    } 
    29953003                    if (op == 0x81 && !flags) 
    29963004                    {   // If we can do the operation in one byte 
    29973005 
    29983006                        // If EA is not SI or DI 
    2999                         if (rm < modregrm(3,4,SP) && 
     3007                        if ((rm < modregrm(3,4,SP) || I64) && 
    30003008                            (config.flags4 & CFG4space || 
    30013009                             config.target_cpu < TARGET_PentiumPro) 
    30023010                           ) 
    30033011                        { 
    30043012                            if ((u & 0xFFFFFF00) == 0xFFFFFF00) 
    30053013                                goto L2; 
    3006                             else 
    3007                             {   if (longop) 
     3014                            else if (rm < modregrm(3,0,0) || (!c->Irex && ereg < 4)) 
     3015                            {   if (!shortop) 
    30083016                                {   if ((u & 0xFFFF00FF) == 0xFFFF00FF) 
    30093017                                        goto L3; 
    30103018                                } 
    30113019                                else 
    30123020                                { 
    30133021                                    if ((u & 0xFF) == 0xFF) 
    30143022                                        goto L3; 
    30153023                                } 
    30163024                            } 
    30173025                        } 
    3018                         if (longop && useopsize) 
     3026                        if (!shortop && useopsize) 
    30193027                        { 
    30203028                            if ((u & 0xFFFF0000) == 0xFFFF0000) 
    30213029                            {   c->Iflags ^= CFopsize; 
    30223030                                goto L1; 
    30233031                            } 
    30243032                            if ((u & 0xFFFF) == 0xFFFF && rm < modregrm(3,4,AX)) 
    30253033                            {   c->IEVoffset1 += 2; /* address MSW      */ 
    30263034                                c->IEV2.Vuns >>= 16; 
    30273035                                c->Iflags ^= CFopsize; 
    30283036                                goto L1; 
    30293037                            } 
    30303038                            if (rm >= modregrm(3,4,AX)) 
    30313039                            { 
    3032                                 if (u == 0xFF && rm <= modregrm(3,4,BX)) 
     3040                                if (u == 0xFF && (rm <= modregrm(3,4,BX) || I64)) 
    30333041                                {   c->Iop2 = 0xB6;     /* MOVZX        */ 
    30343042                                    c->Iop = 0x0F; 
    3035                                     NEWREG(c->Irm,rm & 7); 
     3043                                    c->Irm = modregrm(3,ereg,ereg); 
     3044                                    if (c->Irex & REX_B) 
     3045                                        c->Irex |= REX_R; 
    30363046                                    goto L1; 
    30373047                                } 
    30383048                                if (u == 0xFFFF) 
    30393049                                {   c->Iop2 = 0xB7;     /* MOVZX        */ 
    30403050                                    c->Iop = 0x0F; 
    3041                                     NEWREG(c->Irm,rm & 7); 
     3051                                    c->Irm = modregrm(3,ereg,ereg); 
     3052                                    if (c->Irex & REX_B) 
     3053                                        c->Irex |= REX_R; 
    30423054                                    goto L1; 
    30433055                                } 
    30443056                            } 
    30453057                        } 
    30463058                    } 
    30473059                } 
    30483060 
    30493061                /* Look for ADD,OR,SUB,XOR with u that we can eliminate */ 
    30503062                if (!flags && 
    30513063                    (op == 0x81 || op == 0x80) && 
    3052                     (reg == modregrm(0,0,0) || reg == modregrm(0,1,0) || 
    3053                      reg == modregrm(0,5,0) || reg == modregrm(0,6,0)) 
     3064                    (reg == modregrm(0,0,0) || reg == modregrm(0,1,0) ||  // ADD,OR 
     3065                     reg == modregrm(0,5,0) || reg == modregrm(0,6,0))    // SUB, XOR 
    30543066                   ) 
    3055                 {       if (u == 0) 
     3067                { 
     3068                        if (u == 0) 
    30563069                        { 
    30573070                                c->Iop = NOP; 
    30583071                                goto L1; 
    30593072                        } 
    30603073                        if (u == ~0 && reg == modregrm(0,6,0))  /* XOR  */ 
    30613074                        { 
    30623075                                c->Iop = 0xF6 | (op & 1);       /* NOT  */ 
    30633076                                c->Irm ^= modregrm(0,6^2,0); 
    30643077                                goto L1; 
    30653078                        } 
    3066                         if (longop && 
     3079                        if (!shortop && 
    30673080                            useopsize && 
    30683081                            op == 0x81 && 
    30693082                            (u & 0xFFFF0000) == 0 && 
    30703083                            (reg == modregrm(0,6,0) || reg == modregrm(0,1,0))) 
    30713084                        {    c->Iflags ^= CFopsize; 
    30723085                             goto L1; 
    30733086                        } 
    30743087                } 
    30753088 
    30763089                /* Look for TEST or OR or XOR with an immediate constant */ 
    30773090                /* that we can replace with a byte operation            */ 
    30783091                if (op == 0xF7 && reg == modregrm(0,0,0) || 
    30793092                    op == 0x81 && reg == modregrm(0,6,0) && !flags || 
    30803093                    op == 0x81 && reg == modregrm(0,1,0)) 
    30813094                { 
    30823095                    // See if we can replace a dword with a word 
    30833096                    // (avoid for 32 bit instructions, because CFopsize 
    30843097                    //  is too slow) 
    3085                     if (longop && useopsize) 
     3098                    if (!shortop && useopsize) 
    30863099                    {   if ((u & 0xFFFF0000) == 0) 
    30873100                        {   c->Iflags ^= CFopsize; 
    30883101                            goto L1; 
    30893102                        } 
    30903103                        /* If memory (not register) addressing mode     */ 
    30913104                        if ((u & 0xFFFF) == 0 && rm < modregrm(3,0,AX)) 
    30923105                        {   c->IEVoffset1 += 2; /* address MSW  */ 
    30933106                            c->IEV2.Vuns >>= 16; 
    30943107                            c->Iflags ^= CFopsize; 
    30953108                            goto L1; 
    30963109                        } 
    30973110                    } 
    30983111 
    30993112                    // If EA is not SI or DI 
    31003113                    if (rm < (modregrm(3,0,SP) | reg) && 
    31013114                        (usespace || 
    31023115                         config.target_cpu < TARGET_PentiumPro) 
    31033116                       ) 
    31043117                    { 
    31053118                        if ((u & 0xFFFFFF00) == 0) 
    31063119                        { 
    31073120                        L2: c->Iop--;           /* to byte instruction  */ 
    31083121                            c->Iflags &= ~CFopsize; 
    31093122                            goto L1; 
    31103123                        } 
    3111                         if ((u & 0xFFFF00FF) == 0 || 
    3112                             (!longop && (u & 0xFF) == 0)) 
     3124                        if (((u & 0xFFFF00FF) == 0 || 
     3125                             (shortop && (u & 0xFF) == 0)) && 
     3126                            (rm < modregrm(3,0,0) || (!c->Irex && ereg < 4))) 
    31133127                        { 
    31143128                        L3: 
    31153129                            c->IEV2.Vuns >>= 8; 
    31163130                            if (rm >= (modregrm(3,0,AX) | reg)) 
    31173131                                c->Irm |= 4;    /* AX->AH, BX->BH, etc. */ 
    31183132                            else 
    31193133                                c->IEVoffset1 += 1; 
    31203134                            goto L2; 
    31213135                        } 
    31223136                    } 
    31233137#if 0 
    31243138                    // BUG: which is right? 
    31253139                    else if ((u & 0xFFFF0000) == 0) 
    31263140#else 
    31273141                    else if (0 && op == 0xF7 && 
    31283142                             rm >= modregrm(3,0,SP) && 
    31293143                             (u & 0xFFFF0000) == 0) 
    31303144#endif 
    31313145                        c->Iflags &= ~CFopsize; 
    31323146                } 
    31333147 
    31343148                // Try to replace TEST reg,-1 with TEST reg,reg 
    3135                 if (op == 0xF6 && rm >= modregrm(3,0,AX)) 
    3136                 {       if (u == ~0
     3149                if (op == 0xF6 && rm >= modregrm(3,0,AX) && rm <= modregrm(3,0,7)) // TEST regL,immed8 
     3150                {       if ((u & 0xFF) == 0xFF
    31373151                        { 
    31383152                           L4:  c->Iop = 0x84;          // TEST regL,regL 
    3139                                 c->Irm |= ereg << 3; 
     3153                                c->Irm = modregrm(3,ereg,ereg); 
     3154                                if (c->Irex & REX_B) 
     3155                                    c->Irex |= REX_R; 
    31403156                                c->Iflags &= ~CFopsize; 
    31413157                                goto L1; 
    31423158                        } 
    31433159                } 
    3144                 if (op == 0xF7 && rm >= modregrm(3,0,AX) && ereg < SP
     3160                if (op == 0xF7 && rm >= modregrm(3,0,AX) && rm <= modregrm(3,0,7) && (I64 || ereg < 4)
    31453161                {       if (u == 0xFF) 
    31463162                                goto L4; 
    3147                         if (u == ~0xFF && !longop
    3148                         {       rm |= 4;                /* to regH      */ 
     3163                        if ((u & 0xFFFF) == 0xFF00 && shortop && !c->Irex && ereg < 4
     3164                        {       ereg |= 4;                /* to regH      */ 
    31493165                                goto L4; 
    31503166                        } 
    31513167                } 
    31523168 
    31533169                /* Look for sign extended immediate data */ 
    31543170                if ((signed char) u == u) 
    31553171                { 
    31563172                    if (op == 0x81) 
    31573173                    {   if (reg != 0x08 && reg != 0x20 && reg != 0x30) 
    31583174                            c->Iop = op = 0x83;         /* 8 bit sgn ext */ 
    31593175                    } 
    31603176                    else if (op == 0x69)                /* IMUL rw,ew,dw */ 
    31613177                        c->Iop = op = 0x6B;             /* IMUL rw,ew,db */ 
    31623178                } 
    31633179 
    31643180                // Look for SHIFT EA,imm8 we can replace with short form 
    31653181                if (u == 1 && ((op & 0xFE) == 0xC0)) 
    31663182                    c->Iop |= 0xD0; 
    31673183 
    31683184            } /* if immediate second operand */ 
    31693185 
    31703186            /* Look for AX short form */ 
    31713187            if (ins & A) 
    3172             {   if (rm == modregrm(0,AX,local_BPRM) && (op & ~3) == 0x88) 
     3188            {   if (rm == modregrm(0,AX,local_BPRM) && 
     3189                    !(c->Irex & REX_R) &&               // and it's AX, not R8 
     3190                    (op & ~3) == 0x88 && 
     3191                    !I64) 
    31733192                {       op = ((op & 3) + 0xA0) ^ 2; 
    31743193                        /* 8A-> A0 */ 
    31753194                        /* 8B-> A1 */ 
    31763195                        /* 88-> A2 */ 
    31773196                        /* 89-> A3 */ 
    31783197                        c->Iop = op; 
    31793198                        c->IFL2 = c->IFL1; 
    31803199                        c->IEV2 = c->IEV1; 
    31813200                } 
    31823201 
    31833202                /* Replace MOV REG1,REG2 with MOV EREG1,EREG2   */ 
    3184                 else if (I32 && 
     3203                else if (!I16 && 
    31853204                         (op == 0x89 || op == 0x8B) && 
    31863205                         (rm & 0xC0) == 0xC0 && 
    31873206                         (!b || b->BC != BCasm) 
    31883207                        ) 
    31893208                    c->Iflags &= ~CFopsize; 
    31903209 
    3191                 else if ((rm & 0xC7) == 0xC0) 
     3210                // If rm is AX 
     3211                else if ((rm & modregrm(3,0,7)) == modregrm(3,0,AX) && !(c->Irex & (REX_R | REX_B))) 
    31923212                {       switch (op) 
    31933213                        {   case 0x80:  op = reg | 4; break; 
    31943214                            case 0x81:  op = reg | 5; break; 
    3195                             case 0x87:  op = 0x90 + (reg>>3); break; 
     3215                            case 0x87:  op = 0x90 + (reg>>3); break;    // XCHG 
    31963216                            case 0xF6: 
    31973217                                if (reg == 0) 
    31983218                                    op = 0xA8;  /* TEST AL,immed8       */ 
    31993219                                break; 
    32003220                            case 0xF7: 
    32013221                                if (reg == 0) 
    32023222                                    op = 0xA9;  /* TEST AX,immed16      */ 
    32033223                                break; 
    32043224                        } 
    32053225                        c->Iop = op; 
    32063226                } 
    32073227            } 
    32083228 
    32093229            /* Look for reg short form */ 
    32103230            if ((ins & R) && (rm & 0xC0) == 0xC0) 
    32113231            {   switch (op) 
    32123232                {   case 0xC6:  op = 0xB0 + ereg; break; 
    32133233                    case 0xC7:  op = 0xB8 + ereg; break; 
    32143234                    case 0xFF: 
    32153235                        switch (reg) 
    32163236                        {   case 6<<3: op = 0x50+ereg; break;/* PUSH*/ 
    3217                             case 0<<3: op = 0x40+ereg; break; /* INC*/ 
    3218                             case 1<<3: op = 0x48+ereg; break; /* DEC*/ 
     3237                            case 0<<3: if (!I64) op = 0x40+ereg; break; /* INC*/ 
     3238                            case 1<<3: if (!I64) op = 0x48+ereg; break; /* DEC*/ 
    32193239                        } 
    32203240                        break; 
    32213241                    case 0x8F:  op = 0x58 + ereg; break; 
    32223242                    case 0x87: 
    32233243                        if (reg == 0) op = 0x90 + ereg; 
    32243244                        break; 
    32253245                } 
    32263246                c->Iop = op; 
    32273247            } 
    32283248 
    32293249            // Look to replace SHL reg,1 with ADD reg,reg 
    32303250            if ((op & 0xFE) == 0xD0 && 
    32313251                     (rm & modregrm(3,7,0)) == modregrm(3,4,0) && 
    32323252                     config.target_cpu >= TARGET_80486) 
    32333253            { 
    32343254                c->Iop &= 1; 
    32353255                c->Irm = (rm & modregrm(3,0,7)) | (ereg << 3); 
    3236                 if (!(c->Iflags & CFpsw) && I32) 
     3256                if (c->Irex & REX_B) 
     3257                    c->Irex |= REX_R; 
     3258                if (!(c->Iflags & CFpsw) && !I16) 
    32373259                    c->Iflags &= ~CFopsize; 
    32383260                goto L1; 
    32393261            } 
    32403262 
    32413263            /* Look for sign extended modregrm displacement, or 0 
    32423264             * displacement. 
    32433265             */ 
    32443266 
    32453267            if (((rm & 0xC0) == 0x80) && // it's a 16/32 bit disp 
    32463268                c->IFL1 == FLconst)      // and it's a constant 
    32473269            { 
    32483270                a = c->IEVpointer1; 
    3249                 if (a == 0 && (rm & 7) != local_BPRM &&         // if 0 disp 
    3250                     !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP
     3271                if (a == 0 && (rm & 7) != local_BPRM &&         // if 0[disp] 
     3272                    !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP && !(c->Irex & REX_B)
    32513273                   ) 
    32523274                    c->Irm &= 0x3F; 
    3253                 else if (I32
     3275                else if (!I16
    32543276                { 
    32553277                    if ((targ_size_t)(targ_schar)a == a) 
    32563278                        c->Irm ^= 0xC0;                 /* do 8 sx      */ 
    32573279                } 
    32583280                else if (((targ_size_t)(targ_schar)a & 0xFFFF) == (a & 0xFFFF)) 
    32593281                    c->Irm ^= 0xC0;                     /* do 8 sx      */ 
    32603282            } 
    32613283 
    32623284            /* Look for LEA reg,[ireg], replace with MOV reg,ireg       */ 
    32633285            else if (op == 0x8D) 
    32643286            {   rm = c->Irm & 7; 
    32653287                mod = c->Irm & modregrm(3,0,0); 
    32663288                if (mod == 0) 
    32673289                { 
    3268                     if (I32
     3290                    if (!I16
    32693291                    { 
    32703292                        switch (rm) 
    32713293                        { 
    32723294                            case 4: 
    32733295                            case 5: 
    32743296                                break; 
    32753297                            default: 
    32763298                                c->Irm |= modregrm(3,0,0); 
    32773299                                c->Iop = 0x8B; 
    32783300                                break; 
    32793301                        } 
    32803302                    } 
    32813303                    else 
    32823304                    { 
    32833305                        switch (rm) 
    32843306                        { 
    32853307                            case 4:     rm = modregrm(3,0,SI);  goto L6; 
    32863308                            case 5:     rm = modregrm(3,0,DI);  goto L6; 
    32873309                            case 7:     rm = modregrm(3,0,BX);  goto L6; 
    32883310                            L6:     c->Irm = rm + reg; 
    32893311                                    c->Iop = 0x8B; 
    32903312                                    break; 
    32913313                        } 
    32923314                    } 
    32933315                } 
    32943316 
    32953317                /* replace LEA reg,0[BP] with MOV reg,BP        */ 
    32963318                else if (mod == modregrm(1,0,0) && rm == local_BPRM && 
    32973319                        c->IFL1 == FLconst && c->IEVpointer1 == 0) 
    32983320                {       c->Iop = 0x8B;          /* MOV reg,BP   */ 
    32993321                        c->Irm = modregrm(3,0,BP) + reg; 
    33003322                } 
     3323            } 
     3324 
     3325            // Replace [R13] with 0[R13] 
     3326            if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 
     3327            { 
     3328                c->Irm |= modregrm(1,0,0); 
     3329                c->IFL1 = FLconst; 
     3330                c->IEVpointer1 = 0; 
    33013331            } 
    33023332        } 
    33033333        else 
    33043334        { 
    33053335            switch (op) 
    33063336            { 
    33073337                default: 
    33083338                    if ((op & 0xF0) != 0x70) 
    33093339                        break; 
    33103340                case JMP: 
    33113341                    switch (c->IFL2) 
    33123342                    {   case FLcode: 
    33133343                                if (c->IEV2.Vcode == code_next(c)) 
    33143344                                {       c->Iop = NOP; 
    33153345                                        continue; 
    33163346                                } 
    33173347                                break; 
    33183348                        case FLblock: 
    33193349                                if (!code_next(c) && c->IEV2.Vblock == bn) 
    33203350                                {       c->Iop = NOP; 
    33213351                                        continue; 
    33223352                                } 
    33233353                                break; 
    33243354                        case FLconst: 
    33253355                        case FLfunc: 
    33263356                        case FLextern: 
    33273357                                break; 
    33283358                        default: 
    33293359#ifdef DEBUG 
    33303360                                WRFL((enum FL)c->IFL2); 
    33313361#endif 
    33323362                                assert(0); 
    33333363                    } 
    33343364                    break; 
    33353365 
    33363366                case 0x68:                      // PUSH immed16 
    33373367                    if (c->IFL2 == FLconst) 
    3338                     {   targ_long u; 
    3339  
    3340                         u = c->IEV2.Vuns; 
    3341                         if ((c->Iflags & CFopsize) ? !I32 : I32) 
    3342                         {   if (u == (signed char) u) 
     3368                    { 
     3369                        targ_long u = c->IEV2.Vuns; 
     3370                        if (I64 || 
     3371                            ((c->Iflags & CFopsize) ? I16 : I32)) 
     3372                        {   // PUSH 32/64 bit operand 
     3373                            if (u == (signed char) u) 
    33433374                                c->Iop = 0x6A;          // PUSH immed8 
    33443375                        } 
    3345                         else 
     3376                        else // PUSH 16 bit operand 
    33463377                        {   if ((short)u == (signed char) u) 
    33473378                                c->Iop = 0x6A;          // PUSH immed8 
    33483379                        } 
    33493380                    } 
    33503381                    break; 
    33513382            } 
    33523383        } 
    33533384  } 
    33543385#if 0 
    33553386  if (1 || debugc) { 
    33563387      printf("-pinholeopt(%p)\n",cstart); 
    33573388        for (c = cstart; c; c = code_next(c)) 
    33583389            c->print(); 
    33593390  } 
    33603391#endif 
    33613392} 
    33623393 
     3394#ifdef DEBUG 
     3395STATIC void pinholeopt_unittest() 
     3396{ 
     3397    //printf("pinholeopt_unittest()\n"); 
     3398    struct CS { unsigned model,op,ea,ev1,ev2,flags; } tests[][2] = 
     3399    { 
     3400        // XOR reg,immed                            NOT regL 
     3401        {{ 16,0x81,modregrm(3,6,BX),0,0xFF,0 },    { 0,0xF6,modregrm(3,2,BX),0,0xFF }}, 
     3402 
     3403#if 0 // only if config.flags4 & CFG4space 
     3404        // TEST regL,immed8 
     3405        {{ 0,0xF6,modregrm(3,0,BX),0,0xFF,0 },    { 0,0x84,modregrm(3,BX,BX),0,0xFF }}, 
     3406        {{ 0,0xF7,modregrm(3,0,BX),0,0xFF,0 },    { 0,0x84,modregrm(3,BX,BX),0,0xFF }}, 
     3407        {{ 64,0xF6,modregrmx(3,0,R8),0,0xFF,0 },  { 0,0x84,modregxrmx(3,R8,R8),0,0xFF }}, 
     3408        {{ 64,0xF7,modregrmx(3,0,R8),0,0xFF,0 },  { 0,0x84,modregxrmx(3,R8,R8),0,0xFF }}, 
     3409#endif 
     3410 
     3411        // PUSH immed => PUSH immed8 
     3412        {{ 0,0x68,0,0,0 },    { 0,0x6A,0,0,0 }}, 
     3413        {{ 0,0x68,0,0,0x7F }, { 0,0x6A,0,0,0x7F }}, 
     3414        {{ 0,0x68,0,0,0x80 }, { 0,0x68,0,0,0x80 }}, 
     3415        {{ 16,0x68,0,0,0,CFopsize },    { 0,0x6A,0,0,0,CFopsize }}, 
     3416        {{ 16,0x68,0,0,0x7F,CFopsize }, { 0,0x6A,0,0,0x7F,CFopsize }}, 
     3417        {{ 16,0x68,0,0,0x80,CFopsize }, { 0,0x68,0,0,0x80,CFopsize }}, 
     3418        {{ 16,0x68,0,0,0x10000,0 },     { 0,0x6A,0,0,0x10000,0 }}, 
     3419        {{ 16,0x68,0,0,0x10000,CFopsize }, { 0,0x68,0,0,0x10000,CFopsize }}, 
     3420        {{ 32,0x68,0,0,0,CFopsize },    { 0,0x6A,0,0,0,CFopsize }}, 
     3421        {{ 32,0x68,0,0,0x7F,CFopsize }, { 0,0x6A,0,0,0x7F,CFopsize }}, 
     3422        {{ 32,0x68,0,0,0x80,CFopsize }, { 0,0x68,0,0,0x80,CFopsize }}, 
     3423        {{ 32,0x68,0,0,0x10000,CFopsize },    { 0,0x6A,0,0,0x10000,CFopsize }}, 
     3424        {{ 32,0x68,0,0,0x8000,CFopsize }, { 0,0x68,0,0,0x8000,CFopsize }}, 
     3425    }; 
     3426 
     3427    //config.flags4 |= CFG4space; 
     3428    for (int i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) 
     3429    {   CS *pin  = &tests[i][0]; 
     3430        CS *pout = &tests[i][1]; 
     3431        code cs; 
     3432        memset(&cs, 0, sizeof(cs)); 
     3433        if (pin->model) 
     3434        { 
     3435            if (I16 && pin->model != 16) 
     3436                continue; 
     3437            if (I32 && pin->model != 32) 
     3438                continue; 
     3439            if (I64 && pin->model != 64) 
     3440                continue; 
     3441        } 
     3442        //printf("[%d]\n", i); 
     3443        cs.Iop = pin->op; 
     3444        cs.Iea = pin->ea; 
     3445        cs.IFL1 = FLconst; 
     3446        cs.IFL2 = FLconst; 
     3447        cs.IEV1.Vuns = pin->ev1; 
     3448        cs.IEV2.Vuns = pin->ev2; 
     3449        cs.Iflags = pin->flags; 
     3450        pinholeopt(&cs, NULL); 
     3451        if (cs.Iop != pout->op) 
     3452        {   printf("[%d] Iop = x%02x, pout = x%02x\n", i, cs.Iop, pout->op); 
     3453            assert(0); 
     3454        } 
     3455        assert(cs.Iea == pout->ea); 
     3456        assert(cs.IEV1.Vuns == pout->ev1); 
     3457        assert(cs.IEV2.Vuns == pout->ev2); 
     3458        assert(cs.Iflags == pout->flags); 
     3459    } 
     3460} 
     3461#endif 
    33633462 
    33643463/************************** 
    33653464 * Compute jump addresses for FLcode. 
    33663465 * Note: only works for forward referenced code. 
    33673466 *       only direct jumps and branches are detected. 
    33683467 *       LOOP instructions only work for backward refs. 
    33693468 */ 
    33703469 
    33713470void jmpaddr(code *c) 
    33723471{ code *ci,*cn,*ctarg,*cstart; 
    33733472  targ_size_t ad; 
    33743473  unsigned char op; 
    33753474 
    33763475  //printf("jmpaddr()\n"); 
    33773476  cstart = c;                           /* remember start of code       */ 
    33783477  while (c) 
    33793478  { 
    33803479        op = c->Iop; 
    33813480        if (inssize[op] & T &&          /* if second operand            */ 
    33823481            c->IFL2 == FLcode && 
     
    35593658            } 
    35603659            if (iflags & CFopsize) 
    35613660                size++;                         /* +1 for OPSIZE prefix         */ 
    35623661        } 
    35633662    } 
    35643663 
    35653664    if ((op & 0xF0) == 0x70) 
    35663665    {   if (iflags & CFjmp16)           // if long branch 
    35673666            size += I16 ? 3 : 4;        // + 3(4) bytes for JMP 
    35683667    } 
    35693668    else if (ins & M)                   // if modregrm byte 
    35703669    { 
    35713670        rm = c->Irm; 
    35723671        mod = rm & 0xC0; 
    35733672        if (a32 || I64) 
    35743673        {   // 32 bit addressing 
    35753674            if (issib(rm)) 
    35763675                size++; 
    35773676            switch (mod) 
    35783677            {   case 0: 
    3579                     if (issib(rm) && (c->Isib & 7) == 5 || (rm & 7) == 5) 
     3678                    if (issib(rm) && (c->Isib & 7) == 5 || 
     3679                        (rm & 7) == 5) 
    35803680                        size += 4;      /* disp32                       */ 
     3681                    if (c->Irex & REX_B && (rm & 7) == 5) 
     3682                        /* Instead of selecting R13, this mode is an [RIP] relative 
     3683                         * address. Although valid, it's redundant, and should not 
     3684                         * be generated. Instead, generate 0[R13] instead of [R13]. 
     3685                         */ 
     3686                        assert(0); 
    35813687                    break; 
    35823688                case 0x40: 
    35833689                    size++;             /* disp8                        */ 
    35843690                    break; 
    35853691                case 0x80: 
    35863692                    size += 4;          /* disp32                       */ 
    35873693                    break; 
    35883694            } 
    35893695        } 
    35903696        else 
    35913697        {   // 16 bit addressing 
    35923698            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    35933699                size++; 
    35943700            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    35953701                size += 2; 
    35963702        } 
    35973703    } 
    35983704 
    35993705Lret: 
    36003706    if (c->Irex) 
     
    37273833 
    37283834STATIC void cod3_flush() 
    37293835{ 
    37303836    // Emit accumulated bytes to code segment 
    37313837#ifdef DEBUG 
    37323838    assert(pgen - bytes < sizeof(bytes)); 
    37333839#endif 
    37343840    offset += obj_bytes(cseg,offset,pgen - bytes,bytes); 
    37353841    pgen = bytes; 
    37363842} 
    37373843 
    37383844unsigned codout(code *c) 
    37393845{ unsigned op; 
    37403846  unsigned char rm,mod; 
    37413847  unsigned char ins; 
    37423848  code *cn; 
    37433849  unsigned flags; 
    37443850  symbol *s; 
    37453851 
    37463852#ifdef DEBUG 
    3747   if (debugc) printf("codout(%p), Coffset = x%lx\n",c,Coffset); 
     3853  if (debugc) printf("codout(%p), Coffset = x%llx\n",c,(unsigned long long)Coffset); 
    37483854#endif 
    37493855 
    37503856  pgen = bytes; 
    37513857  offset = Coffset; 
    37523858  for (; c; c = code_next(c)) 
    37533859  { 
    37543860#ifdef DEBUG 
    37553861        if (debugc) { printf("off=%02lx, sz=%ld, ",(long)OFFSET(),(long)calccodsize(c)); c->print(); } 
    37563862#endif 
    37573863        op = c->Iop; 
    37583864        ins = inssize[op]; 
    37593865        switch (op) 
    37603866        {   case ESCAPE: 
    37613867                switch (c->Iop2) 
    37623868                {   case ESClinnum: 
    37633869                        /* put out line number stuff    */ 
    37643870                        objlinnum(c->IEV2.Vsrcpos,OFFSET()); 
    37653871                        break; 
    37663872#if SCPP 
    37673873#if 1 
     
    48914997            printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 
    48924998        } 
    48934999        if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 
    48945000        { 
    48955001            switch (c->IFL1) 
    48965002            { 
    48975003                case FLconst: 
    48985004                case FLoffset: 
    48995005                    printf(" int = %4d",c->IEV1.Vuns); 
    49005006                    break; 
    49015007                case FLblock: 
    49025008                    printf(" block = %p",c->IEV1.Vblock); 
    49035009                    break; 
    49045010                case FLswitch: 
    49055011                case FLblockoff: 
    49065012                case FLlocalsize: 
    49075013                case FLframehandler: 
    49085014                case 0: 
    49095015                    break; 
    49105016                case FLdatseg: 
    4911                     printf(" %d.%lx",c->IEVseg1,c->IEVpointer1); 
     5017                    printf(" %d.%llx",c->IEVseg1,(unsigned long long)c->IEVpointer1); 
    49125018                    break; 
    49135019                case FLauto: 
    49145020                case FLreg: 
    49155021                case FLdata: 
    49165022                case FLudata: 
    49175023                case FLpara: 
    49185024                case FLtmp: 
    49195025                case FLbprel: 
    49205026                case FLtlsdata: 
    49215027                    printf(" sym='%s'",c->IEVsym1->Sident); 
    49225028                    break; 
    49235029                default: 
    49245030                    WRFL((enum FL)c->IFL1); 
    49255031                    break; 
    49265032            } 
    49275033        } 
    49285034  } 
    49295035  if (ins & T) 
    49305036  {     printf(" "); WRFL((enum FL)c->IFL2); 
    49315037        switch (c->IFL2) 
    49325038        { 
    49335039            case FLconst: 
    49345040                printf(" int = %4d",c->IEV2.Vuns); 
    49355041                break; 
    49365042            case FLblock: 
    49375043                printf(" block = %p",c->IEV2.Vblock); 
    49385044                break; 
    49395045            case FLswitch: 
    49405046            case FLblockoff: 
    49415047            case 0: 
    49425048            case FLlocalsize: 
    49435049            case FLframehandler: 
    49445050                break; 
    49455051            case FLdatseg: 
    4946                 printf(" %d.%lx",c->IEVseg2,c->IEVpointer2); 
     5052                printf(" %d.%llx",c->IEVseg2,(unsigned long long)c->IEVpointer2); 
    49475053                break; 
    49485054            case FLauto: 
    49495055            case FLreg: 
    49505056            case FLpara: 
    49515057            case FLtmp: 
    49525058            case FLbprel: 
    49535059            case FLfunc: 
    49545060            case FLdata: 
    49555061            case FLudata: 
    49565062            case FLtlsdata: 
    49575063                printf(" sym='%s'",c->IEVsym2->Sident); 
    49585064                break; 
    49595065            case FLcode: 
    49605066                printf(" code = %p",c->IEV2.Vcode); 
    49615067                break; 
    49625068            default: 
    49635069                WRFL((enum FL)c->IFL2); 
    49645070                break; 
    49655071        } 
    49665072  } 
  • branches/dmd-1.x/src/backend/code.h

    r580 r581  
    150150#define SEG_ES  0 
    151151#define SEG_CS  1 
    152152#define SEG_SS  2 
    153153#define SEG_DS  3 
    154154 
    155155/********************* 
    156156 * Masks for register pairs. 
    157157 * Note that index registers are always LSWs. This is for the convenience 
    158158 * of implementing far pointers. 
    159159 */ 
    160160 
    161161#if 0 
    162162// Give us an extra one so we can enregister a long 
    163163#define mMSW    (mCX|mDX|mDI|mES)       // most significant regs 
    164164#define mLSW    (mAX|mBX|mSI)           // least significant regs 
    165165#else 
    166166#define mMSW    (mCX|mDX|mES)           /* most significant regs        */ 
    167167#define mLSW    (mAX|mBX|mSI|mDI)       /* least significant regs       */ 
    168168#endif 
    169169 
    170 /* Return !=0 if there is an SIB byte   */ 
     170/* Return !=0 if there is a SIB byte   */ 
    171171#define issib(rm)       (((rm) & 7) == 4 && ((rm) & 0xC0) != 0xC0) 
    172172 
    173173#if 0 
    174174// relocation field size is always 32bits 
    175175#define is32bitaddr(x,Iflags) (1) 
    176176#else 
    177177// 
    178178// is32bitaddr works correctly only when x is 0 or 1.  This is 
    179179// true today for the current definition of I32, but if the definition 
    180180// of I32 changes, this macro will need to change as well 
    181181// 
    182182// Note: even for linux targets, CFaddrsize can be set by the inline 
    183183// assembler. 
    184184#define is32bitaddr(x,Iflags) (I64 || ((x) ^(((Iflags) & CFaddrsize) !=0))) 
    185185#endif 
    186186 
    187187/******************* 
    188188 * Some instructions. 
    189189 */ 
    190190 
  • branches/dmd-1.x/src/backend/el.c

    r580 r581  
    13261326        default: 
    13271327            break; 
    13281328    } 
    13291329    return e; 
    13301330} 
    13311331#endif 
    13321332#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    13331333 
    13341334elem *el_picvar(symbol *s) 
    13351335{   elem *e; 
    13361336    int x; 
    13371337 
    13381338    //printf("el_picvar(s = '%s')\n", s->Sident); 
    13391339    symbol_debug(s); 
    13401340    type_debug(s->Stype); 
    13411341    e = el_calloc(); 
    13421342    e->Eoper = OPvar; 
    13431343    e->EV.sp.Vsym = s; 
    13441344    e->Ety = s->ty(); 
    13451345 
     1346    /* For 32 bit: 
     1347     *      CALL __i686.get_pc_thunk.bx@PC32 
     1348     *      ADD  EBX,offset _GLOBAL_OFFSET_TABLE_@GOTPC[2] 
     1349     * Generate for var locals: 
     1350     *      MOV  reg,s@GOTOFF[014h][EBX] 
     1351     * For var globals: 
     1352     *      MOV  EAX,s@GOT32[EBX] 
     1353     *      MOV  reg,[EAX] 
     1354     * For TLS var locals and globals: 
     1355     *      MOV  EAX,s@TLS_GD[EBX] 
     1356     *      CALL ___tls_get_addr@PLT32 
     1357     *      MOV  reg,[EAX] 
     1358     ***************************************** 
     1359     * Generate for var locals: 
     1360     *      MOV reg,s@PC32[RIP] 
     1361     * For var globals: 
     1362     *      MOV RAX,s@GOTPCREL[RIP] 
     1363     *      MOV reg,[RAX] 
     1364     * For TLS var locals and globals: 
     1365     *      0x66 
     1366     *      LEA DI,s@TLSGD[RIP] 
     1367     *      0x66 
     1368     *      0x66 
     1369     *      0x48 (REX | REX_W) 
     1370     *      CALL __tls_get_addr@PLT32 
     1371     *      MOV reg,[RAX] 
     1372     */ 
     1373 
     1374    if (I64) 
     1375    { 
     1376        elfobj_refGOTsym(); 
     1377        switch (s->Sclass) 
     1378        { 
     1379            case SCstatic: 
     1380            case SClocstat: 
     1381                x = 0; 
     1382                goto case_got64; 
     1383 
     1384            case SCcomdat: 
     1385            case SCcomdef: 
     1386            case SCglobal: 
     1387            case SCextern: 
     1388                x = 1; 
     1389            case_got64: 
     1390            { 
     1391                int op = e->Eoper; 
     1392                tym_t tym = e->Ety; 
     1393                e->Ety = TYnptr; 
     1394 
     1395                if (s->Stype->Tty & mTYthread) 
     1396                { 
     1397                    /* Add "volatile" to prevent e from being common subexpressioned. 
     1398                     * This is so we can preserve the magic sequence of instructions 
     1399                     * that the gnu linker patches: 
     1400                     *   lea EDI,x@tlsgd[RIP], call __tls_get_addr@plt 
     1401                     *      => 
     1402                     *   mov EAX,gs[0], sub EAX,x@tpoff 
     1403                     */ 
     1404                    e->Eoper = OPrelconst; 
     1405                    e->Ety |= mTYvolatile; 
     1406                    if (!tls_get_addr_sym) 
     1407                    { 
     1408                        /* void *__tls_get_addr(void *ptr); 
     1409                         * Parameter ptr is passed in RDI, matching TYnfunc calling convention. 
     1410                         */ 
     1411                        tls_get_addr_sym = symbol_name("__tls_get_addr",SCglobal,type_fake(TYnfunc)); 
     1412                        symbol_keep(tls_get_addr_sym); 
     1413                    } 
     1414                    e = el_bin(OPcall, TYnptr, el_var(tls_get_addr_sym), e); 
     1415                } 
     1416 
     1417                switch (op * 2 + x) 
     1418                { 
     1419                    case OPvar * 2 + 1: 
     1420                        e = el_una(OPind, TYnptr, e); 
     1421                        break; 
     1422                    case OPvar * 2 + 0: 
     1423                    case OPrelconst * 2 + 1: 
     1424                        break; 
     1425                    case OPrelconst * 2 + 0: 
     1426                        e = el_una(OPaddr, TYnptr, e); 
     1427                        break; 
     1428                    default: 
     1429                        assert(0); 
     1430                        break; 
     1431                } 
     1432                e->Ety = tym; 
     1433                break; 
     1434            } 
     1435            default: 
     1436                break; 
     1437        } 
     1438    } 
     1439    else 
    13461440    switch (s->Sclass) 
    13471441    { 
    13481442        /* local (and thread) symbols get only one level of indirection; 
    13491443         * all globally known symbols get two. 
    13501444         */ 
    13511445        case SCstatic: 
    13521446        case SClocstat: 
    13531447            x = 0; 
    13541448            goto case_got; 
    13551449 
    13561450        case SCcomdat: 
    13571451        case SCcomdef: 
    13581452        case SCglobal: 
    13591453        case SCextern: 
    13601454            if (s->Stype->Tty & mTYthread) 
    13611455                x = 0; 
    13621456            else 
    13631457                x = 1; 
    13641458        case_got: 
    13651459        {   if (!localgot) 
     
    14241518            break; 
    14251519    } 
    14261520    return e; 
    14271521} 
    14281522#endif 
    14291523 
    14301524/************************** 
    14311525 * Make an elem out of a symbol. 
    14321526 */ 
    14331527 
    14341528#if MARS 
    14351529elem * el_var(symbol *s) 
    14361530{   elem *e; 
    14371531 
    14381532    //printf("el_var(s = '%s')\n", s->Sident); 
    14391533    //printf("%x\n", s->Stype->Tty); 
    14401534#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    14411535    // OSX is currently always pic 
    14421536    if (config.flags3 & CFG3pic && 
    14431537#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    1444         !(s->Stype->Tty & mTYthread) && 
     1538        (!(s->Stype->Tty & mTYthread) || I64) && 
    14451539#endif 
    14461540        !tyfunc(s->ty())) 
    14471541        // Position Independent Code 
    14481542        return el_picvar(s); 
    14491543#endif 
    14501544    symbol_debug(s); 
    14511545    type_debug(s->Stype); 
    14521546    e = el_calloc(); 
    14531547    e->Eoper = OPvar; 
    14541548    e->EV.sp.Vsym = s; 
    14551549    type_debug(s->Stype); 
    14561550    e->Ety = s->ty(); 
    14571551    if (s->Stype->Tty & mTYthread) 
    14581552    { 
    14591553        //printf("thread local %s\n", s->Sident); 
    14601554#if TARGET_OSX 
    14611555        ; 
    14621556#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    14631557        /* For 32 bit: 
    14641558         * Generate for var locals: 
     
    14771571         * For var globals: 
    14781572         *      MOV RAX,s@GOTTPOFF[RIP] 
    14791573         *      MOV reg,FS:[RAX] 
    14801574         * 
    14811575         * For address of locals: 
    14821576         *      MOV RAX,FS:[00] 
    14831577         *      LEA reg,s@TPOFF32[RAX] 
    14841578         *      e => &s + *(FS:0) 
    14851579         * For address of globals: 
    14861580         *      MOV reg,FS:[00] 
    14871581         *      MOV RAX,s@GOTTPOFF[RIP] 
    14881582         *      ADD reg,RAX 
    14891583         *      e => s + *(FS:0) 
    14901584         * This leaves us with a problem, as the 'var' version cannot simply have 
    14911585         * its address taken, as what is the address of FS:s ? The (not so efficient) 
    14921586         * solution is to just use the second address form, and * it. 
    14931587         * Turns out that is identical to the 32 bit version, except GS => FS and the 
    14941588         * fixups are different. 
    14951589         * In the future, we should figure out a way to optimize to the 'var' version. 
    14961590         */ 
     1591        if (I64) 
     1592            elfobj_refGOTsym(); 
    14971593        elem *e1 = el_calloc(); 
    14981594        e1->EV.sp.Vsym = s; 
    14991595        if (s->Sclass == SCstatic || s->Sclass == SClocstat) 
    15001596        {   e1->Eoper = OPrelconst; 
    15011597            e1->Ety = TYnptr; 
    15021598        } 
    15031599        else 
    15041600        { 
    15051601            e1->Eoper = OPvar; 
    15061602            e1->Ety = TYnptr; 
    15071603        } 
    15081604 
    15091605        /* Fake GS:[0000] as a load of _tls_array, and then in the back end recognize 
    15101606         * the fake and rewrite it as GS:[0000] (or FS:[0000] for I64), because there is 
    15111607         * no way to represent segment overrides in the elem nodes. 
    15121608         */ 
    15131609        elem *e2 = el_calloc(); 
    15141610        e2->Eoper = OPvar; 
    15151611        e2->EV.sp.Vsym = rtlsym[RTLSYM_TLS_ARRAY]; 
    15161612        e2->Ety = e2->EV.sp.Vsym->ty(); 
  • branches/dmd-1.x/src/backend/elfobj.c

    r579 r581  
    6767 *      RI_TYPE_GOT32   R_X86_64_         R_X86_64_ 
    6868 *      RI_TYPE_TLS_GD  R_X86_64_TLSGD    R_X86_64_ 
    6969 *      RI_TYPE_TLS_IE  R_X86_64_GOTTPOFF R_X86_64_ 
    7070 *      RI_TYPE_TLS_LE  R_X86_64_TPOFF32  R_X86_64_ 
    7171 *      RI_TYPE_PLT32   R_X86_64_PLT32    R_X86_64_ 
    7272 *      RI_TYPE_PC32    R_X86_64_PC32     R_X86_64_ 
    7373 */ 
    7474 
    7575/****************************************** 
    7676 */ 
    7777 
    7878symbol *GOTsym; // global offset table reference 
    7979 
    8080symbol *elfobj_getGOTsym() 
    8181{ 
    8282    if (!GOTsym) 
    8383    { 
    8484        GOTsym = symbol_name("_GLOBAL_OFFSET_TABLE_",SCglobal,tspvoid); 
    8585    } 
    8686    return GOTsym; 
     87} 
     88 
     89void elfobj_refGOTsym() 
     90{ 
     91    if (!GOTsym) 
     92    { 
     93        symbol *s = elfobj_getGOTsym(); 
     94        objextern(s); 
     95    } 
    8796} 
    8897 
    8998static void objfile_write(FILE *fd, void *buffer, unsigned len); 
    9099 
    91100STATIC char * objmodtoseg (const char *modname); 
    92101STATIC void obj_browse_flush(); 
    93102STATIC void objfixupp (struct FIXUP *); 
    94103STATIC void ledata_new (int seg,targ_size_t offset); 
    95104void obj_tlssections(); 
    96105 
    97106static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz, 
    98107                        unsigned typ,unsigned bind,IDXSEC sec); 
    99108static long elf_align(FILE *fd, targ_size_t size, long offset); 
    100109 
    101110// The object file is built is several separate pieces 
    102111 
    103112// Non-repeatable section types have single output buffers 
    104113//      Pre-allocated buffers are defined for: 
    105114//              Section Names string table 
    106115//              Section Headers table 
     
    22962305 *      seg =           where the address is going 
    22972306 *      offset =        offset within seg 
    22982307 *      val =           displacement from address 
    22992308 *      targetdatum =   DATA, CDATA or UDATA, depending where the address is 
    23002309 *      flags =         CFoff, CFseg 
    23012310 * Example: 
    23022311 *      int *abc = &def[3]; 
    23032312 *      to allocate storage: 
    23042313 *              reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); 
    23052314 */ 
    23062315 
    23072316void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 
    23082317        unsigned targetdatum,int flags) 
    23092318{ 
    23102319    Outbuffer *buf; 
    23112320    int save; 
    23122321 
    23132322    buf = SegData[seg]->SDbuf; 
    23142323    save = buf->size(); 
    23152324    buf->setsize(offset); 
    2316     //dbg_printf("reftodatseg(seg=%d, offset=x%lx, val=x%lx,data %x, flags %x )\n", 
    2317     //  seg,offset,val,targetdatum,flags); 
     2325#if 0 
     2326    printf("reftodatseg(seg=%d, offset=x%llx, val=x%llx,data %x, flags %x)\n", 
     2327        seg,(unsigned long long)offset,(unsigned long long)val,targetdatum,flags); 
     2328#endif 
    23182329    /*if (OPT_IS_SET(OPTfwritable_strings)) 
    23192330    { 
    23202331        elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 
    23212332    } 
    23222333    else*/ 
    23232334    { 
    23242335        int relinfo; 
    23252336 
    23262337        if (I64) 
    23272338        { 
    23282339            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
    23292340                relinfo = R_X86_64_PC32; 
    23302341            else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 
    23312342                relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 
    23322343            else 
    23332344                relinfo = R_X86_64_32; 
    23342345        } 
    23352346        else 
    23362347        { 
    23372348            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
     
    24022413 *      flags =         CFselfrel: self-relative 
    24032414 *                      CFseg: get segment 
    24042415 *                      CFoff: get offset 
    24052416 *                      CFoffset64: 64 bit fixup 
    24062417 * Returns: 
    24072418 *      number of bytes in reference (4 or 8) 
    24082419 */ 
    24092420 
    24102421int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 
    24112422        int flags) 
    24122423{ 
    24132424    tym_t ty; 
    24142425    bool external = TRUE; 
    24152426    Outbuffer *buf; 
    24162427    elf_u32_f32 relinfo,refseg; 
    24172428    int segtyp = MAP_SEG2TYP(seg); 
    24182429    //assert(val == 0); 
    24192430    int retsize = (flags & CFoffset64) ? 8 : 4; 
    24202431 
    24212432#if 0 
    2422     dbg_printf("\nreftoident('%s' seg %d, offset x%lx, val x%lx, flags x%x)\n", 
     2433    printf("\nreftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", 
    24232434        s->Sident,seg,offset,val,flags); 
    2424     dbg_printf("Sseg = %d, Sxtrnnum = %d\n",s->Sseg,s->Sxtrnnum); 
     2435    dbg_printf("Sseg = %d, Sxtrnnum = %d, retsize = %d\n",s->Sseg,s->Sxtrnnum,retsize); 
    24252436    symbol_print(s); 
    24262437#endif 
    24272438 
    24282439    ty = s->ty(); 
    24292440    if (s->Sxtrnnum) 
    24302441    {                           // identifier is defined somewhere else 
    24312442        if (I64) 
    24322443        { 
    24332444            if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24342445                external = FALSE; 
    24352446        } 
    24362447        else 
    24372448        { 
    24382449            if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24392450                external = FALSE; 
    24402451        } 
    24412452    } 
    24422453 
    24432454    switch (s->Sclass) 
    24442455    { 
     
    25032514                    if (!external &&            // local definition found 
    25042515                         s->Sseg == seg &&      // within same code segment 
    25052516                          (!(config.flags3 & CFG3pic) ||        // not position indp code 
    25062517                           s->Sclass == SCstatic)) // or is pic, but declared static 
    25072518                    {                   // Can use PC relative 
    25082519                        //dbg_printf("\tdoing PC relative\n"); 
    25092520                        val = (s->Soffset+val) - (offset+4); 
    25102521                    } 
    25112522                    else 
    25122523                    { 
    25132524                        val = (targ_size_t)-4; 
    25142525                        //dbg_printf("\tadding relocation\n"); 
    25152526                        if (I64) 
    25162527                            relinfo = config.flags3 & CFG3pic ?  R_X86_64_PLT32 : R_X86_64_PC32; 
    25172528                        else 
    25182529                            relinfo = config.flags3 & CFG3pic ?  RI_TYPE_PLT32 : RI_TYPE_PC32; 
    25192530                        elf_addrel(seg,offset, 
    25202531                                relinfo, 
    25212532                                s->Sxtrnnum,0); 
    25222533                    } 
     2534                    if (I64) 
     2535                        val += 4; 
    25232536                } 
    25242537                else 
    25252538                {       // code to code code to data, data to code, data to data refs 
    25262539                    refseg = s->Sxtrnnum;       // default to name symbol table entry 
    25272540                    if (s->Sclass == SCstatic) 
    25282541                    {                           // offset into .data or .bss seg 
    25292542                        refseg = MAP_SEG2SYMIDX(s->Sseg); 
    25302543                                                // use segment symbol table entry 
    25312544                        val += s->Soffset; 
    25322545                        if (!(config.flags3 & CFG3pic) ||       // all static refs from normal code 
    25332546                             segtyp == DATA)    // or refs from data from posi indp 
    25342547                        { 
    25352548                           relinfo = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 
    25362549                        } 
    25372550                        else 
    25382551                        { 
    25392552                            relinfo = I64 ? R_X86_64_PC32 : RI_TYPE_GOTOFF; 
    25402553                        } 
    25412554                    } 
    25422555                    else if (config.flags3 & CFG3pic && s == GOTsym) 
    25432556                    {                   // relocation for Gbl Offset Tab 
    25442557                        relinfo =  I64 ? R_X86_64_NONE : RI_TYPE_GOTPC; 
    25452558                    } 
    25462559                    else if (segtyp == DATA) 
    25472560                    {                   // relocation from within DATA seg 
    25482561                        relinfo = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 
    25492562                    } 
    25502563                    else 
    25512564                    {                   // relocation from within CODE seg 
    25522565                        if (I64) 
    2553                             relinfo = config.flags3 & CFG3pic ? R_X86_64_NONE : R_X86_64_32; 
     2566                        {   if (config.flags3 & CFG3pic) 
     2567                                relinfo = R_X86_64_GOTPCREL; 
     2568                            else 
     2569                                relinfo = (flags & CFpc32) ? R_X86_64_PC32 : R_X86_64_32; 
     2570                        } 
    25542571                        else 
    25552572                            relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOT32 : RI_TYPE_SYM32; 
    25562573                    } 
    25572574                    if ((s->ty() & mTYLINK) & mTYthread) 
    25582575                    { 
    25592576                        if (I64) 
    25602577                        { 
    25612578                            if (config.flags3 & CFG3pic) 
    25622579                            { 
    2563                                 if (s->Sclass == SCstatic
    2564                                     relinfo = R_X86_64_TPOFF32;  // TLS_GD? 
     2580                                if (s->Sclass == SCstatic || s->Sclass == SClocstat
     2581                                    relinfo = R_X86_64_TLSGD;  // TLS_GD? 
    25652582                                else 
    2566                                     relinfo = R_X86_64_GOTTPOFF
     2583                                    relinfo = R_X86_64_TLSGD
    25672584                            } 
    25682585                            else 
    25692586                            { 
    2570                                 if (s->Sclass == SCstatic
     2587                                if (s->Sclass == SCstatic || s->Sclass == SClocstat
    25712588                                    relinfo = R_X86_64_TPOFF32; 
    25722589                                else 
    25732590                                    relinfo = R_X86_64_GOTTPOFF; 
    25742591                            } 
    25752592                        } 
    25762593                        else 
    25772594                        { 
    25782595                            if (config.flags3 & CFG3pic) 
    25792596                            { 
    25802597                                if (s->Sclass == SCstatic) 
    25812598                                    relinfo = RI_TYPE_TLS_LE;  // TLS_GD? 
    25822599                                else 
    25832600                                    relinfo = RI_TYPE_TLS_IE; 
    25842601                            } 
    25852602                            else 
    25862603                            { 
    25872604                                if (s->Sclass == SCstatic) 
    25882605                                    relinfo = RI_TYPE_TLS_LE; 
    25892606                                else 
    25902607                                    relinfo = RI_TYPE_TLS_IE; 
  • trunk/src/backend/cod1.c

    r580 r581  
    13271327                s->Sclass == SCparameter) 
    13281328            {   refparam = TRUE; 
    13291329                reflocal = TRUE;        // kludge to set up prolog 
    13301330            } 
    13311331            pcs->Irm = modregrm(3,0,s->Sreglsw & 7); 
    13321332            if (s->Sreglsw & 8) 
    13331333                pcs->Irex |= REX_B; 
    13341334            if (e->EV.sp.Voffset == 1 && sz == 1) 
    13351335            {   assert(s->Sregm & BYTEREGS); 
    13361336                assert(s->Sreglsw < 4); 
    13371337                pcs->Irm |= 4;                  // use 2nd byte of register 
    13381338            } 
    13391339            else 
    13401340                assert(!e->EV.sp.Voffset); 
    13411341        } 
    13421342        else if (s->ty() & mTYcs && !(fl == FLextern && LARGECODE)) 
    13431343        { 
    13441344            pcs->Iflags |= CFcs | CFoff; 
    13451345        } 
    13461346#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    1347 //      if (fl == FLtlsdata || s->ty() & mTYthread) 
    1348 //          pcs->Iflags |= CFgs; 
     1347        if (I64 && config.flags3 & CFG3pic && 
     1348            (fl == FLtlsdata || s->ty() & mTYthread)) 
     1349        { 
     1350            pcs->Iflags |= CFopsize; 
     1351            pcs->Irex = 0x48; 
     1352        } 
    13491353#endif 
    13501354        pcs->IEVsym1 = s; 
    13511355        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    13521356        if (sz == 1) 
    13531357        {   /* Don't use SI or DI for this variable     */ 
    13541358            s->Sflags |= GTbyte; 
    13551359            if (e->EV.sp.Voffset > 1) 
    13561360                s->Sflags &= ~GTregcand; 
    13571361        } 
    13581362        else if (e->EV.sp.Voffset) 
    13591363            s->Sflags &= ~GTregcand; 
    13601364        if (!(keepmsk & RMstore))               // if not store only 
    13611365        {   s->Sflags |= SFLread;               // assume we are doing a read 
    13621366        } 
    13631367        break; 
    13641368    case FLpseudo: 
    13651369#if MARS 
    13661370        assert(0); 
    13671371#else 
    13681372    { 
     
    26762680                goto LF1; 
    26772681            else 
    26782682                goto LF2; 
    26792683        } 
    26802684        else 
    26812685        {   int fl; 
    26822686 
    26832687            fl = FLfunc; 
    26842688            if (!tyfunc(s->ty())) 
    26852689                fl = el_fl(e1); 
    26862690            if (tym1 == TYifunc) 
    26872691                c1 = gen1(c1,0x9C);                             // PUSHF 
    26882692#if 0 && TARGET_LINUX 
    26892693            if (s->Sfl == FLgot || s->Sfl == FLgotoff) 
    26902694                fl = s->Sfl; 
    26912695#endif 
    26922696            ce = gencs(CNIL,farfunc ? 0x9A : 0xE8,0,fl,s);      // CALL extern 
    26932697            ce->Iflags |= farfunc ? (CFseg | CFoff) : (CFselfrel | CFoff); 
    26942698#if TARGET_LINUX 
    26952699            if (s == tls_get_addr_sym) 
    2696             {   /* Append a NOP so GNU linker has patch room 
    2697                  */ 
    2698                 ce = gen1(ce, 0x90);            // NOP 
    2699                 code_orflag(ce, CFvolatile);    // don't schedule it 
     2700            { 
     2701                if (I32) 
     2702                { 
     2703                    /* Append a NOP so GNU linker has patch room 
     2704                     */ 
     2705                    ce = gen1(ce, 0x90);        // NOP 
     2706                    code_orflag(ce, CFvolatile);    // don't schedule it 
     2707                } 
     2708                else 
     2709                {   /* Prepend 66 66 48 so GNU linker has patch room 
     2710                     */ 
     2711                    assert(I64); 
     2712                    ce->Irex = REX | REX_W; 
     2713                    ce = cat(gen1(CNIL, 0x66), ce); 
     2714                    ce = cat(gen1(CNIL, 0x66), ce); 
     2715                } 
    27002716            } 
    27012717#endif 
    27022718        } 
    27032719        ce = cat(c1,ce); 
    27042720  } 
    27052721  else 
    27062722  {     /* Call function via pointer    */ 
    27072723        elem *e11; 
    27082724        tym_t e11ty; 
    27092725 
    27102726#ifdef DEBUG 
    27112727        if (e1->Eoper != OPind 
    27122728                ) { WRFL((enum FL)el_fl(e1)); WROP(e1->Eoper); } 
    27132729#endif 
    27142730        c = save87();                   // assume 8087 regs are all trashed 
    27152731        assert(e1->Eoper == OPind); 
    27162732        e11 = e1->E1; 
    27172733        e11ty = tybasic(e11->Ety); 
    27182734        assert(!I16 || (e11ty == (farfunc ? TYfptr : TYnptr))); 
    27192735 
  • trunk/src/backend/cod2.c

    r579 r581  
    37363736{ code cs; 
    37373737  code *c; 
    37383738 
    37393739  cs.Iflags = 0; 
    37403740  unsigned char rex = 0; 
    37413741  cs.Irex = rex; 
    37423742  assert(e->Eoper == OPvar || e->Eoper == OPrelconst); 
    37433743  enum FL fl = el_fl(e); 
    37443744  switch (fl) 
    37453745  { 
    37463746    case FLdatseg: 
    37473747        cs.IEV2._EP.Vpointer = e->EV.Vpointer; 
    37483748        goto L3; 
    37493749 
    37503750    case FLfardata: 
    37513751        assert(!TARGET_FLAT); 
    37523752        goto L4; 
    37533753 
    37543754    case FLtlsdata: 
    37553755#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    3756     {   /* Generate: 
     3756    { 
     3757      L5: 
     3758        if (I64 && config.flags3 & CFG3pic) 
     3759        { 
     3760            /* Generate: 
     3761             *   LEA DI,s@TLSGD[RIP] 
     3762             */ 
     3763            assert(reg == DI); 
     3764            code css; 
     3765            css.Irex = REX | REX_W; 
     3766            css.Iop = 0x8D;             // LEA 
     3767            css.Irm = modregrm(0,DI,5); 
     3768            css.Iflags = CFopsize; 
     3769            css.IFL1 = fl; 
     3770            css.IEVsym1 = e->EV.sp.Vsym; 
     3771            css.IEVoffset1 = e->EV.sp.Voffset; 
     3772            c = gen(NULL, &css); 
     3773            return c; 
     3774        } 
     3775        /* Generate: 
    37573776         *      MOV reg,GS:[00000000] 
    37583777         *      ADD reg, offset s@TLS_LE 
    37593778         * for locals, and for globals: 
    37603779         *      MOV reg,GS:[00000000] 
    37613780         *      ADD reg, s@TLS_IE 
    37623781         * note different fixup 
    37633782         */ 
    3764       L5: 
    37653783        int stack = 0; 
    37663784        c = NULL; 
    37673785        if (reg == STACK) 
    37683786        {   regm_t retregs = ALLREGS; 
    37693787 
    37703788            c = allocreg(&retregs,&reg,TYoffset); 
    37713789            reg = findreg(retregs); 
    37723790            stack = 1; 
    37733791        } 
    37743792 
    37753793        code css; 
    37763794        css.Irex = rex; 
    37773795        css.Iop = 0x8B; 
    37783796        css.Irm = modregrm(0, 0, BPRM); 
    37793797        code_newreg(&css, reg); 
    37803798        css.Iflags = CFgs; 
    37813799        css.IFL1 = FLconst; 
    37823800        css.IEV1.Vuns = 0; 
    37833801        c = gen(c, &css);               // MOV reg,GS:[00000000] 
    37843802 
  • trunk/src/backend/cod3.c

    r580 r581  
    1919#include        "cc.h" 
    2020#include        "el.h" 
    2121#include        "code.h" 
    2222#include        "oper.h" 
    2323#include        "global.h" 
    2424#include        "type.h" 
    2525#include        "parser.h" 
    2626#if SCPP 
    2727#include        "cpp.h" 
    2828#include        "exh.h" 
    2929#endif 
    3030 
    3131static char __file__[] = __FILE__;      /* for tassert.h                */ 
    3232#include        "tassert.h" 
    3333 
    3434#if MARS 
    3535#define tstrace NULL 
    3636#endif 
    3737 
    3838extern targ_size_t retsize; 
     39STATIC void pinholeopt_unittest(); 
    3940STATIC void do8bit (enum FL,union evc *); 
    4041STATIC void do16bit (enum FL,union evc *,int); 
    4142STATIC void do32bit (enum FL,union evc *,int); 
    4243STATIC void do64bit (enum FL,union evc *,int); 
    4344 
    4445static int hasframe;            /* !=0 if this function has a stack frame */ 
    4546static targ_size_t Foff;        // BP offset of floating register 
    4647static targ_size_t CSoff;       // offset of common sub expressions 
    4748static targ_size_t NDPoff;      // offset of saved 8087 registers 
    4849int BPoff;                      // offset from BP 
    4950static int EBPtoESP;            // add to EBP offset to get ESP offset 
    5051static int AAoff;               // offset of alloca temporary 
    5152 
    5253#if ELFOBJ || MACHOBJ 
    5354#define JMPSEG  CDATA 
    5455#define JMPOFF  CDoffset 
    5556#else 
    5657#define JMPSEG  DATA 
    5758#define JMPOFF  Doffset 
    5859#endif 
     
    28932894    return offset; 
    28942895} 
    28952896 
    28962897 
    28972898 
    28982899/******************************* 
    28992900 * Find shorter versions of the same instructions. 
    29002901 * Does these optimizations: 
    29012902 *      replaces jmps to the next instruction with NOPs 
    29022903 *      sign extension of modregrm displacement 
    29032904 *      sign extension of immediate data (can't do it for OR, AND, XOR 
    29042905 *              as the opcodes are not defined) 
    29052906 *      short versions for AX EA 
    29062907 *      short versions for reg EA 
    29072908 * Input: 
    29082909 *      b -> block for code (or NULL) 
    29092910 */ 
    29102911 
    29112912void pinholeopt(code *c,block *b) 
    29122913{ targ_size_t a; 
    2913   unsigned op,mod,rm,reg,ereg
     2914  unsigned op,mod
    29142915  unsigned char ins; 
    29152916  int usespace; 
    29162917  int useopsize; 
    29172918  int space; 
    29182919  block *bn; 
     2920 
     2921#ifdef DEBUG 
     2922    static int tested; if (!tested) { tested++; pinholeopt_unittest(); } 
     2923#endif 
    29192924 
    29202925#if 0 
    29212926  code *cstart = c; 
    29222927  if (debugc) 
    29232928  { 
    29242929      printf("+pinholeopt(%p)\n",c); 
    29252930  } 
    29262931#endif 
    29272932 
    29282933  if (b) 
    29292934  {     bn = b->Bnext; 
    29302935        usespace = (config.flags4 & CFG4space && b->BC != BCasm); 
    29312936        useopsize = (I16 || (config.flags4 & CFG4space && b->BC != BCasm)); 
    29322937  } 
    29332938  else 
    29342939  {     bn = NULL; 
    29352940        usespace = (config.flags4 & CFG4space); 
    29362941        useopsize = (I16 || config.flags4 & CFG4space); 
    29372942  } 
    29382943  for (; c; c = code_next(c)) 
    29392944  { 
    29402945    L1: 
    29412946        op = c->Iop; 
    29422947        if (op == 0x0F) 
    29432948            ins = inssize2[c->Iop2]; 
    29442949        else 
    29452950            ins = inssize[c->Iop]; 
    2946         if (!I64 && ins & M)            // if modregrm byte 
    2947         {   int longop = (c->Iflags & CFopsize) ? I16 : I32
     2951        if (ins & M)            // if modregrm byte 
     2952        {   int shortop = (c->Iflags & CFopsize) ? !I16 : I16
    29482953            int local_BPRM = BPRM; 
    29492954 
    29502955            if (c->Iflags & CFaddrsize) 
    29512956                local_BPRM ^= 5 ^ 6;    // toggle between 5 and 6 
    29522957 
    2953             rm = c->Irm; 
    2954             reg = rm & (7<<3);          // isolate reg field 
    2955             ereg = rm & 7; 
     2958            unsigned rm = c->Irm; 
     2959            unsigned reg = rm & modregrm(0,7,0);          // isolate reg field 
     2960            unsigned ereg = rm & 7; 
     2961            //printf("c = %p, op = %02x rm = %02x\n", c, op, rm); 
    29562962 
    29572963            /* If immediate second operand      */ 
    29582964            if ((ins & T || op == 0xF6 || op == 0xF7) && 
    29592965                c->IFL2 == FLconst) 
    2960             {   int flags; 
    2961                 targ_long u; 
    2962  
    2963                 flags = c->Iflags & CFpsw;      /* if want result in flags */ 
    2964                 u = c->IEV2.Vuns; 
     2966            { 
     2967                int flags = c->Iflags & CFpsw;      /* if want result in flags */ 
     2968                targ_long u = c->IEV2.Vuns; 
    29652969                if (ins & E) 
    29662970                    u = (signed char) u; 
    2967                 else if (!longop) 
     2971                else if (shortop) 
    29682972                    u = (short) u; 
    29692973 
    29702974                // Replace CMP reg,0 with TEST reg,reg 
    2971                 if ((op & 0xFE) == 0x80 && 
     2975                if ((op & 0xFE) == 0x80 &&              // 80 is CMP R8,imm8; 81 is CMP reg,imm 
    29722976                    rm >= modregrm(3,7,AX) && 
    29732977                    u == 0) 
    29742978                {       c->Iop = (op & 1) | 0x84; 
    29752979                        c->Irm = modregrm(3,ereg,ereg); 
     2980                        if (c->Irex & REX_B) 
     2981                            c->Irex |= REX_R; 
    29762982                        goto L1; 
    29772983                } 
    29782984 
    29792985                /* Optimize ANDs with an immediate constant             */ 
    29802986                if ((op == 0x81 || op == 0x80) && reg == modregrm(0,4,0)) 
    29812987                { 
    2982                     if (rm >= modregrm(3,4,AX)) 
     2988                    if (rm >= modregrm(3,4,AX))         // AND reg,imm 
    29832989                    { 
    29842990                        if (u == 0) 
    29852991                        {       /* Replace with XOR reg,reg     */ 
    29862992                                c->Iop = 0x30 | (op & 1); 
    2987                                 NEWREG(c->Irm,rm & 7); 
     2993                                c->Irm = modregrm(3,ereg,ereg); 
     2994                                if (c->Irex & REX_B) 
     2995                                    c->Irex |= REX_R; 
    29882996                                goto L1; 
    29892997                        } 
    29902998                        if (u == 0xFFFFFFFF && !flags) 
    29912999                        {       c->Iop = NOP; 
    29923000                                goto L1; 
    29933001                        } 
    29943002                    } 
    29953003                    if (op == 0x81 && !flags) 
    29963004                    {   // If we can do the operation in one byte 
    29973005 
    29983006                        // If EA is not SI or DI 
    2999                         if (rm < modregrm(3,4,SP) && 
     3007                        if ((rm < modregrm(3,4,SP) || I64) && 
    30003008                            (config.flags4 & CFG4space || 
    30013009                             config.target_cpu < TARGET_PentiumPro) 
    30023010                           ) 
    30033011                        { 
    30043012                            if ((u & 0xFFFFFF00) == 0xFFFFFF00) 
    30053013                                goto L2; 
    3006                             else 
    3007                             {   if (longop) 
     3014                            else if (rm < modregrm(3,0,0) || (!c->Irex && ereg < 4)) 
     3015                            {   if (!shortop) 
    30083016                                {   if ((u & 0xFFFF00FF) == 0xFFFF00FF) 
    30093017                                        goto L3; 
    30103018                                } 
    30113019                                else 
    30123020                                { 
    30133021                                    if ((u & 0xFF) == 0xFF) 
    30143022                                        goto L3; 
    30153023                                } 
    30163024                            } 
    30173025                        } 
    3018                         if (longop && useopsize) 
     3026                        if (!shortop && useopsize) 
    30193027                        { 
    30203028                            if ((u & 0xFFFF0000) == 0xFFFF0000) 
    30213029                            {   c->Iflags ^= CFopsize; 
    30223030                                goto L1; 
    30233031                            } 
    30243032                            if ((u & 0xFFFF) == 0xFFFF && rm < modregrm(3,4,AX)) 
    30253033                            {   c->IEVoffset1 += 2; /* address MSW      */ 
    30263034                                c->IEV2.Vuns >>= 16; 
    30273035                                c->Iflags ^= CFopsize; 
    30283036                                goto L1; 
    30293037                            } 
    30303038                            if (rm >= modregrm(3,4,AX)) 
    30313039                            { 
    3032                                 if (u == 0xFF && rm <= modregrm(3,4,BX)) 
     3040                                if (u == 0xFF && (rm <= modregrm(3,4,BX) || I64)) 
    30333041                                {   c->Iop2 = 0xB6;     /* MOVZX        */ 
    30343042                                    c->Iop = 0x0F; 
    3035                                     NEWREG(c->Irm,rm & 7); 
     3043                                    c->Irm = modregrm(3,ereg,ereg); 
     3044                                    if (c->Irex & REX_B) 
     3045                                        c->Irex |= REX_R; 
    30363046                                    goto L1; 
    30373047                                } 
    30383048                                if (u == 0xFFFF) 
    30393049                                {   c->Iop2 = 0xB7;     /* MOVZX        */ 
    30403050                                    c->Iop = 0x0F; 
    3041                                     NEWREG(c->Irm,rm & 7); 
     3051                                    c->Irm = modregrm(3,ereg,ereg); 
     3052                                    if (c->Irex & REX_B) 
     3053                                        c->Irex |= REX_R; 
    30423054                                    goto L1; 
    30433055                                } 
    30443056                            } 
    30453057                        } 
    30463058                    } 
    30473059                } 
    30483060 
    30493061                /* Look for ADD,OR,SUB,XOR with u that we can eliminate */ 
    30503062                if (!flags && 
    30513063                    (op == 0x81 || op == 0x80) && 
    3052                     (reg == modregrm(0,0,0) || reg == modregrm(0,1,0) || 
    3053                      reg == modregrm(0,5,0) || reg == modregrm(0,6,0)) 
     3064                    (reg == modregrm(0,0,0) || reg == modregrm(0,1,0) ||  // ADD,OR 
     3065                     reg == modregrm(0,5,0) || reg == modregrm(0,6,0))    // SUB, XOR 
    30543066                   ) 
    3055                 {       if (u == 0) 
     3067                { 
     3068                        if (u == 0) 
    30563069                        { 
    30573070                                c->Iop = NOP; 
    30583071                                goto L1; 
    30593072                        } 
    30603073                        if (u == ~0 && reg == modregrm(0,6,0))  /* XOR  */ 
    30613074                        { 
    30623075                                c->Iop = 0xF6 | (op & 1);       /* NOT  */ 
    30633076                                c->Irm ^= modregrm(0,6^2,0); 
    30643077                                goto L1; 
    30653078                        } 
    3066                         if (longop && 
     3079                        if (!shortop && 
    30673080                            useopsize && 
    30683081                            op == 0x81 && 
    30693082                            (u & 0xFFFF0000) == 0 && 
    30703083                            (reg == modregrm(0,6,0) || reg == modregrm(0,1,0))) 
    30713084                        {    c->Iflags ^= CFopsize; 
    30723085                             goto L1; 
    30733086                        } 
    30743087                } 
    30753088 
    30763089                /* Look for TEST or OR or XOR with an immediate constant */ 
    30773090                /* that we can replace with a byte operation            */ 
    30783091                if (op == 0xF7 && reg == modregrm(0,0,0) || 
    30793092                    op == 0x81 && reg == modregrm(0,6,0) && !flags || 
    30803093                    op == 0x81 && reg == modregrm(0,1,0)) 
    30813094                { 
    30823095                    // See if we can replace a dword with a word 
    30833096                    // (avoid for 32 bit instructions, because CFopsize 
    30843097                    //  is too slow) 
    3085                     if (longop && useopsize) 
     3098                    if (!shortop && useopsize) 
    30863099                    {   if ((u & 0xFFFF0000) == 0) 
    30873100                        {   c->Iflags ^= CFopsize; 
    30883101                            goto L1; 
    30893102                        } 
    30903103                        /* If memory (not register) addressing mode     */ 
    30913104                        if ((u & 0xFFFF) == 0 && rm < modregrm(3,0,AX)) 
    30923105                        {   c->IEVoffset1 += 2; /* address MSW  */ 
    30933106                            c->IEV2.Vuns >>= 16; 
    30943107                            c->Iflags ^= CFopsize; 
    30953108                            goto L1; 
    30963109                        } 
    30973110                    } 
    30983111 
    30993112                    // If EA is not SI or DI 
    31003113                    if (rm < (modregrm(3,0,SP) | reg) && 
    31013114                        (usespace || 
    31023115                         config.target_cpu < TARGET_PentiumPro) 
    31033116                       ) 
    31043117                    { 
    31053118                        if ((u & 0xFFFFFF00) == 0) 
    31063119                        { 
    31073120                        L2: c->Iop--;           /* to byte instruction  */ 
    31083121                            c->Iflags &= ~CFopsize; 
    31093122                            goto L1; 
    31103123                        } 
    3111                         if ((u & 0xFFFF00FF) == 0 || 
    3112                             (!longop && (u & 0xFF) == 0)) 
     3124                        if (((u & 0xFFFF00FF) == 0 || 
     3125                             (shortop && (u & 0xFF) == 0)) && 
     3126                            (rm < modregrm(3,0,0) || (!c->Irex && ereg < 4))) 
    31133127                        { 
    31143128                        L3: 
    31153129                            c->IEV2.Vuns >>= 8; 
    31163130                            if (rm >= (modregrm(3,0,AX) | reg)) 
    31173131                                c->Irm |= 4;    /* AX->AH, BX->BH, etc. */ 
    31183132                            else 
    31193133                                c->IEVoffset1 += 1; 
    31203134                            goto L2; 
    31213135                        } 
    31223136                    } 
    31233137#if 0 
    31243138                    // BUG: which is right? 
    31253139                    else if ((u & 0xFFFF0000) == 0) 
    31263140#else 
    31273141                    else if (0 && op == 0xF7 && 
    31283142                             rm >= modregrm(3,0,SP) && 
    31293143                             (u & 0xFFFF0000) == 0) 
    31303144#endif 
    31313145                        c->Iflags &= ~CFopsize; 
    31323146                } 
    31333147 
    31343148                // Try to replace TEST reg,-1 with TEST reg,reg 
    3135                 if (op == 0xF6 && rm >= modregrm(3,0,AX)) 
    3136                 {       if (u == ~0
     3149                if (op == 0xF6 && rm >= modregrm(3,0,AX) && rm <= modregrm(3,0,7)) // TEST regL,immed8 
     3150                {       if ((u & 0xFF) == 0xFF
    31373151                        { 
    31383152                           L4:  c->Iop = 0x84;          // TEST regL,regL 
    3139                                 c->Irm |= ereg << 3; 
     3153                                c->Irm = modregrm(3,ereg,ereg); 
     3154                                if (c->Irex & REX_B) 
     3155                                    c->Irex |= REX_R; 
    31403156                                c->Iflags &= ~CFopsize; 
    31413157                                goto L1; 
    31423158                        } 
    31433159                } 
    3144                 if (op == 0xF7 && rm >= modregrm(3,0,AX) && ereg < SP
     3160                if (op == 0xF7 && rm >= modregrm(3,0,AX) && rm <= modregrm(3,0,7) && (I64 || ereg < 4)
    31453161                {       if (u == 0xFF) 
    31463162                                goto L4; 
    3147                         if (u == ~0xFF && !longop
    3148                         {       rm |= 4;                /* to regH      */ 
     3163                        if ((u & 0xFFFF) == 0xFF00 && shortop && !c->Irex && ereg < 4
     3164                        {       ereg |= 4;                /* to regH      */ 
    31493165                                goto L4; 
    31503166                        } 
    31513167                } 
    31523168 
    31533169                /* Look for sign extended immediate data */ 
    31543170                if ((signed char) u == u) 
    31553171                { 
    31563172                    if (op == 0x81) 
    31573173                    {   if (reg != 0x08 && reg != 0x20 && reg != 0x30) 
    31583174                            c->Iop = op = 0x83;         /* 8 bit sgn ext */ 
    31593175                    } 
    31603176                    else if (op == 0x69)                /* IMUL rw,ew,dw */ 
    31613177                        c->Iop = op = 0x6B;             /* IMUL rw,ew,db */ 
    31623178                } 
    31633179 
    31643180                // Look for SHIFT EA,imm8 we can replace with short form 
    31653181                if (u == 1 && ((op & 0xFE) == 0xC0)) 
    31663182                    c->Iop |= 0xD0; 
    31673183 
    31683184            } /* if immediate second operand */ 
    31693185 
    31703186            /* Look for AX short form */ 
    31713187            if (ins & A) 
    3172             {   if (rm == modregrm(0,AX,local_BPRM) && (op & ~3) == 0x88) 
     3188            {   if (rm == modregrm(0,AX,local_BPRM) && 
     3189                    !(c->Irex & REX_R) &&               // and it's AX, not R8 
     3190                    (op & ~3) == 0x88 && 
     3191                    !I64) 
    31733192                {       op = ((op & 3) + 0xA0) ^ 2; 
    31743193                        /* 8A-> A0 */ 
    31753194                        /* 8B-> A1 */ 
    31763195                        /* 88-> A2 */ 
    31773196                        /* 89-> A3 */ 
    31783197                        c->Iop = op; 
    31793198                        c->IFL2 = c->IFL1; 
    31803199                        c->IEV2 = c->IEV1; 
    31813200                } 
    31823201 
    31833202                /* Replace MOV REG1,REG2 with MOV EREG1,EREG2   */ 
    3184                 else if (I32 && 
     3203                else if (!I16 && 
    31853204                         (op == 0x89 || op == 0x8B) && 
    31863205                         (rm & 0xC0) == 0xC0 && 
    31873206                         (!b || b->BC != BCasm) 
    31883207                        ) 
    31893208                    c->Iflags &= ~CFopsize; 
    31903209 
    3191                 else if ((rm & 0xC7) == 0xC0) 
     3210                // If rm is AX 
     3211                else if ((rm & modregrm(3,0,7)) == modregrm(3,0,AX) && !(c->Irex & (REX_R | REX_B))) 
    31923212                {       switch (op) 
    31933213                        {   case 0x80:  op = reg | 4; break; 
    31943214                            case 0x81:  op = reg | 5; break; 
    3195                             case 0x87:  op = 0x90 + (reg>>3); break; 
     3215                            case 0x87:  op = 0x90 + (reg>>3); break;    // XCHG 
    31963216                            case 0xF6: 
    31973217                                if (reg == 0) 
    31983218                                    op = 0xA8;  /* TEST AL,immed8       */ 
    31993219                                break; 
    32003220                            case 0xF7: 
    32013221                                if (reg == 0) 
    32023222                                    op = 0xA9;  /* TEST AX,immed16      */ 
    32033223                                break; 
    32043224                        } 
    32053225                        c->Iop = op; 
    32063226                } 
    32073227            } 
    32083228 
    32093229            /* Look for reg short form */ 
    32103230            if ((ins & R) && (rm & 0xC0) == 0xC0) 
    32113231            {   switch (op) 
    32123232                {   case 0xC6:  op = 0xB0 + ereg; break; 
    32133233                    case 0xC7:  op = 0xB8 + ereg; break; 
    32143234                    case 0xFF: 
    32153235                        switch (reg) 
    32163236                        {   case 6<<3: op = 0x50+ereg; break;/* PUSH*/ 
    3217                             case 0<<3: op = 0x40+ereg; break; /* INC*/ 
    3218                             case 1<<3: op = 0x48+ereg; break; /* DEC*/ 
     3237                            case 0<<3: if (!I64) op = 0x40+ereg; break; /* INC*/ 
     3238                            case 1<<3: if (!I64) op = 0x48+ereg; break; /* DEC*/ 
    32193239                        } 
    32203240                        break; 
    32213241                    case 0x8F:  op = 0x58 + ereg; break; 
    32223242                    case 0x87: 
    32233243                        if (reg == 0) op = 0x90 + ereg; 
    32243244                        break; 
    32253245                } 
    32263246                c->Iop = op; 
    32273247            } 
    32283248 
    32293249            // Look to replace SHL reg,1 with ADD reg,reg 
    32303250            if ((op & 0xFE) == 0xD0 && 
    32313251                     (rm & modregrm(3,7,0)) == modregrm(3,4,0) && 
    32323252                     config.target_cpu >= TARGET_80486) 
    32333253            { 
    32343254                c->Iop &= 1; 
    32353255                c->Irm = (rm & modregrm(3,0,7)) | (ereg << 3); 
    3236                 if (!(c->Iflags & CFpsw) && I32) 
     3256                if (c->Irex & REX_B) 
     3257                    c->Irex |= REX_R; 
     3258                if (!(c->Iflags & CFpsw) && !I16) 
    32373259                    c->Iflags &= ~CFopsize; 
    32383260                goto L1; 
    32393261            } 
    32403262 
    32413263            /* Look for sign extended modregrm displacement, or 0 
    32423264             * displacement. 
    32433265             */ 
    32443266 
    32453267            if (((rm & 0xC0) == 0x80) && // it's a 16/32 bit disp 
    32463268                c->IFL1 == FLconst)      // and it's a constant 
    32473269            { 
    32483270                a = c->IEVpointer1; 
    3249                 if (a == 0 && (rm & 7) != local_BPRM &&         // if 0 disp 
    3250                     !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP
     3271                if (a == 0 && (rm & 7) != local_BPRM &&         // if 0[disp] 
     3272                    !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP && !(c->Irex & REX_B)
    32513273                   ) 
    32523274                    c->Irm &= 0x3F; 
    3253                 else if (I32
     3275                else if (!I16
    32543276                { 
    32553277                    if ((targ_size_t)(targ_schar)a == a) 
    32563278                        c->Irm ^= 0xC0;                 /* do 8 sx      */ 
    32573279                } 
    32583280                else if (((targ_size_t)(targ_schar)a & 0xFFFF) == (a & 0xFFFF)) 
    32593281                    c->Irm ^= 0xC0;                     /* do 8 sx      */ 
    32603282            } 
    32613283 
    32623284            /* Look for LEA reg,[ireg], replace with MOV reg,ireg       */ 
    32633285            else if (op == 0x8D) 
    32643286            {   rm = c->Irm & 7; 
    32653287                mod = c->Irm & modregrm(3,0,0); 
    32663288                if (mod == 0) 
    32673289                { 
    3268                     if (I32
     3290                    if (!I16
    32693291                    { 
    32703292                        switch (rm) 
    32713293                        { 
    32723294                            case 4: 
    32733295                            case 5: 
    32743296                                break; 
    32753297                            default: 
    32763298                                c->Irm |= modregrm(3,0,0); 
    32773299                                c->Iop = 0x8B; 
    32783300                                break; 
    32793301                        } 
    32803302                    } 
    32813303                    else 
    32823304                    { 
    32833305                        switch (rm) 
    32843306                        { 
    32853307                            case 4:     rm = modregrm(3,0,SI);  goto L6; 
    32863308                            case 5:     rm = modregrm(3,0,DI);  goto L6; 
    32873309                            case 7:     rm = modregrm(3,0,BX);  goto L6; 
    32883310                            L6:     c->Irm = rm + reg; 
    32893311                                    c->Iop = 0x8B; 
    32903312                                    break; 
    32913313                        } 
    32923314                    } 
    32933315                } 
    32943316 
    32953317                /* replace LEA reg,0[BP] with MOV reg,BP        */ 
    32963318                else if (mod == modregrm(1,0,0) && rm == local_BPRM && 
    32973319                        c->IFL1 == FLconst && c->IEVpointer1 == 0) 
    32983320                {       c->Iop = 0x8B;          /* MOV reg,BP   */ 
    32993321                        c->Irm = modregrm(3,0,BP) + reg; 
    33003322                } 
     3323            } 
     3324 
     3325            // Replace [R13] with 0[R13] 
     3326            if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 
     3327            { 
     3328                c->Irm |= modregrm(1,0,0); 
     3329                c->IFL1 = FLconst; 
     3330                c->IEVpointer1 = 0; 
    33013331            } 
    33023332        } 
    33033333        else 
    33043334        { 
    33053335            switch (op) 
    33063336            { 
    33073337                default: 
    33083338                    if ((op & 0xF0) != 0x70) 
    33093339                        break; 
    33103340                case JMP: 
    33113341                    switch (c->IFL2) 
    33123342                    {   case FLcode: 
    33133343                                if (c->IEV2.Vcode == code_next(c)) 
    33143344                                {       c->Iop = NOP; 
    33153345                                        continue; 
    33163346                                } 
    33173347                                break; 
    33183348                        case FLblock: 
    33193349                                if (!code_next(c) && c->IEV2.Vblock == bn) 
    33203350                                {       c->Iop = NOP; 
    33213351                                        continue; 
    33223352                                } 
    33233353                                break; 
    33243354                        case FLconst: 
    33253355                        case FLfunc: 
    33263356                        case FLextern: 
    33273357                                break; 
    33283358                        default: 
    33293359#ifdef DEBUG 
    33303360                                WRFL((enum FL)c->IFL2); 
    33313361#endif 
    33323362                                assert(0); 
    33333363                    } 
    33343364                    break; 
    33353365 
    33363366                case 0x68:                      // PUSH immed16 
    33373367                    if (c->IFL2 == FLconst) 
    3338                     {   targ_long u; 
    3339  
    3340                         u = c->IEV2.Vuns; 
    3341                         if ((c->Iflags & CFopsize) ? !I32 : I32) 
    3342                         {   if (u == (signed char) u) 
     3368                    { 
     3369                        targ_long u = c->IEV2.Vuns; 
     3370                        if (I64 || 
     3371                            ((c->Iflags & CFopsize) ? I16 : I32)) 
     3372                        {   // PUSH 32/64 bit operand 
     3373                            if (u == (signed char) u) 
    33433374                                c->Iop = 0x6A;          // PUSH immed8 
    33443375                        } 
    3345                         else 
     3376                        else // PUSH 16 bit operand 
    33463377                        {   if ((short)u == (signed char) u) 
    33473378                                c->Iop = 0x6A;          // PUSH immed8 
    33483379                        } 
    33493380                    } 
    33503381                    break; 
    33513382            } 
    33523383        } 
    33533384  } 
    33543385#if 0 
    33553386  if (1 || debugc) { 
    33563387      printf("-pinholeopt(%p)\n",cstart); 
    33573388        for (c = cstart; c; c = code_next(c)) 
    33583389            c->print(); 
    33593390  } 
    33603391#endif 
    33613392} 
    33623393 
     3394#ifdef DEBUG 
     3395STATIC void pinholeopt_unittest() 
     3396{ 
     3397    //printf("pinholeopt_unittest()\n"); 
     3398    struct CS { unsigned model,op,ea,ev1,ev2,flags; } tests[][2] = 
     3399    { 
     3400        // XOR reg,immed                            NOT regL 
     3401        {{ 16,0x81,modregrm(3,6,BX),0,0xFF,0 },    { 0,0xF6,modregrm(3,2,BX),0,0xFF }}, 
     3402 
     3403#if 0 // only if config.flags4 & CFG4space 
     3404        // TEST regL,immed8 
     3405        {{ 0,0xF6,modregrm(3,0,BX),0,0xFF,0 },    { 0,0x84,modregrm(3,BX,BX),0,0xFF }}, 
     3406        {{ 0,0xF7,modregrm(3,0,BX),0,0xFF,0 },    { 0,0x84,modregrm(3,BX,BX),0,0xFF }}, 
     3407        {{ 64,0xF6,modregrmx(3,0,R8),0,0xFF,0 },  { 0,0x84,modregxrmx(3,R8,R8),0,0xFF }}, 
     3408        {{ 64,0xF7,modregrmx(3,0,R8),0,0xFF,0 },  { 0,0x84,modregxrmx(3,R8,R8),0,0xFF }}, 
     3409#endif 
     3410 
     3411        // PUSH immed => PUSH immed8 
     3412        {{ 0,0x68,0,0,0 },    { 0,0x6A,0,0,0 }}, 
     3413        {{ 0,0x68,0,0,0x7F }, { 0,0x6A,0,0,0x7F }}, 
     3414        {{ 0,0x68,0,0,0x80 }, { 0,0x68,0,0,0x80 }}, 
     3415        {{ 16,0x68,0,0,0,CFopsize },    { 0,0x6A,0,0,0,CFopsize }}, 
     3416        {{ 16,0x68,0,0,0x7F,CFopsize }, { 0,0x6A,0,0,0x7F,CFopsize }}, 
     3417        {{ 16,0x68,0,0,0x80,CFopsize }, { 0,0x68,0,0,0x80,CFopsize }}, 
     3418        {{ 16,0x68,0,0,0x10000,0 },     { 0,0x6A,0,0,0x10000,0 }}, 
     3419        {{ 16,0x68,0,0,0x10000,CFopsize }, { 0,0x68,0,0,0x10000,CFopsize }}, 
     3420        {{ 32,0x68,0,0,0,CFopsize },    { 0,0x6A,0,0,0,CFopsize }}, 
     3421        {{ 32,0x68,0,0,0x7F,CFopsize }, { 0,0x6A,0,0,0x7F,CFopsize }}, 
     3422        {{ 32,0x68,0,0,0x80,CFopsize }, { 0,0x68,0,0,0x80,CFopsize }}, 
     3423        {{ 32,0x68,0,0,0x10000,CFopsize },    { 0,0x6A,0,0,0x10000,CFopsize }}, 
     3424        {{ 32,0x68,0,0,0x8000,CFopsize }, { 0,0x68,0,0,0x8000,CFopsize }}, 
     3425    }; 
     3426 
     3427    //config.flags4 |= CFG4space; 
     3428    for (int i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) 
     3429    {   CS *pin  = &tests[i][0]; 
     3430        CS *pout = &tests[i][1]; 
     3431        code cs; 
     3432        memset(&cs, 0, sizeof(cs)); 
     3433        if (pin->model) 
     3434        { 
     3435            if (I16 && pin->model != 16) 
     3436                continue; 
     3437            if (I32 && pin->model != 32) 
     3438                continue; 
     3439            if (I64 && pin->model != 64) 
     3440                continue; 
     3441        } 
     3442        //printf("[%d]\n", i); 
     3443        cs.Iop = pin->op; 
     3444        cs.Iea = pin->ea; 
     3445        cs.IFL1 = FLconst; 
     3446        cs.IFL2 = FLconst; 
     3447        cs.IEV1.Vuns = pin->ev1; 
     3448        cs.IEV2.Vuns = pin->ev2; 
     3449        cs.Iflags = pin->flags; 
     3450        pinholeopt(&cs, NULL); 
     3451        if (cs.Iop != pout->op) 
     3452        {   printf("[%d] Iop = x%02x, pout = x%02x\n", i, cs.Iop, pout->op); 
     3453            assert(0); 
     3454        } 
     3455        assert(cs.Iea == pout->ea); 
     3456        assert(cs.IEV1.Vuns == pout->ev1); 
     3457        assert(cs.IEV2.Vuns == pout->ev2); 
     3458        assert(cs.Iflags == pout->flags); 
     3459    } 
     3460} 
     3461#endif 
    33633462 
    33643463/************************** 
    33653464 * Compute jump addresses for FLcode. 
    33663465 * Note: only works for forward referenced code. 
    33673466 *       only direct jumps and branches are detected. 
    33683467 *       LOOP instructions only work for backward refs. 
    33693468 */ 
    33703469 
    33713470void jmpaddr(code *c) 
    33723471{ code *ci,*cn,*ctarg,*cstart; 
    33733472  targ_size_t ad; 
    33743473  unsigned char op; 
    33753474 
    33763475  //printf("jmpaddr()\n"); 
    33773476  cstart = c;                           /* remember start of code       */ 
    33783477  while (c) 
    33793478  { 
    33803479        op = c->Iop; 
    33813480        if (inssize[op] & T &&          /* if second operand            */ 
    33823481            c->IFL2 == FLcode && 
     
    35593658            } 
    35603659            if (iflags & CFopsize) 
    35613660                size++;                         /* +1 for OPSIZE prefix         */ 
    35623661        } 
    35633662    } 
    35643663 
    35653664    if ((op & 0xF0) == 0x70) 
    35663665    {   if (iflags & CFjmp16)           // if long branch 
    35673666            size += I16 ? 3 : 4;        // + 3(4) bytes for JMP 
    35683667    } 
    35693668    else if (ins & M)                   // if modregrm byte 
    35703669    { 
    35713670        rm = c->Irm; 
    35723671        mod = rm & 0xC0; 
    35733672        if (a32 || I64) 
    35743673        {   // 32 bit addressing 
    35753674            if (issib(rm)) 
    35763675                size++; 
    35773676            switch (mod) 
    35783677            {   case 0: 
    3579                     if (issib(rm) && (c->Isib & 7) == 5 || (rm & 7) == 5) 
     3678                    if (issib(rm) && (c->Isib & 7) == 5 || 
     3679                        (rm & 7) == 5) 
    35803680                        size += 4;      /* disp32                       */ 
     3681                    if (c->Irex & REX_B && (rm & 7) == 5) 
     3682                        /* Instead of selecting R13, this mode is an [RIP] relative 
     3683                         * address. Although valid, it's redundant, and should not 
     3684                         * be generated. Instead, generate 0[R13] instead of [R13]. 
     3685                         */ 
     3686                        assert(0); 
    35813687                    break; 
    35823688                case 0x40: 
    35833689                    size++;             /* disp8                        */ 
    35843690                    break; 
    35853691                case 0x80: 
    35863692                    size += 4;          /* disp32                       */ 
    35873693                    break; 
    35883694            } 
    35893695        } 
    35903696        else 
    35913697        {   // 16 bit addressing 
    35923698            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    35933699                size++; 
    35943700            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    35953701                size += 2; 
    35963702        } 
    35973703    } 
    35983704 
    35993705Lret: 
    36003706    if (c->Irex) 
     
    37273833 
    37283834STATIC void cod3_flush() 
    37293835{ 
    37303836    // Emit accumulated bytes to code segment 
    37313837#ifdef DEBUG 
    37323838    assert(pgen - bytes < sizeof(bytes)); 
    37333839#endif 
    37343840    offset += obj_bytes(cseg,offset,pgen - bytes,bytes); 
    37353841    pgen = bytes; 
    37363842} 
    37373843 
    37383844unsigned codout(code *c) 
    37393845{ unsigned op; 
    37403846  unsigned char rm,mod; 
    37413847  unsigned char ins; 
    37423848  code *cn; 
    37433849  unsigned flags; 
    37443850  symbol *s; 
    37453851 
    37463852#ifdef DEBUG 
    3747   if (debugc) printf("codout(%p), Coffset = x%lx\n",c,Coffset); 
     3853  if (debugc) printf("codout(%p), Coffset = x%llx\n",c,(unsigned long long)Coffset); 
    37483854#endif 
    37493855 
    37503856  pgen = bytes; 
    37513857  offset = Coffset; 
    37523858  for (; c; c = code_next(c)) 
    37533859  { 
    37543860#ifdef DEBUG 
    37553861        if (debugc) { printf("off=%02lx, sz=%ld, ",(long)OFFSET(),(long)calccodsize(c)); c->print(); } 
    37563862#endif 
    37573863        op = c->Iop; 
    37583864        ins = inssize[op]; 
    37593865        switch (op) 
    37603866        {   case ESCAPE: 
    37613867                switch (c->Iop2) 
    37623868                {   case ESClinnum: 
    37633869                        /* put out line number stuff    */ 
    37643870                        objlinnum(c->IEV2.Vsrcpos,OFFSET()); 
    37653871                        break; 
    37663872#if SCPP 
    37673873#if 1 
     
    48914997            printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 
    48924998        } 
    48934999        if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 
    48945000        { 
    48955001            switch (c->IFL1) 
    48965002            { 
    48975003                case FLconst: 
    48985004                case FLoffset: 
    48995005                    printf(" int = %4d",c->IEV1.Vuns); 
    49005006                    break; 
    49015007                case FLblock: 
    49025008                    printf(" block = %p",c->IEV1.Vblock); 
    49035009                    break; 
    49045010                case FLswitch: 
    49055011                case FLblockoff: 
    49065012                case FLlocalsize: 
    49075013                case FLframehandler: 
    49085014                case 0: 
    49095015                    break; 
    49105016                case FLdatseg: 
    4911                     printf(" %d.%lx",c->IEVseg1,c->IEVpointer1); 
     5017                    printf(" %d.%llx",c->IEVseg1,(unsigned long long)c->IEVpointer1); 
    49125018                    break; 
    49135019                case FLauto: 
    49145020                case FLreg: 
    49155021                case FLdata: 
    49165022                case FLudata: 
    49175023                case FLpara: 
    49185024                case FLtmp: 
    49195025                case FLbprel: 
    49205026                case FLtlsdata: 
    49215027                    printf(" sym='%s'",c->IEVsym1->Sident); 
    49225028                    break; 
    49235029                default: 
    49245030                    WRFL((enum FL)c->IFL1); 
    49255031                    break; 
    49265032            } 
    49275033        } 
    49285034  } 
    49295035  if (ins & T) 
    49305036  {     printf(" "); WRFL((enum FL)c->IFL2); 
    49315037        switch (c->IFL2) 
    49325038        { 
    49335039            case FLconst: 
    49345040                printf(" int = %4d",c->IEV2.Vuns); 
    49355041                break; 
    49365042            case FLblock: 
    49375043                printf(" block = %p",c->IEV2.Vblock); 
    49385044                break; 
    49395045            case FLswitch: 
    49405046            case FLblockoff: 
    49415047            case 0: 
    49425048            case FLlocalsize: 
    49435049            case FLframehandler: 
    49445050                break; 
    49455051            case FLdatseg: 
    4946                 printf(" %d.%lx",c->IEVseg2,c->IEVpointer2); 
     5052                printf(" %d.%llx",c->IEVseg2,(unsigned long long)c->IEVpointer2); 
    49475053                break; 
    49485054            case FLauto: 
    49495055            case FLreg: 
    49505056            case FLpara: 
    49515057            case FLtmp: 
    49525058            case FLbprel: 
    49535059            case FLfunc: 
    49545060            case FLdata: 
    49555061            case FLudata: 
    49565062            case FLtlsdata: 
    49575063                printf(" sym='%s'",c->IEVsym2->Sident); 
    49585064                break; 
    49595065            case FLcode: 
    49605066                printf(" code = %p",c->IEV2.Vcode); 
    49615067                break; 
    49625068            default: 
    49635069                WRFL((enum FL)c->IFL2); 
    49645070                break; 
    49655071        } 
    49665072  } 
  • trunk/src/backend/code.h

    r580 r581  
    150150#define SEG_ES  0 
    151151#define SEG_CS  1 
    152152#define SEG_SS  2 
    153153#define SEG_DS  3 
    154154 
    155155/********************* 
    156156 * Masks for register pairs. 
    157157 * Note that index registers are always LSWs. This is for the convenience 
    158158 * of implementing far pointers. 
    159159 */ 
    160160 
    161161#if 0 
    162162// Give us an extra one so we can enregister a long 
    163163#define mMSW    (mCX|mDX|mDI|mES)       // most significant regs 
    164164#define mLSW    (mAX|mBX|mSI)           // least significant regs 
    165165#else 
    166166#define mMSW    (mCX|mDX|mES)           /* most significant regs        */ 
    167167#define mLSW    (mAX|mBX|mSI|mDI)       /* least significant regs       */ 
    168168#endif 
    169169 
    170 /* Return !=0 if there is an SIB byte   */ 
     170/* Return !=0 if there is a SIB byte   */ 
    171171#define issib(rm)       (((rm) & 7) == 4 && ((rm) & 0xC0) != 0xC0) 
    172172 
    173173#if 0 
    174174// relocation field size is always 32bits 
    175175#define is32bitaddr(x,Iflags) (1) 
    176176#else 
    177177// 
    178178// is32bitaddr works correctly only when x is 0 or 1.  This is 
    179179// true today for the current definition of I32, but if the definition 
    180180// of I32 changes, this macro will need to change as well 
    181181// 
    182182// Note: even for linux targets, CFaddrsize can be set by the inline 
    183183// assembler. 
    184184#define is32bitaddr(x,Iflags) (I64 || ((x) ^(((Iflags) & CFaddrsize) !=0))) 
    185185#endif 
    186186 
    187187/******************* 
    188188 * Some instructions. 
    189189 */ 
    190190 
  • trunk/src/backend/el.c

    r580 r581  
    13261326        default: 
    13271327            break; 
    13281328    } 
    13291329    return e; 
    13301330} 
    13311331#endif 
    13321332#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    13331333 
    13341334elem *el_picvar(symbol *s) 
    13351335{   elem *e; 
    13361336    int x; 
    13371337 
    13381338    //printf("el_picvar(s = '%s')\n", s->Sident); 
    13391339    symbol_debug(s); 
    13401340    type_debug(s->Stype); 
    13411341    e = el_calloc(); 
    13421342    e->Eoper = OPvar; 
    13431343    e->EV.sp.Vsym = s; 
    13441344    e->Ety = s->ty(); 
    13451345 
     1346    /* For 32 bit: 
     1347     *      CALL __i686.get_pc_thunk.bx@PC32 
     1348     *      ADD  EBX,offset _GLOBAL_OFFSET_TABLE_@GOTPC[2] 
     1349     * Generate for var locals: 
     1350     *      MOV  reg,s@GOTOFF[014h][EBX] 
     1351     * For var globals: 
     1352     *      MOV  EAX,s@GOT32[EBX] 
     1353     *      MOV  reg,[EAX] 
     1354     * For TLS var locals and globals: 
     1355     *      MOV  EAX,s@TLS_GD[EBX] 
     1356     *      CALL ___tls_get_addr@PLT32 
     1357     *      MOV  reg,[EAX] 
     1358     ***************************************** 
     1359     * Generate for var locals: 
     1360     *      MOV reg,s@PC32[RIP] 
     1361     * For var globals: 
     1362     *      MOV RAX,s@GOTPCREL[RIP] 
     1363     *      MOV reg,[RAX] 
     1364     * For TLS var locals and globals: 
     1365     *      0x66 
     1366     *      LEA DI,s@TLSGD[RIP] 
     1367     *      0x66 
     1368     *      0x66 
     1369     *      0x48 (REX | REX_W) 
     1370     *      CALL __tls_get_addr@PLT32 
     1371     *      MOV reg,[RAX] 
     1372     */ 
     1373 
     1374    if (I64) 
     1375    { 
     1376        elfobj_refGOTsym(); 
     1377        switch (s->Sclass) 
     1378        { 
     1379            case SCstatic: 
     1380            case SClocstat: 
     1381                x = 0; 
     1382                goto case_got64; 
     1383 
     1384            case SCcomdat: 
     1385            case SCcomdef: 
     1386            case SCglobal: 
     1387            case SCextern: 
     1388                x = 1; 
     1389            case_got64: 
     1390            { 
     1391                int op = e->Eoper; 
     1392                tym_t tym = e->Ety; 
     1393                e->Ety = TYnptr; 
     1394 
     1395                if (s->Stype->Tty & mTYthread) 
     1396                { 
     1397                    /* Add "volatile" to prevent e from being common subexpressioned. 
     1398                     * This is so we can preserve the magic sequence of instructions 
     1399                     * that the gnu linker patches: 
     1400                     *   lea EDI,x@tlsgd[RIP], call __tls_get_addr@plt 
     1401                     *      => 
     1402                     *   mov EAX,gs[0], sub EAX,x@tpoff 
     1403                     */ 
     1404                    e->Eoper = OPrelconst; 
     1405                    e->Ety |= mTYvolatile; 
     1406                    if (!tls_get_addr_sym) 
     1407                    { 
     1408                        /* void *__tls_get_addr(void *ptr); 
     1409                         * Parameter ptr is passed in RDI, matching TYnfunc calling convention. 
     1410                         */ 
     1411                        tls_get_addr_sym = symbol_name("__tls_get_addr",SCglobal,type_fake(TYnfunc)); 
     1412                        symbol_keep(tls_get_addr_sym); 
     1413                    } 
     1414                    e = el_bin(OPcall, TYnptr, el_var(tls_get_addr_sym), e); 
     1415                } 
     1416 
     1417                switch (op * 2 + x) 
     1418                { 
     1419                    case OPvar * 2 + 1: 
     1420                        e = el_una(OPind, TYnptr, e); 
     1421                        break; 
     1422                    case OPvar * 2 + 0: 
     1423                    case OPrelconst * 2 + 1: 
     1424                        break; 
     1425                    case OPrelconst * 2 + 0: 
     1426                        e = el_una(OPaddr, TYnptr, e); 
     1427                        break; 
     1428                    default: 
     1429                        assert(0); 
     1430                        break; 
     1431                } 
     1432                e->Ety = tym; 
     1433                break; 
     1434            } 
     1435            default: 
     1436                break; 
     1437        } 
     1438    } 
     1439    else 
    13461440    switch (s->Sclass) 
    13471441    { 
    13481442        /* local (and thread) symbols get only one level of indirection; 
    13491443         * all globally known symbols get two. 
    13501444         */ 
    13511445        case SCstatic: 
    13521446        case SClocstat: 
    13531447            x = 0; 
    13541448            goto case_got; 
    13551449 
    13561450        case SCcomdat: 
    13571451        case SCcomdef: 
    13581452        case SCglobal: 
    13591453        case SCextern: 
    13601454            if (s->Stype->Tty & mTYthread) 
    13611455                x = 0; 
    13621456            else 
    13631457                x = 1; 
    13641458        case_got: 
    13651459        {   if (!localgot) 
     
    14241518            break; 
    14251519    } 
    14261520    return e; 
    14271521} 
    14281522#endif 
    14291523 
    14301524/************************** 
    14311525 * Make an elem out of a symbol. 
    14321526 */ 
    14331527 
    14341528#if MARS 
    14351529elem * el_var(symbol *s) 
    14361530{   elem *e; 
    14371531 
    14381532    //printf("el_var(s = '%s')\n", s->Sident); 
    14391533    //printf("%x\n", s->Stype->Tty); 
    14401534#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    14411535    // OSX is currently always pic 
    14421536    if (config.flags3 & CFG3pic && 
    14431537#if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    1444         !(s->Stype->Tty & mTYthread) && 
     1538        (!(s->Stype->Tty & mTYthread) || I64) && 
    14451539#endif 
    14461540        !tyfunc(s->ty())) 
    14471541        // Position Independent Code 
    14481542        return el_picvar(s); 
    14491543#endif 
    14501544    symbol_debug(s); 
    14511545    type_debug(s->Stype); 
    14521546    e = el_calloc(); 
    14531547    e->Eoper = OPvar; 
    14541548    e->EV.sp.Vsym = s; 
    14551549    type_debug(s->Stype); 
    14561550    e->Ety = s->ty(); 
    14571551    if (s->Stype->Tty & mTYthread) 
    14581552    { 
    14591553        //printf("thread local %s\n", s->Sident); 
    14601554#if TARGET_OSX 
    14611555        ; 
    14621556#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS 
    14631557        /* For 32 bit: 
    14641558         * Generate for var locals: 
     
    14771571         * For var globals: 
    14781572         *      MOV RAX,s@GOTTPOFF[RIP] 
    14791573         *      MOV reg,FS:[RAX] 
    14801574         * 
    14811575         * For address of locals: 
    14821576         *      MOV RAX,FS:[00] 
    14831577         *      LEA reg,s@TPOFF32[RAX] 
    14841578         *      e => &s + *(FS:0) 
    14851579         * For address of globals: 
    14861580         *      MOV reg,FS:[00] 
    14871581         *      MOV RAX,s@GOTTPOFF[RIP] 
    14881582         *      ADD reg,RAX 
    14891583         *      e => s + *(FS:0) 
    14901584         * This leaves us with a problem, as the 'var' version cannot simply have 
    14911585         * its address taken, as what is the address of FS:s ? The (not so efficient) 
    14921586         * solution is to just use the second address form, and * it. 
    14931587         * Turns out that is identical to the 32 bit version, except GS => FS and the 
    14941588         * fixups are different. 
    14951589         * In the future, we should figure out a way to optimize to the 'var' version. 
    14961590         */ 
     1591        if (I64) 
     1592            elfobj_refGOTsym(); 
    14971593        elem *e1 = el_calloc(); 
    14981594        e1->EV.sp.Vsym = s; 
    14991595        if (s->Sclass == SCstatic || s->Sclass == SClocstat) 
    15001596        {   e1->Eoper = OPrelconst; 
    15011597            e1->Ety = TYnptr; 
    15021598        } 
    15031599        else 
    15041600        { 
    15051601            e1->Eoper = OPvar; 
    15061602            e1->Ety = TYnptr; 
    15071603        } 
    15081604 
    15091605        /* Fake GS:[0000] as a load of _tls_array, and then in the back end recognize 
    15101606         * the fake and rewrite it as GS:[0000] (or FS:[0000] for I64), because there is 
    15111607         * no way to represent segment overrides in the elem nodes. 
    15121608         */ 
    15131609        elem *e2 = el_calloc(); 
    15141610        e2->Eoper = OPvar; 
    15151611        e2->EV.sp.Vsym = rtlsym[RTLSYM_TLS_ARRAY]; 
    15161612        e2->Ety = e2->EV.sp.Vsym->ty(); 
  • trunk/src/backend/elfobj.c

    r579 r581  
    6767 *      RI_TYPE_GOT32   R_X86_64_         R_X86_64_ 
    6868 *      RI_TYPE_TLS_GD  R_X86_64_TLSGD    R_X86_64_ 
    6969 *      RI_TYPE_TLS_IE  R_X86_64_GOTTPOFF R_X86_64_ 
    7070 *      RI_TYPE_TLS_LE  R_X86_64_TPOFF32  R_X86_64_ 
    7171 *      RI_TYPE_PLT32   R_X86_64_PLT32    R_X86_64_ 
    7272 *      RI_TYPE_PC32    R_X86_64_PC32     R_X86_64_ 
    7373 */ 
    7474 
    7575/****************************************** 
    7676 */ 
    7777 
    7878symbol *GOTsym; // global offset table reference 
    7979 
    8080symbol *elfobj_getGOTsym() 
    8181{ 
    8282    if (!GOTsym) 
    8383    { 
    8484        GOTsym = symbol_name("_GLOBAL_OFFSET_TABLE_",SCglobal,tspvoid); 
    8585    } 
    8686    return GOTsym; 
     87} 
     88 
     89void elfobj_refGOTsym() 
     90{ 
     91    if (!GOTsym) 
     92    { 
     93        symbol *s = elfobj_getGOTsym(); 
     94        objextern(s); 
     95    } 
    8796} 
    8897 
    8998static void objfile_write(FILE *fd, void *buffer, unsigned len); 
    9099 
    91100STATIC char * objmodtoseg (const char *modname); 
    92101STATIC void obj_browse_flush(); 
    93102STATIC void objfixupp (struct FIXUP *); 
    94103STATIC void ledata_new (int seg,targ_size_t offset); 
    95104void obj_tlssections(); 
    96105 
    97106static IDXSYM elf_addsym(IDXSTR sym, targ_size_t val, unsigned sz, 
    98107                        unsigned typ,unsigned bind,IDXSEC sec); 
    99108static long elf_align(FILE *fd, targ_size_t size, long offset); 
    100109 
    101110// The object file is built is several separate pieces 
    102111 
    103112// Non-repeatable section types have single output buffers 
    104113//      Pre-allocated buffers are defined for: 
    105114//              Section Names string table 
    106115//              Section Headers table 
     
    22962305 *      seg =           where the address is going 
    22972306 *      offset =        offset within seg 
    22982307 *      val =           displacement from address 
    22992308 *      targetdatum =   DATA, CDATA or UDATA, depending where the address is 
    23002309 *      flags =         CFoff, CFseg 
    23012310 * Example: 
    23022311 *      int *abc = &def[3]; 
    23032312 *      to allocate storage: 
    23042313 *              reftodatseg(DATA,offset,3 * sizeof(int *),UDATA); 
    23052314 */ 
    23062315 
    23072316void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 
    23082317        unsigned targetdatum,int flags) 
    23092318{ 
    23102319    Outbuffer *buf; 
    23112320    int save; 
    23122321 
    23132322    buf = SegData[seg]->SDbuf; 
    23142323    save = buf->size(); 
    23152324    buf->setsize(offset); 
    2316     //dbg_printf("reftodatseg(seg=%d, offset=x%lx, val=x%lx,data %x, flags %x )\n", 
    2317     //  seg,offset,val,targetdatum,flags); 
     2325#if 0 
     2326    printf("reftodatseg(seg=%d, offset=x%llx, val=x%llx,data %x, flags %x)\n", 
     2327        seg,(unsigned long long)offset,(unsigned long long)val,targetdatum,flags); 
     2328#endif 
    23182329    /*if (OPT_IS_SET(OPTfwritable_strings)) 
    23192330    { 
    23202331        elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 
    23212332    } 
    23222333    else*/ 
    23232334    { 
    23242335        int relinfo; 
    23252336 
    23262337        if (I64) 
    23272338        { 
    23282339            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
    23292340                relinfo = R_X86_64_PC32; 
    23302341            else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 
    23312342                relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 
    23322343            else 
    23332344                relinfo = R_X86_64_32; 
    23342345        } 
    23352346        else 
    23362347        { 
    23372348            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
     
    24022413 *      flags =         CFselfrel: self-relative 
    24032414 *                      CFseg: get segment 
    24042415 *                      CFoff: get offset 
    24052416 *                      CFoffset64: 64 bit fixup 
    24062417 * Returns: 
    24072418 *      number of bytes in reference (4 or 8) 
    24082419 */ 
    24092420 
    24102421int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 
    24112422        int flags) 
    24122423{ 
    24132424    tym_t ty; 
    24142425    bool external = TRUE; 
    24152426    Outbuffer *buf; 
    24162427    elf_u32_f32 relinfo,refseg; 
    24172428    int segtyp = MAP_SEG2TYP(seg); 
    24182429    //assert(val == 0); 
    24192430    int retsize = (flags & CFoffset64) ? 8 : 4; 
    24202431 
    24212432#if 0 
    2422     dbg_printf("\nreftoident('%s' seg %d, offset x%lx, val x%lx, flags x%x)\n", 
     2433    printf("\nreftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", 
    24232434        s->Sident,seg,offset,val,flags); 
    2424     dbg_printf("Sseg = %d, Sxtrnnum = %d\n",s->Sseg,s->Sxtrnnum); 
     2435    dbg_printf("Sseg = %d, Sxtrnnum = %d, retsize = %d\n",s->Sseg,s->Sxtrnnum,retsize); 
    24252436    symbol_print(s); 
    24262437#endif 
    24272438 
    24282439    ty = s->ty(); 
    24292440    if (s->Sxtrnnum) 
    24302441    {                           // identifier is defined somewhere else 
    24312442        if (I64) 
    24322443        { 
    24332444            if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24342445                external = FALSE; 
    24352446        } 
    24362447        else 
    24372448        { 
    24382449            if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24392450                external = FALSE; 
    24402451        } 
    24412452    } 
    24422453 
    24432454    switch (s->Sclass) 
    24442455    { 
     
    25032514                    if (!external &&            // local definition found 
    25042515                         s->Sseg == seg &&      // within same code segment 
    25052516                          (!(config.flags3 & CFG3pic) ||        // not position indp code 
    25062517                           s->Sclass == SCstatic)) // or is pic, but declared static 
    25072518                    {                   // Can use PC relative 
    25082519                        //dbg_printf("\tdoing PC relative\n"); 
    25092520                        val = (s->Soffset+val) - (offset+4); 
    25102521                    } 
    25112522                    else 
    25122523                    { 
    25132524                        val = (targ_size_t)-4; 
    25142525                        //dbg_printf("\tadding relocation\n"); 
    25152526                        if (I64) 
    25162527                            relinfo = config.flags3 & CFG3pic ?  R_X86_64_PLT32 : R_X86_64_PC32; 
    25172528                        else 
    25182529                            relinfo = config.flags3 & CFG3pic ?  RI_TYPE_PLT32 : RI_TYPE_PC32; 
    25192530                        elf_addrel(seg,offset, 
    25202531                                relinfo, 
    25212532                                s->Sxtrnnum,0); 
    25222533                    } 
     2534                    if (I64) 
     2535                        val += 4; 
    25232536                } 
    25242537                else 
    25252538                {       // code to code code to data, data to code, data to data refs 
    25262539                    refseg = s->Sxtrnnum;       // default to name symbol table entry 
    25272540                    if (s->Sclass == SCstatic) 
    25282541                    {                           // offset into .data or .bss seg 
    25292542                        refseg = MAP_SEG2SYMIDX(s->Sseg); 
    25302543                                                // use segment symbol table entry 
    25312544                        val += s->Soffset; 
    25322545                        if (!(config.flags3 & CFG3pic) ||       // all static refs from normal code 
    25332546                             segtyp == DATA)    // or refs from data from posi indp 
    25342547                        { 
    25352548                           relinfo = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 
    25362549                        } 
    25372550                        else 
    25382551                        { 
    25392552                            relinfo = I64 ? R_X86_64_PC32 : RI_TYPE_GOTOFF; 
    25402553                        } 
    25412554                    } 
    25422555                    else if (config.flags3 & CFG3pic && s == GOTsym) 
    25432556                    {                   // relocation for Gbl Offset Tab 
    25442557                        relinfo =  I64 ? R_X86_64_NONE : RI_TYPE_GOTPC; 
    25452558                    } 
    25462559                    else if (segtyp == DATA) 
    25472560                    {                   // relocation from within DATA seg 
    25482561                        relinfo = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 
    25492562                    } 
    25502563                    else 
    25512564                    {                   // relocation from within CODE seg 
    25522565                        if (I64) 
    2553                             relinfo = config.flags3 & CFG3pic ? R_X86_64_NONE : R_X86_64_32; 
     2566                        {   if (config.flags3 & CFG3pic) 
     2567                                relinfo = R_X86_64_GOTPCREL; 
     2568                            else 
     2569                                relinfo = (flags & CFpc32) ? R_X86_64_PC32 : R_X86_64_32; 
     2570                        } 
    25542571                        else 
    25552572                            relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOT32 : RI_TYPE_SYM32; 
    25562573                    } 
    25572574                    if ((s->ty() & mTYLINK) & mTYthread) 
    25582575                    { 
    25592576                        if (I64) 
    25602577                        { 
    25612578                            if (config.flags3 & CFG3pic) 
    25622579                            { 
    2563                                 if (s->Sclass == SCstatic
    2564                                     relinfo = R_X86_64_TPOFF32;  // TLS_GD? 
     2580                                if (s->Sclass == SCstatic || s->Sclass == SClocstat
     2581                                    relinfo = R_X86_64_TLSGD;  // TLS_GD? 
    25652582                                else 
    2566                                     relinfo = R_X86_64_GOTTPOFF
     2583                                    relinfo = R_X86_64_TLSGD
    25672584                            } 
    25682585                            else 
    25692586                            { 
    2570                                 if (s->Sclass == SCstatic
     2587                                if (s->Sclass == SCstatic || s->Sclass == SClocstat
    25712588                                    relinfo = R_X86_64_TPOFF32; 
    25722589                                else 
    25732590                                    relinfo = R_X86_64_GOTTPOFF; 
    25742591                            } 
    25752592                        } 
    25762593                        else 
    25772594                        { 
    25782595                            if (config.flags3 & CFG3pic) 
    25792596                            { 
    25802597                                if (s->Sclass == SCstatic) 
    25812598                                    relinfo = RI_TYPE_TLS_LE;  // TLS_GD? 
    25822599                                else 
    25832600                                    relinfo = RI_TYPE_TLS_IE; 
    25842601                            } 
    25852602                            else 
    25862603                            { 
    25872604                                if (s->Sclass == SCstatic) 
    25882605                                    relinfo = RI_TYPE_TLS_LE; 
    25892606                                else 
    25902607                                    relinfo = RI_TYPE_TLS_IE; 
  • trunk/src/clone.c

    r428 r581  
    100100        if (tv->ty == Tstruct) 
    101101        {   TypeStruct *ts = (TypeStruct *)tv; 
    102102            StructDeclaration *sd = ts->sym; 
    103103            if (sd->eq) 
    104104                goto Lneed; 
    105105        } 
    106106    } 
    107107Ldontneed: 
    108108    if (X) printf("\tdontneed\n"); 
    109109    return 0; 
    110110 
    111111Lneed: 
    112112    if (X) printf("\tneed\n"); 
    113113    return 1; 
    114114#undef X 
    115115} 
    116116 
    117117/****************************************** 
    118118 * Build opAssign for struct. 
    119119 *      S* opAssign(S s) { ... } 
     120 * 
     121 * Note that s will be constructed onto the stack, probably copy-constructed. 
     122 * Then, the body is: 
     123 *      S tmp = *this;  // bit copy 
     124 *      *this = s;      // bit copy 
     125 *      tmp.dtor(); 
     126 * Instead of running the destructor on s, run it on tmp instead. 
    120127 */ 
    121128 
    122129FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) 
    123130{ 
    124131    if (!needOpAssign()) 
    125132        return NULL; 
    126133 
    127134    //printf("StructDeclaration::buildOpAssign() %s\n", toChars()); 
    128135 
    129136    FuncDeclaration *fop = NULL; 
    130137 
    131138    Parameter *param = new Parameter(STCnodtor, type, Id::p, NULL); 
    132139    Parameters *fparams = new Parameters; 
    133140    fparams->push(param); 
    134141    Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd); 
    135142#if STRUCTTHISREF 
    136143    ((TypeFunction *)ftype)->isref = 1; 
    137144#endif 
    138145 
    139146    fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype);