ia32_insn.h 19.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
#ifndef IA32_INSN_H
#define IA32_INSN_H
/* this file contains the structure of opcode definitions and the
 * constants they use */

#include <sys/types.h>
#include "libdis.h"


#define GET_BYTE( buf, buf_len ) buf_len ? *buf : 0

#define OP_SIZE_16	1
#define OP_SIZE_32	2
#define ADDR_SIZE_16	4
#define ADDR_SIZE_32	8

#define MAX_INSTRUCTION_SIZE 20

/* invalid instructions are handled by returning 0 [error] from the
 * function, setting the size of the insn to 1 byte, and copying
 * the byte at the start of the invalid insn into the x86_insn_t.
 * if the caller is saving the x86_insn_t for invalid instructions,
 * instead of discarding them, this will maintain a consistent
 * address space in the x86_insn_ts */

#define INVALID_INSN ((size_t) -1)	/* return value for invalid insn */
#define MAKE_INVALID( i, buf )                          \
                strcpy( i->mnemonic, "invalid" );       \
                x86_oplist_free( i );                   \
                i->size = 1;                            \
                i->group = insn_none;                   \
                i->type = insn_invalid;                 \
                memcpy( i->bytes, buf, 1 );


size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len, 
		x86_insn_t *insn);


/* --------------------------------------------------------- Table Lookup */
/* IA32 Instruction defintion for ia32_opcodes.c */
typedef struct {
   unsigned int table;          /* escape to this sub-table */
   unsigned int mnem_flag;      /* Flags referring to mnemonic */
   unsigned int notes;          /* Notes for this instruction */
   unsigned int dest_flag, src_flag, aux_flag; /* and for specific operands */
   unsigned int cpu;            /* minimumCPU [AND with clocks?? */
   char mnemonic[16];           /* buffers for building instruction */
   char mnemonic_att[16];       /* at&t style mnemonic name */
   int32_t dest;
   int32_t src;
   int32_t aux;
   unsigned int flags_effected;
   unsigned int implicit_ops;	/* implicit operands */
} ia32_insn_t;



/* --------------------------------------------------------- Prefixes */
/* Prefix Flags */
/* Prefixes, same order as in the manual */
/* had to reverse the values of the first three as they were entered into
 * libdis.h incorrectly. */
#define PREFIX_LOCK       0x0004
#define PREFIX_REPNZ      0x0002
#define PREFIX_REPZ       0x0001
#define PREFIX_OP_SIZE    0x0010
#define PREFIX_ADDR_SIZE  0x0020
#define PREFIX_CS         0x0100
#define PREFIX_SS         0x0200
#define PREFIX_DS         0x0300
#define PREFIX_ES         0x0400
#define PREFIX_FS         0x0500
#define PREFIX_GS         0x0600
#define PREFIX_TAKEN      0x1000	/* branch taken */
#define PREFIX_NOTTAKEN   0x2000	/* branch not taken */
#define PREFIX_REG_MASK   0x0F00
#define BRANCH_HINT_MASK  0x3000 
#define PREFIX_PRINT_MASK 0x000F	/* printable prefixes */
#define PREFIX_MASK       0xFFFF

/* ---------------------------------------------------------- CPU Type */

#define cpu_8086         0x0001
#define cpu_80286        0x0002
#define cpu_80386        0x0003
#define cpu_80387        0x0004 /* originally these were a co-proc */
#define cpu_80486        0x0005
#define cpu_PENTIUM      0x0006
#define cpu_PENTPRO      0x0007
#define cpu_PENTIUM2     0x0008
#define cpu_PENTIUM3     0x0009
#define cpu_PENTIUM4     0x000A
#define cpu_K6		 0x0010
#define cpu_K7		 0x0020
#define cpu_ATHLON	 0x0030
#define CPU_MODEL_MASK	 0xFFFF
#define CPU_MODEL(cpu)	 (cpu & CPU_MODEL_MASK)
/* intel instruction subsets */
#define isa_GP		 0x10000	/* General Purpose Instructions */
#define isa_FPU		 0x20000	/* FPU instructions */
#define isa_FPUMGT	 0x30000	/* FPU/SIMD Management */
#define isa_MMX		 0x40000	/* MMX */
#define isa_SSE1	 0x50000	/* SSE */
#define isa_SSE2	 0x60000	/* SSE 2 */
#define isa_SSE3	 0x70000	/* SSE 3 */
#define isa_3DNOW	 0x80000	/* AMD 3d Now */
#define isa_SYS		 0x90000	/* System Instructions */
#define ISA_SUBSET_MASK	 0xFFFF0000
#define ISA_SUBSET(isa)	(isa & ISA_SUBSET_MASK)


