core/x86/encode.c
/* Helper routine that sets/checks rex.w or data prefix, if necessary, for
 * variable-sized OPSZ_ constants that the user asks for.  We try to be flexible
 * setting/checking only enough prefix flags to ensure that the final template size
 * is one of the possible sizes in the request.
 */
Helper routine that sets/checks rex.w or data prefix, if necessary, for
variable-sized OPSZ_ constants that the user asks for.  We try to be flexible
setting/checking only enough prefix flags to ensure that the final template size
is one of the possible sizes in the request.
Helper routine that sets / checks rex . w or data prefix if necessary for variable - sized OPSZ_ constants that the user asks for . We try to be flexible setting / checking only enough prefix flags to ensure that the final template size is one of the possible sizes in the request .
static bool
size_ok_varsz(decode_info_t *di,
              opnd_size_t size_op, opnd_size_t size_template,
              uint prefix_data_addr)
{
    CLIENT_ASSERT(size_op != size_template, "size_ok_varsz: internal decoding error");
    switch (size_op) {
    case OPSZ_2_short1:
        if (size_template == OPSZ_2 || size_template == OPSZ_1)
            return true; 
        if (size_template == OPSZ_4_short2 || size_template == OPSZ_8_short2) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        if (size_template == OPSZ_4_rex8_short2) {
            if (TEST(PREFIX_REX_W, di->prefixes))
                return false; 
            di->prefixes |= prefix_data_addr;
            return true;
        }
        return false;
    case OPSZ_4_short2:
        if (size_template == OPSZ_4 || size_template == OPSZ_2)
            return true; 
        if (size_template == OPSZ_4_rex8_short2 || size_template == OPSZ_4_rex8)
            return !TEST(PREFIX_REX_W, di->prefixes);
        if (size_template == OPSZ_8_short2 || size_template == OPSZ_8_short4) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        if (size_template == OPSZ_6_irex10_short4 &&
            (proc_get_vendor() == VENDOR_AMD || !TEST(PREFIX_REX_W, di->prefixes))) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        return false;
    case OPSZ_4_rex8_short2:
        if (size_template == OPSZ_4_short2 || size_template == OPSZ_4_rex8 ||
            size_template == OPSZ_8_short2 || size_template == OPSZ_8_short4 ||
            size_template == OPSZ_2 || size_template == OPSZ_4 || size_template == OPSZ_8)
            return true; 
        if (size_template == OPSZ_6_irex10_short4 &&
            (proc_get_vendor() == VENDOR_AMD || !TEST(PREFIX_REX_W, di->prefixes))) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        return false;
    case OPSZ_4_rex8:
        if (size_template == OPSZ_8_short4 || size_template == OPSZ_4 ||
            size_template == OPSZ_8)
            return true; 
        if (size_template == OPSZ_4_short2 || size_template == OPSZ_4_rex8_short2 ||
            size_template == OPSZ_8_short2)
            return !TEST(prefix_data_addr, di->prefixes);
        if (size_template == OPSZ_6_irex10_short4 &&
            (proc_get_vendor() == VENDOR_AMD || !TEST(PREFIX_REX_W, di->prefixes))) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        return false;
    case OPSZ_6_irex10_short4:
        if (size_template == OPSZ_6 || size_template == OPSZ_4 ||
            (size_template == OPSZ_10 && proc_get_vendor() != VENDOR_AMD))
            return true; 
        if (size_template == OPSZ_4_short2)
            return !TEST(prefix_data_addr, di->prefixes);
        if (size_template == OPSZ_4_rex8_short2)
            return !TESTANY(prefix_data_addr|PREFIX_REX_W, di->prefixes);
        if (size_template == OPSZ_4_rex8)
            return !TEST(PREFIX_REX_W, di->prefixes);
        if (size_template == OPSZ_8_short4) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        return false;
    case OPSZ_8_short2:
        if (size_template == OPSZ_8 || size_template == OPSZ_2)
            return true; 
        if (size_template == OPSZ_4_short2) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        if (size_template == OPSZ_4_rex8_short2) {
            if (TEST(prefix_data_addr, di->prefixes))
                return true; 
            if (X64_MODE(di))
                di->prefixes |= PREFIX_REX_W;
            else
                di->prefixes |= prefix_data_addr;
            return true;
        }
        if (X64_MODE(di) && size_template == OPSZ_4_rex8) {
            di->prefixes |= PREFIX_REX_W;
            return true;
        }
        if (size_template == OPSZ_8_short4)
            return !TEST(prefix_data_addr, di->prefixes);
        return false;
    case OPSZ_8_short4:
        if (size_template == OPSZ_4_rex8 || size_template == OPSZ_8 ||
            size_template == OPSZ_4)
            return true; 
        if (size_template == OPSZ_4_short2 || size_template == OPSZ_4_rex8_short2 ||
            size_template == OPSZ_8_short2)
            return !TEST(prefix_data_addr, di->prefixes);
        if (size_template == OPSZ_6_irex10_short4 &&
            (proc_get_vendor() == VENDOR_AMD || !TEST(PREFIX_REX_W, di->prefixes))) {
            di->prefixes |= prefix_data_addr;
            return true;
        }
        return false;
    case OPSZ_28_short14:
        if (size_template == OPSZ_28 || size_template == OPSZ_14)
            return true; 
        return false;
    case OPSZ_108_short94:
        if (size_template == OPSZ_108 || size_template == OPSZ_94)
            return true; 
        return false;
    default:
        CLIENT_ASSERT(false, "size_ok_varsz() internal decoding error (invalid size)");
        break;
    }
    return false;
}
static bool size_ok_varsz ( decode_info_t * di , opnd_size_t size_op , opnd_size_t size_template , uint prefix_data_addr ) { CLIENT_ASSERT ( size_op != size_template , " " ) ; switch ( size_op ) { case OPSZ_2_short1 : if ( size_template == OPSZ_2 || size_template == OPSZ_1 ) return true ; if ( size_template == OPSZ_4_short2 || size_template == OPSZ_8_short2 ) { di -> prefixes |= prefix_data_addr ; return true ; } if ( size_template == OPSZ_4_rex8_short2 ) { if ( TEST ( PREFIX_REX_W , di -> prefixes ) ) return false ; di -> prefixes |= prefix_data_addr ; return true ; } return false ; case OPSZ_4_short2 : if ( size_template == OPSZ_4 || size_template == OPSZ_2 ) return true ; if ( size_template == OPSZ_4_rex8_short2 || size_template == OPSZ_4_rex8 ) return ! TEST ( PREFIX_REX_W , di -> prefixes ) ; if ( size_template == OPSZ_8_short2 || size_template == OPSZ_8_short4 ) { di -> prefixes |= prefix_data_addr ; return true ; } if ( size_template == OPSZ_6_irex10_short4 && ( proc_get_vendor ( ) == VENDOR_AMD || ! TEST ( PREFIX_REX_W , di -> prefixes ) ) ) { di -> prefixes |= prefix_data_addr ; return true ; } return false ; case OPSZ_4_rex8_short2 : if ( size_template == OPSZ_4_short2 || size_template == OPSZ_4_rex8 || size_template == OPSZ_8_short2 || size_template == OPSZ_8_short4 || size_template == OPSZ_2 || size_template == OPSZ_4 || size_template == OPSZ_8 ) return true ; if ( size_template == OPSZ_6_irex10_short4 && ( proc_get_vendor ( ) == VENDOR_AMD || ! TEST ( PREFIX_REX_W , di -> prefixes ) ) ) { di -> prefixes |= prefix_data_addr ; return true ; } return false ; case OPSZ_4_rex8 : if ( size_template == OPSZ_8_short4 || size_template == OPSZ_4 || size_template == OPSZ_8 ) return true ; if ( size_template == OPSZ_4_short2 || size_template == OPSZ_4_rex8_short2 || size_template == OPSZ_8_short2 ) return ! TEST ( prefix_data_addr , di -> prefixes ) ; if ( size_template == OPSZ_6_irex10_short4 && ( proc_get_vendor ( ) == VENDOR_AMD || ! TEST ( PREFIX_REX_W , di -> prefixes ) ) ) { di -> prefixes |= prefix_data_addr ; return true ; } return false ; case OPSZ_6_irex10_short4 : if ( size_template == OPSZ_6 || size_template == OPSZ_4 || ( size_template == OPSZ_10 && proc_get_vendor ( ) != VENDOR_AMD ) ) return true ; if ( size_template == OPSZ_4_short2 ) return ! TEST ( prefix_data_addr , di -> prefixes ) ; if ( size_template == OPSZ_4_rex8_short2 ) return ! TESTANY ( prefix_data_addr | PREFIX_REX_W , di -> prefixes ) ; if ( size_template == OPSZ_4_rex8 ) return ! TEST ( PREFIX_REX_W , di -> prefixes ) ; if ( size_template == OPSZ_8_short4 ) { di -> prefixes |= prefix_data_addr ; return true ; } return false ; case OPSZ_8_short2 : if ( size_template == OPSZ_8 || size_template == OPSZ_2 ) return true ; if ( size_template == OPSZ_4_short2 ) { di -> prefixes |= prefix_data_addr ; return true ; } if ( size_template == OPSZ_4_rex8_short2 ) { if ( TEST ( prefix_data_addr , di -> prefixes ) ) return true ; if ( X64_MODE ( di ) ) di -> prefixes |= PREFIX_REX_W ; else di -> prefixes |= prefix_data_addr ; return true ; } if ( X64_MODE ( di ) && size_template == OPSZ_4_rex8 ) { di -> prefixes |= PREFIX_REX_W ; return true ; } if ( size_template == OPSZ_8_short4 ) return ! TEST ( prefix_data_addr , di -> prefixes ) ; return false ; case OPSZ_8_short4 : if ( size_template == OPSZ_4_rex8 || size_template == OPSZ_8 || size_template == OPSZ_4 ) return true ; if ( size_template == OPSZ_4_short2 || size_template == OPSZ_4_rex8_short2 || size_template == OPSZ_8_short2 ) return ! TEST ( prefix_data_addr , di -> prefixes ) ; if ( size_template == OPSZ_6_irex10_short4 && ( proc_get_vendor ( ) == VENDOR_AMD || ! TEST ( PREFIX_REX_W , di -> prefixes ) ) ) { di -> prefixes |= prefix_data_addr ; return true ; } return false ; case OPSZ_28_short14 : if ( size_template == OPSZ_28 || size_template == OPSZ_14 ) return true ; return false ; case OPSZ_108_short94 : if ( size_template == OPSZ_108 || size_template == OPSZ_94 ) return true ; return false ; default : CLIENT_ASSERT ( false , " " ) ; break ; } return false ; }
Helper routine that sets/checks rex.w or data prefix, if necessary, for
 variable-sized OPSZ_ constants that the user asks for.
Helper routine that sets / checks rex . w or data prefix if necessary for variable - sized OPSZ_ constants that the user asks for .
/*prefixes field is IN/OUT; x86_mode is IN*/ /* FIXME: this code is getting long and complex: is there a better way?
     * Any way to resolve these var sizes further first?  Doesn't seem like it.
     */ /* if identical sizes we shouldn't be called */ /* will take prefix or no prefix */ /* rex.w trumps data prefix */ /* will take prefix or no prefix */ /* will take prefix or no prefix */ /* will take prefix or no prefix */ /* will take prefix or no prefix */ /* will take prefix or no prefix */ /* Already shrinking so ok */ /* FIXME - ambiguous on 64-bit (could widen to 8 or shrink to 2).
             * We choose to widen by default for 64-bit as that seems the more likely
             * usage, but whatever choice we make here could conflict with a later
             * operand and lead to encoding failure even if there was a possible match. */ /* will take prefix or no prefix */ /* will take prefix or no prefix */ /* will take prefix or no prefix */