|
@@ -82,6 +82,8 @@ interface
|
|
|
procedure g_exception_reason_load(list: TAsmList; fromsize, tosize: tdef; const href: treference; reg: tregister); override;
|
|
|
procedure g_exception_reason_discard(list: TAsmList; size: tdef; href: treference); override;
|
|
|
|
|
|
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
|
|
|
+
|
|
|
procedure location_force_mem(list:TAsmList;var l:tlocation;size:tdef);override;
|
|
|
end;
|
|
|
|
|
@@ -92,6 +94,7 @@ implementation
|
|
|
uses
|
|
|
verbose,
|
|
|
paramgr,
|
|
|
+ aasmbase,aasmtai,
|
|
|
cpubase,cpuinfo,tgobj,cgobj,cgx86,cgcpu,
|
|
|
defutil,
|
|
|
symconst,symcpu,
|
|
@@ -436,6 +439,208 @@ implementation
|
|
|
end;
|
|
|
|
|
|
|
|
|
+ procedure thlcgcpu.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
|
|
|
+ {
|
|
|
+ possible calling conventions:
|
|
|
+ default stdcall cdecl pascal register
|
|
|
+ default(0): OK OK OK OK OK
|
|
|
+ virtual(1): OK OK OK OK OK(2)
|
|
|
+
|
|
|
+ (0):
|
|
|
+ set self parameter to correct value
|
|
|
+ jmp mangledname
|
|
|
+
|
|
|
+ (1): The wrapper code use %eax to reach the virtual method address
|
|
|
+ set self to correct value
|
|
|
+ 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 %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 getselftobx(offs: longint);
|
|
|
+ var
|
|
|
+ href : treference;
|
|
|
+ selfoffsetfromsp : longint;
|
|
|
+ begin
|
|
|
+ { "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);
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ inc(selfoffsetfromsp,2);
|
|
|
+ list.concat(taicpu.op_reg_reg(A_mov,S_W,NR_SP,NR_DI));
|
|
|
+ reference_reset_base(href,voidpointertype,NR_DI,selfoffsetfromsp+offs+2,2);
|
|
|
+ if not segment_regs_equal(NR_SS,NR_DS) then
|
|
|
+ href.segment:=NR_SS;
|
|
|
+ if current_settings.x86memorymodel in x86_near_data_models then
|
|
|
+ cg.a_load_ref_reg(list,OS_16,OS_16,href,NR_BX)
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_ref_reg(A_LES,S_W,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 loadvmttobx;
|
|
|
+ var
|
|
|
+ href : treference;
|
|
|
+ begin
|
|
|
+ { mov 0(%bx),%bx ; load vmt}
|
|
|
+ if current_settings.x86memorymodel in x86_near_data_models then
|
|
|
+ begin
|
|
|
+ reference_reset_base(href,voidpointertype,NR_BX,0,2);
|
|
|
+ cg.a_load_ref_reg(list,OS_16,OS_16,href,NR_BX);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ reference_reset_base(href,voidpointertype,NR_BX,0,2);
|
|
|
+ href.segment:=NR_ES;
|
|
|
+ list.concat(taicpu.op_ref_reg(A_LES,S_W,href,NR_BX));
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure loadmethodoffstobx;
|
|
|
+ var
|
|
|
+ href : treference;
|
|
|
+ srcseg: TRegister;
|
|
|
+ begin
|
|
|
+ if (procdef.extnumber=$ffff) then
|
|
|
+ Internalerror(200006139);
|
|
|
+ if current_settings.x86memorymodel in x86_far_data_models then
|
|
|
+ srcseg:=NR_ES
|
|
|
+ else
|
|
|
+ srcseg:=NR_NO;
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ begin
|
|
|
+ { mov vmtseg(%bx),%si ; method seg }
|
|
|
+ reference_reset_base(href,voidpointertype,NR_BX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)+2,2);
|
|
|
+ href.segment:=srcseg;
|
|
|
+ cg.a_load_ref_reg(list,OS_16,OS_16,href,NR_SI);
|
|
|
+ end;
|
|
|
+ { mov vmtoffs(%bx),%bx ; method offs }
|
|
|
+ reference_reset_base(href,voidpointertype,NR_BX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),2);
|
|
|
+ href.segment:=srcseg;
|
|
|
+ cg.a_load_ref_reg(list,OS_16,OS_16,href,NR_BX);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ var
|
|
|
+ lab : tasmsymbol;
|
|
|
+ make_global : boolean;
|
|
|
+ href : treference;
|
|
|
+ begin
|
|
|
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
|
|
|
+ Internalerror(200006137);
|
|
|
+ if not assigned(procdef.struct) or
|
|
|
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
|
|
|
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
|
|
|
+ Internalerror(200006138);
|
|
|
+ if procdef.owner.symtabletype<>ObjectSymtable then
|
|
|
+ Internalerror(200109191);
|
|
|
+
|
|
|
+ make_global:=false;
|
|
|
+ if (not current_module.is_unit) or
|
|
|
+ create_smartlink or
|
|
|
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
|
|
|
+ make_global:=true;
|
|
|
+
|
|
|
+ if make_global then
|
|
|
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
|
|
|
+ else
|
|
|
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
|
|
|
+
|
|
|
+ { set param1 interface to self }
|
|
|
+ g_adjust_self_value(list,procdef,ioffset);
|
|
|
+
|
|
|
+ if (po_virtualmethod in procdef.procoptions) and
|
|
|
+ not is_objectpascal_helper(procdef.struct) then
|
|
|
+ begin
|
|
|
+ { case 1 & case 2 }
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,S_W,NR_BX)); { allocate space for address}
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,S_W,NR_BX));
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,S_W,NR_BX));
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,S_W,NR_DI));
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,S_W,NR_SI));
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ getselftobx(10)
|
|
|
+ else
|
|
|
+ getselftobx(6);
|
|
|
+ loadvmttobx;
|
|
|
+ loadmethodoffstobx;
|
|
|
+ { set target address
|
|
|
+ "mov %bx,4(%sp)" }
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ reference_reset_base(href,voidpointertype,NR_DI,6,2)
|
|
|
+ else
|
|
|
+ reference_reset_base(href,voidpointertype,NR_DI,4,2);
|
|
|
+ if not segment_regs_equal(NR_DS,NR_SS) then
|
|
|
+ href.segment:=NR_SS;
|
|
|
+ list.concat(taicpu.op_reg_reg(A_MOV,S_W,NR_SP,NR_DI));
|
|
|
+ list.concat(taicpu.op_reg_ref(A_MOV,S_W,NR_BX,href));
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ begin
|
|
|
+ inc(href.offset,2);
|
|
|
+ list.concat(taicpu.op_reg_ref(A_MOV,S_W,NR_SI,href));
|
|
|
+ end;
|
|
|
+
|
|
|
+ { 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 }
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ list.concat(taicpu.op_reg(A_POP,S_W,NR_SI));
|
|
|
+ list.concat(taicpu.op_reg(A_POP,S_W,NR_DI));
|
|
|
+ list.concat(taicpu.op_reg(A_POP,S_W,NR_BX));
|
|
|
+
|
|
|
+ { ret ; jump to the address }
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ list.concat(taicpu.op_none(A_RETF,S_W))
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_none(A_RET,S_W));
|
|
|
+ end
|
|
|
+ { case 0 }
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ lab:=current_asmdata.RefAsmSymbol(procdef.mangledname);
|
|
|
+
|
|
|
+ if current_settings.x86memorymodel in x86_far_code_models then
|
|
|
+ list.concat(taicpu.op_sym(A_JMP,S_FAR,lab))
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_sym(A_JMP,S_NO,lab));
|
|
|
+ end;
|
|
|
+
|
|
|
+ List.concat(Tai_symbol_end.Createname(labelname));
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
procedure thlcgcpu.location_force_mem(list: TAsmList; var l: tlocation; size: tdef);
|
|
|
var
|
|
|
r,tmpref: treference;
|