• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * \file libyasm/arch.h
3  * \brief YASM architecture interface.
4  *
5  * \license
6  *  Copyright (C) 2002-2007  Peter Johnson
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *  - Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *  - Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  * \endlicense
29  */
30 #ifndef YASM_ARCH_H
31 #define YASM_ARCH_H
32 
33 /** Errors that may be returned by yasm_arch_module::create(). */
34 typedef enum yasm_arch_create_error {
35     YASM_ARCH_CREATE_OK = 0,            /**< No error. */
36     YASM_ARCH_CREATE_BAD_MACHINE,       /**< Unrecognized machine name. */
37     YASM_ARCH_CREATE_BAD_PARSER         /**< Unrecognized parser name. */
38 } yasm_arch_create_error;
39 
40 /** Return values for yasm_arch_module::parse_check_insnprefix(). */
41 typedef enum yasm_arch_insnprefix {
42     YASM_ARCH_NOTINSNPREFIX = 0,        /**< Unrecognized */
43     YASM_ARCH_INSN,                     /**< An instruction */
44     YASM_ARCH_PREFIX                    /**< An instruction prefix */
45 } yasm_arch_insnprefix;
46 
47 /** Types of registers / target modifiers that may be returned by
48  * yasm_arch_module::parse_check_regtmod().
49  */
50 typedef enum yasm_arch_regtmod {
51     YASM_ARCH_NOTREGTMOD = 0,           /**< Unrecognized */
52     YASM_ARCH_REG,                      /**< A "normal" register */
53     YASM_ARCH_REGGROUP,                 /**< A group of indexable registers */
54     YASM_ARCH_SEGREG,                   /**< A segment register */
55     YASM_ARCH_TARGETMOD                 /**< A target modifier (for jumps) */
56 } yasm_arch_regtmod;
57 
58 #ifndef YASM_DOXYGEN
59 /** Base #yasm_arch structure.  Must be present as the first element in any
60  * #yasm_arch implementation.
61  */
62 typedef struct yasm_arch_base {
63     /** #yasm_arch_module implementation for this architecture. */
64     const struct yasm_arch_module *module;
65 } yasm_arch_base;
66 #endif
67 
68 /** YASM machine subtype.  A number of different machine types may be
69  * associated with a single architecture.  These may be specific CPU's, but
70  * the ABI used to interface with the architecture should be the primary
71  * differentiator between machines.  Some object formats (ELF) use the machine
72  * to determine parameters within the generated output.
73  */
74 typedef struct yasm_arch_machine {
75     /** One-line description of the machine. */
76     const char *name;
77 
78     /** Keyword used to select machine. */
79     const char *keyword;
80 } yasm_arch_machine;
81 
82 /** YASM architecture module interface.
83  * \note All "data" in parser-related functions (yasm_arch_parse_*) needs to
84  *       start the parse initialized to 0 to make it okay for a parser-related
85  *       function to use/check previously stored data to see if it's been
86  *       called before on the same piece of data.
87  */
88 typedef struct yasm_arch_module {
89     /** One-line description of the architecture.
90      * Call yasm_arch_name() to get the name of a particular #yasm_arch.
91      */
92     const char *name;
93 
94     /** Keyword used to select architecture.
95      * Call yasm_arch_keyword() to get the keyword of a particular #yasm_arch.
96      */
97     const char *keyword;
98 
99     /** NULL-terminated list of directives.  NULL if none. */
100     /*@null@*/ const yasm_directive *directives;
101 
102     /** Create architecture.
103      * Module-level implementation of yasm_arch_create().
104      * Call yasm_arch_create() instead of calling this function.
105      */
106     /*@only@*/ yasm_arch * (*create) (const char *machine, const char *parser,
107                                       /*@out@*/ yasm_arch_create_error *error);
108 
109     /** Module-level implementation of yasm_arch_destroy().
110      * Call yasm_arch_destroy() instead of calling this function.
111      */
112     void (*destroy) (/*@only@*/ yasm_arch *arch);
113 
114     /** Module-level implementation of yasm_arch_get_machine().
115      * Call yasm_arch_get_machine() instead of calling this function.
116      */
117     const char * (*get_machine) (const yasm_arch *arch);
118 
119     /** Module-level implementation of yasm_arch_get_address_size().
120      * Call yasm_arch_get_address_size() instead of calling this function.
121      */
122     unsigned int (*get_address_size) (const yasm_arch *arch);
123 
124     /** Module-level implementation of yasm_arch_set_var().
125      * Call yasm_arch_set_var() instead of calling this function.
126      */
127     int (*set_var) (yasm_arch *arch, const char *var, unsigned long val);
128 
129     /** Module-level implementation of yasm_arch_parse_check_insnprefix().
130      * Call yasm_arch_parse_check_insnprefix() instead of calling this function.
131      */
132     yasm_arch_insnprefix (*parse_check_insnprefix)
133         (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
134          /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
135 
136     /** Module-level implementation of yasm_arch_parse_check_regtmod().
137      * Call yasm_arch_parse_check_regtmod() instead of calling this function.
138      */
139     yasm_arch_regtmod (*parse_check_regtmod)
140         (yasm_arch *arch, const char *id, size_t id_len,
141          /*@out@*/ uintptr_t *data);
142 
143     /** Module-level implementation of yasm_arch_get_fill().
144      * Call yasm_arch_get_fill() instead of calling this function.
145      */
146     const unsigned char ** (*get_fill) (const yasm_arch *arch);
147 
148     /** Module-level implementation of yasm_arch_floatnum_tobytes().
149      * Call yasm_arch_floatnum_tobytes() instead of calling this function.
150      */
151     int (*floatnum_tobytes) (yasm_arch *arch, const yasm_floatnum *flt,
152                              unsigned char *buf, size_t destsize,
153                              size_t valsize, size_t shift, int warn);
154 
155     /** Module-level implementation of yasm_arch_intnum_tobytes().
156      * Call yasm_arch_intnum_tobytes() instead of calling this function.
157      */
158     int (*intnum_tobytes) (yasm_arch *arch, const yasm_intnum *intn,
159                            unsigned char *buf, size_t destsize, size_t valsize,
160                            int shift, const yasm_bytecode *bc,
161                            int warn);
162 
163     /** Module-level implementation of yasm_arch_get_reg_size().
164      * Call yasm_arch_get_reg_size() instead of calling this function.
165      */
166     unsigned int (*get_reg_size) (yasm_arch *arch, uintptr_t reg);
167 
168     /** Module-level implementation of yasm_arch_reggroup_get_reg().
169      * Call yasm_arch_reggroup_get_reg() instead of calling this function.
170      */
171     uintptr_t (*reggroup_get_reg) (yasm_arch *arch, uintptr_t reggroup,
172                                    unsigned long regindex);
173 
174     /** Module-level implementation of yasm_arch_reg_print().
175      * Call yasm_arch_reg_print() instead of calling this function.
176      */
177     void (*reg_print) (yasm_arch *arch, uintptr_t reg, FILE *f);
178 
179     /** Module-level implementation of yasm_arch_segreg_print().
180      * Call yasm_arch_segreg_print() instead of calling this function.
181      */
182     void (*segreg_print) (yasm_arch *arch, uintptr_t segreg, FILE *f);
183 
184     /** Module-level implementation of yasm_arch_ea_create().
185      * Call yasm_arch_ea_create() instead of calling this function.
186      */
187     yasm_effaddr * (*ea_create) (yasm_arch *arch, /*@keep@*/ yasm_expr *e);
188 
189     /** Module-level implementation of yasm_arch_ea_destroy().
190      * Call yasm_arch_ea_destroy() instead of calling this function.
191      */
192     void (*ea_destroy) (/*@only@*/ yasm_effaddr *ea);
193 
194     /** Module-level implementation of yasm_arch_ea_print().
195      * Call yasm_arch_ea_print() instead of calling this function.
196      */
197     void (*ea_print) (const yasm_effaddr *ea, FILE *f, int indent_level);
198 
199     /** Module-level implementation of yasm_arch_create_empty_insn().
200      * Call yasm_arch_create_empty_insn() instead of calling this function.
201      */
202     /*@only@*/ yasm_bytecode * (*create_empty_insn) (yasm_arch *arch,
203                                                      unsigned long line);
204 
205     /** NULL-terminated list of machines for this architecture.
206      * Call yasm_arch_get_machine() to get the active machine of a particular
207      * #yasm_arch.
208      */
209     const yasm_arch_machine *machines;
210 
211     /** Default machine keyword.
212      * Call yasm_arch_get_machine() to get the active machine of a particular
213      * #yasm_arch.
214      */
215     const char *default_machine_keyword;
216 
217     /** Canonical "word" size in bits.
218      * Call yasm_arch_wordsize() to get the word size of a particular
219      * #yasm_arch.
220      */
221     unsigned int wordsize;
222 
223     /** Worst case minimum instruction length in bytes.
224      * Call yasm_arch_min_insn_len() to get the minimum instruction length of
225      * a particular #yasm_arch.
226      */
227     unsigned int min_insn_len;
228 } yasm_arch_module;
229 
230 /** Get the one-line description of an architecture.
231  * \param arch      architecture
232  * \return One-line description of architecture.
233  */
234 const char *yasm_arch_name(const yasm_arch *arch);
235 
236 /** Get the keyword used to select an architecture.
237  * \param arch      architecture
238  * \return Architecture keyword.
239  */
240 const char *yasm_arch_keyword(const yasm_arch *arch);
241 
242 /** Get the word size of an architecture.
243  * \param arch      architecture
244  * \return Word size (in bits).
245  */
246 unsigned int yasm_arch_wordsize(const yasm_arch *arch);
247 
248 /** Get the minimum instruction length of an architecture.
249  * \param arch      architecture
250  * \return Minimum instruction length (in bytes).
251  */
252 unsigned int yasm_arch_min_insn_len(const yasm_arch *arch);
253 
254 /** Create architecture.
255  * \param module        architecture module
256  * \param machine       keyword of machine in use (must be one listed in
257  *                      #yasm_arch_module.machines)
258  * \param parser        keyword of parser in use
259  * \param error         error return value
260  * \return NULL on error (error returned in error parameter), otherwise new
261  *         architecture.
262  */
263 /*@only@*/ yasm_arch *yasm_arch_create(const yasm_arch_module *module,
264                                        const char *machine, const char *parser,
265                                        /*@out@*/ yasm_arch_create_error *error);
266 
267 /** Clean up, free any architecture-allocated memory.
268  * \param arch  architecture
269  */
270 void yasm_arch_destroy(/*@only@*/ yasm_arch *arch);
271 
272 /** Get architecture's active machine name.
273  * \param arch  architecture
274  * \return Active machine name.
275  */
276 const char *yasm_arch_get_machine(const yasm_arch *arch);
277 
278 /** Get architecture's active address size, in bits.
279  * \param arch  architecture
280  * \return Active address size (in bits).
281  */
282 unsigned int yasm_arch_get_address_size(const yasm_arch *arch);
283 
284 /** Set any arch-specific variables.  For example, "mode_bits" in x86.
285  * \param arch  architecture
286  * \param var   variable name
287  * \param val   value to set
288  * \return Zero on success, non-zero on failure (variable does not exist).
289  */
290 int yasm_arch_set_var(yasm_arch *arch, const char *var, unsigned long val);
291 
292 /** Check an generic identifier to see if it matches architecture specific
293  * names for instructions or instruction prefixes.  Unrecognized identifiers
294  * should return #YASM_ARCH_NOTINSNPREFIX so they can be treated as normal
295  * symbols.  Any additional data beyond just the type (almost always necessary)
296  * should be returned into the space provided by the data parameter.
297  * \param arch          architecture
298  * \param id            identifier as in the input file
299  * \param id_len        length of id string
300  * \param line          virtual line
301  * \param bc            for instructions, yasm_insn-based bytecode is returned
302  *                      (and NULL otherwise)
303  * \param prefix        for prefixes, yasm_arch-specific value is returned
304  *                      (and 0 otherwise)
305  * \return Identifier type (#YASM_ARCH_NOTINSNPREFIX if unrecognized)
306  */
307 yasm_arch_insnprefix yasm_arch_parse_check_insnprefix
308     (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
309      /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
310 
311 /** Check an generic identifier to see if it matches architecture specific
312  * names for registers or target modifiers.  Unrecognized identifiers should
313  * return #YASM_ARCH_NOTREGTMOD.  Any additional data beyond just the type
314  * (almost always necessary) should be returned into the space provided by the
315  * data parameter.
316  * \param arch          architecture
317  * \param id            identifier as in the input file
318  * \param id_len        length of id string
319  * \param data          extra identification information (yasm_arch-specific)
320  *                      [output]
321  * \return Identifier type (#YASM_ARCH_NOTREGTMOD if unrecognized)
322  */
323 yasm_arch_regtmod yasm_arch_parse_check_regtmod
324     (yasm_arch *arch, const char *id, size_t id_len,
325      /*@out@*/ uintptr_t *data);
326 
327 /** Get NOP fill patterns for 1-15 bytes of fill.
328  * \param arch          architecture
329  * \return 16-entry array of arrays; [0] is unused, [1] - [15] point to arrays
330  * of 1-15 bytes (respectively) in length.
331  */
332 const unsigned char **yasm_arch_get_fill(const yasm_arch *arch);
333 
334 /** Output #yasm_floatnum to buffer.  Puts the value into the least
335  * significant bits of the destination, or may be shifted into more
336  * significant bits by the shift parameter.  The destination bits are
337  * cleared before being set.
338  * Architecture-specific because of endianness.
339  * \param arch          architecture
340  * \param flt           floating point value
341  * \param buf           buffer to write into
342  * \param destsize      destination size (in bytes)
343  * \param valsize       size (in bits)
344  * \param shift         left shift (in bits)
345  * \param warn          enables standard overflow/underflow warnings
346  * \return Nonzero on error.
347  */
348 int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
349                                unsigned char *buf, size_t destsize,
350                                size_t valsize, size_t shift, int warn);
351 
352 /** Output #yasm_intnum to buffer.  Puts the value into the least
353  * significant bits of the destination, or may be shifted into more
354  * significant bits by the shift parameter.  The destination bits are
355  * cleared before being set.
356  * \param arch          architecture
357  * \param intn          integer value
358  * \param buf           buffer to write into
359  * \param destsize      destination size (in bytes)
360  * \param valsize       size (in bits)
361  * \param shift         left shift (in bits); may be negative to specify right
362  *                      shift (standard warnings include truncation to boundary)
363  * \param bc            bytecode being output ("parent" of value)
364  * \param warn          enables standard warnings (value doesn't fit into
365  *                      valsize bits)
366  * \return Nonzero on error.
367  */
368 int yasm_arch_intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
369                              unsigned char *buf, size_t destsize,
370                              size_t valsize, int shift,
371                              const yasm_bytecode *bc, int warn);
372 
373 /** Get the equivalent size of a register in bits.
374  * \param arch  architecture
375  * \param reg   register
376  * \return 0 if there is no suitable equivalent size, otherwise the size.
377  */
378 unsigned int yasm_arch_get_reg_size(yasm_arch *arch, uintptr_t reg);
379 
380 /** Get a specific register of a register group, based on the register
381  * group and the index within the group.
382  * \param arch          architecture
383  * \param reggroup      register group
384  * \param regindex      register index
385  * \return 0 if regindex is not valid for that register group, otherwise the
386  *         specific register value.
387  */
388 uintptr_t yasm_arch_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup,
389                                      unsigned long regindex);
390 
391 /** Print a register.  For debugging purposes.
392  * \param arch          architecture
393  * \param reg           register
394  * \param f             file
395  */
396 void yasm_arch_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f);
397 
398 /** Print a segment register.  For debugging purposes.
399  * \param arch          architecture
400  * \param segreg        segment register
401  * \param f             file
402  */
403 void yasm_arch_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f);
404 
405 /** Create an effective address from an expression.
406  * \param arch  architecture
407  * \param e     expression (kept, do not delete)
408  * \return Newly allocated effective address.
409  */
410 yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e);
411 
412 /** Delete (free allocated memory for) an effective address.
413  * \param arch  architecture
414  * \param ea    effective address (only pointer to it).
415  */
416 void yasm_arch_ea_destroy(yasm_arch *arch, /*@only@*/ yasm_effaddr *ea);
417 
418 /** Print an effective address.  For debugging purposes.
419  * \param arch          architecture
420  * \param ea            effective address
421  * \param f             file
422  * \param indent_level  indentation level
423  */
424 void yasm_arch_ea_print(const yasm_arch *arch, const yasm_effaddr *ea,
425                         FILE *f, int indent_level);
426 
427 /** Create a bytecode that represents a single empty (0 length) instruction.
428  * This is used for handling solitary prefixes.
429  * \param arch          architecture
430  * \param line          virtual line (from yasm_linemap)
431  * \return Newly allocated bytecode.
432  */
433 /*@only@*/ yasm_bytecode *yasm_arch_create_empty_insn(yasm_arch *arch,
434                                                       unsigned long line);
435 
436 #ifndef YASM_DOXYGEN
437 
438 /* Inline macro implementations for arch functions */
439 
440 #define yasm_arch_name(arch) \
441     (((yasm_arch_base *)arch)->module->name)
442 #define yasm_arch_keyword(arch) \
443     (((yasm_arch_base *)arch)->module->keyword)
444 #define yasm_arch_wordsize(arch) \
445     (((yasm_arch_base *)arch)->module->wordsize)
446 #define yasm_arch_min_insn_len(arch) \
447     (((yasm_arch_base *)arch)->module->min_insn_len)
448 
449 #define yasm_arch_create(module, machine, parser, error) \
450     module->create(machine, parser, error)
451 
452 #define yasm_arch_destroy(arch) \
453     ((yasm_arch_base *)arch)->module->destroy(arch)
454 #define yasm_arch_get_machine(arch) \
455     ((yasm_arch_base *)arch)->module->get_machine(arch)
456 #define yasm_arch_get_address_size(arch) \
457     ((yasm_arch_base *)arch)->module->get_address_size(arch)
458 #define yasm_arch_set_var(arch, var, val) \
459     ((yasm_arch_base *)arch)->module->set_var(arch, var, val)
460 #define yasm_arch_parse_check_insnprefix(arch, id, id_len, line, bc, prefix) \
461     ((yasm_arch_base *)arch)->module->parse_check_insnprefix \
462         (arch, id, id_len, line, bc, prefix)
463 #define yasm_arch_parse_check_regtmod(arch, id, id_len, data) \
464     ((yasm_arch_base *)arch)->module->parse_check_regtmod \
465         (arch, id, id_len, data)
466 #define yasm_arch_get_fill(arch) \
467     ((yasm_arch_base *)arch)->module->get_fill(arch)
468 #define yasm_arch_floatnum_tobytes(arch, flt, buf, destsize, valsize, shift, \
469                                    warn) \
470     ((yasm_arch_base *)arch)->module->floatnum_tobytes \
471         (arch, flt, buf, destsize, valsize, shift, warn)
472 #define yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, shift, \
473                                  bc, warn) \
474     ((yasm_arch_base *)arch)->module->intnum_tobytes \
475         (arch, intn, buf, destsize, valsize, shift, bc, warn)
476 #define yasm_arch_get_reg_size(arch, reg) \
477     ((yasm_arch_base *)arch)->module->get_reg_size(arch, reg)
478 #define yasm_arch_reggroup_get_reg(arch, regg, regi) \
479     ((yasm_arch_base *)arch)->module->reggroup_get_reg(arch, regg, regi)
480 #define yasm_arch_reg_print(arch, reg, f) \
481     ((yasm_arch_base *)arch)->module->reg_print(arch, reg, f)
482 #define yasm_arch_segreg_print(arch, segreg, f) \
483     ((yasm_arch_base *)arch)->module->segreg_print(arch, segreg, f)
484 #define yasm_arch_ea_create(arch, e) \
485     ((yasm_arch_base *)arch)->module->ea_create(arch, e)
486 #define yasm_arch_ea_destroy(arch, ea) \
487     ((yasm_arch_base *)arch)->module->ea_destroy(ea)
488 #define yasm_arch_ea_print(arch, ea, f, i) \
489     ((yasm_arch_base *)arch)->module->ea_print(ea, f, i)
490 #define yasm_arch_create_empty_insn(arch, line) \
491     ((yasm_arch_base *)arch)->module->create_empty_insn(arch, line)
492 
493 #endif
494 
495 #endif
496