/* ------------------------------------------------------ Operand Decoding */
#define ARG_NONE         0

/* Using a mask allows us to store info such as OP_SIGNED in the
 * operand flags field */
#define   OPFLAGS_MASK 	0x0000FFFF

/* Operand Addressing Methods, per intel manual */
#define   ADDRMETH_MASK	0x00FF0000

/* note: for instructions with implied operands, use no ADDRMETH */
#define   ADDRMETH_A  	0x00010000   
#define   ADDRMETH_C   	0x00020000
#define   ADDRMETH_D   	0x00030000
#define   ADDRMETH_E   	0x00040000
#define   ADDRMETH_F   	0x00050000
#define   ADDRMETH_G   	0x00060000
#define   ADDRMETH_I   	0x00070000
#define   ADDRMETH_J   	0x00080000
#define   ADDRMETH_M   	0x00090000
#define   ADDRMETH_O   	0x000A0000
#define   ADDRMETH_P   	0x000B0000
#define   ADDRMETH_Q   	0x000C0000
#define   ADDRMETH_R   	0x000D0000
#define   ADDRMETH_S   	0x000E0000
#define   ADDRMETH_T   	0x000F0000
#define   ADDRMETH_V   	0x00100000
#define   ADDRMETH_W   	0x00110000
#define   ADDRMETH_X   	0x00120000
#define   ADDRMETH_Y   	0x00130000
#define	  ADDRMETH_RR  	0x00140000	/* gen reg hard-coded in opcode */
#define	  ADDRMETH_RS  	0x00150000	/* seg reg hard-coded in opcode */
#define	  ADDRMETH_RT  	0x00160000	/* test reg hard-coded in opcode */
#define	  ADDRMETH_RF  	0x00170000	/* fpu reg hard-coded in opcode */
#define	  ADDRMETH_II  	0x00180000	/* immediate hard-coded in opcode */
#define   ADDRMETH_PP   0x00190000	/* mm reg ONLY in modr/m field */
#define   ADDRMETH_VV   0x001A0000	/* xmm reg ONLY in mod/rm field */

/* Operand Types, per intel manual */
#define OPTYPE_MASK	0xFF000000

#define OPTYPE_a	0x01000000 /* BOUND: h:h or w:w */
#define OPTYPE_b   	0x02000000 /* byte */
#define OPTYPE_c   	0x03000000 /* byte or word */
#define OPTYPE_d   	0x04000000 /* word */
#define OPTYPE_dq   	0x05000000 /* qword */
#define OPTYPE_p   	0x06000000 /* 16:16 or 16:32 pointer */
#define OPTYPE_pi   	0x07000000 /* dword MMX reg */
#define OPTYPE_ps   	0x08000000 /* 128-bit single fp */
#define OPTYPE_q   	0x09000000 /* dword */
#define OPTYPE_s   	0x0A000000 /* 6-byte descriptor */
#define OPTYPE_ss   	0x0B000000 /* scalar of 128-bit single fp */
#define OPTYPE_si   	0x0C000000 /* word general register */
#define OPTYPE_v   	0x0D000000 /* hword or word */
#define OPTYPE_w   	0x0E000000 /* hword */
#define OPTYPE_m   	0x0F000000	/* to handle LEA */
#define OPTYPE_none 0xFF000000 /* no valid operand size, INVLPG */

/* custom ones for FPU instructions */
#define OPTYPE_fs	0x10000000	/* pointer to single-real*/
#define OPTYPE_fd	0x20000000	/* pointer to double real */
#define OPTYPE_fe	0x30000000	/* pointer to extended real */
#define OPTYPE_fb	0x40000000	/* pointer to packed BCD */
#define OPTYPE_fv	0x50000000	/* pointer to FPU env: 14|28-bytes */
#define OPTYPE_ft	0x60000000	/* pointer to FPU state: 94|108-bytes */
#define OPTYPE_fx       0x70000000      /* pointer to FPU regs: 512 bites */
#define OPTYPE_fp       0x80000000      /* general fpu register: dbl ext */

