Răsfoiți Sursa

+ added support for the parameterized versions of the x86 string instructions
(movs, cmps, scas, lods, stos, ins, outs) in the inline asm of the i8086, i386
and x86_64 targets. Both intel and at&t syntax is supported.
* NEC V20/V30 instruction 'ins' (available only on the i8086 target, because it
is incompatible with 386+ instructions) renamed 'nec_ins', to avoid conflict
with the 186+ 'ins' instruction.

git-svn-id: trunk@37446 -

nickysn 7 ani în urmă
părinte
comite
0fb79946a5

+ 6 - 0
.gitattributes

@@ -12382,6 +12382,12 @@ tests/test/tarrconstr7.pp svneol=native#text/pascal
 tests/test/tasm1.pp svneol=native#text/plain
 tests/test/tasm10.pp svneol=native#text/plain
 tests/test/tasm10a.pp svneol=native#text/plain
+tests/test/tasm11a.pp svneol=native#text/plain
+tests/test/tasm11b.pp svneol=native#text/plain
+tests/test/tasm11c.pp svneol=native#text/plain
+tests/test/tasm12a.pp svneol=native#text/plain
+tests/test/tasm12b.pp svneol=native#text/plain
+tests/test/tasm12c.pp svneol=native#text/plain
 tests/test/tasm2.inc svneol=native#text/plain
 tests/test/tasm2.pp svneol=native#text/plain
 tests/test/tasm2a.pp svneol=native#text/plain

+ 28 - 2
compiler/aasmtai.pas

@@ -2617,7 +2617,20 @@ implementation
 {$ifdef x86}
             { We allow this exception for x86, since overloading this would be
               too much of a a speed penalty}
