Browse Source

m68k implementation of g_save_registers and g_restore_registers using movem.l

git-svn-id: trunk@26923 -
Károly Balogh 11 years ago
parent
commit
1d5f74fae0
1 changed files with 110 additions and 2 deletions
  1. 110 2
      compiler/m68k/cgcpu.pas

+ 110 - 2
compiler/m68k/cgcpu.pas

@@ -85,8 +85,8 @@ unit cgcpu;
         procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
         procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
 
-//        procedure g_restore_frame_pointer(list : TAsmList);override;
-//        procedure g_return_from_proc(list : TAsmList;parasize : tcgint);override;
+        procedure g_save_registers(list:TAsmList);override;
+        procedure g_restore_registers(list:TAsmList);override;
 
         procedure g_adjust_self_value(list:TAsmList;procdef:tprocdef;ioffset:tcgint);override;
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
@@ -1752,6 +1752,114 @@ unit cgcpu;
       end;
 
 
+    procedure tcg68k.g_save_registers(list:TAsmList);
+      var
+        dataregs: tcpuregisterset;
+        addrregs: tcpuregisterset;
+        href : treference;
+        hreg : tregister;
+        size : longint;
+        r : integer;
+      begin
+        { The code generated by the section below, particularly the movem.l
+          instruction is known to cause an issue when compiled by some GNU 
+          assembler versions (I had it with 2.17, while 2.24 seems OK.) 
+          when you run into this problem, just call inherited here instead
+          to skip the movem.l generation. But better just use working GNU
+          AS version instead. (KB) }
+        dataregs:=[];
+        addrregs:=[];
+
+        { calculate temp. size }
+        size:=0;
+        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+            begin
+              hreg:=newreg(R_INTREGISTER,saved_address_registers[r],R_SUBWHOLE);
+              inc(size,sizeof(aint));
+              dataregs:=dataregs + [saved_standard_registers[r]];
+            end;
+        if uses_registers(R_ADDRESSREGISTER) then
+          for r:=low(saved_address_registers) to high(saved_address_registers) do
+            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+              begin
+                hreg:=newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE);
+                inc(size,sizeof(aint));
+                addrregs:=addrregs + [saved_address_registers[r]];
+              end;
+
+        { 68k has no MM registers }
+        if uses_registers(R_MMREGISTER) then
+          internalerror(2014030201);
+
+        if size>0 then
+          begin
+            tg.GetTemp(list,size,sizeof(aint),tt_noreuse,current_procinfo.save_regs_ref);
+            include(current_procinfo.flags,pi_has_saved_regs);
+
+            { Copy registers to temp }
+            href:=current_procinfo.save_regs_ref;
+            if size = sizeof(aint) then
+              a_load_reg_ref(list, OS_32, OS_32, hreg, href)
+            else
+              list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,dataregs,addrregs,href));
+          end;
+      end;
+
+
+    procedure tcg68k.g_restore_registers(list:TAsmList);
+      var
+        dataregs: tcpuregisterset;
+        addrregs: tcpuregisterset;
+        href    : treference;
+        r       : integer;
+        hreg    : tregister;
+        size    : longint;
+      begin
+        { see the remark about buggy GNU AS versions in g_save_registers() (KB) }
+        dataregs:=[];
+        addrregs:=[];
+
+        if not(pi_has_saved_regs in current_procinfo.flags) then
+          exit;
+        { Copy registers from temp }
+        size:=0;
+        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+            begin
+              inc(size,sizeof(aint));
+              hreg:=newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE);
+              { Allocate register so the optimizer does not remove the load }
+              a_reg_alloc(list,hreg);
+              dataregs:=dataregs + [saved_standard_registers[r]];
+            end;
+
+        if uses_registers(R_ADDRESSREGISTER) then
+          for r:=low(saved_address_registers) to high(saved_address_registers) do
+            if saved_address_registers[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+              begin
+                inc(size,sizeof(aint));
+                hreg:=newreg(R_ADDRESSREGISTER,saved_address_registers[r],R_SUBWHOLE);
+                { Allocate register so the optimizer does not remove the load }
+                a_reg_alloc(list,hreg);
+                addrregs:=addrregs + [saved_address_registers[r]];
+              end;
+
+        { 68k has no MM registers }
+        if uses_registers(R_MMREGISTER) then
+          internalerror(2014030202);
+
+        { Restore registers from temp }
+        href:=current_procinfo.save_regs_ref;
+        if size = sizeof(aint) then
+          a_load_ref_reg(list, OS_32, OS_32, href, hreg)
+        else
+          list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,href,dataregs,addrregs));
+
+        tg.UnGetTemp(list,current_procinfo.save_regs_ref);
+      end;
+
+
     procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
       begin
         case _oldsize of