Support r/m operands for non-integer types
authorH. Peter Anvin <hpa@zytor.com>
Thu, 13 Sep 2007 03:32:39 +0000 (20:32 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 13 Sep 2007 04:04:39 +0000 (21:04 -0700)
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
insns.pl
nasm.h
parser.c

index 162e2e8..cf7cd71 100644 (file)
--- 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 */
index 280213c..421f16a 100644 (file)
--- 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 (file)
--- 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 */
index 8a376fd..1c7b8d9 100644 (file)
--- 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 &&