diff options
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | nasm.h | 108 | ||||
-rw-r--r-- | opflags.h | 21 | ||||
-rw-r--r-- | parser.c | 94 | ||||
-rw-r--r-- | regs.dat | 15 | ||||
-rwxr-xr-x | regs.pl | 2 | ||||
-rw-r--r-- | stdscan.c | 94 | ||||
-rw-r--r-- | tables.h | 3 | ||||
-rw-r--r-- | tokens.dat | 28 | ||||
-rwxr-xr-x | tokhash.pl | 17 |
10 files changed, 358 insertions, 28 deletions
@@ -869,6 +869,7 @@ static expr *expr6(int critical) case TOKEN_INSN: /* Opcodes that occur here are really labels */ case TOKEN_HERE: case TOKEN_BASE: + case TOKEN_DECORATOR: begintemp(); switch (i) { case TOKEN_NUM: @@ -938,6 +939,9 @@ static expr *expr6(int critical) if (label_seg != NO_SEG) addtotemp(EXPR_SEGBASE + label_seg, 1L); break; + case TOKEN_DECORATOR: + addtotemp(EXPR_RDSAE, tokval->t_integer); + break; } i = scan(scpriv, tokval); return finishtemp(); @@ -226,6 +226,8 @@ enum token_type { /* token types, other than chars */ TOKEN_FLOATIZE, /* __floatX__ */ TOKEN_STRFUNC, /* __utf16*__, __utf32*__ */ TOKEN_IFUNC, /* __ilog2*__ */ + TOKEN_DECORATOR, /* decorators such as {...} */ + TOKEN_OPMASK, /* translated token for opmask registers */ }; enum floatize { @@ -272,6 +274,7 @@ struct tokenval { int64_t t_integer; int64_t t_inttwo; enum token_type t_type; + int8_t t_flag; }; typedef int (*scanner)(void *private_data, struct tokenval *tv); @@ -352,11 +355,14 @@ typedef expr *(*evalfunc)(scanner sc, void *scprivate, /* * 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 (EXPR_REG_END+1) /* forward references */ #define EXPR_SIMPLE (EXPR_REG_END+2) #define EXPR_WRT (EXPR_REG_END+3) -#define EXPR_SEGBASE (EXPR_REG_END+4) +#define EXPR_RDSAE (EXPR_REG_END+4) +#define EXPR_SEGBASE (EXPR_REG_END+5) /* * Linked list of strings @@ -466,6 +472,14 @@ enum ccode { /* condition code names */ C_none = -1 }; +/* + * token flags + */ +#define TFLAG_BRC (1 << 0) /* valid only with braces. {1to8}, {rd-sae}, ...*/ +#define TFLAG_BRC_OPT (1 << 1) /* may or may not have braces. opmasks {k1} */ +#define TFLAG_BRC_ANY (TFLAG_BRC | TFLAG_BRC_OPT) +#define TFLAG_BRDCAST (1 << 2) /* broadcasting decorator */ + static inline uint8_t get_cond_opcode(enum ccode c) { static const uint8_t ccode_opcodes[] = { @@ -563,6 +577,7 @@ typedef struct operand { /* operand to an instruction */ int32_t wrt; /* segment base it's relative to */ int eaflags; /* special EA flags */ int opflags; /* see OPFLAG_* defines below */ + decoflags_t decoflags; /* decorator flags such as {...} */ } operand; #define OPFLAG_FORWARD 1 /* operand is a forward reference */ @@ -627,6 +642,7 @@ typedef struct insn { /* an instruction itself */ int vexreg; /* Register encoded in VEX prefix */ int vex_cm; /* Class and M field for VEX prefix */ int vex_wlp; /* W, P and L information for VEX prefix */ + int evex_rm; /* static rounding mode for AVX3 (EVEX) */ } insn; enum geninfo { GI_SWITCH }; @@ -951,6 +967,96 @@ enum special_tokens { SPECIAL_ENUM_LIMIT }; +enum decorator_tokens { + DECORATOR_ENUM_START = SPECIAL_ENUM_LIMIT, + BRC_1TO8 = DECORATOR_ENUM_START, + BRC_1TO16, + BRC_RN, + BRC_RU, + BRC_RD, + BRC_RZ, + BRC_SAE, + BRC_Z, + DECORATOR_ENUM_LIMIT +}; + +/* + * 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 + */ + +/* + * Opmask register number + * identical to EVEX.aaa + * + * Bits: 0 - 3 + */ +#define OPMASK_SHIFT (0) +#define OPMASK_BITS (4) +#define OPMASK_MASK OP_GENMASK(OPMASK_BITS, OPMASK_SHIFT) +#define GEN_OPMASK(bit) OP_GENBIT(bit, OPMASK_SHIFT) +#define VAL_OPMASK(val) OP_GENVAL(val, OPMASK_BITS, OPMASK_SHIFT) + +/* + * zeroing / merging control available + * matching to EVEX.z + * + * Bits: 4 + */ +#define Z_SHIFT (4) +#define Z_BITS (1) +#define Z_MASK OP_GENMASK(Z_BITS, Z_SHIFT) +#define GEN_Z(bit) OP_GENBIT(bit, Z_SHIFT) +#define VAL_Z(val) OP_GENVAL(val, Z_BITS, Z_SHIFT) + +/* + * broadcast - Whether this operand can be broadcasted + * + * Bits: 5 + */ +#define BRDCAST_SHIFT (5) +#define BRDCAST_BITS (1) +#define BRDCAST_MASK OP_GENMASK(BRDCAST_BITS, BRDCAST_SHIFT) +#define GEN_BRDCAST(bit) OP_GENBIT(bit, BRDCAST_SHIFT) +#define VAL_BRDCAST(val) OP_GENVAL(val, BRDCAST_BITS, BRDCAST_SHIFT) + +/* + * 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 (6) +#define STATICRND_BITS (1) +#define STATICRND_MASK OP_GENMASK(STATICRND_BITS, STATICRND_SHIFT) +#define GEN_STATICRND(bit) OP_GENBIT(bit, STATICRND_SHIFT) + +/* + * SAE(Suppress all exception) available + * + * Bits: 7 + */ +#define SAE_SHIFT (7) +#define SAE_BITS (1) +#define SAE_MASK OP_GENMASK(SAE_BITS, SAE_SHIFT) +#define GEN_SAE(bit) OP_GENBIT(bit, SAE_SHIFT) + +#define MASK OPMASK_MASK /* Opmask (k1 ~ 7) can be used */ +#define Z Z_MASK +#define B32 BRDCAST_MASK /* {1to16} : load+op instruction can broadcast when it is reg-reg operation */ +#define B64 BRDCAST_MASK /* {1to8} : There are two definitions just for conforming to SDM */ +#define ER STATICRND_MASK /* ER(Embedded Rounding) == Static rounding mode */ +#define SAE SAE_MASK /* SAE(Suppress All Exception) */ + /* * Global modes */ @@ -39,6 +39,7 @@ #define NASM_OPFLAGS_H #include "compiler.h" +#include "tables.h" /* for opflags_t and nasm_reg_flags[] */ /* * Here we define the operand types. These are implemented as bit @@ -53,10 +54,9 @@ * if and only if "operand" belongs to class type "class". */ -typedef uint64_t opflags_t; - #define OP_GENMASK(bits, shift) (((UINT64_C(1) << (bits)) - 1) << (shift)) #define OP_GENBIT(bit, shift) (UINT64_C(1) << ((shift) + (bit))) +#define OP_GENVAL(val, bits, shift) (((val) & ((UINT64_C(1) << (bits)) - 1)) << (shift)) /* * Type of operand: memory reference, register, etc. @@ -162,11 +162,14 @@ typedef uint64_t opflags_t; #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 is_class(class, op) (!((opflags_t)(class) & ~(opflags_t)(op))) +#define is_class(class, op) (!((opflags_t)(class) & ~(opflags_t)(op))) +#define is_reg_class(class, reg) is_class((class), nasm_reg_flags[(reg)]) -#define IS_SREG(op) is_class(REG_SREG, nasm_reg_flags[(op)]) -#define IS_FSGS(op) is_class(REG_FSGS, nasm_reg_flags[(op)]) +#define IS_SREG(op) is_reg_class(REG_SREG, (op)) +#define IS_FSGS(op) is_reg_class(REG_FSGS, (op)) /* Register classes */ #define REG_EA ( REGMEM | REGISTER) /* 'normal' reg, qualifies as EA */ @@ -186,6 +189,12 @@ typedef uint64_t opflags_t; #define RM_YMM ( REG_CLASS_RM_YMM | REGMEM) /* YMM (AVX) operand */ #define YMMREG ( REG_CLASS_RM_YMM | REGMEM | REGISTER) /* YMM (AVX) register */ #define YMM0 (GEN_SUBCLASS(1) | REG_CLASS_RM_YMM | REGMEM | REGISTER) /* YMM register zero */ +#define RM_ZMM ( REG_CLASS_RM_ZMM | REGMEM) /* ZMM (AVX512) operand */ +#define ZMMREG ( REG_CLASS_RM_ZMM | REGMEM | REGISTER) /* ZMM (AVX512) register */ +#define ZMM0 (GEN_SUBCLASS(1) | REG_CLASS_RM_ZMM | REGMEM | REGISTER) /* ZMM register zero */ +#define RM_OPMASK ( REG_CLASS_OPMASK | REGMEM) /* Opmask operand */ +#define OPMASKREG ( REG_CLASS_OPMASK | REGMEM | REGISTER) /* Opmask register */ +#define OPMASK0 (GEN_SUBCLASS(1) | REG_CLASS_OPMASK | REGMEM | REGISTER) /* Opmask register zero (k0) */ #define REG_CDT ( REG_CLASS_CDT | BITS32 | REGISTER) /* CRn, DRn and TRn */ #define REG_CREG (GEN_SUBCLASS(1) | REG_CLASS_CDT | BITS32 | REGISTER) /* CRn */ #define REG_DREG (GEN_SUBCLASS(2) | REG_CLASS_CDT | BITS32 | REGISTER) /* DRn */ @@ -232,7 +241,7 @@ typedef uint64_t opflags_t; #define YMEM (GEN_SUBCLASS(4) | MEMORY) /* 256-bit vector SIB */ /* memory which matches any type of r/m operand */ -#define MEMORY_ANY (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM) +#define MEMORY_ANY (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM | RM_ZMM) /* special immediate values */ #define UNITY (GEN_SUBCLASS(0) | IMMEDIATE) /* operand equals 1 */ @@ -193,6 +193,51 @@ static void process_size_override(insn *result, int operand) } } +/* + * when two or more decorators follow a register operand, + * consecutive decorators are parsed here. + * the order of decorators does not matter. + * e.g. zmm1 {k2}{z} or zmm2 {z,k3} + * decorator(s) are placed at the end of an operand. + */ +static bool parse_braces(decoflags_t *decoflags) +{ + int i; + bool recover = false; + + i = tokval.t_type; + do { + if (i == TOKEN_OPMASK) { + if (*decoflags & OPMASK_MASK) { + nasm_error(ERR_NONFATAL, "opmask k%lu is already set", + *decoflags & OPMASK_MASK); + *decoflags &= ~OPMASK_MASK; + } + *decoflags |= VAL_OPMASK(nasm_regvals[tokval.t_integer]); + } else if (i == TOKEN_DECORATOR) { + switch (tokval.t_integer) { + case BRC_Z: + /* + * according to AVX512 spec, only zeroing/merging decorator + * is supported with opmask + */ + *decoflags |= GEN_Z(0); + break; + } + } else if (i == ',' || i == TOKEN_EOS){ + break; + } else { + nasm_error(ERR_NONFATAL, "only a series of valid decorators" + " expected"); + recover = true; + break; + } + i = stdscan(NULL, &tokval); + } while(1); + + return recover; +} + insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef) { bool insn_is_label = false; @@ -557,10 +602,12 @@ is_expression: int mref; /* is this going to be a memory ref? */ int bracket; /* is it a [] mref, or a & mref? */ int setsize = 0; + decoflags_t brace_flags = 0; /* flags for decorators in braces */ result->oprs[operand].disp_size = 0; /* have to zero this whatever */ result->oprs[operand].eaflags = 0; /* and this */ result->oprs[operand].opflags = 0; + result->oprs[operand].decoflags = 0; i = stdscan(NULL, &tokval); if (i == TOKEN_EOS) @@ -702,17 +749,37 @@ is_expression: recover = true; } else { /* we got the required ] */ i = stdscan(NULL, &tokval); + if (i == TOKEN_DECORATOR) { + /* + * according to AVX512 spec, only broacast decorator is + * expected for memory reference operands + */ + if (tokval.t_flag & TFLAG_BRDCAST) { + brace_flags |= GEN_BRDCAST(0); + i = stdscan(NULL, &tokval); + } else { + nasm_error(ERR_NONFATAL, "broadcast decorator" + "expected inside braces"); + recover = true; + } + } + if (i != 0 && i != ',') { nasm_error(ERR_NONFATAL, "comma or end of line expected"); recover = true; } } } else { /* immediate operand */ - if (i != 0 && i != ',' && i != ':') { - nasm_error(ERR_NONFATAL, "comma, colon or end of line expected"); + if (i != 0 && i != ',' && i != ':' && + i != TOKEN_DECORATOR && i != TOKEN_OPMASK) { + nasm_error(ERR_NONFATAL, "comma, colon, decorator or end of " + "line expected after operand"); recover = true; } else if (i == ':') { result->oprs[operand].type |= COLON; + } else if (i == TOKEN_DECORATOR || i == TOKEN_OPMASK) { + /* parse opmask (and zeroing) after an operand */ + recover = parse_braces(&brace_flags); } } if (recover) { @@ -856,6 +923,7 @@ is_expression: result->oprs[operand].indexreg = i; result->oprs[operand].scale = s; result->oprs[operand].offset = o; + result->oprs[operand].decoflags |= brace_flags; } else { /* it's not a memory reference */ if (is_just_unknown(value)) { /* it's immediate but unknown */ result->oprs[operand].type |= IMMEDIATE; @@ -891,6 +959,27 @@ is_expression: result->oprs[operand].type |= SDWORD; } } + } else if(value->type == EXPR_RDSAE) { + /* + * it's not an operand but a rounding or SAE decorator. + * put the decorator information in the (opflag_t) type field + * of previous operand. + */ + operand --; + switch (value->value) { + case BRC_RN: + case BRC_RU: + case BRC_RD: + case BRC_RZ: + case BRC_SAE: + result->oprs[operand].decoflags |= + (value->value == BRC_SAE ? SAE : ER); + result->evex_rm = value->value; + break; + default: + nasm_error(ERR_NONFATAL, "invalid decorator"); + break; + } } else { /* it's a register */ opflags_t rs; @@ -923,6 +1012,7 @@ is_expression: result->oprs[operand].type &= TO; result->oprs[operand].type |= REGISTER; result->oprs[operand].type |= nasm_reg_flags[value->type]; + result->oprs[operand].decoflags |= brace_flags; result->oprs[operand].basereg = value->type; if (rs && (result->oprs[operand].type & SIZE_MASK) != rs) @@ -36,12 +36,17 @@ # # The columns are: # -# register name, assembler class, disassembler class(es), x86 register number +# register name, assembler class, disassembler class(es), x86 register number[, token flag] # # If the register name ends in two numbers separated by a dash, then it is # repeated as many times as indicated, and the register number is # updated with it. # +# If 'token flag' is present, this value will be assigned to tokflag field in +# 'struct tokendata tokendata[]' table. Token flag can be used for specifying +# special usage of corresponding register. E.g. opmask registers can be either +# enclosed by curly braces or standalone operand depending on the usage. +# # General-purpose registers al REG_AL reg8,reg8_rex 0 @@ -117,3 +122,11 @@ xmm1-15 XMMREG xmmreg 1 # AVX registers ymm0 YMM0 ymmreg 0 ymm1-15 YMMREG ymmreg 1 + +# AVX3 registers +zmm0 ZMM0 zmmreg 0 +zmm1-31 ZMMREG zmmreg 1 + +# Opmask registers +k0 OPMASK0 opmaskreg 0 +k1-7 OPMASKREG opmaskreg 1 TFLAG_BRC_OPT @@ -48,7 +48,7 @@ sub process_line($) { my($line) = @_; my @v; - if ( $line !~ /^\s*(\S+)\s*(\S+)\s*(\S+)\s*([0-9]+)$/i ) { + if ( $line !~ /^\s*(\S+)\s*(\S+)\s*(\S+)\s*([0-9]+)\s*(\S*)/i ) { die "regs.dat:$nline: invalid input\n"; } $reg = $1; @@ -53,6 +53,8 @@ static char *stdscan_bufptr = NULL; static char **stdscan_tempstorage = NULL; static int stdscan_tempsize = 0, stdscan_templen = 0; +static int brace = 0; /* nested brace counter */ +static bool brace_opened = false; /* if brace is just opened */ #define STDSCAN_TEMP_DELTA 256 void stdscan_set(char *str) @@ -105,6 +107,40 @@ static char *stdscan_copy(char *p, int len) return text; } +/* + * a token is enclosed with braces. proper token type will be assigned + * accordingly with the token flag. + * a closing brace is treated as an ending character of corresponding token. + */ +static int stdscan_handle_brace(struct tokenval *tv) +{ + if (!(tv->t_flag & TFLAG_BRC_ANY)) { + /* invalid token is put inside braces */ + nasm_error(ERR_NONFATAL, + "%s is not a valid decorator with braces", tv->t_charptr); + tv->t_type = TOKEN_INVALID; + } else if (tv->t_flag & TFLAG_BRC_OPT) { + if (is_reg_class(OPMASKREG, tv->t_integer)) { + /* within braces, opmask register is now used as a mask */ + tv->t_type = TOKEN_OPMASK; + } + } + + stdscan_bufptr = nasm_skip_spaces(stdscan_bufptr); + + if (stdscan_bufptr[0] == '}') { + stdscan_bufptr ++; /* skip the closing brace */ + brace --; + } else if (stdscan_bufptr[0] != ',') { + /* treat {foo,bar} as {foo}{bar} + * by regarding ',' as a mere separator between decorators + */ + nasm_error(ERR_NONFATAL, "closing brace expected"); + tv->t_type = TOKEN_INVALID; + } + return tv->t_type; +} + int stdscan(void *private_data, struct tokenval *tv) { char ourcopy[MAX_KEYWORD + 1], *r, *s; @@ -112,14 +148,22 @@ int stdscan(void *private_data, struct tokenval *tv) (void)private_data; /* Don't warn that this parameter is unused */ stdscan_bufptr = nasm_skip_spaces(stdscan_bufptr); - if (!*stdscan_bufptr) + if (!*stdscan_bufptr) { + /* nested brace shouldn't affect following lines */ + brace = 0; return tv->t_type = TOKEN_EOS; + } /* we have a token; either an id, a number or a char */ if (isidstart(*stdscan_bufptr) || - (*stdscan_bufptr == '$' && isidstart(stdscan_bufptr[1]))) { + (*stdscan_bufptr == '$' && isidstart(stdscan_bufptr[1])) || + (brace && isidchar(*stdscan_bufptr))) { /* because of {1to8} */ /* now we've got an identifier */ bool is_sym = false; + int token_type; + + /* opening brace is followed by any letter */ + brace_opened = false; if (*stdscan_bufptr == '$') { is_sym = true; @@ -128,7 +172,8 @@ int stdscan(void *private_data, struct tokenval *tv) r = stdscan_bufptr++; /* read the entire buffer to advance the buffer pointer but... */ - while (isidchar(*stdscan_bufptr)) + /* {rn-sae}, {rd-sae}, {ru-sae}, {rz-sae} contain '-' in tokens. */ + while (isidchar(*stdscan_bufptr) || (brace && *stdscan_bufptr == '-')) stdscan_bufptr++; /* ... copy only up to IDLEN_MAX-1 characters */ @@ -143,7 +188,19 @@ int stdscan(void *private_data, struct tokenval *tv) *r = '\0'; /* right, so we have an identifier sitting in temp storage. now, * is it actually a register or instruction name, or what? */ - return nasm_token_hash(ourcopy, tv); + token_type = nasm_token_hash(ourcopy, tv); + + if (likely(!brace)) { + if (likely(!(tv->t_flag & TFLAG_BRC))) { + /* most of the tokens fall into this case */ + return token_type; + } else { + return tv->t_type = TOKEN_ID; + } + } else { + /* handle tokens inside braces */ + return stdscan_handle_brace(tv); + } } else if (*stdscan_bufptr == '$' && !isnumchar(stdscan_bufptr[1])) { /* * It's a $ sign with no following hex number; this must @@ -267,6 +324,35 @@ int stdscan(void *private_data, struct tokenval *tv) } else if (stdscan_bufptr[0] == '|' && stdscan_bufptr[1] == '|') { stdscan_bufptr += 2; return tv->t_type = TOKEN_DBL_OR; + } else if (stdscan_bufptr[0] == '{') { + stdscan_bufptr ++; /* skip the opening brace */ + brace ++; /* in case of nested braces */ + brace_opened = true; /* brace is just opened */ + return stdscan(private_data, tv); + } else if (stdscan_bufptr[0] == ',' && brace) { + /* + * a comma inside braces should be treated just as a separator. + * this is almost same as an opening brace except increasing counter. + */ + stdscan_bufptr ++; + brace_opened = true; /* brace is just opened */ + return stdscan(private_data, tv); + } else if (stdscan_bufptr[0] == '}') { + stdscan_bufptr ++; /* skip the closing brace */ + if (brace) { + /* unhandled nested closing brace */ + brace --; + /* if brace is closed without any content in it */ + if (brace_opened) { + brace_opened = false; + nasm_error(ERR_NONFATAL, "nothing inside braces"); + } + return stdscan(private_data, tv); + } else { + /* redundant closing brace */ + return tv->t_type = TOKEN_INVALID; + } + return stdscan(private_data, tv); } else /* just an ordinary char */ return tv->t_type = (uint8_t)(*stdscan_bufptr++); } @@ -43,7 +43,6 @@ #include "compiler.h" #include <inttypes.h> #include "insnsi.h" /* For enum opcode */ -#include "opflags.h" /* For opflags_t */ /* --- From standard.mac via macros.pl: --- */ @@ -62,6 +61,8 @@ extern const char * const nasm_insn_names[]; /* regs.c */ extern const char * const nasm_reg_names[]; /* regflags.c */ +typedef uint64_t opflags_t; +typedef uint8_t decoflags_t; extern const opflags_t nasm_reg_flags[]; /* regvals.c */ extern const int nasm_regvals[]; @@ -35,7 +35,7 @@ # Tokens other than instructions and registers # -% TOKEN_PREFIX, 0, P_* +% TOKEN_PREFIX, 0, 0, P_* a16 a32 a64 @@ -55,7 +55,7 @@ wait xacquire xrelease -% TOKEN_SPECIAL, 0, S_* +% TOKEN_SPECIAL, 0, 0, S_* abs byte dword @@ -73,13 +73,13 @@ tword word yword -% TOKEN_FLOAT, 0, 0 +% TOKEN_FLOAT, 0, 0, 0 __infinity__ __nan__ __qnan__ __snan__ -% TOKEN_FLOATIZE, 0, FLOAT_{__float*__} +% TOKEN_FLOATIZE, 0, 0, FLOAT_{__float*__} __float8__ __float16__ __float32__ @@ -89,7 +89,7 @@ __float80e__ __float128l__ __float128h__ -% TOKEN_STRFUNC, 0, STRFUNC_{__*__} +% TOKEN_STRFUNC, 0, 0, STRFUNC_{__*__} __utf16__ __utf16le__ __utf16be__ @@ -97,12 +97,26 @@ __utf32__ __utf32le__ __utf32be__ -% TOKEN_IFUNC, 0, IFUNC_{__*__} +% TOKEN_IFUNC, 0, 0, IFUNC_{__*__} __ilog2e__ __ilog2w__ __ilog2f__ __ilog2c__ -% TOKEN_*, 0, 0 +% TOKEN_*, 0, 0, 0 seg wrt + +% TOKEN_DECORATOR, 0, TFLAG_BRC | TFLAG_BRDCAST , BRC_1TO{1to*} +1to8 +1to16 + +% TOKEN_DECORATOR, 0, TFLAG_BRC, BRC_{*-sae} +rn-sae +rd-sae +ru-sae +rz-sae + +% TOKEN_DECORATOR, 0, TFLAG_BRC, BRC_* +sae +z @@ -65,14 +65,14 @@ while (defined($line = <ID>)) { # Single instruction token if (!defined($tokens{$token})) { $tokens{$token} = scalar @tokendata; - push(@tokendata, "\"${token}\", TOKEN_INSN, C_none, I_${insn}"); + push(@tokendata, "\"${token}\", TOKEN_INSN, C_none, 0, I_${insn}"); } } else { # Conditional instruction foreach $cc (@conditions) { if (!defined($tokens{$token.$cc})) { $tokens{$token.$cc} = scalar @tokendata; - push(@tokendata, "\"${token}${cc}\", TOKEN_INSN, C_\U$cc\E, I_${insn}"); + push(@tokendata, "\"${token}${cc}\", TOKEN_INSN, C_\U$cc\E, 0, I_${insn}"); } } } @@ -85,8 +85,9 @@ close(ID); # open(RD, "< ${regs_dat}") or die "$0: cannot open $regs_dat: $!\n"; while (defined($line = <RD>)) { - if ($line =~ /^([a-z0-9_-]+)\s/) { + if ($line =~ /^([a-z0-9_-]+)\s*\S+\s*\S+\s*[0-9]+\s*(\S*)/) { $reg = $1; + $reg_flag = $2; if ($reg =~ /^(.*[^0-9])([0-9]+)\-([0-9]+)(|[^0-9].*)$/) { $nregs = $3-$2+1; @@ -104,7 +105,11 @@ while (defined($line = <RD>)) { die "Duplicate definition: $reg\n"; } $tokens{$reg} = scalar @tokendata; - push(@tokendata, "\"${reg}\", TOKEN_REG, 0, R_\U${reg}\E"); + if ($reg_flag eq '') { + push(@tokendata, "\"${reg}\", TOKEN_REG, 0, 0, R_\U${reg}\E"); + } else { + push(@tokendata, "\"${reg}\", TOKEN_REG, 0, ${reg_flag}, R_\U${reg}\E"); + } if (defined($reg_prefix)) { $reg_nr++; @@ -214,7 +219,8 @@ if ($output eq 'h') { print "struct tokendata {\n"; print " const char *string;\n"; print " int16_t tokentype;\n"; - print " int16_t aux;\n"; + print " int8_t aux;\n"; + print " int8_t tokflag;\n"; print " int32_t num;\n"; print "};\n"; print "\n"; @@ -270,6 +276,7 @@ if ($output eq 'h') { print "\n"; print " tv->t_integer = data->num;\n"; print " tv->t_inttwo = data->aux;\n"; + print " tv->t_flag = data->tokflag;\n"; print " return tv->t_type = data->tokentype;\n"; print "}\n"; } |