m68k implementation of g_save_registers and g_restore_registers using movem.l

git-svn-id: trunk@26923 -
This commit is contained in:
Károly Balogh 2014-03-02 14:58:05 +00:00
parent ae28ecd5f8
commit 1d5f74fae0

View File

@ -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