/* BEGIN_LEGAL Copyright (c) 2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. END_LEGAL */ /// This is the place to start learning about the decoder APIs. It /// exercises most of the essential features of the decoder. #include "xed/xed-interface.h" #include "xed-examples-util.h" #include #include #include #include int main(int argc, char** argv); void print_misc(xed_decoded_inst_t* xedd) { xed_uint_t i=0; const xed_operand_values_t* ov = xed_decoded_inst_operands_const(xedd); const xed_inst_t* xi = xed_decoded_inst_inst(xedd); xed_exception_enum_t e = xed_inst_exception(xi); xed_uint_t np = xed_decoded_inst_get_nprefixes(xedd); xed_isa_set_enum_t isaset = xed_decoded_inst_get_isa_set(xedd); if (xed_operand_values_has_real_rep(ov)) { xed_iclass_enum_t norep = xed_rep_remove(xed_decoded_inst_get_iclass(xedd)); printf("REAL REP "); printf("\tcorresponding no-rep iclass: %s\n" , xed_iclass_enum_t2str(norep)); } if (xed_operand_values_has_rep_prefix(ov)) { printf("F3 PREFIX\n"); } if (xed_operand_values_has_repne_prefix(ov)) { printf("F2 PREFIX\n"); } if (xed_operand_values_has_address_size_prefix(ov)) { printf("67 PREFIX\n"); } if (xed_operand_values_has_operand_size_prefix(ov)) { /* this 66 prefix is not part of the opcode */ printf("66-OSZ PREFIX\n"); } if (xed_operand_values_has_66_prefix(ov)) { /* this is any 66 prefix including the above */ printf("ANY 66 PREFIX\n"); } if (xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_RING0)) { printf("RING0 only\n"); } if (e != XED_EXCEPTION_INVALID) { printf("EXCEPTION TYPE: %s\n", xed_exception_enum_t2str(e)); } if (xed_decoded_inst_is_broadcast(xedd)) printf("BROADCAST\n"); if ( xed_classify_sse(xedd) || xed_classify_avx(xedd) || xed_classify_avx512(xedd) ) { if (xed_classify_avx512_maskop(xedd)) printf("AVX512 KMASK-OP\n"); else { xed_bool_t sse = 0; if (xed_classify_sse(xedd)) { sse = 1; printf("SSE\n"); } else if (xed_classify_avx(xedd)) printf("AVX\n"); else if (xed_classify_avx512(xedd)) printf("AVX512\n"); if (xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_SIMD_SCALAR)) printf("SCALAR\n"); else { // xed_decoded_inst_vector_length_bits is only for VEX/EVEX instr. // This will print 128 vl for FXSAVE and LD/ST MXCSR which is unfortunate. xed_uint_t vl_bits = sse ? 128 : xed_decoded_inst_vector_length_bits(xedd); printf("Vector length: %u\n", vl_bits); } if (xed_classify_avx512(xedd)) { xed_uint_t vec_elements = xed_decoded_inst_avx512_dest_elements(xedd); printf( "AVX512 vector elements: %u\n", vec_elements); } } } // does not include instructions that have XED_ATTRIBUTE_MASK_AS_CONTROL. // does not include vetor instructions that have k0 as a mask register. if (xed_decoded_inst_masked_vector_operation(xedd)) printf("WRITE-MASKING\n"); if (np) printf("Number of legacy prefixes: %u \n", np); printf("ISA SET: [%s]\n", xed_isa_set_enum_t2str(isaset)); for(i=0; i0 && t<5) printf("rounding mode override = %s\n", rounding_modes[t]); } } void print_branch_hints(xed_decoded_inst_t* xedd) { if (xed_operand_values_branch_not_taken_hint(xedd)) printf("HINT: NOT TAKEN\n"); else if (xed_operand_values_branch_taken_hint(xedd)) printf("HINT: TAKEN\n"); else if (xed_operand_values_cet_no_track(xedd)) printf("CET NO-TRACK\n"); } void print_attributes(xed_decoded_inst_t* xedd) { /* Walk the attributes. Generally, you'll know the one you want to * query and just access that one directly. */ const xed_inst_t* xi = xed_decoded_inst_inst(xedd); unsigned int i, nattributes = xed_attribute_max(); printf("ATTRIBUTES: "); for(i=0;is.zf) { printf("READS ZF\n"); } } } void print_flags(xed_decoded_inst_t* xedd) { unsigned int i, nflags; if (xed_decoded_inst_uses_rflags(xedd)) { const xed_simple_flag_t* rfi = xed_decoded_inst_get_rflags_info(xedd); assert(rfi); printf("FLAGS:\n"); if (xed_simple_flag_reads_flags(rfi)) { printf(" reads-rflags "); } else if (xed_simple_flag_writes_flags(rfi)) { //XED provides may-write and must-write information if (xed_simple_flag_get_may_write(rfi)) { printf(" may-write-rflags "); } if (xed_simple_flag_get_must_write(rfi)) { printf(" must-write-rflags "); } } nflags = xed_simple_flag_get_nflags(rfi); for( i=0;i> 3); printf(" %2u", xed_decoded_inst_operand_elements(xedd,i)); printf(" %3u", xed_decoded_inst_operand_element_size_bits(xedd,i)); printf(" %10s", xed_operand_element_type_enum_t2str( xed_decoded_inst_operand_element_type(xedd,i))); printf(" %10s\n", xed_reg_class_enum_t2str( xed_reg_class( xed_decoded_inst_get_reg(xedd, op_name)))); } } int main(int argc, char** argv) { xed_state_t dstate; xed_decoded_inst_t xedd; xed_uint_t i, bytes = 0; xed_uint_t argcu = (xed_uint_t)argc; unsigned char itext[XED_MAX_INSTRUCTION_BYTES]; xed_uint_t first_argv; xed_bool_t already_set_mode = 0; xed_chip_enum_t chip = XED_CHIP_INVALID; char const* decode_text=0; unsigned int len; xed_error_enum_t xed_error; #if defined(XED_MPX) unsigned int mpx_mode=0; #endif #if defined(XED_CET) unsigned int cet_mode=0; #endif xed_tables_init(); xed_state_zero(&dstate); first_argv = 1; dstate.mmode=XED_MACHINE_MODE_LEGACY_32; dstate.stack_addr_width=XED_ADDRESS_WIDTH_32b; for(i=1;i< argcu;i++) { if (strcmp(argv[i], "-64") == 0) { assert(already_set_mode == 0); already_set_mode = 1; dstate.mmode=XED_MACHINE_MODE_LONG_64; first_argv++; } #if defined(XED_MPX) else if (strcmp(argv[i], "-mpx") == 0) { mpx_mode = 1; first_argv++; } #endif #if defined(XED_CET) else if (strcmp(argv[i], "-cet") == 0) { cet_mode = 1; first_argv++; } #endif else if (strcmp(argv[i], "-16") == 0) { assert(already_set_mode == 0); already_set_mode = 1; dstate.mmode=XED_MACHINE_MODE_LEGACY_16; dstate.stack_addr_width=XED_ADDRESS_WIDTH_16b; first_argv++; } else if (strcmp(argv[i], "-s16") == 0) { already_set_mode = 1; dstate.stack_addr_width=XED_ADDRESS_WIDTH_16b; first_argv++; } else if (strcmp(argv[i], "-chip") == 0) { assert(i+1 < argcu); chip = str2xed_chip_enum_t(argv[i+1]); printf("Setting chip to %s\n", xed_chip_enum_t2str(chip)); assert(chip != XED_CHIP_INVALID); first_argv+=2; } } assert(first_argv < argcu); xed_decoded_inst_zero_set_mode(&xedd, &dstate); xed_decoded_inst_set_input_chip(&xedd, chip); #if defined(XED_MPX) xed3_operand_set_mpxmode(&xedd, mpx_mode); #endif #if defined(XED_CET) xed3_operand_set_cet(&xedd, cet_mode); #endif // convert ascii hex to hex bytes for(i=first_argv; i< argcu;i++) decode_text = xedex_append_string(decode_text,argv[i]); len = (unsigned int) strlen(decode_text); if ((len & 1) == 1) { printf("Must supply even number of nibbles per substring\n"); exit(1); } if (len > XED_MAX_INSTRUCTION_BYTES*2) { printf("Must supply at most 30 nibbles (15 bytes)\n"); exit(1); } bytes = xed_convert_ascii_to_hex(decode_text, itext, XED_MAX_INSTRUCTION_BYTES); if (bytes == 0) { printf("Must supply some hex bytes\n"); exit(1); } printf("Attempting to decode: "); for(i=0;i