Pārlūkot izejas kodu

* Fixed handling of 'movq' instruction by assembler reader, resolves #18205.

git-svn-id: trunk@17497 -
sergei 14 gadi atpakaļ
vecāks
revīzija
08e895cf7c
3 mainītis faili ar 45 papildinājumiem un 14 dzēšanām
  1. 7 12
      compiler/x86/rax86.pas
  2. 36 1
      compiler/x86/rax86att.pas
  3. 2 1
      compiler/x86_64/rax64att.pas

+ 7 - 12
compiler/x86/rax86.pas

@@ -57,6 +57,8 @@ type
     procedure CheckOperandSizes;
     procedure CheckNonCommutativeOpcodes;
     procedure SwapOperands;
+    { Additional actions required by specific reader }
+    procedure FixupOpcode;virtual;
     { opcode adding }
     function ConcatInstruction(p : TAsmList) : tai;override;
   end;
@@ -535,6 +537,11 @@ begin
         opcode:=A_FDIVRP;
 end;
 
+procedure Tx86Instruction.FixupOpcode;
+begin
+  { does nothing by default }
+end;
+
 {*****************************************************************************
                               opcode Adding
 *****************************************************************************}
@@ -623,18 +630,6 @@ begin
           siz:=S_FAR;
     end;
 
-{$ifdef x86_64}
-  { Convert movq with at least one general registers or constant to a mov instruction }
-  if (opcode=A_MOVQ) and
-     (ops=2) and
-     (
-      (operands[1].opr.typ=OPR_REGISTER) or
-      (operands[2].opr.typ=OPR_REGISTER) or
-      (operands[1].opr.typ=OPR_CONSTANT)
-     ) then
-     opcode:=A_MOV;
-{$endif x86_64}
-
    { GNU AS interprets FDIV without operand differently
      for version 2.9.1 and 2.10
      we add explicit args to it !! }

+ 36 - 1
compiler/x86/rax86att.pas

@@ -42,6 +42,9 @@ Interface
       procedure MaybeGetPICModifier(var oper: tx86operand);
     end;
 
+    Tx86attInstruction = class(Tx86Instruction)
+      procedure FixupOpcode;override;
+    end;
 
 Implementation
 
@@ -63,6 +66,37 @@ Implementation
       cgbase
       ;
 
+    { Tx86attInstruction }
+
+    procedure Tx86attInstruction.FixupOpcode;
+      begin
+        if (OpOrder=op_intel) then
+          SwapOperands;
+
+        case opcode of
+          A_MOVQ:
+            begin
+              { May be either real 'movq' or a generic 'mov' with 'q' suffix. Convert to mov
+                if source is a constant, or if neither operand is an mmx/xmm register }
+{$ifdef x86_64}
+              if (ops=2) and
+                (
+                  (operands[1].opr.typ=OPR_CONSTANT) or not
+                    (
+                      ((operands[1].opr.typ=OPR_REGISTER) and
+                        (getregtype(operands[1].opr.reg) in [R_MMXREGISTER,R_MMREGISTER])) or
+                      ((operands[2].opr.typ=OPR_REGISTER) and
+                        (getregtype(operands[2].opr.reg) in [R_MMXREGISTER,R_MMREGISTER]))
+                    )
+                ) then
+                opcode:=A_MOV;
+{$endif x86_64}
+            end;
+        end;
+      end;
+
+    { Tx86attReader }
+
     procedure tx86attreader.handlepercent;
       var
         len : longint;
@@ -848,12 +882,13 @@ Implementation
       var
         instr : Tx86Instruction;
       begin
-        instr:=Tx86Instruction.Create(Tx86Operand);
+        instr:=Tx86attInstruction.Create(Tx86Operand);
         instr.OpOrder:=op_att;
         BuildOpcode(instr);
         instr.AddReferenceSizes;
         instr.SetInstructionOpsize;
         instr.CheckOperandSizes;
+        instr.FixupOpcode;
         instr.ConcatInstruction(curlist);
         instr.Free;
       end;

+ 2 - 1
compiler/x86_64/rax64att.pas

@@ -43,12 +43,13 @@ Unit rax64att;
       var
         instr : Tx86Instruction;
       begin
-        instr:=Tx86Instruction.Create(Tx86Operand);
+        instr:=Tx86attInstruction.Create(Tx86Operand);
         instr.OpOrder:=op_att;
         BuildOpcode(instr);
         instr.AddReferenceSizes;
         instr.SetInstructionOpsize;
         instr.CheckOperandSizes;
+        instr.FixupOpcode;
         instr.ConcatInstruction(curlist);
         instr.Free;
       end;