diff --git a/compiler/m68k/cgcpu.pas b/compiler/m68k/cgcpu.pas index e68eabb6d0..aefd01f6e9 100644 --- a/compiler/m68k/cgcpu.pas +++ b/compiler/m68k/cgcpu.pas @@ -67,7 +67,7 @@ unit cgcpu; procedure a_loadmm_reg_cgpara(list: TAsmList; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle); override; procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister); override; -// procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); override; + //procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); override; procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); override; procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister; @@ -88,6 +88,7 @@ unit cgcpu; // procedure g_restore_frame_pointer(list : TAsmList);override; // procedure g_return_from_proc(list : TAsmList;parasize : tcgint);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; protected @@ -1773,37 +1774,82 @@ unit cgcpu; end; + procedure tcg68k.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(2013100702); + 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 } + reference_reset_base(href,reference.index,reference.offset-sizeof(pint),sizeof(pint)); + list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,NR_D0)); + list.concat(taicpu.op_const_reg(A_SUB,S_L,ioffset,NR_D0)); + list.concat(taicpu.op_reg_ref(A_MOVE,S_L,NR_D0,href)); + end + else + internalerror(2013100703); + end; + paraloc:=next; + end; + end; + procedure tcg68k.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint); -{ - procedure loadvmttor11; + + procedure getselftoa0(offs:longint); + var + href : treference; + selfoffsetfromsp : longint; + begin + { move.l offset(%sp),%a0 } + + { framepointer is pushed for nested procs } + if procdef.parast.symtablelevel>normal_function_level then + selfoffsetfromsp:=sizeof(aint) + else + selfoffsetfromsp:=0; + reference_reset_base(href,NR_SP,selfoffsetfromsp+offs,4); + cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_A0); + end; + + procedure loadvmttoa0; var href : treference; begin - reference_reset_base(href,NR_R3,0); - cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11); + { move.l (%a0),%a0 ; load vmt} + reference_reset_base(href,NR_A0,0,4); + cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_A0); end; - procedure op_onr11methodaddr; + procedure op_ona0methodaddr; var href : treference; + offs : longint; begin if (procdef.extnumber=$ffff) then - Internalerror(200006139); - { call/jmp vmtoffs(%eax) ; method offs } - reference_reset_base(href,NR_R11,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)); - if not((longint(href.offset) >= low(smallint)) and - (longint(href.offset) <= high(smallint))) then - begin - list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11, - smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0)))); - href.offset := smallint(href.offset and $ffff); - end; - list.concat(taicpu.op_reg_ref(A_LWZ,NR_R11,href)); - list.concat(taicpu.op_reg(A_MTCTR,NR_R11)); - list.concat(taicpu.op_none(A_BCTR)); + Internalerror(2013100701); + reference_reset_base(href,NR_A0,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4); + list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,NR_A0)); + reference_reset_base(href,NR_A0,0,4); + list.concat(taicpu.op_ref(A_JMP,S_L,href)); end; -} + var make_global : boolean; begin @@ -1828,18 +1874,19 @@ unit cgcpu; List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0)); { set param1 interface to self } -// g_adjust_self_value(list,procdef,ioffset); + g_adjust_self_value(list,procdef,ioffset); { case 4 } if (po_virtualmethod in procdef.procoptions) and not is_objectpascal_helper(procdef.struct) then begin -// loadvmttor11; -// op_onr11methodaddr; + getselftoa0(4); + loadvmttoa0; + op_ona0methodaddr; end { case 0 } else -// list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname))); + list.concat(taicpu.op_sym(A_JMP,S_L,current_asmdata.RefAsmSymbol(procdef.mangledname))); List.concat(Tai_symbol_end.Createname(labelname)); end;