summaryrefslogtreecommitdiffstats
path: root/libpixelflinger/codeflinger/x86/libenc/enc_prvt.h
blob: 343b161f1405efb5c7699bd1f24b25336b208d82 (plain)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Alexander V. Astapchuk
 */
#ifndef __ENC_PRVT_H_INCLUDED__
#define __ENC_PRVT_H_INCLUDED__

#include "enc_base.h"

ENCODER_NAMESPACE_START
/*
 * @file
 * @brief Contains some definitions/constants and other stuff used by the
 *        Encoder internally.
 */

enum OpcodeByteKind {
    //OpcodeByteKind_Opcode = 0x0000,
    OpcodeByteKind_ZeroOpcodeByte           = 0x0100,
    //
    // The names _SlashR,  _SlahsNum, _ib, _iw, etc
    // represent the appropriate abbreviations used
    // in the mnemonic descriptions in the Intel's arch manual.
    //
    OpcodeByteKind_SlashR                   = 0x0200,
    OpcodeByteKind_SlashNum                 = 0x0300,
    OpcodeByteKind_ib                       = 0x0400,
    OpcodeByteKind_iw                       = 0x0500,
    OpcodeByteKind_id                       = 0x0600,
#ifdef _EM64T_
    OpcodeByteKind_io                       = 0x0700,
#endif
    OpcodeByteKind_cb                       = 0x0800,
    OpcodeByteKind_cw                       = 0x0900,
    OpcodeByteKind_cd                       = 0x0A00,
    //OpcodeByteKind_cp                     = 0x0B00,
    //OpcodeByteKind_co                     = 0x0C00,
    //OpcodeByteKind_ct                     = 0x0D00,

    OpcodeByteKind_rb                       = 0x0E00,
    OpcodeByteKind_rw                       = 0x0F00,
    OpcodeByteKind_rd                       = 0x1000,
#ifdef _EM64T_
    OpcodeByteKind_ro                       = 0x1100,
    //OpcodeByteKind_REX                    = 0x1200,
    OpcodeByteKind_REX_W                    = 0x1300,
#endif
    OpcodeByteKind_plus_i                   = 0x1400,
    /**
        * a special marker, means 'no opcode on the given position'
        * used in opcodes array, to specify the empty slot, say
        * to fill an em64t-specific opcode on ia32.
        * last 'e' made lowercase to avoid a mess with 'F' in
        * OpcodeByteKind_LAST .
        */
    OpcodeByteKind_EMPTY                    = 0xFFFE,
    /**
        * a special marker, means 'no more opcodes in the array'
        * used in in opcodes array to show that there are no more
        * opcodes in the array for a given mnemonic.
        */
    OpcodeByteKind_LAST                     = 0xFFFF,
    /**
        * a mask to extract the OpcodeByteKind
        */
    OpcodeByteKind_KindMask                 = 0xFF00,
    /**
        * a mask to extract the opcode byte when presented
        */
    OpcodeByteKind_OpcodeMask               = 0x00FF
};

#ifdef USE_ENCODER_DEFINES

#define N           {0, 0, 0, 0 }
#define U           {1, 0, 1, OpndRole_Use }
#define D           {1, 1, 0, OpndRole_Def }
#define DU          {1, 1, 1, OpndRole_Def|OpndRole_Use }

#define U_U         {2, 0, 2, OpndRole_Use<<2 | OpndRole_Use }
#define D_U         {2, 1, 1, OpndRole_Def<<2 | OpndRole_Use }
#define D_DU        {2, 2, 1, OpndRole_Def<<2 | (OpndRole_Def|OpndRole_Use) }
#define DU_U        {2, 1, 2, ((OpndRole_Def|OpndRole_Use)<<2 | OpndRole_Use) }
#define DU_DU       {2, 2, 2, ((OpndRole_Def|OpndRole_Use)<<2 | (OpndRole_Def|OpndRole_Use)) }

#define DU_DU_DU    {3, 3, 3, ((OpndRole_Def|OpndRole_Use)<<4) | ((OpndRole_Def|OpndRole_Use)<<2) | (OpndRole_Def|OpndRole_Use) }
#define DU_DU_U     {3, 2, 3, (((OpndRole_Def|OpndRole_Use)<<4) | ((OpndRole_Def|OpndRole_Use)<<2) | OpndRole_Use) }
#define D_DU_U      {3, 2, 2, (((OpndRole_Def)<<4) | ((OpndRole_Def|OpndRole_Use)<<2) | OpndRole_Use) }
#define D_U_U       {3, 1, 2, (((OpndRole_Def)<<4) | ((OpndRole_Use)<<2) | OpndRole_Use) }

// Special encoding of 0x00 opcode byte. Note: it's all O-s, not zeros.
#define OxOO        OpcodeByteKind_ZeroOpcodeByte

#define Size16      InstPrefix_OpndSize

#define _r          OpcodeByteKind_SlashR

#define _0          OpcodeByteKind_SlashNum|0
#define _1          OpcodeByteKind_SlashNum|1
#define _2          OpcodeByteKind_SlashNum|2
#define _3          OpcodeByteKind_SlashNum|3
#define _4          OpcodeByteKind_SlashNum|4
#define _5          OpcodeByteKind_SlashNum|5
#define _6          OpcodeByteKind_SlashNum|6
#define _7          OpcodeByteKind_SlashNum|7

// '+i' for floating-point instructions
#define _i          OpcodeByteKind_plus_i


#define ib          OpcodeByteKind_ib
#define iw          OpcodeByteKind_iw
#define id          OpcodeByteKind_id

#define cb          OpcodeByteKind_cb
#define cw          OpcodeByteKind_cw
#define cd          OpcodeByteKind_cd

#define rb          OpcodeByteKind_rb
#define rw          OpcodeByteKind_rw
#define rd          OpcodeByteKind_rd

#define AL          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_AL}
#define AH          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_AH}
#define AX          {OpndKind_GPReg, OpndSize_16, OpndExt_Any, RegName_AX}
#define EAX         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_EAX}
#ifdef _EM64T_
    #define RAX     {OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RAX }
#endif

#define CL          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_CL}
#define ECX         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_ECX}
#ifdef _EM64T_
    #define RCX         {OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RCX}
#endif

#define DX          {OpndKind_GPReg, OpndSize_16, OpndExt_Any, RegName_DX}
#define EDX         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_EDX}
#ifdef _EM64T_
    #define RDX     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RDX }
#endif

#define ESI         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_ESI}
#ifdef _EM64T_
    #define RSI     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RSI }
#endif

#define EDI         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_EDI}
#ifdef _EM64T_
    #define RDI     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_RDI }
#endif

#define r8          {OpndKind_GPReg, OpndSize_8, OpndExt_Any, RegName_Null}
#define r16         {OpndKind_GPReg, OpndSize_16, OpndExt_Any, RegName_Null}
#define r32         {OpndKind_GPReg, OpndSize_32, OpndExt_Any, RegName_Null}
#ifdef _EM64T_
    #define r64     { OpndKind_GPReg, OpndSize_64, OpndExt_Any, RegName_Null }
#endif

#define r_m8        {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_8, OpndExt_Any, RegName_Null}
#define r_m16       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_16, OpndExt_Any, RegName_Null}
#define r_m32       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_32, OpndExt_Any, RegName_Null}

#define r_m8s        {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_8, OpndExt_Signed, RegName_Null}
#define r_m16s       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_16, OpndExt_Signed, RegName_Null}
#define r_m32s       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_32, OpndExt_Signed, RegName_Null}

#define r_m8u        {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_8, OpndExt_Zero, RegName_Null}
#define r_m16u       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_16, OpndExt_Zero, RegName_Null}
#define r_m32u       {(OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_32, OpndExt_Zero, RegName_Null}

//'m' was only used in LEA mnemonic, but is replaced with
// set of exact sizes. See more comments for LEA instruction in TheTable.
//#define m           {OpndKind_Mem, OpndSize_Null, RegName_Null}
#define m8          {OpndKind_Mem, OpndSize_8, OpndExt_Any, RegName_Null}
#define m16         {OpndKind_Mem, OpndSize_16, OpndExt_Any, RegName_Null}
#define m32         {OpndKind_Mem, OpndSize_32, OpndExt_Any, RegName_Null}
#define m64         {OpndKind_Mem, OpndSize_64, OpndExt_Any, RegName_Null}
#ifdef _EM64T_
    #define r_m64   { (OpndKind)(OpndKind_GPReg|OpndKind_Mem), OpndSize_64, OpndExt_Any, RegName_Null }
#endif

#define imm8        {OpndKind_Imm, OpndSize_8, OpndExt_Any, RegName_Null}
#define imm16       {OpndKind_Imm, OpndSize_16, OpndExt_Any, RegName_Null}
#define imm32       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}

#define imm8s        {OpndKind_Imm, OpndSize_8, OpndExt_Signed, RegName_Null}
#define imm16s       {OpndKind_Imm, OpndSize_16, OpndExt_Signed, RegName_Null}
#define imm32s       {OpndKind_Imm, OpndSize_32, OpndExt_Signed, RegName_Null}

#define imm8u        {OpndKind_Imm, OpndSize_8, OpndExt_Zero, RegName_Null}
#define imm16u       {OpndKind_Imm, OpndSize_16, OpndExt_Zero, RegName_Null}
#define imm32u       {OpndKind_Imm, OpndSize_32, OpndExt_Zero, RegName_Null}

#ifdef _EM64T_
    #define imm64   {OpndKind_Imm, OpndSize_64, OpndExt_Any, RegName_Null }
#endif

//FIXME: moff-s are in fact memory refs, but presented as immediate.
// Need to specify this in OpndDesc.
#define moff8        {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
#define moff16       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
#define moff32       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}
#ifdef _EM64T_
    #define moff64       {OpndKind_Imm, OpndSize_64, OpndExt_Any, RegName_Null}
#endif


#define rel8        {OpndKind_Imm, OpndSize_8, OpndExt_Any, RegName_Null}
#define rel16       {OpndKind_Imm, OpndSize_16, OpndExt_Any, RegName_Null}
#define rel32       {OpndKind_Imm, OpndSize_32, OpndExt_Any, RegName_Null}

#define mm64        {OpndKind_MMXReg, OpndSize_64, OpndExt_Any, RegName_Null}
#define mm_m64      {(OpndKind)(OpndKind_MMXReg|OpndKind_Mem), OpndSize_64, OpndExt_Any, RegName_Null}

#define xmm64       {OpndKind_XMMReg, OpndSize_64, OpndExt_Any, RegName_Null}
#define xmm_m64     {(OpndKind)(OpndKind_XMMReg|OpndKind_Mem), OpndSize_64, OpndExt_Any, RegName_Null}

#define xmm32       {OpndKind_XMMReg, OpndSize_32, OpndExt_Any, RegName_Null}
#define xmm_m32     {(OpndKind)(OpndKind_XMMReg|OpndKind_Mem), OpndSize_32, OpndExt_Any, RegName_Null}

#define FP0S        {OpndKind_FPReg, OpndSize_32, OpndExt_Any, RegName_FP0S}
#define FP0D        {OpndKind_FPReg, OpndSize_64, OpndExt_Any, RegName_FP0D}
#define FP1S        {OpndKind_FPReg, OpndSize_32, OpndExt_Any, RegName_FP1S}
#define FP1D        {OpndKind_FPReg, OpndSize_64, OpndExt_Any, RegName_FP1D}
#define fp32        {OpndKind_FPReg, OpndSize_32, OpndExt_Any, RegName_Null}
#define fp64        {OpndKind_FPReg, OpndSize_64, OpndExt_Any, RegName_Null}

#ifdef _EM64T_
    #define io      OpcodeByteKind_io
    #define REX_W   OpcodeByteKind_REX_W

#endif

#endif // USE_ENCODER_DEFINES

/**
 * @brief Represents the REX part of instruction.
 */
struct  Rex {
    unsigned char b : 1;
    unsigned char x : 1;
    unsigned char r : 1;
    unsigned char w : 1;
    unsigned char dummy : 4;        // must be '0100'b
    unsigned int  :24;
};

/**
 * @brief Describes SIB (scale,index,base) byte.
 */
struct SIB {
    unsigned char base:3;
    unsigned char index:3;
    unsigned char scale:2;
    unsigned int  padding:24;
};
/**
 * @brief Describes ModRM byte.
 */
struct ModRM
{
    unsigned char rm:3;
    unsigned char reg:3;
    unsigned char mod:2;
    unsigned int  padding:24;
};



/**
* exactly the same as EncoderBase::OpcodeDesc, but also holds info about
* platform on which the opcode is applicable.
*/
struct OpcodeInfo {
    enum platform {
        /// an opcode is valid on all platforms
        all,
        // opcode is valid on IA-32 only
        em64t,
        // opcode is valid on Intel64 only
        ia32,
        // opcode is added for the sake of disassembling, should not be used in encoding
        decoder,
        // only appears in master table, replaced with 'decoder' in hashed version
        decoder32,
        // only appears in master table, replaced with 'decoder' in hashed version
        decoder64,
    };
    platform                        platf;
    unsigned                        opcode[4+1+1];
    EncoderBase::OpndDesc           opnds[EncoderBase::MAX_NUM_OPCODE_OPERANDS];
    EncoderBase::OpndRolesDesc      roles;
};

/**
 * @defgroup MF_ Mnemonic flags
*/

    /**
 * Operation has no special properties.
    */
#define MF_NONE             (0x00000000)
    /**
 * Operation affects flags
    */
#define MF_AFFECTS_FLAGS    (0x00000001)
    /**
 * Operation uses flags - conditional operations, ADC/SBB/ETC
    */
#define MF_USES_FLAGS       (0x00000002)
    /**
 * Operation is conditional - MOVcc/SETcc/Jcc/ETC
    */
#define MF_CONDITIONAL      (0x00000004)
/**
 * Operation is symmetric - its args can be swapped (ADD/MUL/etc).
 */
#define MF_SYMMETRIC        (0x00000008)
/**
 * Operation is XOR-like - XOR, SUB - operations of 'arg,arg' is pure def,
 * without use.
 */
#define MF_SAME_ARG_NO_USE  (0x00000010)

///@} // ~MNF

/**
 * @see same structure as EncoderBase::MnemonicDesc, but carries
 * MnemonicInfo::OpcodeInfo[] instead of OpcodeDesc[].
 * Only used during prebuilding the encoding tables, thus it's hidden under
 * the appropriate define.
 */
struct MnemonicInfo {
    /**
    * The mnemonic itself
    */
    Mnemonic    mn;
    /**
     * Various characteristics of mnemonic.
     * @see MF_
     */
    unsigned    flags;
    /**
     * Number of args/des/uses/roles for the operation. For the operations
     * which may use different number of operands (i.e. IMUL/SHL) use the
     * most common value, or leave '0' if you are sure this info is not
     * required.
     */
    EncoderBase::OpndRolesDesc              roles;
    /**
     * Print name of the mnemonic
     */
    const char *                            name;
    /**
     * Array of opcodes.
     * The terminating opcode description always have OpcodeByteKind_LAST
     * at the opcodes[i].opcode[0].
     * The size of '25' has nothing behind it, just counted the max
     * number of opcodes currently used (MOV instruction).
     */
    OpcodeInfo                              opcodes[25];
};

ENCODER_NAMESPACE_END

#endif  // ~__ENC_PRVT_H_INCLUDED__