m68k: basic 68881 FPU register save/restore support. probably still needs some work here and there.

git-svn-id: trunk@29644 -
This commit is contained in:
Károly Balogh 2015-02-07 22:13:07 +00:00
parent 82fd859a19
commit a99c9c29b6
6 changed files with 101 additions and 27 deletions

View File

@ -276,7 +276,7 @@ interface
top_shifterop : (shifterop : pshifterop);
{$endif defined(arm) or defined(aarch64)}
{$ifdef m68k}
top_regset : (dataregset,addrregset:^tcpuregisterset);
top_regset : (dataregset,addrregset,fpuregset:^tcpuregisterset);
{$endif m68k}
{$ifdef jvm}
top_single : (sval:single);
@ -2653,6 +2653,7 @@ implementation
begin
dispose(dataregset);
dispose(addrregset);
dispose(fpuregset);
end;
{$endif m68k}
{$ifdef jvm}

View File

@ -41,7 +41,7 @@ type
taicpu = class(tai_cpu_abstract_sym)
opsize : topsize;
procedure loadregset(opidx:longint; const dataregs,addrregs:tcpuregisterset);
procedure loadregset(opidx:longint; const dataregs,addrregs,fpuregs:tcpuregisterset);
constructor op_none(op : tasmop);
constructor op_none(op : tasmop;_size : topsize);
@ -68,11 +68,11 @@ type
constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : treference);
constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : treference);
constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr: tcpuregisterset);
constructor op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: tregister);
constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
constructor op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr,_op1fpu: tcpuregisterset; _op2: tregister);
constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr: tcpuregisterset);
constructor op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: treference);
constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
constructor op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr,_op1fpu: tcpuregisterset; _op2: treference);
{ this is for Jmp instructions }
constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
@ -116,7 +116,7 @@ type
procedure taicpu.loadregset(opidx:longint; const dataregs,addrregs:tcpuregisterset);
procedure taicpu.loadregset(opidx:longint; const dataregs,addrregs,fpuregs:tcpuregisterset);
var
i : byte;
begin
@ -127,8 +127,10 @@ type
clearop(opidx);
new(dataregset);
new(addrregset);
new(fpuregset);
dataregset^:=dataregs;
addrregset^:=addrregs;
fpuregset^:=fpuregs;
typ:=top_regset;
for i:=RS_D0 to RS_D7 do
begin
@ -140,6 +142,11 @@ type
if assigned(add_reg_instruction_hook) and (i in addrregset^) then
add_reg_instruction_hook(self,newreg(R_ADDRESSREGISTER,i,R_SUBWHOLE));
end;
for i:=RS_FP0 to RS_FP7 do
begin
if assigned(add_reg_instruction_hook) and (i in fpuregset^) then
add_reg_instruction_hook(self,newreg(R_FPUREGISTER,i,R_SUBWHOLE));
end;
end;
end;
@ -327,43 +334,43 @@ type
end;
constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr: tcpuregisterset);
constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
Begin
inherited create(op);
init(_size);
ops:=2;
loadref(0,_op1);
loadregset(1,_op2data,_op2addr);
loadregset(1,_op2data,_op2addr,_op2fpu);
end;
constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: treference);
constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1data,_op1addr,_op1fpu: tcpuregisterset; _op2: treference);
Begin
inherited create(op);
init(_size);
ops:=2;
loadregset(0,_op1data,_op1addr);
loadregset(0,_op1data,_op1addr,_op1fpu);
loadref(1,_op2);
End;
constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr: tcpuregisterset);
constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2data,_op2addr,_op2fpu: tcpuregisterset);
Begin
inherited create(op);
init(_size);
ops:=2;
loadreg(0,_op1);
loadregset(1,_op2data,_op2addr);
loadregset(1,_op2data,_op2addr,_op2fpu);
end;
constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr: tcpuregisterset; _op2: tregister);
constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1data,_op1addr,_op1fpu: tcpuregisterset; _op2: tregister);
Begin
inherited create(op);
init(_size);
ops:=2;
loadregset(0,_op1data,_op1addr);
loadregset(0,_op1data,_op1addr,_op1fpu);
loadreg(1,_op2);
End;

View File

@ -173,6 +173,11 @@ interface
if i in o.addrregset^ then
hs:=hs+gas_regname(newreg(R_ADDRESSREGISTER,i,R_SUBWHOLE))+'/';
end;
for i:=RS_FP0 to RS_FP7 do
begin
if i in o.fpuregset^ then
hs:=hs+gas_regname(newreg(R_FPUREGISTER,i,R_SUBWHOLE))+'/';
end;
delete(hs,length(hs),1);
getopstr := hs;
end;

View File

