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
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/***************************************************************************/
/* OpInfo.cpp */
/***************************************************************************/
#include "stdafx.h"
#include <cor.h> // for debugMacros.h
#include "debugmacros.h" // for ASSERTE
#include "opinfo.h"
OpInfo::OpInfoData OpInfo::table[] = {
#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) \
{ s, (OPCODE_FORMAT) (args + type), FLOW_ ## ctrl, pop, push, c },
// Kind of a workaround, get the prefixes (IInternal) to return InlineOpcode instead of InlineNone
#define IInternal (InlineOpcode - InlineNone)
#define IMacro 0
#define IPrimitive 0
#define IAnnotation 0
#define IObjModel 0
#define IPrefix 0
#define Pop0 0
#define Pop1 1
#define PopI 1
#define PopI4 1
#define PopR4 1
#define PopI8 1
#define PopR8 1
#define PopRef 1
#define VarPop -1
#define Push0 0
#define Push1 1
#define PushI 1
#define PushI4 1
#define PushR4 1
#define PushI8 1
#define PushR8 1
#define PushRef 1
#define VarPush -1
#include "opcode.def"
#undef OPDEF
};
/***************************************************************************/
/* parse instruction at 'instrPtr', into its opcode (OpInfo), and its
(inline)args, 'args' 'instrPtr' is updated */
/***************************************************************************/
const BYTE* OpInfo::fetch(const BYTE* instrPtr, OpArgsVal* args) {
data = &table[*instrPtr++];
AGAIN:
_ASSERTE(data - table == data->opcode);
switch(data->format) {
case InlineNone:
break;
case InlineOpcode:
_ASSERTE(*instrPtr + 256 < (int) (sizeof(table) / sizeof(OpInfoData)));
data = &table[256 + *instrPtr++];
goto AGAIN;
case ShortInlineVar:
args->i = *instrPtr; instrPtr +=1;
break;
case InlineVar:
args->i = GET_UNALIGNED_VAL16(instrPtr); instrPtr +=2;
break;
case ShortInlineI:
case ShortInlineBrTarget:
args->i = *instrPtr; instrPtr +=1;
break;
case ShortInlineR: {
DWORD f = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=4;
args->r = *((float*) (&f));
}
break;
case InlineRVA:
case InlineI:
case InlineMethod:
case InlineField:
case InlineType:
case InlineString:
case InlineSig:
case InlineTok:
case InlineBrTarget:
args->i = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=4;
break;
case InlineI8:
args->i8 = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8;
break;
case InlineR: {
__int64 d = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8;
args->r = *((double*) (&d));
} break;
case InlineSwitch:
args->switch_.count = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=4;
args->switch_.targets = (int*) instrPtr; instrPtr += (4 * args->switch_.count);
break;
case InlinePhi:
args->phi.count = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=1;
args->phi.vars = (unsigned short*) instrPtr; instrPtr += (2 * args->phi.count);
break;
default:
#ifdef _DEBUG
_ASSERTE(!"BadType");
#else
__assume(0); // we are really certain the default case does not happen
#endif
break;
}
return(instrPtr);
}
|