diff --git a/compiler/cg64f32.pas b/compiler/cg64f32.pas index e5624c6ca5..028cf8d2c6 100644 --- a/compiler/cg64f32.pas +++ b/compiler/cg64f32.pas @@ -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; diff --git a/compiler/i8086/cpupara.pas b/compiler/i8086/cpupara.pas index c041d85bed..eae8a959bf 100644 --- a/compiler/i8086/cpupara.pas +++ b/compiler/i8086/cpupara.pas @@ -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 diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 52c6849df7..80582f29ea 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -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 diff --git a/compiler/x86/cpubase.pas b/compiler/x86/cpubase.pas index 6534e11845..a2cbf20166 100644 --- a/compiler/x86/cpubase.pas +++ b/compiler/x86/cpubase.pas @@ -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)