/* SSE2 operand types */
#define OPTYPE_sd	0x90000000	/* scalar of 128-bit double fp */
#define OPTYPE_pd	0xA0000000	/* 128-bit double fp */



/* ---------------------------------------------- Opcode Table Descriptions */
/* the table type describes how to handle byte/size increments before 
 * and after lookup. Some tables re-use the current byte, others
 * consume a byte only if the ModR/M encodes no operands, etc */
enum ia32_tbl_type_id {
	tbl_opcode = 0,	/* standard opcode table: no surprises */
	tbl_prefix,	/* Prefix Override, e.g. 66/F2/F3 */
	tbl_suffix,	/* 3D Now style */
	tbl_extension,	/* ModR/M extension: 00-FF -> 00-07 */
	tbl_ext_ext,	/* extension of modr/m using R/M field */
	tbl_fpu,	/* fpu table: 00-BF -> 00-0F */
	tbl_fpu_ext	/* fpu extension : C0-FF -> 00-1F */
 };

/* How it works:
 * Bytes are 'consumed' if the next table lookup requires that the byte
 * pointer be advanced in the instruction stream. 'Does not consume' means
 * that, when the lookup function recurses, the same byte it re-used in the
 * new table. It also means that size is not decremented, for example when
 * a ModR/M byte is used. Note that tbl_extension (ModR/M) instructions that
 * do not increase the size of an insn with their operands have a forced
 3 size increase in the lookup algo. Weird, yes, confusing, yes, welcome
 * to the Intel ISA. Another note: tbl_prefix is used as an override, so an
 * empty insn in a prefix table causes the instruction in the original table
 * to be used, rather than an invalid insn being generated.
 * 	tbl_opcode uses current byte and consumes it
 * 	tbl_prefix uses current byte but does not consume it
 * 	tbl_suffix uses and consumes last byte in insn
 * 	tbl_extension uses current byte but does not consume it
 * 	tbl_ext_ext uses current byte but does not consume it
 * 	tbl_fpu uses current byte and consumes it
 * 	tbl_fpu_ext uses current byte but does not consume it 
 */

/* Convenience struct for opcode tables : these will be stored in a 
 * 'table of tables' so we can use a table index instead of a pointer */
typedef struct {		/* Assembly instruction tables */
   ia32_insn_t *table;		/* Pointer to table of instruction encodings */
   enum ia32_tbl_type_id type;
   unsigned char shift;		/* amount to shift modrm byte */
   unsigned char mask;		/* bit mask for look up */
   unsigned char minlim,maxlim;	/* limits on min/max entries. */
} ia32_table_desc_t;


/* ---------------------------------------------- 'Cooked' Operand Type Info */
/*                   Permissions: */
#define OP_R         0x001      /* operand is READ */
#define OP_W         0x002      /* operand is WRITTEN */
#define OP_RW        0x003	/* (OP_R|OP_W): convenience macro */
#define OP_X         0x004      /* operand is EXECUTED */

#define OP_PERM_MASK 0x0000007  /* perms are NOT mutually exclusive */
#define OP_PERM( type )       (type & OP_PERM_MASK)

/* Flags */
#define OP_SIGNED    0x010   	/* operand is signed */

#define OP_FLAG_MASK  0x0F0  /* mods are NOT mutually exclusive */
#define OP_FLAGS( type )        (type & OP_FLAG_MASK)

#define OP_REG_MASK    0x0000FFFF /* lower WORD is register ID */
#define OP_REGTBL_MASK 0xFFFF0000 /* higher word is register type [gen/dbg] */
#define OP_REGID( type )      (type & OP_REG_MASK)
#define OP_REGTYPE( type )    (type & OP_REGTBL_MASK)

/* ------------------------------------------'Cooked' Instruction Type Info */
/* high-bit opcode types/insn meta-types */
#define INS_FLAG_PREFIX		0x10000000	/* insn is a prefix */
#define INS_FLAG_SUFFIX		0x20000000	/* followed by a suffix byte */
#define INS_FLAG_MASK    	0xFF000000

/* insn notes */
#define INS_NOTE_RING0		0x00000001	/* insn is privileged */
#define INS_NOTE_SMM		0x00000002	/* Sys Mgt Mode only */
#define INS_NOTE_SERIAL		0x00000004	/* serializes */
#define INS_NOTE_NONSWAP    0x00000008  /* insn is not swapped in att format */ // could be separate field?
#define INS_NOTE_NOSUFFIX   0x00000010  /* insn has no size suffix in att format */ // could be separate field?
//#define INS_NOTE_NMI		

