فهرست منبع

* fixed a bug which caused non commutative fpu instructions to be wrong when using an intel-style external assembler and compiling a smartlinked unit

git-svn-id: branches/i8086@24151 -
nickysn 12 سال پیش
والد
کامیت
c3aaa37c0c
2فایلهای تغییر یافته به همراه34 افزوده شده و 24 حذف شده
  1. 23 14
      compiler/x86/aasmcpu.pas
  2. 11 10
      compiler/x86/agx86nsm.pas

+ 23 - 14
compiler/x86/aasmcpu.pas

@@ -306,7 +306,14 @@ interface
          procedure changeopsize(siz:topsize);
 
          function  GetString:string;
-         procedure CheckNonCommutativeOpcodes;
+
+         { This is a workaround for the GAS non commutative fpu instruction braindamage.
+           Early versions of the UnixWare assembler had a bug where some fpu instructions
+           were reversed and GAS still keeps this "feature" for compatibility.
+           for details: http://sourceware.org/binutils/docs/as/i386_002dBugs.html#i386_002dBugs
+                        http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=372528
+                        http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#Caveats }
+         function FixNonCommutativeOpcodes: tasmop;
       private
          FOperandOrder : TOperandOrder;
          procedure init(_size : topsize); { this need to be called by all constructor }
@@ -961,8 +968,10 @@ implementation
       end;
 
 
-    procedure taicpu.CheckNonCommutativeOpcodes;
+    function taicpu.FixNonCommutativeOpcodes: tasmop;
       begin
+        result:=opcode;
+
         { we need ATT order }
         SetOperandOrder(op_att);
 
@@ -981,21 +990,21 @@ implementation
            (ops=0) then
           begin
             if opcode=A_FSUBR then
-              opcode:=A_FSUB
+              result:=A_FSUB
             else if opcode=A_FSUB then
-              opcode:=A_FSUBR
+              result:=A_FSUBR
             else if opcode=A_FDIVR then
-              opcode:=A_FDIV
+              result:=A_FDIV
             else if opcode=A_FDIV then
-              opcode:=A_FDIVR
+              result:=A_FDIVR
             else if opcode=A_FSUBRP then
-              opcode:=A_FSUBP
+              result:=A_FSUBP
             else if opcode=A_FSUBP then
-              opcode:=A_FSUBRP
+              result:=A_FSUBRP
             else if opcode=A_FDIVRP then
-              opcode:=A_FDIVP
+              result:=A_FDIVP
             else if opcode=A_FDIVP then
-              opcode:=A_FDIVRP;
+              result:=A_FDIVRP;
           end;
         if (
             (ops=1) and
@@ -1005,13 +1014,13 @@ implementation
            ) then
          begin
            if opcode=A_FSUBRP then
-             opcode:=A_FSUBP
+             result:=A_FSUBP
            else if opcode=A_FSUBP then
-             opcode:=A_FSUBRP
+             result:=A_FSUBRP
            else if opcode=A_FDIVRP then
-             opcode:=A_FDIVP
+             result:=A_FDIVP
            else if opcode=A_FDIVP then
-             opcode:=A_FDIVRP;
+             result:=A_FDIVRP;
          end;
       end;
 

+ 11 - 10
compiler/x86/agx86nsm.pas

@@ -537,6 +537,7 @@ interface
 {$ifdef cpuextended}
       e        : extended;
 {$endif cpuextended}
+      fixed_opcode: TAsmOp;
     begin
       if not assigned(p) then
        exit;
@@ -884,12 +885,12 @@ interface
 
            ait_instruction :
              begin
-               taicpu(hp).CheckNonCommutativeOpcodes;
+               fixed_opcode:=taicpu(hp).FixNonCommutativeOpcodes;
                { We need intel order, no At&t }
                taicpu(hp).SetOperandOrder(op_intel);
                s:='';
-               if ((taicpu(hp).opcode=A_FADDP) or
-                   (taicpu(hp).opcode=A_FMULP))
+               if ((fixed_opcode=A_FADDP) or
+                   (fixed_opcode=A_FMULP))
                   and (taicpu(hp).ops=0) then
                  begin
                    taicpu(hp).allocate_oper(2);
@@ -898,7 +899,7 @@ interface
                    taicpu(hp).oper[1]^.typ:=top_reg;
                    taicpu(hp).oper[1]^.reg:=NR_ST;
                  end;
-               if taicpu(hp).opcode=A_FWAIT then
+               if fixed_opcode=A_FWAIT then
                 AsmWriteln(#9#9'DB'#9'09bh')
                else
                 begin
@@ -906,18 +907,18 @@ interface
                     word prefix to get selectors
                     to be pushed in 2 bytes  PM }
                   if (taicpu(hp).opsize=S_W) and
-                     ((taicpu(hp).opcode=A_PUSH) or
-                      (taicpu(hp).opcode=A_POP)) and
+                     ((fixed_opcode=A_PUSH) or
+                      (fixed_opcode=A_POP)) and
                       (taicpu(hp).oper[0]^.typ=top_reg) and
                       (is_segment_reg(taicpu(hp).oper[0]^.reg)) then
                     AsmWriteln(#9#9'DB'#9'066h');
-                  AsmWrite(#9#9+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]);
+                  AsmWrite(#9#9+std_op2str[fixed_opcode]+cond2str[taicpu(hp).condition]);
                   if taicpu(hp).ops<>0 then
                    begin
-                     if is_calljmp(taicpu(hp).opcode) then
+                     if is_calljmp(fixed_opcode) then
                       begin
                         AsmWrite(#9);
-                        WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp).opcode);
+                        WriteOper_jmp(taicpu(hp).oper[0]^,fixed_opcode);
                       end
                      else
                       begin
@@ -927,7 +928,7 @@ interface
                             AsmWrite(#9)
                            else
                             AsmWrite(',');
-                           WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,taicpu(hp).opcode,taicpu(hp).ops,(i=2));
+                           WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,fixed_opcode,taicpu(hp).ops,(i=2));
                          end;
                       end;
                    end;