Browse Source

* support for unaligned loads/stores on sparc

git-svn-id: trunk@7062 -
florian 18 years ago
parent
commit
9140766d5a
2 changed files with 42 additions and 31 deletions
  1. 16 12
      compiler/cgobj.pas
  2. 26 19
      compiler/sparc/cgcpu.pas

+ 16 - 12
compiler/cgobj.pas

@@ -1152,12 +1152,12 @@ implementation
       begin
         intloadsize := packedbitsloadsize(sref.bitlen);
 
-{$if not defined(arm)}
+{$if not(defined(arm)) and not(defined(sparc))}
         { may need to be split into several smaller loads/stores }
         if (tf_requires_proper_alignment in target_info.flags) and
            (intloadsize <> sref.ref.alignment) then
           internalerror(2006082011);
-{$endif not defined(arm)}
+{$endif not(defined(arm)) and not(defined(sparc))}
 
         if (intloadsize = 0) then
           internalerror(2006081310);
@@ -1794,24 +1794,26 @@ implementation
         if ref.alignment<>0 then
           begin
             tmpref:=ref;
+            { we take care of the alignment now }
+            tmpref.alignment:=0;
             case FromSize of
               OS_16,OS_S16:
                 begin
                   if target_info.endian=endian_big then
                     inc(tmpref.offset);
-                  a_load_reg_ref(list,OS_8,OS_8,register,Ref);
+                  a_load_reg_ref(list,OS_8,OS_8,register,tmpref);
                   a_op_const_reg(list,OP_SHR,OS_8,8,register);
                   if target_info.endian=endian_big then
                     dec(tmpref.offset)
                   else
                     inc(tmpref.offset);
-                  a_load_reg_ref(list,OS_8,OS_8,register,Ref);
+                  a_load_reg_ref(list,OS_8,OS_8,register,tmpref);
                 end;
               OS_32,OS_S32:
                 begin
                   if target_info.endian=endian_big then
                     inc(tmpref.offset,3);
-                  a_load_reg_ref(list,OS_8,OS_8,register,Ref);
+                  a_load_reg_ref(list,OS_8,OS_8,register,tmpref);
                   for i:=1 to 3 do
                     begin
                       a_op_const_reg(list,OP_SHR,OS_8,8,register);
@@ -1819,11 +1821,11 @@ implementation
                         dec(tmpref.offset)
                       else
                         inc(tmpref.offset);
-                      a_load_reg_ref(list,OS_8,OS_8,register,Ref);
+                      a_load_reg_ref(list,OS_8,OS_8,register,tmpref);
                     end;
                 end
               else
-                a_load_reg_ref(list,fromsize,tosize,register,ref);
+                a_load_reg_ref(list,fromsize,tosize,register,tmpref);
             end;
           end
         else
@@ -1840,26 +1842,28 @@ implementation
         if ref.alignment<>0 then
           begin
             tmpref:=ref;
+            { we take care of the alignment now }
+            tmpref.alignment:=0;
             case FromSize of
               OS_16,OS_S16:
                 begin
                   if target_info.endian=endian_little then
                     inc(tmpref.offset);
-                  a_load_ref_reg(list,OS_8,OS_8,Ref,register);
+                  a_load_ref_reg(list,OS_8,OS_8,tmpref,register);
                   a_op_const_reg(list,OP_SHL,OS_8,8,register);
                   if target_info.endian=endian_little then
                     dec(tmpref.offset)
                   else
                     inc(tmpref.offset);
                   tmpreg:=getintregister(list,OS_INT);
-                  a_load_ref_reg(list,OS_8,OS_16,Ref,tmpreg);
+                  a_load_ref_reg(list,OS_8,OS_16,tmpref,tmpreg);
                   a_op_reg_reg(list,OP_OR,OS_16,tmpreg,register);
                 end;
               OS_32,OS_S32:
                 begin
                   if target_info.endian=endian_little then
                     inc(tmpref.offset,3);
-                  a_load_ref_reg(list,OS_8,OS_8,Ref,register);
+                  a_load_ref_reg(list,OS_8,OS_8,tmpref,register);
                   for i:=1 to 3 do
                     begin
                       a_op_const_reg(list,OP_SHL,OS_8,8,register);
@@ -1868,12 +1872,12 @@ implementation
                       else
                         inc(tmpref.offset);
                       tmpreg:=getintregister(list,OS_INT);
-                      a_load_ref_reg(list,OS_8,OS_32,Ref,tmpreg);
+                      a_load_ref_reg(list,OS_8,OS_32,tmpref,tmpreg);
                       a_op_reg_reg(list,OP_OR,OS_32,tmpreg,register);
                     end;
                 end
               else
-                a_load_ref_reg(list,fromsize,tosize,ref,register);
+                a_load_ref_reg(list,fromsize,tosize,tmpref,register);
             end;
           end
         else

+ 26 - 19
compiler/sparc/cgcpu.pas

@@ -505,25 +505,32 @@ implementation
       begin
         if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
           fromsize := tosize;
-        case fromsize of
-          OS_S8:
-            Op:=A_LDSB;{Load Signed Byte}
-          OS_8:
-            Op:=A_LDUB;{Load Unsigned Byte}
-          OS_S16:
-            Op:=A_LDSH;{Load Signed Halfword}
-          OS_16:
-            Op:=A_LDUH;{Load Unsigned Halfword}
-          OS_S32,
-          OS_32:
-            Op:=A_LD;{Load Word}
-          OS_S64,
-          OS_64:
-            Op:=A_LDD;{Load a Long Word}
-          else
-            InternalError(2002122101);
-        end;
-        handle_load_store(list,false,op,reg,ref);
+         if Ref.alignment<>0 then
+           begin
+             a_load_ref_reg_unaligned(list,FromSize,ToSize,ref,reg);
+           end
+         else
+           begin
+             case fromsize of
+               OS_S8:
+                 Op:=A_LDSB;{Load Signed Byte}
+               OS_8:
+                 Op:=A_LDUB;{Load Unsigned Byte}
+               OS_S16:
+                 Op:=A_LDSH;{Load Signed Halfword}
+               OS_16:
+                 Op:=A_LDUH;{Load Unsigned Halfword}
+               OS_S32,
+               OS_32:
+                 Op:=A_LD;{Load Word}
+               OS_S64,
+               OS_64:
+                 Op:=A_LDD;{Load a Long Word}
+               else
+                 InternalError(2002122101);
+             end;
+             handle_load_store(list,false,op,reg,ref);
+           end;
       end;