From dfb918047b32e57b5cf4840021ccc0c03b4685f9 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 May 2008 11:43:53 -0700 Subject: [PATCH] Add DY, YWORD, and the SY instruction flag Add the DY instruction, YWORD keyword, and an SY marker for instruction sizes. Add a few more AVX sample instructions. --- assemble.c | 27 ++++++++++++++++++++++----- disasm.c | 3 +++ insns.dat | 42 ++++++++++++++++++++++++++---------------- insns.h | 3 ++- nasm.c | 13 +++++++++++++ nasm.h | 12 +++++++----- parser.c | 14 ++++++++++++-- preproc.c | 4 ++-- tokens.dat | 1 + 9 files changed, 88 insertions(+), 31 deletions(-) diff --git a/assemble.c b/assemble.c index d10e5b06..63ac21e1 100644 --- a/assemble.c +++ b/assemble.c @@ -119,6 +119,9 @@ #include "regflags.c" #include "regvals.c" +/* Initialized to zero by the C standard */ +static const uint8_t const_zero_buf[256]; + typedef struct { int sib_present; /* is a SIB byte necessary? */ int bytes; /* # of bytes of offset needed */ @@ -168,6 +171,8 @@ static const char *size_name(int size) return "tword"; case 16: return "oword"; + case 32: + return "yword"; default: return "???"; } @@ -294,6 +299,9 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp, case I_DO: wsize = 16; break; + case I_DY: + wsize = 32; + break; default: break; } @@ -318,7 +326,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp, OUT_RAWDATA, 1, NO_SEG, NO_SEG); } } else if (wsize > 8) { - errfunc(ERR_NONFATAL, "integer supplied to a DT or DO" + errfunc(ERR_NONFATAL, "integer supplied to a DT, DO or DY" " instruction"); } else out(offset, segment, &e->offset, @@ -333,8 +341,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp, if (align) { align = wsize - align; - out(offset, segment, - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", + out(offset, segment, const_zero_buf, OUT_RAWDATA, align, NO_SEG, NO_SEG); } offset += e->stringlen + align; @@ -630,7 +637,8 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp, if (instruction->opcode == I_DB || instruction->opcode == I_DW || instruction->opcode == I_DD || instruction->opcode == I_DQ || - instruction->opcode == I_DT || instruction->opcode == I_DO) { + instruction->opcode == I_DT || instruction->opcode == I_DO || + instruction->opcode == I_DY) { extop *e; int32_t isize, osize, wsize = 0; /* placate gcc */ @@ -654,6 +662,9 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp, case I_DO: wsize = 16; break; + case I_DY: + wsize = 32; + break; default: break; } @@ -1483,7 +1494,7 @@ static void gencode(int32_t segment, int64_t offset, int bits, if (opx->segment == NO_SEG) errfunc(ERR_NONFATAL, "value referenced by FAR is not" " relocatable"); - data = 0L; + data = 0; out(offset, segment, &data, OUT_ADDRESS, 2, outfmt->segbase(1 + opx->segment), opx->wrt); @@ -1957,6 +1968,9 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits) case IF_SO: size[i] = BITS128; break; + case IF_SY: + size[i] = BITS256; + break; case IF_SZ: switch (bits) { case 16: @@ -1991,6 +2005,9 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits) case IF_SO: asize = BITS128; break; + case IF_SY: + asize = BITS256; + break; case IF_SZ: switch (bits) { case 16: diff --git a/disasm.c b/disasm.c index 711304c0..2d93ea64 100644 --- a/disasm.c +++ b/disasm.c @@ -1331,6 +1331,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, if (t & BITS128) slen += snprintf(output + slen, outbufsize - slen, "oword "); + if (t & BITS256) + slen += + snprintf(output + slen, outbufsize - slen, "yword "); if (t & FAR) slen += snprintf(output + slen, outbufsize - slen, "far "); if (t & NEAR) diff --git a/insns.dat b/insns.dat index 114569f5..ef1ba588 100644 --- a/insns.dat +++ b/insns.dat @@ -25,12 +25,14 @@ DD ignore ignore ignore DQ ignore ignore ignore DT ignore ignore ignore DO ignore ignore ignore +DY ignore ignore ignore RESB imm \340 8086 RESW ignore ignore ignore RESD ignore ignore ignore RESQ ignore ignore ignore REST ignore ignore ignore RESO ignore ignore ignore +RESY ignore ignore ignore ;# Conventional instructions AAA void \1\x37 8086,NOLONG @@ -2023,22 +2025,30 @@ PFRCP mmxreg,mmxrm \323\2\x0F\x0F\110\1\x86 PENT,3DNOW,SQ,CYRIX PFRSQRT mmxreg,mmxrm \323\2\x0F\x0F\110\1\x87 PENT,3DNOW,SQ,CYRIX ;# Intel AVX instructions -VPERMILTD2PS xmmreg,xmmreg,xmmrm,xmmreg [rvms: vex.nds.128.66.0f3a.w0 48 /r /is4=0] AVX,SANDYBRIDGE -VPERMILTD2PS xmmreg,xmmreg,xmmreg,xmmrm [rvsm: vex.nds.128.66.0f3a.w1 48 /r /is4=0] AVX,SANDYBRIDGE -VPERMILTD2PS ymmreg,ymmreg,ymmrm,ymmreg [rvms: vex.nds.256.66.0f3a.w0 48 /r /is4=0] AVX,SANDYBRIDGE -VPERMILTD2PS ymmreg,ymmreg,ymmreg,ymmrm [rvsm: vex.nds.256.66.0f3a.w1 48 /r /is4=0] AVX,SANDYBRIDGE -VPERMILMO2PS xmmreg,xmmreg,xmmrm,xmmreg [rvms: vex.nds.128.66.0f3a.w0 48 /r /is4=2] AVX,SANDYBRIDGE -VPERMILMO2PS xmmreg,xmmreg,xmmreg,xmmrm [rvsm: vex.nds.128.66.0f3a.w1 48 /r /is4=2] AVX,SANDYBRIDGE -VPERMILMO2PS ymmreg,ymmreg,ymmrm,ymmreg [rvms: vex.nds.256.66.0f3a.w0 48 /r /is4=2] AVX,SANDYBRIDGE -VPERMILMO2PS ymmreg,ymmreg,ymmreg,ymmrm [rvsm: vex.nds.256.66.0f3a.w1 48 /r /is4=2] AVX,SANDYBRIDGE -VPERMILMZ2PS xmmreg,xmmreg,xmmrm,xmmreg [rvms: vex.nds.128.66.0f3a.w0 48 /r /is4=3] AVX,SANDYBRIDGE -VPERMILMZ2PS xmmreg,xmmreg,xmmreg,xmmrm [rvsm: vex.nds.128.66.0f3a.w1 48 /r /is4=3] AVX,SANDYBRIDGE -VPERMILMZ2PS ymmreg,ymmreg,ymmrm,ymmreg [rvms: vex.nds.256.66.0f3a.w0 48 /r /is4=3] AVX,SANDYBRIDGE -VPERMILMZ2PS ymmreg,ymmreg,ymmreg,ymmrm [rvsm: vex.nds.256.66.0f3a.w1 48 /r /is4=3] AVX,SANDYBRIDGE -VPERMIL2PS xmmreg,xmmreg,xmmrm,xmmreg,imm [rvmsi: vex.nds.128.66.0f3a.w0 48 /r /is4] AVX,SANDYBRIDGE -VPERMIL2PS xmmreg,xmmreg,xmmreg,xmmrm,imm [rvsmi: vex.nds.128.66.0f3a.w1 48 /r /is4] AVX,SANDYBRIDGE -VPERMIL2PS ymmreg,ymmreg,ymmrm,ymmreg,imm [rvmsi: vex.nds.256.66.0f3a.w0 48 /r /is4] AVX,SANDYBRIDGE -VPERMIL2PS ymmreg,ymmreg,ymmreg,ymmrm,imm [rvsmi: vex.nds.256.66.0f3a.w1 48 /r /is4] AVX,SANDYBRIDGE +VADDPD xmmreg,xmmreg,xmmrm [rvm: vex.nds.128.66.0f 58 /r] AVX,SANDYBRIDGE,SO +VADDPD ymmreg,ymmreg,ymmrm [rvm: vex.nds.256.66.0f 58 /r] AVX,SANDYBRIDGE,SY +VADDPD xmmreg,xmmrm [r+vm: vex.nds.128.66.0f 58 /r] AVX,SANDYBRIDGE,SO +VADDPD ymmreg,ymmrm [r+vm: vex.nds.256.66.0f 58 /r] AVX,SANDYBRIDGE,SY +VADDPS xmmreg,xmmreg,xmmrm [rvm: vex.nds.128.0f 58 /r] AVX,SANDYBRIDGE,SO +VADDPS ymmreg,ymmreg,ymmrm [rvm: vex.nds.256.0f 58 /r] AVX,SANDYBRIDGE,SY +VADDPS xmmreg,xmmrm [r+vm: vex.nds.128.0f 58 /r] AVX,SANDYBRIDGE,SO +VADDPS ymmreg,ymmrm [r+vm: vex.nds.256.0f 58 /r] AVX,SANDYBRIDGE,SY +VPERMILTD2PS xmmreg,xmmreg,xmmrm,xmmreg [rvms: vex.nds.128.66.0f3a.w0 48 /r /is4=0] AVX,SANDYBRIDGE,SO +VPERMILTD2PS xmmreg,xmmreg,xmmreg,xmmrm [rvsm: vex.nds.128.66.0f3a.w1 48 /r /is4=0] AVX,SANDYBRIDGE,SO +VPERMILTD2PS ymmreg,ymmreg,ymmrm,ymmreg [rvms: vex.nds.256.66.0f3a.w0 48 /r /is4=0] AVX,SANDYBRIDGE,SY +VPERMILTD2PS ymmreg,ymmreg,ymmreg,ymmrm [rvsm: vex.nds.256.66.0f3a.w1 48 /r /is4=0] AVX,SANDYBRIDGE,SY +VPERMILMO2PS xmmreg,xmmreg,xmmrm,xmmreg [rvms: vex.nds.128.66.0f3a.w0 48 /r /is4=2] AVX,SANDYBRIDGE,SO +VPERMILMO2PS xmmreg,xmmreg,xmmreg,xmmrm [rvsm: vex.nds.128.66.0f3a.w1 48 /r /is4=2] AVX,SANDYBRIDGE,SO +VPERMILMO2PS ymmreg,ymmreg,ymmrm,ymmreg [rvms: vex.nds.256.66.0f3a.w0 48 /r /is4=2] AVX,SANDYBRIDGE,SY +VPERMILMO2PS ymmreg,ymmreg,ymmreg,ymmrm [rvsm: vex.nds.256.66.0f3a.w1 48 /r /is4=2] AVX,SANDYBRIDGE,SY +VPERMILMZ2PS xmmreg,xmmreg,xmmrm,xmmreg [rvms: vex.nds.128.66.0f3a.w0 48 /r /is4=3] AVX,SANDYBRIDGE,SO +VPERMILMZ2PS xmmreg,xmmreg,xmmreg,xmmrm [rvsm: vex.nds.128.66.0f3a.w1 48 /r /is4=3] AVX,SANDYBRIDGE,SO +VPERMILMZ2PS ymmreg,ymmreg,ymmrm,ymmreg [rvms: vex.nds.256.66.0f3a.w0 48 /r /is4=3] AVX,SANDYBRIDGE,SY +VPERMILMZ2PS ymmreg,ymmreg,ymmreg,ymmrm [rvsm: vex.nds.256.66.0f3a.w1 48 /r /is4=3] AVX,SANDYBRIDGE,SY +VPERMIL2PS xmmreg,xmmreg,xmmrm,xmmreg,imm [rvmsi: vex.nds.128.66.0f3a.w0 48 /r /is4] AVX,SANDYBRIDGE,SO +VPERMIL2PS xmmreg,xmmreg,xmmreg,xmmrm,imm [rvsmi: vex.nds.128.66.0f3a.w1 48 /r /is4] AVX,SANDYBRIDGE,SO +VPERMIL2PS ymmreg,ymmreg,ymmrm,ymmreg,imm [rvmsi: vex.nds.256.66.0f3a.w0 48 /r /is4] AVX,SANDYBRIDGE,SY +VPERMIL2PS ymmreg,ymmreg,ymmreg,ymmrm,imm [rvsmi: vex.nds.256.66.0f3a.w1 48 /r /is4] AVX,SANDYBRIDGE,SY ;# VIA (Centaur) security instructions XSTORE void \360\3\x0F\xA7\xC0 PENT,CYRIX diff --git a/insns.h b/insns.h index 474e715c..4f954a53 100644 --- a/insns.h +++ b/insns.h @@ -75,7 +75,8 @@ extern const uint8_t nasm_bytecodes[]; #define IF_SD 0x0000000CUL /* unsized operands can't be non-dword */ #define IF_SQ 0x00000010UL /* unsized operands can't be non-qword */ #define IF_SO 0x00000014UL /* unsized operands can't be non-oword */ -#define IF_SZ 0x00000018UL /* unsized operands must match the bitsize */ +#define IF_SY 0x00000018UL /* unsized operands can't be non-yword */ +#define IF_SZ 0x0000001CUL /* unsized operands must match the bitsize */ #define IF_SMASK 0x0000001CUL /* mask for unsized argument size */ #define IF_AR0 0x00000020UL /* SB, SW, SD applies to argument 0 */ #define IF_AR1 0x00000040UL /* SB, SW, SD applies to argument 1 */ diff --git a/nasm.c b/nasm.c index 85865e8e..484993a7 100644 --- a/nasm.c +++ b/nasm.c @@ -1486,6 +1486,16 @@ static void assemble_file(char *fname) TYS_ELEMENTS(output_ins.oprs[0]. offset) | TY_TBYTE; break; + case I_RESO: + typeinfo = + TYS_ELEMENTS(output_ins.oprs[0]. + offset) | TY_OWORD; + break; + case I_RESY: + typeinfo = + TYS_ELEMENTS(output_ins.oprs[0]. + offset) | TY_YWORD; + break; case I_DB: typeinfo |= TY_BYTE; break; @@ -1507,6 +1517,9 @@ static void assemble_file(char *fname) case I_DO: typeinfo |= TY_OWORD; break; + case I_DY: + typeinfo |= TY_YWORD; + break; default: typeinfo = TY_LABEL; diff --git a/nasm.h b/nasm.h index 18184d18..f76f87d9 100644 --- a/nasm.h +++ b/nasm.h @@ -374,7 +374,7 @@ enum { * * The bits are assigned as follows: * - * Bits 0-7, 29: sizes + * Bits 0-7, 23, 29: sizes * 0: 8 bits (BYTE) * 1: 16 bits (WORD) * 2: 32 bits (DWORD) @@ -383,6 +383,7 @@ enum { * 5: FAR * 6: NEAR * 7: SHORT + * 23: 256 bits (YWORD) * 29: 128 bits (OWORD) * * Bits 8-11 modifiers @@ -432,11 +433,10 @@ enum { * 18: BYTENESS32 (-128..127) * 19: BYTENESS64 (-128..127) * - * Bits 20-26: register classes + * Bits 20-22, 24-27: register classes * 20: REG_CDT (CRx, DRx, TRx) * 21: RM_GPR (REG_GPR) (integer register) * 22: REG_SREG - * 23: IP_REG (RIP or EIP) [unused] * 24: FPUREG * 25: RM_MMX (MMXREG) * 26: RM_XMM (XMMREG) @@ -459,12 +459,13 @@ typedef uint32_t opflags_t; #define BITS64 0x00000008U /* x64 and FPU only */ #define BITS80 0x00000010U /* FPU only */ #define BITS128 0x20000000U +#define BITS256 0x00800000U #define FAR 0x00000020U /* grotty: this means 16:16 or */ /* 16:32, like in CALL/JMP */ #define NEAR 0x00000040U #define SHORT 0x00000080U /* and this means what it says :) */ -#define SIZE_MASK 0x200000FFU /* all the size attributes */ +#define SIZE_MASK 0x208000FFU /* all the size attributes */ /* Modifiers */ #define MODIFIER_MASK 0x00000f00U @@ -955,6 +956,7 @@ struct dfmt { #define TY_QWORD 0x30 #define TY_TBYTE 0x38 #define TY_OWORD 0x40 +#define TY_YWORD 0x48 #define TY_COMMON 0xE0 #define TY_SEG 0xE8 #define TY_EXTERN 0xF0 @@ -975,7 +977,7 @@ enum special_tokens { SPECIAL_ENUM_START = PREFIX_ENUM_LIMIT, S_ABS = SPECIAL_ENUM_START, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, - S_OWORD, S_QWORD, S_REL, S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD, + S_OWORD, S_QWORD, S_REL, S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD, S_YWORD, SPECIAL_ENUM_LIMIT }; diff --git a/parser.c b/parser.c index 9172fb1c..72e4e6c9 100644 --- a/parser.c +++ b/parser.c @@ -322,6 +322,7 @@ restart_parse: if (result->opcode == I_RESB || result->opcode == I_RESW || result->opcode == I_RESD || result->opcode == I_RESQ || result->opcode == I_REST || result->opcode == I_RESO || + result->opcode == I_RESY || result->opcode == I_EQU || result->opcode == I_INCBIN) { critical = (pass0 < 2 ? 1 : 2); @@ -331,7 +332,7 @@ restart_parse: if (result->opcode == I_DB || result->opcode == I_DW || result->opcode == I_DD || result->opcode == I_DQ || result->opcode == I_DT || result->opcode == I_DO || - result->opcode == I_INCBIN) { + result->opcode == I_DY || result->opcode == I_INCBIN) { extop *eop, **tail = &result->eops, **fixptr; int oper_num = 0; @@ -560,6 +561,11 @@ restart_parse: result->oprs[operand].type |= BITS128; setsize = 1; break; + case S_YWORD: + if (!setsize) + result->oprs[operand].type |= BITS256; + setsize = 1; + break; case S_TO: result->oprs[operand].type |= TO; break; @@ -857,7 +863,7 @@ while (operand < MAX_OPERANDS) result->oprs[operand++].type = 0; /* - * Transform RESW, RESD, RESQ, REST, RESO into RESB. + * Transform RESW, RESD, RESQ, REST, RESO, RESY into RESB. */ switch (result->opcode) { case I_RESW: @@ -880,6 +886,10 @@ while (operand < MAX_OPERANDS) result->opcode = I_RESB; result->oprs[0].offset *= 16; break; + case I_RESY: + result->opcode = I_RESB; + result->oprs[0].offset *= 32; + break; default: break; } diff --git a/preproc.c b/preproc.c index f3ef2729..9e97257c 100644 --- a/preproc.c +++ b/preproc.c @@ -1744,9 +1744,9 @@ static void undef_smacro(Context *ctx, const char *mname) */ static int parse_size(const char *str) { static const char *size_names[] = - { "byte", "dword", "oword", "qword", "tword", "word" }; + { "byte", "dword", "oword", "qword", "tword", "word", "yword" }; static const int sizes[] = - { 0, 1, 4, 16, 8, 10, 2 }; + { 0, 1, 4, 16, 8, 10, 2, 32 }; return sizes[bsii(str, size_names, elements(size_names))+1]; } diff --git a/tokens.dat b/tokens.dat index 9e221831..6c3ad650 100644 --- a/tokens.dat +++ b/tokens.dat @@ -35,6 +35,7 @@ strict to tword word +yword % TOKEN_FLOAT, 0, 0 __infinity__