Quellcode durchsuchen

* fix interface wrapper generation for i8086

git-svn-id: branches/i8086@23873 -
florian vor 12 Jahren
Ursprung
Commit
636129ed8c
1 geänderte Dateien mit 111 neuen und 64 gelöschten Zeilen
  1. 111 64
      compiler/i8086/cgcpu.pas

+ 111 - 64
compiler/i8086/cgcpu.pas

@@ -69,6 +69,8 @@ unit cgcpu;
         procedure g_exception_reason_save(list : TAsmList; const href : treference);override;
         procedure g_exception_reason_save(list : TAsmList; const href : treference);override;
         procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: tcgint);override;
         procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: tcgint);override;
         procedure g_exception_reason_load(list : TAsmList; const href : treference);override;
         procedure g_exception_reason_load(list : TAsmList; const href : treference);override;
+
+        procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);override;
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
         procedure g_maybe_got_init(list: TAsmList); override;
         procedure g_maybe_got_init(list: TAsmList); override;
 
 
@@ -91,7 +93,8 @@ unit cgcpu;
     uses
     uses
        globals,verbose,systems,cutils,
        globals,verbose,systems,cutils,
        paramgr,procinfo,fmodule,
        paramgr,procinfo,fmodule,
-       rgcpu,rgx86,cpuinfo;
+       rgcpu,rgx86,cpuinfo,
+       symtype,symsym;
 
 
     function use_push(const cgpara:tcgpara):boolean;
     function use_push(const cgpara:tcgpara):boolean;
       begin
       begin
@@ -1177,6 +1180,56 @@ unit cgcpu;
       end;
       end;
 
 
 
 
+    procedure tcg8086.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
+      var
+        hsym : tsym;
+        href : treference;
+        paraloc : Pcgparalocation;
+      begin
+        { calculate the parameter info for the procdef }
+        procdef.init_paraloc_info(callerside);
+        hsym:=tsym(procdef.parast.Find('self'));
+        if not(assigned(hsym) and
+               (hsym.typ=paravarsym)) then
+          internalerror(200305251);
+        paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+        while paraloc<>nil do
+          with paraloc^ do
+            begin
+              case loc of
+                LOC_REGISTER:
+                  a_op_const_reg(list,OP_SUB,size,ioffset,register);
+                LOC_REFERENCE:
+                  begin
+                    { offset in the wrapper needs to be adjusted for the stored
+                      return address }
+                    if (reference.index<>NR_BP) and (reference.index<>NR_BX) and (reference.index<>NR_DI)
+                      and (reference.index<>NR_SI) then
+                      begin
+                        list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
+                        list.concat(taicpu.op_reg_reg(A_MOV,S_W,reference.index,NR_DI));
+
+                        if reference.index=NR_SP then
+                          reference_reset_base(href,NR_DI,reference.offset+sizeof(pint)+2,sizeof(pint))
+                        else
+                          reference_reset_base(href,NR_DI,reference.offset+sizeof(pint),sizeof(pint));
+                        a_op_const_ref(list,OP_SUB,size,ioffset,href);
+                        list.concat(taicpu.op_reg(A_POP,S_W,NR_DI));
+                      end
+                    else
+                      begin
+                        reference_reset_base(href,reference.index,reference.offset+sizeof(pint),sizeof(pint));
+                        a_op_const_ref(list,OP_SUB,size,ioffset,href);
+                      end;
+                  end
+                else
+                  internalerror(200309189);
+              end;
+              paraloc:=next;
+            end;
+      end;
+
+
     procedure tcg8086.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
     procedure tcg8086.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
       {
       {
       possible calling conventions:
       possible calling conventions:
@@ -1190,72 +1243,70 @@ unit cgcpu;
 
 
       (1): The wrapper code use %eax to reach the virtual method address
       (1): The wrapper code use %eax to reach the virtual method address
            set self to correct value
            set self to correct value
-           move self,%eax
-           mov  0(%eax),%eax ; load vmt
-           jmp  vmtoffs(%eax) ; method offs
+           move self,%bx
+           mov  0(%bx),%bx ; load vmt
+           jmp  vmtoffs(%bx) ; method offs
 
 
       (2): Virtual use values pushed on stack to reach the method address
       (2): Virtual use values pushed on stack to reach the method address
            so the following code be generated:
            so the following code be generated:
            set self to correct value
            set self to correct value
-           push %ebx ; allocate space for function address
-           push %eax
-           mov  self,%eax
-           mov  0(%eax),%eax ; load vmt
-           mov  vmtoffs(%eax),eax ; method offs
-           mov  %eax,4(%esp)
-           pop  %eax
+           push %bx ; allocate space for function address
+           push %bx
+           push %di
+           mov  self,%bx
+           mov  0(%bx),%bx ; load vmt
+           mov  vmtoffs(%bx),bx ; method offs
+           mov  %sp,%di
+           mov  %bx,4(%di)
+           pop  %di
+           pop  %bx
            ret  0; jmp the address
            ret  0; jmp the address
 
 
       }
       }
 
 
-      procedure getselftoeax(offs: longint);
+      procedure getselftobx(offs: longint);
         var
         var
           href : treference;
           href : treference;
           selfoffsetfromsp : longint;
           selfoffsetfromsp : longint;
         begin
         begin
-          { mov offset(%esp),%eax }
+          { "mov offset(%sp),%bx" }
           if (procdef.proccalloption<>pocall_register) then
           if (procdef.proccalloption<>pocall_register) then
             begin
             begin
