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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 #include <stdlib.h>
michael@0 2
michael@0 3 #include "ia32_implicit.h"
michael@0 4 #include "ia32_insn.h"
michael@0 5 #include "ia32_reg.h"
michael@0 6 #include "x86_operand_list.h"
michael@0 7
michael@0 8 /* Conventions: Register operands which are aliases of another register
michael@0 9 * operand (e.g. AX in one operand and AL in another) assume that the
michael@0 10 * operands are different registers and that alias tracking will resolve
michael@0 11 * data flow. This means that something like
michael@0 12 * mov ax, al
michael@0 13 * would have 'write only' access for AX and 'read only' access for AL,
michael@0 14 * even though both AL and AX are read and written */
michael@0 15 typedef struct {
michael@0 16 uint32_t type;
michael@0 17 uint32_t operand;
michael@0 18 } op_implicit_list_t;
michael@0 19
michael@0 20 static op_implicit_list_t list_aaa[] =
michael@0 21 /* 37 : AAA : rw AL */
michael@0 22 /* 3F : AAS : rw AL */
michael@0 23 {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
michael@0 24
michael@0 25 static op_implicit_list_t list_aad[] =
michael@0 26 /* D5 0A, D5 (ib) : AAD : rw AX */
michael@0 27 /* D4 0A, D4 (ib) : AAM : rw AX */
michael@0 28 {{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
michael@0 29
michael@0 30 static op_implicit_list_t list_call[] =
michael@0 31 /* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
michael@0 32 /* C2, C3, CA, CB : RET : rw ESP, rw EIP */
michael@0 33 {{ OP_R | OP_W, REG_EIP_INDEX },
michael@0 34 { OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
michael@0 35
michael@0 36 static op_implicit_list_t list_cbw[] =
michael@0 37 /* 98 : CBW : r AL, rw AX */
michael@0 38 {{ OP_R | OP_W, REG_WORD_OFFSET },
michael@0 39 { OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
michael@0 40
michael@0 41 static op_implicit_list_t list_cwde[] =
michael@0 42 /* 98 : CWDE : r AX, rw EAX */
michael@0 43 {{ OP_R | OP_W, REG_DWORD_OFFSET },
michael@0 44 { OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
michael@0 45
michael@0 46 static op_implicit_list_t list_clts[] =
michael@0 47 /* 0F 06 : CLTS : rw CR0 */
michael@0 48 {{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
michael@0 49
michael@0 50 static op_implicit_list_t list_cmpxchg[] =
michael@0 51 /* 0F B0 : CMPXCHG : rw AL */
michael@0 52 {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
michael@0 53
michael@0 54 static op_implicit_list_t list_cmpxchgb[] =
michael@0 55 /* 0F B1 : CMPXCHG : rw EAX */
michael@0 56 {{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
michael@0 57
michael@0 58 static op_implicit_list_t list_cmpxchg8b[] =
michael@0 59 /* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
michael@0 60 {{ OP_R | OP_W, REG_DWORD_OFFSET },
michael@0 61 { OP_R | OP_W, REG_DWORD_OFFSET + 2 },
michael@0 62 { OP_R, REG_DWORD_OFFSET + 1 },
michael@0 63 { OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
michael@0 64
michael@0 65 static op_implicit_list_t list_cpuid[] =
michael@0 66 /* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
michael@0 67 {{ OP_R | OP_W, REG_DWORD_OFFSET },
michael@0 68 { OP_W, REG_DWORD_OFFSET + 1 },
michael@0 69 { OP_W, REG_DWORD_OFFSET + 2 },
michael@0 70 { OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
michael@0 71
michael@0 72 static op_implicit_list_t list_cwd[] =
michael@0 73 /* 99 : CWD/CWQ : rw EAX, w EDX */
michael@0 74 {{ OP_R | OP_W, REG_DWORD_OFFSET },
michael@0 75 { OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
michael@0 76
michael@0 77 static op_implicit_list_t list_daa[] =
michael@0 78 /* 27 : DAA : rw AL */
michael@0 79 /* 2F : DAS : rw AL */
michael@0 80 {{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
michael@0 81
michael@0 82 static op_implicit_list_t list_idiv[] =
michael@0 83 /* F6 : DIV, IDIV : r AX, w AL, w AH */
michael@0 84 /* FIXED: first op was EAX, not Aw. TODO: verify! */
michael@0 85 {{ OP_R, REG_WORD_OFFSET },
michael@0 86 { OP_W, REG_BYTE_OFFSET },
michael@0 87 { OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
michael@0 88
michael@0 89 static op_implicit_list_t list_div[] =
michael@0 90 /* F7 : DIV, IDIV : rw EDX, rw EAX */
michael@0 91 {{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
michael@0 92 { OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
michael@0 93
michael@0 94 static op_implicit_list_t list_enter[] =
michael@0 95 /* C8 : ENTER : rw ESP w EBP */
michael@0 96 {{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
michael@0 97 { OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
michael@0 98
michael@0 99 static op_implicit_list_t list_f2xm1[] =
michael@0 100 /* D9 F0 : F2XM1 : rw ST(0) */
michael@0 101 /* D9 E1 : FABS : rw ST(0) */
michael@0 102 /* D9 E0 : FCHS : rw ST(0) */
michael@0 103 /* D9 FF : FCOS : rw ST(0)*/
michael@0 104 /* D8, DA : FDIV : rw ST(0) */
michael@0 105 /* D8, DA : FDIVR : rw ST(0) */
michael@0 106 /* D9 F2 : FPTAN : rw ST(0) */
michael@0 107 /* D9 FC : FRNDINT : rw ST(0) */
michael@0 108 /* D9 FB : FSINCOS : rw ST(0) */
michael@0 109 /* D9 FE : FSIN : rw ST(0) */
michael@0 110 /* D9 FA : FSQRT : rw ST(0) */
michael@0 111 /* D9 F4 : FXTRACT : rw ST(0) */
michael@0 112 {{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
michael@0 113
michael@0 114 static op_implicit_list_t list_fcom[] =
michael@0 115 /* D8, DC, DE D9 : FCOM : r ST(0) */
michael@0 116 /* DE, DA : FICOM : r ST(0) */
michael@0 117 /* DF, D8 : FIST : r ST(0) */
michael@0 118 /* D9 E4 : FTST : r ST(0) */
michael@0 119 /* D9 E5 : FXAM : r ST(0) */
michael@0 120 {{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
michael@0 121
michael@0 122 static op_implicit_list_t list_fpatan[] =
michael@0 123 /* D9 F3 : FPATAN : r ST(0), rw ST(1) */
michael@0 124 {{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
michael@0 125
michael@0 126 static op_implicit_list_t list_fprem[] =
michael@0 127 /* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
michael@0 128 /* D9 FD : FSCALE : rw ST(0), r ST(1) */
michael@0 129 {{ OP_R | OP_W, REG_FPU_OFFSET },
michael@0 130 { OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
michael@0 131
michael@0 132 static op_implicit_list_t list_faddp[] =
michael@0 133 /* DE C1 : FADDP : r ST(0), rw ST(1) */
michael@0 134 /* DE E9 : FSUBP : r ST(0), rw ST(1) */
michael@0 135 /* D9 F1 : FYL2X : r ST(0), rw ST(1) */
michael@0 136 /* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
michael@0 137 {{ OP_R, REG_FPU_OFFSET },
michael@0 138 { OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
michael@0 139
michael@0 140 static op_implicit_list_t list_fucompp[] =
michael@0 141 /* DA E9 : FUCOMPP : r ST(0), r ST(1) */
michael@0 142 {{ OP_R, REG_FPU_OFFSET },
michael@0 143 { OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
michael@0 144
michael@0 145 static op_implicit_list_t list_imul[] =
michael@0 146 /* F6 : IMUL : r AL, w AX */
michael@0 147 /* F6 : MUL : r AL, w AX */
michael@0 148 {{ OP_R, REG_BYTE_OFFSET },
michael@0 149 { OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
michael@0 150
michael@0 151 static op_implicit_list_t list_mul[] =
michael@0 152 /* F7 : IMUL : rw EAX, w EDX */
michael@0 153 /* F7 : MUL : rw EAX, w EDX */
michael@0 154 {{ OP_R | OP_W, REG_DWORD_OFFSET },
michael@0 155 { OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
michael@0 156
michael@0 157 static op_implicit_list_t list_lahf[] =
michael@0 158 /* 9F : LAHF : r EFLAGS, w AH */
michael@0 159 {{ OP_R, REG_FLAGS_INDEX },
michael@0 160 { OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
michael@0 161
michael@0 162 static op_implicit_list_t list_ldmxcsr[] =
michael@0 163 /* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
michael@0 164 {{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
michael@0 165
michael@0 166 static op_implicit_list_t list_leave[] =
michael@0 167 /* C9 : LEAVE : rw ESP, w EBP */
michael@0 168 {{ OP_R | OP_W, REG_ESP_INDEX },
michael@0 169 { OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
michael@0 170
michael@0 171 static op_implicit_list_t list_lgdt[] =
michael@0 172 /* 0F 01 : LGDT : w GDTR */
michael@0 173 {{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
michael@0 174
michael@0 175 static op_implicit_list_t list_lidt[] =
michael@0 176 /* 0F 01 : LIDT : w IDTR */
michael@0 177 {{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
michael@0 178
michael@0 179 static op_implicit_list_t list_lldt[] =
michael@0 180 /* 0F 00 : LLDT : w LDTR */
michael@0 181 {{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
michael@0 182
michael@0 183 static op_implicit_list_t list_lmsw[] =
michael@0 184 /* 0F 01 : LMSW : w CR0 */
michael@0 185 {{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
michael@0 186
michael@0 187 static op_implicit_list_t list_loop[] =
michael@0 188 /* E0, E1, E2 : LOOP : rw ECX */
michael@0 189 {{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
michael@0 190
michael@0 191 static op_implicit_list_t list_ltr[] =
michael@0 192 /* 0F 00 : LTR : w Task Register */
michael@0 193 {{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
michael@0 194
michael@0 195 static op_implicit_list_t list_pop[] =
michael@0 196 /* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
michael@0 197 /* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
michael@0 198 {{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
michael@0 199
michael@0 200 static op_implicit_list_t list_popad[] =
michael@0 201 /* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
michael@0 202 {{ OP_R | OP_W, REG_ESP_INDEX },
michael@0 203 { OP_W, REG_DWORD_OFFSET + 7 },
michael@0 204 { OP_W, REG_DWORD_OFFSET + 6 },
michael@0 205 { OP_W, REG_DWORD_OFFSET + 5 },
michael@0 206 { OP_W, REG_DWORD_OFFSET + 3 },
michael@0 207 { OP_W, REG_DWORD_OFFSET + 2 },
michael@0 208 { OP_W, REG_DWORD_OFFSET + 1 },
michael@0 209 { OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
michael@0 210
michael@0 211 static op_implicit_list_t list_popfd[] =
michael@0 212 /* 9D : POPFD : rw esp, w eflags */
michael@0 213 {{ OP_R | OP_W, REG_ESP_INDEX },
michael@0 214 { OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
michael@0 215
michael@0 216 static op_implicit_list_t list_pushad[] =
michael@0 217 /* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
michael@0 218 /* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
michael@0 219 {{ OP_R | OP_W, REG_ESP_INDEX },
michael@0 220 { OP_R, REG_DWORD_OFFSET },
michael@0 221 { OP_R, REG_DWORD_OFFSET + 1 },
michael@0 222 { OP_R, REG_DWORD_OFFSET + 2 },
michael@0 223 { OP_R, REG_DWORD_OFFSET + 3 },
michael@0 224 { OP_R, REG_DWORD_OFFSET + 5 },
michael@0 225 { OP_R, REG_DWORD_OFFSET + 6 },
michael@0 226 { OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
michael@0 227
michael@0 228 static op_implicit_list_t list_pushfd[] =
michael@0 229 /* 9C : PUSHFD : rw esp, r eflags */
michael@0 230 {{ OP_R | OP_W, REG_ESP_INDEX },
michael@0 231 { OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
michael@0 232
michael@0 233 static op_implicit_list_t list_rdmsr[] =
michael@0 234 /* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
michael@0 235 {{ OP_R, REG_DWORD_OFFSET + 1 },
michael@0 236 { OP_W, REG_DWORD_OFFSET + 2 },
michael@0 237 { OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
michael@0 238
michael@0 239 static op_implicit_list_t list_rdpmc[] =
michael@0 240 /* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
michael@0 241 {{ OP_R, REG_DWORD_OFFSET + 1 },
michael@0 242 { OP_W, REG_DWORD_OFFSET + 2 },
michael@0 243 { OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
michael@0 244
michael@0 245 static op_implicit_list_t list_rdtsc[] =
michael@0 246 /* 0F 31 : RDTSC : rw EDX, rw EAX */
michael@0 247 {{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
michael@0 248 { OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
michael@0 249
michael@0 250 static op_implicit_list_t list_rep[] =
michael@0 251 /* F3, F2 ... : REP : rw ECX */
michael@0 252 {{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
michael@0 253
michael@0 254 static op_implicit_list_t list_rsm[] =
michael@0 255 /* 0F AA : RSM : r CR4, r CR0 */
michael@0 256 {{ OP_R, REG_CTRL_OFFSET + 4 },
michael@0 257 { OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
michael@0 258
michael@0 259 static op_implicit_list_t list_sahf[] =
michael@0 260 /* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
michael@0 261 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
michael@0 262
michael@0 263 static op_implicit_list_t list_sgdt[] =
michael@0 264 /* 0F : SGDT : r gdtr */
michael@0 265 /* TODO: finish this! */
michael@0 266 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
michael@0 267
michael@0 268 static op_implicit_list_t list_sidt[] =
michael@0 269 /* 0F : SIDT : r idtr */
michael@0 270 /* TODO: finish this! */
michael@0 271 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
michael@0 272
michael@0 273 static op_implicit_list_t list_sldt[] =
michael@0 274 /* 0F : SLDT : r ldtr */
michael@0 275 /* TODO: finish this! */
michael@0 276 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
michael@0 277
michael@0 278 static op_implicit_list_t list_smsw[] =
michael@0 279 /* 0F : SMSW : r CR0 */
michael@0 280 /* TODO: finish this! */
michael@0 281 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
michael@0 282
michael@0 283 static op_implicit_list_t list_stmxcsr[] =
michael@0 284 /* 0F AE : STMXCSR : r MXCSR */
michael@0 285 /* TODO: finish this! */
michael@0 286 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
michael@0 287
michael@0 288 static op_implicit_list_t list_str[] =
michael@0 289 /* 0F 00 : STR : r TR (task register) */
michael@0 290 /* TODO: finish this! */
michael@0 291 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
michael@0 292
michael@0 293 static op_implicit_list_t list_sysenter[] =
michael@0 294 /* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
michael@0 295 * r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
michael@0 296 /* TODO: finish this! */
michael@0 297 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
michael@0 298
michael@0 299 static op_implicit_list_t list_sysexit[] =
michael@0 300 /* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
michael@0 301 * r sysenter_cs_msr */
michael@0 302 /* TODO: finish this! */
michael@0 303 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
michael@0 304
michael@0 305 static op_implicit_list_t list_wrmsr[] =
michael@0 306 /* 0F 30 : WRMST : r edx, r eax, r ecx */
michael@0 307 /* TODO: finish this! */
michael@0 308 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
michael@0 309
michael@0 310 static op_implicit_list_t list_xlat[] =
michael@0 311 /* D7 : XLAT : rw al r ebx (ptr) */
michael@0 312 /* TODO: finish this! */
michael@0 313 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
michael@0 314 /* TODO:
michael@0 315 * monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
michael@0 316 * mwait 0f 01 c9 eax OP_R ecx OP_R
michael@0 317 */
michael@0 318 static op_implicit_list_t list_monitor[] =
michael@0 319 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
michael@0 320 static op_implicit_list_t list_mwait[] =
michael@0 321 {{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
michael@0 322
michael@0 323 op_implicit_list_t *op_implicit_list[] = {
michael@0 324 /* This is a list of implicit operands which are read/written by
michael@0 325 * various x86 instructions. Note that modifications to the stack
michael@0 326 * register are mentioned here, but that additional information on
michael@0 327 * the effect an instruction has on the stack is contained in the
michael@0 328 * x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
michael@0 329 * eflags register, i.e. setting, clearing, and testing flags, is
michael@0 330 * not recorded here but rather in the flags_set and flags_tested
michael@0 331 * fields of the x86_insn_t.*/
michael@0 332 NULL,
michael@0 333 list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
michael@0 334 list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
michael@0 335 list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
michael@0 336 list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
michael@0 337 list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
michael@0 338 list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
michael@0 339 list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
michael@0 340 list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
michael@0 341 list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
michael@0 342 list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
michael@0 343 /* NOTE: 'REP' is a hack since it is a prefix: if its position
michael@0 344 * in the table changes, then change IDX_IMPLICIT_REP in the .h */
michael@0 345 list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
michael@0 346 list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
michael@0 347 list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
michael@0 348 list_xlat, list_monitor, list_mwait, /* 53 - 55*/
michael@0 349 NULL /* end of list */
michael@0 350 };
michael@0 351
michael@0 352 #define LAST_IMPL_IDX 55
michael@0 353
michael@0 354 static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
michael@0 355 x86_reg_t *reg = &op->data.reg;
michael@0 356 op->type = op_register;
michael@0 357 ia32_handle_register( reg, (unsigned int) val );
michael@0 358 switch (reg->size) {
michael@0 359 case 1:
michael@0 360 op->datatype = op_byte; break;
michael@0 361 case 2:
michael@0 362 op->datatype = op_word; break;
michael@0 363 case 4:
michael@0 364 op->datatype = op_dword; break;
michael@0 365 case 8:
michael@0 366 op->datatype = op_qword; break;
michael@0 367 case 10:
michael@0 368 op->datatype = op_extreal; break;
michael@0 369 case 16:
michael@0 370 op->datatype = op_dqword; break;
michael@0 371 }
michael@0 372 return;
michael@0 373 }
michael@0 374
michael@0 375 /* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
michael@0 376 /* returns number of operands added */
michael@0 377 unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx ) {
michael@0 378 op_implicit_list_t *list;
michael@0 379 x86_op_t *op;
michael@0 380 unsigned int num = 0;
michael@0 381
michael@0 382 if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
michael@0 383 return 0;
michael@0 384 }
michael@0 385
michael@0 386 for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
michael@0 387 enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
michael@0 388 enum x86_op_flags flags = (enum x86_op_flags) (OP_FLAGS(list->type) >> 12);
michael@0 389
michael@0 390 op = NULL;
michael@0 391 /* In some cases (MUL), EAX is an implicit operand hardcoded in
michael@0 392 * the instruction without being explicitly listed in assembly.
michael@0 393 * For this situation, find the hardcoded operand and add the
michael@0 394 * implied flag rather than adding a new implicit operand. */
michael@0 395 x86_oplist_t * existing;
michael@0 396 if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
michael@0 397 for ( existing = insn->operands; existing; existing = existing->next ) {
michael@0 398 if (existing->op.type == op_register &&
michael@0 399 existing->op.data.reg.id == list->operand) {
michael@0 400 op = &existing->op;
michael@0 401 break;
michael@0 402 }
michael@0 403 }
michael@0 404 }
michael@0 405 if (!op) {
michael@0 406 op = x86_operand_new( insn );
michael@0 407 /* all implicit operands are registers */
michael@0 408 handle_impl_reg( op, list->operand );
michael@0 409 /* decrement the 'explicit count' incremented by default in
michael@0 410 * x86_operand_new */
michael@0 411 insn->explicit_count = insn->explicit_count -1;
michael@0 412 }
michael@0 413 if (!op) {
michael@0 414 return num; /* gah! return early */
michael@0 415 }
michael@0 416 op->access |= access;
michael@0 417 op->flags |= flags;
michael@0 418 op->flags |= op_implied;
michael@0 419 }
michael@0 420
michael@0 421 return num;
michael@0 422 }

mercurial