Selaa lähdekoodia

* MIPS: fixed parameter handling for big-endian targets, and removed a lot of garbage.
* Parameters passed in registers are no longer forced to stack, therefore assembler routines using 'lw' instruction to load such parameters must have it changed to 'move' (tb0072.pp).

git-svn-id: trunk@23627 -

sergei 12 vuotta sitten
vanhempi
commit
30247d8961
3 muutettua tiedostoa jossa 35 lisäystä ja 144 poistoa
  1. 6 41
      compiler/mips/cgcpu.pas
  2. 27 101
      compiler/mips/cpupara.pas
  3. 2 2
      tests/tbs/tb0072.pp

+ 6 - 41
compiler/mips/cgcpu.pas

@@ -710,11 +710,9 @@ procedure TCGMIPS.a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCGSize; reg:
 var
   op: tasmop;
 begin
-
-  if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
-    fromsize := tosize;
-  case fromsize of
-    { signed integer registers }
+  if (TCGSize2Size[fromsize] < TCGSize2Size[tosize]) then
+    a_load_reg_reg(list,fromsize,tosize,reg,reg);
+  case tosize of
     OS_8,
     OS_S8:
       Op := A_SB;
@@ -1394,7 +1392,7 @@ begin
   if nostackframe then
     exit;
 
-  if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
+  if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
     a_reg_alloc(list,NR_FRAME_POINTER_REG);
 
   helplist:=TAsmList.Create;
@@ -1434,7 +1432,7 @@ begin
   nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
   saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
   include(saveregs,RS_R31);
-  if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
+  if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
     include(saveregs,RS_FRAME_POINTER_REG);
   if (cs_create_pic in current_settings.moduleswitches) and
      (pi_needs_got in current_procinfo.flags) then
@@ -1561,44 +1559,11 @@ begin
             //  href.offset:=register_offset[i]+Localsize
             //else
             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));