+              list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
               { framepointer is pushed for nested procs }
               { framepointer is pushed for nested procs }
               if procdef.parast.symtablelevel>normal_function_level then
               if procdef.parast.symtablelevel>normal_function_level then
                 selfoffsetfromsp:=2*sizeof(aint)
                 selfoffsetfromsp:=2*sizeof(aint)
               else
               else
                 selfoffsetfromsp:=sizeof(aint);
                 selfoffsetfromsp:=sizeof(aint);
-              reference_reset_base(href,NR_ESP,selfoffsetfromsp+offs,4);
-              cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
-            end;
+              list.concat(taicpu.op_reg_reg(A_mov,S_W,NR_SP,NR_DI));
+              reference_reset_base(href,NR_DI,selfoffsetfromsp+offs+2,2);
+              cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_BX);
+              list.concat(taicpu.op_reg(A_POP,S_W,NR_DI));
+            end
+          else
+            cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_BX,NR_BX);
         end;
         end;
 
 
-      procedure loadvmttoeax;
-        var
-          href : treference;
-        begin
-          { mov  0(%eax),%eax ; load vmt}
-          reference_reset_base(href,NR_EAX,0,4);
-          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
-        end;
 
 
-      procedure op_oneaxmethodaddr(op: TAsmOp);
+      procedure loadvmttobx;
         var
         var
           href : treference;
           href : treference;
         begin
         begin
-          if (procdef.extnumber=$ffff) then
-            Internalerror(200006139);
-          { call/jmp  vmtoffs(%eax) ; method offs }
-          reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
-          list.concat(taicpu.op_ref(op,S_L,href));
+          { mov  0(%bx),%bx ; load vmt}
+          reference_reset_base(href,NR_BX,0,2);
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_BX);
         end;
         end;
 
 
 
 
-      procedure loadmethodoffstoeax;
+      procedure loadmethodoffstobx;
         var
         var
           href : treference;
           href : treference;
         begin
         begin
           if (procdef.extnumber=$ffff) then
           if (procdef.extnumber=$ffff) then
             Internalerror(200006139);
             Internalerror(200006139);
-          { mov vmtoffs(%eax),%eax ; method offs }
-          reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
-          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+          { mov vmtoffs(%bx),%bx ; method offs }
+          reference_reset_base(href,NR_BX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),2);
+          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_BX);
         end;
         end;
 
 
 
 
@@ -1290,40 +1341,36 @@ unit cgcpu;
         if (po_virtualmethod in procdef.procoptions) and
         if (po_virtualmethod in procdef.procoptions) and
             not is_objectpascal_helper(procdef.struct) then
             not is_objectpascal_helper(procdef.struct) then
           begin
           begin
-            if (procdef.proccalloption=pocall_register) then
-              begin
-                { case 2 }
-                list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX)); { allocate space for address}
-                list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EAX));
-                getselftoeax(8);
-                loadvmttoeax;
-                loadmethodoffstoeax;
-                { mov %eax,4(%esp) }
-                reference_reset_base(href,NR_ESP,4,4);
-                list.concat(taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
-                { pop  %eax }
-                list.concat(taicpu.op_reg(A_POP,S_L,NR_EAX));
-                { ret  ; jump to the address }
-                list.concat(taicpu.op_none(A_RET,S_L));
-              end
-            else
-              begin
-                { case 1 }
-                getselftoeax(0);
-                loadvmttoeax;
-                op_oneaxmethodaddr(A_JMP);
-              end;
+            { case 1 & case 2 }
+            list.concat(taicpu.op_reg(A_PUSH,S_W,NR_BX)); { allocate space for address}
+            list.concat(taicpu.op_reg(A_PUSH,S_W,NR_BX));
+            list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
+            getselftobx(8);
+            loadvmttobx;
+            loadmethodoffstobx;
+            { set target address
+              "mov %bx,4(%sp)" }
+            reference_reset_base(href,NR_DI,4,2);
+            list.concat(taicpu.op_reg_reg(A_MOV,S_W,NR_SP,NR_DI));
+            list.concat(taicpu.op_reg_ref(A_MOV,S_L,NR_BX,href));
+
+            { load ax? }
+            if procdef.proccalloption=pocall_register then
+              list.concat(taicpu.op_reg_reg(A_MOV,S_W,NR_BX,NR_AX));
+
+            { restore register
+              pop  %di,bx }
+            list.concat(taicpu.op_reg(A_POP,S_W,NR_DI));
+            list.concat(taicpu.op_reg(A_POP,S_L,NR_BX));
+
+            { ret  ; jump to the address }
+            list.concat(taicpu.op_none(A_RET,S_W));
           end
           end
         { case 0 }
         { case 0 }
         else
         else
           begin
           begin
-            if (target_info.system <> system_i386_darwin) then
-              begin
-                lab:=current_asmdata.RefAsmSymbol(procdef.mangledname);
-                list.concat(taicpu.op_sym(A_JMP,S_NO,lab))
-              end
-            else
-              list.concat(taicpu.op_sym(A_JMP,S_NO,get_darwin_call_stub(procdef.mangledname,false)))
+            lab:=current_asmdata.RefAsmSymbol(procdef.mangledname);
+            list.concat(taicpu.op_sym(A_JMP,S_NO,lab))
           end;
           end;
 
 
         List.concat(Tai_symbol_end.Createname(labelname));
         List.concat(Tai_symbol_end.Createname(labelname));