mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 19:50:17 +02:00
* fix interface wrapper generation for i8086
git-svn-id: branches/i8086@23873 -
This commit is contained in:
parent
d6f0a1a0df
commit
636129ed8c
@ -69,6 +69,8 @@ unit cgcpu;
|
||||
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_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_maybe_got_init(list: TAsmList); override;
|
||||
|
||||
@ -91,7 +93,8 @@ unit cgcpu;
|
||||
uses
|
||||
globals,verbose,systems,cutils,
|
||||
paramgr,procinfo,fmodule,
|
||||
rgcpu,rgx86,cpuinfo;
|
||||
rgcpu,rgx86,cpuinfo,
|
||||
symtype,symsym;
|
||||
|
||||
function use_push(const cgpara:tcgpara):boolean;
|
||||
begin
|
||||
@ -1177,6 +1180,56 @@ unit cgcpu;
|
||||
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);
|
||||
{
|
||||
possible calling conventions:
|
||||
@ -1190,72 +1243,70 @@ unit cgcpu;
|
||||
|
||||
(1): The wrapper code use %eax to reach the virtual method address
|
||||
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
|
||||
so the following code be generated:
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
procedure getselftoeax(offs: longint);
|
||||
procedure getselftobx(offs: longint);
|
||||
var
|
||||
href : treference;
|
||||
selfoffsetfromsp : longint;
|
||||
begin
|
||||
{ mov offset(%esp),%eax }
|
||||
{ "mov offset(%sp),%bx" }
|
||||
if (procdef.proccalloption<>pocall_register) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
|
||||
{ framepointer is pushed for nested procs }
|
||||
if procdef.parast.symtablelevel>normal_function_level then
|
||||
selfoffsetfromsp:=2*sizeof(aint)
|
||||
else
|
||||
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;
|
||||
|
||||
procedure loadvmttoeax;
|
||||
|
||||
procedure loadvmttobx;
|
||||
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);
|
||||
{ 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;
|
||||
|
||||
procedure op_oneaxmethodaddr(op: TAsmOp);
|
||||
|
||||
procedure loadmethodoffstobx;
|
||||
var
|
||||
href : treference;
|
||||
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));
|
||||
end;
|
||||
|
||||
|
||||
procedure loadmethodoffstoeax;
|
||||
var
|
||||
href : treference;
|
||||
begin
|
||||
if (procdef.extnumber=$ffff) then
|
||||
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;
|
||||
|
||||
|
||||
@ -1290,40 +1341,36 @@ unit cgcpu;
|
||||
if (po_virtualmethod in procdef.procoptions) and
|
||||
not is_objectpascal_helper(procdef.struct) then
|
||||
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
|
||||
{ case 0 }
|
||||
else
|
||||
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;
|
||||
|
||||
List.concat(Tai_symbol_end.Createname(labelname));
|
||||
|
Loading…
Reference in New Issue
Block a user