@ -1753,9 +1753,12 @@ unit cgcpu;
var
dataregs: tcpuregisterset;
addrregs: tcpuregisterset;
fpuregs: tcpuregisterset;
href : treference;
hreg : tregister;
hfreg : tregister;
size : longint;
fsize : longint;
r : integer;
begin
{ The code generated by the section below, particularly the movem.l
@ -1766,10 +1769,13 @@ unit cgcpu;
AS version instead. (KB) }
dataregs:=[];
addrregs:=[];
fpuregs:=[];
{ calculate temp. size }
size:=0;
fsize:=0;
hreg:=NR_NO;
hfreg:=NR_NO;
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
@ -1785,14 +1791,22 @@ unit cgcpu;
inc(size,sizeof(aint));
addrregs:=addrregs + [saved_address_registers[r]];
end;
if uses_registers(R_FPUREGISTER) then
for r:=low(saved_fpu_registers) to high(saved_fpu_registers) do
if saved_fpu_registers[r] in rg[R_FPUREGISTER].used_in_proc then
begin
hfreg:=newreg(R_FPUREGISTER,saved_fpu_registers[r],R_SUBWHOLE);
inc(fsize,10{sizeof(extended)});
fpuregs:=fpuregs + [saved_fpu_registers[r]];
end;
{ 68k has no MM registers }
if uses_registers(R_MMREGISTER) then
internalerror(2014030201);
if size>0 then
if (size+fsize) > 0 then
begin
tg.GetTemp(list,size,sizeof(aint),tt_noreuse,current_procinfo.save_regs_ref);
tg.GetTemp(list,size+fsize,sizeof(aint),tt_noreuse,current_procinfo.save_regs_ref);
include(current_procinfo.flags,pi_has_saved_regs);
{ Copy registers to temp }
@ -1804,10 +1818,22 @@ unit cgcpu;
list.concat(taicpu.op_const_reg(A_ADDA,S_L,href.offset,NR_A0));
reference_reset_base(href,NR_A0,0,sizeof(pint));
end;
if size = sizeof(aint) then
list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hreg,href))
else
list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,dataregs,addrregs,href));
if size > 0 then
if size = sizeof(aint) then
list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hreg,href))
else
list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,dataregs,addrregs,[],href));
if fsize > 0 then
begin
{ size is always longword aligned, while fsize is not }
inc(href.offset,size);
if fsize = 10{sizeof(extended)} then
list.concat(taicpu.op_reg_ref(A_FMOVE,S_FX,hfreg,href))
else
list.concat(taicpu.op_regset_ref(A_FMOVEM,S_FX,[],[],fpuregs,href));
end;
end;
end;
@ -1816,20 +1842,26 @@ unit cgcpu;
var
dataregs: tcpuregisterset;
addrregs: tcpuregisterset;
fpuregs : tcpuregisterset;
href : treference;
r : integer;
hreg : tregister;
hfreg : tregister;
size : longint;
fsize : longint;
begin
{ see the remark about buggy GNU AS versions in g_save_registers() (KB) }
dataregs:=[];
addrregs:=[];
fpuregs:=[];
if not(pi_has_saved_regs in current_procinfo.flags) then
exit;
{ Copy registers from temp }
size:=0;
fsize:=0;
hreg:=NR_NO;
hfreg:=NR_NO;
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
@ -1851,6 +1883,17 @@ unit cgcpu;
addrregs:=addrregs + [saved_address_registers[r]];
end;
if uses_registers(R_FPUREGISTER) then
for r:=low(saved_address_registers) to high(saved_address_registers) do
if saved_fpu_registers[r] in rg[R_FPUREGISTER].used_in_proc then
begin
inc(fsize,10{sizeof(extended)});
hfreg:=newreg(R_FPUREGISTER,saved_address_registers[r],R_SUBWHOLE);
{ Allocate register so the optimizer does not remove the load }
a_reg_alloc(list,hfreg);
fpuregs:=fpuregs + [saved_fpu_registers[r]];
end;
{ 68k has no MM registers }
if uses_registers(R_MMREGISTER) then
internalerror(2014030202);
@ -1863,10 +1906,22 @@ unit cgcpu;
list.concat(taicpu.op_const_reg(A_ADDA,S_L,href.offset,NR_A0));
reference_reset_base(href,NR_A0,0,sizeof(pint));
end;
if size = sizeof(aint) then
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,hreg))
else
list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,href,dataregs,addrregs));
if size > 0 then
if size = sizeof(aint) then
list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,hreg))
else
list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,href,dataregs,addrregs,[]));
if fsize > 0 then
begin
{ size is always longword aligned, while fsize is not }
inc(href.offset,size);
if fsize = 10{sizeof(extended)} then
list.concat(taicpu.op_ref_reg(A_FMOVE,S_FX,href,hfreg))
else
list.concat(taicpu.op_ref_regset(A_FMOVEM,S_FX,href,[],[],fpuregs));
end;
tg.UnGetTemp(list,current_procinfo.save_regs_ref);
end;

View File

@ -50,6 +50,7 @@ unit cpupara;
function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;override;
function get_volatile_registers_int(calloption:tproccalloption):tcpuregisterset;override;
function get_volatile_registers_address(calloption:tproccalloption):tcpuregisterset;override;
function get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;override;
private
function parse_loc_string_to_register(var locreg: tregister; const s : string): boolean;
function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
@ -79,6 +80,11 @@ unit cpupara;
Result:=VOLATILE_ADDRESSREGISTERS;
end;
function tm68kparamanager.get_volatile_registers_fpu(calloption:tproccalloption):tcpuregisterset;
begin
{ fp0 and fp1 are considered volatile }
Result:=VOLATILE_FPUREGISTERS;
end;
function tm68kparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
var

View File

@ -54,7 +54,7 @@ type
OPR_LOCAL : (localvarsize, localconstoffset: asizeint;localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
OPR_REGISTER : (reg:tregister);
{$ifdef m68k}
OPR_REGSET : (regsetdata,regsetaddr : tcpuregisterset);
OPR_REGSET : (regsetdata,regsetaddr,regsetfpu : tcpuregisterset);
{$endif m68k}
{$ifdef powerpc}
OPR_COND : (cond : tasmcond);
@ -1057,7 +1057,7 @@ end;
ai.loadref(i-1,ref);
{$ifdef m68k}
OPR_REGSET:
ai.loadregset(i-1,regsetdata,regsetaddr);
ai.loadregset(i-1,regsetdata,regsetaddr,regsetfpu);
{$endif}
{$ifdef ARM}
OPR_REGSET: