* fix register method pointer for ppc64 and x86_64-linux

git-svn-id: trunk@22351 -
This commit is contained in:
florian 2012-09-07 15:15:10 +00:00
parent 95c69f1f9e
commit d93cee995b
5 changed files with 140 additions and 16 deletions

View File

@ -465,6 +465,7 @@ unit cgobj;
tcg128 = class
procedure a_load128_reg_reg(list : TAsmList;regsrc,regdst : tregister128);virtual;
procedure a_load128_reg_ref(list : TAsmList;reg : tregister128;const ref : treference);virtual;
procedure a_load128_ref_reg(list : TAsmList;const ref : treference;reg : tregister128);virtual;
procedure a_load128_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);virtual;
procedure a_load128_reg_loc(list : TAsmList;reg : tregister128;const l : tlocation);virtual;
@ -2636,6 +2637,41 @@ implementation
end;
procedure tcg128.a_load128_ref_reg(list: TAsmList; const ref: treference;
reg: tregister128);
var
tmpreg: tregister;
tmpref: treference;
begin
if target_info.endian = endian_big then
begin
tmpreg := reg.reglo;
reg.reglo := reg.reghi;
reg.reghi := tmpreg;
end;
tmpref := ref;
if (tmpref.base=reg.reglo) then
begin
tmpreg:=cg.getaddressregister(list);
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
tmpref.base:=tmpreg;
end
else
{ this works only for the i386, thus the i386 needs to override }
{ this method and this method must be replaced by a more generic }
{ implementation FK }
if (tmpref.index=reg.reglo) then
begin
tmpreg:=cg.getaddressregister(list);
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
tmpref.index:=tmpreg;
end;
cg.a_load_ref_reg(list,OS_64,OS_64,tmpref,reg.reglo);
inc(tmpref.offset,8);
cg.a_load_ref_reg(list,OS_64,OS_64,tmpref,reg.reghi);
end;
procedure tcg128.a_load128_loc_ref(list: TAsmList; const l: tlocation;
const ref: treference);
begin

View File

@ -1359,7 +1359,7 @@ implementation
begin
{$ifdef cpu64bitalu}
{ use cg128 only if no "chained" location is used }
if (l.size in [OS_128,OS_S128]) and (cgpara.Size in [OS_128,OS_S128]) then
if is_methodpointer(cgpara.def) and (l.size in [OS_128,OS_S128]) and (cgpara.Size in [OS_128,OS_S128]) then
cg128.a_load128_loc_cgpara(list,l,cgpara)
else
{$else cpu64bitalu}

View File

@ -716,11 +716,15 @@ implementation
LOC_REGISTER,
LOC_CREGISTER :
begin
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if left.location.size in [OS_128,OS_S128] then
cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
else
{$else cpu64bitalu}
if left.location.size in [OS_64,OS_S64] then
cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
else
{$endif not cpu64bitalu}
{$endif cpu64bitalu}
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
end;
LOC_FPUREGISTER,

View File

@ -205,7 +205,7 @@ implementation
if getsupreg(location.register64.reghi)<first_int_imreg then
cg.ungetcpuregister(list,location.register64.reghi);
end
{$endif}
{$endif cpu64bitalu}
else
if getsupreg(location.register)<first_int_imreg then
cg.ungetcpuregister(list,location.register);
@ -317,7 +317,17 @@ implementation
end;
LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
begin
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if opsize in [OS_128,OS_S128] then
begin
hlcg.location_force_reg(list,p.location,p.resultdef,hlcg.tcgsize2orddef(opsize),true);
tmpreg:=cg.getintregister(list,OS_64);
cg.a_op_reg_reg_reg(list,OP_OR,OS_64,p.location.register128.reglo,p.location.register128.reghi,tmpreg);
location_reset(p.location,LOC_REGISTER,OS_64);
p.location.register:=tmpreg;
opsize:=OS_64;
end;
{$else cpu64bitalu}
if opsize in [OS_64,OS_S64] then
begin
hlcg.location_force_reg(list,p.location,p.resultdef,hlcg.tcgsize2orddef(opsize),true);
@ -327,7 +337,7 @@ implementation
p.location.register:=tmpreg;
opsize:=OS_32;
end;
{$endif not cpu64bitalu}
{$endif cpu64bitalu}
cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,current_procinfo.CurrTrueLabel);
cg.a_jmp_always(list,current_procinfo.CurrFalseLabel);
end;
@ -614,14 +624,21 @@ implementation
location_reset(l,LOC_CREGISTER,l.size)
else
location_reset(l,LOC_REGISTER,l.size);
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if l.size in [OS_128,OS_S128,OS_F128] then
begin
l.register128.reglo:=cg.getintregister(list,OS_64);
l.register128.reghi:=cg.getintregister(list,OS_64);
end
else
{$else cpu64bitalu}
if l.size in [OS_64,OS_S64,OS_F64] then
begin
l.register64.reglo:=cg.getintregister(list,OS_32);
l.register64.reghi:=cg.getintregister(list,OS_32);
end
else
{$endif not cpu64bitalu}
{$endif cpu64bitalu}
l.register:=cg.getintregister(list,l.size);
end;
end;
@ -773,7 +790,14 @@ implementation
case loc.loc of
LOC_CREGISTER:
begin
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if loc.size in [OS_128,OS_S128] then
begin
loc.register128.reglo:=cg.getintregister(list,OS_64);
loc.register128.reghi:=cg.getintregister(list,OS_64);
end
else
{$else cpu64bitalu}
if loc.size in [OS_64,OS_S64] then
begin
loc.register64.reglo:=cg.getintregister(list,OS_32);
@ -803,14 +827,21 @@ implementation
begin
{ Allocate register already, to prevent first allocation to be
inside a loop }
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if sym.initialloc.size in [OS_128,OS_S128] then
begin
cg.a_reg_sync(list,sym.initialloc.register128.reglo);
cg.a_reg_sync(list,sym.initialloc.register128.reghi);
end
else
{$else cpu64bitalu}
if sym.initialloc.size in [OS_64,OS_S64] then
begin
cg.a_reg_sync(list,sym.initialloc.register64.reglo);
cg.a_reg_sync(list,sym.initialloc.register64.reghi);
end
else
{$endif not cpu64bitalu}
{$endif cpu64bitalu}
cg.a_reg_sync(list,sym.initialloc.register);
end;
sym.localloc:=sym.initialloc;
@ -897,7 +928,53 @@ implementation
LOC_REGISTER,
LOC_CREGISTER :
begin
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if (para.size in [OS_128,OS_S128,OS_F128]) and
({ in case of fpu emulation, or abi's that pass fpu values
via integer registers }
(vardef.typ=floatdef) or
is_methodpointer(vardef)) then
begin
case paraloc^.loc of
LOC_REGISTER:
begin
if not assigned(paraloc^.next) then
internalerror(200410104);
if (target_info.endian=ENDIAN_BIG) then
begin
{ paraloc^ -> high
paraloc^.next -> low }
unget_para(paraloc^);
gen_alloc_regloc(list,destloc);
{ reg->reg, alignment is irrelevant }
cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reghi,8);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reglo,8);
end
else
begin
{ paraloc^ -> low
paraloc^.next -> high }
unget_para(paraloc^);
gen_alloc_regloc(list,destloc);
cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^,destloc.register128.reglo,8);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_64,paraloc^.next^,destloc.register128.reghi,8);
end;
end;
LOC_REFERENCE:
begin
gen_alloc_regloc(list,destloc);
reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,para.alignment);
cg128.a_load128_ref_reg(list,href,destloc.register128);
unget_para(paraloc^);
end;
else
internalerror(2012090607);
end
end
else
{$else cpu64bitalu}
if (para.size in [OS_64,OS_S64,OS_F64]) and
(is_64bit(vardef) or
{ in case of fpu emulation, or abi's that pass fpu values
@ -944,7 +1021,7 @@ implementation
end
end
else
{$endif not cpu64bitalu}
{$endif cpu64bitalu}
begin
if assigned(paraloc^.next) then
internalerror(200410105);
@ -1520,14 +1597,21 @@ implementation
begin
case location.loc of
LOC_CREGISTER:
{$ifndef cpu64bitalu}
{$ifdef cpu64bitalu}
if location.size in [OS_128,OS_S128] then
begin
rv.intregvars.addnodup(getsupreg(location.register128.reglo));
rv.intregvars.addnodup(getsupreg(location.register128.reghi));
end
else
{$else cpu64bitalu}
if location.size in [OS_64,OS_S64] then
begin
rv.intregvars.addnodup(getsupreg(location.register64.reglo));
rv.intregvars.addnodup(getsupreg(location.register64.reghi));
end
else
{$endif not cpu64bitalu}
{$endif cpu64bitalu}
rv.intregvars.addnodup(getsupreg(location.register));
LOC_CFPUREGISTER:
rv.fpuregvars.addnodup(getsupreg(location.register));

View File

@ -359,7 +359,7 @@ implementation
reg_cgsize:=OS_32
end
else
internalerror(200303181);
internalerror(2003031801);
end;
end;