From 823e3ea398f11545d97ef2ba5a61b3298be73a33 Mon Sep 17 00:00:00 2001 From: sergei Date: Tue, 5 Mar 2013 19:31:20 +0000 Subject: [PATCH] MIPS: reworked PIC/call code: + Favor 'weak' parameter in a_call_name of both thlcgmips and TCGMIPS. * make_simple_ref and a_loadaddr_ref_reg: require input references to be 'raw' (no refaddr=addr_pic, etc) and do not use GP as base/index. If it's not true, raise an internal error. When addr_pic_call16 or so needs to be generated, it must be done without calling the mentioned methods. * thlcgmips.a_call_name: generate PIC sequence for procedures declared as 'external', instead of 'cdecl', this is more correct because ABI has only one calling convention. - make_simple_ref_fpu removed, there's no reason to handle references to floating-point data in different way. - a_loadaddr_ref_cgpara override also removed, generic method does the job just well. - thlcgmips.a_call_ref and a_call_reg overrides removed because indirect calls are now always done using $t9. git-svn-id: trunk@23698 - --- compiler/mips/cgcpu.pas | 534 ++++++++++++++------------------------ compiler/mips/hlcgcpu.pas | 58 +---- 2 files changed, 205 insertions(+), 387 deletions(-) diff --git a/compiler/mips/cgcpu.pas b/compiler/mips/cgcpu.pas index e82cd9d644..cd242efb64 100644 --- a/compiler/mips/cgcpu.pas +++ b/compiler/mips/cgcpu.pas @@ -42,16 +42,15 @@ type function getfpuregister(list: tasmlist; size: Tcgsize): Tregister; override; /// { needed by cg64 } procedure make_simple_ref(list: tasmlist; var ref: treference); - procedure make_simple_ref_fpu(list: tasmlist; var ref: treference); procedure handle_reg_const_reg(list: tasmlist; op: Tasmop; src: tregister; a: tcgint; dst: tregister); procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister); { parameter } - procedure a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); override; procedure a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara); override; procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override; procedure a_call_name(list: tasmlist; const s: string; weak : boolean); override; procedure a_call_reg(list: tasmlist; Reg: TRegister); override; + procedure a_call_sym_pic(list: tasmlist; sym: tasmsymbol); { General purpose instructions } procedure a_op_const_reg(list: tasmlist; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister); override; procedure a_op_reg_reg(list: tasmlist; Op: TOpCG; size: TCGSize; src, dst: TRegister); override; @@ -88,9 +87,6 @@ type { Transform unsupported methods into Internal errors } procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override; procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override; - procedure maybe_reload_gp(list : tasmlist); - procedure Load_PIC_Addr(list : tasmlist; tmpreg : Tregister; - var ref : treference); end; TCg64MPSel = class(tcg64f32) @@ -268,144 +264,94 @@ procedure TCGMIPS.make_simple_ref(list: tasmlist; var ref: treference); var tmpreg, tmpreg1: tregister; tmpref: treference; + base_replaced: boolean; begin - tmpreg := NR_NO; - { Be sure to have a base register } - if (ref.base = NR_NO) then - begin - ref.base := ref.index; - ref.index := NR_NO; - end; - if (ref.refaddr in [addr_pic,addr_pic_call16]) then - maybe_reload_gp(list); - if ((cs_create_pic in current_settings.moduleswitches) or - (ref.refaddr in [addr_pic,addr_pic_call16])) and - assigned(ref.symbol) then - begin - tmpreg := cg.GetIntRegister(list, OS_INT); - Load_PIC_Addr(list,tmpreg,ref); - { ref.symbol is nil now, but we cannot reuse tmpreg below, - thus we need to reset it here, otherwise wrong code is generated } - tmpreg:=NR_NO; - end; - { When need to use LUI, do it first } - if assigned(ref.symbol) or - (ref.offset < simm16lo) or - (ref.offset > simm16hi) then - begin - if tmpreg=NR_NO then - tmpreg := GetIntRegister(list, OS_INT); - reference_reset(tmpref,sizeof(aint)); - tmpref.symbol := ref.symbol; - tmpref.offset := ref.offset; - tmpref.refaddr := addr_high; - list.concat(taicpu.op_reg_ref(A_LUI, tmpreg, tmpref)); - if (ref.offset = 0) and (ref.index = NR_NO) and - (ref.base = NR_NO) then - begin - ref.refaddr := addr_low; - end - else - begin - { Load the low part is left } - tmpref.refaddr := addr_low; - list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg, tmpreg, tmpref)); - ref.offset := 0; - { symbol is loaded } - ref.symbol := nil; - end; - if (ref.index <> NR_NO) then - begin - list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg)); - ref.index := tmpreg; - end - else - begin - if ref.base <> NR_NO then - ref.index := tmpreg - else - ref.base := tmpreg; - end; - end; - if (ref.base <> NR_NO) then - begin - if (ref.index <> NR_NO) and (ref.offset = 0) then - begin - tmpreg1 := GetIntRegister(list, OS_INT); - list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.base, ref.index)); - ref.base := tmpreg1; - ref.index := NR_NO; - end - else if (ref.index <> NR_NO) and - ((ref.offset <> 0) or assigned(ref.symbol)) then - begin - if tmpreg = NR_NO then - tmpreg := GetIntRegister(list, OS_INT); - list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.base, ref.index)); - ref.base := tmpreg; - ref.index := NR_NO; - end; - end; -end; + { Enforce some discipline for callers: + - gp is always implicit + - reference is processed only once } + if (ref.base=NR_GP) or (ref.index=NR_GP) then + InternalError(2013022801); + if (ref.refaddr<>addr_no) then + InternalError(2013022802); -procedure TCGMIPS.make_simple_ref_fpu(list: tasmlist; var ref: treference); -var - tmpreg, tmpreg1: tregister; - tmpref: treference; -begin - tmpreg := NR_NO; - { Be sure to have a base register } - if (ref.base = NR_NO) then - begin - ref.base := ref.index; - ref.index := NR_NO; - end; - - if (ref.refaddr in [addr_pic,addr_pic_call16]) then - maybe_reload_gp(list); - if ((cs_create_pic in current_settings.moduleswitches) or - (ref.refaddr in [addr_pic,addr_pic_call16])) and - assigned(ref.symbol) then + { fixup base/index, if both are present then add them together } + base_replaced:=false; + tmpreg:=ref.base; + if (tmpreg=NR_NO) then + tmpreg:=ref.index + else if (ref.index<>NR_NO) then begin - tmpreg := GetIntRegister(list, OS_ADDR); - Load_PIC_Addr(list,tmpreg,ref); - if (ref.base=NR_NO) and (ref.offset=0) then - exit; + tmpreg:=getintregister(list,OS_ADDR); + list.concat(taicpu.op_reg_reg_reg(A_ADDU,tmpreg,ref.base,ref.index)); + base_replaced:=true; end; + ref.base:=tmpreg; + ref.index:=NR_NO; - { When need to use LUI, do it first } - if (not assigned(ref.symbol)) and (ref.index = NR_NO) and - (ref.offset > simm16lo + 1000) and (ref.offset < simm16hi - 1000) - then + if (ref.symbol=nil) and + (ref.offset>=simm16lo) and + (ref.offset<=simm16hi-sizeof(pint)) then exit; - tmpreg1 := GetIntRegister(list, OS_INT); + { Symbol present or offset > 16bits } if assigned(ref.symbol) then - begin - reference_reset(tmpref,sizeof(aint)); - tmpref.symbol := ref.symbol; - tmpref.offset := ref.offset; - tmpref.refaddr := addr_high; - list.concat(taicpu.op_reg_ref(A_LUI, tmpreg1, tmpref)); - { Load the low part } + begin + ref.base:=getintregister(list,OS_ADDR); + reference_reset_symbol(tmpref,ref.symbol,ref.offset,ref.alignment); + if (cs_create_pic in current_settings.moduleswitches) then + begin + { For PIC global symbols offset must be handled separately. + Otherwise (non-PIC or local symbols) offset can be encoded + into relocation even if exceeds 16 bits. } + if (ref.symbol.bind<>AB_LOCAL) then + tmpref.offset:=0; + tmpref.refaddr:=addr_pic; + tmpref.base:=NR_GP; + list.concat(taicpu.op_reg_ref(A_LW,ref.base,tmpref)); + end + else + begin + tmpref.refaddr:=addr_high; + list.concat(taicpu.op_reg_ref(A_LUI,ref.base,tmpref)); + end; - tmpref.refaddr := addr_low; - list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg1, tmpreg1, tmpref)); - { symbol is loaded } - ref.symbol := nil; - end + { Add original base/index, if any. } + if (tmpreg<>NR_NO) then + list.concat(taicpu.op_reg_reg_reg(A_ADDU,ref.base,tmpreg,ref.base)); + + if (ref.symbol.bind=AB_LOCAL) or + not (cs_create_pic in current_settings.moduleswitches) then + begin + ref.refaddr:=addr_low; + exit; + end; + + { PIC global symbol } + ref.symbol:=nil; + if (ref.offset=0) then + exit; + + if (ref.offset>=simm16lo) and + (ref.offset<=simm16hi-sizeof(pint)) then + begin + list.concat(taicpu.op_reg_reg_const(A_ADDIU,ref.base,ref.base,ref.offset)); + ref.offset:=0; + exit; + end; + { fallthrough to the case of large offset } + end; + + tmpreg1:=getintregister(list,OS_INT); + a_load_const_reg(list,OS_INT,ref.offset,tmpreg1); + if (ref.base=NR_NO) then + ref.base:=tmpreg1 { offset alone, weird but possible } else - list.concat(taicpu.op_reg_const(A_LI, tmpreg1, ref.offset)); - - if (ref.index <> NR_NO) then - begin - list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.index, tmpreg1)); - ref.index := NR_NO - end; - if ref.base <> NR_NO then - list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.base, tmpreg1)); - ref.base := tmpreg1; - ref.offset := 0; + begin + if (not base_replaced) then + ref.base:=getintregister(list,OS_ADDR); + list.concat(taicpu.op_reg_reg_reg(A_ADDU,ref.base,tmpreg,tmpreg1)) + end; + ref.offset:=0; end; @@ -489,34 +435,6 @@ begin end; -procedure TCGMIPS.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); -var - Ref: TReference; - TmpReg: TRegister; -begin - paraloc.check_simple_location; - paramanager.allocparaloc(list,paraloc.location); - with paraloc.location^ do - begin - case loc of - LOC_REGISTER, LOC_CREGISTER: - a_loadaddr_ref_reg(list, r, Register); - LOC_REFERENCE: - begin - reference_reset(ref,sizeof(aint)); - ref.base := reference.index; - ref.offset := reference.offset; - tmpreg := GetAddressRegister(list); - a_loadaddr_ref_reg(list, r, tmpreg); - a_load_reg_ref(list, OS_ADDR, OS_ADDR, tmpreg, ref); - end; - else - internalerror(2002080701); - end; - end; -end; - - procedure TCGMIPS.a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); var href, href2: treference; @@ -567,38 +485,58 @@ begin end; -procedure TCGMIPS.a_call_name(list: tasmlist; const s: string; weak: boolean); +procedure TCGMIPS.a_call_sym_pic(list: tasmlist; sym: tasmsymbol); var href: treference; +begin + reference_reset_symbol(href,sym,0,sizeof(aint)); + if (sym.bind=AB_LOCAL) then + href.refaddr:=addr_pic + else + href.refaddr:=addr_pic_call16; + href.base:=NR_GP; + list.concat(taicpu.op_reg_ref(A_LW,NR_PIC_FUNC,href)); + if (sym.bind=AB_LOCAL) then + begin + href.refaddr:=addr_low; + list.concat(taicpu.op_reg_ref(A_ADDIU,NR_PIC_FUNC,href)); + end; + { JAL handled as macro provides delay slot and correct restoring of GP. } + { Doing it ourselves requires a fixup pass, because GP restore location + becomes known only in g_proc_entry, when all code is already generated. } + + { GAS <2.21 is buggy, it doesn't add delay slot in noreorder mode. As a result, + the code will crash if dealing with stack frame size >32767 or if calling + into shared library. + This can be remedied by enabling instruction reordering, but then we also + have to emit .set macro/.set nomacro pair and exclude JAL from the + list of macro instructions (because noreorder is not allowed after nomacro) } + list.concat(taicpu.op_none(A_P_SET_MACRO)); + list.concat(taicpu.op_none(A_P_SET_REORDER)); + list.concat(taicpu.op_reg(A_JAL,NR_PIC_FUNC)); + list.concat(taicpu.op_none(A_P_SET_NOREORDER)); + list.concat(taicpu.op_none(A_P_SET_NOMACRO)); +end; + + +procedure TCGMIPS.a_call_name(list: tasmlist; const s: string; weak: boolean); +var + sym: tasmsymbol; begin if assigned(current_procinfo) and not (pi_do_call in current_procinfo.flags) then InternalError(2013022101); - if (cs_create_pic in current_settings.moduleswitches) then - begin - reference_reset(href,sizeof(aint)); - href.symbol:=current_asmdata.RefAsmSymbol(s); - a_loadaddr_ref_reg(list,href,NR_PIC_FUNC); - { JAL handled as macro provides delay slot and correct restoring of GP. } - { Doing it ourselves requires a fixup pass, because GP restore location - becomes known only in g_proc_entry, when all code is already generated. } + if weak then + sym:=current_asmdata.WeakRefAsmSymbol(s) + else + sym:=current_asmdata.RefAsmSymbol(s); - { GAS <2.21 is buggy, it doesn't add delay slot in noreorder mode. As a result, - the code will crash if dealing with stack frame size >32767 or if calling - into shared library. - This can be remedied by enabling instruction reordering, but then we also - have to emit .set macro/.set nomacro pair and exclude JAL from the - list of macro instructions (because noreorder is not allowed after nomacro) } - list.concat(taicpu.op_none(A_P_SET_MACRO)); - list.concat(taicpu.op_none(A_P_SET_REORDER)); - list.concat(taicpu.op_reg(A_JAL,NR_PIC_FUNC)); - list.concat(taicpu.op_none(A_P_SET_NOREORDER)); - list.concat(taicpu.op_none(A_P_SET_NOMACRO)); - end + if (cs_create_pic in current_settings.moduleswitches) then + a_call_sym_pic(list,sym) else begin - list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s))); + list.concat(taicpu.op_sym(A_JAL,sym)); { Delay slot } list.concat(taicpu.op_none(A_NOP)); end; @@ -773,171 +711,85 @@ begin end; -procedure TCGMIPS.maybe_reload_gp(list : tasmlist); -var - tmpref: treference; -begin - if not (cs_create_pic in current_settings.moduleswitches) then - begin - list.concat(tai_comment.create( - strpnew('Reloading _gp for non-pic code'))); - reference_reset(tmpref,sizeof(aint)); - tmpref.symbol:=current_asmdata.RefAsmSymbol('_gp'); - cg.a_loadaddr_ref_reg(list,tmpref,NR_GP); - end; -end; - -procedure TCGMIPS.Load_PIC_Addr(list : tasmlist; tmpreg : Tregister; - var ref : treference); -var - tmpref : treference; -begin - reference_reset(tmpref,sizeof(aint)); - tmpref.symbol := ref.symbol; - { This only works correctly if pic generation is used, - so that -KPIC option is passed to GNU assembler } - if (cs_create_pic in current_settings.moduleswitches) then - begin - tmpref.refaddr:=addr_full; - list.concat(taicpu.op_reg_ref(A_LA, tmpreg, tmpref)); - end - else - begin - if (ref.refaddr=addr_pic_call16) or (ref.symbol.typ=AT_FUNCTION) then - begin - list.concat(tai_comment.create(strpnew('loadaddr pic %call16 code'))); - tmpref.refaddr := addr_pic_call16; - end - else - begin - list.concat(tai_comment.create(strpnew('loadaddr pic %got code'))); - tmpref.refaddr := addr_pic; - end; - if not (pi_needs_got in current_procinfo.flags) then - internalerror(200501161); - if current_procinfo.got=NR_NO then - current_procinfo.got:=NR_GP; - { for addr_pic NR_GP can be implicit or explicit } - if ref.refaddr in [addr_pic,addr_pic_call16] then - begin - if (ref.base=current_procinfo.got) then - ref.base:=NR_NO; - if (ref.index=current_procinfo.got) then - ref.index:=NR_NO; - end; - tmpref.base := current_procinfo.got; - list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref)); - if (tmpref.refaddr<>addr_pic_call16) {and - and (ref.symbol is TAsmSymbolSect) and - (TAsmSymbolSect(ref.symbol).sectype in needs_pic_lo16_set)} then - begin - { GOT also requires loading of low part } - { but apparently only for some type of sumbols :( } - list.concat(tai_comment.create(strpnew('pic %lo code'))); - tmpref.refaddr := addr_low; - tmpref.base := NR_NO; - list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg, tmpreg, tmpref)); - end; - end; - ref.symbol:=nil; - { This is now a normal addr reference } - ref.refaddr:=addr_no; - if (ref.index <> NR_NO) then - begin - list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg)); - ref.index := tmpreg; - end - else - begin - if ref.base <> NR_NO then - ref.index := tmpreg - else - ref.base := tmpreg; - end; -end; - - procedure TCGMIPS.a_loadaddr_ref_reg(list: tasmlist; const ref: TReference; r: tregister); var - tmpref, href: treference; - hreg, tmpreg: tregister; - r_used: boolean; + href: treference; + hreg: tregister; begin - r_used := false; - href := ref; - if (href.base = NR_NO) and (href.index <> NR_NO) then - internalerror(200306171); + { Enforce some discipline for callers: + - reference must be a "raw" one and not use gp } + if (ref.base=NR_GP) or (ref.index=NR_GP) then + InternalError(2013022803); + if (ref.refaddr<>addr_no) then + InternalError(2013022804); + if (ref.base=NR_NO) and (ref.index<>NR_NO) then + InternalError(200306171); - if ((cs_create_pic in current_settings.moduleswitches) or - (ref.refaddr in [addr_pic,addr_pic_call16])) and - assigned(href.symbol) then - begin - Load_PIC_Addr(list,r,href); - r_used := true; - if (href.base=NR_NO) and (href.offset=0) then + if (ref.symbol=nil) then + begin + if (ref.base<>NR_NO) then + begin + if (ref.offsetsimm16hi) then + begin + hreg:=getintregister(list,OS_INT); + a_load_const_reg(list,OS_INT,ref.offset,hreg); + list.concat(taicpu.op_reg_reg_reg(A_ADDU,r,ref.base,hreg)); + end + else if (ref.offset<>0) then + list.concat(taicpu.op_reg_reg_const(A_ADDIU,r,ref.base,ref.offset)) + else + a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r); { emit optimizable move } + + if (ref.index<>NR_NO) then + list.concat(taicpu.op_reg_reg_reg(A_ADDU,r,r,ref.index)); + end + else + a_load_const_reg(list,OS_INT,ref.offset,r); exit; - end; - - - if assigned(href.symbol) or - (href.offset < simm16lo) or - (href.offset > simm16hi) then - begin - if (href.base = NR_NO) and (href.index = NR_NO) then - hreg := r - else - hreg := GetAddressRegister(list); - reference_reset(tmpref,sizeof(aint)); - tmpref.symbol := href.symbol; - tmpref.offset := href.offset; - tmpref.refaddr := addr_high; - list.concat(taicpu.op_reg_ref(A_LUI, hreg, tmpref)); - { Only the low part is left } - tmpref.refaddr := addr_low; - list.concat(taicpu.op_reg_reg_ref(A_ADDIU, hreg, hreg, tmpref)); - if href.base <> NR_NO then - begin - if href.index <> NR_NO then - begin - list.concat(taicpu.op_reg_reg_reg(A_ADDU, hreg, href.base, hreg)); - list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index)); - end - else - list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.base)); end; - end - else - { At least small offset, maybe base and maybe index } - if (href.offset >= simm16lo) and - (href.offset <= simm16hi) then - begin - if href.index <> NR_NO then { Both base and index } + + reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment); + if (cs_create_pic in current_settings.moduleswitches) then begin - if href.offset = 0 then - begin - list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, href.base, href.index)); - end - else - begin - if r_used then - hreg := GetAddressRegister(list) - else - hreg := r; - list.concat(taicpu.op_reg_reg_const(A_ADDIU, hreg, href.base, href.offset)); - list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index)); - end + { For PIC global symbols offset must be handled separately. + Otherwise (non-PIC or local symbols) offset can be encoded + into relocation even if exceeds 16 bits. } + if (href.symbol.bind<>AB_LOCAL) then + href.offset:=0; + href.refaddr:=addr_pic; + href.base:=NR_GP; + list.concat(taicpu.op_reg_ref(A_LW,r,href)); end - else if href.base <> NR_NO then { Only base } - begin - if (href.offset<>0) or (r<>href.base) then - list.concat(taicpu.op_reg_reg_const(A_ADDIU, r, href.base, href.offset)); - end - else - { only offset, can be generated by absolute } - a_load_const_reg(list, OS_ADDR, href.offset, r); - end else - internalerror(200703111); + begin + href.refaddr:=addr_high; + list.concat(taicpu.op_reg_ref(A_LUI,r,href)); + end; + + { Add original base/index, if any. } + if (ref.base<>NR_NO) then + list.concat(taicpu.op_reg_reg_reg(A_ADDU,r,r,ref.base)); + if (ref.index<>NR_NO) then + list.concat(taicpu.op_reg_reg_reg(A_ADDU,r,r,ref.index)); + + { add low part if necessary } + if (ref.symbol.bind=AB_LOCAL) or + not (cs_create_pic in current_settings.moduleswitches) then + begin + href.refaddr:=addr_low; + href.base:=NR_NO; + list.concat(taicpu.op_reg_reg_ref(A_ADDIU,r,r,href)); + exit; + end; + + if (ref.offsetsimm16hi) then + begin + hreg:=getintregister(list,OS_INT); + a_load_const_reg(list,OS_INT,ref.offset,hreg); + list.concat(taicpu.op_reg_reg_reg(A_ADDU,r,r,hreg)); + end + else if (ref.offset<>0) then + list.concat(taicpu.op_reg_reg_const(A_ADDIU,r,r,ref.offset)); end; procedure TCGMIPS.a_loadfpu_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister); @@ -964,7 +816,7 @@ var href: TReference; begin href:=ref; - make_simple_ref_fpu(list,href); + make_simple_ref(list,href); case fromsize of OS_F32: list.concat(taicpu.op_reg_ref(A_LWC1,reg,href)); @@ -984,7 +836,7 @@ begin if tosize<>fromsize then a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg); href:=ref; - make_simple_ref_fpu(list,href); + make_simple_ref(list,href); case tosize of OS_F32: list.concat(taicpu.op_reg_ref(A_SWC1,reg,href)); diff --git a/compiler/mips/hlcgcpu.pas b/compiler/mips/hlcgcpu.pas index b98a15379e..2dd5c4a47d 100644 --- a/compiler/mips/hlcgcpu.pas +++ b/compiler/mips/hlcgcpu.pas @@ -32,14 +32,12 @@ uses globtype, aasmbase, aasmdata, cgbase, cgutils, - symtype,symdef, + symconst,symtype,symdef, parabase, hlcgobj, hlcg2ll; type thlcgmips = class(thlcg2ll) function a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara; override; - procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override; - procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override; end; procedure create_hlcodegen; @@ -56,30 +54,23 @@ implementation function thlcgmips.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara; var - ref : treference; + ref: treference; + sym: tasmsymbol; begin - if pd.proccalloption=pocall_cdecl then + if weak then + sym:=current_asmdata.WeakRefAsmSymbol(s) + else + sym:=current_asmdata.RefAsmSymbol(s); + + if (po_external in pd.procoptions) then begin - if (cs_create_pic in current_settings.moduleswitches) then + if not (cs_create_pic in current_settings.moduleswitches) then begin - reference_reset(ref,sizeof(aint)); - ref.symbol:=current_asmdata.RefAsmSymbol(s); - cg.a_loadaddr_ref_reg(list,ref,NR_PIC_FUNC); - end - else - begin - { Use $gp/$t9 registers as the code might be in a shared library } - reference_reset(ref,sizeof(aint)); - ref.symbol:=current_asmdata.RefAsmSymbol('_gp'); + reference_reset_symbol(ref,current_asmdata.RefAsmSymbol('_gp'),0,sizeof(aint)); list.concat(tai_comment.create(strpnew('Using PIC code for a_call_name'))); cg.a_loadaddr_ref_reg(list,ref,NR_GP); - reference_reset(ref,sizeof(aint)); - ref.symbol:=current_asmdata.RefAsmSymbol(s); - ref.base:=NR_GP; - ref.refaddr:=addr_pic_call16; - cg.a_loadaddr_ref_reg(list,ref,NR_PIC_FUNC); end; - cg.a_call_reg(list,NR_PIC_FUNC); + TCGMIPS(cg).a_call_sym_pic(list,sym); end else cg.a_call_name(list,s,weak); @@ -87,31 +78,6 @@ implementation result:=get_call_result_cgpara(pd,forceresdef); end; - procedure thlcgmips.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister); - begin - if (pd.proccalloption=pocall_cdecl) and (reg<>NR_PIC_FUNC) then - begin - list.concat(tai_comment.create(strpnew('Using PIC code for a_call_reg'))); - { Use $t9 register as the code might be in a shared library } - cg.a_load_reg_reg(list,OS_32,OS_32,reg,NR_PIC_FUNC); - cg.a_call_reg(list,NR_PIC_FUNC); - end - else - cg.a_call_reg(list,reg); - end; - - procedure thlcgmips.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference); - begin - if pd.proccalloption =pocall_cdecl then - begin - { Use $t9 register as the code might be in a shared library } - list.concat(tai_comment.create(strpnew('Using PIC code for a_call_ref'))); - cg.a_loadaddr_ref_reg(list,ref,NR_PIC_FUNC); - cg.a_call_reg(list,NR_PIC_FUNC); - end - else - cg.a_call_ref(list,ref); - end; procedure create_hlcodegen; begin