mirror of https://github.com/yasm/yasm.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
637 lines
24 KiB
637 lines
24 KiB
/** |
|
* \file libyasm/arch.h |
|
* \brief YASM architecture interface. |
|
* |
|
* \rcs |
|
* $Id$ |
|
* \endrcs |
|
* |
|
* \license |
|
* Copyright (C) 2002 Peter Johnson |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
* are met: |
|
* - Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* - Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
* POSSIBILITY OF SUCH DAMAGE. |
|
* \endlicense |
|
*/ |
|
#ifndef YASM_ARCH_H |
|
#define YASM_ARCH_H |
|
|
|
/** Errors that may be returned by yasm_arch_module::create(). */ |
|
typedef enum yasm_arch_create_error { |
|
YASM_ARCH_CREATE_OK = 0, /**< No error. */ |
|
YASM_ARCH_CREATE_BAD_MACHINE, /**< Unrecognized machine name. */ |
|
YASM_ARCH_CREATE_BAD_PARSER /**< Unrecognized parser name. */ |
|
} yasm_arch_create_error; |
|
|
|
/** Return values for yasm_arch_module::parse_check_insnprefix(). */ |
|
typedef enum yasm_arch_insnprefix { |
|
YASM_ARCH_NOTINSNPREFIX = 0, /**< Unrecognized */ |
|
YASM_ARCH_INSN, /**< An instruction */ |
|
YASM_ARCH_PREFIX /**< An instruction prefix */ |
|
} yasm_arch_insnprefix; |
|
|
|
/** Types of registers / target modifiers that may be returned by |
|
* yasm_arch_module::parse_check_regtmod(). |
|
*/ |
|
typedef enum yasm_arch_regtmod { |
|
YASM_ARCH_NOTREGTMOD = 0, /**< Unrecognized */ |
|
YASM_ARCH_REG, /**< A "normal" register */ |
|
YASM_ARCH_REGGROUP, /**< A group of indexable registers */ |
|
YASM_ARCH_SEGREG, /**< A segment register */ |
|
YASM_ARCH_TARGETMOD /**< A target modifier (for jumps) */ |
|
} yasm_arch_regtmod; |
|
|
|
/** An instruction operand (opaque type). */ |
|
typedef struct yasm_insn_operand yasm_insn_operand; |
|
#ifdef YASM_LIB_INTERNAL |
|
/*@reldef@*/ STAILQ_HEAD(yasm_insn_operands, yasm_insn_operand); |
|
#endif |
|
|
|
#ifndef YASM_DOXYGEN |
|
/** Base #yasm_arch structure. Must be present as the first element in any |
|
* #yasm_arch implementation. |
|
*/ |
|
typedef struct yasm_arch_base { |
|
/** #yasm_arch_module implementation for this architecture. */ |
|
const struct yasm_arch_module *module; |
|
} yasm_arch_base; |
|
#endif |
|
|
|
/** YASM machine subtype. A number of different machine types may be |
|
* associated with a single architecture. These may be specific CPU's, but |
|
* the ABI used to interface with the architecture should be the primary |
|
* differentiator between machines. Some object formats (ELF) use the machine |
|
* to determine parameters within the generated output. |
|
*/ |
|
typedef struct yasm_arch_machine { |
|
/** One-line description of the machine. */ |
|
const char *name; |
|
|
|
/** Keyword used to select machine. */ |
|
const char *keyword; |
|
} yasm_arch_machine; |
|
|
|
/** YASM architecture module interface. |
|
* \note All "data" in parser-related functions (yasm_arch_parse_*) needs to |
|
* start the parse initialized to 0 to make it okay for a parser-related |
|
* function to use/check previously stored data to see if it's been |
|
* called before on the same piece of data. |
|
*/ |
|
typedef struct yasm_arch_module { |
|
/** One-line description of the architecture. |
|
* Call yasm_arch_name() to get the name of a particular #yasm_arch. |
|
*/ |
|
const char *name; |
|
|
|
/** Keyword used to select architecture. |
|
* Call yasm_arch_keyword() to get the keyword of a particular #yasm_arch. |
|
*/ |
|
const char *keyword; |
|
|
|
/** NULL-terminated list of directives. NULL if none. */ |
|
/*@null@*/ const yasm_directive *directives; |
|
|
|
/** Create architecture. |
|
* Module-level implementation of yasm_arch_create(). |
|
* Call yasm_arch_create() instead of calling this function. |
|
*/ |
|
/*@only@*/ yasm_arch * (*create) (const char *machine, const char *parser, |
|
yasm_arch_create_error *error); |
|
|
|
/** Module-level implementation of yasm_arch_destroy(). |
|
* Call yasm_arch_destroy() instead of calling this function. |
|
*/ |
|
void (*destroy) (/*@only@*/ yasm_arch *arch); |
|
|
|
/** Module-level implementation of yasm_arch_get_machine(). |
|
* Call yasm_arch_get_machine() instead of calling this function. |
|
*/ |
|
const char * (*get_machine) (const yasm_arch *arch); |
|
|
|
/** Module-level implementation of yasm_arch_get_address_size(). |
|
* Call yasm_arch_get_address_size() instead of calling this function. |
|
*/ |
|
unsigned int (*get_address_size) (const yasm_arch *arch); |
|
|
|
/** Module-level implementation of yasm_arch_set_var(). |
|
* Call yasm_arch_set_var() instead of calling this function. |
|
*/ |
|
int (*set_var) (yasm_arch *arch, const char *var, unsigned long val); |
|
|
|
/** Module-level implementation of yasm_arch_parse_check_insnprefix(). |
|
* Call yasm_arch_parse_check_insnprefix() instead of calling this function. |
|
*/ |
|
yasm_arch_insnprefix (*parse_check_insnprefix) |
|
(yasm_arch *arch, /*@out@*/ uintptr_t data[4], const char *id, |
|
size_t id_len); |
|
|
|
/** Module-level implementation of yasm_arch_parse_check_regtmod(). |
|
* Call yasm_arch_parse_check_regtmod() instead of calling this function. |
|
*/ |
|
yasm_arch_regtmod (*parse_check_regtmod) |
|
(yasm_arch *arch, /*@out@*/ uintptr_t *data, const char *id, |
|
size_t id_len); |
|
|
|
/** Module-level implementation of yasm_arch_get_fill(). |
|
* Call yasm_arch_get_fill() instead of calling this function. |
|
*/ |
|
const unsigned char ** (*get_fill) (const yasm_arch *arch); |
|
|
|
/** Module-level implementation of yasm_arch_finalize_insn(). |
|
* Call yasm_arch_finalize_insn() instead of calling this function. |
|
*/ |
|
void (*finalize_insn) |
|
(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc, |
|
const uintptr_t data[4], int num_operands, |
|
/*@null@*/ yasm_insn_operands *operands, int num_prefixes, |
|
uintptr_t **prefixes, int num_segregs, const uintptr_t *segregs); |
|
|
|
/** Module-level implementation of yasm_arch_floatnum_tobytes(). |
|
* Call yasm_arch_floatnum_tobytes() instead of calling this function. |
|
*/ |
|
int (*floatnum_tobytes) (yasm_arch *arch, const yasm_floatnum *flt, |
|
unsigned char *buf, size_t destsize, |
|
size_t valsize, size_t shift, int warn); |
|
|
|
/** Module-level implementation of yasm_arch_intnum_tobytes(). |
|
* Call yasm_arch_intnum_tobytes() instead of calling this function. |
|
*/ |
|
int (*intnum_tobytes) (yasm_arch *arch, const yasm_intnum *intn, |
|
unsigned char *buf, size_t destsize, size_t valsize, |
|
int shift, const yasm_bytecode *bc, |
|
int warn); |
|
|
|
/** Module-level implementation of yasm_arch_get_reg_size(). |
|
* Call yasm_arch_get_reg_size() instead of calling this function. |
|
*/ |
|
unsigned int (*get_reg_size) (yasm_arch *arch, uintptr_t reg); |
|
|
|
/** Module-level implementation of yasm_arch_reggroup_get_reg(). |
|
* Call yasm_arch_reggroup_get_reg() instead of calling this function. |
|
*/ |
|
uintptr_t (*reggroup_get_reg) (yasm_arch *arch, uintptr_t reggroup, |
|
unsigned long regindex); |
|
|
|
/** Module-level implementation of yasm_arch_reg_print(). |
|
* Call yasm_arch_reg_print() instead of calling this function. |
|
*/ |
|
void (*reg_print) (yasm_arch *arch, uintptr_t reg, FILE *f); |
|
|
|
/** Module-level implementation of yasm_arch_segreg_print(). |
|
* Call yasm_arch_segreg_print() instead of calling this function. |
|
*/ |
|
void (*segreg_print) (yasm_arch *arch, uintptr_t segreg, FILE *f); |
|
|
|
/** Module-level implementation of yasm_arch_ea_create(). |
|
* Call yasm_arch_ea_create() instead of calling this function. |
|
*/ |
|
yasm_effaddr * (*ea_create) (yasm_arch *arch, /*@keep@*/ yasm_expr *e); |
|
|
|
/** NULL-terminated list of machines for this architecture. |
|
* Call yasm_arch_get_machine() to get the active machine of a particular |
|
* #yasm_arch. |
|
*/ |
|
const yasm_arch_machine *machines; |
|
|
|
/** Default machine keyword. |
|
* Call yasm_arch_get_machine() to get the active machine of a particular |
|
* #yasm_arch. |
|
*/ |
|
const char *default_machine_keyword; |
|
|
|
/** Canonical "word" size in bits. |
|
* Call yasm_arch_wordsize() to get the word size of a particular |
|
* #yasm_arch. |
|
*/ |
|
unsigned int wordsize; |
|
|
|
/** Worst case minimum instruction length in bytes. |
|
* Call yasm_arch_min_insn_len() to get the minimum instruction length of |
|
* a particular #yasm_arch. |
|
*/ |
|
unsigned int min_insn_len; |
|
} yasm_arch_module; |
|
|
|
#ifdef YASM_LIB_INTERNAL |
|
/** An instruction operand. \internal */ |
|
struct yasm_insn_operand { |
|
/** Link for building linked list of operands. \internal */ |
|
/*@reldef@*/ STAILQ_ENTRY(yasm_insn_operand) link; |
|
|
|
/** Operand type. */ |
|
enum yasm_insn_operand_type { |
|
YASM_INSN__OPERAND_REG = 1, /**< A register. */ |
|
YASM_INSN__OPERAND_SEGREG, /**< A segment register. */ |
|
YASM_INSN__OPERAND_MEMORY, /**< An effective address |
|
* (memory reference). */ |
|
YASM_INSN__OPERAND_IMM /**< An immediate or jump target. */ |
|
} type; |
|
|
|
/** Operand data. */ |
|
union { |
|
uintptr_t reg; /**< Arch data for reg/segreg. */ |
|
yasm_effaddr *ea; /**< Effective address for memory references. */ |
|
yasm_expr *val; /**< Value of immediate or jump target. */ |
|
} data; |
|
|
|
uintptr_t targetmod; /**< Arch target modifier, 0 if none. */ |
|
|
|
/** Specified size of the operand, in bits. 0 if not user-specified. */ |
|
unsigned int size:8; |
|
|
|
/** Nonzero if dereference. Used for "*foo" in GAS. |
|
* The reason for this is that by default in GAS, an unprefixed value |
|
* is a memory address, except for jumps/calls, in which case it needs a |
|
* "*" prefix to become a memory address (otherwise it's an immediate). |
|
* This isn't knowable in the parser stage, so the parser sets this flag |
|
* to indicate the "*" prefix has been used, and the arch needs to adjust |
|
* the operand type appropriately depending on the instruction type. |
|
*/ |
|
unsigned int deref:1; |
|
|
|
/** Nonzero if strict. Used for "strict foo" in NASM. |
|
* This is used to inhibit optimization on otherwise "sized" values. |
|
* For example, the user may just want to be explicit with the size on |
|
* "push dword 4", but not actually want to force the immediate size to |
|
* 4 bytes (rather wanting the optimizer to optimize it down to 1 byte as |
|
* though "dword" was not specified). To indicate the immediate should |
|
* actually be forced to 4 bytes, the user needs to write |
|
* "push strict dword 4", which sets this flag. |
|
*/ |
|
unsigned int strict:1; |
|
}; |
|
#endif |
|
|
|
/** Get the one-line description of an architecture. |
|
* \param arch architecture |
|
* \return One-line description of architecture. |
|
*/ |
|
const char *yasm_arch_name(const yasm_arch *arch); |
|
|
|
/** Get the keyword used to select an architecture. |
|
* \param arch architecture |
|
* \return Architecture keyword. |
|
*/ |
|
const char *yasm_arch_keyword(const yasm_arch *arch); |
|
|
|
/** Get the word size of an architecture. |
|
* \param arch architecture |
|
* \return Word size (in bits). |
|
*/ |
|
unsigned int yasm_arch_wordsize(const yasm_arch *arch); |
|
|
|
/** Get the minimum instruction length of an architecture. |
|
* \param arch architecture |
|
* \return Minimum instruction length (in bytes). |
|
*/ |
|
unsigned int yasm_arch_min_insn_len(const yasm_arch *arch); |
|
|
|
/** Create architecture. |
|
* \param module architecture module |
|
* \param machine keyword of machine in use (must be one listed in |
|
* #yasm_arch_module.machines) |
|
* \param parser keyword of parser in use |
|
* \param error error return value |
|
* \return NULL on error (error returned in error parameter), otherwise new |
|
* architecture. |
|
*/ |
|
/*@only@*/ yasm_arch *yasm_arch_create(const yasm_arch_module *module, |
|
const char *machine, const char *parser, |
|
/*@out@*/ yasm_arch_create_error *error); |
|
|
|
/** Clean up, free any architecture-allocated memory. |
|
* \param arch architecture |
|
*/ |
|
void yasm_arch_destroy(/*@only@*/ yasm_arch *arch); |
|
|
|
/** Get architecture's active machine name. |
|
* \param arch architecture |
|
* \return Active machine name. |
|
*/ |
|
const char *yasm_arch_get_machine(const yasm_arch *arch); |
|
|
|
/** Get architecture's active address size, in bits. |
|
* \param arch architecture |
|
* \return Active address size (in bits). |
|
*/ |
|
unsigned int yasm_arch_get_address_size(const yasm_arch *arch); |
|
|
|
/** Set any arch-specific variables. For example, "mode_bits" in x86. |
|
* \param arch architecture |
|
* \param var variable name |
|
* \param val value to set |
|
* \return Zero on success, non-zero on failure (variable does not exist). |
|
*/ |
|
int yasm_arch_set_var(yasm_arch *arch, const char *var, unsigned long val); |
|
|
|
/** Check an generic identifier to see if it matches architecture specific |
|
* names for instructions or instruction prefixes. Unrecognized identifiers |
|
* should return #YASM_ARCH_NOTINSNPREFIX so they can be treated as normal |
|
* symbols. Any additional data beyond just the type (almost always necessary) |
|
* should be returned into the space provided by the data parameter. |
|
* \param arch architecture |
|
* \param data extra identification information (yasm_arch-specific) |
|
* [output] |
|
* \param id identifier as in the input file |
|
* \param id_len length of id string |
|
* \return Identifier type (#YASM_ARCH_NOTINSNPREFIX if unrecognized) |
|
*/ |
|
yasm_arch_insnprefix yasm_arch_parse_check_insnprefix |
|
(yasm_arch *arch, /*@out@*/ uintptr_t data[4], const char *id, |
|
size_t id_len); |
|
|
|
/** Check an generic identifier to see if it matches architecture specific |
|
* names for registers or target modifiers. Unrecognized identifiers should |
|
* return #YASM_ARCH_NOTREGTMOD. Any additional data beyond just the type |
|
* (almost always necessary) should be returned into the space provided by the |
|
* data parameter. |
|
* \param arch architecture |
|
* \param data extra identification information (yasm_arch-specific) |
|
* [output] |
|
* \param id identifier as in the input file |
|
* \param id_len length of id string |
|
* \return Identifier type (#YASM_ARCH_NOTREGTMOD if unrecognized) |
|
*/ |
|
yasm_arch_regtmod yasm_arch_parse_check_regtmod |
|
(yasm_arch *arch, /*@out@*/ uintptr_t *data, const char *id, |
|
size_t id_len); |
|
|
|
/** Get NOP fill patterns for 1-15 bytes of fill. |
|
* \param arch architecture |
|
* \return 16-entry array of arrays; [0] is unused, [1] - [15] point to arrays |
|
* of 1-15 bytes (respectively) in length. |
|
*/ |
|
const unsigned char **yasm_arch_get_fill(const yasm_arch *arch); |
|
|
|
/** Finalize an instruction from a semi-generic insn description. Note an |
|
* existing bytecode is required. |
|
* \param arch architecture |
|
* \param bc bytecode to finalize |
|
* \param prev_bc previous bytecode in section |
|
* \param data instruction data (from parse_check_id()); all |
|
* zero indicates an empty instruction |
|
* \param num_operands number of operands |
|
* \param operands list of operands (in parse order) |
|
* \param num_prefixes number of prefixes |
|
* \param prefixes array of 4-element prefix data |
|
* \param num_segregs number of segment register prefixes |
|
* \param segregs array of segment register data |
|
* \return If no match is found (the instruction is invalid), no action is |
|
* performed and an error is recorded. |
|
*/ |
|
void yasm_arch_finalize_insn |
|
(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc, |
|
const uintptr_t data[4], int num_operands, |
|
/*@null@*/ yasm_insn_operands *operands, int num_prefixes, |
|
const uintptr_t **prefixes, int num_segregs, const uintptr_t *segregs); |
|
|
|
/** Output #yasm_floatnum to buffer. Puts the value into the least |
|
* significant bits of the destination, or may be shifted into more |
|
* significant bits by the shift parameter. The destination bits are |
|
* cleared before being set. |
|
* Architecture-specific because of endianness. |
|
* \param arch architecture |
|
* \param flt floating point value |
|
* \param buf buffer to write into |
|
* \param destsize destination size (in bytes) |
|
* \param valsize size (in bits) |
|
* \param shift left shift (in bits) |
|
* \param warn enables standard overflow/underflow warnings |
|
* \return Nonzero on error. |
|
*/ |
|
int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt, |
|
unsigned char *buf, size_t destsize, |
|
size_t valsize, size_t shift, int warn); |
|
|
|
/** Output #yasm_intnum to buffer. Puts the value into the least |
|
* significant bits of the destination, or may be shifted into more |
|
* significant bits by the shift parameter. The destination bits are |
|
* cleared before being set. |
|
* \param arch architecture |
|
* \param intn integer value |
|
* \param buf buffer to write into |
|
* \param destsize destination size (in bytes) |
|
* \param valsize size (in bits) |
|
* \param shift left shift (in bits); may be negative to specify right |
|
* shift (standard warnings include truncation to boundary) |
|
* \param bc bytecode being output ("parent" of value) |
|
* \param warn enables standard warnings (value doesn't fit into |
|
* valsize bits) |
|
* \return Nonzero on error. |
|
*/ |
|
int yasm_arch_intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn, |
|
unsigned char *buf, size_t destsize, |
|
size_t valsize, int shift, |
|
const yasm_bytecode *bc, int warn); |
|
|
|
/** Get the equivalent size of a register in bits. |
|
* \param arch architecture |
|
* \param reg register |
|
* \return 0 if there is no suitable equivalent size, otherwise the size. |
|
*/ |
|
unsigned int yasm_arch_get_reg_size(yasm_arch *arch, uintptr_t reg); |
|
|
|
/** Get a specific register of a register group, based on the register |
|
* group and the index within the group. |
|
* \param arch architecture |
|
* \param reggroup register group |
|
* \param regindex register index |
|
* \return 0 if regindex is not valid for that register group, otherwise the |
|
* specific register value. |
|
*/ |
|
uintptr_t yasm_arch_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup, |
|
unsigned long regindex); |
|
|
|
/** Print a register. For debugging purposes. |
|
* \param arch architecture |
|
* \param reg register |
|
* \param f file |
|
*/ |
|
void yasm_arch_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f); |
|
|
|
/** Print a segment register. For debugging purposes. |
|
* \param arch architecture |
|
* \param segreg segment register |
|
* \param f file |
|
*/ |
|
void yasm_arch_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f); |
|
|
|
/** Create an effective address from an expression. |
|
* \param arch architecture |
|
* \param e expression (kept, do not delete) |
|
* \return Newly allocated effective address. |
|
*/ |
|
yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e); |
|
|
|
|
|
#ifndef YASM_DOXYGEN |
|
|
|
/* Inline macro implementations for arch functions */ |
|
|
|
#define yasm_arch_name(arch) \ |
|
(((yasm_arch_base *)arch)->module->name) |
|
#define yasm_arch_keyword(arch) \ |
|
(((yasm_arch_base *)arch)->module->keyword) |
|
#define yasm_arch_wordsize(arch) \ |
|
(((yasm_arch_base *)arch)->module->wordsize) |
|
#define yasm_arch_min_insn_len(arch) \ |
|
(((yasm_arch_base *)arch)->module->min_insn_len) |
|
|
|
#define yasm_arch_create(module, machine, parser, error) \ |
|
module->create(machine, parser, error) |
|
|
|
#define yasm_arch_destroy(arch) \ |
|
((yasm_arch_base *)arch)->module->destroy(arch) |
|
#define yasm_arch_get_machine(arch) \ |
|
((yasm_arch_base *)arch)->module->get_machine(arch) |
|
#define yasm_arch_get_address_size(arch) \ |
|
((yasm_arch_base *)arch)->module->get_address_size(arch) |
|
#define yasm_arch_set_var(arch, var, val) \ |
|
((yasm_arch_base *)arch)->module->set_var(arch, var, val) |
|
#define yasm_arch_parse_check_insnprefix(arch, data, id, id_len) \ |
|
((yasm_arch_base *)arch)->module->parse_check_insnprefix(arch, data, id, \ |
|
id_len) |
|
#define yasm_arch_parse_check_regtmod(arch, data, id, id_len) \ |
|
((yasm_arch_base *)arch)->module->parse_check_regtmod(arch, data, id, \ |
|
id_len) |
|
#define yasm_arch_get_fill(arch) \ |
|
((yasm_arch_base *)arch)->module->get_fill(arch) |
|
#define yasm_arch_finalize_insn(arch, bc, prev_bc, data, num_operands, \ |
|
operands, num_prefixes, prefixes, \ |
|
num_segregs, segregs) \ |
|
((yasm_arch_base *)arch)->module->finalize_insn \ |
|
(arch, bc, prev_bc, data, num_operands, operands, num_prefixes, \ |
|
prefixes, num_segregs, segregs) |
|
#define yasm_arch_floatnum_tobytes(arch, flt, buf, destsize, valsize, shift, \ |
|
warn) \ |
|
((yasm_arch_base *)arch)->module->floatnum_tobytes \ |
|
(arch, flt, buf, destsize, valsize, shift, warn) |
|
#define yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, shift, \ |
|
bc, warn) \ |
|
((yasm_arch_base *)arch)->module->intnum_tobytes \ |
|
(arch, intn, buf, destsize, valsize, shift, bc, warn) |
|
#define yasm_arch_get_reg_size(arch, reg) \ |
|
((yasm_arch_base *)arch)->module->get_reg_size(arch, reg) |
|
#define yasm_arch_reggroup_get_reg(arch, regg, regi) \ |
|
((yasm_arch_base *)arch)->module->reggroup_get_reg(arch, regg, regi) |
|
#define yasm_arch_reg_print(arch, reg, f) \ |
|
((yasm_arch_base *)arch)->module->reg_print(arch, reg, f) |
|
#define yasm_arch_segreg_print(arch, segreg, f) \ |
|
((yasm_arch_base *)arch)->module->segreg_print(arch, segreg, f) |
|
#define yasm_arch_ea_create(arch, e) \ |
|
((yasm_arch_base *)arch)->module->ea_create(arch, e) |
|
|
|
#endif |
|
|
|
/** Create an instruction operand from a register. |
|
* \param reg register |
|
* \return Newly allocated operand. |
|
*/ |
|
yasm_insn_operand *yasm_operand_create_reg(uintptr_t reg); |
|
|
|
/** Create an instruction operand from a segment register. |
|
* \param segreg segment register |
|
* \return Newly allocated operand. |
|
*/ |
|
yasm_insn_operand *yasm_operand_create_segreg(uintptr_t segreg); |
|
|
|
/** Create an instruction operand from an effective address. |
|
* \param ea effective address |
|
* \return Newly allocated operand. |
|
*/ |
|
yasm_insn_operand *yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea); |
|
|
|
/** Create an instruction operand from an immediate expression. |
|
* Looks for cases of a single register and creates a register variant of |
|
* #yasm_insn_operand. |
|
* \param val immediate expression |
|
* \return Newly allocated operand. |
|
*/ |
|
yasm_insn_operand *yasm_operand_create_imm(/*@only@*/ yasm_expr *val); |
|
|
|
/** Print an instruction operand. For debugging purposes. |
|
* \param arch architecture |
|
* \param f file |
|
* \param indent_level indentation level |
|
* \param op instruction operand |
|
*/ |
|
void yasm_operand_print(const yasm_insn_operand *op, FILE *f, int indent_level, |
|
yasm_arch *arch); |
|
|
|
/** Create a new list of instruction operands. |
|
* \return Newly allocated list. |
|
*/ |
|
yasm_insn_operands *yasm_ops_create(void); |
|
|
|
/** Destroy a list of instruction operands (created with yasm_ops_create()). |
|
* \param headp list of instruction operands |
|
* \param content if nonzero, deletes content of each operand |
|
*/ |
|
void yasm_ops_destroy(yasm_insn_operands *headp, int content); |
|
|
|
/** Get the first operand in a list of instruction operands. |
|
* \param headp list of instruction operands |
|
* \return First operand in list (NULL if list is empty). |
|
*/ |
|
yasm_insn_operand *yasm_ops_first(yasm_insn_operands *headp); |
|
|
|
/** Get the next operand in a list of instruction operands. |
|
* \param cur previous operand |
|
* \return Next operand in list (NULL if cur was the last operand). |
|
*/ |
|
yasm_insn_operand *yasm_operand_next(yasm_insn_operand *cur); |
|
|
|
#ifdef YASM_LIB_INTERNAL |
|
#define yasm_ops_initialize(headp) STAILQ_INIT(headp) |
|
#define yasm_ops_first(headp) STAILQ_FIRST(headp) |
|
#define yasm_operand_next(cur) STAILQ_NEXT(cur, link) |
|
|
|
/** Delete (free allocated memory for) a list of instruction operands (created |
|
* with yasm_ops_initialize()). |
|
* \param headp list of instruction operands |
|
* \param content if nonzero, deletes content of each operand |
|
*/ |
|
void yasm_ops_delete(yasm_insn_operands *headp, int content); |
|
#endif |
|
|
|
/** Add data value to the end of a list of instruction operands. |
|
* \note Does not make a copy of the operand; so don't pass this function |
|
* static or local variables, and discard the op pointer after calling |
|
* this function. |
|
* \param headp list of instruction operands |
|
* \param op operand (may be NULL) |
|
* \return If operand was actually appended (it wasn't NULL), the operand; |
|
* otherwise NULL. |
|
*/ |
|
/*@null@*/ yasm_insn_operand *yasm_ops_append |
|
(yasm_insn_operands *headp, |
|
/*@returned@*/ /*@null@*/ yasm_insn_operand *op); |
|
|
|
/** Print a list of instruction operands. For debugging purposes. |
|
* \param arch architecture |
|
* \param f file |
|
* \param indent_level indentation level |
|
* \param headp list of instruction operands |
|
*/ |
|
void yasm_ops_print(const yasm_insn_operands *headp, FILE *f, int indent_level, |
|
yasm_arch *arch); |
|
|
|
#endif
|
|
|