1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// File: Amd64walker.cpp
6//
7
8//
9// AMD64 instruction decoding/stepping logic
10//
11//*****************************************************************************
12
13#include "stdafx.h"
14
15#include "walker.h"
16
17#include "frames.h"
18#include "openum.h"
19
20#ifdef _TARGET_AMD64_
21
22//
23// The AMD64 walker is currently pretty minimal. It only recognizes call and return opcodes, plus a few jumps. The rest
24// is treated as unknown.
25//
26void NativeWalker::Decode()
27{
28 const BYTE *ip = m_ip;
29
30 m_type = WALK_UNKNOWN;
31 m_skipIP = NULL;
32 m_nextIP = NULL;
33
34 BYTE rex = NULL;
35
36 LOG((LF_CORDB, LL_INFO100000, "NW:Decode: m_ip 0x%x\n", m_ip));
37
38 BYTE prefix = *ip;
39 if (prefix == 0xcc)
40 {
41 prefix = (BYTE)DebuggerController::GetPatchedOpcode(m_ip);
42 LOG((LF_CORDB, LL_INFO100000, "NW:Decode 1st byte was patched, might have been prefix\n"));
43 }
44
45 //
46 // Skip instruction prefixes
47 //
48 do
49 {
50 switch (prefix)
51 {
52 // Segment overrides
53 case 0x26: // ES
54 case 0x2E: // CS
55 case 0x36: // SS
56 case 0x3E: // DS
57 case 0x64: // FS
58 case 0x65: // GS
59
60 // Size overrides
61 case 0x66: // Operand-Size
62 case 0x67: // Address-Size
63
64 // Lock
65 case 0xf0:
66
67 // String REP prefixes
68 case 0xf2: // REPNE/REPNZ
69 case 0xf3:
70 LOG((LF_CORDB, LL_INFO10000, "NW:Decode: prefix:%0.2x ", prefix));
71 ip++;
72 continue;
73
74 // REX register extension prefixes
75 case 0x40:
76 case 0x41:
77 case 0x42:
78 case 0x43:
79 case 0x44:
80 case 0x45:
81 case 0x46:
82 case 0x47:
83 case 0x48:
84 case 0x49:
85 case 0x4a:
86 case 0x4b:
87 case 0x4c:
88 case 0x4d:
89 case 0x4e:
90 case 0x4f:
91 LOG((LF_CORDB, LL_INFO10000, "NW:Decode: REX prefix:%0.2x ", prefix));
92 // make sure to set rex to prefix, not *ip because *ip still represents the
93 // codestream which has a 0xcc in it.
94 rex = prefix;
95 ip++;
96 continue;
97
98 default:
99 break;
100 }
101 } while (0);
102
103 // Read the opcode
104 m_opcode = *ip++;
105
106 LOG((LF_CORDB, LL_INFO100000, "NW:Decode: ip 0x%x, m_opcode:%0.2x\n", ip, m_opcode));
107
108 // Don't remove this, when we did the check above for the prefix we didn't modify the codestream
109 // and since m_opcode was just taken directly from the code stream it will be patched if we
110 // didn't have a prefix
111 if (m_opcode == 0xcc)
112 {
113 m_opcode = (BYTE)DebuggerController::GetPatchedOpcode(m_ip);
114 LOG((LF_CORDB, LL_INFO100000, "NW:Decode after patch look up: m_opcode:%0.2x\n", m_opcode));
115 }
116
117 // Setup rex bits if needed
118 BYTE rex_b = 0;
119 BYTE rex_x = 0;
120 BYTE rex_r = 0;
121
122 if (rex != NULL)
123 {
124 rex_b = (rex & 0x1); // high bit to modrm r/m field or SIB base field or OPCODE reg field -- Hmm, when which?
125 rex_x = (rex & 0x2) >> 1; // high bit to sib index field
126 rex_r = (rex & 0x4) >> 2; // high bit to modrm reg field
127 }
128
129 // Analyze what we can of the opcode
130 switch (m_opcode)
131 {
132 case 0xff:
133 {
134 BYTE modrm = *ip++;
135
136 // Ignore "inc dword ptr [reg]" instructions
137 if (modrm == 0)
138 break;
139
140 BYTE mod = (modrm & 0xC0) >> 6;
141 BYTE reg = (modrm & 0x38) >> 3;
142 BYTE rm = (modrm & 0x07);
143
144 reg |= (rex_r << 3);
145 rm |= (rex_b << 3);
146
147 if ((reg < 2) || (reg > 5 && reg < 8) || (reg > 15)) {
148 // not a valid register for a CALL or BRANCH
149 return;
150 }
151
152 BYTE *result;
153 WORD displace;
154
155 // See: Tables A-15,16,17 in AMD Dev Manual 3 for information
156 // about how the ModRM/SIB/REX bytes interact.
157
158 switch (mod)
159 {
160 case 0:
161 case 1:
162 case 2:
163 if ((rm & 0x07) == 4) // we have an SIB byte following
164 {
165 //
166 // Get values from the SIB byte
167 //
168 BYTE sib = *ip;
169
170 _ASSERT(sib != NULL);
171
172 BYTE ss = (sib & 0xC0) >> 6;
173 BYTE index = (sib & 0x38) >> 3;
174 BYTE base = (sib & 0x07);
175
176 index |= (rex_x << 3);
177 base |= (rex_b << 3);
178
179 ip++;
180
181 //
182 // Get starting value
183 //
184 if ((mod == 0) && ((base & 0x07) == 5))
185 {
186 result = 0;
187 }
188 else
189 {
190 result = (BYTE *)(size_t)GetRegisterValue(base);
191 }
192
193 //
194 // Add in the [index]
195 //
196 if (index != 0x4)
197 {
198 result = result + (GetRegisterValue(index) << ss);
199 }
200
201 //
202 // Finally add in the offset
203 //
204 if (mod == 0)
205 {
206 if ((base & 0x07) == 5)
207 {
208 result = result + *((INT32*)ip);
209 displace = 7;
210 }
211 else
212 {
213 displace = 3;
214 }
215 }
216 else if (mod == 1)
217 {
218 result = result + *((INT8*)ip);
219 displace = 4;
220 }
221 else // mod == 2
222 {
223 result = result + *((INT32*)ip);
224 displace = 7;
225 }
226
227 }
228 else
229 {
230 //
231 // Get the value we need from the register.
232 //
233
234 // Check for RIP-relative addressing mode.
235 if ((mod == 0) && ((rm & 0x07) == 5))
236 {
237 displace = 6; // 1 byte opcode + 1 byte modrm + 4 byte displacement (signed)
238 result = const_cast<BYTE *>(m_ip) + displace + *(reinterpret_cast<const INT32*>(ip));
239 }
240 else
241 {
242 result = (BYTE *)GetRegisterValue(rm);
243
244 if (mod == 0)
245 {
246 displace = 2;
247 }
248 else if (mod == 1)
249 {
250 result = result + *((INT8*)ip);
251 displace = 3;
252 }
253 else // mod == 2
254 {
255 result = result + *((INT32*)ip);
256 displace = 6;
257 }
258 }
259 }
260
261 //
262 // Now dereference thru the result to get the resulting IP.
263 //
264 result = (BYTE *)(*((UINT64*)result));
265
266 break;
267
268 case 3:
269 default:
270 // The operand is stored in a register.
271 result = (BYTE *)GetRegisterValue(rm);
272 displace = 2;
273
274 break;
275
276 }
277
278 // the instruction uses r8-r15, add in the extra byte to the displacement
279 // for the REX prefix which was used to specify the extended register
280 if (rex != NULL)
281 {
282 displace++;
283 }
284
285 // because we already checked register validity for CALL/BRANCH
286 // instructions above we can assume that there is no other option
287 if ((reg == 4) || (reg == 5))
288 {
289 m_type = WALK_BRANCH;
290 }
291 else
292 {
293 m_type = WALK_CALL;
294 }
295 m_nextIP = result;
296 m_skipIP = m_ip + displace;
297 break;
298 }
299 case 0xe8:
300 {
301 m_type = WALK_CALL;
302
303 // Sign-extend the displacement is necessary.
304 INT32 disp = *((INT32*)ip);
305 m_nextIP = ip + 4 + (disp < 0 ? (disp | 0xffffffff00000000) : disp);
306 m_skipIP = ip + 4;
307
308 break;
309 }
310 case 0xe9:
311 {
312 m_type = WALK_BRANCH;
313
314 // Sign-extend the displacement is necessary.
315 INT32 disp = *((INT32*)ip);
316 m_nextIP = ip + 4 + (disp < 0 ? (disp | 0xffffffff00000000) : disp);
317 m_skipIP = ip + 4;
318
319 break;
320 }
321 case 0xc2:
322 case 0xc3:
323 case 0xca:
324 case 0xcb:
325 {
326 m_type = WALK_RETURN;
327 break;
328 }
329 default:
330 break;
331 }
332}
333
334
335//
336// Given a regdisplay and a register number, return the value of the register.
337//
338
339UINT64 NativeWalker::GetRegisterValue(int registerNumber)
340{
341 if (m_registers == NULL) {
342 return 0;
343 }
344
345 switch (registerNumber)
346 {
347 case 0:
348 return m_registers->pCurrentContext->Rax;
349 break;
350 case 1:
351 return m_registers->pCurrentContext->Rcx;
352 break;
353 case 2:
354 return m_registers->pCurrentContext->Rdx;
355 break;
356 case 3:
357 return m_registers->pCurrentContext->Rbx;
358 break;
359 case 4:
360 return m_registers->pCurrentContext->Rsp;
361 break;
362 case 5:
363 return m_registers->pCurrentContext->Rbp;
364 break;
365 case 6:
366 return m_registers->pCurrentContext->Rsi;
367 break;
368 case 7:
369 return m_registers->pCurrentContext->Rdi;
370 break;
371 case 8:
372 return m_registers->pCurrentContext->R8;
373 break;
374 case 9:
375 return m_registers->pCurrentContext->R9;
376 break;
377 case 10:
378 return m_registers->pCurrentContext->R10;
379 break;
380 case 11:
381 return m_registers->pCurrentContext->R11;
382 break;
383 case 12:
384 return m_registers->pCurrentContext->R12;
385 break;
386 case 13:
387 return m_registers->pCurrentContext->R13;
388 break;
389 case 14:
390 return m_registers->pCurrentContext->R14;
391 break;
392 case 15:
393 return m_registers->pCurrentContext->R15;
394 break;
395 default:
396 _ASSERTE(!"Invalid register number!");
397 }
398
399 return 0;
400}
401
402
403// mod reg r/m
404// bits 7-6 5-3 2-0
405struct ModRMByte
406{
407 BYTE rm :3;
408 BYTE reg:3;
409 BYTE mod:2;
410};
411
412// fixed W R X B
413// bits 7-4 3 2 1 0
414struct RexByte
415{
416 BYTE b:1;
417 BYTE x:1;
418 BYTE r:1;
419 BYTE w:1;
420 BYTE fixed:4;
421};
422
423// static
424void NativeWalker::DecodeInstructionForPatchSkip(const BYTE *address, InstructionAttribute * pInstrAttrib)
425{
426 //
427 // Skip instruction prefixes
428 //
429
430 LOG((LF_CORDB, LL_INFO10000, "Patch decode: "));
431
432 // for reads and writes where the destination is a RIP-relative address pInstrAttrib->m_cOperandSize will contain the size in bytes of the pointee; in all other
433 // cases it will be zero. if the RIP-relative address is being written to then pInstrAttrib->m_fIsWrite will be true; in all other cases it will be false.
434 // similar to cbImmedSize in some cases we'll set pInstrAttrib->m_cOperandSize to 0x3 meaning that the prefix will determine the size if one is specified.
435 pInstrAttrib->m_cOperandSize = 0;
436 pInstrAttrib->m_fIsWrite = false;
437
438 if (pInstrAttrib == NULL)
439 {
440 return;
441 }
442
443 // These three legacy prefixes are used to modify some of the two-byte opcodes.
444 bool fPrefix66 = false;
445 bool fPrefixF2 = false;
446 bool fPrefixF3 = false;
447
448 bool fRex = false;
449 bool fModRM = false;
450
451 RexByte rex = {0};
452 ModRMByte modrm = {0};
453
454 // We use 0x3 to indicate that we need to look at the operand-size override and the rex byte
455 // to determine whether the immediate size is 2 bytes or 4 bytes.
456 BYTE cbImmedSize = 0;
457
458 const BYTE* originalAddr = address;
459
460 do
461 {
462 switch (*address)
463 {
464 // Operand-Size override
465 case 0x66:
466 fPrefix66 = true;
467 goto LLegacyPrefix;
468
469 // Repeat (REP/REPE/REPZ)
470 case 0xf2:
471 fPrefixF2 = true;
472 goto LLegacyPrefix;
473
474 // Repeat (REPNE/REPNZ)
475 case 0xf3:
476 fPrefixF3 = true;
477 goto LLegacyPrefix;
478
479 // Address-Size override
480 case 0x67: // fall through
481
482 // Segment overrides
483 case 0x26: // ES
484 case 0x2E: // CS
485 case 0x36: // SS
486 case 0x3E: // DS
487 case 0x64: // FS
488 case 0x65: // GS // fall through
489
490 // Lock
491 case 0xf0:
492LLegacyPrefix:
493 LOG((LF_CORDB, LL_INFO10000, "prefix:%0.2x ", *address));
494 address++;
495 continue;
496
497 // REX register extension prefixes
498 case 0x40:
499 case 0x41:
500 case 0x42:
501 case 0x43:
502 case 0x44:
503 case 0x45:
504 case 0x46:
505 case 0x47:
506 case 0x48:
507 case 0x49:
508 case 0x4a:
509 case 0x4b:
510 case 0x4c:
511 case 0x4d:
512 case 0x4e:
513 case 0x4f:
514 LOG((LF_CORDB, LL_INFO10000, "prefix:%0.2x ", *address));
515 fRex = true;
516 rex = *(RexByte*)address;
517 address++;
518 continue;
519
520 default:
521 break;
522 }
523 } while (0);
524
525 pInstrAttrib->Reset();
526
527 BYTE opcode0 = *address;
528 BYTE opcode1 = *(address + 1); // this is only valid if the first opcode byte is 0x0F
529
530 // Handle AVX encodings. Note that these can mostly be handled as if they are aliases
531 // for a corresponding SSE encoding.
532 // See Figure 2-9 in "Intel 64 and IA-32 Architectures Software Developer's Manual".
533
534 if (opcode0 == 0xC4 || opcode0 == 0xC5)
535 {
536 BYTE pp;
537 if (opcode0 == 0xC4)
538 {
539 BYTE opcode2 = *(address + 2);
540 address++;
541
542 // REX bits are encoded in inverted form.
543 // R,X, and B are the top bits (in that order) of opcode1.
544 // W is the top bit of opcode2.
545 if ((opcode1 & 0x80) != 0)
546 {
547 rex.b = 1;
548 fRex = true;
549 }
550 if ((opcode1 & 0x40) == 0)
551 {
552 rex.x = 1;
553 fRex = true;
554 }
555 if ((opcode1 & 0x20) == 0)
556 {
557 rex.b = 1;
558 fRex = true;
559 }
560 if ((opcode2 & 0x80) != 0)
561 {
562 rex.w = 1;
563 fRex = true;
564 }
565
566 pp = opcode2 & 0x3;
567
568 BYTE mmBits = opcode1 & 0x1f;
569 BYTE impliedOpcode1 = 0;
570 switch(mmBits)
571 {
572 case 1: break; // No implied leading byte.
573 case 2: impliedOpcode1 = 0x38; break;
574 case 3: impliedOpcode1 = 0x3A; break;
575 default: _ASSERTE(!"NW::DIFPS - invalid opcode"); break;
576 }
577
578 if (impliedOpcode1 != 0)
579 {
580 opcode1 = impliedOpcode1;
581 }
582 else
583 {
584 opcode1 = *address;
585 address++;
586 }
587 }
588 else
589 {
590 pp = opcode1 & 0x3;
591 if ((opcode1 & 0x80) == 0)
592 {
593 // The two-byte VEX encoding only encodes the 'R' bit.
594 fRex = true;
595 rex.r = 1;
596 }
597 opcode1 = *address;
598 address++;
599 }
600 opcode0 = 0x0f;
601 switch (pp)
602 {
603 case 1: fPrefix66 = true; break;
604 case 2: fPrefixF3 = true; break;
605 case 3: fPrefixF2 = true; break;
606 }
607 }
608
609 // The following opcode decoding follows the tables in "Appendix A Opcode and Operand Encodings" of
610 // "AMD64 Architecture Programmer's Manual Volume 3"
611
612 // one-byte opcodes
613 if (opcode0 != 0x0F)
614 {
615 BYTE highNibble = (opcode0 & 0xF0) >> 4;
616 BYTE lowNibble = (opcode0 & 0x0F);
617
618 switch (highNibble)
619 {
620 case 0x0:
621 case 0x1:
622 case 0x2:
623 case 0x3:
624 if ((lowNibble == 0x6) || (lowNibble == 0x7) || (lowNibble == 0xE) || (lowNibble == 0xF))
625 {
626 _ASSERTE(!"NW::DIFPS - invalid opcode");
627 }
628
629 // CMP
630 if ( (lowNibble <= 0x3) ||
631 ((lowNibble >= 0x8) && (lowNibble <= 0xB)) )
632 {
633 fModRM = true;
634 }
635
636 // ADD/XOR reg/mem, reg
637 if (lowNibble == 0x0)
638 {
639 pInstrAttrib->m_cOperandSize = 0x1;
640 pInstrAttrib->m_fIsWrite = true;
641 }
642 else if (lowNibble == 0x1)
643 {
644 pInstrAttrib->m_cOperandSize = 0x3;
645 pInstrAttrib->m_fIsWrite = true;
646 }
647 // XOR reg, reg/mem
648 else if (lowNibble == 0x2)
649 {
650 pInstrAttrib->m_cOperandSize = 0x1;
651 }
652 else if (lowNibble == 0x3)
653 {
654 pInstrAttrib->m_cOperandSize = 0x3;
655 }
656
657 break;
658
659 case 0x4:
660 case 0x5:
661 break;
662
663 case 0x6:
664 // IMUL
665 if (lowNibble == 0x9)
666 {
667 fModRM = true;
668 cbImmedSize = 0x3;
669 }
670 else if (lowNibble == 0xB)
671 {
672 fModRM = true;
673 cbImmedSize = 0x1;
674 }
675 else if (lowNibble == 0x3)
676 {
677 if (fRex)
678 {
679 // MOVSXD
680 fModRM = true;
681 }
682 }
683 break;
684
685 case 0x7:
686 break;
687
688 case 0x8:
689 fModRM = true;
690
691 // Group 1: lowNibble in [0x0, 0x3]
692 _ASSERTE(lowNibble != 0x2);
693
694 // ADD/XOR reg/mem, imm
695 if (lowNibble == 0x0)
696 {
697 cbImmedSize = 1;
698 pInstrAttrib->m_cOperandSize = 1;
699 pInstrAttrib->m_fIsWrite = true;
700 }
701 else if (lowNibble == 0x1)
702 {
703 cbImmedSize = 3;
704 pInstrAttrib->m_cOperandSize = 3;
705 pInstrAttrib->m_fIsWrite = true;
706 }
707 else if (lowNibble == 0x3)
708 {
709 cbImmedSize = 1;
710 pInstrAttrib->m_cOperandSize = 3;
711 pInstrAttrib->m_fIsWrite = true;
712 }
713 // MOV reg/mem, reg
714 else if (lowNibble == 0x8)
715 {
716 pInstrAttrib->m_cOperandSize = 0x1;
717 pInstrAttrib->m_fIsWrite = true;
718 }
719 else if (lowNibble == 0x9)
720 {
721 pInstrAttrib->m_cOperandSize = 0x3;
722 pInstrAttrib->m_fIsWrite = true;
723 }
724 // MOV reg, reg/mem
725 else if (lowNibble == 0xA)
726 {
727 pInstrAttrib->m_cOperandSize = 0x1;
728 }
729 else if (lowNibble == 0xB)
730 {
731 pInstrAttrib->m_cOperandSize = 0x3;
732 }
733
734 break;
735
736 case 0x9:
737 case 0xA:
738 case 0xB:
739 break;
740
741 case 0xC:
742 if ((lowNibble == 0x4) || (lowNibble == 0x5) || (lowNibble == 0xE))
743 {
744 _ASSERTE(!"NW::DIFPS - invalid opcode");
745 }
746
747 // RET
748 if ((lowNibble == 0x2) || (lowNibble == 0x3))
749 {
750 break;
751 }
752
753 // Group 2 (part 1): lowNibble in [0x0, 0x1]
754 // RCL reg/mem, imm
755 if (lowNibble == 0x0)
756 {
757 fModRM = true;
758 cbImmedSize = 0x1;
759 pInstrAttrib->m_cOperandSize = 0x1;
760 pInstrAttrib->m_fIsWrite = true;
761 }
762 else if (lowNibble == 0x1)
763 {
764 fModRM = true;
765 cbImmedSize = 0x1;
766 pInstrAttrib->m_cOperandSize = 0x3;
767 pInstrAttrib->m_fIsWrite = true;
768 }
769 // Group 11: lowNibble in [0x6, 0x7]
770 // MOV reg/mem, imm
771 else if (lowNibble == 0x6)
772 {
773 fModRM = true;
774 cbImmedSize = 1;
775 pInstrAttrib->m_cOperandSize = 1;
776 pInstrAttrib->m_fIsWrite = true;
777 }
778 else if (lowNibble == 0x7)
779 {
780 fModRM = true;
781 cbImmedSize = 3;
782 pInstrAttrib->m_cOperandSize = 3;
783 pInstrAttrib->m_fIsWrite = true;
784 }
785 break;
786
787 case 0xD:
788 // Group 2 (part 2): lowNibble in [0x0, 0x3]
789 // RCL reg/mem, 1/reg
790 if (lowNibble == 0x0 || lowNibble == 0x2)
791 {
792 fModRM = true;
793 pInstrAttrib->m_cOperandSize = 0x1;
794 pInstrAttrib->m_fIsWrite = true;
795 }
796 else if (lowNibble == 0x1 || lowNibble == 0x3)
797 {
798 fModRM = true;
799 pInstrAttrib->m_cOperandSize = 0x3;
800 pInstrAttrib->m_fIsWrite = true;
801 }
802
803 // x87 instructions: lowNibble in [0x8, 0xF]
804 // - the entire ModRM byte is used to modify the opcode,
805 // so the ModRM byte cannot be used in RIP-relative addressing
806 break;
807
808 case 0xE:
809 break;
810
811 case 0xF:
812 // Group 3: lowNibble in [0x6, 0x7]
813 // TEST
814 if ((lowNibble == 0x6) || (lowNibble == 0x7))
815 {
816 fModRM = true;
817
818 modrm = *(ModRMByte*)(address + 1);
819 if ((modrm.reg == 0x0) || (modrm.reg == 0x1))
820 {
821 if (lowNibble == 0x6)
822 {
823 cbImmedSize = 0x1;
824 }
825 else
826 {
827 cbImmedSize = 0x3;
828 }
829 }
830 }
831 // Group 4: lowNibble == 0xE
832 // INC reg/mem
833 else if (lowNibble == 0xE)
834 {
835 fModRM = true;
836 pInstrAttrib->m_cOperandSize = 1;
837 pInstrAttrib->m_fIsWrite = true;
838 }
839 // Group 5: lowNibble == 0xF
840 else if (lowNibble == 0xF)
841 {
842 fModRM = true;
843 pInstrAttrib->m_cOperandSize = 3;
844 pInstrAttrib->m_fIsWrite = true;
845 }
846 break;
847 }
848
849 address += 1;
850 if (fModRM)
851 {
852 modrm = *(ModRMByte*)address;
853 address += 1;
854 }
855 }
856 // two-byte opcodes
857 else
858 {
859 BYTE highNibble = (opcode1 & 0xF0) >> 4;
860 BYTE lowNibble = (opcode1 & 0x0F);
861
862 switch (highNibble)
863 {
864 case 0x0:
865 // Group 6: lowNibble == 0x0
866 if (lowNibble == 0x0)
867 {
868 fModRM = true;
869 }
870 // Group 7: lowNibble == 0x1
871 else if (lowNibble == 0x1)
872 {
873 fModRM = true;
874 }
875 else if ((lowNibble == 0x2) || (lowNibble == 0x3))
876 {
877 fModRM = true;
878 }
879 // Group p: lowNibble == 0xD
880 else if (lowNibble == 0xD)
881 {
882 fModRM = true;
883 }
884 // 3DNow! instructions: lowNibble == 0xF
885 // - all 3DNow! instructions use the ModRM byte
886 else if (lowNibble == 0xF)
887 {
888 fModRM = true;
889 cbImmedSize = 0x1;
890 }
891 break;
892
893 case 0x1: // Group 16: lowNibble == 0x8
894 // MOVSS xmm, xmm/mem (low nibble 0x0)
895 // MOVSS xmm/mem, xmm (low nibble 0x1)
896 if (lowNibble <= 0x1)
897 {
898 fModRM = true;
899 if (fPrefixF2 || fPrefixF3)
900 pInstrAttrib->m_cOperandSize = 0x8;
901 else
902 pInstrAttrib->m_cOperandSize = 0x10;
903
904 if (lowNibble == 0x1)
905 pInstrAttrib->m_fIsWrite = true;
906
907 break;
908 }
909 case 0x2: // fall through
910 fModRM = true;
911 if (lowNibble == 0x8 || lowNibble == 0x9)
912 {
913 pInstrAttrib->m_cOperandSize = 0x10;
914
915 if (lowNibble == 0x9)
916 pInstrAttrib->m_fIsWrite = true;
917 }
918 break;
919
920 case 0x3:
921 break;
922
923 case 0x4:
924 case 0x5:
925 case 0x6: // fall through
926 fModRM = true;
927 break;
928
929 case 0x7:
930 if (lowNibble == 0x0)
931 {
932 fModRM = true;
933 cbImmedSize = 0x1;
934 }
935 else if ((lowNibble >= 0x1) && (lowNibble <= 0x3))
936 {
937 _ASSERTE(!fPrefixF2 && !fPrefixF3);
938
939 // Group 12: lowNibble == 0x1
940 // Group 13: lowNibble == 0x2
941 // Group 14: lowNibble == 0x3
942 fModRM = true;
943 cbImmedSize = 0x1;
944 }
945 else if ((lowNibble >= 0x4) && (lowNibble <= 0x6))
946 {
947 fModRM = true;
948 }
949 // MOVD reg/mem, mmx for 0F 7E
950 else if ((lowNibble == 0xE) || (lowNibble == 0xF))
951 {
952 _ASSERTE(!fPrefixF2);
953
954 fModRM = true;
955 }
956 break;
957
958 case 0x8:
959 break;
960
961 case 0x9:
962 fModRM = true;
963 break;
964
965 case 0xA:
966 if ((lowNibble >= 0x3) && (lowNibble <= 0x5))
967 {
968 // BT reg/mem, reg
969 fModRM = true;
970 if (lowNibble == 0x3)
971 {
972 pInstrAttrib->m_cOperandSize = 0x3;
973 pInstrAttrib->m_fIsWrite = true;
974 }
975 // SHLD reg/mem, imm
976 else if (lowNibble == 0x4)
977 {
978 cbImmedSize = 0x1;
979 }
980 }
981 else if (lowNibble >= 0xB)
982 {
983 fModRM = true;
984 // BTS reg/mem, reg
985 if (lowNibble == 0xB)
986 {
987 pInstrAttrib->m_cOperandSize = 0x3;
988 pInstrAttrib->m_fIsWrite = true;
989 }
990 // SHRD reg/mem, imm
991 else if (lowNibble == 0xC)
992 {
993 cbImmedSize = 0x1;
994 }
995 // Group 15: lowNibble == 0xE
996 }
997 break;
998
999 case 0xB:
1000 // Group 10: lowNibble == 0x9
1001 // - this entire group is invalid
1002 _ASSERTE((lowNibble != 0x8) && (lowNibble != 0x9));
1003
1004 fModRM = true;
1005 // CMPXCHG reg/mem, reg
1006 if (lowNibble == 0x0)
1007 {
1008 pInstrAttrib->m_cOperandSize = 0x1;
1009 pInstrAttrib->m_fIsWrite = true;
1010 }
1011 else if (lowNibble == 0x1)
1012 {
1013 pInstrAttrib->m_cOperandSize = 0x3;
1014 pInstrAttrib->m_fIsWrite = true;
1015 }
1016 // Group 8: lowNibble == 0xA
1017 // BTS reg/mem, imm
1018 else if (lowNibble == 0xA)
1019 {
1020 cbImmedSize = 0x1;
1021 pInstrAttrib->m_cOperandSize = 0x3;
1022 pInstrAttrib->m_fIsWrite = true;
1023 }
1024 // MOVSX reg, reg/mem
1025 else if (lowNibble == 0xE)
1026 {
1027 pInstrAttrib->m_cOperandSize = 1;
1028 }
1029 else if (lowNibble == 0xF)
1030 {
1031 pInstrAttrib->m_cOperandSize = 2;
1032 }
1033 break;
1034
1035 case 0xC:
1036 if (lowNibble <= 0x7)
1037 {
1038 fModRM = true;
1039 // XADD reg/mem, reg
1040 if (lowNibble == 0x0)
1041 {
1042 pInstrAttrib->m_cOperandSize = 0x1;
1043 pInstrAttrib->m_fIsWrite = true;
1044 }
1045 else if (lowNibble == 0x1)
1046 {
1047 pInstrAttrib->m_cOperandSize = 0x3;
1048 pInstrAttrib->m_fIsWrite = true;
1049 }
1050 else if ( (lowNibble == 0x2) ||
1051 ((lowNibble >= 0x4) && (lowNibble <= 0x6)) )
1052 {
1053 cbImmedSize = 0x1;
1054 }
1055 }
1056 break;
1057
1058 case 0xD:
1059 case 0xE:
1060 case 0xF: // fall through
1061 fModRM = true;
1062 break;
1063 }
1064
1065 address += 2;
1066 if (fModRM)
1067 {
1068 modrm = *(ModRMByte*)address;
1069 address += 1;
1070 }
1071 }
1072
1073 // Check for RIP-relative addressing
1074 if (fModRM && (modrm.mod == 0x0) && (modrm.rm == 0x5))
1075 {
1076 // SIB byte cannot be present with RIP-relative addressing.
1077
1078 pInstrAttrib->m_dwOffsetToDisp = (DWORD)(address - originalAddr);
1079 _ASSERTE(pInstrAttrib->m_dwOffsetToDisp <= MAX_INSTRUCTION_LENGTH);
1080
1081 // Add 4 to the address for the displacement.
1082 address += 4;
1083
1084 // Further adjust the address by the size of the cbImmedSize (if any).
1085 if (cbImmedSize == 0x3)
1086 {
1087 // The size of the cbImmedSizeiate depends on the effective operand size:
1088 // 2 bytes if the effective operand size is 16-bit, or
1089 // 4 bytes if the effective operand size is 32- or 64-bit.
1090 if (fPrefix66)
1091 {
1092 cbImmedSize = 0x2;
1093 }
1094 else
1095 {
1096 cbImmedSize = 0x4;
1097 }
1098 }
1099 address += cbImmedSize;
1100
1101 // if this is a read or write to a RIP-relative address then update pInstrAttrib->m_cOperandSize with the size of the pointee.
1102 if (pInstrAttrib->m_cOperandSize == 0x3)
1103 {
1104 if (fPrefix66)
1105 pInstrAttrib->m_cOperandSize = 0x2; // WORD*
1106 else
1107 pInstrAttrib->m_cOperandSize = 0x4; // DWORD*
1108
1109 if (fRex && rex.w == 0x1)
1110 {
1111 _ASSERTE(pInstrAttrib->m_cOperandSize == 0x4);
1112 pInstrAttrib->m_cOperandSize = 0x8; // QWORD*
1113 }
1114 }
1115
1116 pInstrAttrib->m_cbInstr = (DWORD)(address - originalAddr);
1117 _ASSERTE(pInstrAttrib->m_cbInstr <= MAX_INSTRUCTION_LENGTH);
1118 }
1119 else
1120 {
1121 // not a RIP-relative address so set to default values
1122 pInstrAttrib->m_cOperandSize = 0;
1123 pInstrAttrib->m_fIsWrite = false;
1124 }
1125
1126 //
1127 // Look at opcode to tell if it's a call or an
1128 // absolute branch.
1129 //
1130 switch (opcode0)
1131 {
1132 case 0xC2: // RET
1133 case 0xC3: // RET N
1134 pInstrAttrib->m_fIsAbsBranch = true;
1135 LOG((LF_CORDB, LL_INFO10000, "ABS:%0.2x\n", opcode0));
1136 break;
1137
1138 case 0xE8: // CALL relative
1139 pInstrAttrib->m_fIsCall = true;
1140 LOG((LF_CORDB, LL_INFO10000, "CALL REL:%0.2x\n", opcode0));
1141 break;
1142
1143 case 0xC8: // ENTER
1144 pInstrAttrib->m_fIsCall = true;
1145 pInstrAttrib->m_fIsAbsBranch = true;
1146 LOG((LF_CORDB, LL_INFO10000, "CALL ABS:%0.2x\n", opcode0));
1147 break;
1148
1149 case 0xFF: // CALL/JMP modr/m
1150 //
1151 // Read opcode modifier from modr/m
1152 //
1153
1154 _ASSERTE(fModRM);
1155 switch (modrm.reg)
1156 {
1157 case 2:
1158 case 3:
1159 pInstrAttrib->m_fIsCall = true;
1160 // fall through
1161 case 4:
1162 case 5:
1163 pInstrAttrib->m_fIsAbsBranch = true;
1164 }
1165 LOG((LF_CORDB, LL_INFO10000, "CALL/JMP modr/m:%0.2x\n", opcode0));
1166 break;
1167
1168 default:
1169 LOG((LF_CORDB, LL_INFO10000, "NORMAL:%0.2x\n", opcode0));
1170 }
1171
1172 if (pInstrAttrib->m_cOperandSize == 0x0)
1173 {
1174 // if an operand size wasn't computed (likely because the decoder didn't understand the instruction) then set
1175 // the size to the max buffer size. this is a fall-back to the dev10 behavior and is applicable for reads only.
1176 _ASSERTE(!pInstrAttrib->m_fIsWrite);
1177 pInstrAttrib->m_cOperandSize = SharedPatchBypassBuffer::cbBufferBypass;
1178 }
1179}
1180
1181
1182#endif
1183