Browse Source

m68k: basic 68881 fpu support. probably still broken at umpzillion places, and mostly untested, but at least it builds the RTL and all packages successfully with -Cp68020 -Cf68881 instead of dying with random internalerrors() and now even emits actual FPU opcodes.

git-svn-id: trunk@29370 -
Károly Balogh 10 years ago
parent
commit
d000b1bc7c
4 changed files with 76 additions and 75 deletions
  1. 19 7
      compiler/m68k/aasmcpu.pas
  2. 13 27
      compiler/m68k/cgcpu.pas
  3. 37 40
      compiler/m68k/n68kadd.pas
  4. 7 1
      compiler/m68k/n68kcnv.pas

+ 19 - 7
compiler/m68k/aasmcpu.pas

@@ -464,6 +464,7 @@ type
         result:=operand_read;
 
         case opcode of
+          // CPU opcodes
           A_MOVE, A_MOVEQ, A_MOVEA, A_MVZ, A_MVS, A_MOV3Q, A_LEA:
             if opnr=1 then
               result:=operand_write;
@@ -483,6 +484,17 @@ type
             result:=operand_readwrite;
           A_TST,A_CMP,A_CMPI:
             begin end; { Do nothing, default operand_read is fine here. }
+
+          // FPU opcodes
+          A_FMOVE:
+             if opnr=1 then
+               result:=operand_write;
+          A_FADD, A_FSUB, A_FMUL, A_FDIV:
+             if opnr=1 then
+               result:=operand_readwrite;
+          A_FCMP:
+             begin end; { operand_read }
+
           else begin
             internalerror(2004040903);
           end;
@@ -508,17 +520,17 @@ type
 
     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
       begin
-	case getregtype(r) of
-	  R_INTREGISTER :
-	    result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
-	  R_ADDRESSREGISTER :
-	    result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
-	  R_FPUREGISTER :
+        case getregtype(r) of
+          R_INTREGISTER :
+            result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
+          R_ADDRESSREGISTER :
+            result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
+          R_FPUREGISTER :
             // no need to handle sizes here
             result:=taicpu.op_reg_ref(A_FMOVE,S_FS,r,ref);
           else
             internalerror(200602012);
-	end;
+        end;
       end;
 
 

+ 13 - 27
compiler/m68k/cgcpu.pas

@@ -964,20 +964,16 @@ unit cgcpu;
       var
         instr : taicpu;
       begin
-        { in emulation mode, only 32-bit single is supported }
-        if (cs_fp_emulation in current_settings.moduleswitches) or (current_settings.fputype=fpu_soft) then
-          instr:=taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2)
-        else
-          instr:=taicpu.op_reg_reg(A_FMOVE,tcgsize2opsize[tosize],reg1,reg2);
-         add_move_instruction(instr);
-         list.concat(instr);
+        instr:=taicpu.op_reg_reg(A_FMOVE,S_FX,reg1,reg2);
+        add_move_instruction(instr);
+        list.concat(instr);
       end;
 
 
     procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
-     var
-      opsize : topsize;
-      href : treference;
+      var
+        opsize : topsize;
+        href : treference;
       begin
         opsize := tcgsize2opsize[fromsize];
         { extended is not supported, since it is not available on Coldfire }
@@ -985,30 +981,21 @@ unit cgcpu;
           internalerror(20020729);
         href := ref;
         fixref(list,href);
-        { in emulation mode, only 32-bit single is supported }
-        if (cs_fp_emulation in current_settings.moduleswitches) or (current_settings.fputype=fpu_soft) then
-           list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
-        else
-           begin
-             list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
-             if (tosize < fromsize) then
-               a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
-           end;
+        list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
       end;
 
     procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
       var
-       opsize : topsize;
+        opsize : topsize;
+        href : treference;
       begin
         opsize := tcgsize2opsize[tosize];
         { extended is not supported, since it is not available on Coldfire }
         if opsize = S_FX then
           internalerror(20020729);
-        { in emulation mode, only 32-bit single is supported }
-        if (cs_fp_emulation in current_settings.moduleswitches) or (current_settings.fputype=fpu_soft) then
-          list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
-        else
-          list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
+        href := ref;
+        fixref(list,href);
+        list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg,href));
       end;
 
 
@@ -1018,8 +1005,7 @@ unit cgcpu;
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
               case size of
-                OS_F64:
-                  cg64.a_load64_ref_cgpara(list,ref,cgpara);
+                OS_F64,
                 OS_F32:
                   a_load_ref_cgpara(list,size,ref,cgpara);
                 else

+ 37 - 40
compiler/m68k/n68kadd.pas

@@ -138,56 +138,53 @@ implementation
         if nf_swapped in flags then
           swapleftright;
 
-        // put both operands in a register
-        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
-        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
-
-        // initialize de result
-        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
-        if left.location.loc = LOC_FPUREGISTER then
-          location.register := left.location.register
-        else if right.location.loc = LOC_FPUREGISTER then
-          location.register := right.location.register
-        else
-          location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
-
-        // emit the actual operation
-        {
-          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
-            location.register,left.location.register,
-            right.location.register))
-        }
+        case current_settings.fputype of
+          fpu_68881:
+            begin
+              // put both operands in a register
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+
+              // initialize the result
+              location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+              location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+
+              // emit the actual operation
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FMOVE,S_FX,left.location.register,location.register));
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_FX,right.location.register,location.register));
+            end;
+          else
+            // softfpu should be handled in pass1, others are not yet supported...
+            internalerror(2015010201);
+        end;
       end;
 
 
     procedure t68kaddnode.second_cmpfloat;
       begin
         pass_left_right;
-
-{
         if (nf_swapped in flags) then
           swapleftright;
-}
-        { force fpureg as location, left right doesn't matter
-          as both will be in a fpureg }
-        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
-        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
 
-        location_reset(location,LOC_FLAGS,OS_NO);
-        location.resflags:=getresflags(true);
-{
-        if nodetype in [equaln,unequaln] then
-          current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMF,
-             left.location.register,right.location.register),
-             cgsize2fpuoppostfix[def_cgsize(resultdef)]))
-        else
-          current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMFE,
-             left.location.register,right.location.register),
-             cgsize2fpuoppostfix[def_cgsize(resultdef)]));
+        case current_settings.fputype of
+          fpu_68881:
+            begin
+              location_reset(location,LOC_FLAGS,OS_NO);
 
-        location_reset(location,LOC_FLAGS,OS_NO);
-        location.resflags:=getresflags(false);
-}
+              { force fpureg as location, left right doesn't matter
+                as both will be in a fpureg }
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
+              hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
+
+              // emit compare
+              current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCMP,S_FX,right.location.register,left.location.register));
+
+              location.resflags:=getresflags(false);
+            end;
+          else
+            // softfpu should be handled in pass1, others are not yet supported...
+            internalerror(2015010201);
+        end;
       end;
 
 

+ 7 - 1
compiler/m68k/n68kcnv.pas

@@ -68,8 +68,14 @@ implementation
           end
         else
         { converting a 64bit integer to a float requires a helper }
-        if is_64bitint(left.resultdef) then
+        if is_64bitint(left.resultdef) or
+            is_currency(left.resultdef) then
           begin
+            { hack to avoid double division by 10000, as it's
+              already done by typecheckpass.resultdef_int_to_real }
+            if is_currency(left.resultdef) then
+              left.resultdef := s64inttype;
+
             if is_signed(left.resultdef) then
               fname := 'fpc_int64_to_double'
             else