* refactored the int64 result passing in ax:bx:cx:dx to use 4 paralocs, instead of the GetNextReg hack

git-svn-id: trunk@24527 -
This commit is contained in:
nickysn 2013-05-19 12:50:15 +00:00
parent d98fb1f004
commit ecb5a4866d
4 changed files with 139 additions and 41 deletions

View File

@ -122,8 +122,8 @@ unit cg64f32;
procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
var
paraloclo,
paralochi : pcgparalocation;
paraloclo,paraloclo2,
paralochi,paralochi2 : pcgparalocation;
begin
if not(cgpara.size in [OS_64,OS_S64]) then
internalerror(200408231);
@ -143,6 +143,55 @@ unit cg64f32;
cgparalo.intsize:=4;
cgparalo.alignment:=cgpara.alignment;
paraloclo:=cgparalo.add_location;
{ 4 parameter fields? }
if assigned(cgpara.location^.next) and assigned(cgpara.location^.next^.next) and assigned(cgpara.location^.next^.next^.next) then
begin
{ Order for multiple locations is always
paraloc^ -> high
paraloc^.next -> low }
if (target_info.endian=ENDIAN_BIG) then
begin
{ paraloc^ -> high }
move(cgpara.location^,paralochi^,sizeof(paralochi^));
paralochi^.next:=nil;
paralochi2:=cgparahi.add_location;
move(cgpara.location^.next,paralochi2^,sizeof(paralochi2^));
{ paraloc^.next^.next^ -> low }
move(cgpara.location^.next^.next^,paraloclo^,sizeof(paraloclo^));
paraloclo^.next:=nil;
paraloclo2:=cgparalo.add_location;
move(cgpara.location^.next^.next^.next^,paraloclo2^,sizeof(paraloclo2^));
end
else
begin
{ paraloc^ -> low }
move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
paraloclo^.next:=nil;
paraloclo2:=cgparalo.add_location;
move(cgpara.location^.next^,paraloclo2^,sizeof(paraloclo2^));
{ paraloc^.next^.next -> high }
move(cgpara.location^.next^.next^,paralochi^,sizeof(paralochi^));
paralochi^.next:=nil;
paralochi2:=cgparahi.add_location;
move(cgpara.location^.next^.next^.next^,paralochi2^,sizeof(paralochi2^));
end;
{ fix size }
paraloclo^.size:=OS_16;
paraloclo2^.size:=OS_16;
paraloclo2^.next:=nil;
paralochi^.size:=OS_16;
paralochi2^.size:=OS_16;
paralochi2^.next:=nil;
if cgpara.size=OS_S64 then
if target_info.endian=ENDIAN_BIG then
paralochi^.size:=OS_S16
else
paraloclo2^.size:=OS_S16;
end
else
{ 2 parameter fields? }
if assigned(cgpara.location^.next) then
begin
@ -163,6 +212,12 @@ unit cg64f32;
move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
end;
{ fix size }
paraloclo^.size:=cgparalo.size;
paraloclo^.next:=nil;
paralochi^.size:=cgparahi.size;
paralochi^.next:=nil;
end
else
begin
@ -182,12 +237,13 @@ unit cg64f32;
inc(cgparahi.location^.reference.offset,4);
cgparahi.alignment:=newalignment(cgparahi.alignment,4);
end;
{ fix size }
paraloclo^.size:=cgparalo.size;
paraloclo^.next:=nil;
paralochi^.size:=cgparahi.size;
paralochi^.next:=nil;
end;
{ fix size }
paraloclo^.size:=cgparalo.size;
paraloclo^.next:=nil;
paralochi^.size:=cgparahi.size;
paralochi^.next:=nil;
end;

View File

@ -329,21 +329,39 @@ unit cpupara;
paraloc^.loc:=LOC_REGISTER;
if retcgsize in [OS_64,OS_S64] then
begin
{ low 32bits }
{ bits 0..15 }
if side=callerside then
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
else
paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
paraloc^.size:=OS_32;
paraloc^.size:=OS_16;
{ high 32bits }
{ bits 16..31 }
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if side=callerside then
paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
paraloc^.size:=OS_16;
{ bits 32..47 }
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if side=callerside then
paraloc^.register:=NR_FUNCTION_RESULT64_HIGHER_REG
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
paraloc^.size:=OS_32;
paraloc^.size:=OS_16;
{ bits 48..63 }
paraloc:=result.add_location;
paraloc^.loc:=LOC_REGISTER;
if side=callerside then
paraloc^.register:=NR_FUNCTION_RESULT64_HIGHEST_REG
else
paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
paraloc^.size:=OS_16;
end
else if retcgsize in [OS_32,OS_S32] then
begin

View File

@ -1002,27 +1002,61 @@ implementation
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_32,paraloc^,destloc.register64.reghi,4);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
end
{$ifdef cpu16bitalu}
{ 4 paralocs? }
if assigned(paraloc^.next) and assigned(paraloc^.next^.next) and assigned(paraloc^.next^.next^.next) then
if (target_info.endian=ENDIAN_BIG) then
begin
{ paraloc^ -> high
paraloc^.next^.next -> low }
unget_para(paraloc^);
gen_alloc_regloc(list,destloc);
{ reg->reg, alignment is irrelevant }
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,GetNextReg(destloc.register64.reghi),2);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,destloc.register64.reghi,2);
unget_para(paraloc^.next^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,GetNextReg(destloc.register64.reglo),2);
unget_para(paraloc^.next^.next^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,destloc.register64.reglo,2);
end
else
begin
{ paraloc^ -> low
paraloc^.next^.next -> high }
unget_para(paraloc^);
gen_alloc_regloc(list,destloc);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^,destloc.register64.reglo,2);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^,GetNextReg(destloc.register64.reglo),2);
unget_para(paraloc^.next^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^,destloc.register64.reghi,2);
unget_para(paraloc^.next^.next^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_16,paraloc^.next^.next^.next^,GetNextReg(destloc.register64.reghi),2);
end
else
begin
{ paraloc^ -> low
paraloc^.next -> high }
unget_para(paraloc^);
gen_alloc_regloc(list,destloc);
cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
end;
{$endif cpu16bitalu}
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_32,paraloc^,destloc.register64.reghi,4);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
end
else
begin
{ paraloc^ -> low
paraloc^.next -> high }
unget_para(paraloc^);
gen_alloc_regloc(list,destloc);
cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
unget_para(paraloc^.next^);
cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
end;
end;
LOC_REFERENCE:
begin

View File

@ -556,16 +556,6 @@ implementation
{$ifdef i8086}
function GetNextReg(const r: TRegister): TRegister;
begin
{ HACK for returning 64-bit values in registers ax:bx:cx:dx }
case r of
NR_FUNCTION_RESULT64_LOW_REG: exit(NR_FUNCTION_RESULT64_HIGH_REG);
NR_FUNCTION_RESULT64_HIGHER_REG: exit(NR_FUNCTION_RESULT64_HIGHEST_REG);
end;
case r of
NR_FUNCTION_RETURN64_LOW_REG: exit(NR_FUNCTION_RETURN64_HIGH_REG);
NR_FUNCTION_RETURN64_HIGHER_REG: exit(NR_FUNCTION_RETURN64_HIGHEST_REG);
end;
if getsupreg(r)<first_int_imreg then
internalerror(2013051401);
result:=TRegister(longint(r)+1);