Home | History | Annotate | Download | only in libdisasm
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include "qword.h"
      5 
      6 #include "ia32_insn.h"
      7 #include "ia32_opcode_tables.h"
      8 
      9 #include "ia32_reg.h"
     10 #include "ia32_operand.h"
     11 #include "ia32_implicit.h"
     12 #include "ia32_settings.h"
     13 
     14 #include "libdis.h"
     15 
     16 extern ia32_table_desc_t ia32_tables[];
     17 extern ia32_settings_t ia32_settings;
     18 
     19 #define IS_SP( op )  (op->type == op_register && 	\
     20 		(op->data.reg.id == REG_ESP_INDEX || 	\
     21 		 op->data.reg.alias == REG_ESP_INDEX) )
     22 #define IS_IMM( op ) (op->type == op_immediate )
     23 
     24 #ifdef WIN32
     25 #  define INLINE
     26 #else
     27 #  define INLINE inline
     28 #endif
     29 
     30 /* for calculating stack modification based on an operand */
     31 static INLINE int32_t long_from_operand( x86_op_t *op ) {
     32 
     33 	if (! IS_IMM(op) ) {
     34 		return 0L;
     35 	}
     36 
     37 	switch ( op->datatype ) {
     38 		case op_byte:
     39 			return (int32_t) op->data.sbyte;
     40 		case op_word:
     41 			return (int32_t) op->data.sword;
     42 		case op_qword:
     43 			return (int32_t) op->data.sqword;
     44 		case op_dword:
     45 			return op->data.sdword;
     46 		default:
     47 			/* these are not used in stack insn */
     48 			break;
     49 	}
     50 
     51 	return 0L;
     52 }
     53 
     54 
     55 /* determine what this insn does to the stack */
     56 static void ia32_stack_mod(x86_insn_t *insn) {
     57 	x86_op_t *dest, *src = NULL;
     58 
     59 	if (! insn || ! insn->operands ) {
     60 		return;
     61 	}
     62 
     63 	dest = &insn->operands->op;
     64 	if ( dest ) {
     65 		src = &insn->operands->next->op;
     66 	}
     67 
     68 	insn->stack_mod = 0;
     69 	insn->stack_mod_val = 0;
     70 
     71 	switch ( insn->type ) {
     72 		case insn_call:
     73 		case insn_callcc:
     74 			insn->stack_mod = 1;
     75 			insn->stack_mod_val = insn->addr_size * -1;
     76 			break;
     77 		case insn_push:
     78 			insn->stack_mod = 1;
     79 			insn->stack_mod_val = insn->addr_size * -1;
     80 			break;
     81 		case insn_return:
     82 			insn->stack_mod = 1;
     83 			insn->stack_mod_val = insn->addr_size;
     84 		case insn_int: case insn_intcc:
     85 		case insn_iret:
     86 			break;
     87 		case insn_pop:
     88 			insn->stack_mod = 1;
     89 			if (! IS_SP( dest ) ) {
     90 				insn->stack_mod_val = insn->op_size;
     91 			} /* else we don't know the stack change in a pop esp */
     92 			break;
     93 		case insn_enter:
     94 			insn->stack_mod = 1;
     95 			insn->stack_mod_val = 0; /* TODO : FIX */
     96 			break;
     97 		case insn_leave:
     98 			insn->stack_mod = 1;
     99 			insn->stack_mod_val = 0; /* TODO : FIX */
    100 			break;
    101 		case insn_pushregs:
    102 			insn->stack_mod = 1;
    103 			insn->stack_mod_val = 0; /* TODO : FIX */
    104 			break;
    105 		case insn_popregs:
    106 			insn->stack_mod = 1;
    107 			insn->stack_mod_val = 0; /* TODO : FIX */
    108 			break;
    109 		case insn_pushflags:
    110 			insn->stack_mod = 1;
    111 			insn->stack_mod_val = 0; /* TODO : FIX */
    112 			break;
    113 		case insn_popflags:
    114 			insn->stack_mod = 1;
    115 			insn->stack_mod_val = 0; /* TODO : FIX */
    116 			break;
    117 		case insn_add:
    118 			if ( IS_SP( dest ) ) {
    119 				insn->stack_mod = 1;
    120 				insn->stack_mod_val = long_from_operand( src );
    121 			}
    122 			break;
    123 		case insn_sub:
    124 			if ( IS_SP( dest ) ) {
    125 				insn->stack_mod = 1;
    126 				insn->stack_mod_val = long_from_operand( src );
    127 				insn->stack_mod_val *= -1;
    128 			}
    129 			break;
    130 		case insn_inc:
    131 			if ( IS_SP( dest ) ) {
    132 				insn->stack_mod = 1;
    133 				insn->stack_mod_val = 1;
    134 			}
    135 			break;
    136 		case insn_dec:
    137 			if ( IS_SP( dest ) ) {
    138 				insn->stack_mod = 1;
    139 				insn->stack_mod_val = 1;
    140 			}
    141 			break;
    142 		case insn_mov: case insn_movcc:
    143 		case insn_xchg: case insn_xchgcc:
    144 		case insn_mul: case insn_div:
    145 		case insn_shl: case insn_shr:
    146 		case insn_rol: case insn_ror:
    147 		case insn_and: case insn_or:
    148 		case insn_not: case insn_neg:
    149 		case insn_xor:
    150 			if ( IS_SP( dest ) ) {
    151 				insn->stack_mod = 1;
    152 			}
    153 			break;
    154 		default:
    155 			break;
    156 	}
    157 	if (! strcmp("enter", insn->mnemonic) ) {
    158 		insn->stack_mod = 1;
    159 	} else if (! strcmp("leave", insn->mnemonic) ) {
    160 		insn->stack_mod = 1;
    161 	}
    162 
    163 	/* for mov, etc we return 0 -- unknown stack mod */
    164 
    165 	return;
    166 }
    167 
    168 /* get the cpu details for this insn from cpu flags int */
    169 static void ia32_handle_cpu( x86_insn_t *insn, unsigned int cpu ) {
    170 	insn->cpu = (enum x86_insn_cpu) CPU_MODEL(cpu);
    171 	insn->isa = (enum x86_insn_isa) (ISA_SUBSET(cpu)) >> 16;
    172 	return;
    173 }
    174 
    175 /* handle mnemonic type and group */
    176 static void ia32_handle_mnemtype(x86_insn_t *insn, unsigned int mnemtype) {
    177 	unsigned int type = mnemtype & ~INS_FLAG_MASK;
    178         insn->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12;
    179         insn->type = (enum x86_insn_type) INS_TYPE(type);
    180 
    181 	return;
    182 }
    183 
    184 static void ia32_handle_notes(x86_insn_t *insn, unsigned int notes) {
    185 	insn->note = (enum x86_insn_note) notes;
    186 	return;
    187 }
    188 
    189 static void ia32_handle_eflags( x86_insn_t *insn, unsigned int eflags) {
    190         unsigned int flags;
    191 
    192         /* handle flags effected */
    193         flags = INS_FLAGS_TEST(eflags);
    194         /* handle weird OR cases */
    195         /* these are either JLE (ZF | SF<>OF) or JBE (CF | ZF) */
    196         if (flags & INS_TEST_OR) {
    197                 flags &= ~INS_TEST_OR;
    198                 if ( flags & INS_TEST_ZERO ) {
    199                         flags &= ~INS_TEST_ZERO;
    200                         if ( flags & INS_TEST_CARRY ) {
    201                                 flags &= ~INS_TEST_CARRY ;
    202                                 flags |= (int)insn_carry_or_zero_set;
    203                         } else if ( flags & INS_TEST_SFNEOF ) {
    204                                 flags &= ~INS_TEST_SFNEOF;
    205                                 flags |= (int)insn_zero_set_or_sign_ne_oflow;
    206                         }
    207                 }
    208         }
    209         insn->flags_tested = (enum x86_flag_status) flags;
    210 
    211         insn->flags_set = (enum x86_flag_status) INS_FLAGS_SET(eflags) >> 16;
    212 
    213 	return;
    214 }
    215 
    216 static void ia32_handle_prefix( x86_insn_t *insn, unsigned int prefixes ) {
    217 
    218         insn->prefix = (enum x86_insn_prefix) prefixes & PREFIX_MASK; // >> 20;
    219         if (! (insn->prefix & PREFIX_PRINT_MASK) ) {
    220 		/* no printable prefixes */
    221                 insn->prefix = insn_no_prefix;
    222         }
    223 
    224         /* concat all prefix strings */
    225         if ( (unsigned int)insn->prefix & PREFIX_LOCK ) {
    226                 strncat(insn->prefix_string, "lock ", 32 -
    227 				strlen(insn->prefix_string));
    228         }
    229 
    230         if ( (unsigned int)insn->prefix & PREFIX_REPNZ ) {
    231                 strncat(insn->prefix_string, "repnz ", 32  -
    232 				strlen(insn->prefix_string));
    233         } else if ( (unsigned int)insn->prefix & PREFIX_REPZ ) {
    234                 strncat(insn->prefix_string, "repz ", 32 -
    235 				strlen(insn->prefix_string));
    236         }
    237 
    238         return;
    239 }
    240 
    241 
    242 static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
    243 
    244 	/* if this is a 32-bit register and it is a general register ... */
    245 	if ( op->type == op_register && op->data.reg.size == 4 &&
    246 	     (op->data.reg.type & reg_gen) ) {
    247 		/* WORD registers are 8 indices off from DWORD registers */
    248 		ia32_handle_register( &(op->data.reg),
    249 				op->data.reg.id + 8 );
    250 	}
    251 }
    252 
    253 static void handle_insn_metadata( x86_insn_t *insn, ia32_insn_t *raw_insn ) {
    254 	ia32_handle_mnemtype( insn, raw_insn->mnem_flag );
    255 	ia32_handle_notes( insn, raw_insn->notes );
    256 	ia32_handle_eflags( insn, raw_insn->flags_effected );
    257 	ia32_handle_cpu( insn, raw_insn->cpu );
    258 	ia32_stack_mod( insn );
    259 }
    260 
    261 static size_t ia32_decode_insn( unsigned char *buf, size_t buf_len,
    262 			   ia32_insn_t *raw_insn, x86_insn_t *insn,
    263 			   unsigned int prefixes ) {
    264 	size_t size, op_size;
    265 	unsigned char modrm;
    266 
    267 	/* this should never happen, but just in case... */
    268 	if ( raw_insn->mnem_flag == INS_INVALID ) {
    269 		return 0;
    270 	}
    271 
    272 	if (ia32_settings.options & opt_16_bit) {
    273 		insn->op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
    274 		insn->addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
    275 	} else {
    276 		insn->op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
    277 		insn->addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
    278 	}
    279 
    280 
    281 	/*  ++++   1. Copy mnemonic and mnemonic-flags to CODE struct */
    282 	if ((ia32_settings.options & opt_att_mnemonics) && raw_insn->mnemonic_att[0]) {
    283 		strncpy( insn->mnemonic, raw_insn->mnemonic_att, 16 );
    284 	}
    285 	else {
    286 		strncpy( insn->mnemonic, raw_insn->mnemonic, 16 );
    287 	}
    288 	ia32_handle_prefix( insn, prefixes );
    289 
    290 	handle_insn_metadata( insn, raw_insn );
    291 
    292 	/* prefetch the next byte in case it is a modr/m byte -- saves
    293 	 * worrying about whether the 'mod/rm' operand or the 'reg' operand
    294 	 * occurs first */
    295 	modrm = GET_BYTE( buf, buf_len );
    296 
    297 	/*  ++++   2. Decode Explicit Operands */
    298 	/* Intel uses up to 3 explicit operands in its instructions;
    299 	 * the first is 'dest', the second is 'src', and the third
    300 	 * is an additional source value (usually an immediate value,
    301 	 * e.g. in the MUL instructions). These three explicit operands
    302 	 * are encoded in the opcode tables, even if they are not used
    303 	 * by the instruction. Additional implicit operands are stored
    304 	 * in a supplemental table and are handled later. */
    305 
    306 	op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->dest,
    307 					raw_insn->dest_flag, prefixes, modrm );
    308 	/* advance buffer, increase size if necessary */
    309 	buf += op_size;
    310 	buf_len -= op_size;
    311 	size = op_size;
    312 
    313 	op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->src,
    314 					raw_insn->src_flag, prefixes, modrm );
    315 	buf += op_size;
    316 	buf_len -= op_size;
    317 	size += op_size;
    318 
    319 	op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->aux,
    320 					raw_insn->aux_flag, prefixes, modrm );
    321 	size += op_size;
    322 
    323 
    324 	/*  ++++   3. Decode Implicit Operands */
    325 	/* apply implicit operands */
    326 	ia32_insn_implicit_ops( insn, raw_insn->implicit_ops );
    327 	/* we have one small inelegant hack here, to deal with
    328 	 * the two prefixes that have implicit operands. If Intel
    329 	 * adds more, we'll change the algorithm to suit :) */
    330 	if ( (prefixes & PREFIX_REPZ) || (prefixes & PREFIX_REPNZ) ) {
    331 		ia32_insn_implicit_ops( insn, IDX_IMPLICIT_REP );
    332 	}
    333 
    334 
    335 	/* 16-bit hack: foreach operand, if 32-bit reg, make 16-bit reg */
    336 	if ( insn->op_size == 2 ) {
    337 		x86_operand_foreach( insn, reg_32_to_16, NULL, op_any );
    338 	}
    339 
    340 	return size;
    341 }
    342 
    343 
    344 /* convenience routine */
    345 #define USES_MOD_RM(flag) \
    346 	(flag == ADDRMETH_E || flag == ADDRMETH_M || flag == ADDRMETH_Q || \
    347 	 flag == ADDRMETH_W || flag == ADDRMETH_R)
    348 
    349 static int uses_modrm_flag( unsigned int flag ) {
    350 	unsigned int meth;
    351 	if ( flag == ARG_NONE ) {
    352 		return 0;
    353 	}
    354 	meth = (flag & ADDRMETH_MASK);
    355 	if ( USES_MOD_RM(meth) ) {
    356 		return 1;
    357 	}
    358 
    359 	return 0;
    360 }
    361 
    362 /* This routine performs the actual byte-by-byte opcode table lookup.
    363  * Originally it was pretty simple: get a byte, adjust it to a proper
    364  * index into the table, then check the table row at that index to
    365  * determine what to do next. But is anything that simple with Intel?
    366  * This is now a huge, convoluted mess, mostly of bitter comments. */
    367 /* buf: pointer to next byte to read from stream
    368  * buf_len: length of buf
    369  * table: index of table to use for lookups
    370  * raw_insn: output pointer that receives opcode definition
    371  * prefixes: output integer that is encoded with prefixes in insn
    372  * returns : number of bytes consumed from stream during lookup */
    373 size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
    374 				 unsigned int table, ia32_insn_t **raw_insn,
    375 				 unsigned int *prefixes ) {
    376 	unsigned char *next, op = buf[0];	/* byte value -- 'opcode' */
    377 	size_t size = 1, sub_size = 0, next_len;
    378 	ia32_table_desc_t *table_desc;
    379 	unsigned int subtable, prefix = 0, recurse_table = 0;
    380 
    381 	table_desc = &ia32_tables[table];
    382 
    383 	op = GET_BYTE( buf, buf_len );
    384 
    385 	if ( table_desc->type == tbl_fpu && op > table_desc->maxlim) {
    386 		/* one of the fucking FPU tables out of the 00-BH range */
    387 		/* OK,. this is a bit of a hack -- the proper way would
    388 		 * have been to use subtables in the 00-BF FPU opcode tables,
    389 		 * but that is rather wasteful of space... */
    390 		table_desc = &ia32_tables[table +1];
    391 	}
    392 
    393 	/* PERFORM TABLE LOOKUP */
    394 
    395 	/* ModR/M trick: shift extension bits into lowest bits of byte */
    396 	/* Note: non-ModR/M tables have a shift value of 0 */
    397 	op >>= table_desc->shift;
    398 
    399 	/* ModR/M trick: mask out high bits to turn extension into an index */
    400 	/* Note: non-ModR/M tables have a mask value of 0xFF */
    401 	op &= table_desc->mask;
    402 
    403 
    404 	/* Sparse table trick: check that byte is <= max value */
    405 	/* Note: full (256-entry) tables have a maxlim of 155 */
    406 	if ( op > table_desc->maxlim ) {
    407 		/* this is a partial table, truncated at the tail,
    408 		   and op is out of range! */
    409 		return INVALID_INSN;
    410 	}
    411 
    412 	/* Sparse table trick: check that byte is >= min value */
    413 	/* Note: full (256-entry) tables have a minlim of 0 */
    414 	if ( table_desc->minlim > op ) {
    415 		/* this is a partial table, truncated at the head,
    416 		   and op is out of range! */
    417 		return INVALID_INSN;
    418 	}
    419 	/* adjust op to be an offset from table index 0 */
    420 	op -= table_desc->minlim;
    421 
    422 	/* Yay! 'op' is now fully adjusted to be an index into 'table' */
    423 	*raw_insn = &(table_desc->table[op]);
    424 	//printf("BYTE %X TABLE %d OP %X\n", buf[0], table, op );
    425 
    426 	if ( (*raw_insn)->mnem_flag & INS_FLAG_PREFIX ) {
    427 		prefix = (*raw_insn)->mnem_flag & PREFIX_MASK;
    428 	}
    429 
    430 
    431 	/* handle escape to a multibyte/coproc/extension/etc table */
    432 	/* NOTE: if insn is a prefix and has a subtable, then we
    433 	 *       only recurse if this is the first prefix byte --
    434 	 *       that is, if *prefixes is 0.
    435 	 * NOTE also that suffix tables are handled later */
    436 	subtable = (*raw_insn)->table;
    437 
    438 	if ( subtable && ia32_tables[subtable].type != tbl_suffix &&
    439 	     (! prefix || ! *prefixes) ) {
    440 
    441 	     	if ( ia32_tables[subtable].type == tbl_ext_ext ||
    442 	     	     ia32_tables[subtable].type == tbl_fpu_ext ) {
    443 			/* opcode extension: reuse current byte in buffer */
    444 			next = buf;
    445 			next_len = buf_len;
    446 		} else {
    447 			/* "normal" opcode: advance to next byte in buffer */
    448 			if ( buf_len > 1 ) {
    449 				next = &buf[1];
    450 				next_len = buf_len - 1;
    451 			}
    452 			else {
    453 				// buffer is truncated
    454 				return INVALID_INSN;
    455 			}
    456 		}
    457 		/* we encountered a multibyte opcode: recurse using the
    458 		 * table specified in the opcode definition */
    459 		sub_size = ia32_table_lookup( next, next_len, subtable,
    460 				raw_insn, prefixes );
    461 
    462 		/* SSE/prefix hack: if the original opcode def was a
    463 		 * prefix that specified a subtable, and the subtable
    464 		 * lookup returned a valid insn, then we have encountered
    465 		 * an SSE opcode definition; otherwise, we pretend we
    466 		 * never did the subtable lookup, and deal with the
    467 		 * prefix normally later */
    468 		if ( prefix && ( sub_size == INVALID_INSN  ||
    469 		       INS_TYPE((*raw_insn)->mnem_flag) == INS_INVALID ) ) {
    470 			/* this is a prefix, not an SSE insn :
    471 			 * lookup next byte in main table,
    472 			 * subsize will be reset during the
    473 			 * main table lookup */
    474 			recurse_table = 1;
    475 		} else {
    476 			/* this is either a subtable (two-byte) insn
    477 			 * or an invalid insn: either way, set prefix
    478 			 * to NULL and end the opcode lookup */
    479 			prefix = 0;
    480 			// short-circuit lookup on invalid insn
    481 			if (sub_size == INVALID_INSN) return INVALID_INSN;
    482 		}
    483 	} else if ( prefix ) {
    484 		recurse_table = 1;
    485 	}
    486 
    487 	/* by default, we assume that we have the opcode definition,
    488 	 * and there is no need to recurse on the same table, but
    489 	 * if we do then a prefix was encountered... */
    490 	if ( recurse_table ) {
    491 		/* this must have been a prefix: use the same table for
    492 		 * lookup of the next byte */
    493 		sub_size = ia32_table_lookup( &buf[1], buf_len - 1, table,
    494 				raw_insn, prefixes );
    495 
    496 		// short-circuit lookup on invalid insn
    497 		if (sub_size == INVALID_INSN) return INVALID_INSN;
    498 
    499 		/* a bit of a hack for branch hints */
    500 		if ( prefix & BRANCH_HINT_MASK ) {
    501 			if ( INS_GROUP((*raw_insn)->mnem_flag) == INS_EXEC ) {
    502 				/* segment override prefixes are invalid for
    503 			 	* all branch instructions, so delete them */
    504 				prefix &= ~PREFIX_REG_MASK;
    505 			} else {
    506 				prefix &= ~BRANCH_HINT_MASK;
    507 			}
    508 		}
    509 
    510 		/* apply prefix to instruction */
    511 
    512 		/* TODO: implement something enforcing prefix groups */
    513 		(*prefixes) |= prefix;
    514 	}
    515 
    516 	/* if this lookup was in a ModR/M table, then an opcode byte is
    517 	 * NOT consumed: subtract accordingly. NOTE that if none of the
    518 	 * operands used the ModR/M, then we need to consume the byte
    519 	 * here, but ONLY in the 'top-level' opcode extension table */
    520 
    521 	if ( table_desc->type == tbl_ext_ext ) {
    522 		/* extensions-to-extensions never consume a byte */
    523 		--size;
    524 	} else if ( (table_desc->type == tbl_extension ||
    525 	       	     table_desc->type == tbl_fpu ||
    526 		     table_desc->type == tbl_fpu_ext ) &&
    527 		/* extensions that have an operand encoded in ModR/M
    528 		 * never consume a byte */
    529 	      	    (uses_modrm_flag((*raw_insn)->dest_flag) ||
    530 	             uses_modrm_flag((*raw_insn)->src_flag) )  	) {
    531 		--size;
    532 	}
    533 
    534 	size += sub_size;
    535 
    536 	return size;
    537 }
    538 
    539 static size_t handle_insn_suffix( unsigned char *buf, size_t buf_len,
    540 			   ia32_insn_t *raw_insn, x86_insn_t * insn ) {
    541 	ia32_insn_t *sfx_insn;
    542 	size_t size;
    543 	unsigned int prefixes = 0;
    544 
    545 	size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
    546 				 &prefixes );
    547 	if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {
    548 		return 0;
    549 	}
    550 
    551 	strncpy( insn->mnemonic, sfx_insn->mnemonic, 16 );
    552 	handle_insn_metadata( insn, sfx_insn );
    553 
    554 	return 1;
    555 }
    556 
    557 /* invalid instructions are handled by returning 0 [error] from the
    558  * function, setting the size of the insn to 1 byte, and copying
    559  * the byte at the start of the invalid insn into the x86_insn_t.
    560  * if the caller is saving the x86_insn_t for invalid instructions,
    561  * instead of discarding them, this will maintain a consistent
    562  * address space in the x86_insn_ts */
    563 
    564 /* this function is called by the controlling disassembler, so its name and
    565  * calling convention cannot be changed */
    566 /*    buf   points to the loc of the current opcode (start of the
    567  *          instruction) in the instruction stream. The instruction
    568  *          stream is assumed to be a buffer of bytes read directly
    569  *          from the file for the purpose of disassembly; a mem-mapped
    570  *          file is ideal for *        this.
    571  *    insn points to a code structure to be filled by instr_decode
    572  *    returns the size of the decoded instruction in bytes */
    573 size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len,
    574 		x86_insn_t *insn ) {
    575 	ia32_insn_t *raw_insn = NULL;
    576 	unsigned int prefixes = 0;
    577 	size_t size, sfx_size;
    578 
    579 	if ( (ia32_settings.options & opt_ignore_nulls) && buf_len > 3 &&
    580 	    !buf[0] && !buf[1] && !buf[2] && !buf[3]) {
    581 		/* IF IGNORE_NULLS is set AND
    582 		 * first 4 bytes in the intruction stream are NULL
    583 		 * THEN return 0 (END_OF_DISASSEMBLY) */
    584 		/* TODO: set errno */
    585 		MAKE_INVALID( insn, buf );
    586 		return 0;	/* 4 00 bytes in a row? This isn't code! */
    587 	}
    588 
    589 	/* Perform recursive table lookup starting with main table (0) */
    590 	size = ia32_table_lookup(buf, buf_len, idx_Main, &raw_insn, &prefixes);
    591 	if ( size == INVALID_INSN || size > buf_len || raw_insn->mnem_flag == INS_INVALID ) {
    592 		MAKE_INVALID( insn, buf );
    593 		/* TODO: set errno */
    594 		return 0;
    595 	}
    596 
    597 	/* We now have the opcode itself figured out: we can decode
    598 	 * the rest of the instruction. */
    599 	size += ia32_decode_insn( &buf[size], buf_len - size, raw_insn, insn,
    600 				  prefixes );
    601 	if ( raw_insn->mnem_flag & INS_FLAG_SUFFIX ) {
    602 		/* AMD 3DNow! suffix -- get proper operand type here */
    603 		sfx_size = handle_insn_suffix( &buf[size], buf_len - size,
    604 				raw_insn, insn );
    605 		if (! sfx_size ) {
    606 			/* TODO: set errno */
    607 			MAKE_INVALID( insn, buf );
    608 			return 0;
    609 		}
    610 
    611 		size += sfx_size;
    612 	}
    613 
    614 	if (! size ) {
    615 		/* invalid insn */
    616 		MAKE_INVALID( insn, buf );
    617 		return 0;
    618 	}
    619 
    620 
    621 	insn->size = size;
    622 	return size;		/* return size of instruction in bytes */
    623 }
    624