#define INS_INVALID 	0

/* instruction groups */
#define INS_EXEC	0x1000
#define INS_ARITH	0x2000
#define INS_LOGIC	0x3000
#define INS_STACK	0x4000
#define INS_COND	0x5000
#define INS_LOAD	0x6000
#define INS_ARRAY	0x7000
#define INS_BIT		0x8000
#define INS_FLAG	0x9000
#define INS_FPU		0xA000
#define INS_TRAPS	0xD000
#define INS_SYSTEM	0xE000
#define INS_OTHER	0xF000

#define INS_GROUP_MASK	0xF000
#define INS_GROUP( type )     ( type & INS_GROUP_MASK )

/* INS_EXEC group */
#define INS_BRANCH	(INS_EXEC | 0x01)	/* Unconditional branch */
#define INS_BRANCHCC	(INS_EXEC | 0x02)	/* Conditional branch */
#define INS_CALL	(INS_EXEC | 0x03)	/* Jump to subroutine */
#define INS_CALLCC	(INS_EXEC | 0x04)	/* Jump to subroutine */
#define INS_RET		(INS_EXEC | 0x05)	/* Return from subroutine */

/* INS_ARITH group */
#define INS_ADD 	(INS_ARITH | 0x01)
#define INS_SUB		(INS_ARITH | 0x02)
#define INS_MUL		(INS_ARITH | 0x03)
#define INS_DIV		(INS_ARITH | 0x04)
#define INS_INC		(INS_ARITH | 0x05)	/* increment */
#define INS_DEC		(INS_ARITH | 0x06)	/* decrement */
#define INS_SHL		(INS_ARITH | 0x07)	/* shift right */
#define INS_SHR		(INS_ARITH | 0x08)	/* shift left */
#define INS_ROL		(INS_ARITH | 0x09)	/* rotate left */
#define INS_ROR		(INS_ARITH | 0x0A)	/* rotate right */
#define INS_MIN		(INS_ARITH | 0x0B)	/* min func */
#define INS_MAX		(INS_ARITH | 0x0C)	/* max func */
#define INS_AVG		(INS_ARITH | 0x0D)	/* avg func */
#define INS_FLR		(INS_ARITH | 0x0E)	/* floor func */
#define INS_CEIL	(INS_ARITH | 0x0F)	/* ceiling func */

/* INS_LOGIC group */
#define INS_AND		(INS_LOGIC | 0x01)
#define INS_OR		(INS_LOGIC | 0x02)
#define INS_XOR		(INS_LOGIC | 0x03)
#define INS_NOT		(INS_LOGIC | 0x04)
#define INS_NEG		(INS_LOGIC | 0x05)
#define INS_NAND	(INS_LOGIC | 0x06)

/* INS_STACK group */
#define INS_PUSH	(INS_STACK | 0x01)
#define INS_POP		(INS_STACK | 0x02)
#define INS_PUSHREGS	(INS_STACK | 0x03)	/* push register context */
#define INS_POPREGS	(INS_STACK | 0x04)	/* pop register context */
#define INS_PUSHFLAGS	(INS_STACK | 0x05)	/* push all flags */
#define INS_POPFLAGS	(INS_STACK | 0x06)	/* pop all flags */
#define INS_ENTER	(INS_STACK | 0x07)	/* enter stack frame */
#define INS_LEAVE	(INS_STACK | 0x08)	/* leave stack frame */

/* INS_COND group */
#define INS_TEST	(INS_COND | 0x01)
#define INS_CMP		(INS_COND | 0x02)

/* INS_LOAD group */
#define INS_MOV		(INS_LOAD | 0x01)
#define INS_MOVCC	(INS_LOAD | 0x02)
#define INS_XCHG	(INS_LOAD | 0x03)
#define INS_XCHGCC	(INS_LOAD | 0x04)
#define INS_CONV	(INS_LOAD | 0x05)	/* move and convert type */

/* INS_ARRAY group */
#define INS_STRCMP	(INS_ARRAY | 0x01)
#define INS_STRLOAD	(INS_ARRAY | 0x02)
#define INS_STRMOV	(INS_ARRAY | 0x03)
#define INS_STRSTOR	(INS_ARRAY | 0x04)
#define INS_XLAT	(INS_ARRAY | 0x05)

