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 | /***************************************************************************/ |
6 | /* OpInfo.cpp */ |
7 | /***************************************************************************/ |
8 | |
9 | #include "stdafx.h" |
10 | #include <cor.h> // for debugMacros.h |
11 | #include "debugmacros.h" // for ASSERTE |
12 | #include "opinfo.h" |
13 | |
14 | |
15 | OpInfo::OpInfoData OpInfo::table[] = { |
16 | |
17 | #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) \ |
18 | { s, (OPCODE_FORMAT) (args + type), FLOW_ ## ctrl, pop, push, c }, |
19 | |
20 | // Kind of a workaround, get the prefixes (IInternal) to return InlineOpcode instead of InlineNone |
21 | #define IInternal (InlineOpcode - InlineNone) |
22 | #define IMacro 0 |
23 | #define IPrimitive 0 |
24 | #define IAnnotation 0 |
25 | #define IObjModel 0 |
26 | #define IPrefix 0 |
27 | |
28 | #define Pop0 0 |
29 | #define Pop1 1 |
30 | #define PopI 1 |
31 | #define PopI4 1 |
32 | #define PopR4 1 |
33 | #define PopI8 1 |
34 | #define PopR8 1 |
35 | #define PopRef 1 |
36 | #define VarPop -1 |
37 | |
38 | #define Push0 0 |
39 | #define Push1 1 |
40 | #define PushI 1 |
41 | #define PushI4 1 |
42 | #define PushR4 1 |
43 | #define PushI8 1 |
44 | #define PushR8 1 |
45 | #define PushRef 1 |
46 | #define VarPush -1 |
47 | |
48 | #include "opcode.def" |
49 | #undef OPDEF |
50 | }; |
51 | |
52 | |
53 | /***************************************************************************/ |
54 | /* parse instruction at 'instrPtr', into its opcode (OpInfo), and its |
55 | (inline)args, 'args' 'instrPtr' is updated */ |
56 | |
57 | /***************************************************************************/ |
58 | const BYTE* OpInfo::fetch(const BYTE* instrPtr, OpArgsVal* args) { |
59 | |
60 | data = &table[*instrPtr++]; |
61 | AGAIN: |
62 | _ASSERTE(data - table == data->opcode); |
63 | switch(data->format) { |
64 | case InlineNone: |
65 | break; |
66 | case InlineOpcode: |
67 | _ASSERTE(*instrPtr + 256 < (int) (sizeof(table) / sizeof(OpInfoData))); |
68 | data = &table[256 + *instrPtr++]; |
69 | goto AGAIN; |
70 | |
71 | case ShortInlineVar: |
72 | args->i = *instrPtr; instrPtr +=1; |
73 | break; |
74 | case InlineVar: |
75 | args->i = GET_UNALIGNED_VAL16(instrPtr); instrPtr +=2; |
76 | break; |
77 | case ShortInlineI: |
78 | case ShortInlineBrTarget: |
79 | args->i = *instrPtr; instrPtr +=1; |
80 | break; |
81 | case ShortInlineR: { |
82 | DWORD f = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=4; |
83 | args->r = *((float*) (&f)); |
84 | } |
85 | break; |
86 | case InlineRVA: |
87 | case InlineI: |
88 | case InlineMethod: |
89 | case InlineField: |
90 | case InlineType: |
91 | case InlineString: |
92 | case InlineSig: |
93 | case InlineTok: |
94 | case InlineBrTarget: |
95 | args->i = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=4; |
96 | break; |
97 | case InlineI8: |
98 | args->i8 = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8; |
99 | break; |
100 | case InlineR: { |
101 | __int64 d = GET_UNALIGNED_VAL64(instrPtr); instrPtr +=8; |
102 | args->r = *((double*) (&d)); |
103 | } break; |
104 | case InlineSwitch: |
105 | args->switch_.count = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=4; |
106 | args->switch_.targets = (int*) instrPtr; instrPtr += (4 * args->switch_.count); |
107 | break; |
108 | case InlinePhi: |
109 | args->phi.count = GET_UNALIGNED_VAL32(instrPtr); instrPtr +=1; |
110 | args->phi.vars = (unsigned short*) instrPtr; instrPtr += (2 * args->phi.count); |
111 | break; |
112 | default: |
113 | #ifdef _DEBUG |
114 | _ASSERTE(!"BadType" ); |
115 | #else |
116 | __assume(0); // we are really certain the default case does not happen |
117 | #endif |
118 | break; |
119 | } |
120 | return(instrPtr); |
121 | } |
122 | |
123 | |