Explorar o código

+ another helper function: x86_parameterized_string_op_param_count
* when generating x86 code for parameterized string instructions with the
internal object writer, don't rely on the destination operand being [(r/e)di]
when determining the segment prefix, because when using intel syntax, source
and destination can be anything (only the operand size, the address size and
the source segment is taken into account)

git-svn-id: trunk@37452 -

nickysn %!s(int64=7) %!d(string=hai) anos
pai
achega
baf492c7a5
Modificáronse 3 ficheiros con 36 adicións e 6 borrados
  1. 21 6
      compiler/aasmtai.pas
  2. 1 0
      compiler/x86/aasmcpu.pas
  3. 14 0
      compiler/x86/cpubase.pas

+ 21 - 6
compiler/aasmtai.pas

@@ -933,6 +933,9 @@ interface
 implementation
 implementation
 
 
     uses
     uses
+{$ifdef x86}
+      aasmcpu,
+{$endif x86}
       SysUtils,
       SysUtils,
       verbose,
       verbose,
       globals;
       globals;
@@ -2603,6 +2606,10 @@ implementation
 
 
 
 
     procedure tai_cpu_abstract.loadref(opidx:longint;const r:treference);
     procedure tai_cpu_abstract.loadref(opidx:longint;const r:treference);
+{$ifdef x86}
+      var
+        si_param: ShortInt;
+{$endif}
       begin
       begin
         allocate_oper(opidx+1);
         allocate_oper(opidx+1);
         with oper[opidx]^ do
         with oper[opidx]^ do
@@ -2619,9 +2626,10 @@ implementation
               too much of a a speed penalty}
               too much of a a speed penalty}
             if is_x86_parameterized_string_op(opcode) then
             if is_x86_parameterized_string_op(opcode) then
               begin
               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
+                si_param:=get_x86_string_op_si_param(opcode);
+                if (si_param<>-1) and (taicpu(self).OperandOrder=op_att) then
+                  si_param:=x86_parameterized_string_op_param_count(opcode)-si_param-1;
+                if (si_param=opidx) and (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
                   segprefix:=ref^.segment;
                   segprefix:=ref^.segment;
               end
               end
             else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
             else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
@@ -2680,6 +2688,10 @@ implementation
 
 
 
 
     procedure tai_cpu_abstract.loadoper(opidx:longint;o:toper);
     procedure tai_cpu_abstract.loadoper(opidx:longint;o:toper);
+{$ifdef x86}
+      var
+        si_param: ShortInt;
+{$endif x86}
       begin
       begin
         allocate_oper(opidx+1);
         allocate_oper(opidx+1);
         clearop(opidx);
         clearop(opidx);
@@ -2698,11 +2710,14 @@ implementation
                   new(ref);
                   new(ref);
                   ref^:=o.ref^;
                   ref^:=o.ref^;
 {$ifdef x86}
 {$ifdef x86}
+                  { We allow this exception for x86, since overloading this would be
+                    too much of a a speed penalty}
                   if is_x86_parameterized_string_op(opcode) then
                   if is_x86_parameterized_string_op(opcode) then
                     begin
                     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
+                      si_param:=get_x86_string_op_si_param(opcode);
+                      if (si_param<>-1) and (taicpu(self).OperandOrder=op_att) then
+                        si_param:=x86_parameterized_string_op_param_count(opcode)-si_param-1;
+                      if (si_param=opidx) and (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
                         segprefix:=ref^.segment;
                         segprefix:=ref^.segment;
                     end
                     end
                   else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
                   else if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then

+ 1 - 0
compiler/x86/aasmcpu.pas

@@ -468,6 +468,7 @@ interface
 {$ifdef i8086}
 {$ifdef i8086}
          procedure loadsegsymbol(opidx:longint;s:tasmsymbol);
          procedure loadsegsymbol(opidx:longint;s:tasmsymbol);
 {$endif i8086}
 {$endif i8086}
+         property OperandOrder : TOperandOrder read FOperandOrder;
       private
       private
          { next fields are filled in pass1, so pass2 is faster }
          { next fields are filled in pass1, so pass2 is faster }
          insentry  : PInsEntry;
          insentry  : PInsEntry;

+ 14 - 0
compiler/x86/cpubase.pas

@@ -323,6 +323,7 @@ uses
     { checks whether the specified op is an x86 parameterized string instruction
     { checks whether the specified op is an x86 parameterized string instruction
       (e.g. returns true for movs, cmps, etc, but returns false for movsb, cmpsb, etc.) }
       (e.g. returns true for movs, cmps, etc, but returns false for movsb, cmpsb, etc.) }
     function is_x86_parameterized_string_op(op: TAsmOp): boolean;
     function is_x86_parameterized_string_op(op: TAsmOp): boolean;
+    function x86_parameterized_string_op_param_count(op: TAsmOp): shortint;
     function x86_param2paramless_string_op(op: TAsmOp): TAsmOp;
     function x86_param2paramless_string_op(op: TAsmOp): TAsmOp;
     function get_x86_string_op_size(op: TAsmOp): TOpSize;
     function get_x86_string_op_size(op: TAsmOp): TOpSize;
     { returns the 0-based operand number (intel syntax) of the ds:[si] param of
     { returns the 0-based operand number (intel syntax) of the ds:[si] param of
@@ -716,6 +717,19 @@ implementation
       end;
       end;
 
 
 
 
+    function x86_parameterized_string_op_param_count(op: TAsmOp): shortint;
+      begin
+        case op of
+          A_MOVS,A_CMPS,A_INS,A_OUTS:
+            result:=2;
+          A_SCAS,A_LODS,A_STOS:
+            result:=1;
+          else
+            internalerror(2017101203);
+        end;
+      end;
+
+
     function x86_param2paramless_string_op(op: TAsmOp): TAsmOp;
     function x86_param2paramless_string_op(op: TAsmOp): TAsmOp;
       begin
       begin
         case op of
         case op of