-{$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
@@ -1646,7 +1611,7 @@ begin
        nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
        saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
        include(saveregs,RS_R31);
-       if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
+       if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
          include(saveregs,RS_FRAME_POINTER_REG);
        if (cs_create_pic in current_settings.moduleswitches) and
           (pi_needs_got in current_procinfo.flags) then

+ 27 - 101
compiler/mips/cpupara.pas

@@ -216,31 +216,6 @@ implementation
               begin
                 if intparareg=0 then
                   inc(intparareg);
-                if side=calleeside then
-                  begin
-                    result.reset;
-                    paraloc:=result.add_location;
-                    paraloc^.loc:=LOC_REFERENCE;
-                    paraloc^.reference.index:=NR_STACK_POINTER_REG;
-                    { 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
-                    getIntParaLoc(p,1,result);
-                    result.def:=retdef;
-                  end;
-                // This is now done in set_common_funcretloc_info already
-                // result.def:=getpointerdef(result.def);
               end;
             exit;
           end;
@@ -350,9 +325,17 @@ implementation
             //writeln('para: ',hp.Name,' typ=',hp.vardef.typ,' paracgsize=',paracgsize,' align=',hp.vardef.alignment);
             hp.paraloc[side].reset;
             hp.paraloc[side].Alignment:=alignment;
-            if paracgsize=OS_NO then
+            if (paracgsize=OS_NO) or
+              { Ordinals on caller side must be promoted to machine word }
+              ((target_info.endian=endian_big) and     // applies to little-endian too?
+              (paradef.typ<>recorddef) and
+              (side=callerside) and
+              (paralen<tcgsize2size[OS_INT]))then
               begin
-                paracgsize:=OS_32;
+                if is_signed(paradef) then
+                  paracgsize:=OS_S32
+                else
+                  paracgsize:=OS_32;
                 paralen:=align(paralen,4);
               end
             else
@@ -395,48 +378,15 @@ implementation
                 else
                   paraloc^.size:=paracgsize;
 
-                { big-endian targets require that record data stored in parameter
-                  registers is left-aligned }
-                if (target_info.endian=endian_big) and
-                   (paradef.typ = recorddef) and
-                   (tcgsize2size[paraloc^.size] <> sizeof(aint)) then
-                  begin
-                    paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
-                    paraloc^.size := OS_INT;
-                  end;
-
                 { ret in param? }
                 if (vo_is_funcret in hp.varoptions) and
                   is_abi_record(hp.vardef) then
                   begin
                     { This should be the first parameter }
-                    if (side=calleeside) and 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]:=paraloc^.size;
-                        TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
-                      end;
                     //if (intparareg<>1) then
                     //  Comment(V_Warning,'intparareg should be one for funcret in TMipsParaManager.create_paraloc_info_intern');
-                    if side=callerside then
-                    begin
-                      paraloc^.loc:=LOC_REGISTER;
-                      paraloc^.register:=newreg(R_INTREGISTER,parasupregs[0],R_SUBWHOLE);
-                    end
-                    else
-                    begin
-                      paraloc^.loc:=LOC_REFERENCE;
-                      if (po_nostackframe in p.procoptions) then
-                        paraloc^.reference.index := NR_STACK_POINTER_REG
-                      else
-                        begin
-                          paraloc^.reference.index := NR_FRAME_POINTER_REG;
-                          if assigned(current_procinfo) then
-                            TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
-                        end;
-                      paraloc^.reference.offset:=0;
-                    end;
+                    paraloc^.loc:=LOC_REGISTER;
+                    paraloc^.register:=newreg(R_INTREGISTER,parasupregs[0],R_SUBWHOLE);
                     inc(intparasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
                   end
                 { In case of po_delphi_nested_cc, the parent frame pointer
@@ -470,30 +420,17 @@ implementation
                       end
                     else { not can use float }
                      begin
-                       if (side=calleeside) and assigned(current_procinfo) then
+                       paraloc^.loc:=LOC_REGISTER;
+                       paraloc^.register:=newreg(R_INTREGISTER,parasupregs[intparareg],R_SUBWHOLE);
+
+                       { big-endian targets require that record data stored in parameter
+                         registers is left-aligned }
+                       if (target_info.endian=endian_big) and
+                          (paradef.typ=recorddef) and
+                          (paralen<tcgsize2size[OS_INT]) then
                          begin
-                           TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
-                           TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
-                           TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paraloc^.size;
-                           TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
-                         end;
-                       if side=callerside then
-                         begin
-                           paraloc^.loc:=LOC_REGISTER;
-                           paraloc^.register:=newreg(R_INTREGISTER,parasupregs[intparareg],R_SUBWHOLE);
-                         end
-                       else
-                         begin
-                           paraloc^.loc:=LOC_REFERENCE;
-                           if (po_nostackframe in p.procoptions) then
-                             paraloc^.reference.index := NR_STACK_POINTER_REG
-                           else
-                             begin
-                               paraloc^.reference.index := NR_FRAME_POINTER_REG;
-                               if assigned(current_procinfo) then
-                                 TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
-                             end;
-                           paraloc^.reference.offset:=intparareg*mips_sizeof_register_param;
+                           paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
+                           paraloc^.size := OS_INT;
                          end;
                        inc(intparareg);
                        inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
@@ -504,16 +441,6 @@ implementation
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.size:=int_cgsize(paralen);
 
-                    { Force size to multiple of 4 for records passed by value,
-                      to obtain correct memory layout for big endian }
-(*
-                    if (paradef.typ = recorddef) and 
-                       (tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
-                      begin
-                        inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
-                        paraloc^.size := OS_32;
-                      end;
-*)
                     if side=callerside then
                       begin
                         paraloc^.reference.index := NR_STACK_POINTER_REG;
@@ -530,6 +457,11 @@ implementation
                               TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
                           end;
                         paraloc^.reference.offset:=intparasize;
+
+                        if (target_info.endian=endian_big) and
+                           (paralen<tcgsize2size[OS_INT]) and
+                           (paradef.typ<>recorddef) then
+                          inc(paraloc^.reference.offset,4-paralen);
                       end;
                     inc(intparasize,align(paralen,mips_sizeof_register_param));
                     paralen:=0;
@@ -540,12 +472,6 @@ implementation
         { O32 ABI reqires at least 16 bytes }
         if (intparasize < 16) then
           intparasize := 16;
-        { Increase maxpushparasize, but only if not examining itself }
-        //if assigned(current_procinfo) and (side=callerside) and
-        //   (current_procinfo.procdef <> p) then
-        //  begin
-        //    TMIPSProcinfo(current_procinfo).allocate_push_parasize(intparasize);
-        //  end;
       end;
 
 

+ 2 - 2
tests/tbs/tb0072.pp

@@ -55,8 +55,8 @@ end;
 {$ifdef CPUMIPS}
 {$define SUPPORTED}
 asm
-  lw $t1,x
-  lw $t2,y
+  move $t1,x
+  move $t2,y
 end;
 {$endif CPUMIPS}
 {$ifndef SUPPORTED}