diff options
author | nickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2013-04-21 13:26:12 +0000 |
---|---|---|
committer | nickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2013-04-21 13:26:12 +0000 |
commit | 952952adcd4fe310da6e4ae9340550c6c50f2d7c (patch) | |
tree | 296d6a448a129d81a5265d635535c7dba987d88d /compiler | |
parent | 5b9324bb6850838bed929a6d35fea20764a9c2e3 (diff) | |
download | fpc-952952adcd4fe310da6e4ae9340550c6c50f2d7c.tar.gz |
* initial support for system procs that use calling conventions that push left to right on i8086 or i386
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/i8086@24282 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/cgobj.pas | 12 | ||||
-rw-r--r-- | compiler/hlcgobj.pas | 103 | ||||
-rw-r--r-- | compiler/ncgflw.pas | 73 | ||||
-rw-r--r-- | compiler/ncgmat.pas | 4 | ||||
-rw-r--r-- | compiler/ncgmem.pas | 24 | ||||
-rw-r--r-- | compiler/ncgutil.pas | 18 |
6 files changed, 184 insertions, 50 deletions
diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas index 0edaef1a87..302594a854 100644 --- a/compiler/cgobj.pas +++ b/compiler/cgobj.pas @@ -2100,8 +2100,16 @@ implementation paramanager.getintparaloc(pd,1,cgpara1); paramanager.getintparaloc(pd,2,cgpara2); reference_reset_symbol(hrefvmt,current_asmdata.RefAsmSymbol(objdef.vmt_mangledname),0,sizeof(pint)); - a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2); - a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1); + if pd.is_pushleftright then + begin + a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1); + a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2); + end + else + begin + a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2); + a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1); + end; paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara2); allocallcpuregisters(list); diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index 8305d015e4..22cd024d4c 100644 --- a/compiler/hlcgobj.pas +++ b/compiler/hlcgobj.pas @@ -2829,9 +2829,18 @@ implementation paramanager.getintparaloc(pd,1,cgpara1); paramanager.getintparaloc(pd,2,cgpara2); paramanager.getintparaloc(pd,3,cgpara3); - a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3); - a_loadaddr_ref_cgpara(list,strdef,source,cgpara2); - a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1); + if pd.is_pushleftright then + begin + a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1); + a_loadaddr_ref_cgpara(list,strdef,source,cgpara2); + a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3); + end + else + begin + a_loadaddr_ref_cgpara(list,strdef,dest,cgpara3); + a_loadaddr_ref_cgpara(list,strdef,source,cgpara2); + a_load_const_cgpara(list,s32inttype,strdef.len,cgpara1); + end; paramanager.freecgpara(list,cgpara3); paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara1); @@ -2851,8 +2860,16 @@ implementation cgpara2.init; paramanager.getintparaloc(pd,1,cgpara1); paramanager.getintparaloc(pd,2,cgpara2); - a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2); - a_loadaddr_ref_cgpara(list,vardef,source,cgpara1); + if pd.is_pushleftright then + begin + a_loadaddr_ref_cgpara(list,vardef,source,cgpara1); + a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2); + end + else + begin + a_loadaddr_ref_cgpara(list,vardef,dest,cgpara2); + a_loadaddr_ref_cgpara(list,vardef,source,cgpara1); + end; paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara1); g_call_system_proc(list,pd,nil); @@ -2904,8 +2921,16 @@ implementation if is_open_array(t) then InternalError(201103054); reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint)); - a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); - a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + if pd.is_pushleftright then + begin + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + end + else + begin + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + end; paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara2); g_call_system_proc(list,pd,nil); @@ -2944,8 +2969,16 @@ implementation paramanager.getintparaloc(pd,1,cgpara1); paramanager.getintparaloc(pd,2,cgpara2); reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint)); - a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); - a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + if pd.is_pushleftright then + begin + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + end + else + begin + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + end; paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara2); g_call_system_proc(list,pd,nil); @@ -2986,8 +3019,16 @@ implementation paramanager.getintparaloc(pd,1,cgpara1); paramanager.getintparaloc(pd,2,cgpara2); reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint)); - a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); - a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + if pd.is_pushleftright then + begin + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + end + else + begin + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + end; paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara2); g_call_system_proc(list,pd,nil); @@ -3019,6 +3060,14 @@ implementation paramanager.getintparaloc(pd,2,cgpara2); paramanager.getintparaloc(pd,3,cgpara3); + { if calling convention is left to right, push parameters 1 and 2 } + if pd.is_pushleftright then + begin + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + end; + + { push parameter 3 } reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint)); if highloc.loc=LOC_CONSTANT then a_load_const_cgpara(list,ptrsinttype,highloc.value+1,cgpara3) @@ -3037,8 +3086,12 @@ implementation a_load_reg_cgpara(list,ptrsinttype,lenreg,cgpara3); end; - a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); - a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + { if calling convention is right to left, push parameters 2 and 1 } + if not pd.is_pushleftright then + begin + a_loadaddr_ref_cgpara(list,voidpointertype,href,cgpara2); + a_loadaddr_ref_cgpara(list,t,ref,cgpara1); + end; paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara3); @@ -3308,12 +3361,24 @@ implementation paramanager.getintparaloc(pd,1,cgpara1); paramanager.getintparaloc(pd,2,cgpara2); paramanager.getintparaloc(pd,3,cgpara3); - { load size } - a_load_reg_cgpara(list,ptrsinttype,sizereg,cgpara3); - { load destination } - a_load_reg_cgpara(list,ptrarrdef,destreg,cgpara2); - { load source } - a_load_reg_cgpara(list,ptrarrdef,sourcereg,cgpara1); + if pd.is_pushleftright then + begin + { load source } + a_load_reg_cgpara(list,ptrarrdef,sourcereg,cgpara1); + { load destination } + a_load_reg_cgpara(list,ptrarrdef,destreg,cgpara2); + { load size } + a_load_reg_cgpara(list,ptrsinttype,sizereg,cgpara3); + end + else + begin + { load size } + a_load_reg_cgpara(list,ptrsinttype,sizereg,cgpara3); + { load destination } + a_load_reg_cgpara(list,ptrarrdef,destreg,cgpara2); + { load source } + a_load_reg_cgpara(list,ptrarrdef,sourcereg,cgpara1); + end; paramanager.freecgpara(list,cgpara3); paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara1); diff --git a/compiler/ncgflw.pas b/compiler/ncgflw.pas index 40c12e47c6..b0ba6e9922 100644 --- a/compiler/ncgflw.pas +++ b/compiler/ncgflw.pas @@ -986,31 +986,64 @@ implementation exit; { Push parameters } - if assigned(right) then + { ugly code repetition follows for left to right and right to left calling conventions } + { TODO: refactor this somehow } + if pd.is_pushleftright then begin - { frame tree } - if assigned(third) then - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3) - else - cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3); - { push address } - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); + if assigned(right) then + begin + { push address } + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + { frame tree } + if assigned(third) then + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3) + else + cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3); + end + else + begin + { get current address } + current_asmdata.getaddrlabel(a); + cg.a_label(current_asmdata.CurrAsmList,a); + reference_reset_symbol(href2,a,0,1); + { push current address } + if target_info.system <> system_powerpc_macos then + cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2) + else + cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2); + { push current frame } + cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3); + end; end else begin - { get current address } - current_asmdata.getaddrlabel(a); - cg.a_label(current_asmdata.CurrAsmList,a); - reference_reset_symbol(href2,a,0,1); - { push current frame } - cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3); - { push current address } - if target_info.system <> system_powerpc_macos then - cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2) - else - cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2); + if assigned(right) then + begin + { frame tree } + if assigned(third) then + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3) + else + cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc3); + { push address } + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + end + else + begin + { get current address } + current_asmdata.getaddrlabel(a); + cg.a_label(current_asmdata.CurrAsmList,a); + reference_reset_symbol(href2,a,0,1); + { push current frame } + cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3); + { push current address } + if target_info.system <> system_powerpc_macos then + cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2) + else + cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,paraloc2); + end; + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); end; - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc3); diff --git a/compiler/ncgmat.pas b/compiler/ncgmat.pas index 60f2fbe1f7..cc3cee544d 100644 --- a/compiler/ncgmat.pas +++ b/compiler/ncgmat.pas @@ -304,6 +304,7 @@ implementation paraloc1 : tcgpara; opsize : tcgsize; opdef : tdef; + pd: tprocdef; begin secondpass(left); if codegenerror then @@ -384,7 +385,8 @@ implementation current_asmdata.getjumplabel(hl); cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,hdenom,hl); paraloc1.init; - paramanager.getintparaloc(search_system_proc('fpc_handleerror'),1,paraloc1); + pd:=search_system_proc('fpc_handleerror'); + paramanager.getintparaloc(pd,1,paraloc1); cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,aint(200),paraloc1); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1); cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false); diff --git a/compiler/ncgmem.pas b/compiler/ncgmem.pas index 264ae8accc..53b9e47c05 100644 --- a/compiler/ncgmem.pas +++ b/compiler/ncgmem.pas @@ -721,8 +721,16 @@ implementation pd:=search_system_proc('fpc_dynarray_rangecheck'); paramanager.getintparaloc(pd,1,paraloc1); paramanager.getintparaloc(pd,2,paraloc2); - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); + if pd.is_pushleftright then + begin + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + end + else + begin + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); + end; paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2); cg.allocallcpuregisters(current_asmdata.CurrAsmList); @@ -755,8 +763,16 @@ implementation pd:=search_system_proc(helpername); paramanager.getintparaloc(pd,1,paraloc1); paramanager.getintparaloc(pd,2,paraloc2); - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); - cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + if pd.is_pushleftright then + begin + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + end + else + begin + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2); + cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1); + end; paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2); diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 1fc04519f9..df41c263b5 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -439,10 +439,20 @@ implementation paramanager.getintparaloc(pd,1,paraloc1); paramanager.getintparaloc(pd,2,paraloc2); paramanager.getintparaloc(pd,3,paraloc3); - cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3); - cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2); - { push type of exceptionframe } - cg.a_load_const_cgpara(list,pushexceptaddr_frametype_cgsize,1,paraloc1); + if pd.is_pushleftright then + begin + { push type of exceptionframe } + cg.a_load_const_cgpara(list,pushexceptaddr_frametype_cgsize,1,paraloc1); + cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2); + cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3); + end + else + begin + cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3); + cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2); + { push type of exceptionframe } + cg.a_load_const_cgpara(list,pushexceptaddr_frametype_cgsize,1,paraloc1); + end; paramanager.freecgpara(list,paraloc3); paramanager.freecgpara(list,paraloc2); paramanager.freecgpara(list,paraloc1); |