Przeglądaj źródła

* x86 assembler: operand type declarations rewritten using expressions instead of literal numbers where possible. Reassigned bit values to match the current NASM (the values themselves don't actually matter and can be chosen pretty arbitrary. What matters is the clean separation between different parts of the bitmask. In particular, the old value of XMM register class bit was equal to OT_BITS80, causing matching algorithm to effectively ignore it and accept e.g. MMX registers in place of XMM ones, part of Mantis #14387).
* Fixed matching of memory references with OT_XMMRM and OT_MMXRM.

git-svn-id: trunk@17449 -

sergei 14 lat temu
rodzic
commit
6d0d8734e0
1 zmienionych plików z 108 dodań i 68 usunięć
  1. 108 68
      compiler/x86/aasmcpu.pas

+ 108 - 68
compiler/x86/aasmcpu.pas

@@ -46,83 +46,126 @@ interface
     { Operand types }
       OT_NONE      = $00000000;
 
-      OT_BITS8     = $00000001;  { size, and other attributes, of the operand  }
+      { Bits 0..7: sizes }
+      OT_BITS8     = $00000001;
       OT_BITS16    = $00000002;
       OT_BITS32    = $00000004;
-      OT_BITS64    = $00000008;  { FPU only  }
-      OT_BITS80    = $00000010;
+      OT_BITS64    = $00000008;  { x86_64 and FPU }
+      OT_BITS80    = $00000010;  { FPU only  }
+      OT_FAR       = $00000020;  { this means 16:16 or 16:32, like in CALL/JMP }
+      OT_NEAR      = $00000040;
+      OT_SHORT     = $00000080;
 
+      { TODO: FAR/NEAR/SHORT are sizes too, they should be included into size mask,
+        but this requires adjusting the opcode table }
       OT_SIZE_MASK = $0000001F;  { all the size attributes  }
       OT_NON_SIZE  = longint(not OT_SIZE_MASK);
 
-      OT_FAR       = $00000020;  { this means 16:16 or 16:32, like in CALL/JMP }
-      OT_NEAR      = $00000040;
-      OT_SHORT     = $00000080;
+      { Bits 8..11: modifiers }
       OT_SIGNED    = $00000100;  { the operand need to be signed -128-127 }
-      OT_TO        = $00000200;  { operand is followed by a colon  }
-                                 { reverse effect in FADD, FSUB &c  }
-      OT_COLON     = $00000400;
+      OT_TO        = $00000200;  { reverse effect in FADD, FSUB &c  }
+      OT_COLON     = $00000400;  { operand is followed by a colon  }
+      OT_MODIFIER_MASK = $00000F00;
 
+      { Bits 12..15: type of operand }
       OT_REGISTER  = $00001000;
       OT_IMMEDIATE = $00002000;
-      OT_IMM8      = $00002001;
-      OT_IMM16     = $00002002;
-      OT_IMM32     = $00002004;
-      OT_IMM64     = $00002008;
-      OT_IMM80     = $00002010;
-      OT_REGMEM    = $00200000;  { for r/m, ie EA, operands  }
-      OT_REGNORM   = $00201000;  { 'normal' reg, qualifies as EA  }
-      OT_REG8      = $00201001;
-      OT_REG16     = $00201002;
-      OT_REG32     = $00201004;
-      OT_REG64     = $00201008;
-      OT_XMMREG    = $00201010;  { Katmai registers  }
-      OT_XMMRM     = $00200010;
-      OT_MMXREG    = $00201020;  { MMX registers  }
-      OT_MMXRM     = $00200020;
-      OT_MEMORY    = $00204000;  { register number in 'basereg'  }
-      OT_MEM8      = $00204001;
-      OT_MEM16     = $00204002;
-      OT_MEM32     = $00204004;
-      OT_MEM64     = $00204008;
-      OT_MEM80     = $00204010;
-      OT_FPUREG    = $01000000;  { floating point stack registers  }
-      OT_FPU0      = $01000800;  { FPU stack register zero  }
-      OT_REG_SMASK = $00070000;  { special register operands: these may be treated differently  }
-                                 { a mask for the following  }
-      OT_REG_ACCUM = $00211000;  { FUNCTION_RETURN_REG: AL, AX or EAX  }
-      OT_REG_AL    = $00211001;    { REG_ACCUM | BITSxx  }
-      OT_REG_AX    = $00211002;    { ditto  }
-      OT_REG_EAX   = $00211004;    { and again  }
+      OT_MEMORY    = $0000C000;  { always includes 'OT_REGMEM' bit as well }
+      OT_REGMEM    = $00008000;  { for r/m, ie EA, operands  }
+      OT_TYPE_MASK = OT_REGISTER or OT_IMMEDIATE or OT_MEMORY or OT_REGMEM;
+
+      OT_REGNORM   = OT_REGISTER or OT_REGMEM;  { 'normal' reg, qualifies as EA  }
+
+      { Bits 20..22, 24..26: register classes
+        otf_* consts are not used alone, only to build other constants. }
+      otf_reg_cdt  = $00100000;
+      otf_reg_gpr  = $00200000;
+      otf_reg_sreg = $00400000;
+      otf_reg_fpu  = $01000000;
+      otf_reg_mmx  = $02000000;
+      otf_reg_xmm  = $04000000;
+      { Bits 16..19: subclasses, meaning depends on classes field }
+      otf_sub0     = $00010000;
+      otf_sub1     = $00020000;
+      otf_sub2     = $00040000;
+      otf_sub3     = $00080000;
+      OT_REG_SMASK = otf_sub0 or otf_sub1 or otf_sub2 or otf_sub3;
+
+      { register class 0: CRx, DRx and TRx }
+      OT_REG_CDT   = OT_REGISTER or otf_reg_cdt or OT_BITS32;
+      OT_REG_CREG  = OT_REG_CDT or otf_sub0;  { CRn  }
+      OT_REG_DREG  = OT_REG_CDT or otf_sub1;  { DRn  }
+      OT_REG_TREG  = OT_REG_CDT or otf_sub2;  { TRn  }
+      OT_REG_CR4   = OT_REG_CDT or otf_sub3;  { CR4 (Pentium only)  }
+
+      { register class 1: general-purpose registers }
+      OT_REG_GPR   = OT_REGNORM or otf_reg_gpr;
+      OT_RM_GPR    = OT_REGMEM or otf_reg_gpr;
+      OT_REG8      = OT_REG_GPR or OT_BITS8;  { 8-bit GPR }
+      OT_REG16     = OT_REG_GPR or OT_BITS16;
+      OT_REG32     = OT_REG_GPR or OT_BITS32;
+      OT_REG64     = OT_REG_GPR or OT_BITS64;
+
+      { GPR subclass 0: accumulator: AL, AX, EAX or RAX }
+      OT_REG_ACCUM = OT_REG_GPR or otf_sub0;
+      OT_REG_AL    = OT_REG_ACCUM or OT_BITS8;
+      OT_REG_AX    = OT_REG_ACCUM or OT_BITS16;
+      OT_REG_EAX   = OT_REG_ACCUM or OT_BITS32;
 {$ifdef x86_64}
-      OT_REG_RAX   = $00211008;
+      OT_REG_RAX   = OT_REG_ACCUM or OT_BITS64;
 {$endif x86_64}
-      OT_REG_COUNT = $00221000;  { counter: CL, CX or ECX  }
-      OT_REG_CL    = $00221001;    { REG_COUNT | BITSxx  }
-      OT_REG_CX    = $00221002;    { ditto  }
-      OT_REG_ECX   = $00221004;    { another one  }
+      { GPR subclass 1: counter: CL, CX, ECX or RCX }
+      OT_REG_COUNT = OT_REG_GPR or otf_sub1;
+      OT_REG_CL    = OT_REG_COUNT or OT_BITS8;
+      OT_REG_CX    = OT_REG_COUNT or OT_BITS16;
+      OT_REG_ECX   = OT_REG_COUNT or OT_BITS32;
 {$ifdef x86_64}
-      OT_REG_RCX   = $00221008;
+      OT_REG_RCX   = OT_REG_COUNT or OT_BITS64;
 {$endif x86_64}
-      OT_REG_DX    = $00241002;
-      OT_REG_EDX   = $00241004;
-
-      OT_REG_SREG  = $00081002;  { any segment register  }
-      OT_REG_CS    = $01081002;  { CS  }
-      OT_REG_DESS  = $02081002;  { DS, ES, SS (non-CS 86 registers)  }
-      OT_REG_FSGS  = $04081002;  { FS, GS (386 extended registers)  }
-
-      OT_REG_CDT   = $00101004;  { CRn, DRn and TRn  }
-      OT_REG_CREG  = $08101004;  { CRn  }
-      OT_REG_CR4   = $08101404;  { CR4 (Pentium only)  }
-      OT_REG_DREG  = $10101004;  { DRn  }
-      OT_REG_TREG  = $20101004;  { TRn  }
-
-      OT_MEM_OFFS  = $00604000;  { special type of EA  }
-                                 { simple [address] offset  }
-      OT_ONENESS   = $00800000;  { special type of immediate operand  }
-                                 { so UNITY == IMMEDIATE | ONENESS  }
-      OT_UNITY     = $00802000;  { for shift/rotate instructions  }
+      { GPR subclass 2: data register: DL, DX, EDX or RDX }
+      OT_REG_DX    = OT_REG_GPR or otf_sub2 or OT_BITS16;
+      OT_REG_EDX   = OT_REG_GPR or otf_sub2 or OT_BITS32;
+
+      { register class 2: Segment registers }
+      OT_REG_SREG  = OT_REGISTER or otf_reg_sreg or OT_BITS16;
+      OT_REG_CS    = OT_REG_SREG or otf_sub0;  { CS  }
+      OT_REG_DESS  = OT_REG_SREG or otf_sub1;  { DS, ES, SS (non-CS 86 registers)  }
+      OT_REG_FSGS  = OT_REG_SREG or otf_sub2;  { FS, GS (386 extended registers)  }
+
+      { register class 3: FPU registers }
+      OT_FPUREG    = OT_REGISTER or otf_reg_fpu;
+      OT_FPU0      = OT_FPUREG or otf_sub0;    { FPU stack register zero  }
+
+      { register class 4: MMX (both reg and r/m) }
+      OT_MMXREG    = OT_REGNORM or otf_reg_mmx;
+      OT_MMXRM     = OT_REGMEM or otf_reg_mmx;
+
+      { register class 5: XMM (both reg and r/m) }
+      OT_XMMREG    = OT_REGNORM or otf_reg_xmm;
+      OT_XMMRM     = OT_REGMEM or otf_reg_xmm;
+
+      { Memory operands }
+      OT_MEM8      = OT_MEMORY or OT_BITS8;
+      OT_MEM16     = OT_MEMORY or OT_BITS16;
+      OT_MEM32     = OT_MEMORY or OT_BITS32;
+      OT_MEM64     = OT_MEMORY or OT_BITS64;
+      OT_MEM80     = OT_MEMORY or OT_BITS80;
+
+      OT_MEM_OFFS  = OT_MEMORY or otf_sub0;  { special type of EA  }
+                                             { simple [address] offset  }
+
+      { Matches any type of r/m operand }
+      OT_MEMORY_ANY = OT_MEMORY or OT_RM_GPR or OT_XMMRM or OT_MMXRM;
+
+      { Immediate operands }
+      OT_IMM8      = OT_IMMEDIATE or OT_BITS8;
+      OT_IMM16     = OT_IMMEDIATE or OT_BITS16;
+      OT_IMM32     = OT_IMMEDIATE or OT_BITS32;
+      OT_IMM64     = OT_IMMEDIATE or OT_BITS64;
+      OT_IMM80     = OT_IMMEDIATE or OT_BITS80;
+
+      OT_ONENESS   = otf_sub0;  { special type of immediate operand  }
+      OT_UNITY     = OT_IMMEDIATE or OT_ONENESS;  { for shift/rotate instructions  }
 
       { Size of the instruction table converted by nasmconv.pas }
 {$ifdef x86_64}
@@ -956,9 +999,9 @@ implementation
                     begin
                       { create ot field }
                       if (ot and OT_SIZE_MASK)=0 then
-                        ot:=OT_MEMORY or opsize_2_type[i,opsize]
+                        ot:=OT_MEMORY_ANY or opsize_2_type[i,opsize]
                       else
-                        ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+                        ot:=OT_MEMORY_ANY or (ot and OT_SIZE_MASK);
                       if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
                         ot:=ot or OT_MEM_OFFS;
                       { fix scalefactor }
@@ -1865,9 +1908,6 @@ implementation
        *                 to the register value of operand 0, 1 or 2
        * \13           - a literal byte follows in the code stream, to be added
        *                 to the condition code value of the instruction.
-       * \17           - encodes the literal byte 0. (Some compilers don't take
-       *                 kindly to a zero byte in the _middle_ of a compile time
-       *                 string constant, so I had to put this hack in.)
        * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
        * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
        * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2