/* ----------------------------------------------------------------------- * * * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * * 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 COPYRIGHT HOLDERS AND * 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 COPYRIGHT OWNER OR * 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. * * ----------------------------------------------------------------------- */ /* * nasm.h main header file for the Netwide Assembler: inter-module interface */ #ifndef NASM_NASM_H #define NASM_NASM_H #include "compiler.h" #include <time.h> #include "nasmlib.h" #include "nctype.h" #include "strlist.h" #include "preproc.h" #include "insnsi.h" /* For enum opcode */ #include "directiv.h" /* For enum directive */ #include "labels.h" /* For enum mangle_index, enum label_type */ #include "opflags.h" #include "regs.h" #include "srcfile.h" #include "error.h" /* Program name for error messages etc. */ extern const char *_progname; /* Time stamp for the official start of compilation */ struct compile_time { … }; extern struct compile_time official_compile_time; #define NO_SEG … #define SEG_ABS … #define IDLEN_MAX … #define DECOLEN_MAX … /* * Name pollution problems: <time.h> on Digital UNIX pulls in some * strange hardware header file which sees fit to define R_SP. We * undefine it here so as not to break the enum below. */ #ifdef R_SP #undef R_SP #endif /* * We must declare the existence of this structure type up here, * since we have to reference it before we define it... */ struct ofmt; /* * Values for the `type' parameter to an output function. */ enum out_type { … }; enum out_sign { … }; /* * The data we send down to the backend. * XXX: We still want to push down the base address symbol if * available, and replace the segment numbers with a structure. */ struct out_data { … }; /* * And a label-definition function. The boolean parameter * `is_norm' states whether the label is a `normal' label (which * should affect the local-label system), or something odder like * an EQU or a segment-base symbol, which shouldn't. */ ldfunc; /* * Token types returned by the scanner, in addition to ordinary * ASCII character values, and zero for end-of-string. */ enum token_type { … }; enum floatize { … }; /* Must match the list in string_transform(), in strfunc.c */ enum strfunc { … }; enum ifunc { … }; size_t string_transform(char *, size_t, char **, enum strfunc); /* * The expression evaluator must be passed a scanner function; a * standard scanner is provided as part of nasmlib.c. The * preprocessor will use a different one. Scanners, and the * token-value structures they return, look like this. * * The return value from the scanner is always a copy of the * `t_type' field in the structure. */ struct tokenval { … }; scanner; struct location { … }; extern struct location location; /* * Expression-evaluator datatype. Expressions, within the * evaluator, are stored as an array of these beasts, terminated by * a record with type==0. Mostly, it's a vector type: each type * denotes some kind of a component, and the value denotes the * multiple of that component present in the expression. The * exception is the WRT type, whose `value' field denotes the * segment to which the expression is relative. These segments will * be segment-base types, i.e. either odd segment values or SEG_ABS * types. So it is still valid to assume that anything with a * `value' field of zero is insignificant. */ expr; /* * Library routines to manipulate expression data types. */ bool is_reloc(const expr *vect); bool is_simple(const expr *vect); bool is_really_simple(const expr *vect); bool is_unknown(const expr *vect); bool is_just_unknown(const expr *vect); int64_t reloc_value(const expr *vect); int32_t reloc_seg(const expr *vect); int32_t reloc_wrt(const expr *vect); bool is_self_relative(const expr *vect); void dump_expr(const expr *vect); /* * The evaluator can also return hints about which of two registers * used in an expression should be the base register. See also the * `operand' structure. */ struct eval_hints { … }; /* * The actual expression evaluator function looks like this. When * called, it expects the first token of its expression to already * be in `*tv'; if it is not, set tv->t_type to TOKEN_INVALID and * it will start by calling the scanner. * * If a forward reference happens during evaluation, the evaluator * must set `*fwref' to true if `fwref' is non-NULL. * * `critical' is non-zero if the expression may not contain forward * references. The evaluator will report its own error if this * occurs; if `critical' is 1, the error will be "symbol not * defined before use", whereas if `critical' is 2, the error will * be "symbol undefined". * * If `critical' has bit 8 set (in addition to its main value: 0x101 * and 0x102 correspond to 1 and 2) then an extended expression * syntax is recognised, in which relational operators such as =, < * and >= are accepted, as well as low-precedence logical operators * &&, ^^ and ||. * * If `hints' is non-NULL, it gets filled in with some hints as to * the base register in complex effective addresses. */ #define CRITICAL … evalfunc; /* * Special values for expr->type. * These come after EXPR_REG_END as defined in regs.h. * Expr types : 0 ~ EXPR_REG_END, EXPR_UNKNOWN, EXPR_...., EXPR_RDSAE, * EXPR_SEGBASE ~ EXPR_SEGBASE + SEG_ABS, ... */ #define EXPR_UNKNOWN … #define EXPR_SIMPLE … #define EXPR_WRT … #define EXPR_RDSAE … #define EXPR_SEGBASE … /* * preprocessors ought to look like this: */ enum preproc_mode { … }; struct preproc_ops { … }; extern const struct preproc_ops nasmpp; extern const struct preproc_ops preproc_nop; /* List of dependency files */ extern struct strlist *depend_list; /* TASM mode changes some properties */ extern bool tasm_compatible_mode; /* * inline function to skip past an identifier; returns the first character past * the identifier if valid, otherwise NULL. */ static inline char *nasm_skip_identifier(const char *str) { … } /* * Data-type flags that get passed to listing-file routines. */ enum { … }; /* * ----------------------------------------------------------- * Format of the `insn' structure returned from `parser.c' and * passed into `assemble.c' * ----------------------------------------------------------- */ /* Verify value to be a valid register */ static inline bool is_register(int reg) { … } enum ccode { … }; /* * token flags */ #define TFLAG_BRC … #define TFLAG_BRC_OPT … #define TFLAG_BRC_ANY … #define TFLAG_BRDCAST … #define TFLAG_WARN … #define TFLAG_DUP … static inline uint8_t get_cond_opcode(enum ccode c) { … } /* * REX flags */ #define REX_MASK … #define REX_B … #define REX_X … #define REX_R … #define REX_W … #define REX_L … #define REX_P … #define REX_H … #define REX_V … #define REX_NH … #define REX_EV … /* * EVEX bit field */ #define EVEX_P0MM … #define EVEX_P0RP … #define EVEX_P0X … #define EVEX_P1PP … #define EVEX_P1VVVV … #define EVEX_P1W … #define EVEX_P2AAA … #define EVEX_P2VP … #define EVEX_P2B … #define EVEX_P2LL … #define EVEX_P2RC … #define EVEX_P2Z … /* * REX_V "classes" (prefixes which behave like VEX) */ enum vex_class { … }; /* * Note that because segment registers may be used as instruction * prefixes, we must ensure the enumerations for prefixes and * register names do not overlap. */ enum prefixes { … }; enum ea_flags { … }; enum eval_hint { … }; operand; #define OPFLAG_FORWARD … #define OPFLAG_EXTERN … #define OPFLAG_UNKNOWN … #define OPFLAG_RELATIVE … enum extop_type { … }; extop; enum ea_type { … }; /* * Prefix positions: each type of prefix goes in a specific slot. * This affects the final ordering of the assembled output, which * shouldn't matter to the processor, but if you have stylistic * preferences, you can change this. REX prefixes are handled * differently for the time being. * * LOCK and REP used to be one slot; this is no longer the case since * the introduction of HLE. */ enum prefix_pos { … }; /* * Tuple types that are used when determining Disp8*N eligibility * The order must match with a hash %tuple_codes in insns.pl */ enum ttypes { … }; /* EVEX.L'L : Vector length on vector insns */ enum vectlens { … }; /* If you need to change this, also change it in insns.pl */ #define MAX_OPERANDS … insn; /* Instruction flags type: IF_* flags are defined in insns.h */ iflags_t; /* * What to return from a directive- or pragma-handling function. * Currently DIRR_OK and DIRR_ERROR are treated the same way; * in both cases the backend is expected to produce the appropriate * error message on its own. * * DIRR_BADPARAM causes a generic error message to be printed. Note * that it is an error, not a warning, even in the case of pragmas; * don't use it where forward compatiblity would be compromised * (instead consider adding a DIRR_WARNPARAM.) */ enum directive_result { … }; /* * A pragma facility: this structure is used to request passing a * parsed pragma directive for a specific facility. If the handler is * NULL then this pragma facility is recognized but ignored; pragma * processing stops at that point. * * Note that the handler is passed a pointer to the facility structure * as part of the struct pragma. */ struct pragma; pragma_handler; struct pragma_facility { … }; /* * This structure defines how a pragma directive is passed to a * facility. This structure may be augmented in the future. * * Any facility MAY, but is not required to, add its operations * keywords or a subset thereof into asm/directiv.dat, in which case * the "opcode" field will be set to the corresponding D_ constant * from directiv.h; otherwise it will be D_unknown. */ struct pragma { … }; /* * These are semi-arbitrary limits to keep the assembler from going * into a black hole on certain kinds of bugs. They can be overridden * by command-line options or %pragma. */ enum nasm_limit { … }; #define LIMIT_MAX … extern int64_t nasm_limit[LIMIT_MAX+1]; extern enum directive_result nasm_set_limit(const char *, const char *); /* * The data structure defining an output format driver, and the * interfaces to the functions therein. */ struct ofmt { … }; /* * Output format driver alias */ struct ofmt_alias { … }; extern const struct ofmt *ofmt; extern FILE *ofile; /* * ------------------------------------------------------------ * The data structure defining a debug format driver, and the * interfaces to the functions therein. * ------------------------------------------------------------ */ struct dfmt { … }; extern const struct dfmt *dfmt; /* * The type definition macros * for debugging * * low 3 bits: reserved * next 5 bits: type * next 24 bits: number of elements for arrays (0 for labels) */ #define TY_UNKNOWN … #define TY_LABEL … #define TY_BYTE … #define TY_WORD … #define TY_DWORD … #define TY_FLOAT … #define TY_QWORD … #define TY_TBYTE … #define TY_OWORD … #define TY_YWORD … #define TY_ZWORD … #define TY_COMMON … #define TY_SEG … #define TY_EXTERN … #define TY_EQU … #define TYM_TYPE(x) … #define TYM_ELEMENTS(x) … #define TYS_ELEMENTS(x) … /* Sizes corresponding to various tokens */ enum byte_sizes { … }; enum special_tokens { … }; enum decorator_tokens { … }; /* * AVX512 Decorator (decoflags_t) bits distribution (counted from 0) * 3 2 1 * 10987654321098765432109876543210 * | * | word boundary * ............................1111 opmask * ...........................1.... zeroing / merging * ..........................1..... broadcast * .........................1...... static rounding * ........................1....... SAE * ......................11........ broadcast element size * ....................11.......... number of broadcast elements */ #define OP_GENVAL(val, bits, shift) … /* * Opmask register number * identical to EVEX.aaa * * Bits: 0 - 3 */ #define OPMASK_SHIFT … #define OPMASK_BITS … #define OPMASK_MASK … #define GEN_OPMASK(bit) … #define VAL_OPMASK(val) … /* * zeroing / merging control available * matching to EVEX.z * * Bits: 4 */ #define Z_SHIFT … #define Z_BITS … #define Z_MASK … #define GEN_Z(bit) … /* * broadcast - Whether this operand can be broadcasted * * Bits: 5 */ #define BRDCAST_SHIFT … #define BRDCAST_BITS … #define BRDCAST_MASK … #define GEN_BRDCAST(bit) … /* * Whether this instruction can have a static rounding mode. * It goes with the last simd operand because the static rounding mode * decorator is located between the last simd operand and imm8 (if any). * * Bits: 6 */ #define STATICRND_SHIFT … #define STATICRND_BITS … #define STATICRND_MASK … #define GEN_STATICRND(bit) … /* * SAE(Suppress all exception) available * * Bits: 7 */ #define SAE_SHIFT … #define SAE_BITS … #define SAE_MASK … #define GEN_SAE(bit) … /* * Broadcasting element size. * * Bits: 8 - 9 */ #define BRSIZE_SHIFT … #define BRSIZE_BITS … #define BRSIZE_MASK … #define GEN_BRSIZE(bit) … #define BR_BITS32 … #define BR_BITS64 … /* * Number of broadcasting elements * * Bits: 10 - 11 */ #define BRNUM_SHIFT … #define BRNUM_BITS … #define BRNUM_MASK … #define VAL_BRNUM(val) … #define BR_1TO2 … #define BR_1TO4 … #define BR_1TO8 … #define BR_1TO16 … #define MASK … #define Z … #define B32 … #define B64 … #define ER … #define SAE … /* * Global modes */ /* * flag to disable optimizations selectively * this is useful to turn-off certain optimizations */ enum optimization_disable_flag { … }; struct optimization { … }; /* * Various types of compiler passes we may execute. * If these are changed, you need to also change _pass_types[] * in asm/nasm.c. */ enum pass_type { … }; extern const char * const _pass_types[]; extern enum pass_type _pass_type; static inline enum pass_type pass_type(void) { … } static inline const char *pass_type_name(void) { … } /* True during initialization, no code read yet */ static inline bool not_started(void) { … } /* True for the initial pass and setup (old "pass2 < 2") */ static inline bool pass_first(void) { … } /* At this point we better have stable definitions */ static inline bool pass_stable(void) { … } /* True for the code generation pass only, (old "pass1 >= 2") */ static inline bool pass_final(void) { … } /* True for code generation *or* preprocess-only mode */ static inline bool pass_final_or_preproc(void) { … } /* * The actual pass number. 0 is used during initialization, the very * first pass is 1, and then it is simply increasing numbers until we are * done. */ extern int64_t _passn; /* Actual pass number */ static inline int64_t pass_count(void) { … } extern struct optimization optimizing; extern int globalbits; /* 16, 32 or 64-bit mode */ extern int globalrel; /* default to relative addressing? */ extern int globalbnd; /* default to using bnd prefix? */ extern const char *inname; /* primary input filename */ extern const char *outname; /* output filename */ /* * Switch to a different segment and return the current offset */ int64_t switch_segment(int32_t segment); #endif /* NASM_NASM_H */