Selaa lähdekoodia

m68k: support 32x32 to 64bit MUL generation when targeting CPUs which support this instruction

git-svn-id: trunk@36339 -
Károly Balogh 8 vuotta sitten
vanhempi
commit
87e8010f05
2 muutettua tiedostoa jossa 71 lisäystä ja 1 poistoa
  1. 23 1
      compiler/m68k/aasmcpu.pas
  2. 48 0
      compiler/m68k/n68kadd.pas

+ 23 - 1
compiler/m68k/aasmcpu.pas

@@ -65,8 +65,10 @@ type
      { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
      constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : treference);
 
-     { this is used for divx/remx regpair generation }
+     { this is used for mulx/divx/remx regpair generation }
      constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+     constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint; _op2,_op3 : tregister);
+     constructor op_ref_reg_reg(op : tasmop;_size : topsize;_op1 : treference; _op2,_op3 : tregister);
 
      constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
      constructor op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr,_op1fpu: tcpuregisterset; _op2: tregister);
@@ -321,6 +323,26 @@ type
          loadreg(2,_op3);
       end;
 
+    constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint; _op2,_op3 : tregister);
+      begin
+         inherited create(op);
+         init(_size);
+         ops:=3;
+         loadconst(0,aword(_op1));
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+      end;
+
+    constructor taicpu.op_ref_reg_reg(op : tasmop;_size : topsize;_op1 : treference; _op2,_op3 : tregister);
+      begin
+         inherited create(op);
+         init(_size);
+         ops:=3;
+         loadref(0,_op1);
+         loadreg(1,_op2);
+         loadreg(2,_op3);
+      end;
+
    constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
      Begin
         inherited create(op);

+ 48 - 0
compiler/m68k/n68kadd.pas

@@ -37,6 +37,7 @@ interface
           procedure second_mul64bit;
        protected
           function use_generic_mul64bit: boolean; override;
+          function use_generic_mul32to64: boolean; override;
           procedure second_addfloat;override;
           procedure second_cmpfloat;override;
           procedure second_addordinal;override;
@@ -359,8 +360,13 @@ implementation
 *****************************************************************************}
 
     procedure t68kaddnode.second_addordinal;
+      const
+        mul_op_signed: array[boolean] of tasmop = ( A_MULU, A_MULS );
       var
         cgop    : topcg;
+        asmop   : tasmop;
+        list    : tasmlist;
+        href    : treference;
       begin
         { if we need to handle overflow checking, fall back to the generic cg }
         if (nodetype in [addn,subn,muln]) and
@@ -372,6 +378,8 @@ implementation
             exit;
           end;
 
+        list:=current_asmdata.CurrAsmList;
+
         case nodetype of
           addn: cgop:=OP_ADD;
           xorn: cgop:=OP_XOR;
@@ -398,6 +406,41 @@ implementation
 
         { initialize the result }
         location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+
+        { this is only true, if the CPU supports 32x32 -> 64 bit MUL, see the relevant method }
+        if (nodetype=muln) and is_64bit(resultdef) then
+          begin
+            list.concat(tai_comment.create(strpnew('second_addordinal: mul32to64bit')));
+
+            asmop:=mul_op_signed[cgop = OP_IMUL];
+            location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+            location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+            cg.a_load_reg_reg(list,left.location.size,OS_INT,left.location.register,location.register64.reglo);
+
+            if not (right.location.size in [OS_S32, OS_32]) or
+               not (right.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_CONSTANT,LOC_REFERENCE,LOC_CREFERENCE]) or
+               ((right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and needs_unaligned(right.location.reference.alignment,def_cgsize(resultdef))) then
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
+
+            case right.location.loc of
+              LOC_REGISTER,
+              LOC_CREGISTER:
+                list.concat(taicpu.op_reg_reg_reg(asmop,S_L,right.location.register,location.register64.reghi,location.register64.reglo));
+              LOC_CONSTANT:
+                list.concat(taicpu.op_const_reg_reg(asmop,S_L,right.location.value,location.register64.reghi,location.register64.reglo));
+              LOC_REFERENCE,
+              LOC_CREFERENCE:
+                begin
+                  href:=right.location.reference;
+                  tcg68k(cg).fixref(list,href,false);
+                  list.concat(taicpu.op_ref_reg_reg(asmop,S_L,href,location.register64.reghi,location.register64.reglo));
+                 end;
+              else
+                internalerror(2017052601);
+            end;
+            exit;
+          end;
+
         location.register := cg.getintregister(current_asmdata.CurrAsmList,location.size);
         cg.a_load_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register);
 
@@ -527,6 +570,11 @@ implementation
                                 64-bit
 *****************************************************************************}
 
+    function t68kaddnode.use_generic_mul32to64: boolean;
+    begin
+      result:=not (CPUM68K_HAS_64BITMUL in cpu_capabilities[current_settings.cputype]);
+    end;
+
     function t68kaddnode.use_generic_mul64bit: boolean;
     begin
       result:=(cs_check_overflow in current_settings.localswitches) or