summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authornickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2>2013-04-21 13:26:12 +0000
committernickysn <nickysn@3ad0048d-3df7-0310-abae-a5850022a9f2>2013-04-21 13:26:12 +0000
commit952952adcd4fe310da6e4ae9340550c6c50f2d7c (patch)
tree296d6a448a129d81a5265d635535c7dba987d88d /compiler
parent5b9324bb6850838bed929a6d35fea20764a9c2e3 (diff)
downloadfpc-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.pas12
-rw-r--r--compiler/hlcgobj.pas103
-rw-r--r--compiler/ncgflw.pas73
-rw-r--r--compiler/ncgmat.pas4
-rw-r--r--compiler/ncgmem.pas24
-rw-r--r--compiler/ncgutil.pas18
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);