2
0
Эх сурвалжийг харах

+ 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 7 жил өмнө
parent
commit
baf492c7a5

+ 21 - 6
compiler/aasmtai.pas

@@ -933,6 +933,9 @@ interface
 implementation
 
     uses
+{$ifdef x86}
+      aasmcpu,
+{$endif x86}
       SysUtils,
       verbose,
       globals;
@@ -2603,6 +2606,10 @@ implementation
 
 
     procedure tai_cpu_abstract.loadref(opidx:longint;const r:treference);
+{$ifdef x86}
+      var
+        si_param: ShortInt;
+{$endif}
       begin
         allocate_oper(opidx+1);
         with oper[opidx]^ do
@@ -2619,9 +2626,10 @@ implementation
               too much of a a speed penalty}
             if is_x86_parameterized_string_op(opcode) 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
+                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;
               end
             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);
+{$ifdef x86}
+      var
+        si_param: ShortInt;
+{$endif x86}
       begin
         allocate_oper(opidx+1);
         clearop(opidx);
@@ -2698,11 +2710,14 @@ implementation
                   new(ref);
                   ref^:=o.ref^;
 {$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
                     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;
                     end
                   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}
          procedure loadsegsymbol(opidx:longint;s:tasmsymbol);
 {$endif i8086}
+         property OperandOrder : TOperandOrder read FOperandOrder;
       private
          { next fields are filled in pass1, so pass2 is faster }
          insentry  : PInsEntry;

+ 14 - 0
compiler/x86/cpubase.pas

@@ -323,6 +323,7 @@ uses
     { 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.) }
     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 get_x86_string_op_size(op: TAsmOp): TOpSize;
     { returns the 0-based operand number (intel syntax) of the ds:[si] param of
@@ -716,6 +717,19 @@ implementation
       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;
       begin
         case op of