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

Changeset 596

Show
Ignore:
Timestamp:
08/04/10 08:19:55 (14 years ago)
Author:
walter
Message:

refactor Iop

Files:

Legend:

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

    r595 r596  
    13431343            dbg_printf(" block (%p) Btry=%p Bindex=%d\n",b,b->Btry,b->Bindex); 
    13441344        } 
    13451345#endif 
    13461346        except_index_set(b->Bindex); 
    13471347        if (btry != b->Btry)                    // exited previous try block 
    13481348        { 
    13491349            except_pop(b,NULL,btry); 
    13501350            btry = b->Btry; 
    13511351        } 
    13521352        if (b->BC == BCtry) 
    13531353        { 
    13541354            except_push(b,NULL,b); 
    13551355            btry = b; 
    13561356            tryidx = except_index_get(); 
    13571357            b->Bcode = cat(nteh_gensindex(tryidx - 1),b->Bcode); 
    13581358        } 
    13591359 
    13601360        stack = NULL; 
    13611361        for (c = b->Bcode; c; c = code_next(c)) 
    13621362        { 
    1363             if (c->Iop == ESCAPE) 
     1363            if ((c->Iop & 0xFF) == ESCAPE) 
    13641364            { 
    13651365                c1 = NULL; 
    1366                 switch (c->Iop2
     1366                switch (c->Iop & 0xFF00
    13671367                { 
    13681368                    case ESCctor: 
    13691369//printf("ESCctor\n"); 
    13701370                        except_push(c,c->IEV1.Vtor,NULL); 
    13711371                        goto L1; 
    13721372 
    13731373                    case ESCdtor: 
    13741374//printf("ESCdtor\n"); 
    13751375                        except_pop(c,c->IEV1.Vtor,NULL); 
    13761376                    L1: if (config.flags2 & CFG2seh) 
    13771377                        { 
    13781378                            c1 = nteh_gensindex(except_index_get() - 1); 
    13791379                            code_next(c1) = code_next(c); 
    13801380                            code_next(c) = c1; 
    13811381                        } 
    13821382                        break; 
    13831383                    case ESCmark: 
    13841384//printf("ESCmark\n"); 
    13851385                        idx = except_index_get(); 
    13861386                        list_prependdata(&stack,idx); 
    13871387                        except_mark(); 
    13881388                        break; 
    13891389                    case ESCrelease: 
    13901390//printf("ESCrelease\n"); 
    13911391                        idx = list_data(stack); 
    13921392                        list_pop(&stack); 
    13931393                        if (idx != except_index_get()) 
    13941394                        { 
    13951395                            if (config.flags2 & CFG2seh) 
    13961396                            {   c1 = nteh_gensindex(idx - 1); 
    13971397                                code_next(c1) = code_next(c); 
    13981398                                code_next(c) = c1; 
    13991399                            } 
    14001400                            else 
    14011401                            {   except_pair_append(c,idx - 1); 
    1402                                 c->Iop2 = ESCoffset; 
     1402                                c->Iop = ESCAPE | ESCoffset; 
    14031403                            } 
    14041404                        } 
    14051405                        except_release(); 
    14061406                        break; 
    14071407                    case ESCmark2: 
    14081408//printf("ESCmark2\n"); 
    14091409                        except_mark(); 
    14101410                        break; 
    14111411                    case ESCrelease2: 
    14121412//printf("ESCrelease2\n"); 
    14131413                        except_release(); 
    14141414                        break; 
    14151415                } 
    14161416            } 
    14171417        } 
    14181418        assert(stack == NULL); 
    14191419        b->Bendindex = except_index_get(); 
    14201420 
    14211421        if (b->BC != BCret && b->BC != BCretexp) 
    14221422            lastidx = b->Bendindex; 
  • branches/dmd-1.x/src/backend/cgen.c

    r595 r596  
    4949            c = c->next; 
    5050        c->Iflags |= flag; 
    5151    } 
    5252} 
    5353 
    5454/***************************** 
    5555 * Set rex bits on last code in list. 
    5656 */ 
    5757 
    5858void code_orrex(code *c,unsigned rex) 
    5959{ 
    6060    if (rex && c) 
    6161    {   while (c->next) 
    6262            c = c->next; 
    6363        c->Irex |= rex; 
    6464    } 
    6565} 
    6666 
    6767/************************************** 
    6868 * Set the opcode fields in cs. 
    69  * This is ridiculously complex, cs.Iop should 
    70  * just be an unsigned. 
    7169 */ 
    7270code *setOpcode(code *c, code *cs, unsigned op) 
    7371{ 
    74     cs->Iflags = 0; 
    75     if (op > 0xFF) 
    76     { 
    77         switch (op & 0xFF0000) 
    78         { 
    79             case 0: 
    80                 break; 
    81             case 0x660000: 
    82                 cs->Iflags = CFopsize; 
    83                 break; 
    84             case 0xF20000:                      // REPNE 
    85             case 0xF30000:                      // REP/REPE 
    86                 c = gen1(c, op >> 16); 
    87                 break; 
    88         } 
    89         cs->Iop = op >> 8; 
    90         cs->Iop2 = op & 0xFF; 
    91     } 
    92     else 
    93         cs->Iop = op; 
     72    cs->Iop = op; 
    9473    return c; 
    9574} 
    9675 
    9776/***************************** 
    9877 * Concatenate two code lists together. Return pointer to result. 
    9978 */ 
    10079 
    10180#if TX86 && __INTSIZE == 4 && __SC__ 
    10281__declspec(naked) code * __pascal cat(code *c1,code *c2) 
    10382{ 
    10483    _asm 
    10584    { 
    10685        mov     EAX,c1-4[ESP] 
    10786        mov     ECX,c2-4[ESP] 
    10887        test    EAX,EAX 
    10988        jne     L6D 
    11089        mov     EAX,ECX 
    11190        ret     8 
    11291 
    11392L6D:    mov     EDX,EAX 
     
    208187 
    209188code *gen1(code *c,unsigned op) 
    210189{ code *ce,*cstart; 
    211190 
    212191  ce = code_calloc(); 
    213192  ce->Iop = op; 
    214193  if (c) 
    215194  {     cstart = c; 
    216195        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    217196        code_next(c) = ce;                      /* link into list       */ 
    218197        return cstart; 
    219198  } 
    220199  return ce; 
    221200} 
    222201 
    223202code *gen2(code *c,unsigned op,unsigned rm) 
    224203{ code *ce,*cstart; 
    225204 
    226205  cstart = ce = code_calloc(); 
    227206  /*cxcalloc++;*/ 
    228   if (op > 0xFF) 
    229   {     ce->Iop = op >> 8; 
    230         ce->Iop2 = op & 0xFF; 
    231   } 
    232   else 
    233         ce->Iop = op; 
     207  ce->Iop = op; 
    234208  ce->Iea = rm; 
    235209  if (c) 
    236210  {     cstart = c; 
    237211        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    238212        code_next(c) = ce;                      /* link into list       */ 
    239213  } 
    240214  return cstart; 
    241215} 
    242216 
    243217code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 
    244218{ code *ce,*cstart; 
    245219 
    246220  cstart = ce = code_calloc(); 
    247221  /*cxcalloc++;*/ 
    248222  ce->Iop = op; 
    249223  ce->Irm = rm; 
    250224  ce->Isib = sib; 
    251225  ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 
    252226  if (sib & (REX_R << 16)) 
    253227        ce->Irex |= REX_X; 
     
    318292        { 
    319293                if (to == ES) 
    320294                        c = genregs(c,0x8E,0,from); 
    321295                else if (from == ES) 
    322296                        c = genregs(c,0x8C,0,to); 
    323297                else 
    324298                        c = genregs(c,0x89,from,to); 
    325299        } 
    326300        return c; 
    327301} 
    328302 
    329303/************************** 
    330304 * Generate a jump instruction. 
    331305 */ 
    332306 
    333307code *genjmp(code *c,unsigned op,unsigned fltarg,block *targ) 
    334308{   code cs; 
    335309    code *cj; 
    336310    code *cnop; 
    337311 
    338     cs.Iop = op
     312    cs.Iop = op & 0xFF
    339313    cs.Iflags = 0; 
    340314    cs.Irex = 0; 
    341315    if (op != JMP)                      /* if not already long branch   */ 
    342316          cs.Iflags = CFjmp16;          /* assume long branch for op = 0x7x */ 
    343317    cs.IFL2 = fltarg;                   /* FLblock (or FLcode)          */ 
    344318    cs.IEV2.Vblock = targ;              /* target block (or code)       */ 
    345319    if (fltarg == FLcode) 
    346320        ((code *)targ)->Iflags |= CFtarg; 
    347321 
    348322    if (config.flags4 & CFG4fastfloat)  // if fast floating point 
    349323        return gen(c,&cs); 
    350324 
    351325    cj = gen(CNIL,&cs); 
    352326    switch (op & 0xFF00)                /* look at second jump opcode   */ 
    353327    { 
    354328        /* The JP and JNP come from floating point comparisons          */ 
    355329        case JP << 8: 
    356330            cs.Iop = JP; 
    357331            gen(cj,&cs); 
    358332            break; 
     
    373347    } 
    374348    return cat(c,cj); 
    375349} 
    376350 
    377351code *gencs(code *c,unsigned op,unsigned ea,unsigned FL2,symbol *s) 
    378352{   code cs; 
    379353 
    380354    cs.Iop = op; 
    381355    cs.Iea = ea; 
    382356    cs.Iflags = 0; 
    383357    cs.IFL2 = FL2; 
    384358    cs.IEVsym2 = s; 
    385359    cs.IEVoffset2 = 0; 
    386360 
    387361    return gen(c,&cs); 
    388362} 
    389363 
    390364code *genc2(code *c,unsigned op,unsigned ea,targ_size_t EV2) 
    391365{   code cs; 
    392366 
    393     if (op > 0xFF) 
    394     {   cs.Iop = op >> 8; 
    395         cs.Iop2 = op & 0xFF; 
    396     } 
    397     else 
    398         cs.Iop = op; 
     367    cs.Iop = op; 
    399368    cs.Iea = ea; 
    400369    cs.Iflags = CFoff; 
    401370    cs.IFL2 = FLconst; 
    402371    cs.IEV2.Vsize_t = EV2; 
    403372    return gen(c,&cs); 
    404373} 
    405374 
    406375/***************** 
    407376 * Generate code. 
    408377 */ 
    409378 
    410379code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 
    411380{   code cs; 
    412381 
    413382    assert(FL1 < FLMAX); 
    414     if (op > 0xFF) 
    415     { 
    416         c = setOpcode(c, &cs, op); 
    417         cs.Iflags |= CFoff; 
    418     } 
    419     else 
    420     {   cs.Iop = op; 
    421         cs.Iflags = CFoff; 
    422     } 
     383    cs.Iop = op; 
     384    cs.Iflags = CFoff; 
    423385    cs.Iea = ea; 
    424386    cs.IFL1 = FL1; 
    425387    cs.IEV1.Vsize_t = EV1; 
    426388    return gen(c,&cs); 
    427389} 
    428390 
    429391/***************** 
    430392 * Generate code. 
    431393 */ 
    432394 
    433395code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
    434396{   code cs; 
    435397 
    436398    assert(FL1 < FLMAX); 
    437     assert(op < 256); 
    438399    cs.Iop = op; 
    439400    cs.Iea = ea; 
    440401    cs.Iflags = CFoff; 
    441402    cs.IFL1 = FL1; 
    442403    cs.IEV1.Vsize_t = EV1; 
    443404    assert(FL2 < FLMAX); 
    444405    cs.IFL2 = FL2; 
    445406    cs.IEV2.Vsize_t = EV2; 
    446407    return gen(c,&cs); 
    447408} 
    448409 
    449410/*************************************** 
    450411 * Generate immediate multiply instruction for r1=r2*imm. 
    451412 * Optimize it into LEA's if we can. 
    452413 */ 
    453414 
    454415code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm) 
    455416{   code cs; 
    456417 
    457418    // These optimizations should probably be put into pinholeopt() 
     
    471432            c = genc2(c,0x69,modregxrmx(3,r1,r2),imm);    // IMUL r1,r2,imm 
    472433            break; 
    473434    } 
    474435    return c; 
    475436} 
    476437 
    477438/******************************** 
    478439 * Generate 'instruction' which is actually a line number. 
    479440 */ 
    480441 
    481442code *genlinnum(code *c,Srcpos srcpos) 
    482443{   code cs; 
    483444 
    484445#if 0 
    485446#if MARS 
    486447    printf("genlinnum(Sfilename = %p, Slinnum = %u)\n", srcpos.Sfilename, srcpos.Slinnum); 
    487448#else 
    488449    printf("genlinnum(Sfilptr = %p, Slinnum = %u)\n", srcpos.Sfilptr, srcpos.Slinnum); 
    489450#endif 
    490451#endif 
    491     cs.Iop = ESCAPE; 
    492     cs.Iop2 = ESClinnum; 
     452    cs.Iop = ESCAPE | ESClinnum; 
    493453    cs.Iflags = 0; 
    494454    cs.Irex = 0; 
    495455    cs.IFL1 = 0; 
    496456    cs.IFL2 = 0; 
    497457    cs.IEV2.Vsrcpos = srcpos; 
    498458    return gen(c,&cs); 
    499459} 
    500460 
    501461/****************************** 
    502462 * Append line number to existing code. 
    503463 */ 
    504464 
    505465void cgen_linnum(code **pc,Srcpos srcpos) 
    506466{ 
    507467    *pc = genlinnum(*pc,srcpos); 
    508468} 
    509469 
    510470/***************************** 
    511471 * Prepend line number to existing code. 
    512472 */ 
    513473 
    514474void cgen_prelinnum(code **pc,Srcpos srcpos) 
    515475{ 
    516476    *pc = cat(genlinnum(NULL,srcpos),*pc); 
    517477} 
    518478 
    519479/******************************** 
    520480 * Generate 'instruction' which tells the address resolver that the stack has 
    521481 * changed. 
    522482 */ 
    523483 
    524484code *genadjesp(code *c, int offset) 
    525485{   code cs; 
    526486 
    527487    if (!I16 && offset) 
    528488    { 
    529         cs.Iop = ESCAPE; 
    530         cs.Iop2 = ESCadjesp; 
     489        cs.Iop = ESCAPE | ESCadjesp; 
    531490        cs.Iflags = 0; 
    532491        cs.Irex = 0; 
    533492        cs.IEV2.Vint = offset; 
    534493        return gen(c,&cs); 
    535494    } 
    536495    else 
    537496        return c; 
    538497} 
    539498 
    540499/******************************** 
    541500 * Generate 'nop' 
    542501 */ 
    543502 
    544503code *gennop(code *c) 
    545504{ 
    546505    return gen1(c,NOP); 
    547506} 
    548507 
    549508/****************************** 
    550509 * Load CX with the value of _AHSHIFT. 
  • branches/dmd-1.x/src/backend/cgsched.c

    r569 r596  
    761761        1,1,5,5,        4,4,0,0,                /* F8 */ 
    762762}; 
    763763 
    764764static unsigned char uopsx[8] = { 1,1,2,5,1,1,1,5 }; 
    765765 
    766766/************************************************ 
    767767 * Determine number of micro-ops for Pentium Pro and Pentium II processors. 
    768768 * 5 means 'complex'. 
    769769 * Doesn't currently handle: 
    770770 *      floating point 
    771771 *      MMX 
    772772 *      0F opcodes 
    773773 *      prefix bytes 
    774774 */ 
    775775 
    776776STATIC int uops(code *c) 
    777777{   int n; 
    778778    int op; 
    779779    int op2; 
    780780 
    781     op = c->Iop; 
     781    op = c->Iop & 0xFF; 
     782    if ((c->Iop & 0xFF00) == 0x0F00) 
     783        op = 0x0F; 
    782784    n = insuops[op]; 
    783785    if (!n)                             // if special case 
    784786    {   unsigned char irm,mod,reg,rm; 
    785787 
    786788        irm = c->Irm; 
    787789        mod = (irm >> 6) & 3; 
    788790        reg = (irm >> 3) & 7; 
    789791        rm = irm & 7; 
    790792 
    791793        switch (op) 
    792794        { 
    793795            case 0x10: 
    794796            case 0x11:                  // ADC rm,r 
    795797            case 0x18: 
    796798            case 0x19:                  // SBB rm,r 
    797799                n = (mod == 3) ? 2 : 4; 
    798800                break; 
    799801 
    800802            case 0x12: 
    801803            case 0x13:                  // ADC r,rm 
     
    966968                    n = 4; 
    967969                else if (reg == 4 || reg == 5)  // MUL/IMUL rm 
    968970                    n = (mod == 3) ? 3 : 4; 
    969971                else if (reg == 2 || reg == 3)  // NOT/NEG rm 
    970972                    n = (mod == 3) ? 1 : 4; 
    971973                break; 
    972974 
    973975            case 0xFF: 
    974976                if (reg == 2 || reg == 3 ||     // CALL rm, CALL m,rm 
    975977                    reg == 5)                   // JMP seg:offset 
    976978                    n = 5; 
    977979                else if (reg == 4) 
    978980                    n = (mod == 3) ? 1 : 2; 
    979981                else if (reg == 0 || reg == 1)  // INC/DEC rm 
    980982                    n = (mod == 3) ? 1 : 4; 
    981983                else if (reg == 6)              // PUSH rm 
    982984                    n = (mod == 3) ? 3 : 4; 
    983985                break; 
    984986 
    985987            case 0x0F: 
    986                 op2 = c->Iop2
     988                op2 = c->Iop & 0xFF
    987989                if ((op2 & 0xF0) == 0x80)       // Jcc 
    988990                {   n = 1; 
    989991                    break; 
    990992                } 
    991993                if ((op2 & 0xF0) == 0x90)       // SETcc 
    992994                {   n = (mod == 3) ? 1 : 3; 
    993995                    break; 
    994996                } 
    995997                if (op2 == 0xB6 || op2 == 0xB7 ||       // MOVZX 
    996998                    op2 == 0xBE || op2 == 0xBF)         // MOVSX 
    997999                {   n = 1; 
    9981000                    break; 
    9991001                } 
    10001002                if (op2 == 0xAF)                        // IMUL r,m 
    10011003                {   n = (mod == 3) ? 1 : 2; 
    10021004                    break; 
    10031005                } 
    10041006                break; 
    10051007        } 
    10061008    } 
     
    10081010        n = 5;                                  // copout for now 
    10091011    return n; 
    10101012} 
    10111013 
    10121014/****************************************** 
    10131015 * Determine pairing classification. 
    10141016 * Don't deal with floating point, just assume they are all NP (Not Pairable). 
    10151017 * Returns: 
    10161018 *      NP,UV,PU,PV optionally OR'd with PE 
    10171019 */ 
    10181020 
    10191021STATIC int pair_class(code *c) 
    10201022{   unsigned char op; 
    10211023    unsigned char irm,mod,reg,rm; 
    10221024    unsigned a32; 
    10231025    int pc; 
    10241026 
    10251027    // Of course, with Intel this is *never* simple, and Intel's 
    10261028    // documentation is vague about the specifics. 
    10271029 
    1028     op = c->Iop; 
     1030    op = c->Iop & 0xFF; 
     1031    if ((c->Iop & 0xFF00) == 0x0F00) 
     1032        op = 0x0F; 
    10291033    pc = pentcycl[op]; 
    10301034    a32 = I32; 
    10311035    if (c->Iflags & CFaddrsize) 
    10321036        a32 ^= 1; 
    10331037    irm = c->Irm; 
    10341038    mod = (irm >> 6) & 3; 
    10351039    reg = (irm >> 3) & 7; 
    10361040    rm = irm & 7; 
    10371041    switch (op) 
    10381042    { 
    10391043        case 0x0F:                              // 2 byte opcode 
    1040             if ((c->Iop2 & 0xF0) == 0x80)       // if Jcc 
     1044            if ((c->Iop & 0xF0) == 0x80)        // if Jcc 
    10411045                pc = PV | PF; 
    10421046            break; 
    10431047 
    10441048        case 0x80: 
    10451049        case 0x81: 
    10461050        case 0x83: 
    10471051            if (reg == 2 ||                     // ADC EA,immed 
    10481052                reg == 3)                       // SBB EA,immed 
    10491053            {   pc = PU; 
    10501054                goto L2; 
    10511055            } 
    10521056            goto L1;                            // AND/OR/XOR/ADD/SUB/CMP EA,immed 
    10531057 
    10541058        case 0x84: 
    10551059        case 0x85:                              // TEST EA,reg 
    10561060            if (mod == 3)                       // TEST reg,reg 
    10571061                pc = UV; 
    10581062            break; 
    10591063 
    10601064        case 0xC0: 
     
    11671171 
    11681172    if (PRO) 
    11691173    { 
    11701174        ci->uops = uops(c); 
    11711175        ci->isz = calccodsize(c); 
    11721176    } 
    11731177    else 
    11741178        ci->pair = pair_class(c); 
    11751179 
    11761180    unsigned char op; 
    11771181    unsigned char op2; 
    11781182    unsigned char irm,mod,reg,rm; 
    11791183    unsigned a32; 
    11801184    int pc; 
    11811185    unsigned r,w; 
    11821186    int sz = I32 ? 4 : 2; 
    11831187 
    11841188    ci->r = 0; 
    11851189    ci->w = 0; 
    11861190    ci->a = 0; 
    1187     op = c->Iop; 
     1191    op = c->Iop & 0xFF; 
     1192    if ((c->Iop & 0xFF00) == 0x0F00) 
     1193        op = 0x0F; 
    11881194    //printf("\tgetinfo %x, op %x \n",c,op); 
    11891195    pc = pentcycl[op]; 
    11901196    a32 = I32; 
    11911197    if (c->Iflags & CFaddrsize) 
    11921198        a32 ^= 1; 
    11931199    if (c->Iflags & CFopsize) 
    11941200        sz ^= 2 | 4; 
    11951201    irm = c->Irm; 
    11961202    mod = (irm >> 6) & 3; 
    11971203    reg = (irm >> 3) & 7; 
    11981204    rm = irm & 7; 
    11991205 
    12001206    r = oprw[op][0]; 
    12011207    w = oprw[op][1]; 
    12021208 
    12031209    switch (op) 
    12041210    { 
    12051211        case 0x50: 
    12061212        case 0x51: 
    12071213        case 0x52: 
     
    12951301                w = F; 
    12961302#if CLASSINIT2 
    12971303                ci->pair = UV;                  // it is patched to CMP EAX,0 
    12981304#else 
    12991305                ci->pair = NP; 
    13001306#endif 
    13011307            } 
    13021308            break; 
    13031309 
    13041310        case 0xF6: 
    13051311            r = grprw[3][reg][0];               // Grp 3, byte version 
    13061312            w = grprw[3][reg][1]; 
    13071313            break; 
    13081314 
    13091315        case 0xF7: 
    13101316            r = grprw[1][reg][0];               // Grp 3 
    13111317            w = grprw[1][reg][1]; 
    13121318            break; 
    13131319 
    13141320        case 0x0F: 
    1315             op2 = c->Iop2
     1321            op2 = c->Iop & 0xFF
    13161322            if ((op2 & 0xF0) == 0x80)           // if Jxx instructions 
    13171323            { 
    13181324                ci->r = F | N; 
    13191325                ci->w = N; 
    13201326                goto Lret; 
    13211327            } 
    13221328            ci->r = N; 
    13231329            ci->w = N;          // copout for now 
    13241330            goto Lret; 
    13251331 
    13261332        case 0xD7:                              // XLAT 
    13271333            ci->a = mAX | mBX; 
    13281334            break; 
    13291335 
    13301336        case 0xFF: 
    13311337            r = grprw[2][reg][0];               // Grp 5 
    13321338            w = grprw[2][reg][1]; 
    13331339            if (reg == 6)                       // PUSH rm 
    13341340                goto Lpush; 
    13351341            break; 
     
    17441750Lnopair: 
    17451751    return 0; 
    17461752} 
    17471753 
    17481754/******************************************** 
    17491755 * Get next instruction worth looking at for scheduling. 
    17501756 * Returns: 
    17511757 *      NULL    no more instructions 
    17521758 */ 
    17531759 
    17541760STATIC code * cnext(code *c) 
    17551761{ 
    17561762    while (1) 
    17571763    { 
    17581764        c = code_next(c); 
    17591765        if (!c) 
    17601766            break; 
    17611767        if (c->Iflags & (CFtarg | CFtarg2)) 
    17621768            break; 
    17631769        if (!(c->Iop == NOP || 
    1764               (c->Iop == ESCAPE && c->Iop2 == ESClinnum))) 
     1770              c->Iop == (ESCAPE | ESClinnum))) 
    17651771            break; 
    17661772    } 
    17671773    return c; 
    17681774} 
    17691775 
    17701776/****************************************** 
    17711777 * Instruction scheduler. 
    17721778 * Input: 
    17731779 *      c               list of instructions to schedule 
    17741780 *      scratch         scratch registers we can use 
    17751781 * Returns: 
    17761782 *      revised list of scheduled instructions 
    17771783 */ 
    17781784 
    17791785/////////////////////////////////// 
    17801786// Determine if c1 and c2 are swappable. 
    17811787// c1 comes before c2. 
    17821788// If they do not conflict 
    17831789//      return 0 
    17841790// If they do conflict 
     
    18671873            w2 &= ~F;                   // remove conflict 
    18681874            goto L1;                    // and try again 
    18691875        } 
    18701876#endif 
    18711877        // If other than the memory reference is a conflict 
    18721878        if (w1 & r2 & ~mMEM || (r1 | w1) & w2 & ~mMEM) 
    18731879        {   if (i) printf("\t1\n"); 
    18741880            if (i) printf("r1=%x, w1=%x, a1=%x, sz1=%d, r2=%x, w2=%x, a2=%x, sz2=%d\n",r1,w1,a1,sz1,r2,w2,a2,sz2); 
    18751881            goto Lconflict; 
    18761882        } 
    18771883 
    18781884        // If referring to distinct types, then no dependency 
    18791885        if (c1->Irex && c2->Irex && c1->Irex != c2->Irex) 
    18801886            goto Lswap; 
    18811887 
    18821888        ifl1 = c1->IFL1; 
    18831889        ifl2 = c2->IFL1; 
    18841890 
    18851891        // Special case: Allow indexed references using registers other than 
    18861892        // ESP and EBP to be swapped with PUSH instructions 
    1887         if (((c1->Iop & 0xF8) == 0x50 ||        // PUSH reg 
     1893        if (((c1->Iop & ~7) == 0x50 ||          // PUSH reg 
    18881894             c1->Iop == 0x6A ||                 // PUSH imm8 
    18891895             c1->Iop == 0x68 ||                 // PUSH imm16/imm32 
    18901896             (c1->Iop == 0xFF && ci1->reg == 6) // PUSH EA 
    18911897            ) && 
    18921898            ci2->flags & CIFLea && !(a2 & mSP) && 
    18931899            !(a2 & mBP && (long)c2->IEVpointer1 < 0) 
    18941900           ) 
    18951901        { 
    18961902            if (c1->Iop == 0xFF) 
    18971903            { 
    18981904                if (!(w2 & mMEM)) 
    18991905                    goto Lswap; 
    19001906            } 
    19011907            else 
    19021908                goto Lswap; 
    19031909        } 
    19041910 
    19051911        // Special case: Allow indexed references using registers other than 
    19061912        // ESP and EBP to be swapped with PUSH instructions 
    1907         if (((c2->Iop & 0xF8) == 0x50 ||        // PUSH reg 
     1913        if (((c2->Iop & ~7) == 0x50 ||          // PUSH reg 
    19081914             c2->Iop == 0x6A ||                 // PUSH imm8 
    19091915             c2->Iop == 0x68 ||                 // PUSH imm16/imm32 
    19101916             (c2->Iop == 0xFF && ci2->reg == 6) // PUSH EA 
    19111917            ) && 
    19121918            ci1->flags & CIFLea && !(a1 & mSP) && 
    19131919            !(a2 & mBP && (long)c2->IEVpointer1 < 0) 
    19141920           ) 
    19151921        { 
    19161922            if (c2->Iop == 0xFF) 
    19171923            { 
    19181924                if (!(w1 & mMEM)) 
    19191925                    goto Lswap; 
    19201926            } 
    19211927            else 
    19221928                goto Lswap; 
    19231929        } 
    19241930 
    19251931        // If not both an EA addressing mode, conflict 
    19261932        if (!(ci1->flags & ci2->flags & CIFLea)) 
    19271933        {   if (i) printf("\t2\n"); 
     
    22822288       ) 
    22832289    { 
    22842290        movesp = 1;                     // this is a MOV reg2,offset[ESP] 
    22852291        offset = (signed char)c->IEVpointer1; 
    22862292        reg2 = (c->Irm >> 3) & 7; 
    22872293    } 
    22882294 
    22892295 
    22902296    // Start at tblmax, and back up until we get a conflict 
    22912297    ic = -1; 
    22922298    imin = 0; 
    22932299    for (i = tblmax; i >= 0; i--) 
    22942300    {   Cinfo *cit; 
    22952301 
    22962302        cit = tbl[i]; 
    22972303        if (!cit) 
    22982304            continue; 
    22992305 
    23002306        // Look for special case swap 
    23012307        if (movesp && 
    2302             (cit->c->Iop & 0xF8) == 0x50 &&             // if PUSH reg1 
     2308            (cit->c->Iop & ~7) == 0x50 &&               // if PUSH reg1 
    23032309            (cit->c->Iop & 7) != reg2 &&                // if reg1 != reg2 
    23042310            ((signed char)c->IEVpointer1) >= -cit->spadjust 
    23052311           ) 
    23062312        { 
    23072313            c->IEVpointer1 += cit->spadjust; 
    23082314            //printf("\t1, spadjust = %d, ptr = x%x\n",cit->spadjust,c->IEVpointer1); 
    23092315            continue; 
    23102316        } 
    23112317 
    23122318        if (movesp && 
    23132319            cit->c->Iop == 0x83 && 
    23142320            cit->c->Irm == modregrm(3,5,SP) &&          // if SUB ESP,offset 
    23152321            cit->c->IFL2 == FLconst && 
    23162322            ((signed char)c->IEVpointer1) >= -cit->spadjust 
    23172323           ) 
    23182324        { 
    23192325            //printf("\t2, spadjust = %d\n",cit->spadjust); 
    23202326            c->IEVpointer1 += cit->spadjust; 
    23212327            continue; 
    23222328        } 
     
    25052511                c->IEVpointer1 -= cit->spadjust; 
    25062512                //printf("\t3, spadjust = %d, ptr = x%x\n",cit->spadjust,c->IEVpointer1); 
    25072513            } 
    25082514        } 
    25092515    } 
    25102516    if (i >= tblmax) 
    25112517        tblmax = i + 1; 
    25122518 
    25132519    // Now do a hack. Look back at immediately preceding instructions, 
    25142520    // and see if we can swap with a push. 
    25152521    if (0 && movesp) 
    25162522    {   int j; 
    25172523 
    25182524        while (1) 
    25192525        { 
    25202526            for (j = 1; i > j; j++) 
    25212527                if (tbl[i - j]) 
    25222528                    break; 
    25232529 
    25242530            if (i >= j && tbl[i - j] && 
    2525                    (tbl[i - j]->c->Iop & 0xF8) == 0x50 &&       // if PUSH reg1 
     2531                   (tbl[i - j]->c->Iop & ~7) == 0x50 &&       // if PUSH reg1 
    25262532                   (tbl[i - j]->c->Iop & 7) != reg2 &&  // if reg1 != reg2 
    25272533                   (signed char)c->IEVpointer1 >= REGSIZE) 
    25282534            { 
    25292535                //printf("\t-4 prec, i-j=%d, i=%d\n",i-j,i); 
    25302536                assert((unsigned)i < TBLMAX); 
    25312537                assert((unsigned)(i - j) < TBLMAX); 
    25322538                tbl[i] = tbl[i - j]; 
    25332539                tbl[i - j] = ci; 
    25342540                i -= j; 
    25352541                c->IEVpointer1 -= REGSIZE; 
    25362542            } 
    25372543            else 
    25382544                break; 
    25392545        } 
    25402546    } 
    25412547 
    25422548    //printf("\tinsert\n"); 
    25432549    return 1; 
    25442550} 
    25452551 
     
    26472653 * Returns: 
    26482654 *      next instruction (the tail) or 
    26492655 *      NULL for no more instructions 
    26502656 */ 
    26512657 
    26522658STATIC code * csnip(code *c) 
    26532659{   code **pc; 
    26542660    unsigned iflags; 
    26552661 
    26562662    if (c) 
    26572663    {   iflags = c->Iflags & CFclassinit; 
    26582664        while (1) 
    26592665        { 
    26602666            pc = &code_next(c); 
    26612667            c = *pc; 
    26622668            if (!c) 
    26632669                break; 
    26642670            if (c->Iflags & (CFtarg | CFtarg2)) 
    26652671                break; 
    26662672            if (!(c->Iop == NOP || 
    2667                   (c->Iop == ESCAPE && c->Iop2 == ESClinnum) || 
     2673                  c->Iop == (ESCAPE | ESClinnum) || 
    26682674                  c->Iflags & iflags)) 
    26692675                break; 
    26702676        } 
    26712677        *pc = NULL; 
    26722678    } 
    26732679    return c; 
    26742680} 
    26752681 
    26762682 
    26772683/****************************** 
    26782684 * Schedule Pentium instructions, 
    26792685 * based on Steve Russell's algorithm. 
    26802686 */ 
    26812687 
    26822688code *schedule(code *c,regm_t scratch) 
    26832689{ 
    26842690    code *cresult = NULL; 
    26852691    code **pctail = &cresult; 
    26862692    Schedule sch; 
    26872693 
    26882694    sch.initialize(0);                  // initialize scheduling table 
    26892695    while (c) 
    26902696    { 
    2691         if ((c->Iop == NOP || c->Iop == ESCAPE || c->Iflags & CFclassinit) && 
     2697        if ((c->Iop == NOP || (c->Iop & 0xFF) == ESCAPE || c->Iflags & CFclassinit) && 
    26922698            !(c->Iflags & (CFtarg | CFtarg2))) 
    26932699        {   code *cn; 
    26942700 
    26952701            // Just append this instruction to pctail and go to the next one 
    26962702            *pctail = c; 
    26972703            cn = code_next(c); 
    26982704            code_next(c) = NULL; 
    26992705            pctail = &code_next(c); 
    27002706            c = cn; 
    27012707            continue; 
    27022708        } 
    27032709 
    27042710        //printf("init\n"); 
    27052711        sch.initialize(sch.fpustackused);       // initialize scheduling table 
    27062712 
    27072713        while (c) 
    27082714        { 
    27092715            //printf("insert %p\n",c); 
    27102716            if (!sch.stage(c))          // store c in scheduling table 
    27112717                break; 
     
    28342840    code *c; 
    28352841    code *c1,*c2,*c3; 
    28362842    unsigned r1,r2; 
    28372843    unsigned mod,reg,rm; 
    28382844 
    28392845    //printf("peephole\n"); 
    28402846    for (c = cstart; c; c = c1) 
    28412847    {   unsigned char rmi; 
    28422848        unsigned char rmn; 
    28432849 
    28442850        //c->print(); 
    28452851        c1 = cnext(c); 
    28462852    Ln: 
    28472853        if (!c1) 
    28482854            break; 
    28492855        if (c1->Iflags & (CFtarg | CFtarg2)) 
    28502856            continue; 
    28512857 
    28522858        // Do: 
    28532859        //      PUSH    reg 
    2854         if (I32 && (c->Iop & 0xF8) == 0x50) 
     2860        if (I32 && (c->Iop & ~7) == 0x50) 
    28552861        {   unsigned reg = c->Iop & 7; 
    28562862 
    28572863            //  MOV     [ESP],reg       =>      NOP 
    28582864            if (c1->Iop == 0x8B && 
    28592865                c1->Irm == modregrm(0,reg,4) && 
    28602866                c1->Isib == modregrm(0,4,SP)) 
    28612867            {   c1->Iop = NOP; 
    28622868                continue; 
    28632869            } 
    28642870 
    28652871            //  PUSH    [ESP]           =>      PUSH    reg 
    28662872            if (c1->Iop == 0xFF && 
    28672873                c1->Irm == modregrm(0,6,4) && 
    28682874                c1->Isib == modregrm(0,4,SP)) 
    28692875            {   c1->Iop = 0x50 + reg; 
    28702876                continue; 
    28712877            } 
    28722878 
    28732879            //  CMP     [ESP],imm       =>      CMP     reg,i,, 
    28742880            if (c1->Iop == 0x83 && 
  • branches/dmd-1.x/src/backend/cod1.c

    r595 r596  
    538538 
    539539/****************************** 
    540540 * Routine to aid in setting things up for gen(). 
    541541 * Look for common subexpression. 
    542542 * Can handle indirection operators, but not if they're common subs. 
    543543 * Input: 
    544544 *      e ->    elem where we get some of the data from 
    545545 *      cs ->   partially filled code to add 
    546546 *      op =    opcode 
    547547 *      reg =   reg field of (mod reg r/m) 
    548548 *      offset = data to be added to Voffset field 
    549549 *      keepmsk = mask of registers we must not destroy 
    550550 *      desmsk  = mask of registers destroyed by executing the instruction 
    551551 * Returns: 
    552552 *      pointer to code generated 
    553553 */ 
    554554 
    555555code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    556556        regm_t keepmsk,regm_t desmsk) 
    557557{ 
    558   code *c,*cg,*cd,*cprefix
     558  code *c,*cg,*cd
    559559 
    560560#ifdef DEBUG 
    561561  if (debugw) 
    562562    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 
    563563            e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 
    564564#endif 
    565565 
    566566  assert(e); 
    567567  cs->Iflags = 0; 
    568568  cs->Irex = 0; 
    569   cprefix = NULL; 
    570   if (op > 0xFF)               // if 2 byte opcode 
    571         cprefix = setOpcode(NULL, cs, op); 
    572   else 
    573         cs->Iop = op; 
     569  cs->Iop = op; 
    574570  tym_t tym = e->Ety; 
    575571  int sz = tysize(tym); 
    576572 
    577573  /* Determine if location we want to get is in a register. If so,      */ 
    578574  /* substitute the register for the EA.                                */ 
    579575  /* Note that operators don't go through this. CSE'd operators are     */ 
    580576  /* picked up by comsub().                                             */ 
    581577  if (e->Ecount &&                      /* if cse                       */ 
    582578      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    583579      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
    584580      (op != 0xFF || reg != 3) &&       /* and not CALLF MEM16          */ 
    585581      (op & 0xFFF8) != 0xD8)            // and not 8087 opcode 
    586582  { 
    587583        assert(!EOP(e));                /* can't handle this            */ 
    588584        regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 
    589585        if (sz > REGSIZE)               // value is in 2 or 4 registers 
    590586        { 
    591587                if (I16 && sz == 8)     // value is in 4 registers 
    592588                {       static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 
    593589                        rm &= rmask[offset >> 1]; 
     
    648644        cs->Iflags |= CFwait; 
    649645L2: 
    650646  cg = getregs(desmsk);                 /* save any regs we destroy     */ 
    651647 
    652648  /* KLUDGE! fix up DX for divide instructions */ 
    653649  cd = CNIL; 
    654650  if (op == 0xF7 && desmsk == (mAX|mDX))        /* if we need to fix DX */ 
    655651  {     if (reg == 7)                           /* if IDIV              */ 
    656652        {   cd = gen1(cd,0x99);                 // CWD 
    657653            if (I64 && sz == 8) 
    658654                code_orrex(cd, REX_W); 
    659655        } 
    660656        else if (reg == 6)                      // if DIV 
    661657        {   cd = genregs(cd,0x33,DX,DX);        // XOR DX,DX 
    662658            if (I64 && sz == 8) 
    663659                code_orrex(cd, REX_W); 
    664660        } 
    665661  } 
    666662 
    667663  // Eliminate MOV reg,reg 
    668   if ((cs->Iop & 0xFC) == 0x88 && 
     664  if ((cs->Iop & ~3) == 0x88 && 
    669665      (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 
    670666  { 
    671667        unsigned r = cs->Irm & 7; 
    672668        if (cs->Irex & REX_B) 
    673669            r |= 8; 
    674670        if (r == reg) 
    675671            cs->Iop = NOP; 
    676672  } 
    677673 
    678   return cat4(c,cg,cd,gen(cprefix,cs)); 
     674  return cat4(c,cg,cd,gen(NULL,cs)); 
    679675} 
    680676 
    681677/************************** 
    682678 * Get addressing mode. 
    683679 */ 
    684680 
    685681unsigned getaddrmode(regm_t idxregs) 
    686682{ 
    687683    unsigned mode; 
    688684 
    689685    if (I16) 
    690686    { 
    691687        mode =  (idxregs & mBX) ? modregrm(2,0,7) :     /* [BX] */ 
    692688                (idxregs & mDI) ? modregrm(2,0,5):      /* [DI] */ 
    693689                (idxregs & mSI) ? modregrm(2,0,4):      /* [SI] */ 
    694690                                  (assert(0),1); 
    695691    } 
    696692    else 
    697693    {   unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 
    698694        mode = modregrmx(2,0,reg); 
     
    791787  if (tyfloating(ty)) 
    792788        obj_fltused(); 
    793789  else if (I64 && sz == 8) 
    794790        pcs->Irex |= REX_W; 
    795791  if (!I16 && sz == SHORTSIZE) 
    796792        pcs->Iflags |= CFopsize; 
    797793  if (ty & mTYvolatile) 
    798794        pcs->Iflags |= CFvolatile; 
    799795  c = CNIL; 
    800796  switch (fl) 
    801797  { 
    802798#if 0 && TARGET_LINUX 
    803799    case FLgot: 
    804800    case FLgotoff: 
    805801        gotref = 1; 
    806802        pcs->IEVsym1 = s; 
    807803        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    808804        if (e->Eoper == OPvar && fl == FLgot) 
    809805        { 
    810806            code *c1; 
    811             int saveop = pcs->Iop; 
     807            unsigned saveop = pcs->Iop; 
    812808            idxregs = allregs & ~keepmsk;       // get a scratch register 
    813809            c = allocreg(&idxregs,&reg,TYptr); 
    814810            pcs->Irm = modregrm(2,reg,BX);      // BX has GOT 
    815811            pcs->Isib = 0; 
    816812            //pcs->Iflags |= CFvolatile; 
    817813            pcs->Iop = 0x8B; 
    818814            c = gen(c,pcs);                     // MOV reg,disp[EBX] 
    819815            pcs->Irm = modregrm(0,0,reg); 
    820816            pcs->IEVoffset1 = 0; 
    821817            pcs->Iop = saveop; 
    822818        } 
    823819        else 
    824820        { 
    825821            pcs->Irm = modregrm(2,0,BX);        // disp[EBX] is addr 
    826822            pcs->Isib = 0; 
    827823        } 
    828824        break; 
    829825#endif 
    830826    case FLoper: 
    831827#ifdef DEBUG 
     
    17161712        else if (sz == 8) 
    17171713            code_orrex(ce, REX_W); 
    17181714    } 
    17191715    else 
    17201716        ce = gentstreg(ce,reg);                 // TEST reg,reg 
    17211717    return ce; 
    17221718  } 
    17231719  if (saveflag || tyfv(tym)) 
    17241720  { 
    17251721        scrregm = ALLREGS & ~regm;              /* possible scratch regs */ 
    17261722        ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 
    17271723        if (I32 || sz == REGSIZE * 2) 
    17281724        {   code *c; 
    17291725 
    17301726            assert(regm & mMSW && regm & mLSW); 
    17311727 
    17321728            reg = findregmsw(regm); 
    17331729            if (I32) 
    17341730            { 
    17351731                if (tyfv(tym)) 
    1736                 {   c = genregs(CNIL,0x0F,scrreg,reg); 
    1737                     c->Iop2 = 0xB7;                     /* MOVZX scrreg,msreg   */ 
     1732                {   c = genregs(CNIL,0x0FB7,scrreg,reg); // MOVZX scrreg,msreg 
    17381733                    ce = cat(ce,c); 
    17391734                } 
    17401735                else 
    17411736                {   ce = genmovreg(ce,scrreg,reg);      /* MOV scrreg,msreg     */ 
    17421737                    if (tym == TYdouble || tym == TYdouble_alias) 
    17431738                        gen2(ce,0xD1,modregrm(3,4,scrreg)); /* SHL scrreg,1     */ 
    17441739                } 
    17451740            } 
    17461741            else 
    17471742            { 
    17481743                ce = genmovreg(ce,scrreg,reg);  /* MOV scrreg,msreg     */ 
    17491744                if (tym == TYfloat) 
    17501745                    gen2(ce,0xD1,modregrm(3,4,scrreg)); /* SHL scrreg,1 */ 
    17511746            } 
    17521747            reg = findreglsw(regm); 
    17531748            genorreg(ce,scrreg,reg);                    /* OR scrreg,lsreg */ 
    17541749        } 
    17551750        else if (sz == 8) 
    17561751        {       /* !I32 */ 
    17571752                ce = genmovreg(ce,scrreg,AX);           /* MOV scrreg,AX */ 
     
    35753570                /* FALSE:       CMP SP,SP       (always equal)          */ 
    35763571                c = genregs(CNIL,(boolres(e)) ? 0x09 : 0x39,SP,SP); 
    35773572        } 
    35783573        else if (sz <= REGSIZE) 
    35793574        { 
    35803575            if (!I16 && (tym == TYfloat || tym == TYifloat)) 
    35813576            {   c = allocreg(&regm,&reg,TYoffset);      /* get a register */ 
    35823577                ce = loadea(e,&cs,0x8B,reg,0,0,0);      // MOV reg,data 
    35833578                c = cat(c,ce); 
    35843579                ce = gen2(CNIL,0xD1,modregrmx(3,4,reg)); /* SHL reg,1      */ 
    35853580                c = cat(c,ce); 
    35863581            } 
    35873582            else 
    35883583            {   cs.IFL2 = FLconst; 
    35893584                cs.IEV2.Vint = 0; 
    35903585                op = (sz == 1) ? 0x80 : 0x81; 
    35913586                c = loadea(e,&cs,op,7,0,0,0);           /* CMP EA,0     */ 
    35923587 
    35933588                // Convert to TEST instruction if EA is a register 
    35943589                // (to avoid register contention on Pentium) 
    3595                 if ((c->Iop & 0xFE) == 0x38 && 
     3590                if ((c->Iop & ~1) == 0x38 && 
    35963591                    (c->Irm & modregrm(3,0,0)) == modregrm(3,0,0) 
    35973592                   ) 
    35983593                {   c->Iop = (c->Iop & 1) | 0x84; 
    35993594                    code_newreg(c, c->Irm & 7); 
    36003595                    if (c->Irex & REX_B) 
    36013596                        c->Irex = (c->Irex & ~REX_B) | REX_R; 
    36023597                } 
    36033598            } 
    36043599        } 
    36053600        else if (sz < 8) 
    36063601        { 
    36073602            c = allocreg(&regm,&reg,TYoffset);          /* get a register */ 
    36083603            if (I32)                                    // it's a 48 bit pointer 
    36093604                ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 
    36103605            else 
    36113606            {   ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 
    36123607                if (tym == TYfloat || tym == TYifloat)  // dump sign bit 
    36133608                    gen2(ce,0xD1,modregrm(3,4,reg));    /* SHL reg,1      */ 
    36143609            } 
    36153610            c = cat(c,ce); 
  • branches/dmd-1.x/src/backend/cod2.c

    r589 r596  
    16971697        freenode(e2); 
    16981698        c = cat6(cc,c,c2,cnop1,fixresult(e,retregs,pretregs),NULL); 
    16991699        goto Lret; 
    17001700  } 
    17011701 
    17021702  cnop1 = gennop(CNIL); 
    17031703  cnop2 = gennop(CNIL);         /* dummy target addresses       */ 
    17041704  c = logexp(e1,FALSE,FLcode,cnop1);    /* evaluate condition           */ 
    17051705  regconold = regcon; 
    17061706  stackusedold = stackused; 
    17071707  stackpushold = stackpush; 
    17081708  memcpy(_8087old,_8087elems,sizeof(_8087elems)); 
    17091709  c1 = codelem(e21,pretregs,FALSE); 
    17101710 
    17111711#if SCPP 
    17121712  if (CPP && e2->Eoper == OPcolon2) 
    17131713  {     code cs; 
    17141714 
    17151715        // This is necessary so that any cleanup code on one branch 
    17161716        // is redone on the other branch. 
    1717         cs.Iop = ESCAPE; 
    1718         cs.Iop2 = ESCmark2; 
     1717        cs.Iop = ESCAPE | ESCmark2; 
    17191718        cs.Iflags = 0; 
    17201719        cs.Irex = 0; 
    17211720        c1 = cat(gen(CNIL,&cs),c1); 
    1722         cs.Iop2 = ESCrelease2; 
     1721        cs.Iop = ESCAPE | ESCrelease2; 
    17231722        c1 = gen(c1,&cs); 
    17241723  } 
    17251724#endif 
    17261725 
    17271726  regconsave = regcon; 
    17281727  regcon = regconold; 
    17291728 
    17301729  stackpushsave = stackpush; 
    17311730  stackpush = stackpushold; 
    17321731 
    17331732  stackusedsave = stackused; 
    17341733  stackused = stackusedold; 
    17351734 
    17361735  memcpy(_8087save,_8087elems,sizeof(_8087elems)); 
    17371736  memcpy(_8087elems,_8087old,sizeof(_8087elems)); 
    17381737 
    17391738  *pretregs |= psw;                     /* PSW bit may have been trashed */ 
    17401739  c2 = codelem(e22,pretregs,FALSE); /* use same regs as E1 */ 
    17411740  andregcon(&regconold); 
    17421741  andregcon(&regconsave); 
     
    24122411  { 
    24132412        if (!I16 && tym == TYfloat) 
    24142413        {       retregs = ALLREGS & ~idxregs; 
    24152414                c = cat(c,allocreg(&retregs,&reg,TYfloat)); 
    24162415                cs.Iop = 0x8B; 
    24172416                code_newreg(&cs,reg); 
    24182417                ce = gen(CNIL,&cs);                     // MOV reg,lsw 
    24192418                gen2(ce,0xD1,modregrmx(3,4,reg));       // SHL reg,1 
    24202419        } 
    24212420        else if (sz <= REGSIZE) 
    24222421        { 
    24232422                cs.Iop = 0x81 ^ byte; 
    24242423                cs.Irm |= modregrm(0,7,0); 
    24252424                cs.IFL2 = FLconst; 
    24262425                cs.IEV2.Vint = 0; 
    24272426                ce = gen(CNIL,&cs);             /* CMP [idx],0          */ 
    24282427        } 
    24292428        else if (!I16 && sz == REGSIZE + 2)      // if far pointer 
    24302429        {       retregs = ALLREGS & ~idxregs; 
    24312430                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    2432                 cs.Iop = 0x0F; 
    2433                 cs.Iop2 = 0xB7; 
     2431                cs.Iop = 0x0FB7; 
    24342432                cs.Irm |= modregrm(0,reg,0); 
    24352433                getlvalue_msw(&cs); 
    24362434                ce = gen(CNIL,&cs);             /* MOVZX reg,msw        */ 
    24372435                goto L4; 
    24382436        } 
    24392437        else if (sz <= 2 * REGSIZE) 
    24402438        {       retregs = ALLREGS & ~idxregs; 
    24412439                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    24422440                cs.Iop = 0x8B; 
    24432441                cs.Irm |= modregrm(0,reg,0); 
    24442442                getlvalue_msw(&cs); 
    24452443                ce = gen(CNIL,&cs);             /* MOV reg,msw          */ 
    24462444                if (I32) 
    24472445                {   if (tym == TYdouble || tym == TYdouble_alias) 
    24482446                        gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 
    24492447                } 
    24502448                else if (tym == TYfloat) 
    24512449                    gen2(ce,0xD1,modregrm(3,4,reg));    /* SHL reg,1    */ 
    24522450        L4:     cs.Iop = 0x0B; 
    24532451                getlvalue_lsw(&cs); 
     
    45144512            if (0 && config.exe == EX_NT) 
    45154513            {   unsigned idx; 
    45164514 
    45174515                idx = except_index_get(); 
    45184516                except_mark(); 
    45194517                c = codelem(e->E2,pretregs,FALSE); 
    45204518                if (config.exe == EX_NT && idx != except_index_get()) 
    45214519                {   usednteh |= NTEHcleanup; 
    45224520                    c = cat(c,nteh_gensindex(idx - 1)); 
    45234521                } 
    45244522                except_release(); 
    45254523                assert(idx == except_index_get()); 
    45264524            } 
    45274525            else 
    45284526            { 
    45294527#if 0 
    45304528                usednteh |= EHcleanup; 
    45314529                if (config.exe == EX_NT) 
    45324530                    usednteh |= NTEHcleanup; 
    45334531#endif 
    4534                 cs.Iop = ESCAPE; 
    4535                 cs.Iop2 = ESCmark; 
     4532                cs.Iop = ESCAPE | ESCmark; 
    45364533                cs.Iflags = 0; 
    45374534                cs.Irex = 0; 
    45384535                c = gen(CNIL,&cs); 
    45394536                c = cat(c,codelem(e->E2,pretregs,FALSE)); 
    4540                 cs.Iop2 = ESCrelease; 
     4537                cs.Iop = ESCAPE | ESCrelease; 
    45414538                gen(c,&cs); 
    45424539            } 
    45434540            freenode(e->E1); 
    45444541            break; 
    45454542        default: 
    45464543            assert(0); 
    45474544    } 
    45484545    return c; 
    45494546#else 
    45504547    return NULL; 
    45514548#endif 
    45524549} 
    45534550 
    45544551code *cdctor(elem *e,regm_t *pretregs) 
    45554552{ 
    45564553#if SCPP 
    45574554    code cs; 
    45584555    code *c; 
    45594556 
    45604557#if 0 
    45614558    if (config.exe == EX_NT) 
    45624559    {   usednteh |= NTEHcleanup; 
    45634560        except_push(NULL,e,NULL); 
    45644561        return nteh_gensindex(except_index_get() - 1); 
    45654562    } 
    45664563#else 
    45674564    usednteh |= EHcleanup; 
    45684565    if (config.exe == EX_NT) 
    45694566        usednteh |= NTEHcleanup; 
    45704567#endif 
    45714568    assert(*pretregs == 0); 
    4572     cs.Iop = ESCAPE; 
    4573     cs.Iop2 = ESCctor; 
     4569    cs.Iop = ESCAPE | ESCctor; 
    45744570    cs.Iflags = 0; 
    45754571    cs.Irex = 0; 
    45764572    cs.IFL1 = FLctor; 
    45774573    cs.IEV1.Vtor = e; 
    45784574    c = gen(CNIL,&cs); 
    45794575    //except_push(c,e,NULL); 
    45804576    return c; 
    45814577#else 
    45824578    return NULL; 
    45834579#endif 
    45844580} 
    45854581 
    45864582code *cddtor(elem *e,regm_t *pretregs) 
    45874583{ 
    45884584#if SCPP 
    45894585    code cs; 
    45904586    code *c; 
    45914587 
    45924588#if 0 
    45934589    if (config.exe == EX_NT) 
    45944590    {   usednteh |= NTEHcleanup; 
    45954591        except_pop(NULL,e,NULL); 
    45964592        return nteh_gensindex(except_index_get() - 1); 
    45974593    } 
    45984594#else 
    45994595    usednteh |= EHcleanup; 
    46004596    if (config.exe == EX_NT) 
    46014597        usednteh |= NTEHcleanup; 
    46024598#endif 
    46034599    assert(*pretregs == 0); 
    4604     cs.Iop = ESCAPE; 
    4605     cs.Iop2 = ESCdtor; 
     4600    cs.Iop = ESCAPE | ESCdtor; 
    46064601    cs.Iflags = 0; 
    46074602    cs.Irex = 0; 
    46084603    cs.IFL1 = FLdtor; 
    46094604    cs.IEV1.Vtor = e; 
    46104605    c = gen(CNIL,&cs); 
    46114606    //except_pop(c,e,NULL); 
    46124607    return c; 
    46134608#else 
    46144609    return NULL; 
    46154610#endif 
    46164611} 
    46174612 
    46184613code *cdmark(elem *e,regm_t *pretregs) 
    46194614{ 
    46204615    return NULL; 
    46214616} 
    46224617 
    46234618#if !NTEXCEPTIONS 
    46244619code *cdsetjmp(elem *e,regm_t *pretregs) 
    46254620{ 
  • branches/dmd-1.x/src/backend/cod3.c

    r595 r596  
    201201        2,2,2,M|3,      M|T|E|4,M|3,M|3,M|3,    // A8 
    202202        M|E|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,     // B0 
    203203        2,2,M|T|E|4,M|3, M|3,M|3,M|3,M|3,       // B8 
    204204        M|3,M|3,M|T|E|4,M|3, M|T|E|4,M|T|E|4,M|T|E|4,M|3,       // C0 
    205205        2,2,2,2,        2,2,2,2,                // C8 
    206206        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // D0 
    207207        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // D8 
    208208        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // E0 
    209209        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // E8 
    210210        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // F0 
    211211        M|3,M|3,M|3,M|3, M|3,M|3,M|3,2          // F8 
    212212}; 
    213213 
    214214/************************************ 
    215215 * Determine if there is a modregrm byte for code. 
    216216 */ 
    217217 
    218218int cod3_EA(code *c) 
    219219{   unsigned ins; 
    220220 
    221     switch (c->Iop) 
    222     {   case ESCAPE: 
    223             ins = 0; 
    224             break; 
    225         case 0x0F: 
    226             ins = inssize2[c->Iop2]; 
    227             break; 
    228         default: 
    229             ins = inssize[c->Iop]; 
    230             break; 
    231     } 
     221    unsigned op1 = c->Iop & 0xFF; 
     222    if (op1 == ESCAPE) 
     223        ins = 0; 
     224    else if ((c->Iop & 0xFF00) == 0x0F00) 
     225        ins = inssize2[op1]; 
     226    else 
     227        ins = inssize[op1]; 
    232228    return ins & M; 
    233229} 
    234230 
    235231/******************************** 
    236232 * Fix global variables for 386. 
    237233 */ 
    238234 
    239235void cod3_set386() 
    240236{ 
    241237//    if (I32) 
    242238    {   unsigned i; 
    243239 
    244240        inssize[0xA0] = T|5; 
    245241        inssize[0xA1] = T|5; 
    246242        inssize[0xA2] = T|5; 
    247243        inssize[0xA3] = T|5; 
    248244        BPRM = 5;                       /* [EBP] addressing mode        */ 
    249245        fregsaved = mBP | mBX | mSI | mDI;      // saved across function calls 
    250246        FLOATREGS = FLOATREGS_32; 
    251247        FLOATREGS2 = FLOATREGS2_32; 
     
    10541050    return mBP; 
    10551051 
    10561052Lcant: 
    10571053    return 0; 
    10581054} 
    10591055 
    10601056/*************************************** 
    10611057 * Gen code for OPframeptr 
    10621058 */ 
    10631059 
    10641060code *cdframeptr(elem *e, regm_t *pretregs) 
    10651061{ 
    10661062    unsigned reg; 
    10671063    code cs; 
    10681064 
    10691065    regm_t retregs = *pretregs & allregs; 
    10701066    if  (!retregs) 
    10711067        retregs = allregs; 
    10721068    code *cg = allocreg(&retregs, &reg, TYint); 
    10731069 
    1074     cs.Iop = ESCAPE; 
    1075     cs.Iop2 = ESCframeptr; 
     1070    cs.Iop = ESCAPE | ESCframeptr; 
    10761071    cs.Iflags = 0; 
    10771072    cs.Irex = 0; 
    10781073    cs.Irm = reg; 
    10791074    cg = gen(cg,&cs); 
    10801075 
    10811076    return cat(cg,fixresult(e,retregs,pretregs)); 
    10821077} 
    10831078 
    10841079/*************************************** 
    10851080 * Gen code for load of _GLOBAL_OFFSET_TABLE_. 
    10861081 * This value gets cached in the local variable 'localgot'. 
    10871082 */ 
    10881083 
    10891084code *cdgot(elem *e, regm_t *pretregs) 
    10901085{ 
    10911086#if TARGET_OSX 
    10921087    regm_t retregs; 
    10931088    unsigned reg; 
    10941089    code *c; 
    10951090 
     
    23032298 
    23042299int branch(block *bl,int flag) 
    23052300{ int bytesaved; 
    23062301  code *c,*cn,*ct; 
    23072302  targ_size_t offset,disp; 
    23082303  targ_size_t csize; 
    23092304 
    23102305  if (!flag) 
    23112306      bl->Bflags |= BFLjmpoptdone;      // assume this will be all 
    23122307  c = bl->Bcode; 
    23132308  if (!c) 
    23142309        return 0; 
    23152310  bytesaved = 0; 
    23162311  offset = bl->Boffset;                 /* offset of start of block     */ 
    23172312  while (1) 
    23182313  {     unsigned char op; 
    23192314 
    23202315        csize = calccodsize(c); 
    23212316        cn = code_next(c); 
    23222317        op = c->Iop; 
    2323         if ((op & 0xF0) == 0x70 && c->Iflags & CFjmp16 || 
     2318        if ((op & ~0x0F) == 0x70 && c->Iflags & CFjmp16 || 
    23242319            op == JMP) 
    23252320        { 
    23262321          L1: 
    23272322            switch (c->IFL2) 
    23282323            { 
    23292324                case FLblock: 
    23302325                    if (flag)           // no offsets yet, don't optimize 
    23312326                        goto L3; 
    23322327                    disp = c->IEV2.Vblock->Boffset - offset - csize; 
    23332328 
    23342329                    /* If this is a forward branch, and there is an aligned 
    23352330                     * block intervening, it is possible that shrinking 
    23362331                     * the jump instruction will cause it to be out of 
    23372332                     * range of the target. This happens if the alignment 
    23382333                     * prevents the target block from moving correspondingly 
    23392334                     * closer. 
    23402335                     */ 
    23412336                    if (disp >= 0x7F-4 && c->IEV2.Vblock->Boffset > offset) 
    23422337                    {   /* Look for intervening alignment 
    23432338                         */ 
     
    23712366 
    23722367                    if (!cr) 
    23732368                    {   // Didn't find it in forward search. Try backwards jump 
    23742369                        int s = 0; 
    23752370                        disp = 0; 
    23762371                        for (cr = bl->Bcode; cr != cn; cr = code_next(cr)) 
    23772372                        { 
    23782373                            assert(cr != NULL); // must have found it 
    23792374                            if (cr == ct) 
    23802375                                s = 1; 
    23812376                            if (s) 
    23822377                                disp += calccodsize(cr); 
    23832378                        } 
    23842379                    } 
    23852380 
    23862381                    if (config.flags4 & CFG4optimized && !flag) 
    23872382                    { 
    23882383                        /* Propagate branch forward past junk   */ 
    23892384                        while (1) 
    23902385                        {   if (ct->Iop == NOP || 
    2391                                 (ct->Iop == ESCAPE && ct->Iop2 == ESClinnum)) 
     2386                                ct->Iop == (ESCAPE | ESClinnum)) 
    23922387                            {   ct = code_next(ct); 
    23932388                                if (!ct) 
    23942389                                    goto L2; 
    23952390                            } 
    23962391                            else 
    23972392                            {   c->IEV2.Vcode = ct; 
    23982393                                ct->Iflags |= CFtarg; 
    23992394                                break; 
    24002395                            } 
    24012396                        } 
    24022397 
    24032398                        /* And eliminate jmps to jmps   */ 
    24042399                        if ((op == ct->Iop || ct->Iop == JMP) && 
    24052400                            (op == JMP || c->Iflags & CFjmp16)) 
    24062401                        {   c->IFL2 = ct->IFL2; 
    24072402                            c->IEV2.Vcode = ct->IEV2.Vcode; 
    24082403                            /*printf("eliminating branch\n");*/ 
    24092404                            goto L1; 
    24102405                        } 
    24112406                     L2: ; 
     
    24322427                if (op == JMP) 
    24332428                {   c->Iop = JMPS;              // JMP SHORT 
    24342429                    bytesaved += I16 ? 1 : 3; 
    24352430                } 
    24362431                else                            // else Jcond 
    24372432                {   c->Iflags &= ~CFjmp16;      // a branch is ok 
    24382433                    bytesaved += I16 ? 3 : 4; 
    24392434 
    24402435                    // Replace a cond jump around a call to a function that 
    24412436                    // never returns with a cond jump to that function. 
    24422437                    if (config.flags4 & CFG4optimized && 
    24432438                        config.target_cpu >= TARGET_80386 && 
    24442439                        disp == (I16 ? 3 : 5) && 
    24452440                        cn && 
    24462441                        cn->Iop == 0xE8 && 
    24472442                        cn->IFL2 == FLfunc && 
    24482443                        cn->IEVsym2->Sflags & SFLexit && 
    24492444                        !(cn->Iflags & (CFtarg | CFtarg2)) 
    24502445                       ) 
    24512446                    { 
    2452                         cn->Iop = 0x0F; 
    2453                         cn->Iop2 = (c->Iop & 0x0F) ^ 0x81; 
     2447                        cn->Iop = 0x0F00 | ((c->Iop & 0x0F) ^ 0x81); 
    24542448                        c->Iop = NOP; 
    24552449                        c->IEV2.Vcode = NULL; 
    24562450                        bytesaved++; 
    24572451 
    24582452                        // If nobody else points to ct, we can remove the CFtarg 
    24592453                        if (flag && ct) 
    24602454                        {   code *cx; 
    24612455 
    24622456                            for (cx = bl->Bcode; 1; cx = code_next(cx)) 
    24632457                            { 
    24642458                                if (!cx) 
    24652459                                {   ct->Iflags &= ~CFtarg; 
    24662460                                    break; 
    24672461                                } 
    24682462                                if (cx->IEV2.Vcode == ct) 
    24692463                                    break; 
    24702464                            } 
    24712465                        } 
    24722466                    } 
    24732467                } 
     
    25602554 
    25612555void assignaddrc(code *c) 
    25622556{ 
    25632557    int sn; 
    25642558    symbol *s; 
    25652559    unsigned char ins,rm; 
    25662560    targ_size_t soff; 
    25672561    targ_size_t base; 
    25682562 
    25692563    base = EBPtoESP; 
    25702564    for (; c; c = code_next(c)) 
    25712565    { 
    25722566#ifdef DEBUG 
    25732567        if (0) 
    25742568        {       printf("assignaddrc()\n"); 
    25752569                c->print(); 
    25762570        } 
    25772571        if (code_next(c) && code_next(code_next(c)) == c) 
    25782572            assert(0); 
    25792573#endif 
    2580         if (c->Iop == 0x0F
    2581             ins = inssize2[c->Iop2]; 
    2582         else if (c->Iop == ESCAPE) 
    2583         { 
    2584             if (c->Iop2 == ESCadjesp
     2574        if ((c->Iop & 0xFF00) == 0x0F00
     2575            ins = inssize2[c->Iop & 0xFF]; 
     2576        else if ((c->Iop & 0xFF) == ESCAPE) 
     2577        { 
     2578            if (c->Iop == (ESCAPE | ESCadjesp)
    25852579            { 
    25862580                //printf("adjusting EBPtoESP (%d) by %ld\n",EBPtoESP,c->IEV2.Vint); 
    25872581                EBPtoESP += c->IEV2.Vint; 
    25882582                c->Iop = NOP; 
    25892583            } 
    2590             if (c->Iop2 == ESCframeptr
     2584            if (c->Iop == (ESCAPE | ESCframeptr)
    25912585            {   // Convert to load of frame pointer 
    25922586                // c->Irm is the register to use 
    25932587                if (hasframe) 
    25942588                {   // MOV reg,EBP 
    25952589                    c->Iop = 0x89; 
    25962590                    if (c->Irm & 8) 
    25972591                        c->Irex |= REX_B; 
    25982592                    c->Irm = modregrm(3,BP,c->Irm & 7); 
    25992593                } 
    26002594                else 
    26012595                {   // LEA reg,EBPtoESP[ESP] 
    26022596                    c->Iop = 0x8D; 
    26032597                    if (c->Irm & 8) 
    26042598                        c->Irex |= REX_R; 
    26052599                    c->Irm = modregrm(2,c->Irm & 7,4); 
    26062600                    c->Isib = modregrm(0,4,SP); 
    26072601                    c->Iflags = CFoff; 
    26082602                    c->IFL1 = FLconst; 
    26092603                    c->IEV1.Vuns = EBPtoESP; 
    26102604                } 
    26112605            } 
    26122606            if (I64) 
    26132607                c->Irex |= REX_W; 
    26142608            continue; 
    26152609        } 
    26162610        else 
    2617             ins = inssize[c->Iop]; 
     2611            ins = inssize[c->Iop & 0xFF]; 
    26182612        if (!(ins & M) || 
    26192613            ((rm = c->Irm) & 0xC0) == 0xC0) 
    26202614            goto do2;           /* if no first operand          */ 
    26212615        if (is32bitaddr(I32,c->Iflags)) 
    26222616        { 
    26232617 
    26242618            if ( 
    26252619                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    26262620               ) 
    26272621                goto do2;       /* if no first operand  */ 
    26282622        } 
    26292623        else 
    26302624        { 
    26312625            if ( 
    26322626                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
    26332627               ) 
    26342628                goto do2;       /* if no first operand  */ 
    26352629        } 
    26362630        s = c->IEVsym1; 
    26372631        switch (c->IFL1) 
     
    29432937  if (debugc) 
    29442938  { 
    29452939      printf("+pinholeopt(%p)\n",c); 
    29462940  } 
    29472941#endif 
    29482942 
    29492943  if (b) 
    29502944  {     bn = b->Bnext; 
    29512945        usespace = (config.flags4 & CFG4space && b->BC != BCasm); 
    29522946        useopsize = (I16 || (config.flags4 & CFG4space && b->BC != BCasm)); 
    29532947  } 
    29542948  else 
    29552949  {     bn = NULL; 
    29562950        usespace = (config.flags4 & CFG4space); 
    29572951        useopsize = (I16 || config.flags4 & CFG4space); 
    29582952  } 
    29592953  for (; c; c = code_next(c)) 
    29602954  { 
    29612955    L1: 
    29622956        op = c->Iop; 
    2963         if (op == 0x0F
    2964             ins = inssize2[c->Iop2]; 
     2957        if ((op & 0xFF00) == 0x0F00
     2958            ins = inssize2[op & 0xFF]; 
    29652959        else 
    2966             ins = inssize[c->Iop]; 
     2960            ins = inssize[op & 0xFF]; 
    29672961        if (ins & M)            // if modregrm byte 
    29682962        {   int shortop = (c->Iflags & CFopsize) ? !I16 : I16; 
    29692963            int local_BPRM = BPRM; 
    29702964 
    29712965            if (c->Iflags & CFaddrsize) 
    29722966                local_BPRM ^= 5 ^ 6;    // toggle between 5 and 6 
    29732967 
    29742968            unsigned rm = c->Irm; 
    29752969            unsigned reg = rm & modregrm(0,7,0);          // isolate reg field 
    29762970            unsigned ereg = rm & 7; 
    29772971            //printf("c = %p, op = %02x rm = %02x\n", c, op, rm); 
    29782972 
    29792973            /* If immediate second operand      */ 
    29802974            if ((ins & T || op == 0xF6 || op == 0xF7) && 
    29812975                c->IFL2 == FLconst) 
    29822976            { 
    29832977                int flags = c->Iflags & CFpsw;      /* if want result in flags */ 
    29842978                targ_long u = c->IEV2.Vuns; 
    29852979                if (ins & E) 
    29862980                    u = (signed char) u; 
     
    30373031                                    if ((u & 0xFF) == 0xFF) 
    30383032                                        goto L3; 
    30393033                                } 
    30403034                            } 
    30413035                        } 
    30423036                        if (!shortop && useopsize) 
    30433037                        { 
    30443038                            if ((u & 0xFFFF0000) == 0xFFFF0000) 
    30453039                            {   c->Iflags ^= CFopsize; 
    30463040                                goto L1; 
    30473041                            } 
    30483042                            if ((u & 0xFFFF) == 0xFFFF && rm < modregrm(3,4,AX)) 
    30493043                            {   c->IEVoffset1 += 2; /* address MSW      */ 
    30503044                                c->IEV2.Vuns >>= 16; 
    30513045                                c->Iflags ^= CFopsize; 
    30523046                                goto L1; 
    30533047                            } 
    30543048                            if (rm >= modregrm(3,4,AX)) 
    30553049                            { 
    30563050                                if (u == 0xFF && (rm <= modregrm(3,4,BX) || I64)) 
    3057                                 {   c->Iop2 = 0xB6;     /* MOVZX        */ 
    3058                                     c->Iop = 0x0F; 
     3051                                {   c->Iop = 0x0FB6;     // MOVZX 
    30593052                                    c->Irm = modregrm(3,ereg,ereg); 
    30603053                                    if (c->Irex & REX_B) 
    30613054                                        c->Irex |= REX_R; 
    30623055                                    goto L1; 
    30633056                                } 
    30643057                                if (u == 0xFFFF) 
    3065                                 {   c->Iop2 = 0xB7;     /* MOVZX        */ 
    3066                                     c->Iop = 0x0F; 
     3058                                {   c->Iop = 0x0FB7;     // MOVZX 
    30673059                                    c->Irm = modregrm(3,ereg,ereg); 
    30683060                                    if (c->Irex & REX_B) 
    30693061                                        c->Irex |= REX_R; 
    30703062                                    goto L1; 
    30713063                                } 
    30723064                            } 
    30733065                        } 
    30743066                    } 
    30753067                } 
    30763068 
    30773069                /* Look for ADD,OR,SUB,XOR with u that we can eliminate */ 
    30783070                if (!flags && 
    30793071                    (op == 0x81 || op == 0x80) && 
    30803072                    (reg == modregrm(0,0,0) || reg == modregrm(0,1,0) ||  // ADD,OR 
    30813073                     reg == modregrm(0,5,0) || reg == modregrm(0,6,0))    // SUB, XOR 
    30823074                   ) 
    30833075                { 
    30843076                        if (u == 0) 
    30853077                        { 
    30863078                                c->Iop = NOP; 
     
    32463238            if ((ins & R) && (rm & 0xC0) == 0xC0) 
    32473239            {   switch (op) 
    32483240                {   case 0xC6:  op = 0xB0 + ereg; break; 
    32493241                    case 0xC7:  op = 0xB8 + ereg; break; 
    32503242                    case 0xFF: 
    32513243                        switch (reg) 
    32523244                        {   case 6<<3: op = 0x50+ereg; break;/* PUSH*/ 
    32533245                            case 0<<3: if (!I64) op = 0x40+ereg; break; /* INC*/ 
    32543246                            case 1<<3: if (!I64) op = 0x48+ereg; break; /* DEC*/ 
    32553247                        } 
    32563248                        break; 
    32573249                    case 0x8F:  op = 0x58 + ereg; break; 
    32583250                    case 0x87: 
    32593251                        if (reg == 0) op = 0x90 + ereg; 
    32603252                        break; 
    32613253                } 
    32623254                c->Iop = op; 
    32633255            } 
    32643256 
    32653257            // Look to replace SHL reg,1 with ADD reg,reg 
    3266             if ((op & 0xFE) == 0xD0 && 
     3258            if ((op & ~1) == 0xD0 && 
    32673259                     (rm & modregrm(3,7,0)) == modregrm(3,4,0) && 
    32683260                     config.target_cpu >= TARGET_80486) 
    32693261            { 
    32703262                c->Iop &= 1; 
    32713263                c->Irm = (rm & modregrm(3,0,7)) | (ereg << 3); 
    32723264                if (c->Irex & REX_B) 
    32733265                    c->Irex |= REX_R; 
    32743266                if (!(c->Iflags & CFpsw) && !I16) 
    32753267                    c->Iflags &= ~CFopsize; 
    32763268                goto L1; 
    32773269            } 
    32783270 
    32793271            /* Look for sign extended modregrm displacement, or 0 
    32803272             * displacement. 
    32813273             */ 
    32823274 
    32833275            if (((rm & 0xC0) == 0x80) && // it's a 16/32 bit disp 
    32843276                c->IFL1 == FLconst)      // and it's a constant 
    32853277            { 
    32863278                a = c->IEVpointer1; 
     
    33343326                else if (mod == modregrm(1,0,0) && rm == local_BPRM && 
    33353327                        c->IFL1 == FLconst && c->IEVpointer1 == 0) 
    33363328                {       c->Iop = 0x8B;          /* MOV reg,BP   */ 
    33373329                        c->Irm = modregrm(3,0,BP) + reg; 
    33383330                } 
    33393331            } 
    33403332 
    33413333            // Replace [R13] with 0[R13] 
    33423334            if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 
    33433335            { 
    33443336                c->Irm |= modregrm(1,0,0); 
    33453337                c->IFL1 = FLconst; 
    33463338                c->IEVpointer1 = 0; 
    33473339            } 
    33483340        } 
    33493341        else 
    33503342        { 
    33513343            switch (op) 
    33523344            { 
    33533345                default: 
    3354                     if ((op & 0xF0) != 0x70) 
     3346                    if ((op & ~0x0F) != 0x70) 
    33553347                        break; 
    33563348                case JMP: 
    33573349                    switch (c->IFL2) 
    33583350                    {   case FLcode: 
    33593351                                if (c->IEV2.Vcode == code_next(c)) 
    33603352                                {       c->Iop = NOP; 
    33613353                                        continue; 
    33623354                                } 
    33633355                                break; 
    33643356                        case FLblock: 
    33653357                                if (!code_next(c) && c->IEV2.Vblock == bn) 
    33663358                                {       c->Iop = NOP; 
    33673359                                        continue; 
    33683360                                } 
    33693361                                break; 
    33703362                        case FLconst: 
    33713363                        case FLfunc: 
    33723364                        case FLextern: 
    33733365                                break; 
    33743366                        default: 
     
    34793471} 
    34803472#endif 
    34813473 
    34823474/************************** 
    34833475 * Compute jump addresses for FLcode. 
    34843476 * Note: only works for forward referenced code. 
    34853477 *       only direct jumps and branches are detected. 
    34863478 *       LOOP instructions only work for backward refs. 
    34873479 */ 
    34883480 
    34893481void jmpaddr(code *c) 
    34903482{ code *ci,*cn,*ctarg,*cstart; 
    34913483  targ_size_t ad; 
    34923484  unsigned char op; 
    34933485 
    34943486  //printf("jmpaddr()\n"); 
    34953487  cstart = c;                           /* remember start of code       */ 
    34963488  while (c) 
    34973489  { 
    34983490        op = c->Iop; 
    3499         if (inssize[op] & T &&          /* if second operand            */ 
     3491        if (inssize[op & 0xFF] & T &&   // if second operand 
    35003492            c->IFL2 == FLcode && 
    3501             ((op & 0xF0) == 0x70 || op == JMP || op == JMPS || op == JCXZ)) 
     3493            ((op & ~0x0F) == 0x70 || op == JMP || op == JMPS || op == JCXZ)) 
    35023494        {       ci = code_next(c); 
    35033495                ctarg = c->IEV2.Vcode;  /* target code                  */ 
    35043496                ad = 0;                 /* IP displacement              */ 
    35053497                while (ci && ci != ctarg) 
    35063498                { 
    35073499                        ad += calccodsize(ci); 
    35083500                        ci = code_next(ci); 
    35093501                } 
    35103502                if (!ci) 
    35113503                    goto Lbackjmp;      // couldn't find it 
    35123504                if (I32 || op == JMP || op == JMPS || op == JCXZ) 
    35133505                        c->IEVpointer2 = ad; 
    35143506                else                    /* else conditional             */ 
    35153507                {       if (!(c->Iflags & CFjmp16))     /* if branch    */ 
    35163508                                c->IEVpointer2 = ad; 
    35173509                        else            /* branch around a long jump    */ 
    35183510                        {       cn = code_next(c); 
    35193511                                code_next(c) = code_calloc(); 
    35203512                                code_next(code_next(c)) = cn; 
    35213513                                c->Iop = op ^ 1;        /* converse jmp */ 
     
    35663558/***************************** 
    35673559 * Calculate and return code size of a code. 
    35683560 * Note that NOPs are sometimes used as markers, but are 
    35693561 * never output. LINNUMs are never output. 
    35703562 * Note: This routine must be fast. Profiling shows it is significant. 
    35713563 */ 
    35723564 
    35733565unsigned calccodsize(code *c) 
    35743566{   unsigned size; 
    35753567    unsigned op; 
    35763568    unsigned char rm,mod,ins; 
    35773569    unsigned iflags; 
    35783570    unsigned i32 = I32 || I64; 
    35793571    unsigned a32 = i32; 
    35803572 
    35813573#ifdef DEBUG 
    35823574    assert((a32 & ~1) == 0); 
    35833575#endif 
    35843576    iflags = c->Iflags; 
    35853577    op = c->Iop; 
     3578    if ((op & 0xFF00) == 0x0F00) 
     3579        op = 0x0F; 
     3580    else 
     3581        op &= 0xFF; 
    35863582    switch (op) 
    35873583    { 
    35883584        case 0x0F: 
    3589             ins = inssize2[c->Iop2]; 
     3585            ins = inssize2[c->Iop & 0xFF]; 
    35903586            size = ins & 7; 
     3587            if (c->Iop & 0xFF0000) 
     3588                size++; 
    35913589            break; 
    35923590 
    35933591        case NOP: 
    35943592        case ESCAPE: 
    35953593            size = 0;                   // since these won't be output 
    35963594            goto Lret2; 
    35973595 
    35983596        case ASM: 
    35993597            if (c->Iflags == CFaddrsize)        // kludge for DA inline asm 
    36003598                size = NPTRSIZE; 
    36013599            else 
    36023600                size = c->IEV1.as.len; 
    36033601            goto Lret2; 
    36043602 
    36053603        case 0xA1: 
    36063604        case 0xA3: 
    36073605            if (c->Irex) 
    36083606            { 
    36093607                size = 9;               // 64 bit immediate value for MOV to/from RAX 
    36103608                goto Lret; 
     
    36633661                            size += 2; 
    36643662                    } 
    36653663                } 
    36663664                else if (iflags & CFopsize) 
    36673665                {   if (I32) 
    36683666                        size -= 2; 
    36693667                    else 
    36703668                        size += 2; 
    36713669                } 
    36723670            } 
    36733671            if (iflags & CFaddrsize) 
    36743672            {   if (!I64) 
    36753673                    a32 ^= 1; 
    36763674                size++; 
    36773675            } 
    36783676            if (iflags & CFopsize) 
    36793677                size++;                         /* +1 for OPSIZE prefix         */ 
    36803678        } 
    36813679    } 
    36823680 
    3683     if ((op & 0xF0) == 0x70) 
     3681    if ((op & ~0x0F) == 0x70) 
    36843682    {   if (iflags & CFjmp16)           // if long branch 
    36853683            size += I16 ? 3 : 4;        // + 3(4) bytes for JMP 
    36863684    } 
    36873685    else if (ins & M)                   // if modregrm byte 
    36883686    { 
    36893687        rm = c->Irm; 
    36903688        mod = rm & 0xC0; 
    36913689        if (a32 || I64) 
    36923690        {   // 32 bit addressing 
    36933691            if (issib(rm)) 
    36943692                size++; 
    36953693            switch (mod) 
    36963694            {   case 0: 
    36973695                    if (issib(rm) && (c->Isib & 7) == 5 || 
    36983696                        (rm & 7) == 5) 
    36993697                        size += 4;      /* disp32                       */ 
    37003698                    if (c->Irex & REX_B && (rm & 7) == 5) 
    37013699                        /* Instead of selecting R13, this mode is an [RIP] relative 
    37023700                         * address. Although valid, it's redundant, and should not 
    37033701                         * be generated. Instead, generate 0[R13] instead of [R13]. 
     
    37073705                case 0x40: 
    37083706                    size++;             /* disp8                        */ 
    37093707                    break; 
    37103708                case 0x80: 
    37113709                    size += 4;          /* disp32                       */ 
    37123710                    break; 
    37133711            } 
    37143712        } 
    37153713        else 
    37163714        {   // 16 bit addressing 
    37173715            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    37183716                size++; 
    37193717            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    37203718                size += 2; 
    37213719        } 
    37223720    } 
    37233721 
    37243722Lret: 
    37253723    if (c->Irex) 
    37263724    {   size++; 
    3727         if (c->Irex & REX_W && (op & 0xF8) == 0xB8) 
     3725        if (c->Irex & REX_W && (op & ~7) == 0xB8) 
    37283726            size += 4; 
    37293727    } 
    37303728Lret2: 
    37313729    //printf("op = x%02x, size = %d\n",op,size); 
    37323730    return size; 
    37333731} 
    37343732 
    37353733/******************************** 
    37363734 * Return !=0 if codes match. 
    37373735 */ 
    37383736 
    37393737#if 0 
    37403738 
    37413739int code_match(code *c1,code *c2) 
    37423740{   code cs1,cs2; 
    37433741    unsigned char ins; 
    37443742 
    37453743    if (c1 == c2) 
    37463744        goto match; 
    37473745    cs1 = *c1; 
    37483746    cs2 = *c2; 
    37493747    if (cs1.Iop != cs2.Iop) 
    37503748        goto nomatch; 
    37513749    switch (cs1.Iop) 
    3752     {   case ESCAPE: 
    3753             switch (c->Iop2) 
    3754             { 
    3755                 case ESCctor: 
    3756                     goto nomatch; 
    3757                 case ESCdtor: 
    3758                     goto nomatch; 
    3759             } 
    3760             goto match; 
     3750    { 
     3751        case ESCAPE | ESCctor: 
     3752        case ESCAPE | ESCdtor: 
     3753            goto nomatch; 
     3754 
    37613755        case NOP: 
    37623756            goto match; 
    37633757        case ASM: 
    37643758            if (cs1.IEV1.as.len == cs2.IEV1.as.len && 
    37653759                memcmp(cs1.IEV1.as.bytes,cs2.IEV1.as.bytes,cs1.EV1.as.len) == 0) 
    37663760                goto match; 
    37673761            else 
    37683762                goto nomatch; 
     3764 
     3765        default: 
     3766            if ((cs1.Iop & 0xFF) == ESCAPE) 
     3767                goto match; 
     3768            break; 
    37693769    } 
    37703770    if (cs1.Iflags != cs2.Iflags) 
    37713771        goto nomatch; 
    37723772 
    3773     ins = inssize[cs1.Iop]; 
    3774     if (cs1.Iop == 0x0F
     3773    ins = inssize[cs1.Iop & 0xFF]; 
     3774    if ((cs1.Iop & 0xFF00) == 0x0F00
    37753775    { 
    3776         if (cs1.Iop2 != cs2.Iop2) 
    3777             goto nomatch; 
    3778         if (cs1.Iop2 == 0x38 || cs1.Iop2 == 0x3A) 
    3779         { 
    3780             if (cs1.Iop3 != cs2.Iop3) 
    3781                 goto nomatch; 
    3782         } 
    3783         ins = inssize2[cs1.Iop2]; 
     3776        ins = inssize2[cs1.Iop & 0xFF]; 
    37843777    } 
    37853778 
    37863779    if (ins & M)                // if modregrm byte 
    37873780    { 
    37883781        if (cs1.Irm != cs2.Irm) 
    37893782            goto nomatch; 
    37903783        if ((cs1.Irm & 0xC0) == 0xC0) 
    37913784            goto do2; 
    37923785        if (is32bitaddr(I32,cs1.Iflags)) 
    37933786        { 
    37943787            if (issib(cs1.Irm) && cs1.Isib != cs2.Isib) 
    37953788                goto nomatch; 
    37963789            if ( 
    37973790                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    37983791               ) 
    37993792                goto do2;       /* if no first operand  */ 
    38003793        } 
    38013794        else 
    38023795        { 
    38033796            if ( 
     
    38643857} 
    38653858 
    38663859unsigned codout(code *c) 
    38673860{ unsigned op; 
    38683861  unsigned char rm,mod; 
    38693862  unsigned char ins; 
    38703863  code *cn; 
    38713864  unsigned flags; 
    38723865  symbol *s; 
    38733866 
    38743867#ifdef DEBUG 
    38753868  if (debugc) printf("codout(%p), Coffset = x%llx\n",c,(unsigned long long)Coffset); 
    38763869#endif 
    38773870 
    38783871  pgen = bytes; 
    38793872  offset = Coffset; 
    38803873  for (; c; c = code_next(c)) 
    38813874  { 
    38823875#ifdef DEBUG 
    38833876        if (debugc) { printf("off=%02lx, sz=%ld, ",(long)OFFSET(),(long)calccodsize(c)); c->print(); } 
     3877        unsigned startoffset = OFFSET(); 
    38843878#endif 
    38853879        op = c->Iop; 
    3886         ins = inssize[op]; 
    3887         switch (op
     3880        ins = inssize[op & 0xFF]; 
     3881        switch (op & 0xFF
    38883882        {   case ESCAPE: 
    3889                 switch (c->Iop2
     3883                switch (op & 0xFF00
    38903884                {   case ESClinnum: 
    38913885                        /* put out line number stuff    */ 
    38923886                        objlinnum(c->IEV2.Vsrcpos,OFFSET()); 
    38933887                        break; 
    38943888#if SCPP 
    38953889#if 1 
    38963890                    case ESCctor: 
    38973891                    case ESCdtor: 
    38983892                    case ESCoffset: 
    38993893                        if (config.exe != EX_NT) 
    39003894                            except_pair_setoffset(c,OFFSET() - funcoffset); 
    39013895                        break; 
    39023896                    case ESCmark: 
    39033897                    case ESCrelease: 
    39043898                    case ESCmark2: 
    39053899                    case ESCrelease2: 
    39063900                        break; 
    39073901#else 
    39083902                    case ESCctor: 
    39093903                        except_push(OFFSET() - funcoffset,c->IEV1.Vtor,NULL); 
    39103904                        break; 
    39113905                    case ESCdtor: 
    39123906                        except_pop(OFFSET() - funcoffset,c->IEV1.Vtor,NULL); 
    39133907                        break; 
    39143908                    case ESCmark: 
    39153909                        except_mark(); 
    39163910                        break; 
    39173911                    case ESCrelease: 
    39183912                        except_release(); 
    39193913                        break; 
    39203914#endif 
    39213915#endif 
    39223916                } 
     3917#ifdef DEBUG 
     3918                assert(calccodsize(c) == 0); 
     3919#endif 
    39233920                continue; 
    39243921            case NOP:                   /* don't send them out          */ 
     3922                if (op != NOP) 
     3923                    break; 
     3924#ifdef DEBUG 
     3925                assert(calccodsize(c) == 0); 
     3926#endif 
    39253927                continue; 
    39263928            case ASM: 
     3929                if (op != ASM) 
     3930                    break; 
    39273931                FLUSH(); 
    39283932                if (c->Iflags == CFaddrsize)    // kludge for DA inline asm 
    39293933                { 
    39303934                    do32bit(FLblockoff,&c->IEV1,0); 
    39313935                } 
    39323936                else 
    39333937                { 
    39343938                    offset += obj_bytes(cseg,offset,c->IEV1.as.len,c->IEV1.as.bytes); 
    39353939                } 
     3940#ifdef DEBUG 
     3941                assert(calccodsize(c) == c->IEV1.as.len); 
     3942#endif 
    39363943                continue; 
    39373944        } 
    39383945        flags = c->Iflags; 
    39393946 
    39403947        // See if we need to flush (don't have room for largest code sequence) 
    3941         if (pgen - bytes > sizeof(bytes) - (4+4+4+4)) 
     3948        if (pgen - bytes > sizeof(bytes) - (1+4+4+8+8)) 
    39423949            FLUSH(); 
    39433950 
    39443951        // see if we need to put out prefix bytes 
    39453952        if (flags & (CFwait | CFPREFIX | CFjmp16)) 
    39463953        {   int override; 
    39473954 
    39483955            if (flags & CFwait) 
    39493956                GEN(0x9B);                      // FWAIT 
    39503957                                                /* ? SEGES : SEGSS      */ 
    39513958            switch (flags & CFSEG) 
    39523959            {   case CFes:      override = SEGES;       goto segover; 
    39533960                case CFss:      override = SEGSS;       goto segover; 
    39543961                case CFcs:      override = SEGCS;       goto segover; 
    39553962                case CFds:      override = SEGDS;       goto segover; 
    39563963                case CFfs:      override = SEGFS;       goto segover; 
    39573964                case CFgs:      override = SEGGS;       goto segover; 
    39583965                segover:        GEN(override); 
    39593966                                break; 
    39603967            } 
    39613968 
    39623969            if (flags & CFaddrsize) 
    39633970                GEN(0x67); 
    39643971 
    39653972            // Do this last because of instructions like ADDPD 
    39663973            if (flags & CFopsize) 
    39673974                GEN(0x66);                      /* operand size         */ 
    39683975 
    3969             if ((op & 0xF0) == 0x70 && flags & CFjmp16) /* long condit jmp */ 
     3976            if ((op & ~0x0F) == 0x70 && flags & CFjmp16) /* long condit jmp */ 
    39703977            { 
    39713978                if (!I16) 
    39723979                {   // Put out 16 bit conditional jump 
    3973                     c->Iop2 = 0x80 | (op & 0x0F); 
    3974                     c->Iop = op = 0x0F; 
     3980                    c->Iop = op = 0x0F00 | (0x80 | (op & 0x0F)); 
    39753981                } 
    39763982                else 
    39773983                { 
    39783984                    cn = code_calloc(); 
    39793985                    /*cxcalloc++;*/ 
    39803986                    code_next(cn) = code_next(c); 
    39813987                    code_next(c) = cn;          // link into code 
    39823988                    cn->Iop = JMP;              // JMP block 
    39833989                    cn->IFL2 = c->IFL2; 
    39843990                    cn->IEV2.Vblock = c->IEV2.Vblock; 
    39853991                    c->Iop = op ^= 1;           // toggle condition 
    39863992                    c->IFL2 = FLconst; 
    39873993                    c->IEVpointer2 = I16 ? 3 : 5; // skip over JMP block 
    39883994                } 
    39893995            } 
    39903996        } 
    39913997 
    39923998        if (c->Irex) 
    39933999            GEN(c->Irex | REX); 
    3994         GEN(op); 
    3995         if (op == 0x0F) 
    3996         { 
    3997            ins = inssize2[c->Iop2]; 
    3998            GEN(c->Iop2); 
    3999            if (c->Iop2 == 0x38 || c->Iop2 == 0x3A) 
    4000                 GEN(c->Iop3); 
    4001         } 
     4000        if (op > 0xFF) 
     4001        { 
     4002            if ((op & 0xFF00) == 0x0F00) 
     4003                ins = inssize2[op & 0xFF]; 
     4004            if (op & 0xFF000000) 
     4005            {   GEN(op >> 24); 
     4006                GEN((op >> 8) & 0xFF); 
     4007                GEN(op & 0xFF); 
     4008                GEN((op >> 16) & 0xFF);         // yes, this is out of order. For 0x660F3A41 & 40 
     4009            } 
     4010            else if (op & 0xFF0000) 
     4011            { 
     4012                GEN((op >> 16) & 0xFF); 
     4013                GEN((op >> 8) & 0xFF); 
     4014                GEN(op & 0xFF); 
     4015            } 
     4016            else 
     4017            {   GEN((op >> 8) & 0xFF); 
     4018                GEN(op & 0xFF); 
     4019            } 
     4020        } 
     4021        else 
     4022            GEN(op); 
    40024023        if (ins & M)            /* if modregrm byte             */ 
    40034024        { 
    40044025            rm = c->Irm; 
    40054026            GEN(rm); 
    40064027 
    40074028            // Look for an address size override when working with the 
    40084029            // MOD R/M and SIB bytes 
    40094030 
    40104031            if (is32bitaddr( I32, flags)) 
    40114032            { 
    40124033                if (issib(rm)) 
    40134034                    GEN(c->Isib); 
    40144035                switch (rm & 0xC0) 
    40154036                {   case 0x40: 
    40164037                        do8bit((enum FL) c->IFL1,&c->IEV1);     // 8 bit 
    40174038                        break; 
    40184039                    case 0: 
    40194040                        if (!(issib(rm) && (c->Isib & 7) == 5 || 
    40204041                              (rm & 7) == 5)) 
    40214042                            break; 
     
    40784099                            if (c->Iflags & CFopsize) 
    40794100                                goto ptr1616; 
    40804101                            else 
    40814102                                goto ptr1632; 
    40824103 
    40834104                        case 0x68:              // PUSH immed32 
    40844105                            if ((enum FL)c->IFL2 == FLblock) 
    40854106                            { 
    40864107                                c->IFL2 = FLblockoff; 
    40874108                                goto do32; 
    40884109                            } 
    40894110                            else 
    40904111                                goto case_default; 
    40914112 
    40924113                        case 0xE8:              // CALL rel 
    40934114                        case 0xE9:              // JMP  rel 
    40944115                            flags |= CFselfrel; 
    40954116                            goto case_default; 
    40964117 
    40974118                        default: 
    4098                             if (I64 && (op & 0xF8) == 0xB8 && c->Irex & REX_W) 
     4119                            if (I64 && (op & ~7) == 0xB8 && c->Irex & REX_W) 
    40994120                                goto do64; 
    41004121                        case_default: 
    41014122                            if (c->Iflags & CFopsize) 
    41024123                                goto do16; 
    41034124                            else 
    41044125                                goto do32; 
    41054126                            break; 
    41064127                    } 
    41074128                } 
    41084129                else 
    41094130                { 
    41104131                    switch (op) { 
    41114132                        case 0xC2: 
    41124133                        case 0xCA: 
    41134134                            goto do16; 
    41144135                        case 0xA0: 
    41154136                        case 0xA1: 
    41164137                        case 0xA2: 
    41174138                        case 0xA3: 
    41184139                            if (c->Iflags & CFaddrsize) 
     
    41614182                                goto do32; 
    41624183                            else 
    41634184                                goto do16; 
    41644185                            break; 
    41654186                    } 
    41664187                } 
    41674188        } 
    41684189        else if (op == 0xF6)            /* TEST mem8,immed8             */ 
    41694190        {       if ((rm & (7<<3)) == 0) 
    41704191                        do8bit((enum FL)c->IFL2,&c->IEV2); 
    41714192        } 
    41724193        else if (op == 0xF7) 
    41734194        {   if ((rm & (7<<3)) == 0)     /* TEST mem16/32,immed16/32     */ 
    41744195            { 
    41754196                if ((I32 || I64) ^ ((c->Iflags & CFopsize) != 0)) 
    41764197                    do32bit((enum FL)c->IFL2,&c->IEV2,flags); 
    41774198                else 
    41784199                    do16bit((enum FL)c->IFL2,&c->IEV2,flags); 
    41794200            } 
    41804201        } 
     4202#ifdef DEBUG 
     4203        if (OFFSET() - startoffset != calccodsize(c)) 
     4204        { 
     4205            printf("actual: %d, calc: %d\n", (int)(OFFSET() - startoffset), (int)calccodsize(c)); 
     4206            c->print(); 
     4207            assert(0); 
     4208        } 
     4209#endif 
    41814210    } 
    41824211    FLUSH(); 
    41834212    Coffset = offset; 
    41844213    //printf("-codout(), Coffset = x%x\n", Coffset); 
    41854214    return offset;                      /* ending address               */ 
    41864215} 
    41874216 
    41884217 
    41894218STATIC void do64bit(enum FL fl,union evc *uev,int flags) 
    41904219{   char *p; 
    41914220    symbol *s; 
    41924221    targ_size_t ad; 
    41934222    long tmp; 
    41944223 
    41954224    assert(I64); 
    41964225    switch (fl) 
    41974226    { 
    41984227        case FLconst: 
    41994228            ad = * (targ_size_t *) uev; 
    42004229        L1: 
     
    46454674#endif 
    46464675        } 
    46474676  } 
    46484677} 
    46494678 
    46504679 
    46514680/********************************** 
    46524681 */ 
    46534682 
    46544683#if HYDRATE 
    46554684void code_hydrate(code **pc) 
    46564685{ 
    46574686    code *c; 
    46584687    unsigned char ins,rm; 
    46594688    enum FL fl; 
    46604689 
    46614690    assert(pc); 
    46624691    while (*pc) 
    46634692    { 
    46644693        c = (code *) ph_hydrate(pc); 
     4694        if ((c->Iop & 0xFF00) == 0x0F00) 
     4695            ins = inssize2[c->Iop & 0xFF]; 
     4696        else 
     4697            ins = inssize[c->Iop & 0xFF]; 
    46654698        switch (c->Iop) 
    4666         {   case 0x0F: 
    4667                 ins = inssize2[c->Iop2]; 
    4668                 break; 
     4699        { 
    46694700            default: 
    4670                 ins = inssize[c->Iop]; 
    4671                 break; 
    4672             case ESCAPE: 
    4673                 switch (c->Iop2) 
    4674                 {   case ESClinnum: 
    4675                         srcpos_hydrate(&c->IEV2.Vsrcpos); 
    4676                         break; 
    4677                     case ESCctor: 
    4678                     case ESCdtor: 
    4679                         el_hydrate(&c->IEV1.Vtor); 
    4680                         break; 
    4681                 } 
     4701                break; 
     4702 
     4703            case ESCAPE | ESClinnum: 
     4704                srcpos_hydrate(&c->IEV2.Vsrcpos); 
    46824705                goto done; 
     4706 
     4707            case ESCAPE | ESCctor: 
     4708            case ESCAPE | ESCdtor: 
     4709                el_hydrate(&c->IEV1.Vtor); 
     4710                goto done; 
     4711 
    46834712            case ASM: 
    46844713                ph_hydrate(&c->IEV1.as.bytes); 
    46854714                goto done; 
    46864715        } 
    46874716        if (!(ins & M) || 
    46884717            ((rm = c->Irm) & 0xC0) == 0xC0) 
    46894718            goto do2;           /* if no first operand          */ 
    46904719        if (is32bitaddr(I32,c->Iflags)) 
    46914720        { 
    46924721 
    46934722            if ( 
    46944723                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    46954724               ) 
    46964725                goto do2;       /* if no first operand  */ 
    46974726        } 
    46984727        else 
    46994728        { 
    47004729            if ( 
    47014730                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
    47024731               ) 
     
    48094838 
    48104839        pc = &code_next(c); 
    48114840    } 
    48124841} 
    48134842#endif 
    48144843 
    48154844/********************************** 
    48164845 */ 
    48174846 
    48184847#if DEHYDRATE 
    48194848void code_dehydrate(code **pc) 
    48204849{ 
    48214850    code *c; 
    48224851    unsigned char ins,rm; 
    48234852    enum FL fl; 
    48244853 
    48254854    while ((c = *pc) != NULL) 
    48264855    { 
    48274856        ph_dehydrate(pc); 
    48284857 
     4858        if ((c->Iop & 0xFF00) == 0x0F00) 
     4859            ins = inssize2[c->Iop & 0xFF]; 
     4860        else 
     4861            ins = inssize[c->Iop & 0xFF]; 
    48294862        switch (c->Iop) 
    4830         {   case 0x0F: 
    4831                 ins = inssize2[c->Iop2]; 
    4832                 break; 
     4863        { 
    48334864            default: 
    4834                 ins = inssize[c->Iop]; 
    4835                 break; 
    4836             case ESCAPE: 
    4837                 switch (c->Iop2) 
    4838                 {   case ESClinnum: 
    4839                         srcpos_dehydrate(&c->IEV2.Vsrcpos); 
    4840                         break; 
    4841                     case ESCctor: 
    4842                     case ESCdtor: 
    4843                         el_dehydrate(&c->IEV1.Vtor); 
    4844                         break; 
    4845                 } 
     4865                break; 
     4866 
     4867            case ESCAPE | ESClinnum: 
     4868                srcpos_dehydrate(&c->IEV2.Vsrcpos); 
    48464869                goto done; 
     4870 
     4871            case ESCAPE | ESCctor: 
     4872            case ESCAPE | ESCdtor: 
     4873                el_dehydrate(&c->IEV1.Vtor); 
     4874                goto done; 
     4875 
    48474876            case ASM: 
    48484877                ph_dehydrate(&c->IEV1.as.bytes); 
    48494878                goto done; 
    48504879        } 
    48514880 
    48524881        if (!(ins & M) || 
    48534882            ((rm = c->Irm) & 0xC0) == 0xC0) 
    48544883            goto do2;           /* if no first operand          */ 
    48554884        if (is32bitaddr(I32,c->Iflags)) 
    48564885        { 
    48574886 
    48584887            if ( 
    48594888                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    48604889               ) 
    48614890                goto do2;       /* if no first operand  */ 
    48624891        } 
    48634892        else 
    48644893        { 
    48654894            if ( 
    48664895                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
     
    49825011 */ 
    49835012 
    49845013#if DEBUG 
    49855014 
    49865015void WRcodlst(code *c) 
    49875016{ for (; c; c = code_next(c)) 
    49885017        c->print(); 
    49895018} 
    49905019 
    49915020void code::print() 
    49925021{ 
    49935022  unsigned op,rm; 
    49945023  unsigned char ins; 
    49955024  code *c = this; 
    49965025 
    49975026  if (c == CNIL) 
    49985027  {     printf("code 0\n"); 
    49995028        return; 
    50005029  } 
    50015030  op = c->Iop; 
    5002   ins = inssize[op]; 
    5003   if (op == 0x0F) 
    5004   {     op = 0x0F00 + c->Iop2; 
    5005         if (op == 0x0F38 || op == 0x0F3A) 
    5006             op = (op << 8) | c->Iop3; 
    5007         ins = inssize2[c->Iop2]; 
    5008   } 
     5031 
     5032    if ((c->Iop & 0xFF00) == 0x0F00) 
     5033        ins = inssize2[op & 0xFF]; 
     5034    else 
     5035        ins = inssize[op & 0xFF]; 
     5036 
    50095037  printf("code %p: nxt=%p op=%02x",c,code_next(c),op); 
    5010   if (op == ESCAPE) 
    5011   {     if (c->Iop2 == ESClinnum) 
     5038  if ((op & 0xFF) == ESCAPE) 
     5039  {     if ((op & 0xFF00) == ESClinnum) 
    50125040        {   printf(" linnum = %d\n",c->IEV2.Vsrcpos.Slinnum); 
    50135041            return; 
    50145042        } 
    5015         printf(" ESCAPE %d",c->Iop2); 
     5043        printf(" ESCAPE %d",c->Iop >> 8); 
    50165044  } 
    50175045  if (c->Iflags) 
    50185046        printf(" flg=%x",c->Iflags); 
    50195047  if (ins & M) 
    50205048  {     rm = c->Irm; 
    50215049        printf(" rm=%02x=%d,%d,%d",rm,(rm>>6)&3,(rm>>3)&7,rm&7); 
    50225050        if (I32 && issib(rm)) 
    50235051        {   unsigned char sib = c->Isib; 
    50245052            printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 
    50255053        } 
    50265054        if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 
    50275055        { 
    50285056            switch (c->IFL1) 
    50295057            { 
    50305058                case FLconst: 
    50315059                case FLoffset: 
    50325060                    printf(" int = %4d",c->IEV1.Vuns); 
    50335061                    break; 
    50345062                case FLblock: 
    50355063                    printf(" block = %p",c->IEV1.Vblock); 
  • branches/dmd-1.x/src/backend/cod4.c

    r577 r596  
    12231223                cl = getlvalue(&cs,e1,0);       /* get EA               */ 
    12241224                regm_t idxregs = idxregm(&cs); 
    12251225                retregs = *pretregs & (ALLREGS | mBP) & ~idxregs; 
    12261226                if (!retregs) 
    12271227                    retregs = ALLREGS & ~idxregs; 
    12281228                cg = allocreg(&retregs,&resreg,tyml); 
    12291229                cs.Iop = 0x69;                  /* IMUL reg,EA,e2value  */ 
    12301230                cs.IFL2 = FLconst; 
    12311231                cs.IEV2.Vint = e2factor; 
    12321232                opr = resreg; 
    12331233            } 
    12341234            else if (!I16 && !byte) 
    12351235            { 
    12361236             L1: 
    12371237                retregs = *pretregs & (ALLREGS | mBP); 
    12381238                if (!retregs) 
    12391239                    retregs = ALLREGS; 
    12401240                cr = codelem(e2,&retregs,FALSE); /* load rvalue in reg  */ 
    12411241                cl = getlvalue(&cs,e1,retregs); /* get EA               */ 
    12421242                cg = getregs(retregs);          /* destroy these regs   */ 
    1243                 cs.Iop = 0x0F;                  /* IMUL resreg,EA       */ 
    1244                 cs.Iop2 = 0xAF; 
     1243                cs.Iop = 0x0FAF;                // IMUL resreg,EA 
    12451244                resreg = findreg(retregs); 
    12461245                opr = resreg; 
    12471246            } 
    12481247            else 
    12491248            { 
    12501249                retregs = mAX; 
    12511250                cr = codelem(e2,&retregs,FALSE); // load rvalue in AX 
    12521251                cl = getlvalue(&cs,e1,mAX);     // get EA 
    12531252                cg = getregs(byte ? mAX : mAX | mDX); // destroy these regs 
    12541253                cs.Iop = 0xF7 ^ byte;           // [I]MUL EA 
    12551254            } 
    12561255            cs.Irm |= modregrm(0,opr,0); 
    12571256            c = gen(CNIL,&cs); 
    12581257        } 
    12591258        else // /= or %= 
    12601259        {   targ_size_t e2factor; 
    12611260            int pow2; 
    12621261            targ_ulong m; 
    12631262 
    12641263            assert(!byte);                      // should never happen 
     
    25702569            if (cx->Iop == 0x81 && (cx->Irm & modregrm(3,7,0)) == modregrm(3,4,0)) 
    25712570            { 
    25722571                // Convert AND of a word to AND of a dword, zeroing upper word 
    25732572                retregs = mask[cx->Irm & 7]; 
    25742573                cx->Iflags &= ~CFopsize; 
    25752574                cx->IEV2.Vint &= 0xFFFF; 
    25762575                goto L1; 
    25772576            } 
    25782577        } 
    25792578        if (op == OPs16_32 && retregs == mAX) 
    25802579            c2 = gen1(c2,0x98);         /* CWDE                         */ 
    25812580        else 
    25822581        { 
    25832582            reg = findreg(retregs); 
    25842583            if (config.flags4 & CFG4speed && op == OPu16_32) 
    25852584            {   // AND reg,0xFFFF 
    25862585                c3 = genc2(NULL,0x81,modregrm(3,4,reg),0xFFFFu); 
    25872586            } 
    25882587            else 
    25892588            { 
    2590                 c3 = genregs(CNIL,0x0F,reg,reg); 
    2591                 c3->Iop2 = (op == OPu16_32) ? 0xB7 : 0xBF; /* MOVZX/MOVSX reg,reg */ 
     2589                unsigned iop = (op == OPu16_32) ? 0x0FB7 : 0x0FBF; /* MOVZX/MOVSX reg,reg */ 
     2590                c3 = genregs(CNIL,iop,reg,reg); 
    25922591            } 
    25932592            c2 = cat(c2,c3); 
    25942593        } 
    25952594     L1: 
    25962595        c3 = e1comsub ? getregs(retregs) : CNIL; 
    25972596    } 
    25982597    c4 = fixresult(e,retregs,pretregs); 
    25992598    c = cat4(c1,c2,c3,c4); 
    26002599  } 
    26012600  else if (*pretregs & mPSW || config.target_cpu < TARGET_80286) 
    26022601  { 
    26032602    // OPs16_32, OPs32_64 
    26042603    // CWD doesn't affect flags, so we can depend on the integer 
    26052604    // math to provide the flags. 
    26062605    retregs = mAX | mPSW;               // want integer result in AX 
    26072606    *pretregs &= ~mPSW;                 // flags are already set 
    26082607    c1 = codelem(e->E1,&retregs,FALSE); 
    26092608    c2 = getregs(mDX);                  // sign extend into DX 
    26102609    c2 = gen1(c2,0x99);                 // CWD/CDQ 
    26112610    c3 = e1comsub ? getregs(retregs) : CNIL; 
     
    27242723    } 
    27252724    else 
    27262725    { 
    27272726     L1: 
    27282727        if (!I16) 
    27292728        { 
    27302729            if (op == OPs8int && reg == AX && size == 2) 
    27312730            {   c3 = gen1(c3,0x98);             /* CBW                  */ 
    27322731                c3->Iflags |= CFopsize;         /* don't do a CWDE      */ 
    27332732            } 
    27342733            else 
    27352734            { 
    27362735                /* We could do better by not forcing the src and dst    */ 
    27372736                /* registers to be the same.                            */ 
    27382737 
    27392738                if (config.flags4 & CFG4speed && op == OPu8_16) 
    27402739                {   // AND reg,0xFF 
    27412740                    c3 = genc2(c3,0x81,modregrm(3,4,reg),0xFF); 
    27422741                } 
    27432742                else 
    2744                 {   c3 = genregs(c3,0x0F,reg,reg); 
    2745                     c3->Iop2 = (op == OPu8int) ? 0xB6 : 0xBE; /* MOVZX/MOVSX reg,reg */ 
     2743                { 
     2744                    unsigned iop = (op == OPu8int) ? 0x0FB6 : 0x0FBE; // MOVZX/MOVSX reg,reg 
     2745                    c3 = genregs(c3,iop,reg,reg); 
    27462746                } 
    27472747            } 
    27482748        } 
    27492749        else 
    27502750        { 
    27512751            if (op == OPu8int) 
    27522752                c3 = genregs(c3,0x30,reg+4,reg+4);      // XOR regH,regH 
    27532753            else 
    27542754            { 
    27552755                c3 = gen1(c3,0x98);             /* CBW                  */ 
    27562756                *pretregs &= ~mPSW;             /* flags already set    */ 
    27572757            } 
    27582758        } 
    27592759    } 
    27602760    c2 = getregs(retregs); 
    27612761L2: 
    27622762    c4 = fixresult(e,retregs,pretregs); 
    27632763    return cat6(c0,c1,c2,c3,c4,NULL); 
    27642764} 
    27652765 
     
    30333033        case OPbts:     op = 0xAB; mode = 5; break; 
    30343034 
    30353035        default: 
    30363036            assert(0); 
    30373037    } 
    30383038 
    30393039    e1 = e->E1; 
    30403040    e2 = e->E2; 
    30413041    cs.Iflags = 0; 
    30423042    c = getlvalue(&cs, e, RMload);      // get addressing mode 
    30433043    if (e->Eoper == OPbt && *pretregs == 0) 
    30443044        return cat(c, codelem(e2,pretregs,FALSE)); 
    30453045 
    30463046    ty1 = tybasic(e1->Ety); 
    30473047    word = (!I16 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0; 
    30483048    idxregs = idxregm(&cs);         // mask if index regs used 
    30493049 
    30503050//    if (e2->Eoper == OPconst && e2->EV.Vuns < 0x100)  // should do this instead? 
    30513051    if (e2->Eoper == OPconst) 
    30523052    { 
    3053         cs.Iop = 0x0F; 
    3054         cs.Iop2 = 0xBA;                         // BT rm,imm8 
     3053        cs.Iop = 0x0FBA;                         // BT rm,imm8 
    30553054        cs.Irm |= modregrm(0,mode,0); 
    30563055        cs.Iflags |= CFpsw | word; 
    30573056        cs.IFL2 = FLconst; 
    30583057        if (tysize[ty1] == SHORTSIZE) 
    30593058        { 
    30603059            cs.IEVoffset1 += (e2->EV.Vuns & ~15) >> 3; 
    30613060            cs.IEV2.Vint = e2->EV.Vint & 15; 
    30623061        } 
    30633062        else if (tysize[ty1] == 4) 
    30643063        { 
    30653064            cs.IEVoffset1 += (e2->EV.Vuns & ~31) >> 3; 
    30663065            cs.IEV2.Vint = e2->EV.Vint & 31; 
    30673066        } 
    30683067        else 
    30693068        { 
    30703069            cs.IEVoffset1 += (e2->EV.Vuns & ~63) >> 3; 
    30713070            cs.IEV2.Vint = e2->EV.Vint & 63; 
    30723071        } 
    30733072        c2 = gen(CNIL,&cs); 
    30743073    } 
    30753074    else 
    30763075    { 
    30773076        retregs = ALLREGS & ~idxregs; 
    30783077        c2 = scodelem(e2,&retregs,idxregs,TRUE); 
    30793078        reg = findreg(retregs); 
    30803079 
    3081         cs.Iop = 0x0F; 
    3082         cs.Iop2 = op;                           // BT rm,reg 
     3080        cs.Iop = 0x0F00 | op;                     // BT rm,reg 
    30833081        code_newreg(&cs,reg); 
    30843082        cs.Iflags |= CFpsw | word; 
    30853083        c2 = gen(c2,&cs); 
    30863084    } 
    30873085 
    30883086    if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register 
    30893087    { 
    30903088        code *nop = CNIL; 
    30913089        regm_t save = regcon.immed.mval; 
    30923090        code *cg = allocreg(&retregs,&reg,TYint); 
    30933091        regcon.immed.mval = save; 
    30943092        if ((*pretregs & mPSW) == 0) 
    30953093        { 
    30963094            cg = cat(cg,getregs(retregs)); 
    30973095            cg = genregs(cg,0x19,reg,reg);              // SBB reg,reg 
    30983096        } 
    30993097        else 
    31003098        { 
    31013099            cg = movregconst(cg,reg,1,8);               // MOV reg,1 
    31023100            nop = gennop(nop); 
     
    31373135    { 
    31383136        cl = getlvalue(&cs, e->E1, RMload);     // get addressing mode 
    31393137    } 
    31403138    else 
    31413139    { 
    31423140        retregs = allregs; 
    31433141        cl = codelem(e->E1, &retregs, FALSE); 
    31443142        reg = findreg(retregs); 
    31453143        cs.Irm = modregrm(3,0,reg & 7); 
    31463144        cs.Iflags = 0; 
    31473145        cs.Irex = 0; 
    31483146        if (reg & 8) 
    31493147            cs.Irex |= REX_B; 
    31503148    } 
    31513149 
    31523150    retregs = *pretregs & allregs; 
    31533151    if  (!retregs) 
    31543152        retregs = allregs; 
    31553153    cg = allocreg(&retregs, &reg, e->Ety); 
    31563154 
    3157     cs.Iop = 0x0F; 
    3158     cs.Iop2 = (e->Eoper == OPbsf) ? 0xBC : 0xBD;        // BSF/BSR reg,EA 
     3155    cs.Iop = (e->Eoper == OPbsf) ? 0x0FBC : 0x0FBD;        // BSF/BSR reg,EA 
    31593156    code_newreg(&cs, reg); 
    31603157    if (!I16 && sz == SHORTSIZE) 
    31613158        cs.Iflags |= CFopsize; 
    31623159    cg = gen(cg,&cs); 
    31633160 
    31643161    return cat3(cl,cg,fixresult(e,retregs,pretregs)); 
    31653162} 
    31663163 
    31673164/******************************************* 
    31683165 * Generate code for OPpair, OPrpair. 
    31693166 */ 
    31703167 
    31713168code *cdpair(elem *e, regm_t *pretregs) 
    31723169{ 
    31733170    regm_t retregs; 
    31743171    regm_t regs1; 
    31753172    regm_t regs2; 
    31763173    unsigned reg; 
    31773174    code *cg; 
    31783175    code *c1; 
  • branches/dmd-1.x/src/backend/code.h

    r595 r596  
    214214#define JBE     0x76 
    215215#define JA      0x77 
    216216#define JS      0x78 
    217217#define JNS     0x79 
    218218#define JP      0x7A 
    219219#define JNP     0x7B 
    220220#define JL      0x7C 
    221221#define JGE     0x7D 
    222222#define JLE     0x7E 
    223223#define JG      0x7F 
    224224 
    225225/* NOP is used as a placeholder in the linked list of instructions, no  */ 
    226226/* actual code will be generated for it.                                */ 
    227227#define NOP     0x2E    /* actually CS: (we don't use 0x90 because the  */ 
    228228                        /* silly Windows stuff wants to output 0x90's)  */ 
    229229 
    230230#define ESCAPE  0x3E    // marker that special information is here 
    231231                        // (Iop2 is the type of special information) 
    232232                        // (Same as DS:, but we will never generate 
    233233                        // a separate DS: opcode anyway) 
    234     #define ESClinnum   1       // line number information 
    235     #define ESCctor     2       // object is constructed 
    236     #define ESCdtor     3       // object is destructed 
    237     #define ESCmark     4       // mark eh stack 
    238     #define ESCrelease  5       // release eh stack 
    239     #define ESCoffset   6       // set code offset for eh 
    240     #define ESCadjesp   7       // adjust ESP by IEV2.Vint 
    241     #define ESCmark2    8       // mark eh stack 
    242     #define ESCrelease2 9       // release eh stack 
    243     #define ESCframeptr 10      // replace with load of frame pointer 
     234    #define ESClinnum   (1 << 8)       // line number information 
     235    #define ESCctor     (2 << 8)       // object is constructed 
     236    #define ESCdtor     (3 << 8)       // object is destructed 
     237    #define ESCmark     (4 << 8)       // mark eh stack 
     238    #define ESCrelease  (5 << 8)       // release eh stack 
     239    #define ESCoffset   (6 << 8)       // set code offset for eh 
     240    #define ESCadjesp   (7 << 8)       // adjust ESP by IEV2.Vint 
     241    #define ESCmark2    (8 << 8)       // mark eh stack 
     242    #define ESCrelease2 (9 << 8)       // release eh stack 
     243    #define ESCframeptr (10 << 8)      // replace with load of frame pointer 
    244244 
    245245#define ASM     0x36    // string of asm bytes, actually an SS: opcode 
    246246 
    247247/********************************* 
    248248 * Macros to ease generating code 
    249249 * modregrm:    generate mod reg r/m field 
    250250 * modregxrm:   reg could be R8..R15 
    251251 * modregrmx:   rm could be R8..R15 
    252252 * modregxrmx:  reg or rm could be R8..R15 
    253253 * NEWREG:      change reg field of x to r 
    254254 * genorreg:    OR  t,f 
    255255 */ 
    256256 
    257257#define modregrm(m,r,rm)        (((m)<<6)|((r)<<3)|(rm)) 
    258258#define modregxrm(m,r,rm)       ((((r)&8)<<15)|modregrm((m),(r)&7,rm)) 
    259259#define modregrmx(m,r,rm)       ((((rm)&8)<<13)|modregrm((m),r,(rm)&7)) 
    260260#define modregxrmx(m,r,rm)      ((((r)&8)<<15)|(((rm)&8)<<13)|modregrm((m),(r)&7,(rm)&7)) 
    261261 
    262262#define NEWREXR(x,r)            ((x)=((x)&~REX_R)|(((r)&8)>>1)) 
    263263#define NEWREG(x,r)             ((x)=((x)&~(7<<3))|((r)<<3)) 
     
    380380#define CFopsize       0x80     // prefix with operand size 
    381381#define CFaddrsize    0x100     // prefix with address size 
    382382#define CFds          0x200     // need DS override (not with es, ss, or cs ) 
    383383#define CFcs          0x400     // need CS override 
    384384#define CFfs          0x800     // need FS override 
    385385#define CFgs    (CFcs | CFfs)   // need GS override 
    386386#define CFwait       0x1000     // If I32 it indicates when to output a WAIT 
    387387#define CFselfrel    0x2000     // if self-relative 
    388388#define CFunambig    0x4000     // indicates cannot be accessed by other addressing 
    389389                                // modes 
    390390#define CFtarg2      0x8000     // like CFtarg, but we can't optimize this away 
    391391#define CFvolatile  0x10000     // volatile reference, do not schedule 
    392392#define CFclassinit 0x20000     // class init code 
    393393#define CFoffset64  0x40000     // offset is 64 bits 
    394394#define CFpc32      0x80000     // I64: PC relative 32 bit fixup 
    395395 
    396396#define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 
    397397#define CFSEG   (CFes | CFss | CFds | CFcs | CFfs | CFgs) 
    398398 
    399399 
    400     unsigned char Iop; 
    401     unsigned char Iop2;         // second opcode byte 
    402     unsigned char Iop3;         // third opcode byte 
     400    unsigned Iop; 
    403401 
    404402    union 
    405403    {   unsigned _Iea; 
    406404        struct 
    407405        { 
    408406            unsigned char _Irm;          // reg/mode 
    409407            unsigned char _Isib;         // SIB byte 
    410408            unsigned char _Irex;         // REX prefix 
    411409        } _ea; 
    412410    } _EA; 
    413411 
    414412#define Iea _EA._Iea 
    415413#define Irm _EA._ea._Irm 
    416414#define Isib _EA._ea._Isib 
    417415#define Irex _EA._ea._Irex 
    418416 
    419417    unsigned char IFL1,IFL2;    // FLavors of 1st, 2nd operands 
    420418    union evc IEV1;             // 1st operand, if any 
    421419      #define IEVpointer1 IEV1._EP.Vpointer 
    422420      #define IEVseg1     IEV1._EP.Vseg 
  • branches/dmd-1.x/src/iasm.c

    r577 r596  
    13531353                        case _ES: 
    13541354                                emit(0x26); 
    13551355                                pc->Iflags |= CFes; 
    13561356                                break; 
    13571357                        case _FS: 
    13581358                                emit(0x64); 
    13591359                                pc->Iflags |= CFfs; 
    13601360                                break; 
    13611361                        case _GS: 
    13621362                                emit(0x65); 
    13631363                                pc->Iflags |= CFgs; 
    13641364                                break; 
    13651365                        default: 
    13661366                                assert(0); 
    13671367                        } 
    13681368                } 
    13691369                break; 
    13701370        } 
    13711371        unsigned usOpcode = ptb.pptb0->usOpcode; 
    13721372 
     1373        pc->Iop = usOpcode; 
    13731374        if ((usOpcode & 0xFFFFFF00) == 0x660F3A00 ||    // SSE4 
    13741375            (usOpcode & 0xFFFFFF00) == 0x660F3800)      // SSE4 
    13751376        { 
    1376             pc->Iflags |= CFopsize; 
    1377             pc->Iop = 0x0F; 
    1378             pc->Iop2 = (usOpcode >> 8) & 0xFF; 
    1379             pc->Iop3 = usOpcode & 0xFF; 
     1377            pc->Iop = 0x66000F00 | ((usOpcode >> 8) & 0xFF) | ((usOpcode & 0xFF) << 16); 
    13801378            goto L3; 
    13811379        } 
    13821380        switch (usOpcode & 0xFF0000) 
    13831381        { 
    13841382            case 0: 
    13851383                break; 
    13861384 
    13871385            case 0x660000: 
    1388                 pc->Iflags |= CFopsize; 
    13891386                usOpcode &= 0xFFFF; 
    1390                 break
     1387                goto L3
    13911388 
    13921389            case 0xF20000:                      // REPNE 
    13931390            case 0xF30000:                      // REP/REPE 
    13941391                // BUG: What if there's an address size prefix or segment 
    13951392                // override prefix? Must the REP be adjacent to the rest 
    13961393                // of the opcode? 
    1397                 pcPrefix = code_calloc(); 
    1398                 pcPrefix->Iop = usOpcode >> 16; 
    13991394                usOpcode &= 0xFFFF; 
    1400                 break
     1395                goto L3
    14011396 
    14021397            case 0x0F0000:                      // an AMD instruction 
    14031398                puc = ((unsigned char *) &usOpcode); 
    14041399                if (puc[1] != 0x0F)             // if not AMD instruction 0x0F0F 
    14051400                    goto L4; 
    14061401                emit(puc[2]); 
    14071402                emit(puc[1]); 
    14081403                emit(puc[0]); 
    1409                 pc->Iop = puc[2]; 
    1410                 pc->Iop2 = puc[1]; 
     1404                pc->Iop >>= 8; 
    14111405                pc->IEVint2 = puc[0]; 
    14121406                pc->IFL2 = FLconst; 
    14131407                goto L3; 
    14141408 
    14151409            default: 
    14161410                puc = ((unsigned char *) &usOpcode); 
    14171411            L4: 
    14181412                emit(puc[2]); 
    14191413                emit(puc[1]); 
    14201414                emit(puc[0]); 
    1421                 pc->Iop = puc[2]; 
    1422                 pc->Iop2 = puc[1]; 
     1415                pc->Iop >>= 8; 
    14231416                pc->Irm = puc[0]; 
    14241417                goto L3; 
    14251418        } 
    14261419        if (usOpcode & 0xff00) 
    14271420        { 
    14281421            puc = ((unsigned char *) &(usOpcode)); 
    14291422            emit(puc[1]); 
    14301423            emit(puc[0]); 
    14311424            pc->Iop = puc[1]; 
    14321425            if (pc->Iop == 0x0f) 
    1433                 pc->Iop2 = puc[0]; 
     1426                pc->Iop = 0x0F00 | puc[0]; 
    14341427            else 
    14351428            { 
    14361429                if (usOpcode == 0xDFE0) // FSTSW AX 
    14371430                {   pc->Irm = puc[0]; 
    14381431                    goto L2; 
    14391432                } 
    14401433                if (asmstate.ucItype == ITfloat) 
    14411434                    pc->Irm = puc[0]; 
    14421435                else 
    14431436                {   pc->IEVint2 = puc[0]; 
    14441437                    pc->IFL2 = FLconst; 
    14451438                } 
    14461439            } 
    14471440        } 
    14481441        else 
    14491442        { 
    14501443            emit(usOpcode); 
    1451             pc->Iop = usOpcode; 
    14521444        } 
    14531445    L3: ; 
    14541446 
    14551447        // If CALL, Jxx or LOOPx to a symbolic location 
    14561448        if (/*asmstate.ucItype == ITjump &&*/ 
    14571449            popnd1 && popnd1->s && popnd1->s->isLabel()) 
    14581450        {   Dsymbol *s; 
    14591451 
    14601452            s = popnd1->s; 
    14611453            if (s == asmstate.psDollar) 
    14621454            { 
    14631455                pc->IFL2 = FLconst; 
    14641456                if (uSizemaskTable1 & (_8 | _16)) 
    14651457                    pc->IEVint2 = popnd1->disp; 
    14661458                else if (uSizemaskTable1 & _32) 
    14671459                    pc->IEVpointer2 = (targ_size_t) popnd1->disp; 
    14681460            } 
    14691461            else 
    14701462            {   LabelDsymbol *label; 
    14711463 
    14721464                label = s->isLabel(); 
    14731465                if (label) 
    1474                 {   if ((pc->Iop & 0xF0) == 0x70) 
     1466                {   if ((pc->Iop & ~0x0F) == 0x70) 
    14751467                        pc->Iflags |= CFjmp16; 
    14761468                    if (usNumops == 1) 
    14771469                    {   pc->IFL2 = FLblock; 
    14781470                        pc->IEVlsym2 = label; 
    14791471                    } 
    14801472                    else 
    14811473                    {   pc->IFL1 = FLblock; 
    14821474                        pc->IEVlsym1 = label; 
    14831475                    } 
    14841476                } 
    14851477            } 
    14861478        } 
    14871479 
    14881480        switch (usNumops) 
    14891481        { 
    14901482            case 0: 
    14911483                break; 
    14921484            case 1: 
    14931485                if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    14941486                     amodTable1 == _normal && (uRegmaskTable1 & _rplus_r))) 
    14951487                { 
    14961488                    unsigned reg = popnd1->base->val; 
    14971489                    if (reg & 8) 
    14981490                    {   reg &= 7; 
    14991491                        pc->Irex |= REX_B; 
    15001492                        assert(I64); 
    15011493                    } 
    15021494                    if (asmstate.ucItype == ITfloat) 
    15031495                        pc->Irm += reg; 
    1504                     else if (pc->Iop == 0x0f) 
    1505                         pc->Iop2 += reg; 
    15061496                    else 
    15071497                        pc->Iop += reg; 
    15081498#ifdef DEBUG 
    15091499                    auchOpcode[usIdx-1] += reg; 
    15101500#endif 
    15111501                } 
    15121502                else 
    15131503                {       asm_make_modrm_byte( 
    15141504#ifdef DEBUG 
    15151505                                auchOpcode, &usIdx, 
    15161506#endif 
    15171507                                pc, 
    15181508                                ptb.pptb1->usFlags, 
    15191509                                popnd1, NULL); 
    15201510                } 
    15211511                popndTmp = popnd1; 
    15221512                aoptyTmp = aoptyTable1; 
    15231513                uSizemaskTmp = uSizemaskTable1; 
    15241514L1: 
    15251515                if (aoptyTmp == _imm) 
     
    16211611                                popnd2, popnd1); 
    16221612                        } 
    16231613                        popndTmp = popnd1; 
    16241614                        aoptyTmp = aoptyTable1; 
    16251615                        uSizemaskTmp = uSizemaskTable1; 
    16261616                } 
    16271617                else 
    16281618                { 
    16291619                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    16301620                             amodTable1 == _normal && 
    16311621                             (uRegmaskTable1 & _rplus_r))) 
    16321622                        { 
    16331623                            unsigned reg = popnd1->base->val; 
    16341624                            if (reg & 8) 
    16351625                            {   reg &= 7; 
    16361626                                pc->Irex |= REX_B; 
    16371627                                assert(I64); 
    16381628                            } 
    16391629                            if (asmstate.ucItype == ITfloat) 
    16401630                                pc->Irm += reg; 
    1641                             else if (pc->Iop == 0x0f) 
    1642                                 pc->Iop2 += reg; 
    16431631                            else 
    16441632                                pc->Iop += reg; 
    16451633#ifdef DEBUG 
    16461634                            auchOpcode[usIdx-1] += reg; 
    16471635#endif 
    16481636                        } 
    16491637                        else 
    16501638                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    16511639                             amodTable2 == _normal && 
    16521640                             (uRegmaskTable2 & _rplus_r))) 
    16531641                        { 
    16541642                            unsigned reg = popnd2->base->val; 
    16551643                            if (reg & 8) 
    16561644                            {   reg &= 7; 
    16571645                                pc->Irex |= REX_B; 
    16581646                                assert(I64); 
    16591647                            } 
    16601648                            if (asmstate.ucItype == ITfloat) 
    16611649                                pc->Irm += reg; 
    1662                             else if (pc->Iop == 0x0f) 
    1663                                 pc->Iop2 += reg; 
    16641650                            else 
    16651651                                pc->Iop += reg; 
    16661652#ifdef DEBUG 
    16671653                            auchOpcode[usIdx-1] += reg; 
    16681654#endif 
    16691655                        } 
    16701656                        else if (ptb.pptb0->usOpcode == 0xF30FD6 || 
    16711657                                 ptb.pptb0->usOpcode == 0x0F12 || 
    16721658                                 ptb.pptb0->usOpcode == 0x0F16 || 
    16731659                                 ptb.pptb0->usOpcode == 0x660F50 || 
    16741660                                 ptb.pptb0->usOpcode == 0x0F50 || 
    16751661                                 ptb.pptb0->usOpcode == 0x660FD7 || 
    16761662                                 ptb.pptb0->usOpcode == 0x0FD7) 
    16771663                        { 
    16781664                            asm_make_modrm_byte( 
    16791665#ifdef DEBUG 
    16801666                                    auchOpcode, &usIdx, 
    16811667#endif 
    16821668                                    pc, 
    16831669                                    ptb.pptb1->usFlags, 
     
    17211707                                ptb.pptb1->usFlags, 
    17221708                                popnd2, popnd1); 
    17231709                        popndTmp = popnd3; 
    17241710                        aoptyTmp = aoptyTable3; 
    17251711                        uSizemaskTmp = uSizemaskTable3; 
    17261712                } 
    17271713                else { 
    17281714 
    17291715                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    17301716                             amodTable1 == _normal && 
    17311717                             (uRegmaskTable1 &_rplus_r))) 
    17321718                        { 
    17331719                            unsigned reg = popnd1->base->val; 
    17341720                            if (reg & 8) 
    17351721                            {   reg &= 7; 
    17361722                                pc->Irex |= REX_B; 
    17371723                                assert(I64); 
    17381724                            } 
    17391725                            if (asmstate.ucItype == ITfloat) 
    17401726                                pc->Irm += reg; 
    1741                             else if (pc->Iop == 0x0f) 
    1742                                 pc->Iop2 += reg; 
    17431727                            else 
    17441728                                pc->Iop += reg; 
    17451729#ifdef DEBUG 
    17461730                            auchOpcode[usIdx-1] += reg; 
    17471731#endif 
    17481732                        } 
    17491733                        else 
    17501734                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    17511735                             amodTable2 == _normal && 
    17521736                             (uRegmaskTable2 &_rplus_r))) 
    17531737                        { 
    17541738                            unsigned reg = popnd1->base->val; 
    17551739                            if (reg & 8) 
    17561740                            {   reg &= 7; 
    17571741                                pc->Irex |= REX_B; 
    17581742                                assert(I64); 
    17591743                            } 
    17601744                            if (asmstate.ucItype == ITfloat) 
    17611745                                pc->Irm += reg; 
    1762                             else if (pc->Iop == 0x0f) 
    1763                                 pc->Iop2 += reg; 
    17641746                            else 
    17651747                                pc->Iop += reg; 
    17661748#ifdef DEBUG 
    17671749                            auchOpcode[usIdx-1] += reg; 
    17681750#endif 
    17691751                        } 
    17701752                        else 
    17711753                                asm_make_modrm_byte( 
    17721754#ifdef DEBUG 
    17731755                                        auchOpcode, &usIdx, 
    17741756#endif 
    17751757                                        pc, 
    17761758                                        ptb.pptb1->usFlags, 
    17771759                                        popnd1, popnd2); 
    17781760 
    17791761                        popndTmp = popnd3; 
    17801762                        aoptyTmp = aoptyTable3; 
    17811763                        uSizemaskTmp = uSizemaskTable3; 
    17821764 
    17831765                } 
    17841766                goto L1; 
    17851767        } 
    17861768L2: 
    17871769 
    1788         if ((pc->Iop & 0xF8) == 0xD8 && 
     1770        if ((pc->Iop & ~7) == 0xD8 && 
    17891771            ADDFWAIT() && 
    17901772            !(ptb.pptb0->usFlags & _nfwait)) 
    17911773                pc->Iflags |= CFwait; 
    17921774        else if ((ptb.pptb0->usFlags & _fwait) && 
    17931775            config.target_cpu >= TARGET_80386) 
    17941776                pc->Iflags |= CFwait; 
    17951777 
    17961778#ifdef DEBUG 
    17971779        if (debuga) 
    17981780        {   unsigned u; 
    17991781 
    18001782            for (u = 0; u < usIdx; u++) 
    18011783                printf("  %02X", auchOpcode[u]); 
    18021784 
    18031785            printf("\t%s\t", asm_opstr(pop)); 
    18041786            if (popnd1) 
    18051787                asm_output_popnd(popnd1); 
    18061788            if (popnd2) { 
    18071789                printf(","); 
    18081790                asm_output_popnd(popnd2); 
  • trunk/src/backend/cgcod.c

    r595 r596  
    13431343            dbg_printf(" block (%p) Btry=%p Bindex=%d\n",b,b->Btry,b->Bindex); 
    13441344        } 
    13451345#endif 
    13461346        except_index_set(b->Bindex); 
    13471347        if (btry != b->Btry)                    // exited previous try block 
    13481348        { 
    13491349            except_pop(b,NULL,btry); 
    13501350            btry = b->Btry; 
    13511351        } 
    13521352        if (b->BC == BCtry) 
    13531353        { 
    13541354            except_push(b,NULL,b); 
    13551355            btry = b; 
    13561356            tryidx = except_index_get(); 
    13571357            b->Bcode = cat(nteh_gensindex(tryidx - 1),b->Bcode); 
    13581358        } 
    13591359 
    13601360        stack = NULL; 
    13611361        for (c = b->Bcode; c; c = code_next(c)) 
    13621362        { 
    1363             if (c->Iop == ESCAPE) 
     1363            if ((c->Iop & 0xFF) == ESCAPE) 
    13641364            { 
    13651365                c1 = NULL; 
    1366                 switch (c->Iop2
     1366                switch (c->Iop & 0xFF00
    13671367                { 
    13681368                    case ESCctor: 
    13691369//printf("ESCctor\n"); 
    13701370                        except_push(c,c->IEV1.Vtor,NULL); 
    13711371                        goto L1; 
    13721372 
    13731373                    case ESCdtor: 
    13741374//printf("ESCdtor\n"); 
    13751375                        except_pop(c,c->IEV1.Vtor,NULL); 
    13761376                    L1: if (config.flags2 & CFG2seh) 
    13771377                        { 
    13781378                            c1 = nteh_gensindex(except_index_get() - 1); 
    13791379                            code_next(c1) = code_next(c); 
    13801380                            code_next(c) = c1; 
    13811381                        } 
    13821382                        break; 
    13831383                    case ESCmark: 
    13841384//printf("ESCmark\n"); 
    13851385                        idx = except_index_get(); 
    13861386                        list_prependdata(&stack,idx); 
    13871387                        except_mark(); 
    13881388                        break; 
    13891389                    case ESCrelease: 
    13901390//printf("ESCrelease\n"); 
    13911391                        idx = list_data(stack); 
    13921392                        list_pop(&stack); 
    13931393                        if (idx != except_index_get()) 
    13941394                        { 
    13951395                            if (config.flags2 & CFG2seh) 
    13961396                            {   c1 = nteh_gensindex(idx - 1); 
    13971397                                code_next(c1) = code_next(c); 
    13981398                                code_next(c) = c1; 
    13991399                            } 
    14001400                            else 
    14011401                            {   except_pair_append(c,idx - 1); 
    1402                                 c->Iop2 = ESCoffset; 
     1402                                c->Iop = ESCAPE | ESCoffset; 
    14031403                            } 
    14041404                        } 
    14051405                        except_release(); 
    14061406                        break; 
    14071407                    case ESCmark2: 
    14081408//printf("ESCmark2\n"); 
    14091409                        except_mark(); 
    14101410                        break; 
    14111411                    case ESCrelease2: 
    14121412//printf("ESCrelease2\n"); 
    14131413                        except_release(); 
    14141414                        break; 
    14151415                } 
    14161416            } 
    14171417        } 
    14181418        assert(stack == NULL); 
    14191419        b->Bendindex = except_index_get(); 
    14201420 
    14211421        if (b->BC != BCret && b->BC != BCretexp) 
    14221422            lastidx = b->Bendindex; 
  • trunk/src/backend/cgen.c

    r595 r596  
    4949            c = c->next; 
    5050        c->Iflags |= flag; 
    5151    } 
    5252} 
    5353 
    5454/***************************** 
    5555 * Set rex bits on last code in list. 
    5656 */ 
    5757 
    5858void code_orrex(code *c,unsigned rex) 
    5959{ 
    6060    if (rex && c) 
    6161    {   while (c->next) 
    6262            c = c->next; 
    6363        c->Irex |= rex; 
    6464    } 
    6565} 
    6666 
    6767/************************************** 
    6868 * Set the opcode fields in cs. 
    69  * This is ridiculously complex, cs.Iop should 
    70  * just be an unsigned. 
    7169 */ 
    7270code *setOpcode(code *c, code *cs, unsigned op) 
    7371{ 
    74     cs->Iflags = 0; 
    75     if (op > 0xFF) 
    76     { 
    77         switch (op & 0xFF0000) 
    78         { 
    79             case 0: 
    80                 break; 
    81             case 0x660000: 
    82                 cs->Iflags = CFopsize; 
    83                 break; 
    84             case 0xF20000:                      // REPNE 
    85             case 0xF30000:                      // REP/REPE 
    86                 c = gen1(c, op >> 16); 
    87                 break; 
    88         } 
    89         cs->Iop = op >> 8; 
    90         cs->Iop2 = op & 0xFF; 
    91     } 
    92     else 
    93         cs->Iop = op; 
     72    cs->Iop = op; 
    9473    return c; 
    9574} 
    9675 
    9776/***************************** 
    9877 * Concatenate two code lists together. Return pointer to result. 
    9978 */ 
    10079 
    10180#if TX86 && __INTSIZE == 4 && __SC__ 
    10281__declspec(naked) code * __pascal cat(code *c1,code *c2) 
    10382{ 
    10483    _asm 
    10584    { 
    10685        mov     EAX,c1-4[ESP] 
    10786        mov     ECX,c2-4[ESP] 
    10887        test    EAX,EAX 
    10988        jne     L6D 
    11089        mov     EAX,ECX 
    11190        ret     8 
    11291 
    11392L6D:    mov     EDX,EAX 
     
    208187 
    209188code *gen1(code *c,unsigned op) 
    210189{ code *ce,*cstart; 
    211190 
    212191  ce = code_calloc(); 
    213192  ce->Iop = op; 
    214193  if (c) 
    215194  {     cstart = c; 
    216195        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    217196        code_next(c) = ce;                      /* link into list       */ 
    218197        return cstart; 
    219198  } 
    220199  return ce; 
    221200} 
    222201 
    223202code *gen2(code *c,unsigned op,unsigned rm) 
    224203{ code *ce,*cstart; 
    225204 
    226205  cstart = ce = code_calloc(); 
    227206  /*cxcalloc++;*/ 
    228   if (op > 0xFF) 
    229   {     ce->Iop = op >> 8; 
    230         ce->Iop2 = op & 0xFF; 
    231   } 
    232   else 
    233         ce->Iop = op; 
     207  ce->Iop = op; 
    234208  ce->Iea = rm; 
    235209  if (c) 
    236210  {     cstart = c; 
    237211        while (code_next(c)) c = code_next(c);  /* find end of list     */ 
    238212        code_next(c) = ce;                      /* link into list       */ 
    239213  } 
    240214  return cstart; 
    241215} 
    242216 
    243217code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 
    244218{ code *ce,*cstart; 
    245219 
    246220  cstart = ce = code_calloc(); 
    247221  /*cxcalloc++;*/ 
    248222  ce->Iop = op; 
    249223  ce->Irm = rm; 
    250224  ce->Isib = sib; 
    251225  ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 
    252226  if (sib & (REX_R << 16)) 
    253227        ce->Irex |= REX_X; 
     
    318292        { 
    319293                if (to == ES) 
    320294                        c = genregs(c,0x8E,0,from); 
    321295                else if (from == ES) 
    322296                        c = genregs(c,0x8C,0,to); 
    323297                else 
    324298                        c = genregs(c,0x89,from,to); 
    325299        } 
    326300        return c; 
    327301} 
    328302 
    329303/************************** 
    330304 * Generate a jump instruction. 
    331305 */ 
    332306 
    333307code *genjmp(code *c,unsigned op,unsigned fltarg,block *targ) 
    334308{   code cs; 
    335309    code *cj; 
    336310    code *cnop; 
    337311 
    338     cs.Iop = op
     312    cs.Iop = op & 0xFF
    339313    cs.Iflags = 0; 
    340314    cs.Irex = 0; 
    341315    if (op != JMP)                      /* if not already long branch   */ 
    342316          cs.Iflags = CFjmp16;          /* assume long branch for op = 0x7x */ 
    343317    cs.IFL2 = fltarg;                   /* FLblock (or FLcode)          */ 
    344318    cs.IEV2.Vblock = targ;              /* target block (or code)       */ 
    345319    if (fltarg == FLcode) 
    346320        ((code *)targ)->Iflags |= CFtarg; 
    347321 
    348322    if (config.flags4 & CFG4fastfloat)  // if fast floating point 
    349323        return gen(c,&cs); 
    350324 
    351325    cj = gen(CNIL,&cs); 
    352326    switch (op & 0xFF00)                /* look at second jump opcode   */ 
    353327    { 
    354328        /* The JP and JNP come from floating point comparisons          */ 
    355329        case JP << 8: 
    356330            cs.Iop = JP; 
    357331            gen(cj,&cs); 
    358332            break; 
     
    373347    } 
    374348    return cat(c,cj); 
    375349} 
    376350 
    377351code *gencs(code *c,unsigned op,unsigned ea,unsigned FL2,symbol *s) 
    378352{   code cs; 
    379353 
    380354    cs.Iop = op; 
    381355    cs.Iea = ea; 
    382356    cs.Iflags = 0; 
    383357    cs.IFL2 = FL2; 
    384358    cs.IEVsym2 = s; 
    385359    cs.IEVoffset2 = 0; 
    386360 
    387361    return gen(c,&cs); 
    388362} 
    389363 
    390364code *genc2(code *c,unsigned op,unsigned ea,targ_size_t EV2) 
    391365{   code cs; 
    392366 
    393     if (op > 0xFF) 
    394     {   cs.Iop = op >> 8; 
    395         cs.Iop2 = op & 0xFF; 
    396     } 
    397     else 
    398         cs.Iop = op; 
     367    cs.Iop = op; 
    399368    cs.Iea = ea; 
    400369    cs.Iflags = CFoff; 
    401370    cs.IFL2 = FLconst; 
    402371    cs.IEV2.Vsize_t = EV2; 
    403372    return gen(c,&cs); 
    404373} 
    405374 
    406375/***************** 
    407376 * Generate code. 
    408377 */ 
    409378 
    410379code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 
    411380{   code cs; 
    412381 
    413382    assert(FL1 < FLMAX); 
    414     if (op > 0xFF) 
    415     { 
    416         c = setOpcode(c, &cs, op); 
    417         cs.Iflags |= CFoff; 
    418     } 
    419     else 
    420     {   cs.Iop = op; 
    421         cs.Iflags = CFoff; 
    422     } 
     383    cs.Iop = op; 
     384    cs.Iflags = CFoff; 
    423385    cs.Iea = ea; 
    424386    cs.IFL1 = FL1; 
    425387    cs.IEV1.Vsize_t = EV1; 
    426388    return gen(c,&cs); 
    427389} 
    428390 
    429391/***************** 
    430392 * Generate code. 
    431393 */ 
    432394 
    433395code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 
    434396{   code cs; 
    435397 
    436398    assert(FL1 < FLMAX); 
    437     assert(op < 256); 
    438399    cs.Iop = op; 
    439400    cs.Iea = ea; 
    440401    cs.Iflags = CFoff; 
    441402    cs.IFL1 = FL1; 
    442403    cs.IEV1.Vsize_t = EV1; 
    443404    assert(FL2 < FLMAX); 
    444405    cs.IFL2 = FL2; 
    445406    cs.IEV2.Vsize_t = EV2; 
    446407    return gen(c,&cs); 
    447408} 
    448409 
    449410/*************************************** 
    450411 * Generate immediate multiply instruction for r1=r2*imm. 
    451412 * Optimize it into LEA's if we can. 
    452413 */ 
    453414 
    454415code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm) 
    455416{   code cs; 
    456417 
    457418    // These optimizations should probably be put into pinholeopt() 
     
    471432            c = genc2(c,0x69,modregxrmx(3,r1,r2),imm);    // IMUL r1,r2,imm 
    472433            break; 
    473434    } 
    474435    return c; 
    475436} 
    476437 
    477438/******************************** 
    478439 * Generate 'instruction' which is actually a line number. 
    479440 */ 
    480441 
    481442code *genlinnum(code *c,Srcpos srcpos) 
    482443{   code cs; 
    483444 
    484445#if 0 
    485446#if MARS 
    486447    printf("genlinnum(Sfilename = %p, Slinnum = %u)\n", srcpos.Sfilename, srcpos.Slinnum); 
    487448#else 
    488449    printf("genlinnum(Sfilptr = %p, Slinnum = %u)\n", srcpos.Sfilptr, srcpos.Slinnum); 
    489450#endif 
    490451#endif 
    491     cs.Iop = ESCAPE; 
    492     cs.Iop2 = ESClinnum; 
     452    cs.Iop = ESCAPE | ESClinnum; 
    493453    cs.Iflags = 0; 
    494454    cs.Irex = 0; 
    495455    cs.IFL1 = 0; 
    496456    cs.IFL2 = 0; 
    497457    cs.IEV2.Vsrcpos = srcpos; 
    498458    return gen(c,&cs); 
    499459} 
    500460 
    501461/****************************** 
    502462 * Append line number to existing code. 
    503463 */ 
    504464 
    505465void cgen_linnum(code **pc,Srcpos srcpos) 
    506466{ 
    507467    *pc = genlinnum(*pc,srcpos); 
    508468} 
    509469 
    510470/***************************** 
    511471 * Prepend line number to existing code. 
    512472 */ 
    513473 
    514474void cgen_prelinnum(code **pc,Srcpos srcpos) 
    515475{ 
    516476    *pc = cat(genlinnum(NULL,srcpos),*pc); 
    517477} 
    518478 
    519479/******************************** 
    520480 * Generate 'instruction' which tells the address resolver that the stack has 
    521481 * changed. 
    522482 */ 
    523483 
    524484code *genadjesp(code *c, int offset) 
    525485{   code cs; 
    526486 
    527487    if (!I16 && offset) 
    528488    { 
    529         cs.Iop = ESCAPE; 
    530         cs.Iop2 = ESCadjesp; 
     489        cs.Iop = ESCAPE | ESCadjesp; 
    531490        cs.Iflags = 0; 
    532491        cs.Irex = 0; 
    533492        cs.IEV2.Vint = offset; 
    534493        return gen(c,&cs); 
    535494    } 
    536495    else 
    537496        return c; 
    538497} 
    539498 
    540499/******************************** 
    541500 * Generate 'nop' 
    542501 */ 
    543502 
    544503code *gennop(code *c) 
    545504{ 
    546505    return gen1(c,NOP); 
    547506} 
    548507 
    549508/****************************** 
    550509 * Load CX with the value of _AHSHIFT. 
  • trunk/src/backend/cgsched.c

    r569 r596  
    761761        1,1,5,5,        4,4,0,0,                /* F8 */ 
    762762}; 
    763763 
    764764static unsigned char uopsx[8] = { 1,1,2,5,1,1,1,5 }; 
    765765 
    766766/************************************************ 
    767767 * Determine number of micro-ops for Pentium Pro and Pentium II processors. 
    768768 * 5 means 'complex'. 
    769769 * Doesn't currently handle: 
    770770 *      floating point 
    771771 *      MMX 
    772772 *      0F opcodes 
    773773 *      prefix bytes 
    774774 */ 
    775775 
    776776STATIC int uops(code *c) 
    777777{   int n; 
    778778    int op; 
    779779    int op2; 
    780780 
    781     op = c->Iop; 
     781    op = c->Iop & 0xFF; 
     782    if ((c->Iop & 0xFF00) == 0x0F00) 
     783        op = 0x0F; 
    782784    n = insuops[op]; 
    783785    if (!n)                             // if special case 
    784786    {   unsigned char irm,mod,reg,rm; 
    785787 
    786788        irm = c->Irm; 
    787789        mod = (irm >> 6) & 3; 
    788790        reg = (irm >> 3) & 7; 
    789791        rm = irm & 7; 
    790792 
    791793        switch (op) 
    792794        { 
    793795            case 0x10: 
    794796            case 0x11:                  // ADC rm,r 
    795797            case 0x18: 
    796798            case 0x19:                  // SBB rm,r 
    797799                n = (mod == 3) ? 2 : 4; 
    798800                break; 
    799801 
    800802            case 0x12: 
    801803            case 0x13:                  // ADC r,rm 
     
    966968                    n = 4; 
    967969                else if (reg == 4 || reg == 5)  // MUL/IMUL rm 
    968970                    n = (mod == 3) ? 3 : 4; 
    969971                else if (reg == 2 || reg == 3)  // NOT/NEG rm 
    970972                    n = (mod == 3) ? 1 : 4; 
    971973                break; 
    972974 
    973975            case 0xFF: 
    974976                if (reg == 2 || reg == 3 ||     // CALL rm, CALL m,rm 
    975977                    reg == 5)                   // JMP seg:offset 
    976978                    n = 5; 
    977979                else if (reg == 4) 
    978980                    n = (mod == 3) ? 1 : 2; 
    979981                else if (reg == 0 || reg == 1)  // INC/DEC rm 
    980982                    n = (mod == 3) ? 1 : 4; 
    981983                else if (reg == 6)              // PUSH rm 
    982984                    n = (mod == 3) ? 3 : 4; 
    983985                break; 
    984986 
    985987            case 0x0F: 
    986                 op2 = c->Iop2
     988                op2 = c->Iop & 0xFF
    987989                if ((op2 & 0xF0) == 0x80)       // Jcc 
    988990                {   n = 1; 
    989991                    break; 
    990992                } 
    991993                if ((op2 & 0xF0) == 0x90)       // SETcc 
    992994                {   n = (mod == 3) ? 1 : 3; 
    993995                    break; 
    994996                } 
    995997                if (op2 == 0xB6 || op2 == 0xB7 ||       // MOVZX 
    996998                    op2 == 0xBE || op2 == 0xBF)         // MOVSX 
    997999                {   n = 1; 
    9981000                    break; 
    9991001                } 
    10001002                if (op2 == 0xAF)                        // IMUL r,m 
    10011003                {   n = (mod == 3) ? 1 : 2; 
    10021004                    break; 
    10031005                } 
    10041006                break; 
    10051007        } 
    10061008    } 
     
    10081010        n = 5;                                  // copout for now 
    10091011    return n; 
    10101012} 
    10111013 
    10121014/****************************************** 
    10131015 * Determine pairing classification. 
    10141016 * Don't deal with floating point, just assume they are all NP (Not Pairable). 
    10151017 * Returns: 
    10161018 *      NP,UV,PU,PV optionally OR'd with PE 
    10171019 */ 
    10181020 
    10191021STATIC int pair_class(code *c) 
    10201022{   unsigned char op; 
    10211023    unsigned char irm,mod,reg,rm; 
    10221024    unsigned a32; 
    10231025    int pc; 
    10241026 
    10251027    // Of course, with Intel this is *never* simple, and Intel's 
    10261028    // documentation is vague about the specifics. 
    10271029 
    1028     op = c->Iop; 
     1030    op = c->Iop & 0xFF; 
     1031    if ((c->Iop & 0xFF00) == 0x0F00) 
     1032        op = 0x0F; 
    10291033    pc = pentcycl[op]; 
    10301034    a32 = I32; 
    10311035    if (c->Iflags & CFaddrsize) 
    10321036        a32 ^= 1; 
    10331037    irm = c->Irm; 
    10341038    mod = (irm >> 6) & 3; 
    10351039    reg = (irm >> 3) & 7; 
    10361040    rm = irm & 7; 
    10371041    switch (op) 
    10381042    { 
    10391043        case 0x0F:                              // 2 byte opcode 
    1040             if ((c->Iop2 & 0xF0) == 0x80)       // if Jcc 
     1044            if ((c->Iop & 0xF0) == 0x80)        // if Jcc 
    10411045                pc = PV | PF; 
    10421046            break; 
    10431047 
    10441048        case 0x80: 
    10451049        case 0x81: 
    10461050        case 0x83: 
    10471051            if (reg == 2 ||                     // ADC EA,immed 
    10481052                reg == 3)                       // SBB EA,immed 
    10491053            {   pc = PU; 
    10501054                goto L2; 
    10511055            } 
    10521056            goto L1;                            // AND/OR/XOR/ADD/SUB/CMP EA,immed 
    10531057 
    10541058        case 0x84: 
    10551059        case 0x85:                              // TEST EA,reg 
    10561060            if (mod == 3)                       // TEST reg,reg 
    10571061                pc = UV; 
    10581062            break; 
    10591063 
    10601064        case 0xC0: 
     
    11671171 
    11681172    if (PRO) 
    11691173    { 
    11701174        ci->uops = uops(c); 
    11711175        ci->isz = calccodsize(c); 
    11721176    } 
    11731177    else 
    11741178        ci->pair = pair_class(c); 
    11751179 
    11761180    unsigned char op; 
    11771181    unsigned char op2; 
    11781182    unsigned char irm,mod,reg,rm; 
    11791183    unsigned a32; 
    11801184    int pc; 
    11811185    unsigned r,w; 
    11821186    int sz = I32 ? 4 : 2; 
    11831187 
    11841188    ci->r = 0; 
    11851189    ci->w = 0; 
    11861190    ci->a = 0; 
    1187     op = c->Iop; 
     1191    op = c->Iop & 0xFF; 
     1192    if ((c->Iop & 0xFF00) == 0x0F00) 
     1193        op = 0x0F; 
    11881194    //printf("\tgetinfo %x, op %x \n",c,op); 
    11891195    pc = pentcycl[op]; 
    11901196    a32 = I32; 
    11911197    if (c->Iflags & CFaddrsize) 
    11921198        a32 ^= 1; 
    11931199    if (c->Iflags & CFopsize) 
    11941200        sz ^= 2 | 4; 
    11951201    irm = c->Irm; 
    11961202    mod = (irm >> 6) & 3; 
    11971203    reg = (irm >> 3) & 7; 
    11981204    rm = irm & 7; 
    11991205 
    12001206    r = oprw[op][0]; 
    12011207    w = oprw[op][1]; 
    12021208 
    12031209    switch (op) 
    12041210    { 
    12051211        case 0x50: 
    12061212        case 0x51: 
    12071213        case 0x52: 
     
    12951301                w = F; 
    12961302#if CLASSINIT2 
    12971303                ci->pair = UV;                  // it is patched to CMP EAX,0 
    12981304#else 
    12991305                ci->pair = NP; 
    13001306#endif 
    13011307            } 
    13021308            break; 
    13031309 
    13041310        case 0xF6: 
    13051311            r = grprw[3][reg][0];               // Grp 3, byte version 
    13061312            w = grprw[3][reg][1]; 
    13071313            break; 
    13081314 
    13091315        case 0xF7: 
    13101316            r = grprw[1][reg][0];               // Grp 3 
    13111317            w = grprw[1][reg][1]; 
    13121318            break; 
    13131319 
    13141320        case 0x0F: 
    1315             op2 = c->Iop2
     1321            op2 = c->Iop & 0xFF
    13161322            if ((op2 & 0xF0) == 0x80)           // if Jxx instructions 
    13171323            { 
    13181324                ci->r = F | N; 
    13191325                ci->w = N; 
    13201326                goto Lret; 
    13211327            } 
    13221328            ci->r = N; 
    13231329            ci->w = N;          // copout for now 
    13241330            goto Lret; 
    13251331 
    13261332        case 0xD7:                              // XLAT 
    13271333            ci->a = mAX | mBX; 
    13281334            break; 
    13291335 
    13301336        case 0xFF: 
    13311337            r = grprw[2][reg][0];               // Grp 5 
    13321338            w = grprw[2][reg][1]; 
    13331339            if (reg == 6)                       // PUSH rm 
    13341340                goto Lpush; 
    13351341            break; 
     
    17441750Lnopair: 
    17451751    return 0; 
    17461752} 
    17471753 
    17481754/******************************************** 
    17491755 * Get next instruction worth looking at for scheduling. 
    17501756 * Returns: 
    17511757 *      NULL    no more instructions 
    17521758 */ 
    17531759 
    17541760STATIC code * cnext(code *c) 
    17551761{ 
    17561762    while (1) 
    17571763    { 
    17581764        c = code_next(c); 
    17591765        if (!c) 
    17601766            break; 
    17611767        if (c->Iflags & (CFtarg | CFtarg2)) 
    17621768            break; 
    17631769        if (!(c->Iop == NOP || 
    1764               (c->Iop == ESCAPE && c->Iop2 == ESClinnum))) 
     1770              c->Iop == (ESCAPE | ESClinnum))) 
    17651771            break; 
    17661772    } 
    17671773    return c; 
    17681774} 
    17691775 
    17701776/****************************************** 
    17711777 * Instruction scheduler. 
    17721778 * Input: 
    17731779 *      c               list of instructions to schedule 
    17741780 *      scratch         scratch registers we can use 
    17751781 * Returns: 
    17761782 *      revised list of scheduled instructions 
    17771783 */ 
    17781784 
    17791785/////////////////////////////////// 
    17801786// Determine if c1 and c2 are swappable. 
    17811787// c1 comes before c2. 
    17821788// If they do not conflict 
    17831789//      return 0 
    17841790// If they do conflict 
     
    18671873            w2 &= ~F;                   // remove conflict 
    18681874            goto L1;                    // and try again 
    18691875        } 
    18701876#endif 
    18711877        // If other than the memory reference is a conflict 
    18721878        if (w1 & r2 & ~mMEM || (r1 | w1) & w2 & ~mMEM) 
    18731879        {   if (i) printf("\t1\n"); 
    18741880            if (i) printf("r1=%x, w1=%x, a1=%x, sz1=%d, r2=%x, w2=%x, a2=%x, sz2=%d\n",r1,w1,a1,sz1,r2,w2,a2,sz2); 
    18751881            goto Lconflict; 
    18761882        } 
    18771883 
    18781884        // If referring to distinct types, then no dependency 
    18791885        if (c1->Irex && c2->Irex && c1->Irex != c2->Irex) 
    18801886            goto Lswap; 
    18811887 
    18821888        ifl1 = c1->IFL1; 
    18831889        ifl2 = c2->IFL1; 
    18841890 
    18851891        // Special case: Allow indexed references using registers other than 
    18861892        // ESP and EBP to be swapped with PUSH instructions 
    1887         if (((c1->Iop & 0xF8) == 0x50 ||        // PUSH reg 
     1893        if (((c1->Iop & ~7) == 0x50 ||          // PUSH reg 
    18881894             c1->Iop == 0x6A ||                 // PUSH imm8 
    18891895             c1->Iop == 0x68 ||                 // PUSH imm16/imm32 
    18901896             (c1->Iop == 0xFF && ci1->reg == 6) // PUSH EA 
    18911897            ) && 
    18921898            ci2->flags & CIFLea && !(a2 & mSP) && 
    18931899            !(a2 & mBP && (long)c2->IEVpointer1 < 0) 
    18941900           ) 
    18951901        { 
    18961902            if (c1->Iop == 0xFF) 
    18971903            { 
    18981904                if (!(w2 & mMEM)) 
    18991905                    goto Lswap; 
    19001906            } 
    19011907            else 
    19021908                goto Lswap; 
    19031909        } 
    19041910 
    19051911        // Special case: Allow indexed references using registers other than 
    19061912        // ESP and EBP to be swapped with PUSH instructions 
    1907         if (((c2->Iop & 0xF8) == 0x50 ||        // PUSH reg 
     1913        if (((c2->Iop & ~7) == 0x50 ||          // PUSH reg 
    19081914             c2->Iop == 0x6A ||                 // PUSH imm8 
    19091915             c2->Iop == 0x68 ||                 // PUSH imm16/imm32 
    19101916             (c2->Iop == 0xFF && ci2->reg == 6) // PUSH EA 
    19111917            ) && 
    19121918            ci1->flags & CIFLea && !(a1 & mSP) && 
    19131919            !(a2 & mBP && (long)c2->IEVpointer1 < 0) 
    19141920           ) 
    19151921        { 
    19161922            if (c2->Iop == 0xFF) 
    19171923            { 
    19181924                if (!(w1 & mMEM)) 
    19191925                    goto Lswap; 
    19201926            } 
    19211927            else 
    19221928                goto Lswap; 
    19231929        } 
    19241930 
    19251931        // If not both an EA addressing mode, conflict 
    19261932        if (!(ci1->flags & ci2->flags & CIFLea)) 
    19271933        {   if (i) printf("\t2\n"); 
     
    22822288       ) 
    22832289    { 
    22842290        movesp = 1;                     // this is a MOV reg2,offset[ESP] 
    22852291        offset = (signed char)c->IEVpointer1; 
    22862292        reg2 = (c->Irm >> 3) & 7; 
    22872293    } 
    22882294 
    22892295 
    22902296    // Start at tblmax, and back up until we get a conflict 
    22912297    ic = -1; 
    22922298    imin = 0; 
    22932299    for (i = tblmax; i >= 0; i--) 
    22942300    {   Cinfo *cit; 
    22952301 
    22962302        cit = tbl[i]; 
    22972303        if (!cit) 
    22982304            continue; 
    22992305 
    23002306        // Look for special case swap 
    23012307        if (movesp && 
    2302             (cit->c->Iop & 0xF8) == 0x50 &&             // if PUSH reg1 
     2308            (cit->c->Iop & ~7) == 0x50 &&               // if PUSH reg1 
    23032309            (cit->c->Iop & 7) != reg2 &&                // if reg1 != reg2 
    23042310            ((signed char)c->IEVpointer1) >= -cit->spadjust 
    23052311           ) 
    23062312        { 
    23072313            c->IEVpointer1 += cit->spadjust; 
    23082314            //printf("\t1, spadjust = %d, ptr = x%x\n",cit->spadjust,c->IEVpointer1); 
    23092315            continue; 
    23102316        } 
    23112317 
    23122318        if (movesp && 
    23132319            cit->c->Iop == 0x83 && 
    23142320            cit->c->Irm == modregrm(3,5,SP) &&          // if SUB ESP,offset 
    23152321            cit->c->IFL2 == FLconst && 
    23162322            ((signed char)c->IEVpointer1) >= -cit->spadjust 
    23172323           ) 
    23182324        { 
    23192325            //printf("\t2, spadjust = %d\n",cit->spadjust); 
    23202326            c->IEVpointer1 += cit->spadjust; 
    23212327            continue; 
    23222328        } 
     
    25052511                c->IEVpointer1 -= cit->spadjust; 
    25062512                //printf("\t3, spadjust = %d, ptr = x%x\n",cit->spadjust,c->IEVpointer1); 
    25072513            } 
    25082514        } 
    25092515    } 
    25102516    if (i >= tblmax) 
    25112517        tblmax = i + 1; 
    25122518 
    25132519    // Now do a hack. Look back at immediately preceding instructions, 
    25142520    // and see if we can swap with a push. 
    25152521    if (0 && movesp) 
    25162522    {   int j; 
    25172523 
    25182524        while (1) 
    25192525        { 
    25202526            for (j = 1; i > j; j++) 
    25212527                if (tbl[i - j]) 
    25222528                    break; 
    25232529 
    25242530            if (i >= j && tbl[i - j] && 
    2525                    (tbl[i - j]->c->Iop & 0xF8) == 0x50 &&       // if PUSH reg1 
     2531                   (tbl[i - j]->c->Iop & ~7) == 0x50 &&       // if PUSH reg1 
    25262532                   (tbl[i - j]->c->Iop & 7) != reg2 &&  // if reg1 != reg2 
    25272533                   (signed char)c->IEVpointer1 >= REGSIZE) 
    25282534            { 
    25292535                //printf("\t-4 prec, i-j=%d, i=%d\n",i-j,i); 
    25302536                assert((unsigned)i < TBLMAX); 
    25312537                assert((unsigned)(i - j) < TBLMAX); 
    25322538                tbl[i] = tbl[i - j]; 
    25332539                tbl[i - j] = ci; 
    25342540                i -= j; 
    25352541                c->IEVpointer1 -= REGSIZE; 
    25362542            } 
    25372543            else 
    25382544                break; 
    25392545        } 
    25402546    } 
    25412547 
    25422548    //printf("\tinsert\n"); 
    25432549    return 1; 
    25442550} 
    25452551 
     
    26472653 * Returns: 
    26482654 *      next instruction (the tail) or 
    26492655 *      NULL for no more instructions 
    26502656 */ 
    26512657 
    26522658STATIC code * csnip(code *c) 
    26532659{   code **pc; 
    26542660    unsigned iflags; 
    26552661 
    26562662    if (c) 
    26572663    {   iflags = c->Iflags & CFclassinit; 
    26582664        while (1) 
    26592665        { 
    26602666            pc = &code_next(c); 
    26612667            c = *pc; 
    26622668            if (!c) 
    26632669                break; 
    26642670            if (c->Iflags & (CFtarg | CFtarg2)) 
    26652671                break; 
    26662672            if (!(c->Iop == NOP || 
    2667                   (c->Iop == ESCAPE && c->Iop2 == ESClinnum) || 
     2673                  c->Iop == (ESCAPE | ESClinnum) || 
    26682674                  c->Iflags & iflags)) 
    26692675                break; 
    26702676        } 
    26712677        *pc = NULL; 
    26722678    } 
    26732679    return c; 
    26742680} 
    26752681 
    26762682 
    26772683/****************************** 
    26782684 * Schedule Pentium instructions, 
    26792685 * based on Steve Russell's algorithm. 
    26802686 */ 
    26812687 
    26822688code *schedule(code *c,regm_t scratch) 
    26832689{ 
    26842690    code *cresult = NULL; 
    26852691    code **pctail = &cresult; 
    26862692    Schedule sch; 
    26872693 
    26882694    sch.initialize(0);                  // initialize scheduling table 
    26892695    while (c) 
    26902696    { 
    2691         if ((c->Iop == NOP || c->Iop == ESCAPE || c->Iflags & CFclassinit) && 
     2697        if ((c->Iop == NOP || (c->Iop & 0xFF) == ESCAPE || c->Iflags & CFclassinit) && 
    26922698            !(c->Iflags & (CFtarg | CFtarg2))) 
    26932699        {   code *cn; 
    26942700 
    26952701            // Just append this instruction to pctail and go to the next one 
    26962702            *pctail = c; 
    26972703            cn = code_next(c); 
    26982704            code_next(c) = NULL; 
    26992705            pctail = &code_next(c); 
    27002706            c = cn; 
    27012707            continue; 
    27022708        } 
    27032709 
    27042710        //printf("init\n"); 
    27052711        sch.initialize(sch.fpustackused);       // initialize scheduling table 
    27062712 
    27072713        while (c) 
    27082714        { 
    27092715            //printf("insert %p\n",c); 
    27102716            if (!sch.stage(c))          // store c in scheduling table 
    27112717                break; 
     
    28342840    code *c; 
    28352841    code *c1,*c2,*c3; 
    28362842    unsigned r1,r2; 
    28372843    unsigned mod,reg,rm; 
    28382844 
    28392845    //printf("peephole\n"); 
    28402846    for (c = cstart; c; c = c1) 
    28412847    {   unsigned char rmi; 
    28422848        unsigned char rmn; 
    28432849 
    28442850        //c->print(); 
    28452851        c1 = cnext(c); 
    28462852    Ln: 
    28472853        if (!c1) 
    28482854            break; 
    28492855        if (c1->Iflags & (CFtarg | CFtarg2)) 
    28502856            continue; 
    28512857 
    28522858        // Do: 
    28532859        //      PUSH    reg 
    2854         if (I32 && (c->Iop & 0xF8) == 0x50) 
     2860        if (I32 && (c->Iop & ~7) == 0x50) 
    28552861        {   unsigned reg = c->Iop & 7; 
    28562862 
    28572863            //  MOV     [ESP],reg       =>      NOP 
    28582864            if (c1->Iop == 0x8B && 
    28592865                c1->Irm == modregrm(0,reg,4) && 
    28602866                c1->Isib == modregrm(0,4,SP)) 
    28612867            {   c1->Iop = NOP; 
    28622868                continue; 
    28632869            } 
    28642870 
    28652871            //  PUSH    [ESP]           =>      PUSH    reg 
    28662872            if (c1->Iop == 0xFF && 
    28672873                c1->Irm == modregrm(0,6,4) && 
    28682874                c1->Isib == modregrm(0,4,SP)) 
    28692875            {   c1->Iop = 0x50 + reg; 
    28702876                continue; 
    28712877            } 
    28722878 
    28732879            //  CMP     [ESP],imm       =>      CMP     reg,i,, 
    28742880            if (c1->Iop == 0x83 && 
  • trunk/src/backend/cod1.c

    r595 r596  
    538538 
    539539/****************************** 
    540540 * Routine to aid in setting things up for gen(). 
    541541 * Look for common subexpression. 
    542542 * Can handle indirection operators, but not if they're common subs. 
    543543 * Input: 
    544544 *      e ->    elem where we get some of the data from 
    545545 *      cs ->   partially filled code to add 
    546546 *      op =    opcode 
    547547 *      reg =   reg field of (mod reg r/m) 
    548548 *      offset = data to be added to Voffset field 
    549549 *      keepmsk = mask of registers we must not destroy 
    550550 *      desmsk  = mask of registers destroyed by executing the instruction 
    551551 * Returns: 
    552552 *      pointer to code generated 
    553553 */ 
    554554 
    555555code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 
    556556        regm_t keepmsk,regm_t desmsk) 
    557557{ 
    558   code *c,*cg,*cd,*cprefix
     558  code *c,*cg,*cd
    559559 
    560560#ifdef DEBUG 
    561561  if (debugw) 
    562562    printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 
    563563            e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 
    564564#endif 
    565565 
    566566  assert(e); 
    567567  cs->Iflags = 0; 
    568568  cs->Irex = 0; 
    569   cprefix = NULL; 
    570   if (op > 0xFF)               // if 2 byte opcode 
    571         cprefix = setOpcode(NULL, cs, op); 
    572   else 
    573         cs->Iop = op; 
     569  cs->Iop = op; 
    574570  tym_t tym = e->Ety; 
    575571  int sz = tysize(tym); 
    576572 
    577573  /* Determine if location we want to get is in a register. If so,      */ 
    578574  /* substitute the register for the EA.                                */ 
    579575  /* Note that operators don't go through this. CSE'd operators are     */ 
    580576  /* picked up by comsub().                                             */ 
    581577  if (e->Ecount &&                      /* if cse                       */ 
    582578      e->Ecount != e->Ecomsub &&        /* and cse was generated        */ 
    583579      op != 0x8D && op != 0xC4 &&       /* and not an LEA or LES        */ 
    584580      (op != 0xFF || reg != 3) &&       /* and not CALLF MEM16          */ 
    585581      (op & 0xFFF8) != 0xD8)            // and not 8087 opcode 
    586582  { 
    587583        assert(!EOP(e));                /* can't handle this            */ 
    588584        regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 
    589585        if (sz > REGSIZE)               // value is in 2 or 4 registers 
    590586        { 
    591587                if (I16 && sz == 8)     // value is in 4 registers 
    592588                {       static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 
    593589                        rm &= rmask[offset >> 1]; 
     
    648644        cs->Iflags |= CFwait; 
    649645L2: 
    650646  cg = getregs(desmsk);                 /* save any regs we destroy     */ 
    651647 
    652648  /* KLUDGE! fix up DX for divide instructions */ 
    653649  cd = CNIL; 
    654650  if (op == 0xF7 && desmsk == (mAX|mDX))        /* if we need to fix DX */ 
    655651  {     if (reg == 7)                           /* if IDIV              */ 
    656652        {   cd = gen1(cd,0x99);                 // CWD 
    657653            if (I64 && sz == 8) 
    658654                code_orrex(cd, REX_W); 
    659655        } 
    660656        else if (reg == 6)                      // if DIV 
    661657        {   cd = genregs(cd,0x33,DX,DX);        // XOR DX,DX 
    662658            if (I64 && sz == 8) 
    663659                code_orrex(cd, REX_W); 
    664660        } 
    665661  } 
    666662 
    667663  // Eliminate MOV reg,reg 
    668   if ((cs->Iop & 0xFC) == 0x88 && 
     664  if ((cs->Iop & ~3) == 0x88 && 
    669665      (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 
    670666  { 
    671667        unsigned r = cs->Irm & 7; 
    672668        if (cs->Irex & REX_B) 
    673669            r |= 8; 
    674670        if (r == reg) 
    675671            cs->Iop = NOP; 
    676672  } 
    677673 
    678   return cat4(c,cg,cd,gen(cprefix,cs)); 
     674  return cat4(c,cg,cd,gen(NULL,cs)); 
    679675} 
    680676 
    681677/************************** 
    682678 * Get addressing mode. 
    683679 */ 
    684680 
    685681unsigned getaddrmode(regm_t idxregs) 
    686682{ 
    687683    unsigned mode; 
    688684 
    689685    if (I16) 
    690686    { 
    691687        mode =  (idxregs & mBX) ? modregrm(2,0,7) :     /* [BX] */ 
    692688                (idxregs & mDI) ? modregrm(2,0,5):      /* [DI] */ 
    693689                (idxregs & mSI) ? modregrm(2,0,4):      /* [SI] */ 
    694690                                  (assert(0),1); 
    695691    } 
    696692    else 
    697693    {   unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 
    698694        mode = modregrmx(2,0,reg); 
     
    791787  if (tyfloating(ty)) 
    792788        obj_fltused(); 
    793789  else if (I64 && sz == 8) 
    794790        pcs->Irex |= REX_W; 
    795791  if (!I16 && sz == SHORTSIZE) 
    796792        pcs->Iflags |= CFopsize; 
    797793  if (ty & mTYvolatile) 
    798794        pcs->Iflags |= CFvolatile; 
    799795  c = CNIL; 
    800796  switch (fl) 
    801797  { 
    802798#if 0 && TARGET_LINUX 
    803799    case FLgot: 
    804800    case FLgotoff: 
    805801        gotref = 1; 
    806802        pcs->IEVsym1 = s; 
    807803        pcs->IEVoffset1 = e->EV.sp.Voffset; 
    808804        if (e->Eoper == OPvar && fl == FLgot) 
    809805        { 
    810806            code *c1; 
    811             int saveop = pcs->Iop; 
     807            unsigned saveop = pcs->Iop; 
    812808            idxregs = allregs & ~keepmsk;       // get a scratch register 
    813809            c = allocreg(&idxregs,&reg,TYptr); 
    814810            pcs->Irm = modregrm(2,reg,BX);      // BX has GOT 
    815811            pcs->Isib = 0; 
    816812            //pcs->Iflags |= CFvolatile; 
    817813            pcs->Iop = 0x8B; 
    818814            c = gen(c,pcs);                     // MOV reg,disp[EBX] 
    819815            pcs->Irm = modregrm(0,0,reg); 
    820816            pcs->IEVoffset1 = 0; 
    821817            pcs->Iop = saveop; 
    822818        } 
    823819        else 
    824820        { 
    825821            pcs->Irm = modregrm(2,0,BX);        // disp[EBX] is addr 
    826822            pcs->Isib = 0; 
    827823        } 
    828824        break; 
    829825#endif 
    830826    case FLoper: 
    831827#ifdef DEBUG 
     
    17161712        else if (sz == 8) 
    17171713            code_orrex(ce, REX_W); 
    17181714    } 
    17191715    else 
    17201716        ce = gentstreg(ce,reg);                 // TEST reg,reg 
    17211717    return ce; 
    17221718  } 
    17231719  if (saveflag || tyfv(tym)) 
    17241720  { 
    17251721        scrregm = ALLREGS & ~regm;              /* possible scratch regs */ 
    17261722        ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 
    17271723        if (I32 || sz == REGSIZE * 2) 
    17281724        {   code *c; 
    17291725 
    17301726            assert(regm & mMSW && regm & mLSW); 
    17311727 
    17321728            reg = findregmsw(regm); 
    17331729            if (I32) 
    17341730            { 
    17351731                if (tyfv(tym)) 
    1736                 {   c = genregs(CNIL,0x0F,scrreg,reg); 
    1737                     c->Iop2 = 0xB7;                     /* MOVZX scrreg,msreg   */ 
     1732                {   c = genregs(CNIL,0x0FB7,scrreg,reg); // MOVZX scrreg,msreg 
    17381733                    ce = cat(ce,c); 
    17391734                } 
    17401735                else 
    17411736                {   ce = genmovreg(ce,scrreg,reg);      /* MOV scrreg,msreg     */ 
    17421737                    if (tym == TYdouble || tym == TYdouble_alias) 
    17431738                        gen2(ce,0xD1,modregrm(3,4,scrreg)); /* SHL scrreg,1     */ 
    17441739                } 
    17451740            } 
    17461741            else 
    17471742            { 
    17481743                ce = genmovreg(ce,scrreg,reg);  /* MOV scrreg,msreg     */ 
    17491744                if (tym == TYfloat) 
    17501745                    gen2(ce,0xD1,modregrm(3,4,scrreg)); /* SHL scrreg,1 */ 
    17511746            } 
    17521747            reg = findreglsw(regm); 
    17531748            genorreg(ce,scrreg,reg);                    /* OR scrreg,lsreg */ 
    17541749        } 
    17551750        else if (sz == 8) 
    17561751        {       /* !I32 */ 
    17571752                ce = genmovreg(ce,scrreg,AX);           /* MOV scrreg,AX */ 
     
    35753570                /* FALSE:       CMP SP,SP       (always equal)          */ 
    35763571                c = genregs(CNIL,(boolres(e)) ? 0x09 : 0x39,SP,SP); 
    35773572        } 
    35783573        else if (sz <= REGSIZE) 
    35793574        { 
    35803575            if (!I16 && (tym == TYfloat || tym == TYifloat)) 
    35813576            {   c = allocreg(&regm,&reg,TYoffset);      /* get a register */ 
    35823577                ce = loadea(e,&cs,0x8B,reg,0,0,0);      // MOV reg,data 
    35833578                c = cat(c,ce); 
    35843579                ce = gen2(CNIL,0xD1,modregrmx(3,4,reg)); /* SHL reg,1      */ 
    35853580                c = cat(c,ce); 
    35863581            } 
    35873582            else 
    35883583            {   cs.IFL2 = FLconst; 
    35893584                cs.IEV2.Vint = 0; 
    35903585                op = (sz == 1) ? 0x80 : 0x81; 
    35913586                c = loadea(e,&cs,op,7,0,0,0);           /* CMP EA,0     */ 
    35923587 
    35933588                // Convert to TEST instruction if EA is a register 
    35943589                // (to avoid register contention on Pentium) 
    3595                 if ((c->Iop & 0xFE) == 0x38 && 
     3590                if ((c->Iop & ~1) == 0x38 && 
    35963591                    (c->Irm & modregrm(3,0,0)) == modregrm(3,0,0) 
    35973592                   ) 
    35983593                {   c->Iop = (c->Iop & 1) | 0x84; 
    35993594                    code_newreg(c, c->Irm & 7); 
    36003595                    if (c->Irex & REX_B) 
    36013596                        c->Irex = (c->Irex & ~REX_B) | REX_R; 
    36023597                } 
    36033598            } 
    36043599        } 
    36053600        else if (sz < 8) 
    36063601        { 
    36073602            c = allocreg(&regm,&reg,TYoffset);          /* get a register */ 
    36083603            if (I32)                                    // it's a 48 bit pointer 
    36093604                ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 
    36103605            else 
    36113606            {   ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 
    36123607                if (tym == TYfloat || tym == TYifloat)  // dump sign bit 
    36133608                    gen2(ce,0xD1,modregrm(3,4,reg));    /* SHL reg,1      */ 
    36143609            } 
    36153610            c = cat(c,ce); 
  • trunk/src/backend/cod2.c

    r589 r596  
    16971697        freenode(e2); 
    16981698        c = cat6(cc,c,c2,cnop1,fixresult(e,retregs,pretregs),NULL); 
    16991699        goto Lret; 
    17001700  } 
    17011701 
    17021702  cnop1 = gennop(CNIL); 
    17031703  cnop2 = gennop(CNIL);         /* dummy target addresses       */ 
    17041704  c = logexp(e1,FALSE,FLcode,cnop1);    /* evaluate condition           */ 
    17051705  regconold = regcon; 
    17061706  stackusedold = stackused; 
    17071707  stackpushold = stackpush; 
    17081708  memcpy(_8087old,_8087elems,sizeof(_8087elems)); 
    17091709  c1 = codelem(e21,pretregs,FALSE); 
    17101710 
    17111711#if SCPP 
    17121712  if (CPP && e2->Eoper == OPcolon2) 
    17131713  {     code cs; 
    17141714 
    17151715        // This is necessary so that any cleanup code on one branch 
    17161716        // is redone on the other branch. 
    1717         cs.Iop = ESCAPE; 
    1718         cs.Iop2 = ESCmark2; 
     1717        cs.Iop = ESCAPE | ESCmark2; 
    17191718        cs.Iflags = 0; 
    17201719        cs.Irex = 0; 
    17211720        c1 = cat(gen(CNIL,&cs),c1); 
    1722         cs.Iop2 = ESCrelease2; 
     1721        cs.Iop = ESCAPE | ESCrelease2; 
    17231722        c1 = gen(c1,&cs); 
    17241723  } 
    17251724#endif 
    17261725 
    17271726  regconsave = regcon; 
    17281727  regcon = regconold; 
    17291728 
    17301729  stackpushsave = stackpush; 
    17311730  stackpush = stackpushold; 
    17321731 
    17331732  stackusedsave = stackused; 
    17341733  stackused = stackusedold; 
    17351734 
    17361735  memcpy(_8087save,_8087elems,sizeof(_8087elems)); 
    17371736  memcpy(_8087elems,_8087old,sizeof(_8087elems)); 
    17381737 
    17391738  *pretregs |= psw;                     /* PSW bit may have been trashed */ 
    17401739  c2 = codelem(e22,pretregs,FALSE); /* use same regs as E1 */ 
    17411740  andregcon(&regconold); 
    17421741  andregcon(&regconsave); 
     
    24122411  { 
    24132412        if (!I16 && tym == TYfloat) 
    24142413        {       retregs = ALLREGS & ~idxregs; 
    24152414                c = cat(c,allocreg(&retregs,&reg,TYfloat)); 
    24162415                cs.Iop = 0x8B; 
    24172416                code_newreg(&cs,reg); 
    24182417                ce = gen(CNIL,&cs);                     // MOV reg,lsw 
    24192418                gen2(ce,0xD1,modregrmx(3,4,reg));       // SHL reg,1 
    24202419        } 
    24212420        else if (sz <= REGSIZE) 
    24222421        { 
    24232422                cs.Iop = 0x81 ^ byte; 
    24242423                cs.Irm |= modregrm(0,7,0); 
    24252424                cs.IFL2 = FLconst; 
    24262425                cs.IEV2.Vint = 0; 
    24272426                ce = gen(CNIL,&cs);             /* CMP [idx],0          */ 
    24282427        } 
    24292428        else if (!I16 && sz == REGSIZE + 2)      // if far pointer 
    24302429        {       retregs = ALLREGS & ~idxregs; 
    24312430                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    2432                 cs.Iop = 0x0F; 
    2433                 cs.Iop2 = 0xB7; 
     2431                cs.Iop = 0x0FB7; 
    24342432                cs.Irm |= modregrm(0,reg,0); 
    24352433                getlvalue_msw(&cs); 
    24362434                ce = gen(CNIL,&cs);             /* MOVZX reg,msw        */ 
    24372435                goto L4; 
    24382436        } 
    24392437        else if (sz <= 2 * REGSIZE) 
    24402438        {       retregs = ALLREGS & ~idxregs; 
    24412439                c = cat(c,allocreg(&retregs,&reg,TYint)); 
    24422440                cs.Iop = 0x8B; 
    24432441                cs.Irm |= modregrm(0,reg,0); 
    24442442                getlvalue_msw(&cs); 
    24452443                ce = gen(CNIL,&cs);             /* MOV reg,msw          */ 
    24462444                if (I32) 
    24472445                {   if (tym == TYdouble || tym == TYdouble_alias) 
    24482446                        gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 
    24492447                } 
    24502448                else if (tym == TYfloat) 
    24512449                    gen2(ce,0xD1,modregrm(3,4,reg));    /* SHL reg,1    */ 
    24522450        L4:     cs.Iop = 0x0B; 
    24532451                getlvalue_lsw(&cs); 
     
    45144512            if (0 && config.exe == EX_NT) 
    45154513            {   unsigned idx; 
    45164514 
    45174515                idx = except_index_get(); 
    45184516                except_mark(); 
    45194517                c = codelem(e->E2,pretregs,FALSE); 
    45204518                if (config.exe == EX_NT && idx != except_index_get()) 
    45214519                {   usednteh |= NTEHcleanup; 
    45224520                    c = cat(c,nteh_gensindex(idx - 1)); 
    45234521                } 
    45244522                except_release(); 
    45254523                assert(idx == except_index_get()); 
    45264524            } 
    45274525            else 
    45284526            { 
    45294527#if 0 
    45304528                usednteh |= EHcleanup; 
    45314529                if (config.exe == EX_NT) 
    45324530                    usednteh |= NTEHcleanup; 
    45334531#endif 
    4534                 cs.Iop = ESCAPE; 
    4535                 cs.Iop2 = ESCmark; 
     4532                cs.Iop = ESCAPE | ESCmark; 
    45364533                cs.Iflags = 0; 
    45374534                cs.Irex = 0; 
    45384535                c = gen(CNIL,&cs); 
    45394536                c = cat(c,codelem(e->E2,pretregs,FALSE)); 
    4540                 cs.Iop2 = ESCrelease; 
     4537                cs.Iop = ESCAPE | ESCrelease; 
    45414538                gen(c,&cs); 
    45424539            } 
    45434540            freenode(e->E1); 
    45444541            break; 
    45454542        default: 
    45464543            assert(0); 
    45474544    } 
    45484545    return c; 
    45494546#else 
    45504547    return NULL; 
    45514548#endif 
    45524549} 
    45534550 
    45544551code *cdctor(elem *e,regm_t *pretregs) 
    45554552{ 
    45564553#if SCPP 
    45574554    code cs; 
    45584555    code *c; 
    45594556 
    45604557#if 0 
    45614558    if (config.exe == EX_NT) 
    45624559    {   usednteh |= NTEHcleanup; 
    45634560        except_push(NULL,e,NULL); 
    45644561        return nteh_gensindex(except_index_get() - 1); 
    45654562    } 
    45664563#else 
    45674564    usednteh |= EHcleanup; 
    45684565    if (config.exe == EX_NT) 
    45694566        usednteh |= NTEHcleanup; 
    45704567#endif 
    45714568    assert(*pretregs == 0); 
    4572     cs.Iop = ESCAPE; 
    4573     cs.Iop2 = ESCctor; 
     4569    cs.Iop = ESCAPE | ESCctor; 
    45744570    cs.Iflags = 0; 
    45754571    cs.Irex = 0; 
    45764572    cs.IFL1 = FLctor; 
    45774573    cs.IEV1.Vtor = e; 
    45784574    c = gen(CNIL,&cs); 
    45794575    //except_push(c,e,NULL); 
    45804576    return c; 
    45814577#else 
    45824578    return NULL; 
    45834579#endif 
    45844580} 
    45854581 
    45864582code *cddtor(elem *e,regm_t *pretregs) 
    45874583{ 
    45884584#if SCPP 
    45894585    code cs; 
    45904586    code *c; 
    45914587 
    45924588#if 0 
    45934589    if (config.exe == EX_NT) 
    45944590    {   usednteh |= NTEHcleanup; 
    45954591        except_pop(NULL,e,NULL); 
    45964592        return nteh_gensindex(except_index_get() - 1); 
    45974593    } 
    45984594#else 
    45994595    usednteh |= EHcleanup; 
    46004596    if (config.exe == EX_NT) 
    46014597        usednteh |= NTEHcleanup; 
    46024598#endif 
    46034599    assert(*pretregs == 0); 
    4604     cs.Iop = ESCAPE; 
    4605     cs.Iop2 = ESCdtor; 
     4600    cs.Iop = ESCAPE | ESCdtor; 
    46064601    cs.Iflags = 0; 
    46074602    cs.Irex = 0; 
    46084603    cs.IFL1 = FLdtor; 
    46094604    cs.IEV1.Vtor = e; 
    46104605    c = gen(CNIL,&cs); 
    46114606    //except_pop(c,e,NULL); 
    46124607    return c; 
    46134608#else 
    46144609    return NULL; 
    46154610#endif 
    46164611} 
    46174612 
    46184613code *cdmark(elem *e,regm_t *pretregs) 
    46194614{ 
    46204615    return NULL; 
    46214616} 
    46224617 
    46234618#if !NTEXCEPTIONS 
    46244619code *cdsetjmp(elem *e,regm_t *pretregs) 
    46254620{ 
  • trunk/src/backend/cod3.c

    r595 r596  
    201201        2,2,2,M|3,      M|T|E|4,M|3,M|3,M|3,    // A8 
    202202        M|E|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,     // B0 
    203203        2,2,M|T|E|4,M|3, M|3,M|3,M|3,M|3,       // B8 
    204204        M|3,M|3,M|T|E|4,M|3, M|T|E|4,M|T|E|4,M|T|E|4,M|3,       // C0 
    205205        2,2,2,2,        2,2,2,2,                // C8 
    206206        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // D0 
    207207        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // D8 
    208208        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // E0 
    209209        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // E8 
    210210        M|3,M|3,M|3,M|3, M|3,M|3,M|3,M|3,       // F0 
    211211        M|3,M|3,M|3,M|3, M|3,M|3,M|3,2          // F8 
    212212}; 
    213213 
    214214/************************************ 
    215215 * Determine if there is a modregrm byte for code. 
    216216 */ 
    217217 
    218218int cod3_EA(code *c) 
    219219{   unsigned ins; 
    220220 
    221     switch (c->Iop) 
    222     {   case ESCAPE: 
    223             ins = 0; 
    224             break; 
    225         case 0x0F: 
    226             ins = inssize2[c->Iop2]; 
    227             break; 
    228         default: 
    229             ins = inssize[c->Iop]; 
    230             break; 
    231     } 
     221    unsigned op1 = c->Iop & 0xFF; 
     222    if (op1 == ESCAPE) 
     223        ins = 0; 
     224    else if ((c->Iop & 0xFF00) == 0x0F00) 
     225        ins = inssize2[op1]; 
     226    else 
     227        ins = inssize[op1]; 
    232228    return ins & M; 
    233229} 
    234230 
    235231/******************************** 
    236232 * Fix global variables for 386. 
    237233 */ 
    238234 
    239235void cod3_set386() 
    240236{ 
    241237//    if (I32) 
    242238    {   unsigned i; 
    243239 
    244240        inssize[0xA0] = T|5; 
    245241        inssize[0xA1] = T|5; 
    246242        inssize[0xA2] = T|5; 
    247243        inssize[0xA3] = T|5; 
    248244        BPRM = 5;                       /* [EBP] addressing mode        */ 
    249245        fregsaved = mBP | mBX | mSI | mDI;      // saved across function calls 
    250246        FLOATREGS = FLOATREGS_32; 
    251247        FLOATREGS2 = FLOATREGS2_32; 
     
    10541050    return mBP; 
    10551051 
    10561052Lcant: 
    10571053    return 0; 
    10581054} 
    10591055 
    10601056/*************************************** 
    10611057 * Gen code for OPframeptr 
    10621058 */ 
    10631059 
    10641060code *cdframeptr(elem *e, regm_t *pretregs) 
    10651061{ 
    10661062    unsigned reg; 
    10671063    code cs; 
    10681064 
    10691065    regm_t retregs = *pretregs & allregs; 
    10701066    if  (!retregs) 
    10711067        retregs = allregs; 
    10721068    code *cg = allocreg(&retregs, &reg, TYint); 
    10731069 
    1074     cs.Iop = ESCAPE; 
    1075     cs.Iop2 = ESCframeptr; 
     1070    cs.Iop = ESCAPE | ESCframeptr; 
    10761071    cs.Iflags = 0; 
    10771072    cs.Irex = 0; 
    10781073    cs.Irm = reg; 
    10791074    cg = gen(cg,&cs); 
    10801075 
    10811076    return cat(cg,fixresult(e,retregs,pretregs)); 
    10821077} 
    10831078 
    10841079/*************************************** 
    10851080 * Gen code for load of _GLOBAL_OFFSET_TABLE_. 
    10861081 * This value gets cached in the local variable 'localgot'. 
    10871082 */ 
    10881083 
    10891084code *cdgot(elem *e, regm_t *pretregs) 
    10901085{ 
    10911086#if TARGET_OSX 
    10921087    regm_t retregs; 
    10931088    unsigned reg; 
    10941089    code *c; 
    10951090 
     
    23032298 
    23042299int branch(block *bl,int flag) 
    23052300{ int bytesaved; 
    23062301  code *c,*cn,*ct; 
    23072302  targ_size_t offset,disp; 
    23082303  targ_size_t csize; 
    23092304 
    23102305  if (!flag) 
    23112306      bl->Bflags |= BFLjmpoptdone;      // assume this will be all 
    23122307  c = bl->Bcode; 
    23132308  if (!c) 
    23142309        return 0; 
    23152310  bytesaved = 0; 
    23162311  offset = bl->Boffset;                 /* offset of start of block     */ 
    23172312  while (1) 
    23182313  {     unsigned char op; 
    23192314 
    23202315        csize = calccodsize(c); 
    23212316        cn = code_next(c); 
    23222317        op = c->Iop; 
    2323         if ((op & 0xF0) == 0x70 && c->Iflags & CFjmp16 || 
     2318        if ((op & ~0x0F) == 0x70 && c->Iflags & CFjmp16 || 
    23242319            op == JMP) 
    23252320        { 
    23262321          L1: 
    23272322            switch (c->IFL2) 
    23282323            { 
    23292324                case FLblock: 
    23302325                    if (flag)           // no offsets yet, don't optimize 
    23312326                        goto L3; 
    23322327                    disp = c->IEV2.Vblock->Boffset - offset - csize; 
    23332328 
    23342329                    /* If this is a forward branch, and there is an aligned 
    23352330                     * block intervening, it is possible that shrinking 
    23362331                     * the jump instruction will cause it to be out of 
    23372332                     * range of the target. This happens if the alignment 
    23382333                     * prevents the target block from moving correspondingly 
    23392334                     * closer. 
    23402335                     */ 
    23412336                    if (disp >= 0x7F-4 && c->IEV2.Vblock->Boffset > offset) 
    23422337                    {   /* Look for intervening alignment 
    23432338                         */ 
     
    23712366 
    23722367                    if (!cr) 
    23732368                    {   // Didn't find it in forward search. Try backwards jump 
    23742369                        int s = 0; 
    23752370                        disp = 0; 
    23762371                        for (cr = bl->Bcode; cr != cn; cr = code_next(cr)) 
    23772372                        { 
    23782373                            assert(cr != NULL); // must have found it 
    23792374                            if (cr == ct) 
    23802375                                s = 1; 
    23812376                            if (s) 
    23822377                                disp += calccodsize(cr); 
    23832378                        } 
    23842379                    } 
    23852380 
    23862381                    if (config.flags4 & CFG4optimized && !flag) 
    23872382                    { 
    23882383                        /* Propagate branch forward past junk   */ 
    23892384                        while (1) 
    23902385                        {   if (ct->Iop == NOP || 
    2391                                 (ct->Iop == ESCAPE && ct->Iop2 == ESClinnum)) 
     2386                                ct->Iop == (ESCAPE | ESClinnum)) 
    23922387                            {   ct = code_next(ct); 
    23932388                                if (!ct) 
    23942389                                    goto L2; 
    23952390                            } 
    23962391                            else 
    23972392                            {   c->IEV2.Vcode = ct; 
    23982393                                ct->Iflags |= CFtarg; 
    23992394                                break; 
    24002395                            } 
    24012396                        } 
    24022397 
    24032398                        /* And eliminate jmps to jmps   */ 
    24042399                        if ((op == ct->Iop || ct->Iop == JMP) && 
    24052400                            (op == JMP || c->Iflags & CFjmp16)) 
    24062401                        {   c->IFL2 = ct->IFL2; 
    24072402                            c->IEV2.Vcode = ct->IEV2.Vcode; 
    24082403                            /*printf("eliminating branch\n");*/ 
    24092404                            goto L1; 
    24102405                        } 
    24112406                     L2: ; 
     
    24322427                if (op == JMP) 
    24332428                {   c->Iop = JMPS;              // JMP SHORT 
    24342429                    bytesaved += I16 ? 1 : 3; 
    24352430                } 
    24362431                else                            // else Jcond 
    24372432                {   c->Iflags &= ~CFjmp16;      // a branch is ok 
    24382433                    bytesaved += I16 ? 3 : 4; 
    24392434 
    24402435                    // Replace a cond jump around a call to a function that 
    24412436                    // never returns with a cond jump to that function. 
    24422437                    if (config.flags4 & CFG4optimized && 
    24432438                        config.target_cpu >= TARGET_80386 && 
    24442439                        disp == (I16 ? 3 : 5) && 
    24452440                        cn && 
    24462441                        cn->Iop == 0xE8 && 
    24472442                        cn->IFL2 == FLfunc && 
    24482443                        cn->IEVsym2->Sflags & SFLexit && 
    24492444                        !(cn->Iflags & (CFtarg | CFtarg2)) 
    24502445                       ) 
    24512446                    { 
    2452                         cn->Iop = 0x0F; 
    2453                         cn->Iop2 = (c->Iop & 0x0F) ^ 0x81; 
     2447                        cn->Iop = 0x0F00 | ((c->Iop & 0x0F) ^ 0x81); 
    24542448                        c->Iop = NOP; 
    24552449                        c->IEV2.Vcode = NULL; 
    24562450                        bytesaved++; 
    24572451 
    24582452                        // If nobody else points to ct, we can remove the CFtarg 
    24592453                        if (flag && ct) 
    24602454                        {   code *cx; 
    24612455 
    24622456                            for (cx = bl->Bcode; 1; cx = code_next(cx)) 
    24632457                            { 
    24642458                                if (!cx) 
    24652459                                {   ct->Iflags &= ~CFtarg; 
    24662460                                    break; 
    24672461                                } 
    24682462                                if (cx->IEV2.Vcode == ct) 
    24692463                                    break; 
    24702464                            } 
    24712465                        } 
    24722466                    } 
    24732467                } 
     
    25602554 
    25612555void assignaddrc(code *c) 
    25622556{ 
    25632557    int sn; 
    25642558    symbol *s; 
    25652559    unsigned char ins,rm; 
    25662560    targ_size_t soff; 
    25672561    targ_size_t base; 
    25682562 
    25692563    base = EBPtoESP; 
    25702564    for (; c; c = code_next(c)) 
    25712565    { 
    25722566#ifdef DEBUG 
    25732567        if (0) 
    25742568        {       printf("assignaddrc()\n"); 
    25752569                c->print(); 
    25762570        } 
    25772571        if (code_next(c) && code_next(code_next(c)) == c) 
    25782572            assert(0); 
    25792573#endif 
    2580         if (c->Iop == 0x0F
    2581             ins = inssize2[c->Iop2]; 
    2582         else if (c->Iop == ESCAPE) 
    2583         { 
    2584             if (c->Iop2 == ESCadjesp
     2574        if ((c->Iop & 0xFF00) == 0x0F00
     2575            ins = inssize2[c->Iop & 0xFF]; 
     2576        else if ((c->Iop & 0xFF) == ESCAPE) 
     2577        { 
     2578            if (c->Iop == (ESCAPE | ESCadjesp)
    25852579            { 
    25862580                //printf("adjusting EBPtoESP (%d) by %ld\n",EBPtoESP,c->IEV2.Vint); 
    25872581                EBPtoESP += c->IEV2.Vint; 
    25882582                c->Iop = NOP; 
    25892583            } 
    2590             if (c->Iop2 == ESCframeptr
     2584            if (c->Iop == (ESCAPE | ESCframeptr)
    25912585            {   // Convert to load of frame pointer 
    25922586                // c->Irm is the register to use 
    25932587                if (hasframe) 
    25942588                {   // MOV reg,EBP 
    25952589                    c->Iop = 0x89; 
    25962590                    if (c->Irm & 8) 
    25972591                        c->Irex |= REX_B; 
    25982592                    c->Irm = modregrm(3,BP,c->Irm & 7); 
    25992593                } 
    26002594                else 
    26012595                {   // LEA reg,EBPtoESP[ESP] 
    26022596                    c->Iop = 0x8D; 
    26032597                    if (c->Irm & 8) 
    26042598                        c->Irex |= REX_R; 
    26052599                    c->Irm = modregrm(2,c->Irm & 7,4); 
    26062600                    c->Isib = modregrm(0,4,SP); 
    26072601                    c->Iflags = CFoff; 
    26082602                    c->IFL1 = FLconst; 
    26092603                    c->IEV1.Vuns = EBPtoESP; 
    26102604                } 
    26112605            } 
    26122606            if (I64) 
    26132607                c->Irex |= REX_W; 
    26142608            continue; 
    26152609        } 
    26162610        else 
    2617             ins = inssize[c->Iop]; 
     2611            ins = inssize[c->Iop & 0xFF]; 
    26182612        if (!(ins & M) || 
    26192613            ((rm = c->Irm) & 0xC0) == 0xC0) 
    26202614            goto do2;           /* if no first operand          */ 
    26212615        if (is32bitaddr(I32,c->Iflags)) 
    26222616        { 
    26232617 
    26242618            if ( 
    26252619                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    26262620               ) 
    26272621                goto do2;       /* if no first operand  */ 
    26282622        } 
    26292623        else 
    26302624        { 
    26312625            if ( 
    26322626                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
    26332627               ) 
    26342628                goto do2;       /* if no first operand  */ 
    26352629        } 
    26362630        s = c->IEVsym1; 
    26372631        switch (c->IFL1) 
     
    29432937  if (debugc) 
    29442938  { 
    29452939      printf("+pinholeopt(%p)\n",c); 
    29462940  } 
    29472941#endif 
    29482942 
    29492943  if (b) 
    29502944  {     bn = b->Bnext; 
    29512945        usespace = (config.flags4 & CFG4space && b->BC != BCasm); 
    29522946        useopsize = (I16 || (config.flags4 & CFG4space && b->BC != BCasm)); 
    29532947  } 
    29542948  else 
    29552949  {     bn = NULL; 
    29562950        usespace = (config.flags4 & CFG4space); 
    29572951        useopsize = (I16 || config.flags4 & CFG4space); 
    29582952  } 
    29592953  for (; c; c = code_next(c)) 
    29602954  { 
    29612955    L1: 
    29622956        op = c->Iop; 
    2963         if (op == 0x0F
    2964             ins = inssize2[c->Iop2]; 
     2957        if ((op & 0xFF00) == 0x0F00
     2958            ins = inssize2[op & 0xFF]; 
    29652959        else 
    2966             ins = inssize[c->Iop]; 
     2960            ins = inssize[op & 0xFF]; 
    29672961        if (ins & M)            // if modregrm byte 
    29682962        {   int shortop = (c->Iflags & CFopsize) ? !I16 : I16; 
    29692963            int local_BPRM = BPRM; 
    29702964 
    29712965            if (c->Iflags & CFaddrsize) 
    29722966                local_BPRM ^= 5 ^ 6;    // toggle between 5 and 6 
    29732967 
    29742968            unsigned rm = c->Irm; 
    29752969            unsigned reg = rm & modregrm(0,7,0);          // isolate reg field 
    29762970            unsigned ereg = rm & 7; 
    29772971            //printf("c = %p, op = %02x rm = %02x\n", c, op, rm); 
    29782972 
    29792973            /* If immediate second operand      */ 
    29802974            if ((ins & T || op == 0xF6 || op == 0xF7) && 
    29812975                c->IFL2 == FLconst) 
    29822976            { 
    29832977                int flags = c->Iflags & CFpsw;      /* if want result in flags */ 
    29842978                targ_long u = c->IEV2.Vuns; 
    29852979                if (ins & E) 
    29862980                    u = (signed char) u; 
     
    30373031                                    if ((u & 0xFF) == 0xFF) 
    30383032                                        goto L3; 
    30393033                                } 
    30403034                            } 
    30413035                        } 
    30423036                        if (!shortop && useopsize) 
    30433037                        { 
    30443038                            if ((u & 0xFFFF0000) == 0xFFFF0000) 
    30453039                            {   c->Iflags ^= CFopsize; 
    30463040                                goto L1; 
    30473041                            } 
    30483042                            if ((u & 0xFFFF) == 0xFFFF && rm < modregrm(3,4,AX)) 
    30493043                            {   c->IEVoffset1 += 2; /* address MSW      */ 
    30503044                                c->IEV2.Vuns >>= 16; 
    30513045                                c->Iflags ^= CFopsize; 
    30523046                                goto L1; 
    30533047                            } 
    30543048                            if (rm >= modregrm(3,4,AX)) 
    30553049                            { 
    30563050                                if (u == 0xFF && (rm <= modregrm(3,4,BX) || I64)) 
    3057                                 {   c->Iop2 = 0xB6;     /* MOVZX        */ 
    3058                                     c->Iop = 0x0F; 
     3051                                {   c->Iop = 0x0FB6;     // MOVZX 
    30593052                                    c->Irm = modregrm(3,ereg,ereg); 
    30603053                                    if (c->Irex & REX_B) 
    30613054                                        c->Irex |= REX_R; 
    30623055                                    goto L1; 
    30633056                                } 
    30643057                                if (u == 0xFFFF) 
    3065                                 {   c->Iop2 = 0xB7;     /* MOVZX        */ 
    3066                                     c->Iop = 0x0F; 
     3058                                {   c->Iop = 0x0FB7;     // MOVZX 
    30673059                                    c->Irm = modregrm(3,ereg,ereg); 
    30683060                                    if (c->Irex & REX_B) 
    30693061                                        c->Irex |= REX_R; 
    30703062                                    goto L1; 
    30713063                                } 
    30723064                            } 
    30733065                        } 
    30743066                    } 
    30753067                } 
    30763068 
    30773069                /* Look for ADD,OR,SUB,XOR with u that we can eliminate */ 
    30783070                if (!flags && 
    30793071                    (op == 0x81 || op == 0x80) && 
    30803072                    (reg == modregrm(0,0,0) || reg == modregrm(0,1,0) ||  // ADD,OR 
    30813073                     reg == modregrm(0,5,0) || reg == modregrm(0,6,0))    // SUB, XOR 
    30823074                   ) 
    30833075                { 
    30843076                        if (u == 0) 
    30853077                        { 
    30863078                                c->Iop = NOP; 
     
    32463238            if ((ins & R) && (rm & 0xC0) == 0xC0) 
    32473239            {   switch (op) 
    32483240                {   case 0xC6:  op = 0xB0 + ereg; break; 
    32493241                    case 0xC7:  op = 0xB8 + ereg; break; 
    32503242                    case 0xFF: 
    32513243                        switch (reg) 
    32523244                        {   case 6<<3: op = 0x50+ereg; break;/* PUSH*/ 
    32533245                            case 0<<3: if (!I64) op = 0x40+ereg; break; /* INC*/ 
    32543246                            case 1<<3: if (!I64) op = 0x48+ereg; break; /* DEC*/ 
    32553247                        } 
    32563248                        break; 
    32573249                    case 0x8F:  op = 0x58 + ereg; break; 
    32583250                    case 0x87: 
    32593251                        if (reg == 0) op = 0x90 + ereg; 
    32603252                        break; 
    32613253                } 
    32623254                c->Iop = op; 
    32633255            } 
    32643256 
    32653257            // Look to replace SHL reg,1 with ADD reg,reg 
    3266             if ((op & 0xFE) == 0xD0 && 
     3258            if ((op & ~1) == 0xD0 && 
    32673259                     (rm & modregrm(3,7,0)) == modregrm(3,4,0) && 
    32683260                     config.target_cpu >= TARGET_80486) 
    32693261            { 
    32703262                c->Iop &= 1; 
    32713263                c->Irm = (rm & modregrm(3,0,7)) | (ereg << 3); 
    32723264                if (c->Irex & REX_B) 
    32733265                    c->Irex |= REX_R; 
    32743266                if (!(c->Iflags & CFpsw) && !I16) 
    32753267                    c->Iflags &= ~CFopsize; 
    32763268                goto L1; 
    32773269            } 
    32783270 
    32793271            /* Look for sign extended modregrm displacement, or 0 
    32803272             * displacement. 
    32813273             */ 
    32823274 
    32833275            if (((rm & 0xC0) == 0x80) && // it's a 16/32 bit disp 
    32843276                c->IFL1 == FLconst)      // and it's a constant 
    32853277            { 
    32863278                a = c->IEVpointer1; 
     
    33343326                else if (mod == modregrm(1,0,0) && rm == local_BPRM && 
    33353327                        c->IFL1 == FLconst && c->IEVpointer1 == 0) 
    33363328                {       c->Iop = 0x8B;          /* MOV reg,BP   */ 
    33373329                        c->Irm = modregrm(3,0,BP) + reg; 
    33383330                } 
    33393331            } 
    33403332 
    33413333            // Replace [R13] with 0[R13] 
    33423334            if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 
    33433335            { 
    33443336                c->Irm |= modregrm(1,0,0); 
    33453337                c->IFL1 = FLconst; 
    33463338                c->IEVpointer1 = 0; 
    33473339            } 
    33483340        } 
    33493341        else 
    33503342        { 
    33513343            switch (op) 
    33523344            { 
    33533345                default: 
    3354                     if ((op & 0xF0) != 0x70) 
     3346                    if ((op & ~0x0F) != 0x70) 
    33553347                        break; 
    33563348                case JMP: 
    33573349                    switch (c->IFL2) 
    33583350                    {   case FLcode: 
    33593351                                if (c->IEV2.Vcode == code_next(c)) 
    33603352                                {       c->Iop = NOP; 
    33613353                                        continue; 
    33623354                                } 
    33633355                                break; 
    33643356                        case FLblock: 
    33653357                                if (!code_next(c) && c->IEV2.Vblock == bn) 
    33663358                                {       c->Iop = NOP; 
    33673359                                        continue; 
    33683360                                } 
    33693361                                break; 
    33703362                        case FLconst: 
    33713363                        case FLfunc: 
    33723364                        case FLextern: 
    33733365                                break; 
    33743366                        default: 
     
    34793471} 
    34803472#endif 
    34813473 
    34823474/************************** 
    34833475 * Compute jump addresses for FLcode. 
    34843476 * Note: only works for forward referenced code. 
    34853477 *       only direct jumps and branches are detected. 
    34863478 *       LOOP instructions only work for backward refs. 
    34873479 */ 
    34883480 
    34893481void jmpaddr(code *c) 
    34903482{ code *ci,*cn,*ctarg,*cstart; 
    34913483  targ_size_t ad; 
    34923484  unsigned char op; 
    34933485 
    34943486  //printf("jmpaddr()\n"); 
    34953487  cstart = c;                           /* remember start of code       */ 
    34963488  while (c) 
    34973489  { 
    34983490        op = c->Iop; 
    3499         if (inssize[op] & T &&          /* if second operand            */ 
     3491        if (inssize[op & 0xFF] & T &&   // if second operand 
    35003492            c->IFL2 == FLcode && 
    3501             ((op & 0xF0) == 0x70 || op == JMP || op == JMPS || op == JCXZ)) 
     3493            ((op & ~0x0F) == 0x70 || op == JMP || op == JMPS || op == JCXZ)) 
    35023494        {       ci = code_next(c); 
    35033495                ctarg = c->IEV2.Vcode;  /* target code                  */ 
    35043496                ad = 0;                 /* IP displacement              */ 
    35053497                while (ci && ci != ctarg) 
    35063498                { 
    35073499                        ad += calccodsize(ci); 
    35083500                        ci = code_next(ci); 
    35093501                } 
    35103502                if (!ci) 
    35113503                    goto Lbackjmp;      // couldn't find it 
    35123504                if (I32 || op == JMP || op == JMPS || op == JCXZ) 
    35133505                        c->IEVpointer2 = ad; 
    35143506                else                    /* else conditional             */ 
    35153507                {       if (!(c->Iflags & CFjmp16))     /* if branch    */ 
    35163508                                c->IEVpointer2 = ad; 
    35173509                        else            /* branch around a long jump    */ 
    35183510                        {       cn = code_next(c); 
    35193511                                code_next(c) = code_calloc(); 
    35203512                                code_next(code_next(c)) = cn; 
    35213513                                c->Iop = op ^ 1;        /* converse jmp */ 
     
    35663558/***************************** 
    35673559 * Calculate and return code size of a code. 
    35683560 * Note that NOPs are sometimes used as markers, but are 
    35693561 * never output. LINNUMs are never output. 
    35703562 * Note: This routine must be fast. Profiling shows it is significant. 
    35713563 */ 
    35723564 
    35733565unsigned calccodsize(code *c) 
    35743566{   unsigned size; 
    35753567    unsigned op; 
    35763568    unsigned char rm,mod,ins; 
    35773569    unsigned iflags; 
    35783570    unsigned i32 = I32 || I64; 
    35793571    unsigned a32 = i32; 
    35803572 
    35813573#ifdef DEBUG 
    35823574    assert((a32 & ~1) == 0); 
    35833575#endif 
    35843576    iflags = c->Iflags; 
    35853577    op = c->Iop; 
     3578    if ((op & 0xFF00) == 0x0F00) 
     3579        op = 0x0F; 
     3580    else 
     3581        op &= 0xFF; 
    35863582    switch (op) 
    35873583    { 
    35883584        case 0x0F: 
    3589             ins = inssize2[c->Iop2]; 
     3585            ins = inssize2[c->Iop & 0xFF]; 
    35903586            size = ins & 7; 
     3587            if (c->Iop & 0xFF0000) 
     3588                size++; 
    35913589            break; 
    35923590 
    35933591        case NOP: 
    35943592        case ESCAPE: 
    35953593            size = 0;                   // since these won't be output 
    35963594            goto Lret2; 
    35973595 
    35983596        case ASM: 
    35993597            if (c->Iflags == CFaddrsize)        // kludge for DA inline asm 
    36003598                size = NPTRSIZE; 
    36013599            else 
    36023600                size = c->IEV1.as.len; 
    36033601            goto Lret2; 
    36043602 
    36053603        case 0xA1: 
    36063604        case 0xA3: 
    36073605            if (c->Irex) 
    36083606            { 
    36093607                size = 9;               // 64 bit immediate value for MOV to/from RAX 
    36103608                goto Lret; 
     
    36633661                            size += 2; 
    36643662                    } 
    36653663                } 
    36663664                else if (iflags & CFopsize) 
    36673665                {   if (I32) 
    36683666                        size -= 2; 
    36693667                    else 
    36703668                        size += 2; 
    36713669                } 
    36723670            } 
    36733671            if (iflags & CFaddrsize) 
    36743672            {   if (!I64) 
    36753673                    a32 ^= 1; 
    36763674                size++; 
    36773675            } 
    36783676            if (iflags & CFopsize) 
    36793677                size++;                         /* +1 for OPSIZE prefix         */ 
    36803678        } 
    36813679    } 
    36823680 
    3683     if ((op & 0xF0) == 0x70) 
     3681    if ((op & ~0x0F) == 0x70) 
    36843682    {   if (iflags & CFjmp16)           // if long branch 
    36853683            size += I16 ? 3 : 4;        // + 3(4) bytes for JMP 
    36863684    } 
    36873685    else if (ins & M)                   // if modregrm byte 
    36883686    { 
    36893687        rm = c->Irm; 
    36903688        mod = rm & 0xC0; 
    36913689        if (a32 || I64) 
    36923690        {   // 32 bit addressing 
    36933691            if (issib(rm)) 
    36943692                size++; 
    36953693            switch (mod) 
    36963694            {   case 0: 
    36973695                    if (issib(rm) && (c->Isib & 7) == 5 || 
    36983696                        (rm & 7) == 5) 
    36993697                        size += 4;      /* disp32                       */ 
    37003698                    if (c->Irex & REX_B && (rm & 7) == 5) 
    37013699                        /* Instead of selecting R13, this mode is an [RIP] relative 
    37023700                         * address. Although valid, it's redundant, and should not 
    37033701                         * be generated. Instead, generate 0[R13] instead of [R13]. 
     
    37073705                case 0x40: 
    37083706                    size++;             /* disp8                        */ 
    37093707                    break; 
    37103708                case 0x80: 
    37113709                    size += 4;          /* disp32                       */ 
    37123710                    break; 
    37133711            } 
    37143712        } 
    37153713        else 
    37163714        {   // 16 bit addressing 
    37173715            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    37183716                size++; 
    37193717            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    37203718                size += 2; 
    37213719        } 
    37223720    } 
    37233721 
    37243722Lret: 
    37253723    if (c->Irex) 
    37263724    {   size++; 
    3727         if (c->Irex & REX_W && (op & 0xF8) == 0xB8) 
     3725        if (c->Irex & REX_W && (op & ~7) == 0xB8) 
    37283726            size += 4; 
    37293727    } 
    37303728Lret2: 
    37313729    //printf("op = x%02x, size = %d\n",op,size); 
    37323730    return size; 
    37333731} 
    37343732 
    37353733/******************************** 
    37363734 * Return !=0 if codes match. 
    37373735 */ 
    37383736 
    37393737#if 0 
    37403738 
    37413739int code_match(code *c1,code *c2) 
    37423740{   code cs1,cs2; 
    37433741    unsigned char ins; 
    37443742 
    37453743    if (c1 == c2) 
    37463744        goto match; 
    37473745    cs1 = *c1; 
    37483746    cs2 = *c2; 
    37493747    if (cs1.Iop != cs2.Iop) 
    37503748        goto nomatch; 
    37513749    switch (cs1.Iop) 
    3752     {   case ESCAPE: 
    3753             switch (c->Iop2) 
    3754             { 
    3755                 case ESCctor: 
    3756                     goto nomatch; 
    3757                 case ESCdtor: 
    3758                     goto nomatch; 
    3759             } 
    3760             goto match; 
     3750    { 
     3751        case ESCAPE | ESCctor: 
     3752        case ESCAPE | ESCdtor: 
     3753            goto nomatch; 
     3754 
    37613755        case NOP: 
    37623756            goto match; 
    37633757        case ASM: 
    37643758            if (cs1.IEV1.as.len == cs2.IEV1.as.len && 
    37653759                memcmp(cs1.IEV1.as.bytes,cs2.IEV1.as.bytes,cs1.EV1.as.len) == 0) 
    37663760                goto match; 
    37673761            else 
    37683762                goto nomatch; 
     3764 
     3765        default: 
     3766            if ((cs1.Iop & 0xFF) == ESCAPE) 
     3767                goto match; 
     3768            break; 
    37693769    } 
    37703770    if (cs1.Iflags != cs2.Iflags) 
    37713771        goto nomatch; 
    37723772 
    3773     ins = inssize[cs1.Iop]; 
    3774     if (cs1.Iop == 0x0F
     3773    ins = inssize[cs1.Iop & 0xFF]; 
     3774    if ((cs1.Iop & 0xFF00) == 0x0F00
    37753775    { 
    3776         if (cs1.Iop2 != cs2.Iop2) 
    3777             goto nomatch; 
    3778         if (cs1.Iop2 == 0x38 || cs1.Iop2 == 0x3A) 
    3779         { 
    3780             if (cs1.Iop3 != cs2.Iop3) 
    3781                 goto nomatch; 
    3782         } 
    3783         ins = inssize2[cs1.Iop2]; 
     3776        ins = inssize2[cs1.Iop & 0xFF]; 
    37843777    } 
    37853778 
    37863779    if (ins & M)                // if modregrm byte 
    37873780    { 
    37883781        if (cs1.Irm != cs2.Irm) 
    37893782            goto nomatch; 
    37903783        if ((cs1.Irm & 0xC0) == 0xC0) 
    37913784            goto do2; 
    37923785        if (is32bitaddr(I32,cs1.Iflags)) 
    37933786        { 
    37943787            if (issib(cs1.Irm) && cs1.Isib != cs2.Isib) 
    37953788                goto nomatch; 
    37963789            if ( 
    37973790                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    37983791               ) 
    37993792                goto do2;       /* if no first operand  */ 
    38003793        } 
    38013794        else 
    38023795        { 
    38033796            if ( 
     
    38643857} 
    38653858 
    38663859unsigned codout(code *c) 
    38673860{ unsigned op; 
    38683861  unsigned char rm,mod; 
    38693862  unsigned char ins; 
    38703863  code *cn; 
    38713864  unsigned flags; 
    38723865  symbol *s; 
    38733866 
    38743867#ifdef DEBUG 
    38753868  if (debugc) printf("codout(%p), Coffset = x%llx\n",c,(unsigned long long)Coffset); 
    38763869#endif 
    38773870 
    38783871  pgen = bytes; 
    38793872  offset = Coffset; 
    38803873  for (; c; c = code_next(c)) 
    38813874  { 
    38823875#ifdef DEBUG 
    38833876        if (debugc) { printf("off=%02lx, sz=%ld, ",(long)OFFSET(),(long)calccodsize(c)); c->print(); } 
     3877        unsigned startoffset = OFFSET(); 
    38843878#endif 
    38853879        op = c->Iop; 
    3886         ins = inssize[op]; 
    3887         switch (op
     3880        ins = inssize[op & 0xFF]; 
     3881        switch (op & 0xFF
    38883882        {   case ESCAPE: 
    3889                 switch (c->Iop2
     3883                switch (op & 0xFF00
    38903884                {   case ESClinnum: 
    38913885                        /* put out line number stuff    */ 
    38923886                        objlinnum(c->IEV2.Vsrcpos,OFFSET()); 
    38933887                        break; 
    38943888#if SCPP 
    38953889#if 1 
    38963890                    case ESCctor: 
    38973891                    case ESCdtor: 
    38983892                    case ESCoffset: 
    38993893                        if (config.exe != EX_NT) 
    39003894                            except_pair_setoffset(c,OFFSET() - funcoffset); 
    39013895                        break; 
    39023896                    case ESCmark: 
    39033897                    case ESCrelease: 
    39043898                    case ESCmark2: 
    39053899                    case ESCrelease2: 
    39063900                        break; 
    39073901#else 
    39083902                    case ESCctor: 
    39093903                        except_push(OFFSET() - funcoffset,c->IEV1.Vtor,NULL); 
    39103904                        break; 
    39113905                    case ESCdtor: 
    39123906                        except_pop(OFFSET() - funcoffset,c->IEV1.Vtor,NULL); 
    39133907                        break; 
    39143908                    case ESCmark: 
    39153909                        except_mark(); 
    39163910                        break; 
    39173911                    case ESCrelease: 
    39183912                        except_release(); 
    39193913                        break; 
    39203914#endif 
    39213915#endif 
    39223916                } 
     3917#ifdef DEBUG 
     3918                assert(calccodsize(c) == 0); 
     3919#endif 
    39233920                continue; 
    39243921            case NOP:                   /* don't send them out          */ 
     3922                if (op != NOP) 
     3923                    break; 
     3924#ifdef DEBUG 
     3925                assert(calccodsize(c) == 0); 
     3926#endif 
    39253927                continue; 
    39263928            case ASM: 
     3929                if (op != ASM) 
     3930                    break; 
    39273931                FLUSH(); 
    39283932                if (c->Iflags == CFaddrsize)    // kludge for DA inline asm 
    39293933                { 
    39303934                    do32bit(FLblockoff,&c->IEV1,0); 
    39313935                } 
    39323936                else 
    39333937                { 
    39343938                    offset += obj_bytes(cseg,offset,c->IEV1.as.len,c->IEV1.as.bytes); 
    39353939                } 
     3940#ifdef DEBUG 
     3941                assert(calccodsize(c) == c->IEV1.as.len); 
     3942#endif 
    39363943                continue; 
    39373944        } 
    39383945        flags = c->Iflags; 
    39393946 
    39403947        // See if we need to flush (don't have room for largest code sequence) 
    3941         if (pgen - bytes > sizeof(bytes) - (4+4+4+4)) 
     3948        if (pgen - bytes > sizeof(bytes) - (1+4+4+8+8)) 
    39423949            FLUSH(); 
    39433950 
    39443951        // see if we need to put out prefix bytes 
    39453952        if (flags & (CFwait | CFPREFIX | CFjmp16)) 
    39463953        {   int override; 
    39473954 
    39483955            if (flags & CFwait) 
    39493956                GEN(0x9B);                      // FWAIT 
    39503957                                                /* ? SEGES : SEGSS      */ 
    39513958            switch (flags & CFSEG) 
    39523959            {   case CFes:      override = SEGES;       goto segover; 
    39533960                case CFss:      override = SEGSS;       goto segover; 
    39543961                case CFcs:      override = SEGCS;       goto segover; 
    39553962                case CFds:      override = SEGDS;       goto segover; 
    39563963                case CFfs:      override = SEGFS;       goto segover; 
    39573964                case CFgs:      override = SEGGS;       goto segover; 
    39583965                segover:        GEN(override); 
    39593966                                break; 
    39603967            } 
    39613968 
    39623969            if (flags & CFaddrsize) 
    39633970                GEN(0x67); 
    39643971 
    39653972            // Do this last because of instructions like ADDPD 
    39663973            if (flags & CFopsize) 
    39673974                GEN(0x66);                      /* operand size         */ 
    39683975 
    3969             if ((op & 0xF0) == 0x70 && flags & CFjmp16) /* long condit jmp */ 
     3976            if ((op & ~0x0F) == 0x70 && flags & CFjmp16) /* long condit jmp */ 
    39703977            { 
    39713978                if (!I16) 
    39723979                {   // Put out 16 bit conditional jump 
    3973                     c->Iop2 = 0x80 | (op & 0x0F); 
    3974                     c->Iop = op = 0x0F; 
     3980                    c->Iop = op = 0x0F00 | (0x80 | (op & 0x0F)); 
    39753981                } 
    39763982                else 
    39773983                { 
    39783984                    cn = code_calloc(); 
    39793985                    /*cxcalloc++;*/ 
    39803986                    code_next(cn) = code_next(c); 
    39813987                    code_next(c) = cn;          // link into code 
    39823988                    cn->Iop = JMP;              // JMP block 
    39833989                    cn->IFL2 = c->IFL2; 
    39843990                    cn->IEV2.Vblock = c->IEV2.Vblock; 
    39853991                    c->Iop = op ^= 1;           // toggle condition 
    39863992                    c->IFL2 = FLconst; 
    39873993                    c->IEVpointer2 = I16 ? 3 : 5; // skip over JMP block 
    39883994                } 
    39893995            } 
    39903996        } 
    39913997 
    39923998        if (c->Irex) 
    39933999            GEN(c->Irex | REX); 
    3994         GEN(op); 
    3995         if (op == 0x0F) 
    3996         { 
    3997            ins = inssize2[c->Iop2]; 
    3998            GEN(c->Iop2); 
    3999            if (c->Iop2 == 0x38 || c->Iop2 == 0x3A) 
    4000                 GEN(c->Iop3); 
    4001         } 
     4000        if (op > 0xFF) 
     4001        { 
     4002            if ((op & 0xFF00) == 0x0F00) 
     4003                ins = inssize2[op & 0xFF]; 
     4004            if (op & 0xFF000000) 
     4005            {   GEN(op >> 24); 
     4006                GEN((op >> 8) & 0xFF); 
     4007                GEN(op & 0xFF); 
     4008                GEN((op >> 16) & 0xFF);         // yes, this is out of order. For 0x660F3A41 & 40 
     4009            } 
     4010            else if (op & 0xFF0000) 
     4011            { 
     4012                GEN((op >> 16) & 0xFF); 
     4013                GEN((op >> 8) & 0xFF); 
     4014                GEN(op & 0xFF); 
     4015            } 
     4016            else 
     4017            {   GEN((op >> 8) & 0xFF); 
     4018                GEN(op & 0xFF); 
     4019            } 
     4020        } 
     4021        else 
     4022            GEN(op); 
    40024023        if (ins & M)            /* if modregrm byte             */ 
    40034024        { 
    40044025            rm = c->Irm; 
    40054026            GEN(rm); 
    40064027 
    40074028            // Look for an address size override when working with the 
    40084029            // MOD R/M and SIB bytes 
    40094030 
    40104031            if (is32bitaddr( I32, flags)) 
    40114032            { 
    40124033                if (issib(rm)) 
    40134034                    GEN(c->Isib); 
    40144035                switch (rm & 0xC0) 
    40154036                {   case 0x40: 
    40164037                        do8bit((enum FL) c->IFL1,&c->IEV1);     // 8 bit 
    40174038                        break; 
    40184039                    case 0: 
    40194040                        if (!(issib(rm) && (c->Isib & 7) == 5 || 
    40204041                              (rm & 7) == 5)) 
    40214042                            break; 
     
    40784099                            if (c->Iflags & CFopsize) 
    40794100                                goto ptr1616; 
    40804101                            else 
    40814102                                goto ptr1632; 
    40824103 
    40834104                        case 0x68:              // PUSH immed32 
    40844105                            if ((enum FL)c->IFL2 == FLblock) 
    40854106                            { 
    40864107                                c->IFL2 = FLblockoff; 
    40874108                                goto do32; 
    40884109                            } 
    40894110                            else 
    40904111                                goto case_default; 
    40914112 
    40924113                        case 0xE8:              // CALL rel 
    40934114                        case 0xE9:              // JMP  rel 
    40944115                            flags |= CFselfrel; 
    40954116                            goto case_default; 
    40964117 
    40974118                        default: 
    4098                             if (I64 && (op & 0xF8) == 0xB8 && c->Irex & REX_W) 
     4119                            if (I64 && (op & ~7) == 0xB8 && c->Irex & REX_W) 
    40994120                                goto do64; 
    41004121                        case_default: 
    41014122                            if (c->Iflags & CFopsize) 
    41024123                                goto do16; 
    41034124                            else 
    41044125                                goto do32; 
    41054126                            break; 
    41064127                    } 
    41074128                } 
    41084129                else 
    41094130                { 
    41104131                    switch (op) { 
    41114132                        case 0xC2: 
    41124133                        case 0xCA: 
    41134134                            goto do16; 
    41144135                        case 0xA0: 
    41154136                        case 0xA1: 
    41164137                        case 0xA2: 
    41174138                        case 0xA3: 
    41184139                            if (c->Iflags & CFaddrsize) 
     
    41614182                                goto do32; 
    41624183                            else 
    41634184                                goto do16; 
    41644185                            break; 
    41654186                    } 
    41664187                } 
    41674188        } 
    41684189        else if (op == 0xF6)            /* TEST mem8,immed8             */ 
    41694190        {       if ((rm & (7<<3)) == 0) 
    41704191                        do8bit((enum FL)c->IFL2,&c->IEV2); 
    41714192        } 
    41724193        else if (op == 0xF7) 
    41734194        {   if ((rm & (7<<3)) == 0)     /* TEST mem16/32,immed16/32     */ 
    41744195            { 
    41754196                if ((I32 || I64) ^ ((c->Iflags & CFopsize) != 0)) 
    41764197                    do32bit((enum FL)c->IFL2,&c->IEV2,flags); 
    41774198                else 
    41784199                    do16bit((enum FL)c->IFL2,&c->IEV2,flags); 
    41794200            } 
    41804201        } 
     4202#ifdef DEBUG 
     4203        if (OFFSET() - startoffset != calccodsize(c)) 
     4204        { 
     4205            printf("actual: %d, calc: %d\n", (int)(OFFSET() - startoffset), (int)calccodsize(c)); 
     4206            c->print(); 
     4207            assert(0); 
     4208        } 
     4209#endif 
    41814210    } 
    41824211    FLUSH(); 
    41834212    Coffset = offset; 
    41844213    //printf("-codout(), Coffset = x%x\n", Coffset); 
    41854214    return offset;                      /* ending address               */ 
    41864215} 
    41874216 
    41884217 
    41894218STATIC void do64bit(enum FL fl,union evc *uev,int flags) 
    41904219{   char *p; 
    41914220    symbol *s; 
    41924221    targ_size_t ad; 
    41934222    long tmp; 
    41944223 
    41954224    assert(I64); 
    41964225    switch (fl) 
    41974226    { 
    41984227        case FLconst: 
    41994228            ad = * (targ_size_t *) uev; 
    42004229        L1: 
     
    46454674#endif 
    46464675        } 
    46474676  } 
    46484677} 
    46494678 
    46504679 
    46514680/********************************** 
    46524681 */ 
    46534682 
    46544683#if HYDRATE 
    46554684void code_hydrate(code **pc) 
    46564685{ 
    46574686    code *c; 
    46584687    unsigned char ins,rm; 
    46594688    enum FL fl; 
    46604689 
    46614690    assert(pc); 
    46624691    while (*pc) 
    46634692    { 
    46644693        c = (code *) ph_hydrate(pc); 
     4694        if ((c->Iop & 0xFF00) == 0x0F00) 
     4695            ins = inssize2[c->Iop & 0xFF]; 
     4696        else 
     4697            ins = inssize[c->Iop & 0xFF]; 
    46654698        switch (c->Iop) 
    4666         {   case 0x0F: 
    4667                 ins = inssize2[c->Iop2]; 
    4668                 break; 
     4699        { 
    46694700            default: 
    4670                 ins = inssize[c->Iop]; 
    4671                 break; 
    4672             case ESCAPE: 
    4673                 switch (c->Iop2) 
    4674                 {   case ESClinnum: 
    4675                         srcpos_hydrate(&c->IEV2.Vsrcpos); 
    4676                         break; 
    4677                     case ESCctor: 
    4678                     case ESCdtor: 
    4679                         el_hydrate(&c->IEV1.Vtor); 
    4680                         break; 
    4681                 } 
     4701                break; 
     4702 
     4703            case ESCAPE | ESClinnum: 
     4704                srcpos_hydrate(&c->IEV2.Vsrcpos); 
    46824705                goto done; 
     4706 
     4707            case ESCAPE | ESCctor: 
     4708            case ESCAPE | ESCdtor: 
     4709                el_hydrate(&c->IEV1.Vtor); 
     4710                goto done; 
     4711 
    46834712            case ASM: 
    46844713                ph_hydrate(&c->IEV1.as.bytes); 
    46854714                goto done; 
    46864715        } 
    46874716        if (!(ins & M) || 
    46884717            ((rm = c->Irm) & 0xC0) == 0xC0) 
    46894718            goto do2;           /* if no first operand          */ 
    46904719        if (is32bitaddr(I32,c->Iflags)) 
    46914720        { 
    46924721 
    46934722            if ( 
    46944723                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    46954724               ) 
    46964725                goto do2;       /* if no first operand  */ 
    46974726        } 
    46984727        else 
    46994728        { 
    47004729            if ( 
    47014730                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
    47024731               ) 
     
    48094838 
    48104839        pc = &code_next(c); 
    48114840    } 
    48124841} 
    48134842#endif 
    48144843 
    48154844/********************************** 
    48164845 */ 
    48174846 
    48184847#if DEHYDRATE 
    48194848void code_dehydrate(code **pc) 
    48204849{ 
    48214850    code *c; 
    48224851    unsigned char ins,rm; 
    48234852    enum FL fl; 
    48244853 
    48254854    while ((c = *pc) != NULL) 
    48264855    { 
    48274856        ph_dehydrate(pc); 
    48284857 
     4858        if ((c->Iop & 0xFF00) == 0x0F00) 
     4859            ins = inssize2[c->Iop & 0xFF]; 
     4860        else 
     4861            ins = inssize[c->Iop & 0xFF]; 
    48294862        switch (c->Iop) 
    4830         {   case 0x0F: 
    4831                 ins = inssize2[c->Iop2]; 
    4832                 break; 
     4863        { 
    48334864            default: 
    4834                 ins = inssize[c->Iop]; 
    4835                 break; 
    4836             case ESCAPE: 
    4837                 switch (c->Iop2) 
    4838                 {   case ESClinnum: 
    4839                         srcpos_dehydrate(&c->IEV2.Vsrcpos); 
    4840                         break; 
    4841                     case ESCctor: 
    4842                     case ESCdtor: 
    4843                         el_dehydrate(&c->IEV1.Vtor); 
    4844                         break; 
    4845                 } 
     4865                break; 
     4866 
     4867            case ESCAPE | ESClinnum: 
     4868                srcpos_dehydrate(&c->IEV2.Vsrcpos); 
    48464869                goto done; 
     4870 
     4871            case ESCAPE | ESCctor: 
     4872            case ESCAPE | ESCdtor: 
     4873                el_dehydrate(&c->IEV1.Vtor); 
     4874                goto done; 
     4875 
    48474876            case ASM: 
    48484877                ph_dehydrate(&c->IEV1.as.bytes); 
    48494878                goto done; 
    48504879        } 
    48514880 
    48524881        if (!(ins & M) || 
    48534882            ((rm = c->Irm) & 0xC0) == 0xC0) 
    48544883            goto do2;           /* if no first operand          */ 
    48554884        if (is32bitaddr(I32,c->Iflags)) 
    48564885        { 
    48574886 
    48584887            if ( 
    48594888                ((rm & 0xC0) == 0 && !((rm & 7) == 4 && (c->Isib & 7) == 5 || (rm & 7) == 5)) 
    48604889               ) 
    48614890                goto do2;       /* if no first operand  */ 
    48624891        } 
    48634892        else 
    48644893        { 
    48654894            if ( 
    48664895                ((rm & 0xC0) == 0 && !((rm & 7) == 6)) 
     
    49825011 */ 
    49835012 
    49845013#if DEBUG 
    49855014 
    49865015void WRcodlst(code *c) 
    49875016{ for (; c; c = code_next(c)) 
    49885017        c->print(); 
    49895018} 
    49905019 
    49915020void code::print() 
    49925021{ 
    49935022  unsigned op,rm; 
    49945023  unsigned char ins; 
    49955024  code *c = this; 
    49965025 
    49975026  if (c == CNIL) 
    49985027  {     printf("code 0\n"); 
    49995028        return; 
    50005029  } 
    50015030  op = c->Iop; 
    5002   ins = inssize[op]; 
    5003   if (op == 0x0F) 
    5004   {     op = 0x0F00 + c->Iop2; 
    5005         if (op == 0x0F38 || op == 0x0F3A) 
    5006             op = (op << 8) | c->Iop3; 
    5007         ins = inssize2[c->Iop2]; 
    5008   } 
     5031 
     5032    if ((c->Iop & 0xFF00) == 0x0F00) 
     5033        ins = inssize2[op & 0xFF]; 
     5034    else 
     5035        ins = inssize[op & 0xFF]; 
     5036 
    50095037  printf("code %p: nxt=%p op=%02x",c,code_next(c),op); 
    5010   if (op == ESCAPE) 
    5011   {     if (c->Iop2 == ESClinnum) 
     5038  if ((op & 0xFF) == ESCAPE) 
     5039  {     if ((op & 0xFF00) == ESClinnum) 
    50125040        {   printf(" linnum = %d\n",c->IEV2.Vsrcpos.Slinnum); 
    50135041            return; 
    50145042        } 
    5015         printf(" ESCAPE %d",c->Iop2); 
     5043        printf(" ESCAPE %d",c->Iop >> 8); 
    50165044  } 
    50175045  if (c->Iflags) 
    50185046        printf(" flg=%x",c->Iflags); 
    50195047  if (ins & M) 
    50205048  {     rm = c->Irm; 
    50215049        printf(" rm=%02x=%d,%d,%d",rm,(rm>>6)&3,(rm>>3)&7,rm&7); 
    50225050        if (I32 && issib(rm)) 
    50235051        {   unsigned char sib = c->Isib; 
    50245052            printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 
    50255053        } 
    50265054        if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 
    50275055        { 
    50285056            switch (c->IFL1) 
    50295057            { 
    50305058                case FLconst: 
    50315059                case FLoffset: 
    50325060                    printf(" int = %4d",c->IEV1.Vuns); 
    50335061                    break; 
    50345062                case FLblock: 
    50355063                    printf(" block = %p",c->IEV1.Vblock); 
  • trunk/src/backend/cod4.c

    r577 r596  
    12231223                cl = getlvalue(&cs,e1,0);       /* get EA               */ 
    12241224                regm_t idxregs = idxregm(&cs); 
    12251225                retregs = *pretregs & (ALLREGS | mBP) & ~idxregs; 
    12261226                if (!retregs) 
    12271227                    retregs = ALLREGS & ~idxregs; 
    12281228                cg = allocreg(&retregs,&resreg,tyml); 
    12291229                cs.Iop = 0x69;                  /* IMUL reg,EA,e2value  */ 
    12301230                cs.IFL2 = FLconst; 
    12311231                cs.IEV2.Vint = e2factor; 
    12321232                opr = resreg; 
    12331233            } 
    12341234            else if (!I16 && !byte) 
    12351235            { 
    12361236             L1: 
    12371237                retregs = *pretregs & (ALLREGS | mBP); 
    12381238                if (!retregs) 
    12391239                    retregs = ALLREGS; 
    12401240                cr = codelem(e2,&retregs,FALSE); /* load rvalue in reg  */ 
    12411241                cl = getlvalue(&cs,e1,retregs); /* get EA               */ 
    12421242                cg = getregs(retregs);          /* destroy these regs   */ 
    1243                 cs.Iop = 0x0F;                  /* IMUL resreg,EA       */ 
    1244                 cs.Iop2 = 0xAF; 
     1243                cs.Iop = 0x0FAF;                // IMUL resreg,EA 
    12451244                resreg = findreg(retregs); 
    12461245                opr = resreg; 
    12471246            } 
    12481247            else 
    12491248            { 
    12501249                retregs = mAX; 
    12511250                cr = codelem(e2,&retregs,FALSE); // load rvalue in AX 
    12521251                cl = getlvalue(&cs,e1,mAX);     // get EA 
    12531252                cg = getregs(byte ? mAX : mAX | mDX); // destroy these regs 
    12541253                cs.Iop = 0xF7 ^ byte;           // [I]MUL EA 
    12551254            } 
    12561255            cs.Irm |= modregrm(0,opr,0); 
    12571256            c = gen(CNIL,&cs); 
    12581257        } 
    12591258        else // /= or %= 
    12601259        {   targ_size_t e2factor; 
    12611260            int pow2; 
    12621261            targ_ulong m; 
    12631262 
    12641263            assert(!byte);                      // should never happen 
     
    25702569            if (cx->Iop == 0x81 && (cx->Irm & modregrm(3,7,0)) == modregrm(3,4,0)) 
    25712570            { 
    25722571                // Convert AND of a word to AND of a dword, zeroing upper word 
    25732572                retregs = mask[cx->Irm & 7]; 
    25742573                cx->Iflags &= ~CFopsize; 
    25752574                cx->IEV2.Vint &= 0xFFFF; 
    25762575                goto L1; 
    25772576            } 
    25782577        } 
    25792578        if (op == OPs16_32 && retregs == mAX) 
    25802579            c2 = gen1(c2,0x98);         /* CWDE                         */ 
    25812580        else 
    25822581        { 
    25832582            reg = findreg(retregs); 
    25842583            if (config.flags4 & CFG4speed && op == OPu16_32) 
    25852584            {   // AND reg,0xFFFF 
    25862585                c3 = genc2(NULL,0x81,modregrm(3,4,reg),0xFFFFu); 
    25872586            } 
    25882587            else 
    25892588            { 
    2590                 c3 = genregs(CNIL,0x0F,reg,reg); 
    2591                 c3->Iop2 = (op == OPu16_32) ? 0xB7 : 0xBF; /* MOVZX/MOVSX reg,reg */ 
     2589                unsigned iop = (op == OPu16_32) ? 0x0FB7 : 0x0FBF; /* MOVZX/MOVSX reg,reg */ 
     2590                c3 = genregs(CNIL,iop,reg,reg); 
    25922591            } 
    25932592            c2 = cat(c2,c3); 
    25942593        } 
    25952594     L1: 
    25962595        c3 = e1comsub ? getregs(retregs) : CNIL; 
    25972596    } 
    25982597    c4 = fixresult(e,retregs,pretregs); 
    25992598    c = cat4(c1,c2,c3,c4); 
    26002599  } 
    26012600  else if (*pretregs & mPSW || config.target_cpu < TARGET_80286) 
    26022601  { 
    26032602    // OPs16_32, OPs32_64 
    26042603    // CWD doesn't affect flags, so we can depend on the integer 
    26052604    // math to provide the flags. 
    26062605    retregs = mAX | mPSW;               // want integer result in AX 
    26072606    *pretregs &= ~mPSW;                 // flags are already set 
    26082607    c1 = codelem(e->E1,&retregs,FALSE); 
    26092608    c2 = getregs(mDX);                  // sign extend into DX 
    26102609    c2 = gen1(c2,0x99);                 // CWD/CDQ 
    26112610    c3 = e1comsub ? getregs(retregs) : CNIL; 
     
    27242723    } 
    27252724    else 
    27262725    { 
    27272726     L1: 
    27282727        if (!I16) 
    27292728        { 
    27302729            if (op == OPs8int && reg == AX && size == 2) 
    27312730            {   c3 = gen1(c3,0x98);             /* CBW                  */ 
    27322731                c3->Iflags |= CFopsize;         /* don't do a CWDE      */ 
    27332732            } 
    27342733            else 
    27352734            { 
    27362735                /* We could do better by not forcing the src and dst    */ 
    27372736                /* registers to be the same.                            */ 
    27382737 
    27392738                if (config.flags4 & CFG4speed && op == OPu8_16) 
    27402739                {   // AND reg,0xFF 
    27412740                    c3 = genc2(c3,0x81,modregrm(3,4,reg),0xFF); 
    27422741                } 
    27432742                else 
    2744                 {   c3 = genregs(c3,0x0F,reg,reg); 
    2745                     c3->Iop2 = (op == OPu8int) ? 0xB6 : 0xBE; /* MOVZX/MOVSX reg,reg */ 
     2743                { 
     2744                    unsigned iop = (op == OPu8int) ? 0x0FB6 : 0x0FBE; // MOVZX/MOVSX reg,reg 
     2745                    c3 = genregs(c3,iop,reg,reg); 
    27462746                } 
    27472747            } 
    27482748        } 
    27492749        else 
    27502750        { 
    27512751            if (op == OPu8int) 
    27522752                c3 = genregs(c3,0x30,reg+4,reg+4);      // XOR regH,regH 
    27532753            else 
    27542754            { 
    27552755                c3 = gen1(c3,0x98);             /* CBW                  */ 
    27562756                *pretregs &= ~mPSW;             /* flags already set    */ 
    27572757            } 
    27582758        } 
    27592759    } 
    27602760    c2 = getregs(retregs); 
    27612761L2: 
    27622762    c4 = fixresult(e,retregs,pretregs); 
    27632763    return cat6(c0,c1,c2,c3,c4,NULL); 
    27642764} 
    27652765 
     
    30333033        case OPbts:     op = 0xAB; mode = 5; break; 
    30343034 
    30353035        default: 
    30363036            assert(0); 
    30373037    } 
    30383038 
    30393039    e1 = e->E1; 
    30403040    e2 = e->E2; 
    30413041    cs.Iflags = 0; 
    30423042    c = getlvalue(&cs, e, RMload);      // get addressing mode 
    30433043    if (e->Eoper == OPbt && *pretregs == 0) 
    30443044        return cat(c, codelem(e2,pretregs,FALSE)); 
    30453045 
    30463046    ty1 = tybasic(e1->Ety); 
    30473047    word = (!I16 && tysize[ty1] == SHORTSIZE) ? CFopsize : 0; 
    30483048    idxregs = idxregm(&cs);         // mask if index regs used 
    30493049 
    30503050//    if (e2->Eoper == OPconst && e2->EV.Vuns < 0x100)  // should do this instead? 
    30513051    if (e2->Eoper == OPconst) 
    30523052    { 
    3053         cs.Iop = 0x0F; 
    3054         cs.Iop2 = 0xBA;                         // BT rm,imm8 
     3053        cs.Iop = 0x0FBA;                         // BT rm,imm8 
    30553054        cs.Irm |= modregrm(0,mode,0); 
    30563055        cs.Iflags |= CFpsw | word; 
    30573056        cs.IFL2 = FLconst; 
    30583057        if (tysize[ty1] == SHORTSIZE) 
    30593058        { 
    30603059            cs.IEVoffset1 += (e2->EV.Vuns & ~15) >> 3; 
    30613060            cs.IEV2.Vint = e2->EV.Vint & 15; 
    30623061        } 
    30633062        else if (tysize[ty1] == 4) 
    30643063        { 
    30653064            cs.IEVoffset1 += (e2->EV.Vuns & ~31) >> 3; 
    30663065            cs.IEV2.Vint = e2->EV.Vint & 31; 
    30673066        } 
    30683067        else 
    30693068        { 
    30703069            cs.IEVoffset1 += (e2->EV.Vuns & ~63) >> 3; 
    30713070            cs.IEV2.Vint = e2->EV.Vint & 63; 
    30723071        } 
    30733072        c2 = gen(CNIL,&cs); 
    30743073    } 
    30753074    else 
    30763075    { 
    30773076        retregs = ALLREGS & ~idxregs; 
    30783077        c2 = scodelem(e2,&retregs,idxregs,TRUE); 
    30793078        reg = findreg(retregs); 
    30803079 
    3081         cs.Iop = 0x0F; 
    3082         cs.Iop2 = op;                           // BT rm,reg 
     3080        cs.Iop = 0x0F00 | op;                     // BT rm,reg 
    30833081        code_newreg(&cs,reg); 
    30843082        cs.Iflags |= CFpsw | word; 
    30853083        c2 = gen(c2,&cs); 
    30863084    } 
    30873085 
    30883086    if ((retregs = (*pretregs & (ALLREGS | mBP))) != 0) // if return result in register 
    30893087    { 
    30903088        code *nop = CNIL; 
    30913089        regm_t save = regcon.immed.mval; 
    30923090        code *cg = allocreg(&retregs,&reg,TYint); 
    30933091        regcon.immed.mval = save; 
    30943092        if ((*pretregs & mPSW) == 0) 
    30953093        { 
    30963094            cg = cat(cg,getregs(retregs)); 
    30973095            cg = genregs(cg,0x19,reg,reg);              // SBB reg,reg 
    30983096        } 
    30993097        else 
    31003098        { 
    31013099            cg = movregconst(cg,reg,1,8);               // MOV reg,1 
    31023100            nop = gennop(nop); 
     
    31373135    { 
    31383136        cl = getlvalue(&cs, e->E1, RMload);     // get addressing mode 
    31393137    } 
    31403138    else 
    31413139    { 
    31423140        retregs = allregs; 
    31433141        cl = codelem(e->E1, &retregs, FALSE); 
    31443142        reg = findreg(retregs); 
    31453143        cs.Irm = modregrm(3,0,reg & 7); 
    31463144        cs.Iflags = 0; 
    31473145        cs.Irex = 0; 
    31483146        if (reg & 8) 
    31493147            cs.Irex |= REX_B; 
    31503148    } 
    31513149 
    31523150    retregs = *pretregs & allregs; 
    31533151    if  (!retregs) 
    31543152        retregs = allregs; 
    31553153    cg = allocreg(&retregs, &reg, e->Ety); 
    31563154 
    3157     cs.Iop = 0x0F; 
    3158     cs.Iop2 = (e->Eoper == OPbsf) ? 0xBC : 0xBD;        // BSF/BSR reg,EA 
     3155    cs.Iop = (e->Eoper == OPbsf) ? 0x0FBC : 0x0FBD;        // BSF/BSR reg,EA 
    31593156    code_newreg(&cs, reg); 
    31603157    if (!I16 && sz == SHORTSIZE) 
    31613158        cs.Iflags |= CFopsize; 
    31623159    cg = gen(cg,&cs); 
    31633160 
    31643161    return cat3(cl,cg,fixresult(e,retregs,pretregs)); 
    31653162} 
    31663163 
    31673164/******************************************* 
    31683165 * Generate code for OPpair, OPrpair. 
    31693166 */ 
    31703167 
    31713168code *cdpair(elem *e, regm_t *pretregs) 
    31723169{ 
    31733170    regm_t retregs; 
    31743171    regm_t regs1; 
    31753172    regm_t regs2; 
    31763173    unsigned reg; 
    31773174    code *cg; 
    31783175    code *c1; 
  • trunk/src/backend/code.h

    r595 r596  
    214214#define JBE     0x76 
    215215#define JA      0x77 
    216216#define JS      0x78 
    217217#define JNS     0x79 
    218218#define JP      0x7A 
    219219#define JNP     0x7B 
    220220#define JL      0x7C 
    221221#define JGE     0x7D 
    222222#define JLE     0x7E 
    223223#define JG      0x7F 
    224224 
    225225/* NOP is used as a placeholder in the linked list of instructions, no  */ 
    226226/* actual code will be generated for it.                                */ 
    227227#define NOP     0x2E    /* actually CS: (we don't use 0x90 because the  */ 
    228228                        /* silly Windows stuff wants to output 0x90's)  */ 
    229229 
    230230#define ESCAPE  0x3E    // marker that special information is here 
    231231                        // (Iop2 is the type of special information) 
    232232                        // (Same as DS:, but we will never generate 
    233233                        // a separate DS: opcode anyway) 
    234     #define ESClinnum   1       // line number information 
    235     #define ESCctor     2       // object is constructed 
    236     #define ESCdtor     3       // object is destructed 
    237     #define ESCmark     4       // mark eh stack 
    238     #define ESCrelease  5       // release eh stack 
    239     #define ESCoffset   6       // set code offset for eh 
    240     #define ESCadjesp   7       // adjust ESP by IEV2.Vint 
    241     #define ESCmark2    8       // mark eh stack 
    242     #define ESCrelease2 9       // release eh stack 
    243     #define ESCframeptr 10      // replace with load of frame pointer 
     234    #define ESClinnum   (1 << 8)       // line number information 
     235    #define ESCctor     (2 << 8)       // object is constructed 
     236    #define ESCdtor     (3 << 8)       // object is destructed 
     237    #define ESCmark     (4 << 8)       // mark eh stack 
     238    #define ESCrelease  (5 << 8)       // release eh stack 
     239    #define ESCoffset   (6 << 8)       // set code offset for eh 
     240    #define ESCadjesp   (7 << 8)       // adjust ESP by IEV2.Vint 
     241    #define ESCmark2    (8 << 8)       // mark eh stack 
     242    #define ESCrelease2 (9 << 8)       // release eh stack 
     243    #define ESCframeptr (10 << 8)      // replace with load of frame pointer 
    244244 
    245245#define ASM     0x36    // string of asm bytes, actually an SS: opcode 
    246246 
    247247/********************************* 
    248248 * Macros to ease generating code 
    249249 * modregrm:    generate mod reg r/m field 
    250250 * modregxrm:   reg could be R8..R15 
    251251 * modregrmx:   rm could be R8..R15 
    252252 * modregxrmx:  reg or rm could be R8..R15 
    253253 * NEWREG:      change reg field of x to r 
    254254 * genorreg:    OR  t,f 
    255255 */ 
    256256 
    257257#define modregrm(m,r,rm)        (((m)<<6)|((r)<<3)|(rm)) 
    258258#define modregxrm(m,r,rm)       ((((r)&8)<<15)|modregrm((m),(r)&7,rm)) 
    259259#define modregrmx(m,r,rm)       ((((rm)&8)<<13)|modregrm((m),r,(rm)&7)) 
    260260#define modregxrmx(m,r,rm)      ((((r)&8)<<15)|(((rm)&8)<<13)|modregrm((m),(r)&7,(rm)&7)) 
    261261 
    262262#define NEWREXR(x,r)            ((x)=((x)&~REX_R)|(((r)&8)>>1)) 
    263263#define NEWREG(x,r)             ((x)=((x)&~(7<<3))|((r)<<3)) 
     
    380380#define CFopsize       0x80     // prefix with operand size 
    381381#define CFaddrsize    0x100     // prefix with address size 
    382382#define CFds          0x200     // need DS override (not with es, ss, or cs ) 
    383383#define CFcs          0x400     // need CS override 
    384384#define CFfs          0x800     // need FS override 
    385385#define CFgs    (CFcs | CFfs)   // need GS override 
    386386#define CFwait       0x1000     // If I32 it indicates when to output a WAIT 
    387387#define CFselfrel    0x2000     // if self-relative 
    388388#define CFunambig    0x4000     // indicates cannot be accessed by other addressing 
    389389                                // modes 
    390390#define CFtarg2      0x8000     // like CFtarg, but we can't optimize this away 
    391391#define CFvolatile  0x10000     // volatile reference, do not schedule 
    392392#define CFclassinit 0x20000     // class init code 
    393393#define CFoffset64  0x40000     // offset is 64 bits 
    394394#define CFpc32      0x80000     // I64: PC relative 32 bit fixup 
    395395 
    396396#define CFPREFIX (CFSEG | CFopsize | CFaddrsize) 
    397397#define CFSEG   (CFes | CFss | CFds | CFcs | CFfs | CFgs) 
    398398 
    399399 
    400     unsigned char Iop; 
    401     unsigned char Iop2;         // second opcode byte 
    402     unsigned char Iop3;         // third opcode byte 
     400    unsigned Iop; 
    403401 
    404402    union 
    405403    {   unsigned _Iea; 
    406404        struct 
    407405        { 
    408406            unsigned char _Irm;          // reg/mode 
    409407            unsigned char _Isib;         // SIB byte 
    410408            unsigned char _Irex;         // REX prefix 
    411409        } _ea; 
    412410    } _EA; 
    413411 
    414412#define Iea _EA._Iea 
    415413#define Irm _EA._ea._Irm 
    416414#define Isib _EA._ea._Isib 
    417415#define Irex _EA._ea._Irex 
    418416 
    419417    unsigned char IFL1,IFL2;    // FLavors of 1st, 2nd operands 
    420418    union evc IEV1;             // 1st operand, if any 
    421419      #define IEVpointer1 IEV1._EP.Vpointer 
    422420      #define IEVseg1     IEV1._EP.Vseg 
  • trunk/src/iasm.c

    r577 r596  
    13531353                        case _ES: 
    13541354                                emit(0x26); 
    13551355                                pc->Iflags |= CFes; 
    13561356                                break; 
    13571357                        case _FS: 
    13581358                                emit(0x64); 
    13591359                                pc->Iflags |= CFfs; 
    13601360                                break; 
    13611361                        case _GS: 
    13621362                                emit(0x65); 
    13631363                                pc->Iflags |= CFgs; 
    13641364                                break; 
    13651365                        default: 
    13661366                                assert(0); 
    13671367                        } 
    13681368                } 
    13691369                break; 
    13701370        } 
    13711371        unsigned usOpcode = ptb.pptb0->usOpcode; 
    13721372 
     1373        pc->Iop = usOpcode; 
    13731374        if ((usOpcode & 0xFFFFFF00) == 0x660F3A00 ||    // SSE4 
    13741375            (usOpcode & 0xFFFFFF00) == 0x660F3800)      // SSE4 
    13751376        { 
    1376             pc->Iflags |= CFopsize; 
    1377             pc->Iop = 0x0F; 
    1378             pc->Iop2 = (usOpcode >> 8) & 0xFF; 
    1379             pc->Iop3 = usOpcode & 0xFF; 
     1377            pc->Iop = 0x66000F00 | ((usOpcode >> 8) & 0xFF) | ((usOpcode & 0xFF) << 16); 
    13801378            goto L3; 
    13811379        } 
    13821380        switch (usOpcode & 0xFF0000) 
    13831381        { 
    13841382            case 0: 
    13851383                break; 
    13861384 
    13871385            case 0x660000: 
    1388                 pc->Iflags |= CFopsize; 
    13891386                usOpcode &= 0xFFFF; 
    1390                 break
     1387                goto L3
    13911388 
    13921389            case 0xF20000:                      // REPNE 
    13931390            case 0xF30000:                      // REP/REPE 
    13941391                // BUG: What if there's an address size prefix or segment 
    13951392                // override prefix? Must the REP be adjacent to the rest 
    13961393                // of the opcode? 
    1397                 pcPrefix = code_calloc(); 
    1398                 pcPrefix->Iop = usOpcode >> 16; 
    13991394                usOpcode &= 0xFFFF; 
    1400                 break
     1395                goto L3
    14011396 
    14021397            case 0x0F0000:                      // an AMD instruction 
    14031398                puc = ((unsigned char *) &usOpcode); 
    14041399                if (puc[1] != 0x0F)             // if not AMD instruction 0x0F0F 
    14051400                    goto L4; 
    14061401                emit(puc[2]); 
    14071402                emit(puc[1]); 
    14081403                emit(puc[0]); 
    1409                 pc->Iop = puc[2]; 
    1410                 pc->Iop2 = puc[1]; 
     1404                pc->Iop >>= 8; 
    14111405                pc->IEVint2 = puc[0]; 
    14121406                pc->IFL2 = FLconst; 
    14131407                goto L3; 
    14141408 
    14151409            default: 
    14161410                puc = ((unsigned char *) &usOpcode); 
    14171411            L4: 
    14181412                emit(puc[2]); 
    14191413                emit(puc[1]); 
    14201414                emit(puc[0]); 
    1421                 pc->Iop = puc[2]; 
    1422                 pc->Iop2 = puc[1]; 
     1415                pc->Iop >>= 8; 
    14231416                pc->Irm = puc[0]; 
    14241417                goto L3; 
    14251418        } 
    14261419        if (usOpcode & 0xff00) 
    14271420        { 
    14281421            puc = ((unsigned char *) &(usOpcode)); 
    14291422            emit(puc[1]); 
    14301423            emit(puc[0]); 
    14311424            pc->Iop = puc[1]; 
    14321425            if (pc->Iop == 0x0f) 
    1433                 pc->Iop2 = puc[0]; 
     1426                pc->Iop = 0x0F00 | puc[0]; 
    14341427            else 
    14351428            { 
    14361429                if (usOpcode == 0xDFE0) // FSTSW AX 
    14371430                {   pc->Irm = puc[0]; 
    14381431                    goto L2; 
    14391432                } 
    14401433                if (asmstate.ucItype == ITfloat) 
    14411434                    pc->Irm = puc[0]; 
    14421435                else 
    14431436                {   pc->IEVint2 = puc[0]; 
    14441437                    pc->IFL2 = FLconst; 
    14451438                } 
    14461439            } 
    14471440        } 
    14481441        else 
    14491442        { 
    14501443            emit(usOpcode); 
    1451             pc->Iop = usOpcode; 
    14521444        } 
    14531445    L3: ; 
    14541446 
    14551447        // If CALL, Jxx or LOOPx to a symbolic location 
    14561448        if (/*asmstate.ucItype == ITjump &&*/ 
    14571449            popnd1 && popnd1->s && popnd1->s->isLabel()) 
    14581450        {   Dsymbol *s; 
    14591451 
    14601452            s = popnd1->s; 
    14611453            if (s == asmstate.psDollar) 
    14621454            { 
    14631455                pc->IFL2 = FLconst; 
    14641456                if (uSizemaskTable1 & (_8 | _16)) 
    14651457                    pc->IEVint2 = popnd1->disp; 
    14661458                else if (uSizemaskTable1 & _32) 
    14671459                    pc->IEVpointer2 = (targ_size_t) popnd1->disp; 
    14681460            } 
    14691461            else 
    14701462            {   LabelDsymbol *label; 
    14711463 
    14721464                label = s->isLabel(); 
    14731465                if (label) 
    1474                 {   if ((pc->Iop & 0xF0) == 0x70) 
     1466                {   if ((pc->Iop & ~0x0F) == 0x70) 
    14751467                        pc->Iflags |= CFjmp16; 
    14761468                    if (usNumops == 1) 
    14771469                    {   pc->IFL2 = FLblock; 
    14781470                        pc->IEVlsym2 = label; 
    14791471                    } 
    14801472                    else 
    14811473                    {   pc->IFL1 = FLblock; 
    14821474                        pc->IEVlsym1 = label; 
    14831475                    } 
    14841476                } 
    14851477            } 
    14861478        } 
    14871479 
    14881480        switch (usNumops) 
    14891481        { 
    14901482            case 0: 
    14911483                break; 
    14921484            case 1: 
    14931485                if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    14941486                     amodTable1 == _normal && (uRegmaskTable1 & _rplus_r))) 
    14951487                { 
    14961488                    unsigned reg = popnd1->base->val; 
    14971489                    if (reg & 8) 
    14981490                    {   reg &= 7; 
    14991491                        pc->Irex |= REX_B; 
    15001492                        assert(I64); 
    15011493                    } 
    15021494                    if (asmstate.ucItype == ITfloat) 
    15031495                        pc->Irm += reg; 
    1504                     else if (pc->Iop == 0x0f) 
    1505                         pc->Iop2 += reg; 
    15061496                    else 
    15071497                        pc->Iop += reg; 
    15081498#ifdef DEBUG 
    15091499                    auchOpcode[usIdx-1] += reg; 
    15101500#endif 
    15111501                } 
    15121502                else 
    15131503                {       asm_make_modrm_byte( 
    15141504#ifdef DEBUG 
    15151505                                auchOpcode, &usIdx, 
    15161506#endif 
    15171507                                pc, 
    15181508                                ptb.pptb1->usFlags, 
    15191509                                popnd1, NULL); 
    15201510                } 
    15211511                popndTmp = popnd1; 
    15221512                aoptyTmp = aoptyTable1; 
    15231513                uSizemaskTmp = uSizemaskTable1; 
    15241514L1: 
    15251515                if (aoptyTmp == _imm) 
     
    16211611                                popnd2, popnd1); 
    16221612                        } 
    16231613                        popndTmp = popnd1; 
    16241614                        aoptyTmp = aoptyTable1; 
    16251615                        uSizemaskTmp = uSizemaskTable1; 
    16261616                } 
    16271617                else 
    16281618                { 
    16291619                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    16301620                             amodTable1 == _normal && 
    16311621                             (uRegmaskTable1 & _rplus_r))) 
    16321622                        { 
    16331623                            unsigned reg = popnd1->base->val; 
    16341624                            if (reg & 8) 
    16351625                            {   reg &= 7; 
    16361626                                pc->Irex |= REX_B; 
    16371627                                assert(I64); 
    16381628                            } 
    16391629                            if (asmstate.ucItype == ITfloat) 
    16401630                                pc->Irm += reg; 
    1641                             else if (pc->Iop == 0x0f) 
    1642                                 pc->Iop2 += reg; 
    16431631                            else 
    16441632                                pc->Iop += reg; 
    16451633#ifdef DEBUG 
    16461634                            auchOpcode[usIdx-1] += reg; 
    16471635#endif 
    16481636                        } 
    16491637                        else 
    16501638                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    16511639                             amodTable2 == _normal && 
    16521640                             (uRegmaskTable2 & _rplus_r))) 
    16531641                        { 
    16541642                            unsigned reg = popnd2->base->val; 
    16551643                            if (reg & 8) 
    16561644                            {   reg &= 7; 
    16571645                                pc->Irex |= REX_B; 
    16581646                                assert(I64); 
    16591647                            } 
    16601648                            if (asmstate.ucItype == ITfloat) 
    16611649                                pc->Irm += reg; 
    1662                             else if (pc->Iop == 0x0f) 
    1663                                 pc->Iop2 += reg; 
    16641650                            else 
    16651651                                pc->Iop += reg; 
    16661652#ifdef DEBUG 
    16671653                            auchOpcode[usIdx-1] += reg; 
    16681654#endif 
    16691655                        } 
    16701656                        else if (ptb.pptb0->usOpcode == 0xF30FD6 || 
    16711657                                 ptb.pptb0->usOpcode == 0x0F12 || 
    16721658                                 ptb.pptb0->usOpcode == 0x0F16 || 
    16731659                                 ptb.pptb0->usOpcode == 0x660F50 || 
    16741660                                 ptb.pptb0->usOpcode == 0x0F50 || 
    16751661                                 ptb.pptb0->usOpcode == 0x660FD7 || 
    16761662                                 ptb.pptb0->usOpcode == 0x0FD7) 
    16771663                        { 
    16781664                            asm_make_modrm_byte( 
    16791665#ifdef DEBUG 
    16801666                                    auchOpcode, &usIdx, 
    16811667#endif 
    16821668                                    pc, 
    16831669                                    ptb.pptb1->usFlags, 
     
    17211707                                ptb.pptb1->usFlags, 
    17221708                                popnd2, popnd1); 
    17231709                        popndTmp = popnd3; 
    17241710                        aoptyTmp = aoptyTable3; 
    17251711                        uSizemaskTmp = uSizemaskTable3; 
    17261712                } 
    17271713                else { 
    17281714 
    17291715                        if (((aoptyTable1 == _reg || aoptyTable1 == _float) && 
    17301716                             amodTable1 == _normal && 
    17311717                             (uRegmaskTable1 &_rplus_r))) 
    17321718                        { 
    17331719                            unsigned reg = popnd1->base->val; 
    17341720                            if (reg & 8) 
    17351721                            {   reg &= 7; 
    17361722                                pc->Irex |= REX_B; 
    17371723                                assert(I64); 
    17381724                            } 
    17391725                            if (asmstate.ucItype == ITfloat) 
    17401726                                pc->Irm += reg; 
    1741                             else if (pc->Iop == 0x0f) 
    1742                                 pc->Iop2 += reg; 
    17431727                            else 
    17441728                                pc->Iop += reg; 
    17451729#ifdef DEBUG 
    17461730                            auchOpcode[usIdx-1] += reg; 
    17471731#endif 
    17481732                        } 
    17491733                        else 
    17501734                        if (((aoptyTable2 == _reg || aoptyTable2 == _float) && 
    17511735                             amodTable2 == _normal && 
    17521736                             (uRegmaskTable2 &_rplus_r))) 
    17531737                        { 
    17541738                            unsigned reg = popnd1->base->val; 
    17551739                            if (reg & 8) 
    17561740                            {   reg &= 7; 
    17571741                                pc->Irex |= REX_B; 
    17581742                                assert(I64); 
    17591743                            } 
    17601744                            if (asmstate.ucItype == ITfloat) 
    17611745                                pc->Irm += reg; 
    1762                             else if (pc->Iop == 0x0f) 
    1763                                 pc->Iop2 += reg; 
    17641746                            else 
    17651747                                pc->Iop += reg; 
    17661748#ifdef DEBUG 
    17671749                            auchOpcode[usIdx-1] += reg; 
    17681750#endif 
    17691751                        } 
    17701752                        else 
    17711753                                asm_make_modrm_byte( 
    17721754#ifdef DEBUG 
    17731755                                        auchOpcode, &usIdx, 
    17741756#endif 
    17751757                                        pc, 
    17761758                                        ptb.pptb1->usFlags, 
    17771759                                        popnd1, popnd2); 
    17781760 
    17791761                        popndTmp = popnd3; 
    17801762                        aoptyTmp = aoptyTable3; 
    17811763                        uSizemaskTmp = uSizemaskTable3; 
    17821764 
    17831765                } 
    17841766                goto L1; 
    17851767        } 
    17861768L2: 
    17871769 
    1788         if ((pc->Iop & 0xF8) == 0xD8 && 
     1770        if ((pc->Iop & ~7) == 0xD8 && 
    17891771            ADDFWAIT() && 
    17901772            !(ptb.pptb0->usFlags & _nfwait)) 
    17911773                pc->Iflags |= CFwait; 
    17921774        else if ((ptb.pptb0->usFlags & _fwait) && 
    17931775            config.target_cpu >= TARGET_80386) 
    17941776                pc->Iflags |= CFwait; 
    17951777 
    17961778#ifdef DEBUG 
    17971779        if (debuga) 
    17981780        {   unsigned u; 
    17991781 
    18001782            for (u = 0; u < usIdx; u++) 
    18011783                printf("  %02X", auchOpcode[u]); 
    18021784 
    18031785            printf("\t%s\t", asm_opstr(pop)); 
    18041786            if (popnd1) 
    18051787                asm_output_popnd(popnd1); 
    18061788            if (popnd2) { 
    18071789                printf(","); 
    18081790                asm_output_popnd(popnd2);