VirtualBox

Ignore:
Timestamp:
May 30, 2012 3:58:23 PM (13 years ago)
Author:
vboxsync
Message:

DISFormatYasmIsOddEncoding: From tstDisasm-2.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Disassembler/testcase/tstDisasm-2.cpp

    r38636 r41501  
    108108
    109109/**
    110  * Checks if the encoding of the current instruction is something
    111  * we can never get the assembler to produce.
    112  *
    113  * @returns true if it's odd, false if it isn't.
    114  * @param   pCpu        The disassembler output.
    115  */
    116 static bool MyDisasYasmFormatterIsOddEncoding(PMYDISSTATE pState)
    117 {
    118     /*
    119      * Mod rm + SIB: Check for duplicate EBP encodings that yasm won't use for very good reasons.
    120      */
    121     if (    pState->Cpu.addrmode != CPUMODE_16BIT ///@todo correct?
    122         &&  pState->Cpu.ModRM.Bits.Rm == 4
    123         &&  pState->Cpu.ModRM.Bits.Mod != 3)
    124     {
    125         /* No scaled index SIB (index=4), except for ESP. */
    126         if (    pState->Cpu.SIB.Bits.Index == 4
    127             &&  pState->Cpu.SIB.Bits.Base != 4)
    128             return true;
    129 
    130         /* EBP + displacement */
    131         if (    pState->Cpu.ModRM.Bits.Mod != 0
    132              && pState->Cpu.SIB.Bits.Base == 5
    133              && pState->Cpu.SIB.Bits.Scale == 0)
    134             return true;
    135     }
    136 
    137     /*
    138      * Seems to be an instruction alias here, but I cannot find any docs on it... hrmpf!
    139      */
    140     if (    pState->Cpu.pCurInstr->opcode == OP_SHL
    141         &&  pState->Cpu.ModRM.Bits.Reg == 6)
    142         return true;
    143 
    144     /*
    145      * Check for multiple prefixes of the same kind.
    146      */
    147     uint32_t fPrefixes = 0;
    148     for (uint8_t const *pu8 = pState->pbInstr;; pu8++)
    149     {
    150         uint32_t f;
    151         switch (*pu8)
    152         {
    153             case 0xf0:
    154                 f = PREFIX_LOCK;
    155                 break;
    156 
    157             case 0xf2:
    158             case 0xf3:
    159                 f = PREFIX_REP; /* yes, both */
    160                 break;
    161 
    162             case 0x2e:
    163             case 0x3e:
    164             case 0x26:
    165             case 0x36:
    166             case 0x64:
    167             case 0x65:
    168                 f = PREFIX_SEG;
    169                 break;
    170 
    171             case 0x66:
    172                 f = PREFIX_OPSIZE;
    173                 break;
    174 
    175             case 0x67:
    176                 f = PREFIX_ADDRSIZE;
    177                 break;
    178 
    179             case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
    180             case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
    181                 f = pState->Cpu.mode == CPUMODE_64BIT ? PREFIX_REX : 0;
    182                 break;
    183 
    184             default:
    185                 f = 0;
    186                 break;
    187         }
    188         if (!f)
    189             break; /* done */
    190         if (fPrefixes & f)
    191             return true;
    192         fPrefixes |= f;
    193     }
    194 
    195     /* segment overrides are fun */
    196     if (fPrefixes & PREFIX_SEG)
    197     {
    198         /* no effective address which it may apply to. */
    199         Assert((pState->Cpu.prefix & PREFIX_SEG) || pState->Cpu.mode == CPUMODE_64BIT);
    200         if (    !DIS_IS_EFFECTIVE_ADDR(pState->Cpu.param1.flags)
    201             &&  !DIS_IS_EFFECTIVE_ADDR(pState->Cpu.param2.flags)
    202             &&  !DIS_IS_EFFECTIVE_ADDR(pState->Cpu.param3.flags))
    203             return true;
    204     }
    205 
    206     /* fixed register + addr override doesn't go down all that well. */
    207     if (fPrefixes & PREFIX_ADDRSIZE)
    208     {
    209         Assert(pState->Cpu.prefix & PREFIX_ADDRSIZE);
    210         if (    pState->Cpu.pCurInstr->param3 == OP_PARM_NONE
    211             &&  pState->Cpu.pCurInstr->param2 == OP_PARM_NONE
    212             &&  (   pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START
    213                  && pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END))
    214             return true;
    215     }
    216 
    217     /* Almost all prefixes are bad. */
    218     if (fPrefixes)
    219     {
    220         switch (pState->Cpu.pCurInstr->opcode)
    221         {
    222             /* nop w/ prefix(es). */
    223             case OP_NOP:
    224                 return true;
    225 
    226             case OP_JMP:
    227                 if (    pState->Cpu.pCurInstr->param1 != OP_PARM_Jb
    228                     &&  pState->Cpu.pCurInstr->param1 != OP_PARM_Jv)
    229                     break;
    230                 /* fall thru */
    231             case OP_JO:
    232             case OP_JNO:
    233             case OP_JC:
    234             case OP_JNC:
    235             case OP_JE:
    236             case OP_JNE:
    237             case OP_JBE:
    238             case OP_JNBE:
    239             case OP_JS:
    240             case OP_JNS:
    241             case OP_JP:
    242             case OP_JNP:
    243             case OP_JL:
    244             case OP_JNL:
    245             case OP_JLE:
    246             case OP_JNLE:
    247                 /** @todo branch hinting 0x2e/0x3e... */
    248                 return true;
    249         }
    250 
    251     }
    252 
    253     /* All but the segment prefix is bad news. */
    254     if (fPrefixes & ~PREFIX_SEG)
    255     {
    256         switch (pState->Cpu.pCurInstr->opcode)
    257         {
    258             case OP_POP:
    259             case OP_PUSH:
    260                 if (    pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_SEG_START
    261                     &&  pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_SEG_END)
    262                     return true;
    263                 if (    (fPrefixes & ~PREFIX_OPSIZE)
    264                     &&  pState->Cpu.pCurInstr->param1 >= OP_PARM_REG_GEN32_START
    265                     &&  pState->Cpu.pCurInstr->param1 <= OP_PARM_REG_GEN32_END)
    266                     return true;
    267                 break;
    268 
    269             case OP_POPA:
    270             case OP_POPF:
    271             case OP_PUSHA:
    272             case OP_PUSHF:
    273                 if (fPrefixes & ~PREFIX_OPSIZE)
    274                     return true;
    275                 break;
    276         }
    277     }
    278 
    279     /* Implicit 8-bit register instructions doesn't mix with operand size. */
    280     if (    (fPrefixes & PREFIX_OPSIZE)
    281         &&  (   (   pState->Cpu.pCurInstr->param1 == OP_PARM_Gb /* r8 */
    282                  && pState->Cpu.pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */)
    283              || (   pState->Cpu.pCurInstr->param2 == OP_PARM_Gb /* r8 */
    284                  && pState->Cpu.pCurInstr->param1 == OP_PARM_Eb /* r8/mem8 */))
    285        )
    286     {
    287         switch (pState->Cpu.pCurInstr->opcode)
    288         {
    289             case OP_ADD:
    290             case OP_OR:
    291             case OP_ADC:
    292             case OP_SBB:
    293             case OP_AND:
    294             case OP_SUB:
    295             case OP_XOR:
    296             case OP_CMP:
    297                 return true;
    298             default:
    299                 break;
    300         }
    301     }
    302 
    303 
    304     /*
    305      * Check for the version of xyz reg,reg instruction that the assembler doesn't use.
    306      *
    307      * For example:
    308      *    expected: 1aee   sbb ch, dh     ; SBB r8, r/m8
    309      *        yasm: 18F5   sbb ch, dh     ; SBB r/m8, r8
    310      */
    311     if (pState->Cpu.ModRM.Bits.Mod == 3 /* reg,reg */)
    312     {
    313         switch (pState->Cpu.pCurInstr->opcode)
    314         {
    315             case OP_ADD:
    316             case OP_OR:
    317             case OP_ADC:
    318             case OP_SBB:
    319             case OP_AND:
    320             case OP_SUB:
    321             case OP_XOR:
    322             case OP_CMP:
    323                 if (    (    pState->Cpu.pCurInstr->param1 == OP_PARM_Gb /* r8 */
    324                          && pState->Cpu.pCurInstr->param2 == OP_PARM_Eb /* r8/mem8 */)
    325                     ||  (    pState->Cpu.pCurInstr->param1 == OP_PARM_Gv /* rX */
    326                          && pState->Cpu.pCurInstr->param2 == OP_PARM_Ev /* rX/memX */))
    327                     return true;
    328 
    329                 /* 82 (see table A-6). */
    330                 if (pState->Cpu.opcode == 0x82)
    331                     return true;
    332                 break;
    333 
    334             /* ff /0, fe /0, ff /1, fe /0 */
    335             case OP_DEC:
    336             case OP_INC:
    337                 return true;
    338 
    339             case OP_POP:
    340             case OP_PUSH:
    341                 Assert(pState->Cpu.opcode == 0x8f);
    342                 return true;
    343 
    344             default:
    345                 break;
    346         }
    347     }
    348 
    349     /* shl eax,1 will be assembled to the form without the immediate byte. */
    350     if (    pState->Cpu.pCurInstr->param2 == OP_PARM_Ib
    351         &&  (uint8_t)pState->Cpu.param2.parval == 1)
    352     {
    353         switch (pState->Cpu.pCurInstr->opcode)
    354         {
    355             case OP_SHL:
    356             case OP_SHR:
    357             case OP_SAR:
    358             case OP_RCL:
    359             case OP_RCR:
    360             case OP_ROL:
    361             case OP_ROR:
    362                 return true;
    363         }
    364     }
    365 
    366     /* And some more - see table A-6. */
    367     if (pState->Cpu.opcode == 0x82)
    368     {
    369         switch (pState->Cpu.pCurInstr->opcode)
    370         {
    371             case OP_ADD:
    372             case OP_OR:
    373             case OP_ADC:
    374             case OP_SBB:
    375             case OP_AND:
    376             case OP_SUB:
    377             case OP_XOR:
    378             case OP_CMP:
    379                 return true;
    380                 break;
    381         }
    382     }
    383 
    384 
    385     /* check for REX.X = 1 without SIB. */
    386 
    387     /* Yasm encodes setnbe al with /2 instead of /0 like the AMD manual
    388        says (intel doesn't appear to care). */
    389     switch (pState->Cpu.pCurInstr->opcode)
    390     {
    391         case OP_SETO:
    392         case OP_SETNO:
    393         case OP_SETC:
    394         case OP_SETNC:
    395         case OP_SETE:
    396         case OP_SETNE:
    397         case OP_SETBE:
    398         case OP_SETNBE:
    399         case OP_SETS:
    400         case OP_SETNS:
    401         case OP_SETP:
    402         case OP_SETNP:
    403         case OP_SETL:
    404         case OP_SETNL:
    405         case OP_SETLE:
    406         case OP_SETNLE:
    407             AssertMsg(pState->Cpu.opcode >= 0x90 && pState->Cpu.opcode <= 0x9f, ("%#x\n", pState->Cpu.opcode));
    408             if (pState->Cpu.ModRM.Bits.Reg != 2)
    409                 return true;
    410             break;
    411     }
    412 
    413     /*
    414      * The MOVZX reg32,mem16 instruction without an operand size prefix
    415      * doesn't quite make sense...
    416      */
    417     if (    pState->Cpu.pCurInstr->opcode == OP_MOVZX
    418         &&  pState->Cpu.opcode == 0xB7
    419         &&  (pState->Cpu.mode == CPUMODE_16BIT) != !!(fPrefixes & PREFIX_OPSIZE))
    420         return true;
    421 
    422     return false;
    423 }
    424 
    425 
    426 /**
    427110 * Masm style.
    428111 *
     
    689372                /* Use db for odd encodings that we can't make the assembler use. */
    690373                if (    State.enmUndefOp == kUndefOp_DefineByte
    691                     &&  MyDisasYasmFormatterIsOddEncoding(&State))
     374                    &&  DISFormatYasmIsOddEncoding(&State.Cpu))
    692375                {
    693376                    RTPrintf("    db");
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette