瀏覽代碼

Fix big endian issues

git-svn-id: trunk@21672 -
pierre 13 年之前
父節點
當前提交
74eb121d1c
共有 2 個文件被更改,包括 121 次插入48 次删除
  1. 77 6
      compiler/mips/cgcpu.pas
  2. 44 42
      compiler/mips/cpupara.pas

+ 77 - 6
compiler/mips/cgcpu.pas

@@ -1337,6 +1337,7 @@ var
   ra_save,framesave : taicpu;
   fmask,mask : dword;
   saveregs : tcpuregisterset;
+  StoreOp : TAsmOp;
   href:  treference;
   usesfpr, usesgpr, gotgot : boolean;
   reg : Tsuperregister;
@@ -1368,6 +1369,8 @@ begin
           fmask:=fmask or (1 shl ord(reg));
           href.offset:=nextoffset;
           lastfpuoffset:=nextoffset;
+          if cs_asm_source in current_settings.globalswitches then
+            helplist.concat(tai_comment.Create(strpnew(std_regname(newreg(R_FPUREGISTER,reg,R_SUBFS))+' register saved.')));
           helplist.concat(taicpu.op_reg_ref(A_SWC1,newreg(R_FPUREGISTER,reg,R_SUBFS),href));
           inc(nextoffset,4);
         end;
@@ -1396,7 +1399,11 @@ begin
           else if (reg=RS_R31) then
             ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
           else
-            helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
+            begin
+              if cs_asm_source in current_settings.globalswitches then
+                helplist.concat(tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))+' register saved.')));
+              helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
+            end;
           inc(nextoffset,4);
         end;
     end;
@@ -1411,10 +1418,16 @@ begin
 
   if (-LocalSize >= simm16lo) and (-LocalSize <= simm16hi) then
     begin
+      if cs_asm_source in current_settings.globalswitches then
+        list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size')));
       list.concat(Taicpu.Op_reg_reg_const(A_ADDIU,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,-LocalSize));
+      if cs_asm_source in current_settings.globalswitches then
+        list.concat(tai_comment.Create(strpnew('RA register saved.')));
       list.concat(ra_save);
       if assigned(framesave) then
         begin
+          if cs_asm_source in current_settings.globalswitches then
+            list.concat(tai_comment.Create(strpnew('Frame S8/FP register saved.')));
           list.concat(framesave);
           list.concat(Taicpu.op_reg_reg_const(A_ADDIU,NR_FRAME_POINTER_REG,
             NR_STACK_POINTER_REG,LocalSize));
@@ -1422,14 +1435,22 @@ begin
     end
   else
     begin
+      if cs_asm_source in current_settings.globalswitches then
+        list.concat(tai_comment.Create(strpnew('Stack register updated substract '+tostr(LocalSize)+' for local size using R1 register')));
       list.concat(Taicpu.Op_reg_const(A_LI,NR_R1,-LocalSize));
       list.concat(Taicpu.Op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R1));
+      if cs_asm_source in current_settings.globalswitches then
+        list.concat(tai_comment.Create(strpnew('RA register saved.')));
       list.concat(ra_save);
       if assigned(framesave) then
         begin
+          if cs_asm_source in current_settings.globalswitches then
+            list.concat(tai_comment.Create(strpnew('Frame register saved.')));
           list.concat(framesave);
-          list.concat(Taicpu.op_reg_reg_reg(A_SUB,NR_FRAME_POINTER_REG,
-            NR_STACK_POINTER_REG,NR_R3));
+          if cs_asm_source in current_settings.globalswitches then
+            list.concat(tai_comment.Create(strpnew('Frame register updated to $SP+R1 value')));
+          list.concat(Taicpu.op_reg_reg_reg(A_ADDU,NR_FRAME_POINTER_REG,
+            NR_STACK_POINTER_REG,NR_R1));
         end;
     end;
 
@@ -1449,11 +1470,47 @@ begin
             //if current_procinfo.framepointer=NR_STACK_POINTER_REG then
             //  href.offset:=register_offset[i]+Localsize
             //else
-              href.offset:=register_offset[i];
+            href.offset:=register_offset[i];
+{$ifdef MIPSEL}
+            if cs_asm_source in current_settings.globalswitches then
+              list.concat(tai_comment.Create(strpnew('Var '+
+              register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
+                +' saved to offset '+tostr(href.offset))));
             list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
