toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/third_party/libdisasm/ia32_implicit.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,422 @@
     1.4 +#include <stdlib.h>
     1.5 +
     1.6 +#include "ia32_implicit.h"
     1.7 +#include "ia32_insn.h"
     1.8 +#include "ia32_reg.h"
     1.9 +#include "x86_operand_list.h"
    1.10 +
    1.11 +/* Conventions: Register operands which are aliases of another register 
    1.12 + *   operand (e.g. AX in one operand and AL in another) assume that the
    1.13 + *   operands are different registers and that alias tracking will resolve
    1.14 + *   data flow. This means that something like
    1.15 + *   	mov ax, al
    1.16 + *   would have 'write only' access for AX and 'read only' access for AL,
    1.17 + *   even though both AL and AX are read and written */
    1.18 +typedef struct {
    1.19 +	uint32_t type;
    1.20 +	uint32_t operand;
    1.21 +} op_implicit_list_t;
    1.22 +
    1.23 +static op_implicit_list_t list_aaa[] = 
    1.24 +	/* 37 : AAA : rw AL */
    1.25 +	/* 3F : AAS : rw AL */
    1.26 +	{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}};	/* aaa */
    1.27 +
    1.28 +static op_implicit_list_t list_aad[] = 
    1.29 +	/* D5 0A, D5 (ib) : AAD : rw AX */
    1.30 +	/* D4 0A, D4 (ib) : AAM : rw AX */
    1.31 +	{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}};	/* aad */
    1.32 +
    1.33 +static op_implicit_list_t list_call[] = 
    1.34 +	/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
    1.35 +	/* C2, C3, CA, CB : RET  : rw ESP, rw EIP */
    1.36 +	{{ OP_R | OP_W, REG_EIP_INDEX }, 
    1.37 +	 { OP_R | OP_W, REG_ESP_INDEX }, {0}};	/* call, ret */
    1.38 +
    1.39 +static op_implicit_list_t list_cbw[] = 
    1.40 +	/* 98 : CBW : r AL, rw AX */
    1.41 +	{{ OP_R | OP_W, REG_WORD_OFFSET },
    1.42 +	 { OP_R, REG_BYTE_OFFSET}, {0}};		/* cbw */
    1.43 +
    1.44 +static op_implicit_list_t list_cwde[] = 
    1.45 +	/* 98 : CWDE : r AX, rw EAX */
    1.46 +	{{ OP_R | OP_W, REG_DWORD_OFFSET },
    1.47 +	 { OP_R, REG_WORD_OFFSET }, {0}};		/* cwde */
    1.48 +
    1.49 +static op_implicit_list_t list_clts[] = 
    1.50 +	/* 0F 06 : CLTS : rw CR0 */
    1.51 +	{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}};	/* clts */
    1.52 +
    1.53 +static op_implicit_list_t list_cmpxchg[] = 
    1.54 +	/* 0F B0 : CMPXCHG : rw AL */
    1.55 +	{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}};	/* cmpxchg */
    1.56 +
    1.57 +static op_implicit_list_t list_cmpxchgb[] = 
    1.58 +	/* 0F B1 : CMPXCHG : rw EAX */
    1.59 +	{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}};	/* cmpxchg */
    1.60 +
    1.61 +static op_implicit_list_t list_cmpxchg8b[] = 
    1.62 +	/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
    1.63 +	{{ OP_R | OP_W, REG_DWORD_OFFSET }, 
    1.64 +	 { OP_R | OP_W, REG_DWORD_OFFSET + 2 }, 
    1.65 +	 { OP_R, REG_DWORD_OFFSET + 1 }, 
    1.66 +	 { OP_R, REG_DWORD_OFFSET + 3 }, {0}};	/* cmpxchg8b */
    1.67 +
    1.68 +static op_implicit_list_t list_cpuid[] = 
    1.69 +	/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
    1.70 +	{{ OP_R | OP_W, REG_DWORD_OFFSET }, 
    1.71 +	 { OP_W, REG_DWORD_OFFSET + 1 }, 
    1.72 +	 { OP_W, REG_DWORD_OFFSET + 2 }, 
    1.73 +	 { OP_W, REG_DWORD_OFFSET + 3 }, {0}};	/* cpuid */
    1.74 +
    1.75 +static op_implicit_list_t list_cwd[] = 
    1.76 +	/* 99 : CWD/CWQ : rw EAX, w EDX */
    1.77 +	{{ OP_R | OP_W, REG_DWORD_OFFSET }, 
    1.78 +	 { OP_W, REG_DWORD_OFFSET + 2 }, {0}};	/* cwd */
    1.79 +
    1.80 +static op_implicit_list_t list_daa[] = 
    1.81 +	/* 27 : DAA : rw AL */
    1.82 +	/* 2F : DAS : rw AL */
    1.83 +	{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}};	/* daa */
    1.84 +
    1.85 +static op_implicit_list_t list_idiv[] = 
    1.86 +	/* F6 : DIV, IDIV : r AX, w AL, w AH */
    1.87 +	/* FIXED: first op was EAX, not Aw. TODO: verify! */
    1.88 +	{{ OP_R, REG_WORD_OFFSET }, 
    1.89 +	  { OP_W, REG_BYTE_OFFSET },
    1.90 +	  { OP_W, REG_BYTE_OFFSET + 4 }, {0}};	/* div */
    1.91 +
    1.92 +static op_implicit_list_t list_div[] = 
    1.93 +	/* F7 : DIV, IDIV : rw EDX, rw EAX */
    1.94 +	{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 }, 
    1.95 +	  { OP_R | OP_W, REG_DWORD_OFFSET }, {0}};	/* div */
    1.96 +
    1.97 +static op_implicit_list_t list_enter[] = 
    1.98 +	/* C8 : ENTER : rw ESP w EBP */
    1.99 +	{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 }, 
   1.100 +	 { OP_R, REG_DWORD_OFFSET + 5 }, {0}};	/* enter */
   1.101 +
   1.102 +static op_implicit_list_t list_f2xm1[] = 
   1.103 +	/* D9 F0 : F2XM1 : rw ST(0) */
   1.104 +	/* D9 E1 : FABS : rw ST(0) */
   1.105 +	/* D9 E0 : FCHS : rw ST(0) */
   1.106 +	/* D9 FF : FCOS : rw ST(0)*/
   1.107 +	/* D8, DA : FDIV : rw ST(0) */
   1.108 +	/* D8, DA : FDIVR : rw ST(0) */
   1.109 +	/* D9 F2 : FPTAN : rw ST(0) */
   1.110 +	/* D9 FC : FRNDINT : rw ST(0) */
   1.111 +	/* D9 FB : FSINCOS : rw ST(0) */
   1.112 +	/* D9 FE : FSIN : rw ST(0) */
   1.113 +	/* D9 FA : FSQRT : rw ST(0) */
   1.114 +	/* D9 F4 : FXTRACT : rw ST(0) */
   1.115 +	{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}};	/* f2xm1 */
   1.116 +
   1.117 +static op_implicit_list_t list_fcom[] = 
   1.118 +	/* D8, DC, DE D9 : FCOM : r ST(0) */
   1.119 +	/* DE, DA : FICOM : r ST(0) */
   1.120 +	/* DF, D8 : FIST : r ST(0) */
   1.121 +	/* D9 E4 : FTST : r ST(0) */
   1.122 +	/* D9 E5 : FXAM : r ST(0) */
   1.123 +	{{ OP_R, REG_FPU_OFFSET }, {0}};		/* fcom */
   1.124 +
   1.125 +static op_implicit_list_t list_fpatan[] = 
   1.126 +	/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
   1.127 +	{{ OP_R, REG_FPU_OFFSET }, {0}};		/* fpatan */
   1.128 +
   1.129 +static op_implicit_list_t list_fprem[] = 
   1.130 +	/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
   1.131 +	/* D9 FD : FSCALE : rw ST(0), r ST(1) */
   1.132 +	{{ OP_R | OP_W, REG_FPU_OFFSET }, 	
   1.133 +	 { OP_R, REG_FPU_OFFSET + 1 }, {0}};	/* fprem */
   1.134 +
   1.135 +static op_implicit_list_t list_faddp[] = 
   1.136 +	/* DE C1 : FADDP : r ST(0), rw ST(1) */
   1.137 +	/* DE E9 : FSUBP : r ST(0), rw ST(1) */
   1.138 +	/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
   1.139 +	/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
   1.140 +	{{ OP_R, REG_FPU_OFFSET },
   1.141 +	 { OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}};	/* faddp */
   1.142 +
   1.143 +static op_implicit_list_t list_fucompp[] = 
   1.144 +	/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
   1.145 +	{{ OP_R, REG_FPU_OFFSET },
   1.146 +	 { OP_R, REG_FPU_OFFSET + 1 }, {0}};	/* fucompp */
   1.147 +
   1.148 +static op_implicit_list_t list_imul[] = 
   1.149 +	/* F6 : IMUL : r AL, w AX */
   1.150 +	/* F6 : MUL : r AL, w AX */
   1.151 +	{{ OP_R, REG_BYTE_OFFSET },
   1.152 +	 { OP_W, REG_WORD_OFFSET }, {0}};		/* imul */
   1.153 +
   1.154 +static op_implicit_list_t list_mul[] = 
   1.155 +	/* F7 : IMUL : rw EAX, w EDX */
   1.156 +	/* F7 : MUL : rw EAX, w EDX */
   1.157 +	{{ OP_R | OP_W, REG_DWORD_OFFSET },
   1.158 +	 { OP_W, REG_DWORD_OFFSET + 2 }, {0}};	/* imul */
   1.159 +
   1.160 +static op_implicit_list_t list_lahf[] = 
   1.161 +	/* 9F : LAHF : r EFLAGS, w AH */
   1.162 +	{{ OP_R, REG_FLAGS_INDEX },
   1.163 +	 { OP_W, REG_BYTE_OFFSET + 4 }, {0}};	/* lahf */
   1.164 +
   1.165 +static op_implicit_list_t list_ldmxcsr[] = 
   1.166 +	/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
   1.167 +	{{ OP_W, REG_MXCSG_INDEX }, {0}};		/* ldmxcsr */
   1.168 +
   1.169 +static op_implicit_list_t list_leave[] = 
   1.170 +	/* C9 : LEAVE :  rw ESP, w EBP */
   1.171 +	{{ OP_R | OP_W, REG_ESP_INDEX },
   1.172 +	 { OP_W, REG_DWORD_OFFSET + 5 }, {0}};	/* leave */
   1.173 +
   1.174 +static op_implicit_list_t list_lgdt[] = 
   1.175 +	/* 0F 01 : LGDT : w GDTR */
   1.176 +	{{ OP_W, REG_GDTR_INDEX }, {0}};		/* lgdt */
   1.177 +
   1.178 +static op_implicit_list_t list_lidt[] = 
   1.179 +	/* 0F 01 : LIDT : w IDTR */
   1.180 +	{{ OP_W, REG_IDTR_INDEX }, {0}};		/* lidt */
   1.181 +
   1.182 +static op_implicit_list_t list_lldt[] = 
   1.183 +	/* 0F 00 : LLDT : w LDTR */
   1.184 +	{{ OP_W, REG_LDTR_INDEX }, {0}};		/* lldt */
   1.185 +
   1.186 +static op_implicit_list_t list_lmsw[] = 
   1.187 +	/* 0F 01 : LMSW : w CR0 */
   1.188 +	{{ OP_W, REG_CTRL_OFFSET }, {0}};		/* lmsw */
   1.189 +
   1.190 +static op_implicit_list_t list_loop[] = 
   1.191 +	/* E0, E1, E2 : LOOP : rw ECX */
   1.192 +	{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
   1.193 +
   1.194 +static op_implicit_list_t list_ltr[] = 
   1.195 +	/* 0F 00 : LTR : w Task Register */
   1.196 +	{{ OP_W, REG_TR_INDEX }, {0}};		/* ltr */
   1.197 +
   1.198 +static op_implicit_list_t list_pop[] = 
   1.199 +	/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
   1.200 +	/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
   1.201 +	{{ OP_R | OP_W, REG_ESP_INDEX }, {0}};	/* pop, push */
   1.202 +
   1.203 +static op_implicit_list_t list_popad[] = 
   1.204 +	/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
   1.205 +	{{ OP_R | OP_W, REG_ESP_INDEX },
   1.206 +	 { OP_W, REG_DWORD_OFFSET + 7 },
   1.207 +	 { OP_W, REG_DWORD_OFFSET + 6 },
   1.208 +	 { OP_W, REG_DWORD_OFFSET + 5 },
   1.209 +	 { OP_W, REG_DWORD_OFFSET + 3 },
   1.210 +	 { OP_W, REG_DWORD_OFFSET + 2 },
   1.211 +	 { OP_W, REG_DWORD_OFFSET + 1 },
   1.212 +	 { OP_W, REG_DWORD_OFFSET }, {0}};		/* popad */
   1.213 +
   1.214 +static op_implicit_list_t list_popfd[] = 
   1.215 +	/* 9D : POPFD : rw esp, w eflags */
   1.216 +	{{ OP_R | OP_W, REG_ESP_INDEX },
   1.217 +	 { OP_W, REG_FLAGS_INDEX }, {0}};		/* popfd */
   1.218 +
   1.219 +static op_implicit_list_t list_pushad[] = 
   1.220 +	/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
   1.221 +	/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
   1.222 +	{{ OP_R | OP_W, REG_ESP_INDEX },
   1.223 +	 { OP_R, REG_DWORD_OFFSET },
   1.224 +	 { OP_R, REG_DWORD_OFFSET + 1 },
   1.225 +	 { OP_R, REG_DWORD_OFFSET + 2 },
   1.226 +	 { OP_R, REG_DWORD_OFFSET + 3 },
   1.227 +	 { OP_R, REG_DWORD_OFFSET + 5 },
   1.228 +	 { OP_R, REG_DWORD_OFFSET + 6 },
   1.229 +	 { OP_R, REG_DWORD_OFFSET + 7 }, {0}};	/* pushad */
   1.230 +
   1.231 +static op_implicit_list_t list_pushfd[] = 
   1.232 +	/* 9C : PUSHFD : rw esp, r eflags */
   1.233 +	{{ OP_R | OP_W, REG_ESP_INDEX },
   1.234 +	 { OP_R, REG_FLAGS_INDEX }, {0}};		/* pushfd */
   1.235 +
   1.236 +static op_implicit_list_t list_rdmsr[] = 
   1.237 +	/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
   1.238 +	{{ OP_R, REG_DWORD_OFFSET + 1 },
   1.239 +	 { OP_W, REG_DWORD_OFFSET + 2 },
   1.240 +	 { OP_W, REG_DWORD_OFFSET }, {0}};	/* rdmsr */
   1.241 +
   1.242 +static op_implicit_list_t list_rdpmc[] = 
   1.243 +	/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
   1.244 +	{{ OP_R, REG_DWORD_OFFSET + 1 },
   1.245 +	 { OP_W, REG_DWORD_OFFSET + 2 },
   1.246 +	 { OP_W, REG_DWORD_OFFSET }, {0}};		/* rdpmc */
   1.247 +
   1.248 +static op_implicit_list_t list_rdtsc[] = 
   1.249 +	/* 0F 31 : RDTSC : rw EDX, rw EAX */
   1.250 +	{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
   1.251 +	 { OP_R | OP_W, REG_DWORD_OFFSET }, {0}};	/* rdtsc */
   1.252 +
   1.253 +static op_implicit_list_t list_rep[] = 
   1.254 +	/* F3, F2 ... : REP : rw ECX */
   1.255 +	{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
   1.256 +
   1.257 +static op_implicit_list_t list_rsm[] = 
   1.258 +	/* 0F AA : RSM : r CR4, r CR0 */
   1.259 +	{{ OP_R, REG_CTRL_OFFSET + 4 }, 
   1.260 +	 { OP_R, REG_CTRL_OFFSET }, {0}};		/* rsm */
   1.261 +
   1.262 +static op_implicit_list_t list_sahf[] = 
   1.263 +	/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
   1.264 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sahf */
   1.265 +
   1.266 +static op_implicit_list_t list_sgdt[] = 
   1.267 +	/* 0F : SGDT : r gdtr */
   1.268 +	/* TODO: finish this! */
   1.269 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sgdt */
   1.270 +
   1.271 +static op_implicit_list_t list_sidt[] = 
   1.272 +	/* 0F : SIDT : r idtr */
   1.273 +	/* TODO: finish this! */
   1.274 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sidt */
   1.275 +
   1.276 +static op_implicit_list_t list_sldt[] = 
   1.277 +	/* 0F : SLDT : r ldtr */
   1.278 +	/* TODO: finish this! */
   1.279 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sldt */
   1.280 +
   1.281 +static op_implicit_list_t list_smsw[] = 
   1.282 +	/* 0F : SMSW : r CR0 */
   1.283 +	/* TODO: finish this! */
   1.284 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* smsw */
   1.285 +
   1.286 +static op_implicit_list_t list_stmxcsr[] = 
   1.287 +	/* 0F AE : STMXCSR : r MXCSR */
   1.288 +	/* TODO: finish this! */
   1.289 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* stmxcsr */
   1.290 +
   1.291 +static op_implicit_list_t list_str[] = 
   1.292 +	/* 0F 00 : STR : r TR (task register) */
   1.293 +	/* TODO: finish this! */
   1.294 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* str */
   1.295 +
   1.296 +static op_implicit_list_t list_sysenter[] = 
   1.297 +	/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
   1.298 +	 *         r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
   1.299 +	/* TODO: finish this! */
   1.300 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sysenter */
   1.301 +
   1.302 +static op_implicit_list_t list_sysexit[] = 
   1.303 +	/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
   1.304 +	 * 	   r sysenter_cs_msr */
   1.305 +	/* TODO: finish this! */
   1.306 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* sysexit */
   1.307 +
   1.308 +static op_implicit_list_t list_wrmsr[] = 
   1.309 +	/* 0F 30 : WRMST : r edx, r eax, r ecx */
   1.310 +	/* TODO: finish this! */
   1.311 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* wrmsr */
   1.312 +
   1.313 +static op_implicit_list_t list_xlat[] = 
   1.314 +	/* D7 : XLAT : rw al r ebx (ptr) */
   1.315 +	/* TODO: finish this! */
   1.316 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* xlat */
   1.317 +/* TODO:
   1.318 + * monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
   1.319 + * mwait 0f 01 c9 eax OP_R ecx OP_R
   1.320 + */
   1.321 +static op_implicit_list_t list_monitor[] = 
   1.322 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* monitor */
   1.323 +static op_implicit_list_t list_mwait[] = 
   1.324 +	{{ OP_R, REG_DWORD_OFFSET }, {0}};		/* mwait */
   1.325 +
   1.326 +op_implicit_list_t *op_implicit_list[] = {
   1.327 +	/* This is a list of implicit operands which are read/written by
   1.328 +	 * various x86 instructions. Note that modifications to the stack
   1.329 +	 * register are mentioned here, but that additional information on
   1.330 +	 * the effect an instruction has on the stack is contained in the
   1.331 +	 * x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
   1.332 +	 * eflags register, i.e. setting, clearing, and testing flags, is
   1.333 +	 * not recorded here but rather in the flags_set and flags_tested
   1.334 +	 * fields of the x86_insn_t.*/
   1.335 +	NULL,
   1.336 +	list_aaa, list_aad, list_call, list_cbw,		/* 1 - 4 */
   1.337 +	list_cwde, list_clts, list_cmpxchg, list_cmpxchgb,	/* 5 - 8 */
   1.338 +	list_cmpxchg8b, list_cpuid, list_cwd, list_daa,		/* 9 - 12 */
   1.339 +	list_idiv, list_div, list_enter, list_f2xm1,		/* 13 - 16 */
   1.340 +	list_fcom, list_fpatan, list_fprem, list_faddp,		/* 17 - 20 */
   1.341 +	list_fucompp, list_imul, list_mul, list_lahf,		/* 21 - 24 */
   1.342 +	list_ldmxcsr, list_leave, list_lgdt, list_lidt,		/* 25 - 28 */
   1.343 +	list_lldt, list_lmsw, list_loop, list_ltr,		/* 29 - 32 */
   1.344 +	list_pop, list_popad, list_popfd, list_pushad,		/* 33 - 36 */
   1.345 +	list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc,	/* 37 - 40 */
   1.346 +	/* NOTE: 'REP' is a hack since it is a prefix: if its position
   1.347 +	 * in the table changes, then change IDX_IMPLICIT_REP in the .h */
   1.348 +	list_rep, list_rsm, list_sahf, list_sgdt,		/* 41 - 44 */
   1.349 +	list_sidt, list_sldt, list_smsw, list_stmxcsr,		/* 45 - 48 */
   1.350 +	list_str, list_sysenter, list_sysexit, list_wrmsr,	/* 49 - 52 */
   1.351 +	list_xlat, list_monitor, list_mwait,			/* 53 - 55*/
   1.352 +	NULL						/* end of list */
   1.353 + };
   1.354 +
   1.355 +#define LAST_IMPL_IDX 55
   1.356 +
   1.357 +static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
   1.358 +	x86_reg_t *reg = &op->data.reg;
   1.359 +	op->type = op_register;
   1.360 +	ia32_handle_register( reg, (unsigned int) val );
   1.361 +	switch (reg->size) {
   1.362 +		case 1:
   1.363 +			op->datatype = op_byte; break;
   1.364 +		case 2:
   1.365 +			op->datatype = op_word; break;
   1.366 +		case 4:
   1.367 +			op->datatype = op_dword; break;
   1.368 +		case 8:
   1.369 +			op->datatype = op_qword; break;
   1.370 +		case 10:
   1.371 +			op->datatype = op_extreal; break;
   1.372 +		case 16:
   1.373 +			op->datatype = op_dqword; break;
   1.374 +	}
   1.375 +	return;
   1.376 +}
   1.377 +
   1.378 +/* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
   1.379 +/* returns number of operands added */
   1.380 +unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx ) {
   1.381 +	op_implicit_list_t *list;
   1.382 +	x86_op_t *op;
   1.383 +	unsigned int num = 0;
   1.384 +
   1.385 +	if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
   1.386 +		return 0;
   1.387 +	}
   1.388 +
   1.389 +	for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
   1.390 +		enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
   1.391 +		enum x86_op_flags  flags  = (enum x86_op_flags) (OP_FLAGS(list->type) >> 12);
   1.392 +
   1.393 +		op = NULL;
   1.394 +		/* In some cases (MUL), EAX is an implicit operand hardcoded in
   1.395 +                 * the instruction without being explicitly listed in assembly.
   1.396 +                 * For this situation, find the hardcoded operand and add the
   1.397 +                 * implied flag rather than adding a new implicit operand. */
   1.398 +		x86_oplist_t * existing;
   1.399 +		if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
   1.400 +			for ( existing = insn->operands; existing; existing = existing->next ) {
   1.401 +				if (existing->op.type == op_register &&
   1.402 +	                            existing->op.data.reg.id == list->operand) {
   1.403 +					op = &existing->op;
   1.404 +					break;
   1.405 +				}
   1.406 +			}
   1.407 +		}
   1.408 +		if (!op) {
   1.409 +			op = x86_operand_new( insn );
   1.410 +			/* all implicit operands are registers */
   1.411 +			handle_impl_reg( op, list->operand );
   1.412 +			/* decrement the 'explicit count' incremented by default in
   1.413 +			 * x86_operand_new */
   1.414 +			insn->explicit_count = insn->explicit_count -1;
   1.415 +		}
   1.416 +		if (!op) {
   1.417 +			return num;	/* gah! return early */
   1.418 +		}
   1.419 +		op->access |= access;
   1.420 +		op->flags |= flags;
   1.421 +		op->flags |= op_implied;
   1.422 +	}
   1.423 +	
   1.424 +	return num;
   1.425 +}

mercurial