Home | History | Annotate | Download | only in libdisasm
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include "libdis.h"
      6 #include <inttypes.h>
      7 
      8 #ifdef _MSC_VER
      9         #define snprintf        _snprintf
     10         #define inline          __inline
     11 #endif
     12 
     13 
     14 /*
     15  * concatenation macros.  STRNCATF concatenates a format string, buf
     16  * only with one argument.
     17  */
     18 #define STRNCAT( buf, str, len ) do {   				\
     19 	int _i = strlen(str), _blen = strlen(buf), _len = len - 1;  	\
     20 	if ( len ) {							\
     21         	strncat( buf, str, _len );  				\
     22 		if ( _len <= _i ) {					\
     23 			buf[_blen+_len] = '\0';				\
     24 			len = 0;					\
     25 		} else {						\
     26 			len -= _i;					\
     27 		}							\
     28 	}								\
     29 } while( 0 )
     30 
     31 #define STRNCATF( buf, fmt, data, len ) do {        \
     32         char _tmp[MAX_OP_STRING];                   \
     33                                                     \
     34         snprintf( _tmp, sizeof _tmp, fmt, data );   \
     35         STRNCAT( buf, _tmp, len );                  \
     36 } while( 0 )
     37 
     38 
     39 #define PRINT_DISPLACEMENT( ea ) do {                            \
     40         if ( ea->disp_size && ea->disp ) {                       \
     41                 if ( ea->disp_sign ) {    \
     42                         STRNCATF( buf, "-0x%" PRIX32, -ea->disp, len );    \
     43                 } else {                                         \
     44                         STRNCATF( buf, "0x%" PRIX32, ea->disp, len );  \
     45                 }                                                \
     46         }                                                        \
     47 } while( 0 )
     48 
     49 static const char *prefix_strings[] = {
     50 	"",     /* no prefix */
     51 	"repz ", /* the trailing spaces make it easy to prepend to mnemonic */
     52 	"repnz ",
     53 	"lock ",
     54 	"branch delay " /* unused in x86 */
     55 };
     56 
     57 static int format_insn_prefix_str( enum x86_insn_prefix prefix, char *buf,
     58                                    int len ) {
     59 
     60         int len_orig = len;
     61 
     62         /* concat all prefix strings */
     63         if ( prefix & 1 ) { STRNCAT( buf, prefix_strings[1], len ); }
     64         if ( prefix & 2 ) { STRNCAT( buf, prefix_strings[2], len ); }
     65         if ( prefix & 4 ) { STRNCAT( buf, prefix_strings[3], len ); }
     66         if ( prefix & 8 ) { STRNCAT( buf, prefix_strings[4], len ); }
     67 
     68         /* return the number of characters added */
     69         return (len_orig - len);
     70 }
     71 
     72 /*
     73  * sprint's an operand's data to string str.
     74  */
     75 static void get_operand_data_str( x86_op_t *op, char *str, int len ){
     76 
     77         if ( op->flags & op_signed ) {
     78                 switch ( op->datatype ) {
     79                         case op_byte:
     80                                 snprintf( str, len, "%" PRId8, op->data.sbyte );
     81                                 return;
     82                         case op_word:
     83                                 snprintf( str, len, "%" PRId16, op->data.sword );
     84                                 return;
     85                         case op_qword:
     86                                 snprintf( str, len, "%" PRId64, op->data.sqword );
     87                                 return;
     88                         default:
     89                                 snprintf( str, len, "%" PRId32, op->data.sdword );
     90                                 return;
     91                 }
     92         }
     93 
     94         //else
     95         switch ( op->datatype ) {
     96                 case op_byte:
     97                         snprintf( str, len, "0x%02" PRIX8, op->data.byte );
     98                         return;
     99                 case op_word:
    100                         snprintf( str, len, "0x%04" PRIX16, op->data.word );
    101                         return;
    102                 case op_qword:
    103                         snprintf( str, len, "0x%08" PRIX64,op->data.sqword );
    104                         return;
    105                 default:
    106                         snprintf( str, len, "0x%08" PRIX32, op->data.dword );
    107                         return;
    108         }
    109 }
    110 
    111 /*
    112  * sprints register types to a string.  the register types can be ORed
    113  * together.
    114  */
    115 static void get_operand_regtype_str( int regtype, char *str, int len )
    116 {
    117         static struct {
    118                 const char *name;
    119                 int value;
    120         } operand_regtypes[] = {
    121                 {"reg_gen"    , 0x00001},
    122                 {"reg_in"     , 0x00002},
    123                 {"reg_out"    , 0x00004},
    124                 {"reg_local"  , 0x00008},
    125                 {"reg_fpu"    , 0x00010},
    126                 {"reg_seg"    , 0x00020},
    127                 {"reg_simd"   , 0x00040},
    128                 {"reg_sys"    , 0x00080},
    129                 {"reg_sp"     , 0x00100},
    130                 {"reg_fp"     , 0x00200},
    131                 {"reg_pc"     , 0x00400},
    132                 {"reg_retaddr", 0x00800},
    133                 {"reg_cond"   , 0x01000},
    134                 {"reg_zero"   , 0x02000},
    135                 {"reg_ret"    , 0x04000},
    136                 {"reg_src"    , 0x10000},
    137                 {"reg_dest"   , 0x20000},
    138                 {"reg_count"  , 0x40000},
    139                 {NULL, 0}, //end
    140         };
    141 
    142         unsigned int i;
    143 
    144         memset( str, 0, len );
    145 
    146         //go thru every type in the enum
    147         for ( i = 0; operand_regtypes[i].name; i++ ) {
    148                 //skip if type is not set
    149                 if(! (regtype & operand_regtypes[i].value) )
    150                         continue;
    151 
    152                 //not the first time around
    153                 if( str[0] ) {
    154                         STRNCAT( str, " ", len );
    155                 }
    156 
    157                 STRNCAT(str, operand_regtypes[i].name, len );
    158         }
    159 }
    160 
    161 static int format_expr( x86_ea_t *ea, char *buf, int len,
    162                         enum x86_asm_format format ) {
    163         char str[MAX_OP_STRING];
    164 
    165         if ( format == att_syntax ) {
    166 		if (ea->base.name[0] || ea->index.name[0] || ea->scale) {
    167                		PRINT_DISPLACEMENT(ea);
    168 	                STRNCAT( buf, "(", len );
    169 
    170 	                if ( ea->base.name[0]) {
    171 	                        STRNCATF( buf, "%%%s", ea->base.name, len );
    172 	                }
    173 	                if ( ea->index.name[0]) {
    174 	                        STRNCATF( buf, ",%%%s", ea->index.name, len );
    175 	                        if ( ea->scale > 1 ) {
    176 	                                STRNCATF( buf, ",%d", ea->scale, len );
    177 	                        }
    178 	                }
    179 	                /* handle the syntactic exception */
    180 	                if ( ! ea->base.name[0] &&
    181 	                     ! ea->index.name[0]   ) {
    182 	                        STRNCATF( buf, ",%d", ea->scale, len );
    183 	                }
    184 
    185 	                STRNCAT( buf, ")", len );
    186 		} else
    187 			STRNCATF( buf, "0x%" PRIX32, ea->disp, len );
    188 
    189         } else if ( format == xml_syntax ){
    190 
    191                 if ( ea->base.name[0]) {
    192                         STRNCAT (buf, "\t\t\t<base>\n", len);
    193 
    194                         get_operand_regtype_str (ea->base.type, str,
    195                                                  sizeof str);
    196                         STRNCAT (buf, "\t\t\t\t<register ", len);
    197                         STRNCATF (buf, "name=\"%s\" ", ea->base.name, len);
    198                         STRNCATF (buf, "type=\"%s\" ", str, len);
    199                         STRNCATF (buf, "size=%d/>\n", ea->base.size, len);
    200 
    201                         STRNCAT (buf, "\t\t\t</base>\n", len);
    202                 }
    203 
    204                 if ( ea->index.name[0]) {
    205                         STRNCAT (buf, "\t\t\t<index>\n", len);
    206 
    207                         get_operand_regtype_str (ea->index.type, str,
    208                                                  sizeof str);
    209 
    210                         STRNCAT (buf, "\t\t\t\t<register ", len);
    211                         STRNCATF (buf, "name=\"%s\" ", ea->index.name, len);
    212                         STRNCATF (buf, "type=\"%s\" ", str, len);
    213                         STRNCATF (buf, "size=%d/>\n", ea->index.size, len);
    214 
    215                         STRNCAT (buf, "\t\t\t</index>\n", len);
    216                 }
    217 
    218                 //scale
    219                 STRNCAT (buf, "\t\t\t<scale>\n", len);
    220                 STRNCAT (buf, "\t\t\t\t<immediate ", len);
    221                 STRNCATF (buf, "value=\"%d\"/>\n", ea->scale, len);
    222                 STRNCAT (buf, "\t\t\t</scale>\n", len);
    223 
    224                 if ( ea->disp_size ) {
    225 
    226                         STRNCAT (buf, "\t\t\t<displacement>\n", len);
    227 
    228                         if ( ea->disp_size > 1 && ! ea->disp_sign ) {
    229                                 STRNCAT (buf, "\t\t\t\t<address ", len);
    230                                 STRNCATF (buf, "value=\"0x%" PRIX32 "\"/>\n", ea->disp,
    231                                           len);
    232                         } else {
    233                                 STRNCAT (buf, "\t\t\t\t<immediate ", len);
    234                                 STRNCATF (buf, "value=%" PRId32 "/>\n", ea->disp, len);
    235                         }
    236 
    237                         STRNCAT (buf, "\t\t\t</displacement>\n", len);
    238                 }
    239 
    240         } else if ( format == raw_syntax ) {
    241 
    242                 PRINT_DISPLACEMENT(ea);
    243                 STRNCAT( buf, "(", len );
    244 
    245                 STRNCATF( buf, "%s,", ea->base.name, len );
    246                 STRNCATF( buf, "%s,", ea->index.name, len );
    247                 STRNCATF( buf, "%d", ea->scale, len );
    248                 STRNCAT( buf, ")", len );
    249 
    250         } else {
    251 
    252                 STRNCAT( buf, "[", len );
    253 
    254                 if ( ea->base.name[0] ) {
    255                         STRNCAT( buf, ea->base.name, len );
    256                         if ( ea->index.name[0] ||
    257                              (ea->disp_size && ! ea->disp_sign) ) {
    258                                 STRNCAT( buf, "+", len );
    259                         }
    260                 }
    261                 if ( ea->index.name[0] ) {
    262                         STRNCAT( buf, ea->index.name, len );
    263                         if ( ea->scale > 1 )
    264                         {
    265                                 STRNCATF( buf, "*%" PRId32, ea->scale, len );
    266                         }
    267                         if ( ea->disp_size && ! ea->disp_sign )
    268                         {
    269                                 STRNCAT( buf, "+", len );
    270                         }
    271                 }
    272 
    273                 if ( ea->disp_size || (! ea->index.name[0] &&
    274 					! ea->base.name[0] ) )
    275                 {
    276                         PRINT_DISPLACEMENT(ea);
    277                 }
    278 
    279                 STRNCAT( buf, "]", len );
    280         }
    281 
    282         return( strlen(buf) );
    283 }
    284 
    285 static int format_seg( x86_op_t *op, char *buf, int len,
    286                        enum x86_asm_format format ) {
    287         int len_orig = len;
    288         const char *reg = "";
    289 
    290         if (! op || ! buf || ! len || ! op->flags) {
    291                 return(0);
    292         }
    293         if ( op->type != op_offset && op->type != op_expression ){
    294                 return(0);
    295         }
    296         if (! ((int) op->flags & 0xF00) ) {
    297                 return(0);
    298         }
    299 
    300         switch (op->flags & 0xF00) {
    301                 case op_es_seg: reg = "es"; break;
    302                 case op_cs_seg: reg = "cs"; break;
    303                 case op_ss_seg: reg = "ss"; break;
    304                 case op_ds_seg: reg = "ds"; break;
    305                 case op_fs_seg: reg = "fs"; break;
    306                 case op_gs_seg: reg = "gs"; break;
    307                 default:
    308                         break;
    309         }
    310 
    311         if (! reg[0] ) {
    312                 return( 0 );
    313         }
    314 
    315         switch( format ) {
    316                 case xml_syntax:
    317                         STRNCAT( buf, "\t\t\t<segment ", len );
    318                         STRNCATF( buf, "value=\"%s\"/>\n", reg, len );
    319                         break;
    320                 case att_syntax:
    321                         STRNCATF( buf, "%%%s:", reg, len );
    322                         break;
    323 
    324                 default:
    325                         STRNCATF( buf, "%s:", reg, len );
    326                         break;
    327         }
    328 
    329         return( len_orig - len ); /* return length of appended string */
    330 }
    331 
    332 static const char *get_operand_datatype_str( x86_op_t *op ){
    333 
    334         static const char *types[] = {
    335                 "sbyte",		/* 0 */
    336                 "sword",
    337                 "sqword",
    338                 "sdword",
    339                 "sdqword",		/* 4 */
    340                 "byte",
    341                 "word",
    342                 "qword",
    343                 "dword",		/* 8 */
    344                 "dqword",
    345 		"sreal",
    346 		"dreal",
    347 		"extreal",		/* 12 */
    348 		"bcd",
    349 		"ssimd",
    350 		"dsimd",
    351 		"sssimd",		/* 16 */
    352 		"sdsimd",
    353 		"descr32",
    354 		"descr16",
    355 		"pdescr32",		/* 20 */
    356 		"pdescr16",
    357 		"bounds16",
    358 		"bounds32",
    359 		"fpu_env16",
    360 		"fpu_env32",		/* 25 */
    361 		"fpu_state16",
    362 		"fpu_state32",
    363 		"fp_reg_set"
    364         };
    365 
    366 	/* handle signed values first */
    367         if ( op->flags & op_signed ) {
    368                 switch (op->datatype) {
    369                         case op_byte:  return types[0];
    370                         case op_word:  return types[1];
    371                         case op_qword: return types[2];
    372                 	case op_dqword: return types[4];
    373                         default:       return types[3];
    374                 }
    375         }
    376 
    377         switch (op->datatype) {
    378                 case op_byte:   	return types[5];
    379                 case op_word:   	return types[6];
    380                 case op_qword:  	return types[7];
    381                 case op_dqword: 	return types[9];
    382 		case op_sreal:		return types[10];
    383 		case op_dreal:		return types[11];
    384 		case op_extreal:	return types[12];
    385 		case op_bcd:		return types[13];
    386 		case op_ssimd:		return types[14];
    387 		case op_dsimd:		return types[15];
    388 		case op_sssimd:		return types[16];
    389 		case op_sdsimd:		return types[17];
    390 		case op_descr32:	return types[18];
    391 		case op_descr16:	return types[19];
    392 		case op_pdescr32:	return types[20];
    393 		case op_pdescr16:	return types[21];
    394 		case op_bounds16:	return types[22];
    395 		case op_bounds32:	return types[23];
    396 		case op_fpustate16: 	return types[24];
    397 		case op_fpustate32: 	return types[25];
    398 		case op_fpuenv16: 	return types[26];
    399 		case op_fpuenv32: 	return types[27];
    400 		case op_fpregset: 	return types[28];
    401                 default:        	return types[8];
    402         }
    403 }
    404 
    405 static int format_insn_eflags_str( enum x86_flag_status flags, char *buf,
    406                                    int len) {
    407 
    408         static struct {
    409                 const char *name;
    410                 int  value;
    411         } insn_flags[] = {
    412                 { "carry_set ",                 0x0001 },
    413                 { "zero_set ",                  0x0002 },
    414                 { "oflow_set ",                 0x0004 },
    415                 { "dir_set ",                   0x0008 },
    416                 { "sign_set ",                  0x0010 },
    417                 { "parity_set ",                0x0020 },
    418                 { "carry_or_zero_set ",         0x0040 },
    419                 { "zero_set_or_sign_ne_oflow ", 0x0080 },
    420                 { "carry_clear ",               0x0100 },
    421                 { "zero_clear ",                0x0200 },
    422                 { "oflow_clear ",               0x0400 },
    423                 { "dir_clear ",                 0x0800 },
    424                 { "sign_clear ",                0x1000 },
    425                 { "parity_clear ",              0x2000 },
    426                 { "sign_eq_oflow ",             0x4000 },
    427                 { "sign_ne_oflow ",             0x8000 },
    428                 { NULL,                         0x0000 }, //end
    429         };
    430 
    431         unsigned int i;
    432         int len_orig = len;
    433 
    434         for (i = 0; insn_flags[i].name; i++) {
    435                 if (! (flags & insn_flags[i].value) )
    436                         continue;
    437 
    438                 STRNCAT( buf, insn_flags[i].name, len );
    439         }
    440 
    441         return( len_orig - len );
    442 }
    443 
    444 static const char *get_insn_group_str( enum x86_insn_group gp ) {
    445 
    446         static const char *types[] = {
    447                 "",           // 0
    448                 "controlflow",// 1
    449                 "arithmetic", // 2
    450                 "logic",      // 3
    451                 "stack",      // 4
    452                 "comparison", // 5
    453                 "move",       // 6
    454                 "string",     // 7
    455                 "bit_manip",  // 8
    456                 "flag_manip", // 9
    457                 "fpu",        // 10
    458                 "",           // 11
    459                 "",           // 12
    460                 "interrupt",  // 13
    461                 "system",     // 14
    462                 "other",      // 15
    463         };
    464 
    465         if ( gp > sizeof (types)/sizeof(types[0]) )
    466                 return "";
    467 
    468         return types[gp];
    469 }
    470 
    471 static const char *get_insn_type_str( enum x86_insn_type type ) {
    472 
    473         static struct {
    474                 const char *name;
    475                 int  value;
    476         } types[] = {
    477                 /* insn_controlflow */
    478                 { "jmp", 0x1001 },
    479                 { "jcc", 0x1002 },
    480                 { "call", 0x1003 },
    481                 { "callcc", 0x1004 },
    482                 { "return", 0x1005 },
    483                 { "loop", 0x1006 },
    484                 /* insn_arithmetic */
    485                 { "add", 0x2001 },
    486                 { "sub", 0x2002 },
    487                 { "mul", 0x2003 },
    488                 { "div", 0x2004 },
    489                 { "inc", 0x2005 },
    490                 { "dec", 0x2006 },
    491                 { "shl", 0x2007 },
    492                 { "shr", 0x2008 },
    493                 { "rol", 0x2009 },
    494                 { "ror", 0x200A },
    495                 /* insn_logic */
    496                 { "and", 0x3001 },
    497                 { "or", 0x3002 },
    498                 { "xor", 0x3003 },
    499                 { "not", 0x3004 },
    500                 { "neg", 0x3005 },
    501                 /* insn_stack */
    502                 { "push", 0x4001 },
    503                 { "pop", 0x4002 },
    504                 { "pushregs", 0x4003 },
    505                 { "popregs", 0x4004 },
    506                 { "pushflags", 0x4005 },
    507                 { "popflags", 0x4006 },
    508                 { "enter", 0x4007 },
    509                 { "leave", 0x4008 },
    510                 /* insn_comparison */
    511                 { "test", 0x5001 },
    512                 { "cmp", 0x5002 },
    513                 /* insn_move */
    514                 { "mov", 0x6001 },      /* move */
    515                 { "movcc", 0x6002 },    /* conditional move */
    516                 { "xchg", 0x6003 },     /* exchange */
    517                 { "xchgcc", 0x6004 },   /* conditional exchange */
    518                 /* insn_string */
    519                 { "strcmp", 0x7001 },
    520                 { "strload", 0x7002 },
    521                 { "strmov", 0x7003 },
    522                 { "strstore", 0x7004 },
    523                 { "translate", 0x7005 },        /* xlat */
    524                 /* insn_bit_manip */
    525                 { "bittest", 0x8001 },
    526                 { "bitset", 0x8002 },
    527                 { "bitclear", 0x8003 },
    528                 /* insn_flag_manip */
    529                 { "clear_carry", 0x9001 },
    530                 { "clear_zero", 0x9002 },
    531                 { "clear_oflow", 0x9003 },
    532                 { "clear_dir", 0x9004 },
    533                 { "clear_sign", 0x9005 },
    534                 { "clear_parity", 0x9006 },
    535                 { "set_carry", 0x9007 },
    536                 { "set_zero", 0x9008 },
    537                 { "set_oflow", 0x9009 },
    538                 { "set_dir", 0x900A },
    539                 { "set_sign", 0x900B },
    540                 { "set_parity", 0x900C },
    541                 { "tog_carry", 0x9010 },
    542                 { "tog_zero", 0x9020 },
    543                 { "tog_oflow", 0x9030 },
    544                 { "tog_dir", 0x9040 },
    545                 { "tog_sign", 0x9050 },
    546                 { "tog_parity", 0x9060 },
    547                 /* insn_fpu */
    548                 { "fmov", 0xA001 },
    549                 { "fmovcc", 0xA002 },
    550                 { "fneg", 0xA003 },
    551                 { "fabs", 0xA004 },
    552                 { "fadd", 0xA005 },
    553                 { "fsub", 0xA006 },
    554                 { "fmul", 0xA007 },
    555                 { "fdiv", 0xA008 },
    556                 { "fsqrt", 0xA009 },
    557                 { "fcmp", 0xA00A },
    558                 { "fcos", 0xA00C },
    559                 { "fldpi", 0xA00D },
    560                 { "fldz", 0xA00E },
    561                 { "ftan", 0xA00F },
    562                 { "fsine", 0xA010 },
    563                 { "fsys", 0xA020 },
    564                 /* insn_interrupt */
    565                 { "int", 0xD001 },
    566                 { "intcc", 0xD002 },    /* not present in x86 ISA */
    567                 { "iret", 0xD003 },
    568                 { "bound", 0xD004 },
    569                 { "debug", 0xD005 },
    570                 { "trace", 0xD006 },
    571                 { "invalid_op", 0xD007 },
    572                 { "oflow", 0xD008 },
    573                 /* insn_system */
    574                 { "halt", 0xE001 },
    575                 { "in", 0xE002 },       /* input from port/bus */
    576                 { "out", 0xE003 },      /* output to port/bus */
    577                 { "cpuid", 0xE004 },
    578                 /* insn_other */
    579                 { "nop", 0xF001 },
    580                 { "bcdconv", 0xF002 },  /* convert to or from BCD */
    581                 { "szconv", 0xF003 },   /* change size of operand */
    582                 { NULL, 0 }, //end
    583         };
    584 
    585         unsigned int i;
    586 
    587         //go thru every type in the enum
    588         for ( i = 0; types[i].name; i++ ) {
    589                 if ( types[i].value == type )
    590                         return types[i].name;
    591         }
    592 
    593         return "";
    594 }
    595 
    596 static const char *get_insn_cpu_str( enum x86_insn_cpu cpu ) {
    597         static const char *intel[] = {
    598                 "",           		// 0
    599                 "8086",           	// 1
    600                 "80286",           	// 2
    601                 "80386",           	// 3
    602                 "80387",           	// 4
    603                 "80486",           	// 5
    604                 "Pentium",           	// 6
    605                 "Pentium Pro",          // 7
    606                 "Pentium 2",           	// 8
    607                 "Pentium 3",           	// 9
    608                 "Pentium 4"           	// 10
    609         };
    610 
    611         if ( cpu < sizeof(intel)/sizeof(intel[0]) ) {
    612 		return intel[cpu];
    613 	} else if ( cpu == 16 ) {
    614 		return "K6";
    615 	} else if ( cpu == 32 ) {
    616 		return "K7";
    617 	} else if ( cpu == 48 ) {
    618 		return "Athlon";
    619 	}
    620 
    621         return "";
    622 }
    623 
    624 static const char *get_insn_isa_str( enum x86_insn_isa isa ) {
    625         static const char *subset[] = {
    626 		NULL,				// 0
    627                 "General Purpose",           	// 1
    628                 "Floating Point",           	// 2
    629                 "FPU Management",           	// 3
    630                 "MMX",           		// 4
    631                 "SSE",           		// 5
    632                 "SSE2",           		// 6
    633                 "SSE3",           		// 7
    634                 "3DNow!",           		// 8
    635                 "System"           		// 9
    636         };
    637 
    638         if ( isa > sizeof (subset)/sizeof(subset[0]) ) {
    639                 return "";
    640 	}
    641 
    642         return subset[isa];
    643 }
    644 
    645 static int format_operand_att( x86_op_t *op, x86_insn_t *insn, char *buf,
    646                                int len){
    647 
    648         char str[MAX_OP_STRING];
    649 
    650         memset (str, 0, sizeof str);
    651 
    652         switch ( op->type ) {
    653                 case op_register:
    654                         STRNCATF( buf, "%%%s", op->data.reg.name, len );
    655                         break;
    656 
    657                 case op_immediate:
    658                         get_operand_data_str( op, str, sizeof str );
    659                         STRNCATF( buf, "$%s", str, len );
    660                         break;
    661 
    662                 case op_relative_near:
    663                         STRNCATF( buf, "0x%08X",
    664                                  (unsigned int)(op->data.sbyte +
    665                                  insn->addr + insn->size), len );
    666                         break;
    667 
    668 		case op_relative_far:
    669                         if (op->datatype == op_word) {
    670                                 STRNCATF( buf, "0x%08X",
    671                                           (unsigned int)(op->data.sword +
    672                                           insn->addr + insn->size), len );
    673                         } else {
    674                         	STRNCATF( buf, "0x%08X",
    675                                   	(unsigned int)(op->data.sdword +
    676                                   	insn->addr + insn->size), len );
    677 			}
    678                         break;
    679 
    680                 case op_absolute:
    681 			/* ATT uses the syntax $section, $offset */
    682                         STRNCATF( buf, "$0x%04" PRIX16 ", ", op->data.absolute.segment,
    683 				len );
    684 			if (op->datatype == op_descr16) {
    685                         	STRNCATF( buf, "$0x%04" PRIX16,
    686 					op->data.absolute.offset.off16, len );
    687 			} else {
    688                         	STRNCATF( buf, "$0x%08" PRIX32,
    689 					op->data.absolute.offset.off32, len );
    690 			}
    691                         break;
    692                 case op_offset:
    693                         /* ATT requires a '*' before JMP/CALL ops */
    694                         if (insn->type == insn_jmp || insn->type == insn_call)
    695                                 STRNCAT( buf, "*", len );
    696 
    697                         len -= format_seg( op, buf, len, att_syntax );
    698                         STRNCATF( buf, "0x%08" PRIX32, op->data.sdword, len );
    699                         break;
    700 
    701                 case op_expression:
    702                         /* ATT requires a '*' before JMP/CALL ops */
    703                         if (insn->type == insn_jmp || insn->type == insn_call)
    704                                 STRNCAT( buf, "*", len );
    705 
    706                         len -= format_seg( op, buf, len, att_syntax );
    707                         len -= format_expr( &op->data.expression, buf, len,
    708                                      att_syntax );
    709                         break;
    710                 case op_unused:
    711                 case op_unknown:
    712                         /* return 0-truncated buffer */
    713                         break;
    714         }
    715 
    716         return ( strlen( buf ) );
    717 }
    718 
    719 static int format_operand_native( x86_op_t *op, x86_insn_t *insn, char *buf,
    720                                   int len){
    721 
    722         char str[MAX_OP_STRING];
    723 
    724         switch (op->type) {
    725                 case op_register:
    726                         STRNCAT( buf, op->data.reg.name, len );
    727                         break;
    728 
    729                 case op_immediate:
    730                         get_operand_data_str( op, str, sizeof str );
    731                         STRNCAT( buf, str, len );
    732                         break;
    733 
    734                 case op_relative_near:
    735                         STRNCATF( buf, "0x%08" PRIX32,
    736                                   (unsigned int)(op->data.sbyte +
    737                                   insn->addr + insn->size), len );
    738                         break;
    739 
    740                 case op_relative_far:
    741                         if ( op->datatype == op_word ) {
    742                                 STRNCATF( buf, "0x%08" PRIX32,
    743                                           (unsigned int)(op->data.sword +
    744                                           insn->addr + insn->size), len );
    745                                 break;
    746                         } else {
    747                         	STRNCATF( buf, "0x%08" PRIX32, op->data.sdword +
    748                                 	  insn->addr + insn->size, len );
    749 			}
    750                         break;
    751 
    752                 case op_absolute:
    753                         STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
    754 				len );
    755 			if (op->datatype == op_descr16) {
    756                         	STRNCATF( buf, "0x%04" PRIX16,
    757 					op->data.absolute.offset.off16, len );
    758 			} else {
    759                         	STRNCATF( buf, "0x%08" PRIX32,
    760 					op->data.absolute.offset.off32, len );
    761 			}
    762                         break;
    763 
    764                 case op_offset:
    765                         len -= format_seg( op, buf, len, native_syntax );
    766                         STRNCATF( buf, "[0x%08" PRIX32 "]", op->data.sdword, len );
    767                         break;
    768 
    769                 case op_expression:
    770                         len -= format_seg( op, buf, len, native_syntax );
    771                         len -= format_expr( &op->data.expression, buf, len,
    772                                      native_syntax );
    773                         break;
    774                 case op_unused:
    775                 case op_unknown:
    776                         /* return 0-truncated buffer */
    777                         break;
    778         }
    779 
    780         return( strlen( buf ) );
    781 }
    782 
    783 static int format_operand_xml( x86_op_t *op, x86_insn_t *insn, char *buf,
    784                                int len){
    785 
    786         char str[MAX_OP_STRING] = "\0";
    787 
    788         switch (op->type) {
    789                 case op_register:
    790 
    791                         get_operand_regtype_str( op->data.reg.type, str,
    792                                                  sizeof str );
    793 
    794                         STRNCAT( buf, "\t\t<register ", len );
    795                         STRNCATF( buf, "name=\"%s\" ", op->data.reg.name, len );
    796                         STRNCATF( buf, "type=\"%s\" ", str, len );
    797                         STRNCATF( buf, "size=%d/>\n", op->data.reg.size, len );
    798                         break;
    799 
    800                 case op_immediate:
    801 
    802                         get_operand_data_str( op, str, sizeof str );
    803 
    804                         STRNCAT( buf, "\t\t<immediate ", len );
    805                         STRNCATF( buf, "type=\"%s\" ",
    806                                   get_operand_datatype_str (op), len );
    807                         STRNCATF( buf, "value=\"%s\"/>\n", str, len );
    808                         break;
    809 
    810                 case op_relative_near:
    811                         STRNCAT( buf, "\t\t<relative_offset ", len );
    812 
    813                         STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
    814                                   (unsigned int)(op->data.sbyte +
    815                                   insn->addr + insn->size), len );
    816                         break;
    817 
    818                 case op_relative_far:
    819                         STRNCAT( buf, "\t\t<relative_offset ", len );
    820 
    821                         if (op->datatype == op_word) {
    822                                 STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
    823                                           (unsigned int)(op->data.sword +
    824                                           insn->addr + insn->size), len);
    825                                 break;
    826                         } else {
    827 
    828                         	STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
    829                                       op->data.sdword + insn->addr + insn->size,
    830                                       len );
    831 			}
    832                         break;
    833 
    834                 case op_absolute:
    835 
    836                         STRNCATF( buf,
    837 				"\t\t<absolute_address segment=\"0x%04" PRIX16 "\"",
    838                         	op->data.absolute.segment, len );
    839 
    840 			if (op->datatype == op_descr16) {
    841                         	STRNCATF( buf, "offset=\"0x%04" PRIX16 "\">",
    842 					op->data.absolute.offset.off16, len );
    843 			} else {
    844                         	STRNCATF( buf, "offset=\"0x%08" PRIX32 "\">",
    845 					op->data.absolute.offset.off32, len );
    846 			}
    847 
    848                         STRNCAT( buf, "\t\t</absolute_address>\n", len );
    849                         break;
    850 
    851                 case op_expression:
    852 
    853 
    854                         STRNCAT( buf, "\t\t<address_expression>\n", len );
    855 
    856                         len -= format_seg( op, buf, len, xml_syntax );
    857                         len -= format_expr( &op->data.expression, buf, len,
    858                                      xml_syntax );
    859 
    860                         STRNCAT( buf, "\t\t</address_expression>\n", len );
    861                         break;
    862 
    863                 case op_offset:
    864 
    865                         STRNCAT( buf, "\t\t<segment_offset>\n", len );
    866 
    867                         len -= format_seg( op, buf, len, xml_syntax );
    868 
    869                         STRNCAT( buf, "\t\t\t<address ", len);
    870                         STRNCATF( buf, "value=\"0x%08" PRIX32 "\"/>\n",
    871                                           op->data.sdword, len );
    872                         STRNCAT( buf, "\t\t</segment_offset>\n", len );
    873                         break;
    874 
    875                 case op_unused:
    876                 case op_unknown:
    877                         /* return 0-truncated buffer */
    878                         break;
    879         }
    880 
    881         return( strlen( buf ) );
    882 }
    883 
    884 static int format_operand_raw( x86_op_t *op, x86_insn_t *insn, char *buf,
    885                                int len){
    886 
    887         char str[MAX_OP_RAW_STRING];
    888 	const char *datatype = get_operand_datatype_str(op);
    889 
    890         switch (op->type) {
    891                 case op_register:
    892 
    893                         get_operand_regtype_str( op->data.reg.type, str,
    894                                                  sizeof str );
    895 
    896                         STRNCAT( buf, "reg|", len );
    897                         STRNCATF( buf, "%s|", datatype, len );
    898                         STRNCATF( buf, "%s:", op->data.reg.name, len );
    899                         STRNCATF( buf, "%s:", str, len );
    900                         STRNCATF( buf, "%d|", op->data.reg.size, len );
    901                         break;
    902 
    903                 case op_immediate:
    904 
    905                         get_operand_data_str( op, str, sizeof str );
    906 
    907                         STRNCAT( buf, "immediate|", len );
    908                         STRNCATF( buf, "%s|", datatype, len );
    909                         STRNCATF( buf, "%s|", str, len );
    910                         break;
    911 
    912                 case op_relative_near:
    913 			/* NOTE: in raw format, we print the
    914 			 * relative offset, not the actual
    915 			 * address of the jump target */
    916 
    917                         STRNCAT( buf, "relative|", len );
    918                         STRNCATF( buf, "%s|", datatype, len );
    919                         STRNCATF( buf, "%" PRId8 "|", op->data.sbyte, len );
    920                         break;
    921 
    922                 case op_relative_far:
    923 
    924                         STRNCAT( buf, "relative|", len );
    925                         STRNCATF( buf, "%s|", datatype, len );
    926 
    927                         if (op->datatype == op_word) {
    928                                 STRNCATF( buf, "%" PRId16 "|", op->data.sword, len);
    929                                 break;
    930                         } else {
    931                         	STRNCATF( buf, "%" PRId32 "|", op->data.sdword, len );
    932 			}
    933                         break;
    934 
    935                 case op_absolute:
    936 
    937                         STRNCAT( buf, "absolute_address|", len );
    938                         STRNCATF( buf, "%s|", datatype, len );
    939 
    940                         STRNCATF( buf, "$0x%04" PRIX16 ":", op->data.absolute.segment,
    941 				len );
    942 			if (op->datatype == op_descr16) {
    943                         	STRNCATF( buf, "0x%04" PRIX16 "|",
    944 					op->data.absolute.offset.off16, len );
    945 			} else {
    946                         	STRNCATF( buf, "0x%08" PRIX32 "|",
    947 					op->data.absolute.offset.off32, len );
    948 			}
    949 
    950                         break;
    951 
    952                 case op_expression:
    953 
    954                         STRNCAT( buf, "address_expression|", len );
    955                         STRNCATF( buf, "%s|", datatype, len );
    956 
    957                         len -= format_seg( op, buf, len, native_syntax );
    958                         len -= format_expr( &op->data.expression, buf, len,
    959                                      raw_syntax );
    960 
    961                         STRNCAT( buf, "|", len );
    962                         break;
    963 
    964                 case op_offset:
    965 
    966                         STRNCAT( buf, "segment_offset|", len );
    967                         STRNCATF( buf, "%s|", datatype, len );
    968 
    969                         len -= format_seg( op, buf, len, xml_syntax );
    970 
    971                         STRNCATF( buf, "%08" PRIX32 "|", op->data.sdword, len );
    972                         break;
    973 
    974                 case op_unused:
    975                 case op_unknown:
    976                         /* return 0-truncated buffer */
    977                         break;
    978         }
    979 
    980         return( strlen( buf ) );
    981 }
    982 
    983 int x86_format_operand( x86_op_t *op, char *buf, int len,
    984                         enum x86_asm_format format ){
    985 	x86_insn_t *insn;
    986 
    987         if ( ! op || ! buf || len < 1 ) {
    988                 return(0);
    989         }
    990 
    991 	/* insn is stored in x86_op_t since .21-pre3 */
    992 	insn = (x86_insn_t *) op->insn;
    993 
    994         memset( buf, 0, len );
    995 
    996         switch ( format ) {
    997                 case att_syntax:
    998                         return format_operand_att( op, insn, buf, len );
    999                 case xml_syntax:
   1000                         return format_operand_xml( op, insn, buf, len );
   1001                 case raw_syntax:
   1002                         return format_operand_raw( op, insn, buf, len );
   1003                 case native_syntax:
   1004                 case intel_syntax:
   1005                 default:
   1006                         return format_operand_native( op, insn, buf, len );
   1007         }
   1008 }
   1009 
   1010 #define is_imm_jmp(op)   (op->type == op_absolute   || \
   1011                           op->type == op_immediate  || \
   1012                           op->type == op_offset)
   1013 #define is_memory_op(op) (op->type == op_absolute   || \
   1014                           op->type == op_expression || \
   1015                           op->type == op_offset)
   1016 
   1017 static int format_att_mnemonic( x86_insn_t *insn, char *buf, int len) {
   1018         int size = 0;
   1019         const char *suffix;
   1020 
   1021         if (! insn || ! buf || ! len )
   1022                 return(0);
   1023 
   1024         memset( buf, 0, len );
   1025 
   1026         /* do long jump/call prefix */
   1027         if ( insn->type == insn_jmp || insn->type == insn_call ) {
   1028                 if (! is_imm_jmp( x86_operand_1st(insn) ) ||
   1029                      (x86_operand_1st(insn))->datatype != op_byte ) {
   1030                     /* far jump/call, use "l" prefix */
   1031                     STRNCAT( buf, "l", len );
   1032                 }
   1033                 STRNCAT( buf, insn->mnemonic, len );
   1034 
   1035                 return ( strlen( buf ) );
   1036         }
   1037 
   1038         /* do mnemonic */
   1039         STRNCAT( buf, insn->mnemonic, len );
   1040 
   1041         /* do suffixes for memory operands */
   1042         if (!(insn->note & insn_note_nosuffix) &&
   1043             (insn->group == insn_arithmetic ||
   1044              insn->group == insn_logic ||
   1045              insn->group == insn_move ||
   1046              insn->group == insn_stack ||
   1047              insn->group == insn_string ||
   1048              insn->group == insn_comparison ||
   1049              insn->type == insn_in ||
   1050              insn->type == insn_out
   1051             )) {
   1052             if ( x86_operand_count( insn, op_explicit ) > 0 &&
   1053                  is_memory_op( x86_operand_1st(insn) ) ){
   1054                 size = x86_operand_size( x86_operand_1st( insn ) );
   1055             } else if ( x86_operand_count( insn, op_explicit ) > 1 &&
   1056                         is_memory_op( x86_operand_2nd(insn) ) ){
   1057                 size = x86_operand_size( x86_operand_2nd( insn ) );
   1058             }
   1059         }
   1060 
   1061         if ( size == 1 ) suffix = "b";
   1062         else if ( size == 2 ) suffix = "w";
   1063         else if ( size == 4 ) suffix = "l";
   1064         else if ( size == 8 ) suffix = "q";
   1065         else suffix = "";
   1066 
   1067         STRNCAT( buf, suffix, len );
   1068         return ( strlen( buf ) );
   1069 }
   1070 
   1071 int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
   1072                         enum x86_asm_format format){
   1073         char str[MAX_OP_STRING];
   1074 
   1075         memset( buf, 0, len );
   1076         STRNCAT( buf, insn->prefix_string, len );
   1077         if ( format == att_syntax ) {
   1078                 format_att_mnemonic( insn, str, sizeof str );
   1079                 STRNCAT( buf, str, len );
   1080         } else {
   1081                 STRNCAT( buf, insn->mnemonic, len );
   1082         }
   1083 
   1084         return( strlen( buf ) );
   1085 }
   1086 
   1087 struct op_string { char *buf; size_t len; };
   1088 
   1089 static void format_op_raw( x86_op_t *op, x86_insn_t *insn, void *arg ) {
   1090 	struct op_string * opstr = (struct op_string *) arg;
   1091 
   1092         format_operand_raw(op, insn, opstr->buf, opstr->len);
   1093 }
   1094 
   1095 static int format_insn_note(x86_insn_t *insn, char *buf, int len){
   1096 	char note[32] = {0};
   1097 	int len_orig = len, note_len = 32;
   1098 
   1099 	if ( insn->note & insn_note_ring0 ) {
   1100         	STRNCATF( note, "%s", "Ring0 ", note_len );
   1101 	}
   1102 	if ( insn->note & insn_note_smm ) {
   1103         	STRNCATF( note, "%s", "SMM ", note_len );
   1104 	}
   1105 	if ( insn->note & insn_note_serial ) {
   1106         	STRNCATF(note, "%s", "Serialize ", note_len );
   1107 	}
   1108         STRNCATF( buf, "%s|", note, len );
   1109 
   1110         return( len_orig - len );
   1111 }
   1112 
   1113 static int format_raw_insn( x86_insn_t *insn, char *buf, int len ){
   1114 	struct op_string opstr = { buf, len };
   1115         int i;
   1116 
   1117         /* RAW style:
   1118          * ADDRESS|OFFSET|SIZE|BYTES|
   1119          * PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|
   1120 	 * MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|
   1121 	 * STACK_MOD|STACK_MOD_VAL
   1122 	 * [|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*
   1123          *
   1124          * Register values are encoded as:
   1125          * NAME:TYPE:SIZE
   1126          *
   1127          * Effective addresses are encoded as:
   1128          * disp(base_reg,index_reg,scale)
   1129          */
   1130         STRNCATF( buf, "0x%08" PRIX32 "|", insn->addr  , len );
   1131         STRNCATF( buf, "0x%08" PRIX32 "|", insn->offset, len );
   1132         STRNCATF( buf, "%d|"    , insn->size  , len );
   1133 
   1134         /* print bytes */
   1135         for ( i = 0; i < insn->size; i++ ) {
   1136                 STRNCATF( buf, "%02X ", insn->bytes[i], len );
   1137         }
   1138         STRNCAT( buf, "|", len );
   1139 
   1140         len -= format_insn_prefix_str( insn->prefix, buf, len );
   1141         STRNCATF( buf, "|%s|", insn->prefix_string             , len );
   1142         STRNCATF( buf, "%s|", get_insn_group_str( insn->group ), len );
   1143         STRNCATF( buf, "%s|", get_insn_type_str( insn->type )  , len );
   1144         STRNCATF( buf, "%s|", insn->mnemonic                   , len );
   1145         STRNCATF( buf, "%s|", get_insn_cpu_str( insn->cpu )  , len );
   1146         STRNCATF( buf, "%s|", get_insn_isa_str( insn->isa )  , len );
   1147 
   1148 	/* insn note */
   1149 	len -= format_insn_note( insn, buf, len );
   1150 
   1151         len -= format_insn_eflags_str( insn->flags_set, buf, len );
   1152         STRNCAT( buf, "|", len );
   1153         len -= format_insn_eflags_str( insn->flags_tested, buf, len );
   1154         STRNCAT( buf, "|", len );
   1155         STRNCATF( buf, "%d|", insn->stack_mod, len );
   1156         STRNCATF( buf, "%" PRId32 "|", insn->stack_mod_val, len );
   1157 
   1158 	opstr.len = len;
   1159 	x86_operand_foreach( insn, format_op_raw, &opstr, op_any );
   1160 
   1161         return( strlen (buf) );
   1162 }
   1163 
   1164 static int format_xml_insn( x86_insn_t *insn, char *buf, int len ) {
   1165         char str[MAX_OP_XML_STRING];
   1166         int i;
   1167 
   1168         STRNCAT( buf, "<x86_insn>\n", len );
   1169 
   1170         STRNCATF( buf, "\t<address rva=\"0x%08" PRIX32 "\" ", insn->addr, len );
   1171         STRNCATF( buf, "offset=\"0x%08" PRIX32 "\" ", insn->offset, len );
   1172         STRNCATF( buf, "size=%d bytes=\"", insn->size, len );
   1173 
   1174         for ( i = 0; i < insn->size; i++ ) {
   1175                 STRNCATF( buf, "%02X ", insn->bytes[i], len );
   1176         }
   1177         STRNCAT( buf, "\"/>\n", len );
   1178 
   1179         STRNCAT( buf, "\t<prefix type=\"", len );
   1180         len -= format_insn_prefix_str( insn->prefix, buf, len );
   1181         STRNCATF( buf, "\" string=\"%s\"/>\n", insn->prefix_string, len );
   1182 
   1183         STRNCATF( buf, "\t<mnemonic group=\"%s\" ",
   1184                   get_insn_group_str (insn->group), len );
   1185         STRNCATF( buf, "type=\"%s\" ", get_insn_type_str (insn->type), len );
   1186         STRNCATF( buf, "string=\"%s\"/>\n", insn->mnemonic, len );
   1187 
   1188         STRNCAT( buf, "\t<flags type=set>\n", len );
   1189         STRNCAT( buf, "\t\t<flag name=\"", len );
   1190         len -= format_insn_eflags_str( insn->flags_set, buf, len );
   1191         STRNCAT( buf, "\"/>\n\t</flags>\n", len );
   1192 
   1193 
   1194         STRNCAT( buf, "\t<flags type=tested>\n", len );
   1195         STRNCAT( buf, "\t\t<flag name=\"", len );
   1196         len -= format_insn_eflags_str( insn->flags_tested, buf, len );
   1197         STRNCAT( buf, "\"/>\n\t</flags>\n", len );
   1198 
   1199 	if ( x86_operand_1st( insn ) ) {
   1200         	x86_format_operand( x86_operand_1st(insn), str,
   1201                            sizeof str, xml_syntax);
   1202         	STRNCAT( buf, "\t<operand name=dest>\n", len );
   1203         	STRNCAT( buf, str, len );
   1204         	STRNCAT( buf, "\t</operand>\n", len );
   1205 	}
   1206 
   1207 	if ( x86_operand_2nd( insn ) ) {
   1208         	x86_format_operand( x86_operand_2nd( insn ), str,
   1209                            sizeof str, xml_syntax);
   1210         	STRNCAT( buf, "\t<operand name=src>\n", len );
   1211         	STRNCAT( buf, str, len );
   1212         	STRNCAT( buf, "\t</operand>\n", len );
   1213 	}
   1214 
   1215 	if ( x86_operand_3rd( insn ) ) {
   1216         	x86_format_operand( x86_operand_3rd(insn), str,
   1217                            sizeof str, xml_syntax);
   1218         	STRNCAT( buf, "\t<operand name=imm>\n", len );
   1219         	STRNCAT( buf, str, len );
   1220         	STRNCAT( buf, "\t</operand>\n", len );
   1221 	}
   1222 
   1223         STRNCAT( buf, "</x86_insn>\n", len );
   1224 
   1225         return strlen (buf);
   1226 }
   1227 
   1228 int x86_format_header( char *buf, int len, enum x86_asm_format format ) {
   1229         switch (format) {
   1230                 case att_syntax:
   1231                         snprintf( buf, len, "MNEMONIC\tSRC, DEST, IMM" );
   1232                         break;
   1233                 case intel_syntax:
   1234                         snprintf( buf, len, "MNEMONIC\tDEST, SRC, IMM" );
   1235                         break;
   1236                 case native_syntax:
   1237                         snprintf( buf, len, "ADDRESS\tBYTES\tMNEMONIC\t"
   1238                                             "DEST\tSRC\tIMM" );
   1239                         break;
   1240                 case raw_syntax:
   1241                         snprintf( buf, len, "ADDRESS|OFFSET|SIZE|BYTES|"
   1242                                "PREFIX|PREFIX_STRING|GROUP|TYPE|NOTES|"
   1243 			       "MNEMONIC|CPU|ISA|FLAGS_SET|FLAGS_TESTED|"
   1244 			       "STACK_MOD|STACK_MOD_VAL"
   1245 			       "[|OP_TYPE|OP_DATATYPE|OP_ACCESS|OP_FLAGS|OP]*"
   1246                                 );
   1247                         break;
   1248                 case xml_syntax:
   1249                         snprintf( buf, len,
   1250                                   "<x86_insn>"
   1251                                       "<address rva= offset= size= bytes=/>"
   1252                                       "<prefix type= string=/>"
   1253                                       "<mnemonic group= type= string= "
   1254 				      "cpu= isa= note= />"
   1255                                       "<flags type=set>"
   1256                                           "<flag name=>"
   1257                                       "</flags>"
   1258 				      "<stack_mod val= >"
   1259                                       "<flags type=tested>"
   1260                                           "<flag name=>"
   1261                                       "</flags>"
   1262                                       "<operand name=>"
   1263                                           "<register name= type= size=/>"
   1264                                           "<immediate type= value=/>"
   1265                                           "<relative_offset value=/>"
   1266                                           "<absolute_address value=>"
   1267                                               "<segment value=/>"
   1268                                           "</absolute_address>"
   1269                                           "<address_expression>"
   1270                                               "<segment value=/>"
   1271                                               "<base>"
   1272                                                   "<register name= type= size=/>"
   1273                                               "</base>"
   1274                                               "<index>"
   1275                                                   "<register name= type= size=/>"
   1276                                               "</index>"
   1277                                               "<scale>"
   1278                                                   "<immediate value=/>"
   1279                                               "</scale>"
   1280                                               "<displacement>"
   1281                                                   "<immediate value=/>"
   1282                                                   "<address value=/>"
   1283                                               "</displacement>"
   1284                                           "</address_expression>"
   1285                                           "<segment_offset>"
   1286                                               "<address value=/>"
   1287                                           "</segment_offset>"
   1288                                       "</operand>"
   1289                                   "</x86_insn>"
   1290                                 );
   1291                         break;
   1292 		case unknown_syntax:
   1293 			if ( len ) {
   1294 				buf[0] = '\0';
   1295 			}
   1296 			break;
   1297         }
   1298 
   1299         return( strlen(buf) );
   1300 }
   1301 
   1302 int x86_format_insn( x86_insn_t *insn, char *buf, int len,
   1303                      enum x86_asm_format format ){
   1304         char str[MAX_OP_STRING];
   1305         x86_op_t *src, *dst;
   1306         int i;
   1307 
   1308         memset(buf, 0, len);
   1309         if ( format == intel_syntax ) {
   1310                 /* INTEL STYLE: mnemonic dest, src, imm */
   1311                 STRNCAT( buf, insn->prefix_string, len );
   1312                 STRNCAT( buf, insn->mnemonic, len );
   1313                 STRNCAT( buf, "\t", len );
   1314 
   1315                 /* dest */
   1316 		if ( (dst = x86_operand_1st( insn )) && !(dst->flags & op_implied) ) {
   1317         		x86_format_operand( dst, str, MAX_OP_STRING, format);
   1318                 	STRNCAT( buf, str, len );
   1319                 }
   1320 
   1321                 /* src */
   1322 		if ( (src = x86_operand_2nd( insn )) ) {
   1323                         if ( !(dst->flags & op_implied) ) {
   1324                 	        STRNCAT( buf, ", ", len );
   1325                         }
   1326         		x86_format_operand( src, str, MAX_OP_STRING, format);
   1327                 	STRNCAT( buf, str, len );
   1328                 }
   1329 
   1330                 /* imm */
   1331 		if ( x86_operand_3rd( insn )) {
   1332                 	STRNCAT( buf, ", ", len );
   1333         		x86_format_operand( x86_operand_3rd( insn ),
   1334 				str, MAX_OP_STRING, format);
   1335                 	STRNCAT( buf, str, len );
   1336 		}
   1337 
   1338         } else if ( format == att_syntax ) {
   1339                 /* ATT STYLE: mnemonic src, dest, imm */
   1340                 STRNCAT( buf, insn->prefix_string, len );
   1341                 format_att_mnemonic(insn, str, MAX_OP_STRING);
   1342                 STRNCATF( buf, "%s\t", str, len);
   1343 
   1344 
   1345 		/* not sure which is correct? sometimes GNU as requires
   1346 		 * an imm as the first operand, sometimes as the third... */
   1347                 /* imm */
   1348 		if ( x86_operand_3rd( insn ) ) {
   1349         		x86_format_operand(x86_operand_3rd( insn ),
   1350 				str, MAX_OP_STRING, format);
   1351                 	STRNCAT( buf, str, len );
   1352 			/* there is always 'dest' operand if there is 'src' */
   1353 			STRNCAT( buf, ", ", len );
   1354 		}
   1355 
   1356                 if ( (insn->note & insn_note_nonswap ) == 0 ) {
   1357                         /* regular AT&T style swap */
   1358                         src = x86_operand_2nd( insn );
   1359                         dst = x86_operand_1st( insn );
   1360                 }
   1361                 else {
   1362                         /* special-case instructions */
   1363                         src = x86_operand_1st( insn );
   1364                         dst = x86_operand_2nd( insn );
   1365                 }
   1366 
   1367                 /* src */
   1368                 if ( src ) {
   1369                         x86_format_operand(src, str, MAX_OP_STRING, format);
   1370                         STRNCAT( buf, str, len );
   1371                         /* there is always 'dest' operand if there is 'src' */
   1372                         if ( dst && !(dst->flags & op_implied) ) {
   1373                                 STRNCAT( buf, ", ", len );
   1374                         }
   1375                 }
   1376 
   1377                 /* dest */
   1378                 if ( dst && !(dst->flags & op_implied) ) {
   1379                         x86_format_operand( dst, str, MAX_OP_STRING, format);
   1380                         STRNCAT( buf, str, len );
   1381                 }
   1382 
   1383 
   1384         } else if ( format == raw_syntax ) {
   1385                 format_raw_insn( insn, buf, len );
   1386         } else if ( format == xml_syntax ) {
   1387                 format_xml_insn( insn, buf, len );
   1388         } else { /* default to native */
   1389                 /* NATIVE style: RVA\tBYTES\tMNEMONIC\tOPERANDS */
   1390                 /* print address */
   1391                 STRNCATF( buf, "%08" PRIX32 "\t", insn->addr, len );
   1392 
   1393                 /* print bytes */
   1394                 for ( i = 0; i < insn->size; i++ ) {
   1395                         STRNCATF( buf, "%02X ", insn->bytes[i], len );
   1396                 }
   1397 
   1398                 STRNCAT( buf, "\t", len );
   1399 
   1400                 /* print mnemonic */
   1401                 STRNCAT( buf, insn->prefix_string, len );
   1402                 STRNCAT( buf, insn->mnemonic, len );
   1403                 STRNCAT( buf, "\t", len );
   1404 
   1405                 /* print operands */
   1406                 /* dest */
   1407 		if ( x86_operand_1st( insn )  ) {
   1408         		x86_format_operand( x86_operand_1st( insn ),
   1409 				str, MAX_OP_STRING, format);
   1410                 	STRNCATF( buf, "%s\t", str, len );
   1411 		}
   1412 
   1413                 /* src */
   1414 		if ( x86_operand_2nd( insn ) ) {
   1415         		x86_format_operand(x86_operand_2nd( insn ),
   1416 				str, MAX_OP_STRING, format);
   1417                 	STRNCATF( buf, "%s\t", str, len );
   1418 		}
   1419 
   1420                 /* imm */
   1421 		if ( x86_operand_3rd( insn )) {
   1422         		x86_format_operand( x86_operand_3rd( insn ),
   1423 				str, MAX_OP_STRING, format);
   1424                 	STRNCAT( buf, str, len );
   1425 		}
   1426         }
   1427 
   1428         return( strlen( buf ) );
   1429 }
   1430 
   1431