mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-07-24 10:25:42 -04:00
{dfv=} is basically a constant (immediate). Treat it as such during parsing, except that if "naked" (not in an expression), it has special matching properties and does not need a terminal comma. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
341 lines
16 KiB
C
341 lines
16 KiB
C
/* ----------------------------------------------------------------------- *
|
|
*
|
|
* Copyright 1996-2024 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.
|
|
*
|
|
* ----------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* opflags.h - operand flags
|
|
*/
|
|
|
|
#ifndef NASM_OPFLAGS_H
|
|
#define NASM_OPFLAGS_H
|
|
|
|
#include "compiler.h"
|
|
#include "tables.h" /* for opflags_t and nasm_reg_flags[] */
|
|
#include "regs.h"
|
|
|
|
/*
|
|
* Here we define the operand types. These are implemented as bit
|
|
* masks, since some are subsets of others; e.g. AX in a MOV
|
|
* instruction is a special operand type, whereas AX in other
|
|
* contexts is just another 16-bit register. (Also, consider CL in
|
|
* shift instructions, DX in OUT, etc.)
|
|
*
|
|
* The basic concept here is that
|
|
* (class & ~operand) == 0
|
|
*
|
|
* if and only if "operand" belongs to class type "class".
|
|
*/
|
|
|
|
#define OP_GENMASK(bits, shift) (((UINT64_C(1) << (bits)) - 1) << (shift))
|
|
#define OP_GENBIT(bit, shift) (UINT64_C(1) << ((shift) + (bit)))
|
|
|
|
/*
|
|
* Type of operand: memory reference, register, etc.
|
|
*
|
|
* Bits: 0 - 3
|
|
*/
|
|
#define OPTYPE_SHIFT (0)
|
|
#define OPTYPE_BITS (4)
|
|
#define OPTYPE_MASK OP_GENMASK(OPTYPE_BITS, OPTYPE_SHIFT)
|
|
#define GEN_OPTYPE(bit) OP_GENBIT(bit, OPTYPE_SHIFT)
|
|
|
|
/*
|
|
* Modifiers.
|
|
*
|
|
* Bits: 4 - 6
|
|
*/
|
|
#define MODIFIER_SHIFT (4)
|
|
#define MODIFIER_BITS (3)
|
|
#define MODIFIER_MASK OP_GENMASK(MODIFIER_BITS, MODIFIER_SHIFT)
|
|
#define GEN_MODIFIER(bit) OP_GENBIT(bit, MODIFIER_SHIFT)
|
|
|
|
/*
|
|
* Register classes.
|
|
*
|
|
* Bits: 7 - 17
|
|
*/
|
|
#define REG_CLASS_SHIFT (7)
|
|
#define REG_CLASS_BITS (11)
|
|
#define REG_CLASS_MASK OP_GENMASK(REG_CLASS_BITS, REG_CLASS_SHIFT)
|
|
#define GEN_REG_CLASS(bit) OP_GENBIT(bit, REG_CLASS_SHIFT)
|
|
|
|
/*
|
|
* Subclasses. Depends on type of operand.
|
|
*
|
|
* Bits: 18 - 25
|
|
*/
|
|
#define SUBCLASS_SHIFT (18)
|
|
#define SUBCLASS_BITS (8)
|
|
#define SUBCLASS_MASK OP_GENMASK(SUBCLASS_BITS, SUBCLASS_SHIFT)
|
|
#define GEN_SUBCLASS(bit) OP_GENBIT(bit, SUBCLASS_SHIFT)
|
|
|
|
/*
|
|
* Special flags. Context dependent.
|
|
*
|
|
* Bits: 26 - 32
|
|
*/
|
|
#define SPECIAL_SHIFT (26)
|
|
#define SPECIAL_BITS (7)
|
|
#define SPECIAL_MASK OP_GENMASK(SPECIAL_BITS, SPECIAL_SHIFT)
|
|
#define GEN_SPECIAL(bit) OP_GENBIT(bit, SPECIAL_SHIFT)
|
|
|
|
/*
|
|
* Sizes of the operands and attributes.
|
|
*
|
|
* Bits: 33 - 43
|
|
*/
|
|
#define SIZE_SHIFT (33)
|
|
#define SIZE_BITS (11)
|
|
#define SIZE_MASK OP_GENMASK(SIZE_BITS, SIZE_SHIFT)
|
|
#define GEN_SIZE(bit) OP_GENBIT(bit, SIZE_SHIFT)
|
|
|
|
/*
|
|
* Register set count
|
|
*
|
|
* Bits: 44 - 48
|
|
*/
|
|
#define REGSET_SHIFT (44)
|
|
#define REGSET_BITS (5)
|
|
#define REGSET_MASK OP_GENMASK(REGSET_BITS, REGSET_SHIFT)
|
|
#define GEN_REGSET(bit) OP_GENBIT(bit, REGSET_SHIFT)
|
|
|
|
/*
|
|
* Bits distribution (counted from 0)
|
|
*
|
|
* 6 5 4 3 2 1
|
|
* 3210987654321098765432109876543210987654321098765432109876543210
|
|
* |
|
|
* | dword bound
|
|
*
|
|
* ............................................................1111 optypes
|
|
* .........................................................111.... modifiers
|
|
* ..............................................11111111111....... register classes
|
|
* ......................................11111111.................. subclasses
|
|
* ...............................1111111.......................... specials
|
|
* ....................11111111111................................. sizes
|
|
* ...............11111............................................ regset count
|
|
*/
|
|
|
|
#define REGISTER GEN_OPTYPE(0) /* register number in 'basereg' */
|
|
#define IMMEDIATE GEN_OPTYPE(1)
|
|
#define REGMEM GEN_OPTYPE(2) /* for r/m, ie EA, operands */
|
|
#define MEMORY (GEN_OPTYPE(3) | REGMEM)
|
|
|
|
#define BITS8 GEN_SIZE(0) /* 8 bits (BYTE) */
|
|
#define BITS16 GEN_SIZE(1) /* 16 bits (WORD) */
|
|
#define BITS32 GEN_SIZE(2) /* 32 bits (DWORD) */
|
|
#define BITS64 GEN_SIZE(3) /* 64 bits (QWORD), x64 and FPU only */
|
|
#define BITS80 GEN_SIZE(4) /* 80 bits (TWORD), FPU only */
|
|
#define BITS128 GEN_SIZE(5) /* 128 bits (OWORD) */
|
|
#define BITS256 GEN_SIZE(6) /* 256 bits (YWORD) */
|
|
#define BITS512 GEN_SIZE(7) /* 512 bits (ZWORD) */
|
|
#define FAR GEN_SIZE(8) /* grotty: this means 16:16 or 16:32, like in CALL/JMP */
|
|
#define NEAR GEN_SIZE(9)
|
|
#define SHORT GEN_SIZE(10) /* and this means what it says :) */
|
|
|
|
#define TO GEN_MODIFIER(0) /* reverse effect in FADD, FSUB &c */
|
|
#define COLON GEN_MODIFIER(1) /* operand is followed by a colon */
|
|
#define STRICT GEN_MODIFIER(2) /* do not optimize this operand */
|
|
|
|
#define REG_CLASS_CDT GEN_REG_CLASS(0)
|
|
#define REG_CLASS_GPR GEN_REG_CLASS(1)
|
|
#define REG_CLASS_SREG GEN_REG_CLASS(2)
|
|
#define REG_CLASS_FPUREG GEN_REG_CLASS(3)
|
|
#define REG_CLASS_RM_MMX GEN_REG_CLASS(4)
|
|
#define REG_CLASS_RM_XMM GEN_REG_CLASS(5)
|
|
#define REG_CLASS_RM_YMM GEN_REG_CLASS(6)
|
|
#define REG_CLASS_RM_ZMM GEN_REG_CLASS(7)
|
|
#define REG_CLASS_OPMASK GEN_REG_CLASS(8)
|
|
#define REG_CLASS_BND GEN_REG_CLASS(9)
|
|
#define REG_CLASS_RM_TMM GEN_REG_CLASS(10)
|
|
|
|
static inline bool is_class(opflags_t class, opflags_t op)
|
|
{
|
|
return !(class & ~op);
|
|
}
|
|
|
|
static inline bool is_reg_class(opflags_t class, opflags_t reg)
|
|
{
|
|
if (reg >= EXPR_REG_START && reg <= EXPR_REG_END)
|
|
return is_class(class, nasm_reg_flags[reg]);
|
|
return false;
|
|
}
|
|
|
|
#define IS_SREG(reg) is_reg_class(REG_SREG, (reg))
|
|
#define IS_FSGS(reg) is_reg_class(REG_FSGS, (reg))
|
|
|
|
/*
|
|
* These are used across the RM classes so cannot conflict with neither EA
|
|
* nor REG subtypes! x86/insns.pl automatically adds RN_FLAGS(x) to the
|
|
* defintion of each register type.
|
|
*/
|
|
#define RN_L16 GEN_SUBCLASS(5) /* Register number 0-15 */
|
|
#define RN_ZERO (GEN_SUBCLASS(6) | RN_L16) /* Register number 0 */
|
|
#define RN_NZERO GEN_SUBCLASS(7) /* Register number 1+ */
|
|
#define RN_1_15 (RN_NZERO | RN_L16) /* Register number 1-15 */
|
|
|
|
#define RN_FLAGS(n) ((n) == 0 ? RN_ZERO : \
|
|
(n) < 16 ? RN_1_15 : \
|
|
0)
|
|
|
|
#define RM_L16 (RN_L16 | REGMEM)
|
|
#define RM_ZERO (RN_ZERO | REGMEM)
|
|
#define RM_NZERO (RN_NZERO | REGMEM)
|
|
#define RM_1_15 (RM_1_15 | REGMEM)
|
|
|
|
/* Register classes */
|
|
|
|
#define REG_L16 (RN_L16 | REGISTER)
|
|
#define REG_ZERO (RN_ZERO | REGISTER)
|
|
#define REG_NZERO (RN_NZERO | REGISTER)
|
|
#define REG_1_15 (RN_1_15 | REGISTER)
|
|
|
|
#define REG_SMASK SUBCLASS_MASK
|
|
|
|
#define REG_EA ( REGMEM | REGISTER ) /* 'normal' reg, qualifies as EA */
|
|
#define RM_GPR (REG_CLASS_GPR | REGMEM ) /* integer operand */
|
|
#define REG_GPR (REG_CLASS_GPR | REG_EA ) /* integer register */
|
|
#define FPUREG (REG_CLASS_FPUREG | REGISTER ) /* fp stack registers */
|
|
#define FPU0 (REG_CLASS_FPUREG | REG_ZERO ) /* fp stack register zero */
|
|
#define RM_MMX (REG_CLASS_RM_MMX | REGMEM ) /* MMX operand */
|
|
#define MMXREG (REG_CLASS_RM_MMX | REG_EA ) /* MMX register */
|
|
#define RM_XMM (REG_CLASS_RM_XMM | REGMEM ) /* XMM operand */
|
|
#define XMMREG (REG_CLASS_RM_XMM | REG_EA ) /* XMM register */
|
|
#define RM_XMM_L16 (REG_CLASS_RM_XMM | REGMEM | RN_L16 ) /* XMM operand reg 0-15 */
|
|
#define XMM_L16 (REG_CLASS_RM_XMM | REG_EA | RN_L16 ) /* XMM register 0-15 */
|
|
#define XMM0 (REG_CLASS_RM_XMM | REGMEM | REG_ZERO ) /* XMM register 0 */
|
|
#define RM_YMM (REG_CLASS_RM_YMM | REGMEM ) /* YMM operand */
|
|
#define YMMREG (REG_CLASS_RM_YMM | REG_EA ) /* YMM register */
|
|
#define RM_YMM_L16 (REG_CLASS_RM_YMM | REGMEM | RN_L16 ) /* YMM operand reg 0-15 */
|
|
#define YMM_L16 (REG_CLASS_RM_YMM | REG_EA | RN_L16 ) /* YMM register 0-15 */
|
|
#define YMM0 (REG_CLASS_RM_YMM | REGMEM | REG_ZERO ) /* YMM register 0 */
|
|
#define RM_ZMM (REG_CLASS_RM_ZMM | REGMEM ) /* ZMM operand */
|
|
#define ZMMREG (REG_CLASS_RM_ZMM | REG_EA ) /* ZMM register */
|
|
#define RM_ZMM_L16 (REG_CLASS_RM_ZMM | REGMEM | RN_L16 ) /* ZMM operand reg 0-15 */
|
|
#define ZMM_L16 (REG_CLASS_RM_ZMM | REG_EA | RN_L16 ) /* ZMM register 0-15 */
|
|
#define ZMM0 (REG_CLASS_RM_ZMM | REGMEM | REG_ZERO ) /* ZMM register 0 */
|
|
#define RM_OPMASK (REG_CLASS_OPMASK | REGMEM ) /* Opmask operand */
|
|
#define OPMASKREG (REG_CLASS_OPMASK | REG_EA ) /* Opmask register */
|
|
#define OPMASK0 (REG_CLASS_OPMASK | REG_EA ) /* Opmask register zero (k0) */
|
|
#define RM_K RM_OPMASK
|
|
#define KREG OPMASKREG
|
|
#define RM_BND (REG_CLASS_BND | REGMEM ) /* Bounds operand */
|
|
#define BNDREG (REG_CLASS_BND | REG_EA ) /* Bounds register */
|
|
#define TMMREG (REG_CLASS_RM_TMM | REG_EA ) /* TMM (AMX) register */
|
|
|
|
#define REG_CDT (REG_CLASS_CDT | REGISTER) /* CRn, DRn and TRn */
|
|
#define REG_CREG (GEN_SUBCLASS(0) | REG_CDT ) /* CRn */
|
|
#define REG_DREG (GEN_SUBCLASS(1) | REG_CDT ) /* DRn */
|
|
#define REG_TREG (GEN_SUBCLASS(2) | REG_CDT ) /* TRn */
|
|
|
|
#define REG_SREG (REG_CLASS_SREG | REGISTER | BITS16) /* segment register */
|
|
|
|
/* Segment registers */
|
|
#define REG_ES (GEN_SUBCLASS(0) | GEN_SUBCLASS(2) | REG_SREG) /* ES */
|
|
#define REG_CS (GEN_SUBCLASS(1) | GEN_SUBCLASS(2) | REG_SREG) /* CS */
|
|
#define REG_SS (GEN_SUBCLASS(0) | GEN_SUBCLASS(3) | REG_SREG) /* SS */
|
|
#define REG_DS (GEN_SUBCLASS(1) | GEN_SUBCLASS(3) | REG_SREG) /* DS */
|
|
#define REG_FS (GEN_SUBCLASS(0) | GEN_SUBCLASS(4) | REG_SREG) /* FS */
|
|
#define REG_GS (GEN_SUBCLASS(1) | GEN_SUBCLASS(4) | REG_SREG) /* GS */
|
|
#define REG_FSGS ( GEN_SUBCLASS(4) | REG_SREG) /* FS or GS */
|
|
#define REG_SEG6 (GEN_SUBCLASS(0) | GEN_SUBCLASS(5) | REG_SREG)
|
|
#define REG_SEG7 (GEN_SUBCLASS(1) | GEN_SUBCLASS(5) | REG_SREG)
|
|
#define REG_SEG67 ( GEN_SUBCLASS(5) | REG_SREG)
|
|
|
|
/* GPRs */
|
|
|
|
#define REG8 (REG_GPR | BITS8 )
|
|
#define REG16 (REG_GPR | BITS16)
|
|
#define REG32 (REG_GPR | BITS32)
|
|
#define REG64 (REG_GPR | BITS64)
|
|
|
|
/* accumulator: AL, AX, EAX, RAX */
|
|
#define REG_ACCUM (REG_GPR | REG_ZERO)
|
|
#define REG_AL (REG_ACCUM | BITS8 )
|
|
#define REG_AX (REG_ACCUM | BITS16)
|
|
#define REG_EAX (REG_ACCUM | BITS32)
|
|
#define REG_RAX (REG_ACCUM | BITS64)
|
|
|
|
/* counter: CL, CX, ECX, RDX */
|
|
#define REG_COUNT (REG_GPR | REG_1_15 | GEN_SUBCLASS(0))
|
|
#define REG_CL (REG_COUNT | BITS8 )
|
|
#define REG_CX (REG_COUNT | BITS16)
|
|
#define REG_ECX (REG_COUNT | BITS32)
|
|
#define REG_RCX (REG_COUNT | BITS64)
|
|
|
|
/* data: DL, DX, EDX, RDX */
|
|
#define REG_DATA (REG_GPR | REG_1_15 | GEN_SUBCLASS(1))
|
|
#define REG_DL (REG_DATA | BITS8 )
|
|
#define REG_DX (REG_DATA | BITS16)
|
|
#define REG_EDX (REG_DATA | BITS32)
|
|
#define REG_RDX (REG_DATA | BITS64)
|
|
|
|
/* high 8-bit regs: AH, CH, DH, BH */
|
|
#define REG_HIGH (REG8 | REG_1_15 | GEN_SUBCLASS(2))
|
|
|
|
/* Non-accumulator registers */
|
|
#define REG_NA (REG_GPR | REG_NZERO)
|
|
#define REG8NA (REG_NA | BITS8 )
|
|
#define REG16NA (REG_NA | BITS16)
|
|
#define REG32NA (REG_NA | BITS32)
|
|
#define REG64NA (REG_NA | BITS64)
|
|
|
|
/* special types of EAs */
|
|
#define MEM_OFFS (GEN_SUBCLASS(0) | MEMORY) /* simple [address] offset - absolute! */
|
|
#define IP_REL (GEN_SUBCLASS(1) | MEMORY) /* IP-relative offset */
|
|
#define XMEM (GEN_SUBCLASS(2) | MEMORY) /* 128-bit vector SIB */
|
|
#define YMEM (GEN_SUBCLASS(3) | MEMORY) /* 256-bit vector SIB */
|
|
#define ZMEM (GEN_SUBCLASS(4) | MEMORY) /* 512-bit vector SIB */
|
|
|
|
/*
|
|
* operand bits to match an instruction carrying any type of memory r/m operand
|
|
*/
|
|
#define MEMORY_ANY (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM | RM_ZMM | \
|
|
RM_L16 | RM_ZERO | RM_NZERO | RM_OPMASK | RM_BND)
|
|
|
|
/* special immediate values */
|
|
#define UNITY (GEN_SUBCLASS(0) | IMMEDIATE) /* operand equals 1 */
|
|
#define SBYTEWORD (GEN_SUBCLASS(1) | IMMEDIATE) /* operand is in the range -128..127 mod 2^16 */
|
|
#define SBYTEDWORD (GEN_SUBCLASS(2) | IMMEDIATE) /* operand is in the range -128..127 mod 2^32 */
|
|
#define SDWORD (GEN_SUBCLASS(3) | IMMEDIATE) /* operand is in the range -0x80000000..0x7FFFFFFF */
|
|
#define UDWORD (GEN_SUBCLASS(4) | IMMEDIATE) /* operand is in the range 0..0xFFFFFFFF */
|
|
#define IMM_NORMAL (GEN_SUBCLASS(5) | IMMEDIATE) /* operand is NOT a brcconst */
|
|
|
|
/* Register set sizes */
|
|
#define RS2 GEN_REGSET(0)
|
|
#define RS4 GEN_REGSET(1)
|
|
#define RS8 GEN_REGSET(2)
|
|
#define RS16 GEN_REGSET(3)
|
|
#define RS32 GEN_REGSET(4)
|
|
|
|
#endif /* NASM_OPFLAGS_H */
|