/* INS_BIT group */
#define INS_BITTEST	(INS_BIT | 0x01)
#define INS_BITSET	(INS_BIT | 0x02)
#define INS_BITCLR	(INS_BIT | 0x03)

/* INS_FLAG group */
#define INS_CLEARCF	(INS_FLAG | 0x01)	/* clear Carry flag */
#define INS_CLEARZF	(INS_FLAG | 0x02)	/* clear Zero flag */
#define INS_CLEAROF	(INS_FLAG | 0x03)	/* clear Overflow flag */
#define INS_CLEARDF	(INS_FLAG | 0x04)	/* clear Direction flag */
#define INS_CLEARSF	(INS_FLAG | 0x05)	/* clear Sign flag */
#define INS_CLEARPF	(INS_FLAG | 0x06)	/* clear Parity flag */
#define INS_SETCF	(INS_FLAG | 0x07)
#define INS_SETZF	(INS_FLAG | 0x08)
#define INS_SETOF	(INS_FLAG | 0x09)
#define INS_SETDF	(INS_FLAG | 0x0A)
#define INS_SETSF	(INS_FLAG | 0x0B)
#define INS_SETPF	(INS_FLAG | 0x0C)
#define INS_TOGCF	(INS_FLAG | 0x10)	/* toggle */
#define INS_TOGZF	(INS_FLAG | 0x20)
#define INS_TOGOF	(INS_FLAG | 0x30)
#define INS_TOGDF	(INS_FLAG | 0x40)
#define INS_TOGSF	(INS_FLAG | 0x50)
#define INS_TOGPF	(INS_FLAG | 0x60)

/* INS_FPU */
#define INS_FMOV       (INS_FPU | 0x1)
#define INS_FMOVCC     (INS_FPU | 0x2)
#define INS_FNEG       (INS_FPU | 0x3)
#define INS_FABS       (INS_FPU | 0x4)
#define INS_FADD       (INS_FPU | 0x5)
#define INS_FSUB       (INS_FPU | 0x6)
#define INS_FMUL       (INS_FPU | 0x7)
#define INS_FDIV       (INS_FPU | 0x8)
#define INS_FSQRT      (INS_FPU | 0x9)
#define INS_FCMP       (INS_FPU | 0xA)
#define INS_FCOS       (INS_FPU | 0xC)               /* cosine */
#define INS_FLDPI      (INS_FPU | 0xD)               /* load pi */
#define INS_FLDZ       (INS_FPU | 0xE)               /* load 0 */
#define INS_FTAN       (INS_FPU | 0xF)               /* tanget */
#define INS_FSINE      (INS_FPU | 0x10)              /* sine */
#define INS_FSYS       (INS_FPU | 0x20)              /* misc */

/* INS_TRAP */
#define INS_TRAP	(INS_TRAPS | 0x01)	/* generate trap */
#define INS_TRAPCC	(INS_TRAPS | 0x02)	/* conditional trap gen */
#define INS_TRET	(INS_TRAPS | 0x03)	/* return from trap */
#define INS_BOUNDS	(INS_TRAPS | 0x04)	/* gen bounds trap */
#define INS_DEBUG	(INS_TRAPS | 0x05)	/* gen breakpoint trap */
#define INS_TRACE	(INS_TRAPS | 0x06)	/* gen single step trap */
#define INS_INVALIDOP	(INS_TRAPS | 0x07)	/* gen invalid insn */
#define INS_OFLOW	(INS_TRAPS | 0x08)	/* gen overflow trap */
#define INS_ICEBP	(INS_TRAPS | 0x09)	/* ICE breakpoint */

/* INS_SYSTEM */
#define INS_HALT	(INS_SYSTEM | 0x01)	/* halt machine */
#define INS_IN		(INS_SYSTEM | 0x02)	/* input form port */
#define INS_OUT		(INS_SYSTEM | 0x03)	/* output to port */
#define INS_CPUID	(INS_SYSTEM | 0x04)	/* identify cpu */

/* INS_OTHER */
#define INS_NOP		(INS_OTHER | 0x01)
#define INS_BCDCONV	(INS_OTHER | 0x02)	/* convert to/from BCD */
#define INS_SZCONV	(INS_OTHER | 0x03)	/* convert size of operand */
#define INS_SALC	(INS_OTHER | 0x04)	/* set %al on carry */
#define INS_UNKNOWN	(INS_OTHER | 0x05)
 

