From 40193ea1dbc57bbdcb6040edc35416ba10d63883 Mon Sep 17 00:00:00 2001 From: pierre Date: Mon, 11 Jan 2016 15:02:10 +0000 Subject: [PATCH] Add pi_has_open_array_parameter to proc_info.flags as this requires special handling for i8086 huge memory model to restore DS register correctly git-svn-id: trunk@32922 - --- compiler/globtype.pas | 7 ++++- compiler/hlcgobj.pas | 1 + compiler/i8086/cgcpu.pas | 45 +++++++++++++++++++++++------- compiler/utils/ppuutils/ppudump.pp | 4 ++- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/compiler/globtype.pas b/compiler/globtype.pas index fc65ed5112..d366c480b5 100644 --- a/compiler/globtype.pas +++ b/compiler/globtype.pas @@ -644,7 +644,12 @@ interface { set if the stack frame of the procedure is estimated } pi_estimatestacksize, { the routine calls a C-style varargs function } - pi_calls_c_varargs + pi_calls_c_varargs, + { the routine has an open array parameter, + for i8086 cpu huge memory model, + as this changes SP register it requires special handling + to restore DS segment register } + pi_has_open_array_parameter ); tprocinfoflags=set of tprocinfoflag; diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index 91aa9671ec..bfc5afc62b 100644 --- a/compiler/hlcgobj.pas +++ b/compiler/hlcgobj.pas @@ -3685,6 +3685,7 @@ implementation { because some abis don't support dynamic stack allocation properly open array value parameters are copied onto the heap } + include(current_procinfo.flags, pi_has_open_array_parameter); { calculate necessary memory } diff --git a/compiler/i8086/cgcpu.pas b/compiler/i8086/cgcpu.pas index 76c416ce51..5de6eda307 100644 --- a/compiler/i8086/cgcpu.pas +++ b/compiler/i8086/cgcpu.pas @@ -1818,6 +1818,24 @@ unit cgcpu; var stacksize : longint; ret_instr: TAsmOp; + sp_moved : boolean; + + procedure maybe_move_sp; + var + ref : treference; + begin + if sp_moved then + exit; + if not(pi_has_open_array_parameter in current_procinfo.flags) then + exit; + { Restore SP position before SP change } + if current_settings.x86memorymodel=mm_huge then + stacksize:=stacksize + 2; + reference_reset_base(ref,NR_BP,-stacksize,2); + list.concat(Taicpu.op_ref_reg(A_LEA,S_W,ref,NR_SP)); + sp_moved:=true; + end; + begin if is_proc_far(current_procinfo.procdef) then ret_instr:=A_RETF @@ -1828,12 +1846,22 @@ unit cgcpu; (rg[R_MMXREGISTER].uses_registers) then list.concat(Taicpu.op_none(A_EMMS,S_NO)); + sp_moved:=false; { remove stackframe } if not nostackframe then begin + stacksize:=current_procinfo.calc_stackframe_size; + if (target_info.stackalign>4) and + ((stacksize <> 0) or + (pi_do_call in current_procinfo.flags) or + { can't detect if a call in this case -> use nostackframe } + { if you (think you) know what you are doing } + (po_assembler in current_procinfo.procdef.procoptions)) then + stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint); if (po_exports in current_procinfo.procdef.procoptions) and (target_info.system=system_i8086_win16) then begin + maybe_move_sp; list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DI)); list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI)); end; @@ -1841,17 +1869,12 @@ unit cgcpu; not (po_interrupt in current_procinfo.procdef.procoptions)) or ((po_exports in current_procinfo.procdef.procoptions) and (target_info.system=system_i8086_win16)) then - list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS)); + begin + maybe_move_sp; + list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS)); + end; if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then begin - stacksize:=current_procinfo.calc_stackframe_size; - if (target_info.stackalign>4) and - ((stacksize <> 0) or - (pi_do_call in current_procinfo.flags) or - { can't detect if a call in this case -> use nostackframe } - { if you (think you) know what you are doing } - (po_assembler in current_procinfo.procdef.procoptions)) then - stacksize := align(stacksize+sizeof(aint),target_info.stackalign) - sizeof(aint); if (stacksize<>0) then cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer); end @@ -1921,6 +1944,8 @@ unit cgcpu; a_load_loc_reg(list,OS_INT,lenloc,NR_DI); list.concat(Taicpu.op_reg(A_INC,S_W,NR_DI)); { Now DI contains (high+1). } + + include(current_procinfo.flags, pi_has_open_array_parameter); { special case handling for elesize=2: set CX = (high+1) instead of CX = (high+1)*elesize. @@ -2034,7 +2059,7 @@ unit cgcpu; procedure tcg8086.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation); begin - { Nothing to release } + { Nothing to do } end; diff --git a/compiler/utils/ppuutils/ppudump.pp b/compiler/utils/ppuutils/ppudump.pp index 047eef85ff..ba4d8c9b16 100644 --- a/compiler/utils/ppuutils/ppudump.pp +++ b/compiler/utils/ppuutils/ppudump.pp @@ -1281,7 +1281,9 @@ const (mask:pi_estimatestacksize; str:' stack size is estimated before subroutine is compiled '), (mask:pi_calls_c_varargs; - str:' calls function with C-style varargs ') + str:' calls function with C-style varargs '), + (mask:pi_has_open_array_parameter; + str:' has open array parameter ') ); var procinfooptions : tprocinfoflags;