Browse Source

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 -
pierre 9 years ago
parent
commit
40193ea1db
4 changed files with 45 additions and 12 deletions
  1. 6 1
      compiler/globtype.pas
  2. 1 0
      compiler/hlcgobj.pas
  3. 35 10
      compiler/i8086/cgcpu.pas
  4. 3 1
      compiler/utils/ppuutils/ppudump.pp

+ 6 - 1
compiler/globtype.pas

@@ -644,7 +644,12 @@ interface
          { set if the stack frame of the procedure is estimated }
          { set if the stack frame of the procedure is estimated }
          pi_estimatestacksize,
          pi_estimatestacksize,
          { the routine calls a C-style varargs function }
          { 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;
        tprocinfoflags=set of tprocinfoflag;
 
 

+ 1 - 0
compiler/hlcgobj.pas

@@ -3685,6 +3685,7 @@ implementation
       { because some abis don't support dynamic stack allocation properly
       { because some abis don't support dynamic stack allocation properly
         open array value parameters are copied onto the heap
         open array value parameters are copied onto the heap
       }
       }
+      include(current_procinfo.flags, pi_has_open_array_parameter);
 
 
       { calculate necessary memory }
       { calculate necessary memory }
 
 

+ 35 - 10
compiler/i8086/cgcpu.pas

@@ -1818,6 +1818,24 @@ unit cgcpu;
       var
       var
         stacksize : longint;
         stacksize : longint;
         ret_instr: TAsmOp;
         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
       begin
         if is_proc_far(current_procinfo.procdef) then
         if is_proc_far(current_procinfo.procdef) then
           ret_instr:=A_RETF
           ret_instr:=A_RETF
@@ -1828,12 +1846,22 @@ unit cgcpu;
            (rg[R_MMXREGISTER].uses_registers) then
            (rg[R_MMXREGISTER].uses_registers) then
           list.concat(Taicpu.op_none(A_EMMS,S_NO));
           list.concat(Taicpu.op_none(A_EMMS,S_NO));
 
 
+        sp_moved:=false;
         { remove stackframe }
         { remove stackframe }
         if not nostackframe then
         if not nostackframe then
           begin
           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
             if (po_exports in current_procinfo.procdef.procoptions) and
                (target_info.system=system_i8086_win16) then
                (target_info.system=system_i8086_win16) then
               begin
               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_DI));
                 list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI));
                 list.concat(Taicpu.Op_reg(A_POP,S_W,NR_SI));
               end;
               end;
@@ -1841,17 +1869,12 @@ unit cgcpu;
                 not (po_interrupt in current_procinfo.procdef.procoptions)) or
                 not (po_interrupt in current_procinfo.procdef.procoptions)) or
                ((po_exports in current_procinfo.procdef.procoptions) and
                ((po_exports in current_procinfo.procdef.procoptions) and
                 (target_info.system=system_i8086_win16)) then
                 (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
             if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
               begin
               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
                 if (stacksize<>0) then
                   cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
                   cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
               end
               end
@@ -1921,6 +1944,8 @@ unit cgcpu;
         a_load_loc_reg(list,OS_INT,lenloc,NR_DI);
         a_load_loc_reg(list,OS_INT,lenloc,NR_DI);
         list.concat(Taicpu.op_reg(A_INC,S_W,NR_DI));
         list.concat(Taicpu.op_reg(A_INC,S_W,NR_DI));
         { Now DI contains (high+1). }
         { Now DI contains (high+1). }
+	
+        include(current_procinfo.flags, pi_has_open_array_parameter);
 
 
         { special case handling for elesize=2:
         { special case handling for elesize=2:
           set CX = (high+1) instead of CX = (high+1)*elesize.
           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);
     procedure tcg8086.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
       begin
       begin
-        { Nothing to release }
+        { Nothing to do }
       end;
       end;
 
 
 
 

+ 3 - 1
compiler/utils/ppuutils/ppudump.pp

@@ -1281,7 +1281,9 @@ const
          (mask:pi_estimatestacksize;
          (mask:pi_estimatestacksize;
          str:' stack size is estimated before subroutine is compiled '),
          str:' stack size is estimated before subroutine is compiled '),
          (mask:pi_calls_c_varargs;
          (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
 var
   procinfooptions : tprocinfoflags;
   procinfooptions : tprocinfoflags;