-            if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
+            if (opcode=A_MOVS) or
+               (opcode=A_CMPS) or
+               (opcode=A_SCAS) or
+               (opcode=A_LODS) or
+               (opcode=A_STOS) or
+               (opcode=A_INS) or
+               (opcode=A_OUTS) then
+              begin
+                if ((ref^.base=NR_NO) or (getsupreg(ref^.base)<>RS_EDI)) and
+                   ((ref^.index=NR_NO) or (getsupreg(ref^.index)<>RS_EDI)) and
+                   (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
+                  segprefix:=ref^.segment;
+              end
+            else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
               segprefix:=ref^.segment;
 {$endif}
 {$ifndef llvm}
@@ -2691,7 +2704,20 @@ implementation
                   new(ref);
                   ref^:=o.ref^;
 {$ifdef x86}
-                  if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
+                  if (opcode=A_MOVS) or
+                     (opcode=A_CMPS) or
+                     (opcode=A_SCAS) or
+                     (opcode=A_LODS) or
+                     (opcode=A_STOS) or
+                     (opcode=A_INS) or
+                     (opcode=A_OUTS) then
+                    begin
+                      if ((ref^.base=NR_NO) or (getsupreg(ref^.base)<>RS_EDI)) and
+                         ((ref^.index=NR_NO) or (getsupreg(ref^.index)<>RS_EDI)) and
+                         (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
+                        segprefix:=ref^.segment;
+                    end
+                  else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
                     segprefix:=ref^.segment;
 {$endif x86}
                   if assigned(add_reg_instruction_hook) then

+ 7 - 0
compiler/i386/i386att.inc

@@ -386,6 +386,13 @@
 'cmov',
 'j',
 'set',
+'movs',
+'cmps',
+'scas',
+'lods',
+'stos',
+'ins',
+'outs',
 'addps',
 'addss',
 'andnps',

+ 7 - 0
compiler/i386/i386atts.inc

@@ -386,6 +386,13 @@ attsufNONE,
 attsufINT,
 attsufNONE,
 attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 7 - 0
compiler/i386/i386int.inc

@@ -386,6 +386,13 @@
 'cmov',
 'j',
 'set',
+'movs',
+'cmps',
+'scas',
+'lods',
+'stos',
+'ins',
+'outs',
 'addps',
 'addss',
 'andnps',

+ 1 - 1
compiler/i386/i386nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
-1955;
+1976;

+ 7 - 0
compiler/i386/i386op.inc

@@ -386,6 +386,13 @@ A_XCRYPTOFB,
 A_CMOVcc,
 A_Jcc,
 A_SETcc,
+A_MOVS,
+A_CMPS,
+A_SCAS,
+A_LODS,
+A_STOS,
+A_INS,
+A_OUTS,
 A_ADDPS,
 A_ADDSS,
 A_ANDNPS,

+ 7 - 0
compiler/i386/i386prop.inc

@@ -386,6 +386,13 @@
 (Ch: [Ch_ROp1, Ch_RWOp2, Ch_RFLAGScc]),
 (Ch: [Ch_RFLAGScc]),
 (Ch: [Ch_RFLAGScc, Ch_WOp1]),
+(Ch: [Ch_RWESI, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag]),
+(Ch: [Ch_RWESI, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_REAX, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_WEAX, Ch_RWESI, Ch_RDirFlag]),
+(Ch: [Ch_REAX, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag]),
+(Ch: [Ch_WMemEDI, Ch_RWEDI, Ch_REDX, Ch_RDirFlag]),
+(Ch: [Ch_All, Ch_RDirFlag]),
 (Ch: [Ch_Mop2, Ch_Rop1]),
 (Ch: [Ch_Mop2, Ch_Rop1]),
 (Ch: [Ch_Mop2, Ch_Rop1]),

+ 147 - 0
compiler/i386/i386tab.inc

@@ -5971,6 +5971,153 @@
     code    : #1#15#11#144#128;
     flags   : [if_386]
   ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #1#164;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #212#1#165;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #213#1#165;
+    flags   : [if_386,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #218#1#166;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #218#212#1#167;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #218#213#1#167;
+    flags   : [if_386,if_sm]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #218#1#174;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #218#212#1#175;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #218#213#1#175;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #1#172;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #212#1#173;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #213#1#173;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #1#170;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #212#1#171;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #213#1#171;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_reg_dx,ot_none,ot_none);
+    code    : #1#108;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_reg_dx,ot_none,ot_none);
+    code    : #212#1#109;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_reg_dx,ot_none,ot_none);
+    code    : #213#1#109;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #1#110;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #212#1#111;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #213#1#111;
+    flags   : [if_386]
+  ),
   (
     opcode  : A_ADDPS;
     ops     : 2;

+ 8 - 1
compiler/i8086/i8086att.inc

@@ -386,6 +386,13 @@
 'cmov',
 'j',
 'set',
+'movs',
+'cmps',
+'scas',
+'lods',
+'stos',
+'ins',
+'outs',
 'addps',
 'addss',
 'andnps',
@@ -970,7 +977,7 @@
 'clr1',
 'cmp4s',
 'ext',
-'ins',
+'nec_ins',
 'not1',
 'repc',
 'repnc',

+ 7 - 0
compiler/i8086/i8086atts.inc

@@ -386,6 +386,13 @@ attsufNONE,
 attsufINT,
 attsufNONE,
 attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 8 - 1
compiler/i8086/i8086int.inc

@@ -386,6 +386,13 @@
 'cmov',
 'j',
 'set',
+'movs',
+'cmps',
+'scas',
+'lods',
+'stos',
+'ins',
+'outs',
 'addps',
 'addss',
 'andnps',
@@ -970,7 +977,7 @@
 'clr1',
 'cmp4s',
 'ext',
-'ins',
+'nec_ins',
 'not1',
 'repc',
 'repnc',

+ 1 - 1
compiler/i8086/i8086nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
-1987;
+2008;

+ 8 - 1
compiler/i8086/i8086op.inc

@@ -386,6 +386,13 @@ A_XCRYPTOFB,
 A_CMOVcc,
 A_Jcc,
 A_SETcc,
+A_MOVS,
+A_CMPS,
+A_SCAS,
+A_LODS,
+A_STOS,
+A_INS,
+A_OUTS,
 A_ADDPS,
 A_ADDSS,
 A_ANDNPS,
@@ -970,7 +977,7 @@ A_BRKEM,
 A_CLR1,
 A_CMP4S,
 A_EXT,
-A_INS,
+A_NEC_INS,
 A_NOT1,
 A_REPC,
 A_REPNC,

+ 7 - 0
compiler/i8086/i8086prop.inc

@@ -386,6 +386,13 @@
 (Ch: [Ch_ROp1, Ch_RWOp2, Ch_RFLAGScc]),
 (Ch: [Ch_RFLAGScc]),
 (Ch: [Ch_RFLAGScc, Ch_WOp1]),
+(Ch: [Ch_RWESI, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag]),
+(Ch: [Ch_RWESI, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_REAX, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_WEAX, Ch_RWESI, Ch_RDirFlag]),
+(Ch: [Ch_REAX, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag]),
+(Ch: [Ch_WMemEDI, Ch_RWEDI, Ch_REDX, Ch_RDirFlag]),
+(Ch: [Ch_All, Ch_RDirFlag]),
 (Ch: [Ch_Mop2, Ch_Rop1]),
 (Ch: [Ch_Mop2, Ch_Rop1]),
 (Ch: [Ch_Mop2, Ch_Rop1]),

+ 149 - 2
compiler/i8086/i8086tab.inc

@@ -5999,6 +5999,153 @@
     code    : #1#15#11#144#128;
     flags   : [if_386]
   ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #1#164;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #212#1#165;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #213#1#165;
+    flags   : [if_386,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #218#1#166;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #218#212#1#167;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #218#213#1#167;
+    flags   : [if_386,if_sm]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #218#1#174;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #218#212#1#175;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #218#213#1#175;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #1#172;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #212#1#173;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #213#1#173;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #1#170;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #212#1#171;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #213#1#171;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_reg_dx,ot_none,ot_none);
+    code    : #1#108;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_reg_dx,ot_none,ot_none);
+    code    : #212#1#109;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_reg_dx,ot_none,ot_none);
+    code    : #213#1#109;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #1#110;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #212#1#111;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #213#1#111;
+    flags   : [if_386]
+  ),
   (
     opcode  : A_ADDPS;
     ops     : 2;
@@ -13021,14 +13168,14 @@
     flags   : [if_nec,if_sb,if_imm4,if_16bitonly]
   ),
   (
-    opcode  : A_INS;
+    opcode  : A_NEC_INS;
     ops     : 2;
     optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
     code    : #2#15#49#65;
     flags   : [if_nec,if_16bitonly]
   ),
   (
-    opcode  : A_INS;
+    opcode  : A_NEC_INS;
     ops     : 2;
     optypes : (ot_reg8,ot_immediate,ot_none,ot_none);
     code    : #2#15#57#128#21;

+ 63 - 59
compiler/x86/aasmcpu.pas

@@ -4037,71 +4037,75 @@ implementation
               else InternalError(777207);
             end
             else
-            case actMemCount of
-                0: ; // nothing todo
-                1: begin
-                     MRefInfo := msiUnkown;
-                     case actRegMemTypes and (OT_MMXRM OR OT_XMMRM OR OT_YMMRM) of
-                       OT_MMXRM: actMemSize := actMemSize or OT_BITS64;
-                       OT_XMMRM: actMemSize := actMemSize or OT_BITS128;
-                       OT_YMMRM: actMemSize := actMemSize or OT_BITS256;
-                     end;
-
-                     case actMemSize of
-                       0: MRefInfo := msiNoSize;
-                       OT_BITS8: MRefInfo := msiMem8;
-                       OT_BITS16: MRefInfo := msiMem16;
-                       OT_BITS32: MRefInfo := msiMem32;
-                       OT_BITS64: MRefInfo := msiMem64;
-                       OT_BITS128: MRefInfo := msiMem128;
-                       OT_BITS256: MRefInfo := msiMem256;
-                       OT_BITS80,
-                       OT_FAR,
-                       OT_NEAR,
-                       OT_SHORT: ; // ignore
-                       else
-                         begin
-                           bitcount := bitcnt(actMemSize);
-
-                           if bitcount > 1 then MRefInfo := msiMultiple
-                           else InternalError(777203);
+              begin
+                if (actMemCount=2) and ((AsmOp=A_MOVS) or (AsmOp=A_CMPS)) then
+                  actMemCount:=1;
+                case actMemCount of
+                    0: ; // nothing todo
+                    1: begin
+                         MRefInfo := msiUnkown;
+                         case actRegMemTypes and (OT_MMXRM OR OT_XMMRM OR OT_YMMRM) of
+                           OT_MMXRM: actMemSize := actMemSize or OT_BITS64;
+                           OT_XMMRM: actMemSize := actMemSize or OT_BITS128;
+                           OT_YMMRM: actMemSize := actMemSize or OT_BITS256;
                          end;
-                     end;
 
-                     if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
-                       begin
-                         InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
-                       end
-                     else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
-                       begin
-                         with InsTabMemRefSizeInfoCache^[AsmOp] do
-                         begin
-                           if ((MemRefSize = msiMem8)        OR (MRefInfo = msiMem8))   then MemRefSize := msiMultiple8
-                           else if ((MemRefSize = msiMem16)  OR (MRefInfo = msiMem16))  then MemRefSize := msiMultiple16
-                           else if ((MemRefSize = msiMem32)  OR (MRefInfo = msiMem32))  then MemRefSize := msiMultiple32
-                           else if ((MemRefSize = msiMem64)  OR (MRefInfo = msiMem64))  then MemRefSize := msiMultiple64
-                           else if ((MemRefSize = msiMem128) OR (MRefInfo = msiMem128)) then MemRefSize := msiMultiple128
-                           else if ((MemRefSize = msiMem256) OR (MRefInfo = msiMem256)) then MemRefSize := msiMultiple256
-                           else MemRefSize := msiMultiple;
+                         case actMemSize of
+                           0: MRefInfo := msiNoSize;
+                           OT_BITS8: MRefInfo := msiMem8;
+                           OT_BITS16: MRefInfo := msiMem16;
+                           OT_BITS32: MRefInfo := msiMem32;
+                           OT_BITS64: MRefInfo := msiMem64;
+                           OT_BITS128: MRefInfo := msiMem128;
+                           OT_BITS256: MRefInfo := msiMem256;
+                           OT_BITS80,
+                           OT_FAR,
+                           OT_NEAR,
+                           OT_SHORT: ; // ignore
+                           else
+                             begin
+                               bitcount := bitcnt(actMemSize);
+
+                               if bitcount > 1 then MRefInfo := msiMultiple
+                               else InternalError(777203);
+                             end;
                          end;
-                     end;
 
-                     if actRegCount > 0 then
-                       begin
-                         case actRegTypes and (OT_MMXREG or OT_XMMREG or OT_YMMREG) of
-                           OT_MMXREG: RegMMXSizeMask := RegMMXSizeMask or actMemSize;
-                           OT_XMMREG: RegXMMSizeMask := RegXMMSizeMask or actMemSize;
-                           OT_YMMREG: RegYMMSizeMask := RegYMMSizeMask or actMemSize;
-                                 else begin
-                                        RegMMXSizeMask := not(0);
-                                        RegXMMSizeMask := not(0);
-                                        RegYMMSizeMask := not(0);
-                                      end;
+                         if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize = msiUnkown then
+                           begin
+                             InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize := MRefInfo;
+                           end
+                         else if InsTabMemRefSizeInfoCache^[AsmOp].MemRefSize <> MRefInfo then
+                           begin
+                             with InsTabMemRefSizeInfoCache^[AsmOp] do
+                             begin
+                               if ((MemRefSize = msiMem8)        OR (MRefInfo = msiMem8))   then MemRefSize := msiMultiple8
+                               else if ((MemRefSize = msiMem16)  OR (MRefInfo = msiMem16))  then MemRefSize := msiMultiple16
+                               else if ((MemRefSize = msiMem32)  OR (MRefInfo = msiMem32))  then MemRefSize := msiMultiple32
+                               else if ((MemRefSize = msiMem64)  OR (MRefInfo = msiMem64))  then MemRefSize := msiMultiple64
+                               else if ((MemRefSize = msiMem128) OR (MRefInfo = msiMem128)) then MemRefSize := msiMultiple128
+                               else if ((MemRefSize = msiMem256) OR (MRefInfo = msiMem256)) then MemRefSize := msiMultiple256
+                               else MemRefSize := msiMultiple;
+                             end;
                          end;
+
+                         if actRegCount > 0 then
+                           begin
+                             case actRegTypes and (OT_MMXREG or OT_XMMREG or OT_YMMREG) of
+                               OT_MMXREG: RegMMXSizeMask := RegMMXSizeMask or actMemSize;
+                               OT_XMMREG: RegXMMSizeMask := RegXMMSizeMask or actMemSize;
+                               OT_YMMREG: RegYMMSizeMask := RegYMMSizeMask or actMemSize;
+                                     else begin
+                                            RegMMXSizeMask := not(0);
+                                            RegXMMSizeMask := not(0);
+                                            RegYMMSizeMask := not(0);
+                                          end;
+                             end;
+                           end;
                        end;
-                   end;
-              else InternalError(777202);
-            end;
+                  else InternalError(777202);
+                end;
+              end;
 
             inc(insentry);
           end;

+ 57 - 0
compiler/x86/agx86nsm.pas

@@ -635,6 +635,7 @@ interface
       prevfileinfo : tfileposinfo;
       previnfile : tinputfile;
       NewObject :  boolean;
+      tmpreg: TRegister;
     begin
       if not assigned(p) then
        exit;
@@ -985,6 +986,62 @@ interface
                     end;
                if fixed_opcode=A_FWAIT then
                 writer.AsmWriteln(#9#9'DB'#9'09bh')
+               else if (fixed_opcode=A_MOVS) or
+                       (fixed_opcode=A_CMPS) or
+                       (fixed_opcode=A_SCAS) or
+                       (fixed_opcode=A_LODS) or
+                       (fixed_opcode=A_STOS) or
+                       (fixed_opcode=A_INS) or
+                       (fixed_opcode=A_OUTS) then
+                begin
+                  writer.AsmWrite(#9#9);
+                  case fixed_opcode of
+                    A_MOVS,A_OUTS:
+                      i:=1;
+                    A_CMPS,A_LODS:
+                      i:=0;
+                    A_SCAS,A_STOS,A_INS:
+                      i:=-1;
+                    else
+                      internalerror(2017101102);
+                  end;
+                  if (i<>-1) and (taicpu(hp).oper[i]^.typ=top_ref) and
+                     (taicpu(hp).oper[i]^.ref^.segment<>NR_NO) then
+                    writer.AsmWrite(std_regname(taicpu(hp).oper[i]^.ref^.segment)+' ');
+                  for i:=0 to taicpu(hp).ops-1 do
+                    if taicpu(hp).oper[i]^.typ=top_ref then
+                      begin
+                        tmpreg:=NR_NO;
+                        if taicpu(hp).oper[i]^.ref^.base<>NR_NO then
+                          tmpreg:=taicpu(hp).oper[i]^.ref^.base
+                        else if taicpu(hp).oper[i]^.ref^.index<>NR_NO then
+                          tmpreg:=taicpu(hp).oper[i]^.ref^.index;
+                        case reg2opsize(tmpreg) of
+                          S_W:
+                            writer.AsmWrite('a16 ');
+                          S_L:
+                            writer.AsmWrite('a32 ');
+                          S_Q:
+                            writer.AsmWrite('a64 ');
+                        end;
+                        break;
+                      end;
+                  writer.AsmWrite(std_op2str[fixed_opcode]);
+
+                  case taicpu(hp).opsize of
+                    S_B:
+                      writer.AsmWrite('b');
+                    S_W:
+                      writer.AsmWrite('w');
+                    S_L:
+                      writer.AsmWrite('d');
+                    S_Q:
+                      writer.AsmWrite('q');
+                    else
+                      internalerror(2017101101);
+                  end;
+                  writer.AsmLn;
+                end
                else
                 begin
                   prefix:='';

+ 163 - 0
compiler/x86/rax86att.pas

@@ -874,6 +874,165 @@ Implementation
           end; { end case }
         until false;
         instr.Ops:=operandnum;
+        { handle string instructions with memory arguments }
+        with instr do
+          if Ops=2 then
+            begin
+              case opcode of
+                A_MOVSB:
+                  begin
+                    opcode:=A_MOVS;
+                    opsize:=S_B;
+                  end;
+                A_MOVSW:
+                  begin
+                    opcode:=A_MOVS;
+                    opsize:=S_W;
+                  end;
+                A_MOVSD:
+                  begin
+                    { distinguish between MOVS and the SSE MOVSD instruction:
+                      MOVS must have memory 2 reference operands }
+                    if (operands[1].opr.typ=OPR_REFERENCE) and (operands[2].opr.typ=OPR_REFERENCE) then
+                      begin
+                        opcode:=A_MOVS;
+                        opsize:=S_L;
+                      end;
+                  end;
+{$ifdef x86_64}
+                A_MOVSQ:
+                  begin
+                    opcode:=A_MOVS;
+                    opsize:=S_Q;
+                  end;
+{$endif x86_64}
+                A_CMPSB:
+                  begin
+                    opcode:=A_CMPS;
+                    opsize:=S_B;
+                  end;
+                A_CMPSW:
+                  begin
+                    opcode:=A_CMPS;
+                    opsize:=S_W;
+                  end;
+                A_CMPSD:
+                  begin
+                    { no need to distinguish from SSE CMPSD, because the SSE
+                      version has 3 arguments }
+                    opcode:=A_CMPS;
+                    opsize:=S_L;
+                  end;
+{$ifdef x86_64}
+                A_CMPSQ:
+                  begin
+                    opcode:=A_CMPS;
+                    opsize:=S_Q;
+                  end;
+{$endif x86_64}
+                A_INSB:
+                  begin
+                    opcode:=A_INS;
+                    opsize:=S_B;
+                  end;
+                A_INSW:
+                  begin
+                    opcode:=A_INS;
+                    opsize:=S_W;
+                  end;
+                A_INSD:
+                  begin
+                    opcode:=A_INS;
+                    opsize:=S_L;
+                  end;
+                A_OUTSB:
+                  begin
+                    opcode:=A_OUTS;
+                    opsize:=S_B;
+                  end;
+                A_OUTSW:
+                  begin
+                    opcode:=A_OUTS;
+                    opsize:=S_W;
+                  end;
+                A_OUTSD:
+                  begin
+                    opcode:=A_OUTS;
+                    opsize:=S_L;
+                  end;
+              end;
+            end
+          else if Ops=1 then
+            begin
+              case opcode of
+                A_SCASB:
+                  begin
+                    opcode:=A_SCAS;
+                    opsize:=S_B;
+                  end;
+                A_SCASW:
+                  begin
+                    opcode:=A_SCAS;
+                    opsize:=S_W;
+                  end;
+                A_SCASD:
+                  begin
+                    opcode:=A_SCAS;
+                    opsize:=S_L;
+                  end;
+{$ifdef x86_64}
+                A_SCASQ:
+                  begin
+                    opcode:=A_SCAS;
+                    opsize:=S_Q;
+                  end;
+{$endif x86_64}
+                A_LODSB:
+                  begin
+                    opcode:=A_LODS;
+                    opsize:=S_B;
+                  end;
+                A_LODSW:
+                  begin
+                    opcode:=A_LODS;
+                    opsize:=S_W;
+                  end;
+                A_LODSD:
+                  begin
+                    opcode:=A_LODS;
+                    opsize:=S_L;
+                  end;
+{$ifdef x86_64}
+                A_LODSQ:
+                  begin
+                    opcode:=A_LODS;
+                    opsize:=S_Q;
+                  end;
+{$endif x86_64}
+                A_STOSB:
+                  begin
+                    opcode:=A_STOS;
+                    opsize:=S_B;
+                  end;
+                A_STOSW:
+                  begin
+                    opcode:=A_STOS;
+                    opsize:=S_W;
+                  end;
+                A_STOSD:
+                  begin
+                    opcode:=A_STOS;
+                    opsize:=S_L;
+                  end;
+{$ifdef x86_64}
+                A_STOSQ:
+                  begin
+                    opcode:=A_STOS;
+                    opsize:=S_Q;
+                  end;
+{$endif x86_64}
+              end;
+            end;
       end;
 
 
@@ -912,6 +1071,10 @@ Implementation
                   { cmpsd also needs special handling for pretty much the same reasons as movsd }
                   if (actopcode = A_NONE) and (upper(s) = 'CMPSD') then
                     actopcode := A_CMPSD;
+                  { disambiguation between A_MOVS (movsb/movsw/movsl/movsq) and
+                    A_MOVSX (movsbw/movsbl/movswl/movsbq/movswq) }
+                  if (actopcode = A_MOVS) and (suflen=2) then
+                    actopcode := A_MOVSX;
 
                   { two-letter suffix is allowed by just a few instructions (movsx,movzx),
                     and it is always required whenever allowed }

+ 49 - 1
compiler/x86/x86ins.dat

@@ -2134,6 +2134,54 @@ imm16|near            \23\x70\1\x03\1\xE9\60         8086,PASS2,16BITONLY
 (Ch_RFLAGScc, Ch_WOp1)
 rm8                   \1\x0F\13\x90\200              386
 
+; Alternate syntax of string instructions (with memory operands)
+[MOVS,movsX]
+(Ch_RWESI, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag)
+mem8,mem8             \1\xA4                          8086,SM
+mem16,mem16           \324\1\xA5                      8086,SM
+mem32,mem32           \325\1\xA5                      386,SM
+mem64,mem64           \326\1\xA5                      X86_64,SM
+
+[CMPS,cmpsX]
+(Ch_RWESI, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag)
+mem8,mem8             \332\1\xA6                      8086,SM
+mem16,mem16           \332\324\1\xA7                  8086,SM
+mem32,mem32           \332\325\1\xA7                  386,SM
+mem64,mem64           \326\1\xA7                      X86_64,SM
+
+[SCAS,scasX]
+(Ch_REAX, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag)
+mem8                  \332\1\xAE                      8086
+mem16                 \332\324\1\xAF                  8086
+mem32                 \332\325\1\xAF                  386
+mem64                 \332\326\1\xAF                  X86_64
+
+[LODS,lodsX]
+(Ch_WEAX, Ch_RWESI, Ch_RDirFlag)
+mem8                  \1\xAC                          8086
+mem16                 \324\1\xAD                      8086
+mem32                 \325\1\xAD                      386
+mem64                 \326\1\xAD                      X86_64
+
+[STOS,stosX]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag)
+mem8                  \1\xAA                          8086
+mem16                 \324\1\xAB                      8086
+mem32                 \325\1\xAB                      386
+mem64                 \326\1\xAB                      X86_64
+
+[INS,insX]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX, Ch_RDirFlag)
+mem8,reg_dx           \1\x6C                          186
+mem16,reg_dx          \324\1\x6D                      186
+mem32,reg_dx          \325\1\x6D                      386
+
+[OUTS,outsX]
+(Ch_All, Ch_RDirFlag)
+reg_dx,mem8           \1\x6E                          186
+reg_dx,mem16          \324\1\x6F                      186
+reg_dx,mem32          \325\1\x6F                      386
+
 ;
 ; Katmai Streaming SIMD instructions (SSE -- a.k.a. KNI, XMM, MMX2)
 ;
@@ -5072,7 +5120,7 @@ reg8,imm                              \2\x0F\x3B\200\25                   NEC,SB
 
 ;[FPO2]
 
-[INS]
+[NEC_INS]
 (Ch_All)
 reg8,reg8                             \2\x0F\x31\101                      NEC,16BITONLY
 reg8,imm                              \2\x0F\x39\200\25                   NEC,SB,IMM4,16BITONLY

+ 7 - 0
compiler/x86_64/x8664ats.inc

@@ -371,6 +371,13 @@ attsufNONE,
 attsufINT,
 attsufNONE,
 attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
 attsufNONE,
 attsufNONE,
 attsufNONE,

+ 7 - 0
compiler/x86_64/x8664att.inc

@@ -371,6 +371,13 @@
 'cmov',
 'j',
 'set',
+'movs',
+'cmps',
+'scas',
+'lods',
+'stos',
+'ins',
+'outs',
 'addps',
 'addss',
 'andnps',

+ 7 - 0
compiler/x86_64/x8664int.inc

@@ -371,6 +371,13 @@
 'cmov',
 'j',
 'set',
+'movs',
+'cmps',
+'scas',
+'lods',
+'stos',
+'ins',
+'outs',
 'addps',
 'addss',
 'andnps',

+ 1 - 1
compiler/x86_64/x8664nop.inc

@@ -1,2 +1,2 @@
 { don't edit, this file is generated from x86ins.dat }
-2001;
+2027;

+ 7 - 0
compiler/x86_64/x8664op.inc

@@ -371,6 +371,13 @@ A_XCRYPTOFB,
 A_CMOVcc,
 A_Jcc,
 A_SETcc,
+A_MOVS,
+A_CMPS,
+A_SCAS,
+A_LODS,
+A_STOS,
+A_INS,
+A_OUTS,
 A_ADDPS,
 A_ADDSS,
 A_ANDNPS,

+ 7 - 0
compiler/x86_64/x8664pro.inc

@@ -371,6 +371,13 @@
 (Ch: [Ch_ROp1, Ch_RWOp2, Ch_RFLAGScc]),
 (Ch: [Ch_RFLAGScc]),
 (Ch: [Ch_RFLAGScc, Ch_WOp1]),
+(Ch: [Ch_RWESI, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag]),
+(Ch: [Ch_RWESI, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_REAX, Ch_RMemEDI, Ch_RWEDI, Ch_RDirFlag, Ch_WOverflowFlag, Ch_WSignFlag, Ch_WZeroFlag, Ch_WAuxiliaryFlag, Ch_WCarryFlag, Ch_WParityFlag]),
+(Ch: [Ch_WEAX, Ch_RWESI, Ch_RDirFlag]),
+(Ch: [Ch_REAX, Ch_WMemEDI, Ch_RWEDI, Ch_RDirFlag]),
+(Ch: [Ch_WMemEDI, Ch_RWEDI, Ch_REDX, Ch_RDirFlag]),
+(Ch: [Ch_All, Ch_RDirFlag]),
 (Ch: [Ch_Mop2, Ch_Rop1]),
 (Ch: [Ch_Mop2, Ch_Rop1]),
 (Ch: [Ch_Mop2, Ch_Rop1]),

+ 182 - 0
compiler/x86_64/x8664tab.inc

@@ -6055,6 +6055,188 @@
     code    : #1#15#11#144#128;
     flags   : [if_386]
   ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #1#164;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #212#1#165;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #213#1#165;
+    flags   : [if_386,if_sm]
+  ),
+  (
+    opcode  : A_MOVS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits64,ot_memory or ot_bits64,ot_none,ot_none);
+    code    : #214#1#165;
+    flags   : [if_x86_64,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #218#1#166;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #218#212#1#167;
+    flags   : [if_8086,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #218#213#1#167;
+    flags   : [if_386,if_sm]
+  ),
+  (
+    opcode  : A_CMPS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits64,ot_memory or ot_bits64,ot_none,ot_none);
+    code    : #214#1#167;
+    flags   : [if_x86_64,if_sm]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #218#1#174;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #218#212#1#175;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #218#213#1#175;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_SCAS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+    code    : #218#214#1#175;
+    flags   : [if_x86_64]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #1#172;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #212#1#173;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #213#1#173;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_LODS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+    code    : #214#1#173;
+    flags   : [if_x86_64]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits8,ot_none,ot_none,ot_none);
+    code    : #1#170;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+    code    : #212#1#171;
+    flags   : [if_8086]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+    code    : #213#1#171;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_STOS;
+    ops     : 1;
+    optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+    code    : #214#1#171;
+    flags   : [if_x86_64]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits8,ot_reg_dx,ot_none,ot_none);
+    code    : #1#108;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits16,ot_reg_dx,ot_none,ot_none);
+    code    : #212#1#109;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_INS;
+    ops     : 2;
+    optypes : (ot_memory or ot_bits32,ot_reg_dx,ot_none,ot_none);
+    code    : #213#1#109;
+    flags   : [if_386]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits8,ot_none,ot_none);
+    code    : #1#110;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits16,ot_none,ot_none);
+    code    : #212#1#111;
+    flags   : [if_186]
+  ),
+  (
+    opcode  : A_OUTS;
+    ops     : 2;
+    optypes : (ot_reg_dx,ot_memory or ot_bits32,ot_none,ot_none);
+    code    : #213#1#111;
+    flags   : [if_386]
+  ),
   (
     opcode  : A_ADDPS;
     ops     : 2;

+ 100 - 0
tests/test/tasm11a.pp

@@ -0,0 +1,100 @@
+{ %CPU=x86_64 }
+{ %NORUN }
+
+{$asmmode att}
+
+begin
+  asm
+    movsb
+    movsw
+    movsl
+    movsq
+
+    cmpsb
+    cmpsw
+    cmpsl
+    cmpsq
+
+    scasb
+    scasw
+    scasl
+    scasq
+
+    lodsb
+    lodsw
+    lodsl
+    lodsq
+
+    stosb
+    stosw
+    stosl
+    stosq
+
+    insb
+    insw
+    insl
+
+    outsb
+    outsw
+    outsl
+
+    movsb (%rsi), (%rdi)
+    movsb (%esi), (%edi)
+    movsw (%rsi), (%rdi)
+    movsw (%esi), (%edi)
+    movsl (%rsi), (%rdi)
+    movsl (%esi), (%edi)
+    movsq (%rsi), (%rdi)
+    movsq (%esi), (%edi)
+
+    cmpsb (%rdi), (%rsi)
+    cmpsb (%edi), (%esi)
+    cmpsw (%rdi), (%rsi)
+    cmpsw (%edi), (%esi)
+    cmpsl (%rdi), (%rsi)
+    cmpsl (%edi), (%esi)
+    cmpsq (%rdi), (%rsi)
+    cmpsq (%edi), (%esi)
+
+    scasb (%rdi)
+    scasb (%edi)
+    scasw (%rdi)
+    scasw (%edi)
+    scasl (%rdi)
+    scasl (%edi)
+    scasq (%rdi)
+    scasq (%edi)
+
+    lodsb (%rsi)
+    lodsb (%esi)
+    lodsw (%rsi)
+    lodsw (%esi)
+    lodsl (%rsi)
+    lodsl (%esi)
+    lodsq (%rsi)
+    lodsq (%esi)
+
+    stosb (%rdi)
+    stosb (%edi)
+    stosw (%rdi)
+    stosw (%edi)
+    stosl (%rdi)
+    stosl (%edi)
+    stosq (%rdi)
+    stosq (%edi)
+
+    insb %dx,(%rdi)
+    insb %dx,(%edi)
+    insw %dx,(%rdi)
+    insw %dx,(%edi)
+    insl %dx,(%rdi)
+    insl %dx,(%edi)
+
+    outsb (%rsi),%dx
+    outsb (%esi),%dx
+    outsw (%rsi),%dx
+    outsw (%esi),%dx
+    outsl (%rsi),%dx
+    outsl (%esi),%dx
+  end;
+end.

+ 85 - 0
tests/test/tasm11b.pp

@@ -0,0 +1,85 @@
+{ %CPU=i386 }
+{ %NORUN }
+
+{$asmmode att}
+
+begin
+  asm
+    movsb
+    movsw
+    movsl
+
+    cmpsb
+    cmpsw
+    cmpsl
+
+    scasb
+    scasw
+    scasl
+
+    lodsb
+    lodsw
+    lodsl
+
+    stosb
+    stosw
+    stosl
+
+    insb
+    insw
+    insl
+
+    outsb
+    outsw
+    outsl
+
+    movsb (%esi), (%edi)
+    movsb (%si), (%di)
+    movsw (%esi), (%edi)
+    movsw (%si), (%di)
+    movsl (%esi), (%edi)
+    movsl (%si), (%di)
+
+    cmpsb (%edi), (%esi)
+    cmpsb (%di), (%si)
+    cmpsw (%edi), (%esi)
+    cmpsw (%di), (%si)
+    cmpsl (%edi), (%esi)
+    cmpsl (%di), (%si)
+
+    scasb (%edi)
+    scasb (%di)
+    scasw (%edi)
+    scasw (%di)
+    scasl (%edi)
+    scasl (%di)
+
+    lodsb (%esi)
+    lodsb (%si)
+    lodsw (%esi)
+    lodsw (%si)
+    lodsl (%esi)
+    lodsl (%si)
+
+    stosb (%edi)
+    stosb (%di)
+    stosw (%edi)
+    stosw (%di)
+    stosl (%edi)
+    stosl (%di)
+
+    insb %dx,(%edi)
+    insb %dx,(%di)
+    insw %dx,(%edi)
+    insw %dx,(%di)
+    insl %dx,(%edi)
+    insl %dx,(%di)
+
+    outsb (%esi),%dx
+    outsb (%si),%dx
+    outsw (%esi),%dx
+    outsw (%si),%dx
+    outsl (%esi),%dx
+    outsl (%si),%dx
+  end;
+end.

+ 86 - 0
tests/test/tasm11c.pp

@@ -0,0 +1,86 @@
+{ %CPU=i8086 }
+{ %NORUN }
+
+{$asmmode att}
+{$asmcpu 80386}
+
+begin
+  asm
+    movsb
+    movsw
+    movsl
+
+    cmpsb
+    cmpsw
+    cmpsl
+
+    scasb
+    scasw
+    scasl
+
+    lodsb
+    lodsw
+    lodsl
+
+    stosb
+    stosw
+    stosl
+
+    insb
+    insw
+    insl
+
+    outsb
+    outsw
+    outsl
+
+    movsb (%esi), (%edi)
+    movsb (%si), (%di)
+    movsw (%esi), (%edi)
+    movsw (%si), (%di)
+    movsl (%esi), (%edi)
+    movsl (%si), (%di)
+
+    cmpsb (%edi), (%esi)
+    cmpsb (%di), (%si)
+    cmpsw (%edi), (%esi)
+    cmpsw (%di), (%si)
+    cmpsl (%edi), (%esi)
+    cmpsl (%di), (%si)
+
+    scasb (%edi)
+    scasb (%di)
+    scasw (%edi)
+    scasw (%di)
+    scasl (%edi)
+    scasl (%di)
+
+    lodsb (%esi)
+    lodsb (%si)
+    lodsw (%esi)
+    lodsw (%si)
+    lodsl (%esi)
+    lodsl (%si)
+
+    stosb (%edi)
+    stosb (%di)
+    stosw (%edi)
+    stosw (%di)
+    stosl (%edi)
+    stosl (%di)
+
+    insb %dx,(%edi)
+    insb %dx,(%di)
+    insw %dx,(%edi)
+    insw %dx,(%di)
+    insl %dx,(%edi)
+    insl %dx,(%di)
+
+    outsb (%esi),%dx
+    outsb (%si),%dx
+    outsw (%esi),%dx
+    outsw (%si),%dx
+    outsl (%esi),%dx
+    outsl (%si),%dx
+  end;
+end.

+ 222 - 0
tests/test/tasm12a.pp

@@ -0,0 +1,222 @@
+{ %CPU=x86_64 }
+{ %NORUN }
+
+{$asmmode intel}
+
+begin
+  asm
+    { no params }
+    movsb
+    movsw
+    movsd
+    movsq
+
+    cmpsb
+    cmpsw
+    cmpsd
+    cmpsq
+
+    scasb
+    scasw
+    scasd
+    scasq
+
+    lodsb
+    lodsw
+    lodsd
+    lodsq
+
+    stosb
+    stosw
+    stosd
+    stosq
+
+    insb
+    insw
+    insd
+
+    outsb
+    outsw
+    outsd
+
+    { no segment overrides }
+    movs byte ptr [rdi], byte ptr [rsi]
+    movs byte ptr [edi], byte ptr [esi]
+    movs word ptr [rdi], word ptr [rsi]
+    movs word ptr [edi], word ptr [esi]
+    movs dword ptr [rdi], dword ptr [rsi]
+    movs dword ptr [edi], dword ptr [esi]
+    movs qword ptr [rdi], qword ptr [rsi]
+    movs qword ptr [edi], qword ptr [esi]
+
+    cmps byte ptr [rsi], byte ptr [rdi]
+    cmps byte ptr [esi], byte ptr [edi]
+    cmps word ptr [rsi], word ptr [rdi]
+    cmps word ptr [esi], word ptr [edi]
+    cmps dword ptr [rsi], dword ptr [rdi]
+    cmps dword ptr [esi], dword ptr [edi]
+    cmps qword ptr [rsi], qword ptr [rdi]
+    cmps qword ptr [esi], qword ptr [edi]
+
+    scas byte ptr [rdi]
+    scas byte ptr [edi]
+    scas word ptr [rdi]
+    scas word ptr [edi]
+    scas dword ptr [rdi]
+    scas dword ptr [edi]
+    scas qword ptr [rdi]
+    scas qword ptr [edi]
+
+    lods byte ptr [rsi]
+    lods byte ptr [esi]
+    lods word ptr [rsi]
+    lods word ptr [esi]
+    lods dword ptr [rsi]
+    lods dword ptr [esi]
+    lods qword ptr [rsi]
+    lods qword ptr [esi]
+
+    stos byte ptr [rdi]
+    stos byte ptr [edi]
+    stos word ptr [rdi]
+    stos word ptr [edi]
+    stos dword ptr [rdi]
+    stos dword ptr [edi]
+    stos qword ptr [rdi]
+    stos qword ptr [edi]
+
+    ins byte ptr [rdi], dx
+    ins byte ptr [edi], dx
+    ins word ptr [rdi], dx
+    ins word ptr [edi], dx
+    ins dword ptr [rdi], dx
+    ins dword ptr [edi], dx
+
+    outs dx, byte ptr [rsi]
+    outs dx, byte ptr [esi]
+    outs dx, word ptr [rsi]
+    outs dx, word ptr [esi]
+    outs dx, dword ptr [rsi]
+    outs dx, dword ptr [esi]
+
+    { es:di }
+    movs byte ptr es:[rdi], byte ptr [rsi]
+    movs byte ptr es:[edi], byte ptr [esi]
+    movs word ptr es:[rdi], word ptr [rsi]
+    movs word ptr es:[edi], word ptr [esi]
+    movs dword ptr es:[rdi], dword ptr [rsi]
+    movs dword ptr es:[edi], dword ptr [esi]
+    movs qword ptr es:[rdi], qword ptr [rsi]
+    movs qword ptr es:[edi], qword ptr [esi]
+
+    cmps byte ptr [rsi], byte ptr es:[rdi]
+    cmps byte ptr [esi], byte ptr es:[edi]
+    cmps word ptr [rsi], word ptr es:[rdi]
+    cmps word ptr [esi], word ptr es:[edi]
+    cmps dword ptr [rsi], dword ptr es:[rdi]
+    cmps dword ptr [esi], dword ptr es:[edi]
+    cmps qword ptr [rsi], qword ptr es:[rdi]
+    cmps qword ptr [esi], qword ptr es:[edi]
+
+    scas byte ptr es:[rdi]
+    scas byte ptr es:[edi]
+    scas word ptr es:[rdi]
+    scas word ptr es:[edi]
+    scas dword ptr es:[rdi]
+    scas dword ptr es:[edi]
+    scas qword ptr es:[rdi]
+    scas qword ptr es:[edi]
+
+    lods byte ptr [rsi]
+    lods byte ptr [esi]
+    lods word ptr [rsi]
+    lods word ptr [esi]
+    lods dword ptr [rsi]
+    lods dword ptr [esi]
+    lods qword ptr [rsi]
+    lods qword ptr [esi]
+
+    stos byte ptr es:[rdi]
+    stos byte ptr es:[edi]
+    stos word ptr es:[rdi]
+    stos word ptr es:[edi]
+    stos dword ptr es:[rdi]
+    stos dword ptr es:[edi]
+    stos qword ptr es:[rdi]
+    stos qword ptr es:[edi]
+
+    ins byte ptr es:[rdi], dx
+    ins byte ptr es:[edi], dx
+    ins word ptr es:[rdi], dx
+    ins word ptr es:[edi], dx
+    ins dword ptr es:[rdi], dx
+    ins dword ptr es:[edi], dx
+
+    outs dx, byte ptr [rsi]
+    outs dx, byte ptr [esi]
+    outs dx, word ptr [rsi]
+    outs dx, word ptr [esi]
+    outs dx, dword ptr [rsi]
+    outs dx, dword ptr [esi]
+
+    { es:di, fs:si }
+    movs byte ptr es:[rdi], byte ptr fs:[rsi]
+    movs byte ptr es:[edi], byte ptr fs:[esi]
+    movs word ptr es:[rdi], word ptr fs:[rsi]
+    movs word ptr es:[edi], word ptr fs:[esi]
+    movs dword ptr es:[rdi], dword ptr fs:[rsi]
+    movs dword ptr es:[edi], dword ptr fs:[esi]
+    movs qword ptr es:[rdi], qword ptr fs:[rsi]
+    movs qword ptr es:[edi], qword ptr fs:[esi]
+
+    cmps byte ptr fs:[rsi], byte ptr es:[rdi]
+    cmps byte ptr fs:[esi], byte ptr es:[edi]
+    cmps word ptr fs:[rsi], word ptr es:[rdi]
+    cmps word ptr fs:[esi], word ptr es:[edi]
+    cmps dword ptr fs:[rsi], dword ptr es:[rdi]
+    cmps dword ptr fs:[esi], dword ptr es:[edi]
+    cmps qword ptr fs:[rsi], qword ptr es:[rdi]
+    cmps qword ptr fs:[esi], qword ptr es:[edi]
+
+    scas byte ptr es:[rdi]
+    scas byte ptr es:[edi]
+    scas word ptr es:[rdi]
+    scas word ptr es:[edi]
+    scas dword ptr es:[rdi]
+    scas dword ptr es:[edi]
+    scas qword ptr es:[rdi]
+    scas qword ptr es:[edi]
+
+    lods byte ptr fs:[rsi]
+    lods byte ptr fs:[esi]
+    lods word ptr fs:[rsi]
+    lods word ptr fs:[esi]
+    lods dword ptr fs:[rsi]
+    lods dword ptr fs:[esi]
+    lods qword ptr fs:[rsi]
+    lods qword ptr fs:[esi]
+
+    stos byte ptr es:[rdi]
+    stos byte ptr es:[edi]
+    stos word ptr es:[rdi]
+    stos word ptr es:[edi]
+    stos dword ptr es:[rdi]
+    stos dword ptr es:[edi]
+    stos qword ptr es:[rdi]
+    stos qword ptr es:[edi]
+
+    ins byte ptr es:[rdi], dx
+    ins byte ptr es:[edi], dx
+    ins word ptr es:[rdi], dx
+    ins word ptr es:[edi], dx
+    ins dword ptr es:[rdi], dx
+    ins dword ptr es:[edi], dx
+
+    outs dx, byte ptr fs:[rsi]
+    outs dx, byte ptr fs:[esi]
+    outs dx, word ptr fs:[rsi]
+    outs dx, word ptr fs:[esi]
+    outs dx, dword ptr fs:[rsi]
+    outs dx, dword ptr fs:[esi]
+  end;
+end.

+ 187 - 0
tests/test/tasm12b.pp

@@ -0,0 +1,187 @@
+{ %CPU=i386 }
+{ %NORUN }
+
+{$asmmode intel}
+
+begin
+  asm
+    { no params }
+    movsb
+    movsw
+    movsd
+
+    cmpsb
+    cmpsw
+    cmpsd
+
+    scasb
+    scasw
+    scasd
+
+    lodsb
+    lodsw
+    lodsd
+
+    stosb
+    stosw
+    stosd
+
+    insb
+    insw
+    insd
+
+    outsb
+    outsw
+    outsd
+
+    { no segment overrides }
+    movs byte ptr [edi], byte ptr [esi]
+    movs byte ptr [di], byte ptr [si]
+    movs word ptr [edi], word ptr [esi]
+    movs word ptr [di], word ptr [si]
+    movs dword ptr [edi], dword ptr [esi]
+    movs dword ptr [di], dword ptr [si]
+
+    cmps byte ptr [esi], byte ptr [edi]
+    cmps byte ptr [si], byte ptr [di]
+    cmps word ptr [esi], word ptr [edi]
+    cmps word ptr [si], word ptr [di]
+    cmps dword ptr [esi], dword ptr [edi]
+    cmps dword ptr [si], dword ptr [di]
+
+    scas byte ptr [edi]
+    scas byte ptr [di]
+    scas word ptr [edi]
+    scas word ptr [di]
+    scas dword ptr [edi]
+    scas dword ptr [di]
+
+    lods byte ptr [esi]
+    lods byte ptr [si]
+    lods word ptr [esi]
+    lods word ptr [si]
+    lods dword ptr [esi]
+    lods dword ptr [si]
+
+    stos byte ptr [edi]
+    stos byte ptr [di]
+    stos word ptr [edi]
+    stos word ptr [di]
+    stos dword ptr [edi]
+    stos dword ptr [di]
+
+    ins byte ptr [edi], dx
+    ins byte ptr [di], dx
+    ins word ptr [edi], dx
+    ins word ptr [di], dx
+    ins dword ptr [edi], dx
+    ins dword ptr [di], dx
+
+    outs dx, byte ptr [esi]
+    outs dx, byte ptr [si]
+    outs dx, word ptr [esi]
+    outs dx, word ptr [si]
+    outs dx, dword ptr [esi]
+    outs dx, dword ptr [si]
+
+    { es:di }
+    movs byte ptr es:[edi], byte ptr [esi]
+    movs byte ptr es:[di], byte ptr [si]
+    movs word ptr es:[edi], word ptr [esi]
+    movs word ptr es:[di], word ptr [si]
+    movs dword ptr es:[edi], dword ptr [esi]
+    movs dword ptr es:[di], dword ptr [si]
+
+    cmps byte ptr [esi], byte ptr es:[edi]
+    cmps byte ptr [si], byte ptr es:[di]
+    cmps word ptr [esi], word ptr es:[edi]
+    cmps word ptr [si], word ptr es:[di]
+    cmps dword ptr [esi], dword ptr es:[edi]
+    cmps dword ptr [si], dword ptr es:[di]
+
+    scas byte ptr es:[edi]
+    scas byte ptr es:[di]
+    scas word ptr es:[edi]
+    scas word ptr es:[di]
+    scas dword ptr es:[edi]
+    scas dword ptr es:[di]
+
+    lods byte ptr [esi]
+    lods byte ptr [si]
+    lods word ptr [esi]
+    lods word ptr [si]
+    lods dword ptr [esi]
+    lods dword ptr [si]
+
+    stos byte ptr es:[edi]
+    stos byte ptr es:[di]
+    stos word ptr es:[edi]
+    stos word ptr es:[di]
+    stos dword ptr es:[edi]
+    stos dword ptr es:[di]
+
+    ins byte ptr es:[edi], dx
+    ins byte ptr es:[di], dx
+    ins word ptr es:[edi], dx
+    ins word ptr es:[di], dx
+    ins dword ptr es:[edi], dx
+    ins dword ptr es:[di], dx
+
+    outs dx, byte ptr [esi]
+    outs dx, byte ptr [si]
+    outs dx, word ptr [esi]
+    outs dx, word ptr [si]
+    outs dx, dword ptr [esi]
+    outs dx, dword ptr [si]
+
+    { es:di, fs:si }
+    movs byte ptr es:[edi], byte ptr fs:[esi]
+    movs byte ptr es:[di], byte ptr fs:[si]
+    movs word ptr es:[edi], word ptr fs:[esi]
+    movs word ptr es:[di], word ptr fs:[si]
+    movs dword ptr es:[edi], dword ptr fs:[esi]
+    movs dword ptr es:[di], dword ptr fs:[si]
+
+    cmps byte ptr fs:[esi], byte ptr es:[edi]
+    cmps byte ptr fs:[si], byte ptr es:[di]
+    cmps word ptr fs:[esi], word ptr es:[edi]
+    cmps word ptr fs:[si], word ptr es:[di]
+    cmps dword ptr fs:[esi], dword ptr es:[edi]
+    cmps dword ptr fs:[si], dword ptr es:[di]
+
+    scas byte ptr es:[edi]
+    scas byte ptr es:[di]
+    scas word ptr es:[edi]
+    scas word ptr es:[di]
+    scas dword ptr es:[edi]
+    scas dword ptr es:[di]
+
+    lods byte ptr fs:[esi]
+    lods byte ptr fs:[si]
+    lods word ptr fs:[esi]
+    lods word ptr fs:[si]
+    lods dword ptr fs:[esi]
+    lods dword ptr fs:[si]
+
+    stos byte ptr es:[edi]
+    stos byte ptr es:[di]
+    stos word ptr es:[edi]
+    stos word ptr es:[di]
+    stos dword ptr es:[edi]
+    stos dword ptr es:[di]
+
+    ins byte ptr es:[edi], dx
+    ins byte ptr es:[di], dx
+    ins word ptr es:[edi], dx
+    ins word ptr es:[di], dx
+    ins dword ptr es:[edi], dx
+    ins dword ptr es:[di], dx
+
+    outs dx, byte ptr fs:[esi]
+    outs dx, byte ptr fs:[si]
+    outs dx, word ptr fs:[esi]
+    outs dx, word ptr fs:[si]
+    outs dx, dword ptr fs:[esi]
+    outs dx, dword ptr fs:[si]
+  end;
+end.

+ 188 - 0
tests/test/tasm12c.pp

@@ -0,0 +1,188 @@
+{ %CPU=i8086 }
+{ %NORUN }
+
+{$asmmode att}
+{$asmcpu 80386}
+
+begin
+  asm
+    { no params }
+    movsb
+    movsw
+    movsd
+
+    cmpsb
+    cmpsw
+    cmpsd
+
+    scasb
+    scasw
+    scasd
+
+    lodsb
+    lodsw
+    lodsd
+
+    stosb
+    stosw
+    stosd
+
+    insb
+    insw
+    insd
+
+    outsb
+    outsw
+    outsd
+
+    { no segment overrides }
+    movs byte ptr [edi], byte ptr [esi]
+    movs byte ptr [di], byte ptr [si]
+    movs word ptr [edi], word ptr [esi]
+    movs word ptr [di], word ptr [si]
+    movs dword ptr [edi], dword ptr [esi]
+    movs dword ptr [di], dword ptr [si]
+
+    cmps byte ptr [esi], byte ptr [edi]
+    cmps byte ptr [si], byte ptr [di]
+    cmps word ptr [esi], word ptr [edi]
+    cmps word ptr [si], word ptr [di]
+    cmps dword ptr [esi], dword ptr [edi]
+    cmps dword ptr [si], dword ptr [di]
+
+    scas byte ptr [edi]
+    scas byte ptr [di]
+    scas word ptr [edi]
+    scas word ptr [di]
+    scas dword ptr [edi]
+    scas dword ptr [di]
+
+    lods byte ptr [esi]
+    lods byte ptr [si]
+    lods word ptr [esi]
+    lods word ptr [si]
+    lods dword ptr [esi]
+    lods dword ptr [si]
+
+    stos byte ptr [edi]
+    stos byte ptr [di]
+    stos word ptr [edi]
+    stos word ptr [di]
+    stos dword ptr [edi]
+    stos dword ptr [di]
+
+    ins byte ptr [edi], dx
+    ins byte ptr [di], dx
+    ins word ptr [edi], dx
+    ins word ptr [di], dx
+    ins dword ptr [edi], dx
+    ins dword ptr [di], dx
+
+    outs dx, byte ptr [esi]
+    outs dx, byte ptr [si]
+    outs dx, word ptr [esi]
+    outs dx, word ptr [si]
+    outs dx, dword ptr [esi]
+    outs dx, dword ptr [si]
+
+    { es:di }
+    movs byte ptr es:[edi], byte ptr [esi]
+    movs byte ptr es:[di], byte ptr [si]
+    movs word ptr es:[edi], word ptr [esi]
+    movs word ptr es:[di], word ptr [si]
+    movs dword ptr es:[edi], dword ptr [esi]
+    movs dword ptr es:[di], dword ptr [si]
+
+    cmps byte ptr [esi], byte ptr es:[edi]
+    cmps byte ptr [si], byte ptr es:[di]
+    cmps word ptr [esi], word ptr es:[edi]
+    cmps word ptr [si], word ptr es:[di]
+    cmps dword ptr [esi], dword ptr es:[edi]
+    cmps dword ptr [si], dword ptr es:[di]
+
+    scas byte ptr es:[edi]
+    scas byte ptr es:[di]
+    scas word ptr es:[edi]
+    scas word ptr es:[di]
+    scas dword ptr es:[edi]
+    scas dword ptr es:[di]
+
+    lods byte ptr [esi]
+    lods byte ptr [si]
+    lods word ptr [esi]
+    lods word ptr [si]
+    lods dword ptr [esi]
+    lods dword ptr [si]
+
+    stos byte ptr es:[edi]
+    stos byte ptr es:[di]
+    stos word ptr es:[edi]
+    stos word ptr es:[di]
+    stos dword ptr es:[edi]
+    stos dword ptr es:[di]
+
+    ins byte ptr es:[edi], dx
+    ins byte ptr es:[di], dx
+    ins word ptr es:[edi], dx
+    ins word ptr es:[di], dx
+    ins dword ptr es:[edi], dx
+    ins dword ptr es:[di], dx
+
+    outs dx, byte ptr [esi]
+    outs dx, byte ptr [si]
+    outs dx, word ptr [esi]
+    outs dx, word ptr [si]
+    outs dx, dword ptr [esi]
+    outs dx, dword ptr [si]
+
+    { es:di, fs:si }
+    movs byte ptr es:[edi], byte ptr fs:[esi]
+    movs byte ptr es:[di], byte ptr fs:[si]
+    movs word ptr es:[edi], word ptr fs:[esi]
+    movs word ptr es:[di], word ptr fs:[si]
+    movs dword ptr es:[edi], dword ptr fs:[esi]
+    movs dword ptr es:[di], dword ptr fs:[si]
+
+    cmps byte ptr fs:[esi], byte ptr es:[edi]
+    cmps byte ptr fs:[si], byte ptr es:[di]
+    cmps word ptr fs:[esi], word ptr es:[edi]
+    cmps word ptr fs:[si], word ptr es:[di]
+    cmps dword ptr fs:[esi], dword ptr es:[edi]
+    cmps dword ptr fs:[si], dword ptr es:[di]
+
+    scas byte ptr es:[edi]
+    scas byte ptr es:[di]
+    scas word ptr es:[edi]
+    scas word ptr es:[di]
+    scas dword ptr es:[edi]
+    scas dword ptr es:[di]
+
+    lods byte ptr fs:[esi]
+    lods byte ptr fs:[si]
+    lods word ptr fs:[esi]
+    lods word ptr fs:[si]
+    lods dword ptr fs:[esi]
+    lods dword ptr fs:[si]
+
+    stos byte ptr es:[edi]
+    stos byte ptr es:[di]
+    stos word ptr es:[edi]
+    stos word ptr es:[di]
+    stos dword ptr es:[edi]
+    stos dword ptr es:[di]
+
+    ins byte ptr es:[edi], dx
+    ins byte ptr es:[di], dx
+    ins word ptr es:[edi], dx
+    ins word ptr es:[di], dx
+    ins dword ptr es:[edi], dx
+    ins dword ptr es:[di], dx
+
+    outs dx, byte ptr fs:[esi]
+    outs dx, byte ptr fs:[si]
+    outs dx, word ptr fs:[esi]
+    outs dx, word ptr fs:[si]
+    outs dx, dword ptr fs:[esi]
+    outs dx, dword ptr fs:[si]
+  end;
+end.