#define INS_TYPE_MASK	0xFFFF
#define INS_TYPE( type )      ( type & INS_TYPE_MASK )

   /* flags effected by instruction */
#define INS_TEST_CARRY        0x01    /* carry */
#define INS_TEST_ZERO         0x02    /* zero/equal */
#define INS_TEST_OFLOW        0x04    /* overflow */
#define INS_TEST_DIR          0x08    /* direction */
#define INS_TEST_SIGN         0x10    /* negative */
#define INS_TEST_PARITY       0x20    /* parity */
#define INS_TEST_OR           0x40    /* used in jle */
#define INS_TEST_NCARRY       0x100	/* ! carry */
#define INS_TEST_NZERO        0x200	/* ! zero */
#define INS_TEST_NOFLOW       0x400	/* ! oflow */
#define INS_TEST_NDIR         0x800	/* ! dir */
#define INS_TEST_NSIGN        0x100	/* ! sign */
#define INS_TEST_NPARITY      0x2000	/* ! parity */
/* SF == OF */
#define INS_TEST_SFEQOF       0x4000
/* SF != OF */
#define INS_TEST_SFNEOF       0x8000

#define INS_TEST_ALL		INS_TEST_CARRY | INS_TEST_ZERO | \
				INS_TEST_OFLOW | INS_TEST_SIGN | \
				INS_TEST_PARITY

#define INS_SET_CARRY        0x010000    /* carry */
#define INS_SET_ZERO         0x020000    /* zero/equal */
#define INS_SET_OFLOW        0x040000    /* overflow */
#define INS_SET_DIR          0x080000    /* direction */
#define INS_SET_SIGN         0x100000    /* negative */
#define INS_SET_PARITY       0x200000    /* parity */
#define INS_SET_NCARRY       0x1000000 
#define INS_SET_NZERO        0x2000000
#define INS_SET_NOFLOW       0x4000000
#define INS_SET_NDIR         0x8000000
#define INS_SET_NSIGN        0x10000000
#define INS_SET_NPARITY      0x20000000
#define INS_SET_SFEQOF       0x40000000
#define INS_SET_SFNEOF       0x80000000

#define INS_SET_ALL		INS_SET_CARRY | INS_SET_ZERO | \
				INS_SET_OFLOW | INS_SET_SIGN | \
				INS_SET_PARITY

#define INS_TEST_MASK          0x0000FFFF
#define INS_FLAGS_TEST(x)      (x & INS_TEST_MASK)
#define INS_SET_MASK           0xFFFF0000
#define INS_FLAGS_SET(x)       (x & INS_SET_MASK)

#if 0
/* TODO: actually start using these */
#define X86_PAIR_NP	1		/* not pairable; execs in U */
#define X86_PAIR_PU	2		/* pairable in U pipe */
#define X86_PAIR_PV	3		/* pairable in V pipe */
#define X86_PAIR_UV	4		/* pairable in UV pipe */
#define X86_PAIR_FX	5		/* pairable with FXCH */

#define X86_EXEC_PORT_0	1
#define X86_EXEC_PORT_1	2
#define X86_EXEC_PORT_2	4
#define X86_EXEC_PORT_3	8
#define X86_EXEC_PORT_4	16

#define X86_EXEC_UNITS

typedef struct {	/* representation of an insn during decoding */
	uint32_t flags;		/* runtime settings */
	/* instruction prefixes and other foolishness */
	uint32_t prefix;		/* encoding of prefix */
	char prefix_str[16];		/* mnemonics for prefix */
	uint32_t branch_hint;	/* gah! */
	unsigned int cpu_ver;		/* TODO: cpu version */
	unsigned int clocks;		/* TODO: clock cycles: min/max */
	unsigned char last_prefix;
	/* runtime intruction decoding helpers */
	unsigned char mode;		/* 16, 32, 64 */
	unsigned char gen_regs;		/* offset of default general reg set */
	unsigned char sz_operand;	/* operand size for insn */
	unsigned char sz_address;	/* address size for insn */
	unsigned char uops;		/* uops per insn */
	unsigned char pairing;		/* np,pu,pv.lv */
	unsigned char exec_unit;
	unsigned char exec_port;
	unsigned char latency;
} ia32_info_t;
#define MODE_32 0	/* default */
#define MODE_16 1
#define MODE_64 2
#endif

#endif