-          end;
+{$else not MIPSEL, for big endian, size matters}
+            case register_size[i] of
+               OS_8,
+               OS_S8:
+                 StoreOp := A_SB;
+               OS_16,
+               OS_S16:
+                 StoreOp := A_SH;
+               OS_32,
+               OS_NO,
+               OS_F32,
+               OS_S32:
+                 StoreOp := A_SW;
+               OS_F64,
+               OS_64,
+               OS_S64:
+                 begin
+{$ifdef cpu64bitalu}
+                   StoreOp:=A_SD;
+{$else not cpu64bitalu}
+                   StoreOp:= A_SW;
+{$endif not cpu64bitalu}
+                 end
+               else
+                 internalerror(2012061801);
+            end;
+          if cs_asm_source in current_settings.globalswitches then
+            list.concat(tai_comment.Create(strpnew('Var '+
+              register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
+              +' saved to offset '+tostr(href.offset))));
+          list.concat(taicpu.op_reg_ref(StoreOp, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
+{$endif}
+        end;
     end;
-
   if (cs_create_pic in current_settings.moduleswitches) and
     (pi_needs_got in current_procinfo.flags) then
     begin
@@ -1792,8 +1849,15 @@ procedure TCGMIPS.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCG
 procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference);
 var
   tmpref: treference;
+  tmpreg: tregister;
 begin
   { Override this function to prevent loading the reference twice }
+  if target_info.endian = endian_big then
+    begin
+      tmpreg := reg.reglo;
+      reg.reglo := reg.reghi;
+      reg.reghi := tmpreg;
+    end;
   tmpref := ref;
   cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reglo, tmpref);
   Inc(tmpref.offset, 4);
@@ -1804,8 +1868,15 @@ end;
 procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64);
 var
   tmpref: treference;
+  tmpreg: tregister;
 begin
   { Override this function to prevent loading the reference twice }
+  if target_info.endian = endian_big then
+    begin
+      tmpreg := reg.reglo;
+      reg.reglo := reg.reghi;
+      reg.reghi := tmpreg;
+    end;
   tmpref := ref;
   cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reglo);
   Inc(tmpref.offset, 4);

+ 44 - 42
compiler/mips/cpupara.pas

@@ -61,6 +61,8 @@ interface
     type
       tparasupregs = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tsuperregister;
       tparasupregsused = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of boolean;
+      tparasupregsize = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of tcgsize;
+      tparasuprename = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of shortstring;
       tparasupregsoffset = array[0..MIPS_MAX_REGISTERS_USED_IN_CALL-1] of longint;
 
     const
@@ -68,10 +70,6 @@ interface
 
     type
       TMIPSParaManager=class(TParaManager)
-      var
-        param_offset:array[0..MIPS_MAX_OFFSET] of ^Aint;
-        intparareg,
-        parasize : longint;
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
         function  get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
@@ -83,6 +81,8 @@ interface
         function  create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
         function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
       private
+        intparareg,
+        intparasize : longint;
         procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
         procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist);
       end;
@@ -130,11 +130,6 @@ implementation
               begin
                 loc:=LOC_REGISTER;
                 register:=newreg(R_INTREGISTER,parasupregs[nr],R_SUBWHOLE);
-                if assigned(current_procinfo) then
-                  begin
-                    TMIPSProcInfo(current_procinfo).register_used[nr]:=true;
-                    TMIPSProcInfo(current_procinfo).register_offset[nr]:=nr*mips_sizeof_register_param;
-                  end;
               end
             else
               begin
@@ -144,6 +139,10 @@ implementation
                 reference.offset:=nr*mips_sizeof_register_param;
               end;
             size:=OS_INT;
+            { Be sure to reserve enough stack space tp cope with
+              that parameter }
+            if assigned(current_procinfo) then
+              TMIPSProcinfo(current_procinfo).allocate_push_parasize((nr+1)*mips_sizeof_register_param);
           end;
       end;
 
@@ -221,7 +220,6 @@ implementation
           in this case we use the first register R4 for it }
         if ret_in_param(def,p.proccalloption) then
           begin
-            { Reserve first register for ret_in_param }
             if intparareg=0 then
               inc(intparareg);
             if side=calleeside then
@@ -232,6 +230,14 @@ implementation
                 { return is at offset zero }
                 paraloc^.reference.offset:=0;
                 paraloc^.size:=retcgsize;
+                { Reserve first register for ret_in_param }
+                if assigned(current_procinfo) then
+                  begin
+                    TMIPSProcInfo(current_procinfo).register_used[0]:=true;
+                    TMIPSProcInfo(current_procinfo).register_size[0]:=retcgsize;
+                    TMIPSProcInfo(current_procinfo).register_name[0]:='ret_in_param_result';
+                    TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
+                  end;
               end
             else
               begin
@@ -304,8 +310,6 @@ implementation
 	can_use_float := true;
         for i:=0 to paras.count-1 do
           begin
-            if i<=MIPS_MAX_OFFSET then
-              param_offset[i] := Nil;
             hp:=tparavarsym(paras[i]);
             paradef := hp.vardef;
 
@@ -351,11 +355,11 @@ implementation
             hp.paraloc[side].intsize:=paralen;
             hp.paraloc[side].size:=paracgsize;
 	    { check the alignment, mips O32ABI require a nature alignment  }
-	    tmp := align(parasize, alignment) - parasize;
+            tmp := align(intparasize, alignment) - intparasize;
 	    while tmp > 0 do
               begin
                 inc(intparareg);
-	        inc(parasize,4);
+                inc(intparasize,4);
                 dec(tmp,4);
               end;
 
@@ -381,6 +385,8 @@ implementation
                     if assigned(current_procinfo) then
                       begin
                         TMIPSProcInfo(current_procinfo).register_used[0]:=true;
+                        TMIPSProcInfo(current_procinfo).register_name[0]:='result';
+                        TMIPSProcInfo(current_procinfo).register_size[0]:=paracgsize;
                         TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
                       end;
                     //if (intparareg<>1) then
@@ -402,10 +408,8 @@ implementation
                             TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
                         end;
                       paraloc^.reference.offset:=0;
-                      if i<=MIPS_MAX_OFFSET then
-                        param_offset[i] := @paraloc^.reference.offset;
                     end;
-                    inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
+                    inc(intparasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
                   end
                 { In case of po_delphi_nested_cc, the parent frame pointer
                   is always passed on the stack. }
@@ -424,16 +428,16 @@ implementation
                           begin
                             paraloc^.register:=newreg(R_FPUREGISTER, reg, R_SUBFD);
 			    inc(fpparareg);
-			    inc(intparareg);
-			    inc(intparareg);
-			    inc(parasize,8);
+                            inc(intparareg);
+                            inc(intparareg);
+                            inc(intparasize,8);
                           end
                         else
                           begin
                             paraloc^.register:=newreg(R_FPUREGISTER, reg, R_SUBFS);
 			    inc(fpparareg);
-			    inc(intparareg);
-			    inc(parasize,sizeof(aint));
+                            inc(intparareg);
+                            inc(intparasize,sizeof(aint));
                           end;
                       end
                     else { not can use float }
@@ -441,6 +445,8 @@ implementation
                        if assigned(current_procinfo) then
                          begin
                            TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
+                           TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
+                           TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paracgsize;
                            TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
                          end;
                        if side=callerside then
@@ -462,7 +468,7 @@ implementation
                            paraloc^.reference.offset:=intparareg*mips_sizeof_register_param;
                          end;
                        inc(intparareg);
-                       inc(parasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
+                       inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
                      end;
                   end
                 else
@@ -471,7 +477,7 @@ implementation
                     if side=callerside then
                       begin
                         paraloc^.reference.index := NR_STACK_POINTER_REG;
-                        paraloc^.reference.offset:=parasize;
+                        paraloc^.reference.offset:=intparasize;
                       end
                     else
                       begin
@@ -483,34 +489,35 @@ implementation
                             if assigned(current_procinfo) then
                               TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
                           end;
-                        paraloc^.reference.offset:=parasize;
-                        if i<=MIPS_MAX_OFFSET then
-                          param_offset[i] := @paraloc^.reference.offset;
+                        paraloc^.reference.offset:=intparasize;
                       end;
-                    inc(parasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
+                    inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
                   end;
                 dec(paralen,tcgsize2size[paraloc^.size]);
               end;
           end;
+        { O32 ABI reqires at least 16 bytes }
+        if (intparasize < 16) then
+          intparasize := 16;
+        if assigned(current_procinfo) then
+          begin
+            TMIPSProcinfo(current_procinfo).allocate_push_parasize(intparasize);
+          end;
       end;
 
 
     function TMIPSParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
       begin
         intparareg:=0;
-        parasize:=0;
+        intparasize:=0;
         { Create Function result paraloc }
         create_funcretloc_info(p,callerside);
         { calculate the registers for the normal parameters }
         create_paraloc_info_intern(p,callerside,p.paras);
         { append the varargs }
         create_paraloc_info_intern(p,callerside,varargspara);
-        { At least 16 bytes must be reserved for parameter
-          area in O32 ABI, this can be used by called function,
-          even if it has less parameter }
-        if (parasize < 16) then
-          parasize := 16;
-        result:=parasize;
+        { We need to return the size allocated on the stack }
+        result:=intparasize;
       end;
 
 
@@ -518,17 +525,12 @@ implementation
     function TMIPSParaManager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
       begin
         intparareg:=0;
-        parasize:=0;
+        intparasize:=0;
         { Create Function result paraloc }
         create_funcretloc_info(p,side);
         create_paraloc_info_intern(p,side,p.paras);
         { We need to return the size allocated on the stack }
-        { At least 16 bytes must be reserved for parameter
-          area in O32 ABI, this can be used by called function,
-          even if it has less parameter }
-        if (parasize < 16) then
-          parasize := 16;
-        result:=parasize;
+        result:=intparasize;
       end;