Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "jit/Disassembler.h"
8 :
9 : #include "jit/x86-shared/Encoding-x86-shared.h"
10 :
11 : using namespace js;
12 : using namespace js::jit;
13 : using namespace js::jit::X86Encoding;
14 : using namespace js::jit::Disassembler;
15 :
16 0 : MOZ_COLD static bool REX_W(uint8_t rex) { return (rex >> 3) & 0x1; }
17 0 : MOZ_COLD static bool REX_R(uint8_t rex) { return (rex >> 2) & 0x1; }
18 0 : MOZ_COLD static bool REX_X(uint8_t rex) { return (rex >> 1) & 0x1; }
19 0 : MOZ_COLD static bool REX_B(uint8_t rex) { return (rex >> 0) & 0x1; }
20 :
21 : MOZ_COLD static uint8_t
22 0 : MakeREXFlags(bool w, bool r, bool x, bool b)
23 : {
24 0 : uint8_t rex = (w << 3) | (r << 2) | (x << 1) | (b << 0);
25 0 : MOZ_RELEASE_ASSERT(REX_W(rex) == w);
26 0 : MOZ_RELEASE_ASSERT(REX_R(rex) == r);
27 0 : MOZ_RELEASE_ASSERT(REX_X(rex) == x);
28 0 : MOZ_RELEASE_ASSERT(REX_B(rex) == b);
29 0 : return rex;
30 : }
31 :
32 : MOZ_COLD static ModRmMode
33 0 : ModRM_Mode(uint8_t modrm)
34 : {
35 0 : return ModRmMode((modrm >> 6) & 0x3);
36 : }
37 :
38 : MOZ_COLD static uint8_t
39 0 : ModRM_Reg(uint8_t modrm)
40 : {
41 0 : return (modrm >> 3) & 0x7;
42 : }
43 :
44 : MOZ_COLD static uint8_t
45 0 : ModRM_RM(uint8_t modrm)
46 : {
47 0 : return (modrm >> 0) & 0x7;
48 : }
49 :
50 : MOZ_COLD static bool
51 0 : ModRM_hasSIB(uint8_t modrm)
52 : {
53 0 : return ModRM_Mode(modrm) != ModRmRegister && ModRM_RM(modrm) == hasSib;
54 : }
55 : MOZ_COLD static bool
56 0 : ModRM_hasDisp8(uint8_t modrm)
57 : {
58 0 : return ModRM_Mode(modrm) == ModRmMemoryDisp8;
59 : }
60 : MOZ_COLD static bool
61 0 : ModRM_hasRIP(uint8_t modrm)
62 : {
63 : #ifdef JS_CODEGEN_X64
64 0 : return ModRM_Mode(modrm) == ModRmMemoryNoDisp && ModRM_RM(modrm) == noBase;
65 : #else
66 : return false;
67 : #endif
68 : }
69 : MOZ_COLD static bool
70 0 : ModRM_hasDisp32(uint8_t modrm)
71 : {
72 0 : return ModRM_Mode(modrm) == ModRmMemoryDisp32 ||
73 0 : ModRM_hasRIP(modrm);
74 : }
75 :
76 : MOZ_COLD static uint8_t
77 0 : SIB_SS(uint8_t sib)
78 : {
79 0 : return (sib >> 6) & 0x3;
80 : }
81 :
82 : MOZ_COLD static uint8_t
83 0 : SIB_Index(uint8_t sib)
84 : {
85 0 : return (sib >> 3) & 0x7;
86 : }
87 :
88 : MOZ_COLD static uint8_t
89 0 : SIB_Base(uint8_t sib)
90 : {
91 0 : return (sib >> 0) & 0x7;
92 : }
93 :
94 : MOZ_COLD static bool
95 0 : SIB_hasRIP(uint8_t sib)
96 : {
97 0 : return SIB_Base(sib) == noBase && SIB_Index(sib) == noIndex;
98 : }
99 :
100 : MOZ_COLD static bool
101 0 : HasRIP(uint8_t modrm, uint8_t sib, uint8_t rex)
102 : {
103 0 : return ModRM_hasRIP(modrm) && SIB_hasRIP(sib);
104 : }
105 :
106 : MOZ_COLD static bool
107 0 : HasDisp8(uint8_t modrm)
108 : {
109 0 : return ModRM_hasDisp8(modrm);
110 : }
111 :
112 : MOZ_COLD static bool
113 0 : HasDisp32(uint8_t modrm, uint8_t sib)
114 : {
115 0 : return ModRM_hasDisp32(modrm) ||
116 0 : (SIB_Base(sib) == noBase &&
117 0 : SIB_Index(sib) == noIndex &&
118 0 : ModRM_Mode(modrm) == ModRmMemoryNoDisp);
119 : }
120 :
121 : MOZ_COLD static uint32_t
122 0 : Reg(uint8_t modrm, uint8_t sib, uint8_t rex)
123 : {
124 0 : return ModRM_Reg(modrm) | (REX_R(rex) << 3);
125 : }
126 :
127 : MOZ_COLD static bool
128 0 : HasBase(uint8_t modrm, uint8_t sib)
129 : {
130 0 : return !ModRM_hasSIB(modrm) ||
131 0 : SIB_Base(sib) != noBase ||
132 0 : SIB_Index(sib) != noIndex ||
133 0 : ModRM_Mode(modrm) != ModRmMemoryNoDisp;
134 : }
135 :
136 : MOZ_COLD static RegisterID
137 0 : DecodeBase(uint8_t modrm, uint8_t sib, uint8_t rex)
138 : {
139 0 : return HasBase(modrm, sib)
140 0 : ? RegisterID((ModRM_hasSIB(modrm) ? SIB_Base(sib) : ModRM_RM(modrm)) | (REX_B(rex) << 3))
141 0 : : invalid_reg;
142 : }
143 :
144 : MOZ_COLD static RegisterID
145 0 : DecodeIndex(uint8_t modrm, uint8_t sib, uint8_t rex)
146 : {
147 0 : RegisterID index = RegisterID(SIB_Index(sib) | (REX_X(rex) << 3));
148 0 : return ModRM_hasSIB(modrm) && index != noIndex ? index : invalid_reg;
149 : }
150 :
151 : MOZ_COLD static uint32_t
152 0 : DecodeScale(uint8_t modrm, uint8_t sib, uint8_t rex)
153 : {
154 0 : return ModRM_hasSIB(modrm) ? SIB_SS(sib) : 0;
155 : }
156 :
157 : #define PackOpcode(op0, op1, op2) ((op0) | ((op1) << 8) | ((op2) << 16))
158 : #define Pack2ByteOpcode(op1) PackOpcode(OP_2BYTE_ESCAPE, op1, 0)
159 : #define Pack3ByteOpcode(op1, op2) PackOpcode(OP_2BYTE_ESCAPE, op1, op2)
160 :
161 : uint8_t*
162 0 : js::jit::Disassembler::DisassembleHeapAccess(uint8_t* ptr, HeapAccess* access)
163 : {
164 0 : VexOperandType type = VEX_PS;
165 0 : uint32_t opcode = OP_HLT;
166 0 : uint8_t modrm = 0;
167 0 : uint8_t sib = 0;
168 0 : uint8_t rex = 0;
169 0 : int32_t disp = 0;
170 0 : int32_t imm = 0;
171 0 : bool haveImm = false;
172 0 : int opsize = 4;
173 :
174 : // Legacy prefixes
175 0 : switch (*ptr) {
176 : case PRE_LOCK:
177 : case PRE_PREDICT_BRANCH_NOT_TAKEN: // (obsolete), aka %cs
178 : case 0x3E: // aka predict-branch-taken (obsolete)
179 : case 0x36: // %ss
180 : case 0x26: // %es
181 : case 0x64: // %fs
182 : case 0x65: // %gs
183 : case 0x67: // address-size override
184 0 : MOZ_CRASH("Unable to disassemble instruction");
185 : case PRE_SSE_F2: // aka REPNZ/REPNE
186 0 : type = VEX_SD;
187 0 : ptr++;
188 0 : break;
189 : case PRE_SSE_F3: // aka REP/REPE/REPZ
190 0 : type = VEX_SS;
191 0 : ptr++;
192 0 : break;
193 : case PRE_SSE_66: // aka PRE_OPERAND_SIZE
194 0 : type = VEX_PD;
195 0 : opsize = 2;
196 0 : ptr++;
197 0 : break;
198 : default:
199 0 : break;
200 : }
201 :
202 : // REX and VEX prefixes
203 : {
204 0 : int x = 0, b = 0, m = 1, w = 0;
205 : int r, l, p;
206 0 : switch (*ptr) {
207 : #ifdef JS_CODEGEN_X64
208 : case PRE_REX | 0x0: case PRE_REX | 0x1: case PRE_REX | 0x2: case PRE_REX | 0x3:
209 : case PRE_REX | 0x4: case PRE_REX | 0x5: case PRE_REX | 0x6: case PRE_REX | 0x7:
210 : case PRE_REX | 0x8: case PRE_REX | 0x9: case PRE_REX | 0xa: case PRE_REX | 0xb:
211 : case PRE_REX | 0xc: case PRE_REX | 0xd: case PRE_REX | 0xe: case PRE_REX | 0xf:
212 0 : rex = *ptr++ & 0xf;
213 0 : goto rex_done;
214 : #endif
215 : case PRE_VEX_C4: {
216 0 : if (type != VEX_PS)
217 0 : MOZ_CRASH("Unable to disassemble instruction");
218 0 : ++ptr;
219 0 : uint8_t c4a = *ptr++ ^ 0xe0;
220 0 : uint8_t c4b = *ptr++ ^ 0x78;
221 0 : r = (c4a >> 7) & 0x1;
222 0 : x = (c4a >> 6) & 0x1;
223 0 : b = (c4a >> 5) & 0x1;
224 0 : m = (c4a >> 0) & 0x1f;
225 0 : w = (c4b >> 7) & 0x1;
226 0 : l = (c4b >> 2) & 0x1;
227 0 : p = (c4b >> 0) & 0x3;
228 0 : break;
229 : }
230 : case PRE_VEX_C5: {
231 0 : if (type != VEX_PS)
232 0 : MOZ_CRASH("Unable to disassemble instruction");
233 0 : ++ptr;
234 0 : uint8_t c5 = *ptr++ ^ 0xf8;
235 0 : r = (c5 >> 7) & 0x1;
236 0 : l = (c5 >> 2) & 0x1;
237 0 : p = (c5 >> 0) & 0x3;
238 0 : break;
239 : }
240 : default:
241 0 : goto rex_done;
242 : }
243 0 : if (l != 0) // 256-bit SIMD
244 0 : MOZ_CRASH("Unable to disassemble instruction");
245 0 : type = VexOperandType(p);
246 0 : rex = MakeREXFlags(w, r, x, b);
247 0 : switch (m) {
248 : case 0x1:
249 0 : opcode = Pack2ByteOpcode(*ptr++);
250 0 : goto opcode_done;
251 : case 0x2:
252 0 : opcode = Pack3ByteOpcode(ESCAPE_38, *ptr++);
253 0 : goto opcode_done;
254 : case 0x3:
255 0 : opcode = Pack3ByteOpcode(ESCAPE_3A, *ptr++);
256 0 : goto opcode_done;
257 : default:
258 0 : MOZ_CRASH("Unable to disassemble instruction");
259 : }
260 : }
261 : rex_done:;
262 0 : if (REX_W(rex))
263 0 : opsize = 8;
264 :
265 : // Opcode.
266 0 : opcode = *ptr++;
267 0 : switch (opcode) {
268 : #ifdef JS_CODEGEN_X64
269 : case OP_PUSH_EAX + 0: case OP_PUSH_EAX + 1: case OP_PUSH_EAX + 2: case OP_PUSH_EAX + 3:
270 : case OP_PUSH_EAX + 4: case OP_PUSH_EAX + 5: case OP_PUSH_EAX + 6: case OP_PUSH_EAX + 7:
271 : case OP_POP_EAX + 0: case OP_POP_EAX + 1: case OP_POP_EAX + 2: case OP_POP_EAX + 3:
272 : case OP_POP_EAX + 4: case OP_POP_EAX + 5: case OP_POP_EAX + 6: case OP_POP_EAX + 7:
273 : case OP_PUSH_Iz:
274 : case OP_PUSH_Ib:
275 0 : opsize = 8;
276 0 : break;
277 : #endif
278 : case OP_2BYTE_ESCAPE:
279 0 : opcode |= *ptr << 8;
280 0 : switch (*ptr++) {
281 : case ESCAPE_38:
282 : case ESCAPE_3A:
283 0 : opcode |= *ptr++ << 16;
284 0 : break;
285 : default:
286 0 : break;
287 : }
288 0 : break;
289 : default:
290 0 : break;
291 : }
292 : opcode_done:;
293 :
294 : // ModR/M
295 0 : modrm = *ptr++;
296 :
297 : // SIB
298 0 : if (ModRM_hasSIB(modrm))
299 0 : sib = *ptr++;
300 :
301 : // Address Displacement
302 0 : if (HasDisp8(modrm)) {
303 0 : disp = int8_t(*ptr++);
304 0 : } else if (HasDisp32(modrm, sib)) {
305 0 : memcpy(&disp, ptr, sizeof(int32_t));
306 0 : ptr += sizeof(int32_t);
307 : }
308 :
309 : // Immediate operand
310 0 : switch (opcode) {
311 : case OP_PUSH_Ib:
312 : case OP_IMUL_GvEvIb:
313 : case OP_GROUP1_EbIb:
314 : case OP_GROUP1_EvIb:
315 : case OP_TEST_EAXIb:
316 : case OP_GROUP2_EvIb:
317 : case OP_GROUP11_EvIb:
318 : case OP_GROUP3_EbIb:
319 : case Pack2ByteOpcode(OP2_PSHUFD_VdqWdqIb):
320 : case Pack2ByteOpcode(OP2_PSLLD_UdqIb): // aka OP2_PSRAD_UdqIb, aka OP2_PSRLD_UdqIb
321 : case Pack2ByteOpcode(OP2_PEXTRW_GdUdIb):
322 : case Pack2ByteOpcode(OP2_SHUFPS_VpsWpsIb):
323 : case Pack3ByteOpcode(ESCAPE_3A, OP3_PEXTRD_EdVdqIb):
324 : case Pack3ByteOpcode(ESCAPE_3A, OP3_BLENDPS_VpsWpsIb):
325 : case Pack3ByteOpcode(ESCAPE_3A, OP3_PINSRD_VdqEdIb):
326 : // 8-bit signed immediate
327 0 : imm = int8_t(*ptr++);
328 0 : haveImm = true;
329 0 : break;
330 : case OP_RET_Iz:
331 : // 16-bit unsigned immediate
332 0 : memcpy(&imm, ptr, sizeof(int16_t));
333 0 : ptr += sizeof(int16_t);
334 0 : haveImm = true;
335 0 : break;
336 : case OP_ADD_EAXIv:
337 : case OP_OR_EAXIv:
338 : case OP_AND_EAXIv:
339 : case OP_SUB_EAXIv:
340 : case OP_XOR_EAXIv:
341 : case OP_CMP_EAXIv:
342 : case OP_PUSH_Iz:
343 : case OP_IMUL_GvEvIz:
344 : case OP_GROUP1_EvIz:
345 : case OP_TEST_EAXIv:
346 : case OP_MOV_EAXIv:
347 : case OP_GROUP3_EvIz:
348 : // 32-bit signed immediate
349 0 : memcpy(&imm, ptr, sizeof(int32_t));
350 0 : ptr += sizeof(int32_t);
351 0 : haveImm = true;
352 0 : break;
353 : case OP_GROUP11_EvIz:
354 : // opsize-sized signed immediate
355 0 : memcpy(&imm, ptr, opsize);
356 0 : imm = (imm << (32 - opsize * 8)) >> (32 - opsize * 8);
357 0 : ptr += opsize;
358 0 : haveImm = true;
359 0 : break;
360 : default:
361 0 : break;
362 : }
363 :
364 : // Interpret the opcode.
365 0 : if (HasRIP(modrm, sib, rex))
366 0 : MOZ_CRASH("Unable to disassemble instruction");
367 :
368 0 : size_t memSize = 0;
369 0 : OtherOperand otherOperand(imm);
370 0 : HeapAccess::Kind kind = HeapAccess::Unknown;
371 0 : RegisterID gpr(RegisterID(Reg(modrm, sib, rex)));
372 0 : XMMRegisterID xmm(XMMRegisterID(Reg(modrm, sib, rex)));
373 : ComplexAddress addr(disp,
374 0 : DecodeBase(modrm, sib, rex),
375 0 : DecodeIndex(modrm, sib, rex),
376 0 : DecodeScale(modrm, sib, rex));
377 0 : switch (opcode) {
378 : case OP_GROUP11_EvIb:
379 0 : if (gpr != RegisterID(GROUP11_MOV))
380 0 : MOZ_CRASH("Unable to disassemble instruction");
381 0 : MOZ_RELEASE_ASSERT(haveImm);
382 0 : memSize = 1;
383 0 : kind = HeapAccess::Store;
384 0 : break;
385 : case OP_GROUP11_EvIz:
386 0 : if (gpr != RegisterID(GROUP11_MOV))
387 0 : MOZ_CRASH("Unable to disassemble instruction");
388 0 : MOZ_RELEASE_ASSERT(haveImm);
389 0 : memSize = opsize;
390 0 : kind = HeapAccess::Store;
391 0 : break;
392 : case OP_MOV_GvEv:
393 0 : MOZ_RELEASE_ASSERT(!haveImm);
394 0 : otherOperand = OtherOperand(gpr);
395 0 : memSize = opsize;
396 0 : kind = HeapAccess::Load;
397 0 : break;
398 : case OP_MOV_GvEb:
399 0 : MOZ_RELEASE_ASSERT(!haveImm);
400 0 : otherOperand = OtherOperand(gpr);
401 0 : memSize = 1;
402 0 : kind = HeapAccess::Load;
403 0 : break;
404 : case OP_MOV_EvGv:
405 0 : if (!haveImm)
406 0 : otherOperand = OtherOperand(gpr);
407 0 : memSize = opsize;
408 0 : kind = HeapAccess::Store;
409 0 : break;
410 : case OP_MOV_EbGv:
411 0 : if (!haveImm)
412 0 : otherOperand = OtherOperand(gpr);
413 0 : memSize = 1;
414 0 : kind = HeapAccess::Store;
415 0 : break;
416 : case Pack2ByteOpcode(OP2_MOVZX_GvEb):
417 0 : MOZ_RELEASE_ASSERT(!haveImm);
418 0 : otherOperand = OtherOperand(gpr);
419 0 : memSize = 1;
420 0 : kind = HeapAccess::Load;
421 0 : break;
422 : case Pack2ByteOpcode(OP2_MOVZX_GvEw):
423 0 : MOZ_RELEASE_ASSERT(!haveImm);
424 0 : otherOperand = OtherOperand(gpr);
425 0 : memSize = 2;
426 0 : kind = HeapAccess::Load;
427 0 : break;
428 : case Pack2ByteOpcode(OP2_MOVSX_GvEb):
429 0 : MOZ_RELEASE_ASSERT(!haveImm);
430 0 : otherOperand = OtherOperand(gpr);
431 0 : memSize = 1;
432 0 : kind = opsize == 8 ? HeapAccess::LoadSext64 : HeapAccess::LoadSext32;
433 0 : break;
434 : case Pack2ByteOpcode(OP2_MOVSX_GvEw):
435 0 : MOZ_RELEASE_ASSERT(!haveImm);
436 0 : otherOperand = OtherOperand(gpr);
437 0 : memSize = 2;
438 0 : kind = opsize == 8 ? HeapAccess::LoadSext64 : HeapAccess::LoadSext32;
439 0 : break;
440 : #ifdef JS_CODEGEN_X64
441 : case OP_MOVSXD_GvEv:
442 0 : MOZ_RELEASE_ASSERT(!haveImm);
443 0 : otherOperand = OtherOperand(gpr);
444 0 : memSize = 4;
445 0 : kind = HeapAccess::LoadSext64;
446 0 : break;
447 : #endif // JS_CODEGEN_X64
448 : case Pack2ByteOpcode(OP2_MOVDQ_VdqWdq): // aka OP2_MOVDQ_VsdWsd
449 : case Pack2ByteOpcode(OP2_MOVAPS_VsdWsd):
450 0 : MOZ_RELEASE_ASSERT(!haveImm);
451 0 : otherOperand = OtherOperand(xmm);
452 0 : memSize = 16;
453 0 : kind = HeapAccess::Load;
454 0 : break;
455 : case Pack2ByteOpcode(OP2_MOVSD_VsdWsd): // aka OP2_MOVPS_VpsWps
456 0 : MOZ_RELEASE_ASSERT(!haveImm);
457 0 : otherOperand = OtherOperand(xmm);
458 0 : switch (type) {
459 0 : case VEX_SS: memSize = 4; break;
460 0 : case VEX_SD: memSize = 8; break;
461 : case VEX_PS:
462 0 : case VEX_PD: memSize = 16; break;
463 0 : default: MOZ_CRASH("Unexpected VEX type");
464 : }
465 0 : kind = HeapAccess::Load;
466 0 : break;
467 : case Pack2ByteOpcode(OP2_MOVDQ_WdqVdq):
468 0 : MOZ_RELEASE_ASSERT(!haveImm);
469 0 : otherOperand = OtherOperand(xmm);
470 0 : memSize = 16;
471 0 : kind = HeapAccess::Store;
472 0 : break;
473 : case Pack2ByteOpcode(OP2_MOVSD_WsdVsd): // aka OP2_MOVPS_WpsVps
474 0 : MOZ_RELEASE_ASSERT(!haveImm);
475 0 : otherOperand = OtherOperand(xmm);
476 0 : switch (type) {
477 0 : case VEX_SS: memSize = 4; break;
478 0 : case VEX_SD: memSize = 8; break;
479 : case VEX_PS:
480 0 : case VEX_PD: memSize = 16; break;
481 0 : default: MOZ_CRASH("Unexpected VEX type");
482 : }
483 0 : kind = HeapAccess::Store;
484 0 : break;
485 : case Pack2ByteOpcode(OP2_MOVD_VdEd):
486 0 : MOZ_RELEASE_ASSERT(!haveImm);
487 0 : otherOperand = OtherOperand(xmm);
488 0 : switch (type) {
489 0 : case VEX_PD: memSize = 4; break;
490 0 : default: MOZ_CRASH("Unexpected VEX type");
491 : }
492 0 : kind = HeapAccess::Load;
493 0 : break;
494 : case Pack2ByteOpcode(OP2_MOVQ_WdVd):
495 0 : MOZ_RELEASE_ASSERT(!haveImm);
496 0 : otherOperand = OtherOperand(xmm);
497 0 : switch (type) {
498 0 : case VEX_PD: memSize = 8; break;
499 0 : default: MOZ_CRASH("Unexpected VEX type");
500 : }
501 0 : kind = HeapAccess::Store;
502 0 : break;
503 : case Pack2ByteOpcode(OP2_MOVD_EdVd): // aka OP2_MOVQ_VdWd
504 0 : MOZ_RELEASE_ASSERT(!haveImm);
505 0 : otherOperand = OtherOperand(xmm);
506 0 : switch (type) {
507 0 : case VEX_SS: memSize = 8; kind = HeapAccess::Load; break;
508 0 : case VEX_PD: memSize = 4; kind = HeapAccess::Store; break;
509 0 : default: MOZ_CRASH("Unexpected VEX type");
510 : }
511 0 : break;
512 : default:
513 0 : MOZ_CRASH("Unable to disassemble instruction");
514 : }
515 :
516 0 : *access = HeapAccess(kind, memSize, addr, otherOperand);
517 0 : return ptr;
518 : }
519 :
520 : #ifdef DEBUG
521 : void
522 0 : js::jit::Disassembler::DumpHeapAccess(const HeapAccess& access)
523 : {
524 0 : switch (access.kind()) {
525 0 : case HeapAccess::Store: fprintf(stderr, "store"); break;
526 0 : case HeapAccess::Load: fprintf(stderr, "load"); break;
527 0 : case HeapAccess::LoadSext32: fprintf(stderr, "loadSext32"); break;
528 0 : case HeapAccess::LoadSext64: fprintf(stderr, "loadSext64"); break;
529 0 : default: fprintf(stderr, "unknown"); break;
530 : }
531 0 : fprintf(stderr, "%u ", unsigned(access.size()));
532 :
533 0 : switch (access.otherOperand().kind()) {
534 : case OtherOperand::Imm:
535 0 : fprintf(stderr, "imm %d", access.otherOperand().imm());
536 0 : break;
537 : case OtherOperand::GPR:
538 0 : fprintf(stderr, "gpr %s", X86Encoding::GPRegName(access.otherOperand().gpr()));
539 0 : break;
540 : case OtherOperand::FPR:
541 0 : fprintf(stderr, "fpr %s", X86Encoding::XMMRegName(access.otherOperand().fpr()));
542 0 : break;
543 0 : default: fprintf(stderr, "unknown");
544 : }
545 :
546 0 : fprintf(stderr, " @ ");
547 :
548 0 : if (access.address().isPCRelative()) {
549 0 : fprintf(stderr, MEM_o32r " ", ADDR_o32r(access.address().disp()));
550 0 : } else if (access.address().hasIndex()) {
551 0 : if (access.address().hasBase()) {
552 0 : fprintf(stderr, MEM_obs " ",
553 0 : ADDR_obs(access.address().disp(), access.address().base(),
554 0 : access.address().index(), access.address().scale()));
555 : } else {
556 0 : fprintf(stderr, MEM_os " ",
557 0 : ADDR_os(access.address().disp(),
558 0 : access.address().index(), access.address().scale()));
559 : }
560 0 : } else if (access.address().hasBase()) {
561 0 : fprintf(stderr, MEM_ob " ", ADDR_ob(access.address().disp(), access.address().base()));
562 : } else {
563 0 : fprintf(stderr, MEM_o " ", ADDR_o(access.address().disp()));
564 : }
565 :
566 0 : fprintf(stderr, "\n");
567 0 : }
568 : #endif
|