* Proof of concept: Support threadvars using segment registers.

git-svn-id: trunk@740 -
This commit is contained in:
daniel 2005-07-24 21:06:23 +00:00
parent a1dd230825
commit 22e89e1a42
18 changed files with 149 additions and 94 deletions

View File

@ -47,7 +47,7 @@ interface
TAsmRelocationType = (RELOC_ABSOLUTE,RELOC_RELATIVE,RELOC_RVA);
TAsmSectionType=(sec_none,
sec_code,sec_data,sec_rodata,sec_bss,
sec_code,sec_data,sec_rodata,sec_bss,sec_tbss,
sec_common, { used for executable creation }
sec_custom, { custom section, no prefix }
{ stabs }
@ -572,7 +572,7 @@ implementation
function TAsmObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
const
secnames : array[tasmsectiontype] of string[12] = ('',
'code','data','rodata','bss',
'code','data','rodata','bss','tbss',
'common',
'note',
'stab','stabstr',

View File

@ -577,7 +577,7 @@ interface
Tasmlist=({ default lists }
datasegment,codesegment,bsssegment,debuglist,consts,
withdebuglist,importsection,exportsection,
threadvarsegment,withdebuglist,importsection,exportsection,
resourcesection,rttilist,dwarflist,
{ data used by pic code }
picdata,resourcestrings);

View File

@ -281,7 +281,7 @@ var
const
secnames : array[tasmsectiontype] of string[12] = ('',
{$warning TODO .rodata not yet working}
'.text','.data','.data','.bss',
'.text','.data','.data','.bss','.tbss',
'common',
'.note',
'.stab','.stabstr',
@ -291,7 +291,7 @@ var
);
begin
if use_smartlink_section and
(atype<>sec_bss) and
not (atype in [sec_bss,sec_tbss]) and
(aname<>'') then
result:='.gnu.linkonce'+copy(secnames[atype],1,2)+'.'+aname
else
@ -976,6 +976,7 @@ var
WriteTree(asmlist[picdata]);
Writetree(asmlist[resourcestrings]);
WriteTree(asmlist[bsssegment]);
WriteTree(asmlist[threadvarsegment]);
Writetree(asmlist[importsection]);
{ exports are written by DLLTOOL
if we use it so don't insert it twice (PM) }

View File

@ -1085,7 +1085,7 @@ Implementation
end;
ait_datablock :
begin
if objectdata.currsec.sectype<>sec_bss then
if not (objectdata.currsec.sectype in [sec_bss,sec_tbss]) then
Message(asmw_e_alloc_data_only_in_bss);
l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
if Tai_datablock(hp).is_global and
@ -1256,7 +1256,7 @@ Implementation
case hp.typ of
ait_align :
begin
if objectdata.currsec.sectype=sec_bss then
if objectdata.currsec.sectype in [sec_bss,sec_tbss] then
objectdata.alloc(Tai_align(hp).fillsize)
else
objectdata.writebytes(Tai_align(hp).calculatefillbuf(fillbuffer)^,Tai_align(hp).fillsize);

View File

@ -355,7 +355,7 @@ interface
procedure T386NasmAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
const
secnames : array[tasmsectiontype] of string[12] = ('',
'.text','.data','.rodata','.bss',
'.text','.data','.rodata','.bss','.tbss',
'common',
'.note',
'.stab','.stabstr',
@ -803,6 +803,7 @@ interface
WriteTree(asmlist[rttilist]);
WriteTree(asmlist[resourcestrings]);
WriteTree(asmlist[bsssegment]);
WriteTree(asmlist[threadvarsegment]);
Writetree(asmlist[importsection]);
{ exports are written by DLLTOOL
if we use it so don't insert it twice (PM) }

View File

@ -193,23 +193,25 @@ unit cgcpu;
begin
with r do
begin
{$ifndef segment_threadvars}
if (segment<>NR_NO) then
cgmessage(cg_e_cant_use_far_pointer_there);
{$endif}
if use_push(cgpara) then
begin
cgpara.check_simple_location;
opsize:=tcgsize2opsize[OS_ADDR];
if (base=NR_NO) and (index=NR_NO) then
if (segment=NR_NO) and (base=NR_NO) and (index=NR_NO) then
begin
if assigned(symbol) then
list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
else
list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
end
else if (base=NR_NO) and (index<>NR_NO) and
else if (segment=NR_NO) and (base=NR_NO) and (index<>NR_NO) and
(offset=0) and (scalefactor=0) and (symbol=nil) then
list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
else if (base<>NR_NO) and (index=NR_NO) and
else if (segment=NR_NO) and (base<>NR_NO) and (index=NR_NO) and
(offset=0) and (symbol=nil) then
list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
else

View File

@ -141,6 +141,7 @@ implementation
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
reference_reset_base(location.reference,hregister,0);
end
{$ifndef segment_threadvars}
{ Thread variable }
else if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
begin
@ -187,6 +188,7 @@ implementation
cg.a_label(exprasmlist,endrelocatelab);
location.reference.base:=hregister;
end
{$endif}
{ Nested variable }
else if assigned(left) then
begin
@ -247,6 +249,10 @@ implementation
reference_reset_symbol(location.reference,objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0)
else
location:=tglobalvarsym(symtableentry).localloc;
{$ifdef segment_threadvars}
if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
location.reference.segment:=NR_GS;
{$endif}
end;
end;
else

View File

@ -1966,18 +1966,35 @@ implementation
var
l,varalign : longint;
storefilepos : tfileposinfo;
list : Taasmoutput;
sectype : Tasmsectiontype;
begin
storefilepos:=aktfilepos;
aktfilepos:=sym.fileinfo;
l:=sym.getsize;
{$ifndef segment_threadvars}
if (vo_is_thread_var in sym.varoptions) then
inc(l,sizeof(aint));
list:=asmlist[bsssegment];
sectype:=sec_bss;
{$else}
if (vo_is_thread_var in sym.varoptions) then
begin
list:=asmlist[threadvarsegment];
sectype:=sec_tbss;
end
else
begin
list:=asmlist[bsssegment];
sectype:=sec_bss;
end;
{$endif}
varalign:=var_align(l);
maybe_new_object_file(asmlist[bsssegment]);
new_section(asmlist[bsssegment],sec_bss,lower(sym.mangledname),varalign);
maybe_new_object_file(list);
new_section(list,sectype,lower(sym.mangledname),varalign);
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) then
sym.concatstabto(asmlist[bsssegment]);
sym.concatstabto(list);
{$endif GDB}
if (sym.owner.symtabletype=globalsymtable) or
maybe_smartlink_symbol or
@ -1986,9 +2003,9 @@ implementation
(po_inline in current_procinfo.procdef.procoptions)) or
(vo_is_exported in sym.varoptions) or
(vo_is_C_var in sym.varoptions) then
asmlist[bsssegment].concat(Tai_datablock.Create_global(sym.mangledname,l))
list.concat(Tai_datablock.create_global(sym.mangledname,l))
else
asmlist[bsssegment].concat(Tai_datablock.Create(sym.mangledname,l));
list.concat(Tai_datablock.create(sym.mangledname,l));
aktfilepos:=storefilepos;
end;
@ -2097,8 +2114,8 @@ implementation
{ PIC, DLL and Threadvar need extra code and are handled in ncgld }
if not((target_info.system=system_powerpc_darwin) and
(cs_create_pic in aktmoduleswitches)) and
not(vo_is_dll_var in varoptions) and
not(vo_is_thread_var in varoptions) then
not(vo_is_dll_var in varoptions) {$ifndef segment_threadvars} and
not(vo_is_thread_var in varoptions) {$endif} then
reference_reset_symbol(localloc.reference,objectlibrary.newasmsymbol(mangledname,AB_EXTERNAL,AT_DATA),0);
end;
else

View File

@ -554,7 +554,7 @@ const go32v2stub : array[0..2047] of byte=(
function TCoffObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
const
secnames : array[tasmsectiontype] of string[16] = ('',
'.text','.data','.data','.bss',
'.text','.data','.data','.bss','.tbss',
'common',
'.note',
'.stab','.stabstr',

View File

@ -236,7 +236,7 @@ implementation
AshType:=SHT_PROGBITS;
AAlign:=max(sizeof(aint),AAlign);
end;
sec_bss :
sec_bss,sec_tbss :
begin
Ashflags:=SHF_ALLOC or SHF_WRITE;
AshType:=SHT_NOBITS;
@ -308,6 +308,7 @@ implementation
createsection(sec_code,'',0,[]);
createsection(sec_data,'',0,[]);
createsection(sec_bss,'',0,[]);
createsection(sec_tbss,'',0,[]);
{ create stabs sections if debugging }
if (cs_debuginfo in aktmoduleswitches) then
begin
@ -331,9 +332,9 @@ implementation
const
secnames : array[tasmsectiontype] of string[12] = ('',
{$ifdef userodata}
'.text','.data','.rodata','.bss',
'.text','.data','.rodata','.bss','.tbss',
{$else userodata}
'.text','.data','.data','.bss',
'.text','.data','.data','.bss','.tbss',
{$endif userodata}
'common',
'.note',
@ -344,7 +345,7 @@ implementation
);
begin
if use_smartlink_section and
(atype<>sec_bss) and
not (atype in [sec_bss,sec_tbss]) and
(aname<>'') then
result:='.gnu.linkonce'+copy(secnames[atype],1,2)+'.'+aname
else
@ -378,7 +379,7 @@ implementation
if currsec=nil then
internalerror(200403292);
{$ifdef userodata}
if currsec.sectype in [sec_rodata,sec_bss] then
if currsec.sectype in [sec_rodata,sec_bss,sec_tbss] then
internalerror(200408252);
{$endif userodata}
if assigned(p) then

View File

@ -252,7 +252,7 @@ implementation
exprasmlist:=taasmoutput.create;
{ Create assembler output lists for CG }
to_create:=[datasegment,codesegment,bsssegment,debuglist,
withdebuglist,consts,rttilist,picdata];
threadvarsegment,withdebuglist,consts,rttilist,picdata];
for i:=low(Tasmlist) to high(Tasmlist) do
if i in to_create then
asmlist[i]:=Taasmoutput.create

View File

@ -574,7 +574,7 @@ implementation
{ the top symbol table of symtablestack }
begin
consume(_VAR);
read_var_decs(false,false,false);
read_var_decs([]);
end;
@ -602,7 +602,7 @@ implementation
consume(_THREADVAR);
if not(symtablestack.symtabletype in [staticsymtable,globalsymtable]) then
message(parser_e_threadvars_only_sg);
read_var_decs(false,false,true);
read_var_decs([vd_threadvar]);
end;

View File

@ -597,7 +597,7 @@ implementation
not(oo_can_have_published in aktclass.objectoptions) then
Message(parser_e_cant_have_published);
read_var_decs(false,true,false);
read_var_decs([vd_object]);
end;
end;
end;

View File

@ -29,9 +29,12 @@ interface
uses
symsym,symdef;
type Tvar_dec_option=(vd_record,vd_object,vd_threadvar);
Tvar_dec_options=set of Tvar_dec_option;
function read_property_dec(aclass:tobjectdef):tpropertysym;
procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
procedure read_var_decs(options:Tvar_dec_options);
implementation
@ -582,7 +585,7 @@ implementation
const
variantrecordlevel : longint = 0;
procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
procedure read_var_decs(options:Tvar_dec_options);
{ reads the filed of a record into a }
{ symtablestack, if record=false }
{ variants are forbidden, so this procedure }
@ -710,7 +713,7 @@ implementation
{$endif powerpc}
old_current_object_option:=current_object_option;
{ all variables are public if not in a object declaration }
if not is_object then
if not(vd_object in options) then
current_object_option:=[sp_public];
old_block_type:=block_type;
block_type:=bt_type;
@ -720,8 +723,9 @@ implementation
consume(_ID);
{ read vars }
sc:=tsinglelist.create;
while (token=_ID) and
not(is_object and (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
while (token=_ID) and
not((vd_object in options) and
(idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
begin
sorg:=orgpattern;
semicoloneaten:=false;
@ -749,8 +753,7 @@ implementation
consume(_ID);
until not try_to_consume(_COMMA);
consume(_COLON);
if (m_gpc in aktmodeswitches) and
not(is_record or is_object or is_threadvar) and
if (m_gpc in aktmodeswitches) and (options=[]) and
(token=_ID) and (orgpattern='__asmname__') then
begin
consume(_ID);
@ -760,7 +763,7 @@ implementation
{ this is needed for Delphi mode at least
but should be OK for all modes !! (PM) }
ignore_equal:=true;
if is_record or is_object then
if options*[vd_record,vd_object]<>[] then
begin
{ for records, don't search the recordsymtable for
the symbols of the types }
@ -797,7 +800,7 @@ implementation
the alignment of the first field. */
}
if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and
is_record and
(vd_record in options) and
is_first_field and
(trecordsymtable(symtablestack).usefieldalignment = -1) then
begin
@ -840,8 +843,7 @@ implementation
end;
{ check for absolute }
if not symdone and
(idtoken=_ABSOLUTE) and not(is_record or is_object or is_threadvar) then
if not symdone and (idtoken=_ABSOLUTE) and (options=[]) then
begin
consume(_ABSOLUTE);
abssym:=nil;
@ -949,7 +951,7 @@ implementation
try_consume_hintdirective(dummysymoptions);
{ Records and objects can't have default values }
if is_record or is_object then
if options*[vd_record,vd_object]<>[] then
begin
{ for a record there doesn't need to be a ; before the END or ) }
if not(token in [_END,_RKLAMMER]) and
@ -966,7 +968,7 @@ implementation
if (tt.def.deftype=procvardef) and
(tt.def.typesym=nil) then
handle_calling_convention(tprocvardef(tt.def));
read_default_value(sc,tt,is_threadvar);
read_default_value(sc,tt,vd_threadvar in options);
consume(_SEMICOLON);
{ for locals we've created typedconstsym with a different name }
if symtablestack.symtabletype<>localsymtable then
@ -996,12 +998,11 @@ implementation
{ Add calling convention for procvar }
handle_calling_convention(tprocvardef(tt.def));
{ Handling of Delphi typed const = initialized vars }
if (token=_EQUAL) and
not(is_record or is_object) and
if (token=_EQUAL) and (options*[vd_record,vd_object]=[]) and
not(m_tp7 in aktmodeswitches) and
(symtablestack.symtabletype<>parasymtable) then
begin
read_default_value(sc,tt,is_threadvar);
read_default_value(sc,tt,vd_threadvar in options);
consume(_SEMICOLON);
symdone:=true;
hasdefaultvalue:=true;
@ -1009,7 +1010,7 @@ implementation
end;
{ Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
if not symdone and not(is_record or is_object or is_threadvar) then
if not symdone and (options=[]) then
begin
if (
(token=_ID) and
@ -1147,7 +1148,7 @@ implementation
end;
{ Check for STATIC directive }
if not symdone and (is_object) and
if not symdone and (vd_object in options) and
(cs_static_keyword in aktmoduleswitches) and (idtoken=_STATIC) then
begin
include(current_object_option,sp_static);
@ -1183,14 +1184,14 @@ implementation
Message(parser_e_only_publishable_classes_can__be_published);
exclude(current_object_option,sp_published);
end;
insert_syms(sc,tt,is_threadvar,dummysymoptions);
insert_syms(sc,tt,vd_threadvar in options,dummysymoptions);
current_object_option:=old_current_object_option;
end;
end;
{ Check for Case }
if is_record and (token=_CASE) then
if (vd_record in options) and (token=_CASE) then
begin
maxsize:=0;
maxalignment:=0;
@ -1257,7 +1258,7 @@ implementation
consume(_LKLAMMER);
inc(variantrecordlevel);
if token<>_RKLAMMER then
read_var_decs(true,false,false);
read_var_decs([vd_record]);
dec(variantrecordlevel);
consume(_RKLAMMER);
{ calculates maximal variant size }

View File

@ -165,11 +165,12 @@ implementation
' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
end;
{ align code segment }
asmlist[codesegment].concat(Tai_align.Create(aktalignment.procalign));
asmlist[codesegment].concat(Tai_align.create(aktalignment.procalign));
{ Insert start and end of sections }
fixseg(asmlist[codesegment],sec_code,'____seg_code');
fixseg(asmlist[datasegment],sec_data,'____seg_data');
fixseg(asmlist[bsssegment],sec_bss,'____seg_bss');
fixseg(asmlist[threadvarsegment],sec_bss,'____seg_tbss');
{ we should use .rdata section for these two no ?
.rdata is a read only data section (PM) }
fixseg(asmlist[rttilist],sec_data,'____seg_rtti');
@ -190,7 +191,7 @@ implementation
{$endif GDB}
end;
{$ifndef segment_threadvars}
procedure InsertThreadvarTablesTable;
var
hp : tused_unit;
@ -226,7 +227,6 @@ implementation
ltvTables.free;
end;
procedure AddToThreadvarList(p:tnamedindexitem;arg:pointer);
var
ltvTable : taasmoutput;
@ -266,6 +266,7 @@ implementation
end;
ltvTable.Free;
end;
{$endif}
Procedure InsertResourceTablesTable;
@ -912,6 +913,8 @@ implementation
asmlist[codesegment].empty and
asmlist[datasegment].empty and
asmlist[bsssegment].empty and
asmlist[threadvarsegment].empty and
asmlist[rttilist].empty and
((asmlist[importsection]=nil) or asmlist[importsection].empty) and
((asmlist[resourcesection]=nil) or asmlist[resourcesection].empty) and
((asmlist[aasmtai.resourcestrings]=nil) or asmlist[aasmtai.resourcestrings].empty)
@ -930,7 +933,7 @@ implementation
force_init_final : boolean;
pd : tprocdef;
unitname8 : string[8];
has_impl: boolean;
has_impl,ag: boolean;
begin
if m_mac in aktmodeswitches then
begin
@ -1248,7 +1251,9 @@ implementation
gen_intf_wrappers(asmlist[codesegment],current_module.localsymtable);
{ generate a list of threadvars }
{$ifndef segment_threadvars}
InsertThreadvars;
{$endif}
{ generate imports }
if current_module.uses_imports then
@ -1256,15 +1261,19 @@ implementation
{ insert own objectfile, or say that it's in a library
(no check for an .o when loading) }
if is_assembler_generated then
ag:=is_assembler_generated;
if ag then
insertobjectfile
else
current_module.flags:=current_module.flags or uf_no_link;
begin
current_module.flags:=current_module.flags or uf_no_link;
current_module.flags:=current_module.flags and not uf_has_debuginfo;
end;
if cs_local_browser in aktmoduleswitches then
current_module.localsymtable:=refsymtable;
if is_assembler_generated then
if ag then
begin
{ create dwarf debuginfo }
create_dwarf;
@ -1561,8 +1570,10 @@ implementation
{ generate wrappers for interfaces }
gen_intf_wrappers(asmlist[codesegment],current_module.localsymtable);
{$ifndef segment_threadvars}
{ generate a list of threadvars }
InsertThreadvars;
{$endif}
{ generate imports }
if current_module.uses_imports then
@ -1574,7 +1585,9 @@ implementation
exportlib.generatelib;
{ insert Tables and StackLength }
{$ifndef segment_threadvars}
insertThreadVarTablesTable;
{$endif}
insertResourceTablesTable;
insertinitfinaltable;
insertmemorysizes;

View File

@ -232,7 +232,7 @@ implementation
{ for tp7 don't allow forward types }
if m_tp7 in aktmodeswitches then
typecanbeforward:=false;
read_var_decs(true,false,false);
read_var_decs([vd_record]);
consume(_END);
typecanbeforward:=storetypecanbeforward;
current_object_option:=old_object_option;

View File

@ -59,13 +59,13 @@ implementation
line_length = 70;
secnames : array[TAsmSectionType] of string[4] = ('',
'CODE','DATA','DATA','BSS',
'CODE','DATA','DATA','BSS','',
'','','','','','',
'','','','','',''
);
secnamesml64 : array[TAsmSectionType] of string[7] = ('',
'_TEXT','_DATE','_DATA','_BSS',
'_TEXT','_DATE','_DATA','_BSS','',
'','','','',
'idata$2','idata$4','idata$5','idata$6','idata$7','edata',
'',''
@ -881,6 +881,7 @@ implementation
WriteTree(asmlist[rttilist]);
WriteTree(asmlist[resourcestrings]);
WriteTree(asmlist[bsssegment]);
WriteTree(asmlist[threadvarsegment]);
Writetree(asmlist[importsection]);
{ exports are written by DLLTOOL
if we use it so don't insert it twice (PM) }

View File

@ -686,46 +686,58 @@ unit cgx86;
tmpref : treference;
begin
with ref do
if (base=NR_NO) and (index=NR_NO) then
begin
begin
if (base=NR_NO) and (index=NR_NO) then
if assigned(ref.symbol) then
begin
if cs_create_pic in aktmoduleswitches then
begin
if cs_create_pic in aktmoduleswitches then
begin
{$ifdef x86_64}
reference_reset_symbol(tmpref,ref.symbol,0);
tmpref.refaddr:=addr_pic;
tmpref.base:=NR_RIP;
list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
reference_reset_symbol(tmpref,ref.symbol,0);
tmpref.refaddr:=addr_pic;
tmpref.base:=NR_RIP;
list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
{$else x86_64}
reference_reset_symbol(tmpref,ref.symbol,0);
tmpref.refaddr:=addr_pic;
tmpref.base:=current_procinfo.got;
list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
reference_reset_symbol(tmpref,ref.symbol,0);
tmpref.refaddr:=addr_pic;
tmpref.base:=current_procinfo.got;
list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
{$endif x86_64}
end
else
begin
tmpref:=ref;
tmpref.refaddr:=ADDR_FULL;
list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
end;
end
end
else
begin
tmpref:=ref;
tmpref.refaddr:=ADDR_FULL;
list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
end
else
a_load_const_reg(list,OS_ADDR,offset,r);
end
else if (base=NR_NO) and (index<>NR_NO) and
(offset=0) and (scalefactor=0) and (symbol=nil) then
a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
else if (base<>NR_NO) and (index=NR_NO) and
(offset=0) and (symbol=nil) then
a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
else
begin
tmpref:=ref;
make_simple_ref(list,tmpref);
list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
end;
a_load_const_reg(list,OS_ADDR,offset,r)
else if (base=NR_NO) and (index<>NR_NO) and
(offset=0) and (scalefactor=0) and (symbol=nil) then
a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
else if (base<>NR_NO) and (index=NR_NO) and
(offset=0) and (symbol=nil) then
a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
else
begin
tmpref:=ref;
make_simple_ref(list,tmpref);
list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
end;
if (segment<>NR_NO) then
if segment=NR_GS then
begin
{$ifdef segment_threadvars}
{Convert thread local address to a process global addres
as we cannot handle far pointers.}
reference_reset_symbol(tmpref,objectlibrary.newasmsymbol(
'___fpc_threadvar_offset',AB_EXTERNAL,AT_DATA),0);
tmpref.segment:=NR_GS;
list.concat(Taicpu.op_ref_reg(A_ADD,tcgsize2opsize[OS_ADDR],tmpref,r));
{$endif}
end
else
cgmessage(cg_e_cant_use_far_pointer_there);
end;
end;