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
15OpInfo::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/***************************************************************************/
58const BYTE* OpInfo::fetch(const BYTE* instrPtr, OpArgsVal* args) {
59
60 data = &table[*instrPtr++];
61AGAIN:
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