Browse Source

m68k: some experimental code for the unaligned access support on plain 68000. work in progress, inactive code for now

git-svn-id: trunk@33744 -
Károly Balogh 9 years ago
parent
commit
5acd04d284
1 changed files with 129 additions and 1 deletions
  1. 129 1
      compiler/m68k/cgcpu.pas

+ 129 - 1
compiler/m68k/cgcpu.pas

@@ -50,8 +50,10 @@ unit cgcpu;
         procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
         procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
 
 
         procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);override;
         procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);override;
+        procedure a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);override;
         procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);override;
         procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);override;
         procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);override;
         procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);override;
+        procedure a_load_ref_reg_unaligned(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);override;
         procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);override;
         procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);override;
 
 
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
@@ -748,6 +750,17 @@ unit cgcpu;
         href : treference;
         href : treference;
         hreg : tregister;
         hreg : tregister;
       begin
       begin
+        {
+        // FIX ME: experimental code, disabled for now. (KB)
+        if (current_settings.cputype = cpu_mc68000) and
+           (ref.alignment=1) and (tcgsize2size[tosize] > 1) then
+          begin
+            //list.concat(tai_comment.create(strpnew('a_load_reg_ref calling unaligned')));
+            a_load_reg_ref_unaligned(list,fromsize,tosize,register,ref);
+            exit;
+          end;
+        }
+
         href := ref;
         href := ref;
         hreg := register;
         hreg := register;
         fixref(list,href,false);
         fixref(list,href,false);
@@ -761,6 +774,57 @@ unit cgcpu;
       end;
       end;
 
 
 
 
+    procedure tcg68k.a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
+      var
+        tmpref : treference;
+        tmpreg,
+        tmpreg2 : tregister;
+      begin
+        //list.concat(tai_comment.create(strpnew('a_load_reg_ref_unaligned')));
+        if (current_settings.cputype <> cpu_mc68000) or
+           (ref.alignment <> 1) or
+           (tcgsize2size[tosize] < 2) then
+          begin
+            a_load_reg_ref(list,fromsize,tosize,register,ref);
+            exit;
+          end;
+
+        tmpreg2:=getaddressregister(list);
+        tmpref:=ref;
+        inc(tmpref.offset,tcgsize2size[tosize]);
+        a_loadaddr_ref_reg(list,ref,tmpreg2);
+        reference_reset_base(tmpref,tmpreg2,0,1);
+        tmpref.direction:=dir_dec;
+
+        tmpreg:=getintregister(list,tosize);
+        a_load_reg_reg(list,fromsize,tosize,register,tmpreg);
+
+        case tosize of
+          OS_16,OS_S16:
+            begin
+              list.concat(taicpu.op_reg_ref(A_MOVE,S_B,tmpreg,tmpref));
+              list.concat(taicpu.op_const_reg(A_LSR,S_W,8,tmpreg));
+              tmpref.direction:=dir_none;
+              list.concat(taicpu.op_reg_ref(A_MOVE,S_B,tmpreg,tmpref));
+              sign_extend(list,fromsize,tmpreg);
+            end;
+          OS_32,OS_S32:
+            begin
+              list.concat(taicpu.op_reg_ref(A_MOVE,S_B,tmpreg,tmpref));
+              list.concat(taicpu.op_const_reg(A_LSR,S_W,8,tmpreg));
+              list.concat(taicpu.op_reg_ref(A_MOVE,S_B,tmpreg,tmpref));
+              list.concat(taicpu.op_reg(A_SWAP,S_L,tmpreg));
+              list.concat(taicpu.op_reg_ref(A_MOVE,S_B,tmpreg,tmpref));
+              list.concat(taicpu.op_const_reg(A_LSR,S_W,8,tmpreg));
+              tmpref.direction:=dir_none;
+              list.concat(taicpu.op_reg_ref(A_MOVE,S_B,tmpreg,tmpref));
+            end
+          else
+            internalerror(2016052201);
+        end;
+      end;
+
+
     procedure tcg68k.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
     procedure tcg68k.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
       var
       var
         aref: treference;
         aref: treference;
