• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 /**
22  * @file
23  * @brief Main encoding routines and structures.
24  */
25 
26 #ifndef __ENC_BASE_H_INCLUDED__
27 #define __ENC_BASE_H_INCLUDED__
28 
29 #include "enc_defs.h"
30 
31 
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <memory.h>
35 
36 ENCODER_NAMESPACE_START
37 struct MnemonicInfo;
38 struct OpcodeInfo;
39 struct Rex;
40 
41 /**
42  * @brief Basic facilities for generation of processor's instructions.
43  *
44  * The class EncoderBase represents the basic facilities for the encoding of
45  * processor's instructions on IA32 and EM64T platforms.
46  *
47  * The class provides general interface to generate the instructions as well
48  * as to retrieve some static data about instructions (number of arguments,
49  * their roles, etc).
50  *
51  * Currently, the EncoderBase class is used for both LIL and Jitrino code
52  * generators. Each of these code generators has its own wrapper to adapt
53  * this general interface for specific needs - see encoder.h for LIL wrappers
54  * and Ia32Encoder.h for Jitrino's adapter.
55  *
56  * Interface is provided through static methods, no instances of EncoderBase
57  * to be created.
58  *
59  * @todo RIP-based addressing on EM64T - it's not yet supported currently.
60  */
61 class EncoderBase {
62 public:
63     class Operands;
64     struct MnemonicDesc;
65     /**
66      * @brief Generates processor's instruction.
67      *
68      * @param stream - a buffer to generate into
69      * @param mn - \link Mnemonic mnemonic \endlink of the instruction
70      * @param opnds - operands for the instruction
71      * @returns (stream + length of the just generated instruction)
72      */
73     static char * encode(char * stream, Mnemonic mn, const Operands& opnds);
74     static char * getOpndLocation(int index);
75 
76     /**
77      * @brief Generates the smallest possible number of NOP-s.
78      *
79      * Effectively generates the smallest possible number of instructions,
80      * which are NOP-s for CPU. Normally used to make a code alignment.
81      *
82      * The method inserts exactly number of bytes specified. It's a caller's
83      * responsibility to make sure the buffer is big enough.
84      *
85      * @param stream - buffer where to generate code into, can not be NULL
86      * @param howMany - how many bytes to fill with NOP-s
87      * @return \c (stream+howMany)
88      */
89     static char * nops(char * stream, unsigned howMany);
90 
91     /**
92      * @brief Inserts a prefix into the code buffer.
93      *
94      * The method writes no more than one byte into the buffer. This is a
95      * caller's responsibility to make sure the buffer is big enough.
96      *
97      * @param stream - buffer where to insert the prefix
98      * @param pref - prefix to be inserted. If it's InstPrefix_Null, then
99      *        no action performed and return value is \c stream.
100      * @return \c (stream+1) if pref is not InstPrefix_Null, or \c stream
101      *         otherwise
102      */
103      static char * prefix(char* stream, InstPrefix pref);
104 
105     /**
106      * @brief Determines if operand with opndExt suites the position with instExt.
107      */
108     static bool extAllowed(OpndExt opndExt, OpndExt instExt);
109 
110     /**
111      * @brief Returns #MnemonicDesc by the given Mnemonic.
112      */
getMnemonicDesc(Mnemonic mn)113     static const MnemonicDesc * getMnemonicDesc(Mnemonic mn)
114     {
115         assert(mn < Mnemonic_Count);
116         return mnemonics + mn;
117     }
118 
119     /**
120      * @brief Returns a Mnemonic for the given name.
121      *
122      * The lookup is case insensitive, if no mnemonic found for the given
123      * string, then Mnemonic_Null returned.
124      */
125     static Mnemonic str2mnemonic(const char * mn_name);
126 
127     /**
128      * @brief Returns a string representation of the given Mnemonic.
129      *
130      * If invalid mnemonic passed, then the behavior is unpredictable.
131      */
getMnemonicString(Mnemonic mn)132     static const char * getMnemonicString(Mnemonic mn)
133     {
134         return getMnemonicDesc(mn)->name;
135     }
136 
toStr(Mnemonic mn)137     static const char * toStr(Mnemonic mn)
138     {
139         return getMnemonicDesc(mn)->name;
140     }
141 
142 
143     /**
144      * @brief Description of operand.
145      *
146      * Description of an operand in opcode - its kind, size or RegName if
147      * operand must be a particular register.
148      */
149     struct OpndDesc {
150         /**
151          * @brief Location of the operand.
152          *
153          * May be a mask, i.e. OpndKind_Imm|OpndKind_Mem.
154          */
155         OpndKind        kind;
156         /**
157          * @brief Size of the operand.
158          */
159         OpndSize        size;
160         /**
161          * @brief Extention of the operand.
162          */
163         OpndExt         ext;
164         /**
165          * @brief Appropriate RegName if operand must reside on a particular
166          *        register (i.e. CWD/CDQ instructions), RegName_Null
167          *        otherwise.
168          */
169         RegName         reg;
170     };
171 
172     /**
173      * @brief Description of operands' roles in instruction.
174      */
175     struct OpndRolesDesc {
176         /**
177          * @brief Total number of operands in the operation.
178          */
179         unsigned                count;
180         /**
181          * @brief Number of defs in the operation.
182          */
183         unsigned                defCount;
184         /**
185          * @brief Number of uses in the operation.
186          */
187         unsigned                useCount;
188         /**
189          * @brief Operand roles, bit-packed.
190          *
191          * A bit-packed info about operands' roles. Each operand's role is
192          * described by two bits, counted from right-to-left - the less
193          * significant bits (0,1) represent operand#0.
194          *
195          * The mask is build by ORing #OpndRole_Def and #OpndRole_Use
196          * appropriately and shifting left, i.e. operand#0's role would be
197          * - '(OpndRole_Def|OpndRole_Use)'
198          * - opnd#1's role would be 'OpndRole_Use<<2'
199          * - and operand#2's role would be, say, 'OpndRole_Def<<4'.
200          */
201         unsigned                roles;
202     };
203 
204     /**
205      * @brief Extracts appropriate OpndRole for a given operand.
206      *
207      * The order of operands is left-to-right, i.e. for MOV, it
208      * would be 'MOV op0, op1'
209      */
getOpndRoles(OpndRolesDesc ord,unsigned idx)210     static OpndRole getOpndRoles(OpndRolesDesc ord, unsigned idx)
211     {
212         assert(idx < ord.count);
213         return (OpndRole)(ord.roles>>((ord.count-1-idx)*2) & 0x3);
214     }
215 
216     /**
217      * @brief Info about single opcode - its opcode bytes, operands,
218      *        operands' roles.
219      */
220    union OpcodeDesc {
221        char dummy[128]; // To make total size a power of 2
222 
223        struct {
224            /**
225            * @brief Raw opcode bytes.
226            *
227            * 'Raw' opcode bytes which do not require any analysis and are
228            * independent from arguments/sizes/etc (may include opcode size
229            * prefix).
230            */
231            char        opcode[5];
232            unsigned    opcode_len;
233            unsigned    aux0;
234            unsigned    aux1;
235            /**
236            * @brief Info about opcode's operands.
237            *
238            * The [3] mostly comes from IDIV/IMUL which both may have up to 3
239            * operands.
240            */
241            OpndDesc        opnds[3];
242            unsigned        first_opnd;
243            /**
244            * @brief Info about operands - total number, number of uses/defs,
245            *        operands' roles.
246            */
247            OpndRolesDesc   roles;
248            /**
249            * @brief If not zero, then this is final OpcodeDesc structure in
250            *        the list of opcodes for a given mnemonic.
251            */
252            char            last;
253            char            platf;
254        };
255    };
256 public:
257     /**
258      * @brief General info about mnemonic.
259      */
260     struct MnemonicDesc {
261         /**
262         * @brief The mnemonic itself.
263         */
264         Mnemonic        mn;
265         /**
266         * Various characteristics of mnemonic.
267         * @see MF_
268          */
269         unsigned    flags;
270         /**
271          * @brief Operation's operand's count and roles.
272          *
273          * For the operations whose opcodes may use different number of
274          * operands (i.e. IMUL/SHL) either most common value used, or empty
275          * value left.
276          */
277         OpndRolesDesc   roles;
278         /**
279          * @brief Print name of the mnemonic.
280          */
281         const char *    name;
282     };
283 
284 
285     /**
286      * @brief Magic number, shows a maximum value a hash code can take.
287      *
288      * For meaning and arithmetics see enc_tabl.cpp.
289      *
290      * The value was increased from '5155' to '8192' to make it aligned
291      * for faster access in EncoderBase::lookup().
292      */
293     static const unsigned int               HASH_MAX = 8192; //5155;
294     /**
295      * @brief Empty value, used in hash-to-opcode map to show an empty slot.
296      */
297     static const unsigned char              NOHASH = 0xFF;
298     /**
299      * @brief The name says it all.
300      */
301     static const unsigned char              HASH_BITS_PER_OPERAND = 5;
302 
303     /**
304      * @brief Contains info about a single instructions's operand - its
305      *        location, size and a value for immediate or RegName for
306      *        register operands.
307      */
308     class Operand {
309     public:
310         /**
311          * @brief Initializes the instance with empty size and kind.
312          */
Operand()313         Operand() : m_kind(OpndKind_Null), m_size(OpndSize_Null), m_ext(OpndExt_None), m_need_rex(false) {}
314         /**
315          * @brief Creates register operand from given RegName.
316          */
m_kind(getRegKind (reg))317         Operand(RegName reg, OpndExt ext = OpndExt_None) : m_kind(getRegKind(reg)),
318                                m_size(getRegSize(reg)),
319                                m_ext(ext), m_reg(reg)
320         {
321             hash_it();
322         }
323         /**
324          * @brief Creates register operand from given RegName and with the
325          *        specified size and kind.
326          *
327          * Used to speedup Operand creation as there is no need to extract
328          * size and kind from the RegName.
329          * The provided size and kind must match the RegName's ones though.
330          */
331         Operand(OpndSize sz, OpndKind kind, RegName reg, OpndExt ext = OpndExt_None) :
m_kind(kind)332             m_kind(kind), m_size(sz), m_ext(ext), m_reg(reg)
333         {
334             assert(m_size == getRegSize(reg));
335             assert(m_kind == getRegKind(reg));
336             hash_it();
337         }
338         /**
339          * @brief Creates immediate operand with the given size and value.
340          */
341         Operand(OpndSize size, long long ival, OpndExt ext = OpndExt_None) :
m_kind(OpndKind_Imm)342             m_kind(OpndKind_Imm), m_size(size), m_ext(ext), m_imm64(ival)
343         {
344             hash_it();
345         }
346         /**
347          * @brief Creates immediate operand of OpndSize_32.
348          */
349         Operand(int ival, OpndExt ext = OpndExt_None) :
m_kind(OpndKind_Imm)350             m_kind(OpndKind_Imm), m_size(OpndSize_32), m_ext(ext), m_imm64(ival)
351         {
352             hash_it();
353         }
354         /**
355          * @brief Creates immediate operand of OpndSize_16.
356          */
357         Operand(short ival, OpndExt ext = OpndExt_None) :
m_kind(OpndKind_Imm)358             m_kind(OpndKind_Imm), m_size(OpndSize_16), m_ext(ext), m_imm64(ival)
359         {
360             hash_it();
361         }
362 
363         /**
364          * @brief Creates immediate operand of OpndSize_8.
365          */
366         Operand(char ival, OpndExt ext = OpndExt_None) :
m_kind(OpndKind_Imm)367             m_kind(OpndKind_Imm), m_size(OpndSize_8), m_ext(ext), m_imm64(ival)
368         {
369             hash_it();
370         }
371 
372         /**
373          * @brief Creates memory operand.
374          */
375         Operand(OpndSize size, RegName base, RegName index, unsigned scale,
m_kind(OpndKind_Mem)376                 int disp, OpndExt ext = OpndExt_None) : m_kind(OpndKind_Mem), m_size(size), m_ext(ext)
377         {
378             m_base = base;
379             m_index = index;
380             m_scale = scale;
381             m_disp = disp;
382             hash_it();
383         }
384 
385         /**
386          * @brief Creates memory operand with only base and displacement.
387          */
388         Operand(OpndSize size, RegName base, int disp, OpndExt ext = OpndExt_None) :
m_kind(OpndKind_Mem)389             m_kind(OpndKind_Mem), m_size(size), m_ext(ext)
390         {
391             m_base = base;
392             m_index = RegName_Null;
393             m_scale = 0;
394             m_disp = disp;
395             hash_it();
396         }
397         //
398         // general info
399         //
400         /**
401          * @brief Returns kind of the operand.
402          */
kind(void)403         OpndKind kind(void) const { return m_kind; }
404         /**
405          * @brief Returns size of the operand.
406          */
size(void)407         OpndSize size(void) const { return m_size; }
408         /**
409          * @brief Returns extention of the operand.
410          */
ext(void)411         OpndExt ext(void) const { return m_ext; }
412         /**
413          * @brief Returns hash of the operand.
414          */
hash(void)415         unsigned hash(void) const { return m_hash; }
416         //
417 #ifdef _EM64T_
need_rex(void)418         bool need_rex(void) const { return m_need_rex; }
419 #else
need_rex(void)420         bool need_rex(void) const { return false; }
421 #endif
422         /**
423          * @brief Tests whether operand is memory operand.
424          */
is_mem(void)425         bool is_mem(void) const { return is_placed_in(OpndKind_Mem); }
426         /**
427          * @brief Tests whether operand is immediate operand.
428          */
is_imm(void)429         bool is_imm(void) const { return is_placed_in(OpndKind_Imm); }
430         /**
431          * @brief Tests whether operand is register operand.
432          */
is_reg(void)433         bool is_reg(void) const { return is_placed_in(OpndKind_Reg); }
434         /**
435          * @brief Tests whether operand is general-purpose register operand.
436          */
is_gpreg(void)437         bool is_gpreg(void) const { return is_placed_in(OpndKind_GPReg); }
438         /**
439          * @brief Tests whether operand is float-point pseudo-register operand.
440          */
is_fpreg(void)441         bool is_fpreg(void) const { return is_placed_in(OpndKind_FPReg); }
442         /**
443          * @brief Tests whether operand is XMM register operand.
444          */
is_xmmreg(void)445         bool is_xmmreg(void) const { return is_placed_in(OpndKind_XMMReg); }
446 #ifdef _HAVE_MMX_
447         /**
448          * @brief Tests whether operand is MMX register operand.
449          */
is_mmxreg(void)450         bool is_mmxreg(void) const { return is_placed_in(OpndKind_MMXReg); }
451 #endif
452         /**
453          * @brief Tests whether operand is signed immediate operand.
454          */
455         //bool is_signed(void) const { assert(is_imm()); return m_is_signed; }
456 
457         /**
458          * @brief Returns base of memory operand (RegName_Null if not memory).
459          */
base(void)460         RegName base(void) const { return is_mem() ? m_base : RegName_Null; }
461         /**
462          * @brief Returns index of memory operand (RegName_Null if not memory).
463          */
index(void)464         RegName index(void) const { return is_mem() ? m_index : RegName_Null; }
465         /**
466          * @brief Returns scale of memory operand (0 if not memory).
467          */
scale(void)468         unsigned scale(void) const { return is_mem() ? m_scale : 0; }
469         /**
470          * @brief Returns displacement of memory operand (0 if not memory).
471          */
disp(void)472         int disp(void) const { return is_mem() ? m_disp : 0; }
473         /**
474          * @brief Returns RegName of register operand (RegName_Null if not
475          *        register).
476          */
reg(void)477         RegName reg(void) const { return is_reg() ? m_reg : RegName_Null; }
478         /**
479          * @brief Returns value of immediate operand (0 if not immediate).
480          */
imm(void)481         long long imm(void) const { return is_imm() ? m_imm64 : 0; }
482     private:
is_placed_in(OpndKind kd)483         bool is_placed_in(OpndKind kd) const
484         {
485                 return kd == OpndKind_Reg ?
486                         m_kind == OpndKind_GPReg ||
487 #ifdef _HAVE_MMX_
488                         m_kind == OpndKind_MMXReg ||
489 #endif
490                         m_kind == OpndKind_FPReg ||
491                         m_kind == OpndKind_XMMReg
492                         : kd == m_kind;
493         }
hash_it(void)494         void hash_it(void)
495         {
496             m_hash = get_size_hash(m_size) | get_kind_hash(m_kind);
497 #ifdef _EM64T_
498             m_need_rex = false;
499             if (is_reg() && is_em64t_extra_reg(m_reg)) {
500                 m_need_rex = true;
501             }
502             else if (is_mem() && (is_em64t_extra_reg(m_base) ||
503                                   is_em64t_extra_reg(m_index))) {
504                 m_need_rex = true;
505             }
506 #endif
507         }
508         // general info
509         OpndKind    m_kind;
510         OpndSize    m_size;
511         OpndExt     m_ext;
512         // complex address form support
513         RegName     m_base;
514         RegName     m_index;
515         unsigned    m_scale;
516         union {
517             int         m_disp;
518             RegName     m_reg;
519             long long   m_imm64;
520         };
521         unsigned    m_hash;
522         bool        m_need_rex;
523         friend class EncoderBase::Operands;
524     };
525     /**
526      * @brief Simple container for up to 3 Operand-s.
527      */
528     class Operands {
529     public:
Operands(void)530         Operands(void)
531         {
532             clear();
533         }
Operands(const Operand & op0)534         Operands(const Operand& op0)
535         {
536             clear();
537             add(op0);
538         }
539 
Operands(const Operand & op0,const Operand & op1)540         Operands(const Operand& op0, const Operand& op1)
541         {
542             clear();
543             add(op0); add(op1);
544         }
545 
Operands(const Operand & op0,const Operand & op1,const Operand & op2)546         Operands(const Operand& op0, const Operand& op1, const Operand& op2)
547         {
548             clear();
549             add(op0); add(op1); add(op2);
550         }
551 
count(void)552         unsigned count(void) const { return m_count; }
hash(void)553         unsigned hash(void) const { return m_hash; }
554         const Operand& operator[](unsigned idx) const
555         {
556             assert(idx<m_count);
557             return m_operands[idx];
558         }
559 
add(const Operand & op)560         void add(const Operand& op)
561         {
562             assert(m_count < COUNTOF(m_operands));
563             m_hash = (m_hash<<HASH_BITS_PER_OPERAND) | op.hash();
564             m_operands[m_count++] = op;
565             m_need_rex = m_need_rex || op.m_need_rex;
566         }
567 #ifdef _EM64T_
need_rex(void)568         bool need_rex(void) const { return m_need_rex; }
569 #else
need_rex(void)570         bool need_rex(void) const { return false; }
571 #endif
clear(void)572         void clear(void)
573         {
574             m_count = 0; m_hash = 0; m_need_rex = false;
575         }
576     private:
577         unsigned    m_count;
578         Operand     m_operands[COUNTOF( ((OpcodeDesc*)NULL)->opnds )];
579         unsigned    m_hash;
580         bool        m_need_rex;
581     };
582 public:
583 #ifdef _DEBUG
584     /**
585      * Verifies some presumptions about encoding data table.
586      * Called automaticaly during statics initialization.
587      */
588     static int verify(void);
589 #endif
590 
591 private:
592     /**
593      * @brief Returns found OpcodeDesc by the given Mnemonic and operands.
594      */
595     static const OpcodeDesc * lookup(Mnemonic mn, const Operands& opnds);
596     /**
597      * @brief Encodes mod/rm byte.
598      */
599     static char* encodeModRM(char* stream, const Operands& opnds,
600                              unsigned idx, const OpcodeDesc * odesc, Rex * prex);
601     /**
602      * @brief Encodes special things of opcode description - '/r', 'ib', etc.
603      */
604     static char* encode_aux(char* stream, unsigned aux,
605                             const Operands& opnds, const OpcodeDesc * odesc,
606                             unsigned * pargsCount, Rex* prex);
607 #ifdef _EM64T_
608     /**
609      * @brief Returns true if the 'reg' argument represents one of the new
610      *        EM64T registers - R8(D)-R15(D).
611      *
612      * The 64 bits versions of 'old-fashion' registers, i.e. RAX are not
613      * considered as 'extra'.
614      */
is_em64t_extra_reg(const RegName reg)615     static bool is_em64t_extra_reg(const RegName reg)
616     {
617         if (needs_rex_r(reg)) {
618             return true;
619         }
620         if (RegName_SPL <= reg && reg <= RegName_R15L) {
621             return true;
622         }
623         return false;
624     }
needs_rex_r(const RegName reg)625     static bool needs_rex_r(const RegName reg)
626     {
627         if (RegName_R8 <= reg && reg <= RegName_R15) {
628             return true;
629         }
630         if (RegName_R8D <= reg && reg <= RegName_R15D) {
631             return true;
632         }
633         if (RegName_R8S <= reg && reg <= RegName_R15S) {
634             return true;
635         }
636         if (RegName_R8L <= reg && reg <= RegName_R15L) {
637             return true;
638         }
639         if (RegName_XMM8 <= reg && reg <= RegName_XMM15) {
640             return true;
641         }
642         if (RegName_XMM8D <= reg && reg <= RegName_XMM15D) {
643             return true;
644         }
645         if (RegName_XMM8S <= reg && reg <= RegName_XMM15S) {
646             return true;
647         }
648         return false;
649     }
650     /**
651      * @brief Returns an 'processor's index' of the register - the index
652      *        used to encode the register in ModRM/SIB bytes.
653      *
654      * For the new EM64T registers the 'HW index' differs from the index
655      * encoded in RegName. For old-fashion registers it's effectively the
656      * same as ::getRegIndex(RegName).
657      */
getHWRegIndex(const RegName reg)658     static unsigned char getHWRegIndex(const RegName reg)
659     {
660         if (getRegKind(reg) != OpndKind_GPReg) {
661             return getRegIndex(reg);
662         }
663         if (RegName_SPL <= reg && reg<=RegName_DIL) {
664             return getRegIndex(reg);
665         }
666         if (RegName_R8L<= reg && reg<=RegName_R15L) {
667             return getRegIndex(reg) - getRegIndex(RegName_R8L);
668         }
669         return is_em64t_extra_reg(reg) ?
670                 getRegIndex(reg)-getRegIndex(RegName_R8D) : getRegIndex(reg);
671     }
672 #else
getHWRegIndex(const RegName reg)673     static unsigned char getHWRegIndex(const RegName reg)
674     {
675         return getRegIndex(reg);
676     }
is_em64t_extra_reg(const RegName reg)677     static bool is_em64t_extra_reg(const RegName reg)
678     {
679         return false;
680     }
681 #endif
682 public:
get_size_hash(OpndSize size)683     static unsigned char get_size_hash(OpndSize size) {
684         return (size <= OpndSize_64) ? size_hash[size] : 0xFF;
685     }
get_kind_hash(OpndKind kind)686     static unsigned char get_kind_hash(OpndKind kind) {
687         return (kind <= OpndKind_Mem) ? kind_hash[kind] : 0xFF;
688     }
689 
690     /**
691      * @brief A table used for the fast computation of hash value.
692      *
693      * A change must be strictly balanced with hash-related functions and data
694      * in enc_base.h/.cpp.
695      */
696     static const unsigned char size_hash[OpndSize_64+1];
697     /**
698      * @brief A table used for the fast computation of hash value.
699      *
700      * A change must be strictly balanced with hash-related functions and data
701      * in enc_base.h/.cpp.
702      */
703     static const unsigned char kind_hash[OpndKind_Mem+1];
704     /**
705      * @brief Maximum number of opcodes used for a single mnemonic.
706      *
707      * No arithmetics behind the number, simply estimated.
708      */
709     static const unsigned int   MAX_OPCODES = 32; //20;
710     /**
711      * @brief Mapping between operands hash code and operands.
712      */
713     static unsigned char    opcodesHashMap[Mnemonic_Count][HASH_MAX];
714     /**
715      * @brief Array of mnemonics.
716      */
717     static MnemonicDesc         mnemonics[Mnemonic_Count];
718     /**
719      * @brief Array of available opcodes.
720      */
721     static OpcodeDesc opcodes[Mnemonic_Count][MAX_OPCODES];
722 
723     static int buildTable(void);
724     static void buildMnemonicDesc(const MnemonicInfo * minfo);
725     /**
726      * @brief Computes hash value for the given operands.
727      */
728     static unsigned short getHash(const OpcodeInfo* odesc);
729     /**
730      * @brief Dummy variable, for automatic invocation of buildTable() at
731      *        startup.
732      */
733     static int dummy;
734 
735     static char * curRelOpnd[3];
736 };
737 
738 ENCODER_NAMESPACE_END
739 
740 #endif // ifndef __ENC_BASE_H_INCLUDED__
741