|
@@ -46,11 +46,13 @@ interface
|
|
|
implementation
|
|
|
|
|
|
uses
|
|
|
- globals,aasmdata,defutil,
|
|
|
- symconst,symcpu,
|
|
|
+ globals,verbose,aasmdata,defutil,
|
|
|
+ symconst,symdef,symtable,symcpu,
|
|
|
nld,
|
|
|
cgbase,cgobj,cgutils,
|
|
|
- cpubase,cpuinfo;
|
|
|
+ hlcgobj,
|
|
|
+ cpubase,cpuinfo,
|
|
|
+ parabase,paramgr;
|
|
|
|
|
|
{*****************************************************************************
|
|
|
TI8086LOADNODE
|
|
@@ -98,6 +100,12 @@ implementation
|
|
|
refsym: TAsmSymbol;
|
|
|
segreg: TRegister;
|
|
|
newsize: TCgSize;
|
|
|
+ norelocatelab: TAsmLabel;
|
|
|
+ endrelocatelab: TAsmLabel;
|
|
|
+ pvd: tdef;
|
|
|
+ paraloc1 : tcgpara;
|
|
|
+ hregister: TRegister;
|
|
|
+ href: treference;
|
|
|
begin
|
|
|
if current_settings.x86memorymodel=mm_huge then
|
|
|
begin
|
|
@@ -114,8 +122,72 @@ implementation
|
|
|
{ Thread variable }
|
|
|
else if (vo_is_thread_var in gvs.varoptions) then
|
|
|
begin
|
|
|
- inherited pass_generate_code;
|
|
|
- exit;
|
|
|
+ if (cs_compilesystem in current_settings.moduleswitches) then
|
|
|
+ begin
|
|
|
+ inherited pass_generate_code;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { we don't know the size of all arrays }
|
|
|
+ newsize:=def_cgsize(resultdef);
|
|
|
+ { alignment is overridden per case below }
|
|
|
+ location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment);
|
|
|
+
|
|
|
+ {
|
|
|
+ Thread var loading is optimized to first check if
|
|
|
+ a relocate function is available. When the function
|
|
|
+ is available it is called to retrieve the address.
|
|
|
+ Otherwise the address is loaded with the symbol
|
|
|
+
|
|
|
+ The code needs to be in the order to first handle the
|
|
|
+ call and then the address load to be sure that the
|
|
|
+ register that is used for returning is the same (PFV)
|
|
|
+ }
|
|
|
+ current_asmdata.getjumplabel(norelocatelab);
|
|
|
+ current_asmdata.getjumplabel(endrelocatelab);
|
|
|
+ { make sure hregister can't allocate the register necessary for the parameter }
|
|
|
+ pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
|
|
|
+ if pvd.typ<>procvardef then
|
|
|
+ internalerror(2012120901);
|
|
|
+ paraloc1.init;
|
|
|
+ paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
|
|
|
+ hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
|
|
|
+ segreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_16);
|
|
|
+ reference_reset_symbol(segref,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,0);
|
|
|
+ segref.refaddr:=addr_seg;
|
|
|
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_16,OS_16,segref,segreg);
|
|
|
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,pvd.size);
|
|
|
+ href.segment:=segreg;
|
|
|
+ hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
|
|
|
+ hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
|
|
|
+ { don't save the allocated register else the result will be destroyed later }
|
|
|
+ if not(vo_is_weak_external in gvs.varoptions) then
|
|
|
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
|
|
|
+ else
|
|
|
+ reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
|
|
|
+ cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
|
|
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
|
|
|
+ paraloc1.done;
|
|
|
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
|
|
+ cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
|
|
|
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
|
|
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
|
|
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
|
|
+ hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
|
|
|
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
|
|
|
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
|
|
|
+ cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
|
|
|
+ { no relocation needed, load the address of the variable only, the
|
|
|
+ layout of a threadvar is (4 bytes pointer):
|
|
|
+ 0 - Threadvar index
|
|
|
+ 4 - Threadvar value in single threading }
|
|
|
+ if not(vo_is_weak_external in gvs.varoptions) then
|
|
|
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint))
|
|
|
+ else
|
|
|
+ reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint));
|
|
|
+ hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,voidpointertype,href,hregister);
|
|
|
+ cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
|
|
|
+ hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment);
|
|
|
end
|
|
|
{ Normal (or external) variable }
|
|
|
else
|