From 0da6b580ebb5ed60164b95a720fcf26591007b0f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 12 Sep 2007 20:32:39 -0700 Subject: [PATCH] Support r/m operands for non-integer types Support r/m operands for non-integer operands types, i.e. mmx or xmm operands. This allows mmx and xmm operands to be written more compactly, speeding up the assembler. --- disasm.c | 13 +++++++++---- insns.pl | 4 +++- nasm.h | 20 +++++++++++++------- parser.c | 3 ++- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/disasm.c b/disasm.c index 162e2e8..cf7cd71 100644 --- a/disasm.c +++ b/disasm.c @@ -79,6 +79,11 @@ static uint64_t getu64(uint8_t *data) /* Important: regval must already have been adjusted for rex extensions */ static enum reg_enum whichreg(int32_t regflags, int regval, int rex) { + if (!(regflags & (REGISTER|REGMEM))) + return 0; /* Registers not permissible?! */ + + regflags |= REGISTER; + if (!(REG_AL & ~regflags)) return R_AL; if (!(REG_AX & ~regflags)) @@ -119,17 +124,17 @@ static enum reg_enum whichreg(int32_t regflags, int regval, int rex) if (regval < 0 || regval > 15) return 0; - if (!((REGMEM | BITS8) & ~regflags)) { + if (!(REG8 & ~regflags)) { if (rex & REX_P) return rd_reg8_rex[regval]; else return rd_reg8[regval]; } - if (!((REGMEM | BITS16) & ~regflags)) + if (!(REG16 & ~regflags)) return rd_reg16[regval]; - if (!((REGMEM | BITS32) & ~regflags)) + if (!(REG32 & ~regflags)) return rd_reg32[regval]; - if (!((REGMEM | BITS64) & ~regflags)) + if (!(REG64 & ~regflags)) return rd_reg64[regval]; if (!(REG_SREG & ~regflags)) return rd_sreg[regval & 7]; /* Ignore REX */ diff --git a/insns.pl b/insns.pl index 280213c..421f16a 100644 --- a/insns.pl +++ b/insns.pl @@ -215,7 +215,9 @@ sub format { $operands =~ s/memory_offs/mem_offs/g; $operands =~ s/imm(\d+)/imm|bits$1/g; $operands =~ s/imm/immediate/g; - $operands =~ s/rm(\d+)/regmem|bits$1/g; + $operands =~ s/rm(\d+)/rm_gpr|bits$1/g; + $operands =~ s/mmxrm/rm_mmx/g; + $operands =~ s/xmmrm/rm_xmm/g; $num = 3; $operands = '0,0,0', $num = 0 if $operands eq 'void'; $operands .= ',0', $num-- while $operands !~ /,.*,/; diff --git a/nasm.h b/nasm.h index ff1e80e..34d6d05 100644 --- a/nasm.h +++ b/nasm.h @@ -432,12 +432,12 @@ enum { * * Bits 20-26: register classes * 20: REG_CDT (CRx, DRx, TRx) - * 21: REG_GPR (integer register) + * 21: RM_GPR (REG_GPR) (integer register) * 22: REG_SREG * 23: IP_REG (RIP or EIP) [unused] * 24: FPUREG - * 25: MMXREG - * 26: XMMREG + * 25: RM_MMX (MMXREG) + * 26: RM_XMM (XMMREG) * * Bits 27-31 are currently unallocated. */ @@ -470,6 +470,7 @@ enum { /* Register classes */ #define REG_EA 0x00009000L /* 'normal' reg, qualifies as EA */ +#define RM_GPR 0x00208000L /* integer operand */ #define REG_GPR 0x00209000L /* integer register */ #define REG8 0x00209001L /* 8-bit GPR */ #define REG16 0x00209002L /* 16-bit GPR */ @@ -480,8 +481,10 @@ enum { #define EIPREG 0x00801004L /* EIP */ #define FPUREG 0x01001000L /* floating point stack registers */ #define FPU0 0x01011000L /* FPU stack register zero */ -#define MMXREG 0x02009000L /* MMX registers */ -#define XMMREG 0x04009000L /* XMM Katmai reg */ +#define RM_MMX 0x02008000L /* MMX operand */ +#define MMXREG 0x02009000L /* MMX register */ +#define RM_XMM 0x04008000L /* XMM (SSE) operand */ +#define XMMREG 0x04009000L /* XMM (SSE) register */ #define REG_CDT 0x00101004L /* CRn, DRn and TRn */ #define REG_CREG 0x00111004L /* CRn */ #define REG_DREG 0x00121004L /* DRn */ @@ -514,8 +517,11 @@ enum { #define REG_HIGH 0x00289001L /* high regs: AH, CH, DH, BH */ /* special types of EAs */ -#define MEM_OFFS 0x00214000L /* simple [address] offset - absolute! */ -#define IP_REL 0x00224000L /* IP-relative offset */ +#define MEM_OFFS 0x0001c000L /* simple [address] offset - absolute! */ +#define IP_REL 0x0002c000L /* IP-relative offset */ + +/* memory which matches any type of r/m operand */ +#define MEMORY_ANY (MEMORY|RM_GPR|RM_MMX|RM_XMM) /* special type of immediate operand */ #define UNITY 0x00012000L /* for shift/rotate instructions */ diff --git a/parser.c b/parser.c index 8a376fd..1c7b8d9 100644 --- a/parser.c +++ b/parser.c @@ -667,7 +667,8 @@ insn *parse_line(int pass, char *buffer, insn * result, return result; } - result->oprs[operand].type |= MEMORY; + /* It is memory, but it can match any r/m operand */ + result->oprs[operand].type |= MEMORY_ANY; if (b == -1 && (i == -1 || s == 0)) { int is_rel = globalbits == 64 && -- 2.7.4