1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Alexander V. Astapchuk
19 */
20#ifndef __ENC_PRVT_H_INCLUDED__
21#define __ENC_PRVT_H_INCLUDED__
22
23#include "enc_base.h"
24
25ENCODER_NAMESPACE_START
26/*
27 * @file
28 * @brief Contains some definitions/constants and other stuff used by the
29 *        Encoder internally.
30 */
31
32enum OpcodeByteKind {
33    //OpcodeByteKind_Opcode = 0x0000,
34    OpcodeByteKind_ZeroOpcodeByte           = 0x0100,
35    //
36    // The names _SlashR,  _SlahsNum, _ib, _iw, etc
37    // represent the appropriate abbreviations used
38    // in the mnemonic descriptions in the Intel's arch manual.
39    //
40    OpcodeByteKind_SlashR                   = 0x0200,
41    OpcodeByteKind_SlashNum                 = 0x0300,
42    OpcodeByteKind_ib                       = 0x0400,
43    OpcodeByteKind_iw                       = 0x0500,
44    OpcodeByteKind_id                       = 0x0600,
45#ifdef _EM64T_
46    OpcodeByteKind_io                       = 0x0700,
47#endif
48    OpcodeByteKind_cb                       = 0x0800,
49    OpcodeByteKind_cw                       = 0x0900,
50    OpcodeByteKind_cd                       = 0x0A00,
51    //OpcodeByteKind_cp                     = 0x0B00,
52    //OpcodeByteKind_co                     = 0x0C00,
53    //OpcodeByteKind_ct                     = 0x0D00,
54
55    OpcodeByteKind_rb                       = 0x0E00,
56    OpcodeByteKind_rw                       = 0x0F00,
57    OpcodeByteKind_rd                       = 0x1000,
58#ifdef _EM64T_
59    OpcodeByteKind_ro                       = 0x1100,
60    //OpcodeByteKind_REX                    = 0x1200,
61    OpcodeByteKind_REX_W                    = 0x1300,
62#endif
63    OpcodeByteKind_plus_i                   = 0x1400,
64    /**
65        * a special marker, means 'no opcode on the given position'
66        * used in opcodes array, to specify the empty slot, say
67        * to fill an em64t-specific opcode on ia32.
68        * last 'e' made lowercase to avoid a mess with 'F' in
69        * OpcodeByteKind_LAST .
70        */
71    OpcodeByteKind_EMPTY                    = 0xFFFE,
72    /**
73        * a special marker, means 'no more opcodes in the array'
74        * used in in opcodes array to show that there are no more
75        * opcodes in the array for a given mnemonic.
76        */
77    OpcodeByteKind_LAST                     = 0xFFFF,
78    /**
79        * a mask to extract the OpcodeByteKind
80        */
81    OpcodeByteKind_KindMask                 = 0xFF00,
82    /**
83        * a mask to extract the opcode byte when presented
84        */
85    OpcodeByteKind_OpcodeMask               = 0x00FF
86};
87
88#ifdef USE_ENCODER_DEFINES
89
90#define N           {0, 0, 0, 0 }
91#define U           {1, 0, 1, OpndRole_Use }
92#define D           {1, 1, 0, OpndRole_Def }
93#define DU          {1, 1, 1, OpndRole_Def|OpndRole_Use }
94
95#define U_U         {2, 0, 2, OpndRole_Use<<2 | OpndRole_Use }
96#define D_U         {2, 1, 1, OpndRole_Def<<2 | OpndRole_Use }
97#define D_DU        {2, 2, 1, OpndRole_Def<<2 | (OpndRole_Def|OpndRole_Use) }
98#define DU_U        {2, 1, 2, ((OpndRole_Def|OpndRole_Use)<<2 | OpndRole_Use) }
99#define DU_DU       {2, 2, 2, ((OpndRole_Def|OpndRole_Use)<<2 | (OpndRole_Def|OpndRole_Use)) }
100
101#define DU_DU_DU    {3, 3, 3, ((OpndRole_Def|OpndRole_Use)<<4) | ((OpndRole_Def|OpndRole_Use)<<2) | (OpndRole_Def|OpndRole_Use) }
102#define DU_DU_U     {3, 2, 3, (((OpndRole_Def|OpndRole_Use)<<4) | ((OpndRole_Def|OpndRole_Use)<<2) | OpndRole_Use) }
103#define D_DU_U      {3, 2, 2, (((OpndRole_Def)<<4) | ((OpndRole_Def|OpndRole_Use)<<2) | OpndRole_Use) }
104#define D_U_U       {3, 1, 2, (((OpndRole_Def)<<4) | ((OpndRole_Use)<<2) | OpndRole_Use) }
105
106// Special encoding of 0x00 opcode byte. Note: it's all O-s, not zeros.
107#define OxOO        OpcodeByteKind_ZeroOpcodeByte
108
109#define Size16      InstPrefix_OpndSize
110
111#define _r          OpcodeByteKind_SlashR
112
113#define _0          OpcodeByteKind_SlashNum|0
114#define _1          OpcodeByteKind_SlashNum|1
115#define _2          OpcodeByteKind_SlashNum|2
116#define _3          OpcodeByteKind_SlashNum|3
117#define _4          OpcodeByteKind_SlashNum|4
118#define _5          OpcodeByteKind_SlashNum|5
119#define _6          OpcodeByteKind_SlashNum|6
120#define _7          OpcodeByteKind_SlashNum|7
121
122// '+i' for floating-point instructions
123#define _i          OpcodeByteKind_plus_i
124
125
126#define ib          OpcodeByteKind_ib
127#define iw          OpcodeByteKind_iw
128#define id          OpcodeByteKind_id
129
130#define cb          OpcodeByteKind_cb
131#define cw          OpcodeByteKind_cw
132#define cd          OpcodeByteKind_cd
133
134#define rb          OpcodeByteKind_rb
135#define rw          OpcodeByteKind_rw
136#define rd          OpcodeByteKind_rd
137
138#define AL          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_AL}
139#define AH          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_AH}
140#define AX          {OpndKind_GPReg, OpndSize_16, OpndExt_Any, RegName_AX}
141#define EAX         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_EAX}
142#ifdef _EM64T_
143    #define RAX     {OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RAX }
144#endif
145
146#define CL          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_CL}
147#define ECX         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_ECX}
148#ifdef _EM64T_
149    #define RCX         {OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RCX}
150#endif
151
152#define DX          {OpndKind_GPReg, OpndSize_16, OpndExt_Any, RegName_DX}
153#define EDX         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_EDX}
154#ifdef _EM64T_
155    #define RDX     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RDX }
156#endif
157
158#define ESI         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_ESI}
159#ifdef _EM64T_
160    #define RSI     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RSI }
161#endif
162
163#define EDI         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_EDI}
164#ifdef _EM64T_
165    #define RDI     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RDI }
166#endif
167
168#define r8          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_Null}
169#define r16         {OpndKind_GPReg, OpndSize_16, OpndExt_Any, RegName_Null}
170#define r32         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_Null}
171#ifdef _EM64T_
172    #define r64     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_Null }
173#endif
174
175#define r_m8        {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_8, OpndExt_Any, RegName_Null}
176#define r_m16       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_16, OpndExt_Any, RegName_Null}
177#define r_m32       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_32, OpndExt_Any, RegName_Null}
178
179#define r_m8s        {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_8, OpndExt_Signed, RegName_Null}
180#define r_m16s       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_16, OpndExt_Signed, RegName_Null}
181#define r_m32s       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_32, OpndExt_Signed, RegName_Null}
182
183#define r_m8u        {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_8, OpndExt_Zero, RegName_Null}
184#define r_m16u       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_16, OpndExt_Zero, RegName_Null}
185#define r_m32u       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_32, OpndExt_Zero, RegName_Null}
186
187//'m' was only used in LEA mnemonic, but is replaced with
188// set of exact sizes. See more comments for LEA instruction in TheTable.
189//#define m           {OpndKind_Mem, OpndSize_Null, RegName_Null}
190#define m8          {OpndKind_Mem, OpndSize_8, OpndExt_Any, RegName_Null}
191#define m16         {OpndKind_Mem, OpndSize_16, OpndExt_Any, RegName_Null}
192#define m32         {OpndKind_Mem, OpndSize_32, OpndExt_Any, RegName_Null}
193#define m64         {OpndKind_Mem, OpndSize_64, OpndExt_Any, RegName_Null}
194#ifdef _EM64T_
195    #define r_m64   { (OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_64, OpndExt_Any, RegName_Null }
196#endif
197
198#define imm8        {OpndKind_Imm, OpndSize_8, OpndExt_Any, RegName_Null}
199#define imm16       {OpndKind_Imm, OpndSize_16, OpndExt_Any, RegName_Null}
200#define imm32       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
201
202#define imm8s        {OpndKind_Imm, OpndSize_8, OpndExt_Signed, RegName_Null}
203#define imm16s       {OpndKind_Imm, OpndSize_16, OpndExt_Signed, RegName_Null}
204#define imm32s       {OpndKind_Imm, OpndSize_32, OpndExt_Signed, RegName_Null}
205
206#define imm8u        {OpndKind_Imm, OpndSize_8, OpndExt_Zero, RegName_Null}
207#define imm16u       {OpndKind_Imm, OpndSize_16, OpndExt_Zero, RegName_Null}
208#define imm32u       {OpndKind_Imm, OpndSize_32, OpndExt_Zero, RegName_Null}
209
210#ifdef _EM64T_
211    #define imm64   {OpndKind_Imm, OpndSize_64, OpndExt_Any, RegName_Null }
212#endif
213
214//FIXME: moff-s are in fact memory refs, but presented as immediate.
215// Need to specify this in OpndDesc.
216#define moff8        {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
217#define moff16       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
218#define moff32       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
219#ifdef _EM64T_
220    #define moff64       {OpndKind_Imm, OpndSize_64, OpndExt_Any, RegName_Null}
221#endif
222
223
224#define rel8        {OpndKind_Imm, OpndSize_8, OpndExt_Any, RegName_Null}
225#define rel16       {OpndKind_Imm, OpndSize_16, OpndExt_Any, RegName_Null}
226#define rel32       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
227
228#define mm64        {OpndKind_MMXReg, OpndSize_64, OpndExt_Any, RegName_Null}
229#define mm_m64      {(OpndKind)(OpndKind_MMXReg|OpndKind_Mem), OpndSize_64, OpndExt_Any, RegName_Null}
230
231#define xmm64       {OpndKind_XMMReg, OpndSize_64, OpndExt_Any, RegName_Null}
232#define xmm_m64     {(OpndKind)(OpndKind_XMMReg|OpndKind_Mem), OpndSize_64, OpndExt_Any, RegName_Null}
233
234#define xmm32       {OpndKind_XMMReg, OpndSize_32, OpndExt_Any, RegName_Null}
235#define xmm_m32     {(OpndKind)(OpndKind_XMMReg|OpndKind_Mem), OpndSize_32, OpndExt_Any, RegName_Null}
236
237#define FP0S        {OpndKind_FPReg, OpndSize_32, OpndExt_Any, RegName_FP0S}
238#define FP0D        {OpndKind_FPReg, OpndSize_64, OpndExt_Any, RegName_FP0D}
239#define FP1S        {OpndKind_FPReg, OpndSize_32, OpndExt_Any, RegName_FP1S}
240#define FP1D        {OpndKind_FPReg, OpndSize_64, OpndExt_Any, RegName_FP1D}
241#define fp32        {OpndKind_FPReg, OpndSize_32, OpndExt_Any, RegName_Null}
242#define fp64        {OpndKind_FPReg, OpndSize_64, OpndExt_Any, RegName_Null}
243
244#ifdef _EM64T_
245    #define io      OpcodeByteKind_io
246    #define REX_W   OpcodeByteKind_REX_W
247
248#endif
249
250#endif // USE_ENCODER_DEFINES
251
252/**
253 * @brief Represents the REX part of instruction.
254 */
255struct  Rex {
256    unsigned char b : 1;
257    unsigned char x : 1;
258    unsigned char r : 1;
259    unsigned char w : 1;
260    unsigned char dummy : 4;        // must be '0100'b
261    unsigned int  :24;
262};
263
264/**
265 * @brief Describes SIB (scale,index,base) byte.
266 */
267struct SIB {
268    unsigned char base:3;
269    unsigned char index:3;
270    unsigned char scale:2;
271    unsigned int  padding:24;
272};
273/**
274 * @brief Describes ModRM byte.
275 */
276struct ModRM
277{
278    unsigned char rm:3;
279    unsigned char reg:3;
280    unsigned char mod:2;
281    unsigned int  padding:24;
282};
283
284
285
286/**
287* exactly the same as EncoderBase::OpcodeDesc, but also holds info about
288* platform on which the opcode is applicable.
289*/
290struct OpcodeInfo {
291    enum platform {
292        /// an opcode is valid on all platforms
293        all,
294        // opcode is valid on IA-32 only
295        em64t,
296        // opcode is valid on Intel64 only
297        ia32,
298        // opcode is added for the sake of disassembling, should not be used in encoding
299        decoder,
300        // only appears in master table, replaced with 'decoder' in hashed version
301        decoder32,
302        // only appears in master table, replaced with 'decoder' in hashed version
303        decoder64,
304    };
305    platform                        platf;
306    unsigned                        opcode[4+1+1];
307    EncoderBase::OpndDesc           opnds[3];
308    EncoderBase::OpndRolesDesc      roles;
309};
310
311/**
312 * @defgroup MF_ Mnemonic flags
313*/
314
315    /**
316 * Operation has no special properties.
317    */
318#define MF_NONE             (0x00000000)
319    /**
320 * Operation affects flags
321    */
322#define MF_AFFECTS_FLAGS    (0x00000001)
323    /**
324 * Operation uses flags - conditional operations, ADC/SBB/ETC
325    */
326#define MF_USES_FLAGS       (0x00000002)
327    /**
328 * Operation is conditional - MOVcc/SETcc/Jcc/ETC
329    */
330#define MF_CONDITIONAL      (0x00000004)
331/**
332 * Operation is symmetric - its args can be swapped (ADD/MUL/etc).
333 */
334#define MF_SYMMETRIC        (0x00000008)
335/**
336 * Operation is XOR-like - XOR, SUB - operations of 'arg,arg' is pure def,
337 * without use.
338 */
339#define MF_SAME_ARG_NO_USE  (0x00000010)
340
341///@} // ~MNF
342
343/**
344 * @see same structure as EncoderBase::MnemonicDesc, but carries
345 * MnemonicInfo::OpcodeInfo[] instead of OpcodeDesc[].
346 * Only used during prebuilding the encoding tables, thus it's hidden under
347 * the appropriate define.
348 */
349struct MnemonicInfo {
350    /**
351    * The mnemonic itself
352    */
353    Mnemonic    mn;
354    /**
355     * Various characteristics of mnemonic.
356     * @see MF_
357     */
358    unsigned    flags;
359    /**
360     * Number of args/des/uses/roles for the operation. For the operations
361     * which may use different number of operands (i.e. IMUL/SHL) use the
362     * most common value, or leave '0' if you are sure this info is not
363     * required.
364     */
365    EncoderBase::OpndRolesDesc              roles;
366    /**
367     * Print name of the mnemonic
368     */
369    const char *                            name;
370    /**
371     * Array of opcodes.
372     * The terminating opcode description always have OpcodeByteKind_LAST
373     * at the opcodes[i].opcode[0].
374     * The size of '25' has nothing behind it, just counted the max
375     * number of opcodes currently used (MOV instruction).
376     */
377    OpcodeInfo                              opcodes[25];
378};
379
380ENCODER_NAMESPACE_END
381
382#endif  // ~__ENC_PRVT_H_INCLUDED__
383