Bläddra i källkod

* m68k: support stack cleanup at caller side, fixed calculation of pushed parameters size and offsets and cleaned out another pile of junk.
* Parameter offsets are now calculated similar to other targets, target_info,first_parm_offset is applied only to callee side, while at caller side offsets start from 0.
* For cdecl procedures, parameters are removed by caller, for the rest it's still done by callee (resembles i386 target, except there is no 'register' calling convention).

git-svn-id: trunk@28185 -

sergei 11 år sedan
förälder
incheckning
b7da785688
3 ändrade filer med 21 tillägg och 28 borttagningar
  1. 2 5
      compiler/m68k/cgcpu.pas
  2. 11 23
      compiler/m68k/cpupara.pas
  3. 8 0
      compiler/m68k/n68kcal.pas

+ 2 - 5
compiler/m68k/cgcpu.pas

@@ -1601,9 +1601,6 @@ unit cgcpu;
         if not nostackframe then
           begin
             list.concat(taicpu.op_reg(A_UNLK,S_NO,NR_FRAME_POINTER_REG));
-            parasize := parasize - target_info.first_parm_offset; { i'm still not 100% confident that this is
-                                                                    correct here, but at least it looks less
-                                                                    hacky, and makes some sense (KB) }
 
             { if parasize is less than zero here, we probably have a cdecl function.
               According to the info here: http://www.makestuff.eu/wordpress/gcc-68000-abi/
@@ -1612,7 +1609,7 @@ unit cgcpu;
               caller side free, which looks like a PITA to support. We have to figure this 
               out later. More info welcomed. (KB) }
 
-            if (parasize > 0) then
+            if (parasize > 0) and not (current_procinfo.procdef.proccalloption in clearstack_pocalls) then
               begin
                 if current_settings.cputype=cpu_mc68020 then
                   list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
@@ -1926,7 +1923,7 @@ unit cgcpu;
                   begin
                     { offset in the wrapper needs to be adjusted for the stored
                       return address }
-                    reference_reset_base(href,reference.index,reference.offset-sizeof(pint),sizeof(pint));
+                    reference_reset_base(href,reference.index,reference.offset+sizeof(pint),sizeof(pint));
                     { plain 68k could use SUBI on href directly, but this way it works on Coldfire too
                       and it's probably smaller code for the majority of cases (if ioffset small, the
                       load will use MOVEQ) (KB) }

+ 11 - 23
compiler/m68k/cpupara.pas

@@ -52,9 +52,8 @@ unit cpupara;
           function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
          private
           function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
-          procedure init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
           function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-                                               var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
+                                                var cur_stack_offset: aword):longint;
        end;
 
   implementation
@@ -135,13 +134,6 @@ unit cpupara;
         end;
       end;
 
-    procedure tm68kparamanager.init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
-      begin
-        cur_stack_offset:=8;
-        curintreg:=RS_D0;
-        curfloatreg:=RS_FP0;
-      end;
-
 
     function tm68kparamanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
       begin
@@ -228,17 +220,15 @@ unit cpupara;
     function tm68kparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
       var
         cur_stack_offset: aword;
-        curintreg, curfloatreg: tsuperregister;
       begin
-        init_values(curintreg,curfloatreg,cur_stack_offset);
-
-        result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,cur_stack_offset);
+        cur_stack_offset:=0;
+        result:=create_paraloc_info_intern(p,side,p.paras,cur_stack_offset);
 
         create_funcretloc_info(p,side);
       end;
 
     function tm68kparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
-                               var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
+                               var cur_stack_offset: aword):longint;
       var
         paraloc      : pcgparalocation;
         hp           : tparavarsym;
@@ -246,12 +236,10 @@ unit cpupara;
         paralen      : aint;
         paradef      : tdef;
         i            : longint;
-        stack_offset : longint;
         firstparaloc : boolean;
 
       begin
         result:=0;
-        stack_offset:=cur_stack_offset;
 
         for i:=0 to paras.count-1 do
           begin
@@ -328,23 +316,24 @@ unit cpupara;
                 else
                   paraloc^.size:=int_cgsize(paralen);
 
-                paraloc^.reference.offset:=stack_offset;
+                paraloc^.reference.offset:=cur_stack_offset;
                 if (side = callerside) then
                   paraloc^.reference.index:=NR_STACK_POINTER_REG
                 else
                   begin
                     paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                    inc(paraloc^.reference.offset,target_info.first_parm_offset);
                     { M68K is a big-endian target }
                     if (paralen<tcgsize2size[OS_INT]) then
                       inc(paraloc^.reference.offset,4-paralen);
                   end;
-                inc(stack_offset,align(paralen,4));
+                inc(cur_stack_offset,align(paralen,4));
                 paralen := 0;
 
                 firstparaloc:=false;
               end;
           end;
-         result:=stack_offset;
+         result:=cur_stack_offset;
       end;
 
 
@@ -403,14 +392,13 @@ unit cpupara;
     function tm68kparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
       var
         cur_stack_offset: aword;
-        curintreg, curfloatreg: tsuperregister;
       begin
-        init_values(curintreg,curfloatreg,cur_stack_offset);
+        cur_stack_offset:=0;
 
-        result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,cur_stack_offset);
+        result:=create_paraloc_info_intern(p,callerside,p.paras,cur_stack_offset);
         if (p.proccalloption in cstylearrayofconst) then
           { just continue loading the parameters in the registers }
-          result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,cur_stack_offset)
+          result:=create_paraloc_info_intern(p,callerside,varargspara,cur_stack_offset)
         else
           internalerror(200410231);
       end;

+ 8 - 0
compiler/m68k/n68kcal.pas

@@ -34,6 +34,7 @@ interface
          procedure gen_syscall_para(para: tcallparanode); override;
         public
          procedure do_syscall;override;
+         procedure pop_parasize(pop_size: longint);override;
        end;
 
 
@@ -50,6 +51,13 @@ implementation
       cg64f32,cgcpu,cpupi,procinfo;
 
 
+    procedure tm68kcallnode.pop_parasize(pop_size: longint);
+      begin
+        if pop_size<>0 then
+          current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_ADD,S_L,pop_size,NR_SP));
+      end;
+
+
     procedure tm68kcallnode.gen_syscall_para(para: tcallparanode);
       begin
         { lib parameter has no special type but proccalloptions must be a syscall }