@@ -778,7 +842,7 @@ unit cgcpu;
           begin
           begin
             { if we will use a temp register, we don't need to fully resolve 
             { if we will use a temp register, we don't need to fully resolve 
               the dest ref, not even on coldfire }
               the dest ref, not even on coldfire }
-            fixref(list,bref,false); 
+            fixref(list,bref,false);
             { if we need to change the size then always use a temporary register }
             { if we need to change the size then always use a temporary register }
             hreg:=getintregister(list,fromsize);
             hreg:=getintregister(list,fromsize);
             list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
             list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],aref,hreg));
@@ -831,8 +895,19 @@ unit cgcpu;
        opsize: topsize;
        opsize: topsize;
        needsext: boolean;
        needsext: boolean;
       begin
       begin
+         {
+         // FIX ME: experimental code, disabled for now. (KB)
+         if (current_settings.cputype = cpu_mc68000) and
+            (ref.alignment=1) and (tcgsize2size[fromsize] > 1) then
+           begin
+             //list.concat(tai_comment.create(strpnew('a_load_ref_reg calling unaligned')));
+             a_load_ref_reg_unaligned(list,fromsize,tosize,ref,register);
+             exit;
+           end;
+         }
          href:=ref;
          href:=ref;
          fixref(list,href,false);
          fixref(list,href,false);
+
          needsext:=tcgsize2size[fromsize]<tcgsize2size[tosize];
          needsext:=tcgsize2size[fromsize]<tcgsize2size[tosize];
          if needsext then
          if needsext then
            size:=fromsize
            size:=fromsize
@@ -864,6 +939,59 @@ unit cgcpu;
       end;
       end;
 
 
 
 
+    procedure tcg68k.a_load_ref_reg_unaligned(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
+      var
+        tmpref : treference;
+        tmpreg,
+        tmpreg2 : tregister;
+      begin
+        //list.concat(tai_comment.create(strpnew('a_load_ref_reg_unaligned')));
+        if (current_settings.cputype <> cpu_mc68000) or
+           (ref.alignment <> 1) or
+           (tcgsize2size[fromsize] < 2) then
+          begin
+            a_load_ref_reg(list,fromsize,tosize,ref,register);
+            exit;
+          end;
+
+        tmpreg2:=getaddressregister(list);
+        a_loadaddr_ref_reg(list,ref,tmpreg2);
+        reference_reset_base(tmpref,tmpreg2,0,1);
+        tmpref.direction:=dir_inc;
+
+        if isaddressregister(register) then
+          tmpreg:=getintregister(list,OS_ADDR)
+        else
+          tmpreg:=register;
+
+        case fromsize of
+          OS_16,OS_S16:
+            begin
+              list.concat(taicpu.op_ref_reg(A_MOVE,S_B,tmpref,tmpreg));
+              list.concat(taicpu.op_const_reg(A_LSL,S_W,8,tmpreg));
+              tmpref.direction:=dir_none;
+              list.concat(taicpu.op_ref_reg(A_MOVE,S_B,tmpref,tmpreg));
+              sign_extend(list,fromsize,tmpreg);
+            end;
+          OS_32,OS_S32:
+            begin
+              list.concat(taicpu.op_ref_reg(A_MOVE,S_B,tmpref,tmpreg));
+              list.concat(taicpu.op_const_reg(A_LSL,S_W,8,tmpreg));
+              list.concat(taicpu.op_ref_reg(A_MOVE,S_B,tmpref,tmpreg));
+              list.concat(taicpu.op_reg(A_SWAP,S_L,tmpreg));
+              list.concat(taicpu.op_ref_reg(A_MOVE,S_B,tmpref,tmpreg));
+              list.concat(taicpu.op_const_reg(A_LSL,S_W,8,tmpreg));
+              tmpref.direction:=dir_none;
+              list.concat(taicpu.op_ref_reg(A_MOVE,S_B,tmpref,tmpreg));
+            end
+          else
+            internalerror(2016052103);
+        end;
+        if tmpreg<>register then
+          a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpreg,register);
+      end;
+
+
     procedure tcg68k.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
     procedure tcg68k.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
       var
       var
         href : treference;
         href : treference;