mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 16:09:26 +02:00
* first implementation of pic for i386
git-svn-id: trunk@2107 -
This commit is contained in:
parent
2aa9653a61
commit
fb4557d71e
@ -194,6 +194,9 @@ unit cgobj;
|
||||
procedure a_call_name(list : taasmoutput;const s : string);virtual; abstract;
|
||||
procedure a_call_reg(list : taasmoutput;reg : tregister);virtual; abstract;
|
||||
procedure a_call_ref(list : taasmoutput;ref : treference);virtual; abstract;
|
||||
{ same as a_call_name, might be overriden on certain architectures to emit
|
||||
static calls without usage of a got trampoline }
|
||||
procedure a_call_name_static(list : taasmoutput;const s : string);virtual;
|
||||
|
||||
{ move instructions }
|
||||
procedure a_load_const_reg(list : taasmoutput;size : tcgsize;a : aint;register : tregister);virtual; abstract;
|
||||
@ -2014,6 +2017,12 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcg.a_call_name_static(list : taasmoutput;const s : string);
|
||||
begin
|
||||
a_call_name(list,s);
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
TCG64
|
||||
*****************************************************************************}
|
||||
|
@ -103,8 +103,14 @@ interface
|
||||
is_reset,
|
||||
is_unit,
|
||||
in_interface, { processing the implementation part? }
|
||||
in_global : boolean; { allow global settings }
|
||||
mode_switch_allowed : boolean; { Whether a mode switch is still allowed at this point in the parsing.}
|
||||
{ allow global settings }
|
||||
in_global : boolean;
|
||||
{ Whether a mode switch is still allowed at this point in the parsing.}
|
||||
mode_switch_allowed,
|
||||
{ generate pic helper which loads eip in ecx (for leave procedures) }
|
||||
requires_ecx_pic_helper,
|
||||
{ generate pic helper which loads eip in ebx (for non leave procedures) }
|
||||
requires_ebx_pic_helper : boolean;
|
||||
mainfilepos : tfileposinfo;
|
||||
recompile_reason : trecompile_reason; { the reason why the unit should be recompiled }
|
||||
crc,
|
||||
|
@ -36,6 +36,8 @@ unit cgcpu;
|
||||
type
|
||||
tcg386 = class(tcgx86)
|
||||
procedure init_register_allocators;override;
|
||||
procedure do_register_allocation(list:Taasmoutput;headertai:tai);override;
|
||||
|
||||
{ passing parameter using push instead of mov }
|
||||
procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
|
||||
procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : tcgpara);override;
|
||||
@ -75,11 +77,11 @@ unit cgcpu;
|
||||
end;
|
||||
|
||||
|
||||
procedure Tcg386.init_register_allocators;
|
||||
procedure tcg386.init_register_allocators;
|
||||
begin
|
||||
inherited init_register_allocators;
|
||||
if cs_create_pic in aktmoduleswitches then
|
||||
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
|
||||
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP])
|
||||
else
|
||||
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
|
||||
rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
|
||||
@ -87,6 +89,13 @@ unit cgcpu;
|
||||
rgfpu:=Trgx86fpu.create;
|
||||
end;
|
||||
|
||||
procedure tcg386.do_register_allocation(list:Taasmoutput;headertai:tai);
|
||||
begin
|
||||
if pi_needs_got in current_procinfo.flags then
|
||||
include(rg[R_INTREGISTER].used_in_proc,getsupreg(current_procinfo.got));
|
||||
inherited do_register_allocation(list,headertai);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : tcgpara);
|
||||
var
|
||||
@ -556,7 +565,7 @@ unit cgcpu;
|
||||
if make_global then
|
||||
List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
|
||||
else
|
||||
List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
|
||||
List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
|
||||
|
||||
{ set param1 interface to self }
|
||||
g_adjust_self_value(list,procdef,ioffset);
|
||||
|
@ -116,6 +116,11 @@ interface
|
||||
|
||||
procedure location_free(list: taasmoutput; const location : TLocation);
|
||||
|
||||
function getprocalign : longint;
|
||||
|
||||
procedure gen_pic_helpers(list : taasmoutput);
|
||||
procedure gen_got_load(list : taasmoutput);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@ -1339,7 +1344,7 @@ implementation
|
||||
href : treference;
|
||||
begin
|
||||
case paraloc.loc of
|
||||
LOC_REGISTER :
|
||||
LOC_REGISTER :
|
||||
begin
|
||||
{$IFDEF CPUPOWERPC64}
|
||||
if (paraloc.shiftval <> 0) then
|
||||
@ -1884,6 +1889,25 @@ implementation
|
||||
cg.g_restore_standard_registers(list);
|
||||
end;
|
||||
|
||||
procedure gen_got_load(list : taasmoutput);
|
||||
begin
|
||||
{ if loading got is necessary for more cpus, it can be moved
|
||||
to the cg }
|
||||
{$ifdef i386}
|
||||
{ allocate PIC register }
|
||||
if (cs_create_pic in aktmoduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
begin
|
||||
current_module.requires_ebx_pic_helper:=true;
|
||||
cg.a_call_name_static(list,'fpc_geteipasebx');
|
||||
list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,objectlibrary.newasmsymbol('_GLOBAL_OFFSET_TABLE_',AB_EXTERNAL,AT_DATA),0,NR_PIC_OFFSET_REG));
|
||||
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
|
||||
{ ecx could be used in leave procedures }
|
||||
current_procinfo.got:=NR_EBX;
|
||||
end;
|
||||
{$endif i386}
|
||||
end;
|
||||
|
||||
{****************************************************************************
|
||||
External handling
|
||||
@ -2274,4 +2298,42 @@ implementation
|
||||
cg.g_maybe_testvmt(list,vmtreg,objdef);
|
||||
end;
|
||||
|
||||
|
||||
function getprocalign : longint;
|
||||
begin
|
||||
{ gprof uses 16 byte granularity }
|
||||
if (cs_profile in aktmoduleswitches) then
|
||||
result:=16
|
||||
else
|
||||
result:=aktalignment.procalign;
|
||||
end;
|
||||
|
||||
|
||||
procedure gen_pic_helpers(list : taasmoutput);
|
||||
var
|
||||
href : treference;
|
||||
begin
|
||||
{ if other cpus require such helpers as well, it can be solved more cleaner }
|
||||
{$ifdef i386}
|
||||
if current_module.requires_ebx_pic_helper then
|
||||
begin
|
||||
new_section(list,sec_code,'fpc_geteipasebx',0);
|
||||
list.concat(tai_symbol.Createname('fpc_geteipasebx',AT_FUNCTION,getprocalign));
|
||||
reference_reset(href);
|
||||
href.base:=NR_ESP;
|
||||
list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,NR_EBX));
|
||||
list.concat(taicpu.op_none(A_RET,S_NO));
|
||||
end;
|
||||
if current_module.requires_ecx_pic_helper then
|
||||
begin
|
||||
new_section(list,sec_code,'fpc_geteipasecx',0);
|
||||
list.concat(tai_symbol.Createname('fpc_geteipasecx',AT_FUNCTION,getprocalign));
|
||||
reference_reset(href);
|
||||
href.base:=NR_ESP;
|
||||
list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,NR_ECX));
|
||||
list.concat(taicpu.op_none(A_RET,S_NO));
|
||||
end;
|
||||
{$endif i386}
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -371,7 +371,6 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure AddUnit(const s:string);
|
||||
var
|
||||
hp : tppumodule;
|
||||
@ -812,13 +811,13 @@ implementation
|
||||
end;
|
||||
|
||||
procedure delete_duplicate_macros(p:TNamedIndexItem; arg:pointer);
|
||||
var
|
||||
hp: tsymentry;
|
||||
begin
|
||||
hp:= current_module.localmacrosymtable.search(p.name);
|
||||
if assigned(hp) then
|
||||
current_module.localmacrosymtable.delete(hp);
|
||||
end;
|
||||
var
|
||||
hp: tsymentry;
|
||||
begin
|
||||
hp:= current_module.localmacrosymtable.search(p.name);
|
||||
if assigned(hp) then
|
||||
current_module.localmacrosymtable.delete(hp);
|
||||
end;
|
||||
|
||||
procedure proc_unit;
|
||||
|
||||
@ -1172,6 +1171,9 @@ implementation
|
||||
gen_intf_wrappers(asmlist[al_procedures],current_module.globalsymtable);
|
||||
gen_intf_wrappers(asmlist[al_procedures],current_module.localsymtable);
|
||||
|
||||
{ generate pic helpers to load eip if necessary }
|
||||
gen_pic_helpers(asmlist[al_procedures]);
|
||||
|
||||
{ generate a list of threadvars }
|
||||
{$ifndef segment_threadvars}
|
||||
InsertThreadvars;
|
||||
@ -1494,6 +1496,8 @@ implementation
|
||||
{ generate wrappers for interfaces }
|
||||
gen_intf_wrappers(asmlist[al_procedures],current_module.localsymtable);
|
||||
|
||||
{ generate pic helpers to load eip if necessary }
|
||||
gen_pic_helpers(asmlist[al_procedures]);
|
||||
{$ifndef segment_threadvars}
|
||||
{ generate a list of threadvars }
|
||||
InsertThreadvars;
|
||||
|
@ -611,7 +611,6 @@ implementation
|
||||
oldfilepos : tfileposinfo;
|
||||
templist : Taasmoutput;
|
||||
headertai : tai;
|
||||
curralign : longint;
|
||||
begin
|
||||
{ the initialization procedure can be empty, then we
|
||||
don't need to generate anything. When it was an empty
|
||||
@ -798,6 +797,11 @@ implementation
|
||||
aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
|
||||
end;
|
||||
|
||||
{ load got if necessary }
|
||||
aktfilepos:=entrypos;
|
||||
gen_got_load(templist);
|
||||
aktproccode.insertlistafter(headertai,templist);
|
||||
|
||||
{ The procedure body is finished, we can now
|
||||
allocate the registers }
|
||||
cg.do_register_allocation(aktproccode,headertai);
|
||||
@ -866,15 +870,9 @@ implementation
|
||||
(cs_use_lineinfo in aktglobalswitches) then
|
||||
debuginfo.insertlineinfo(aktproccode);
|
||||
|
||||
{ gprof uses 16 byte granularity }
|
||||
if (cs_profile in aktmoduleswitches) then
|
||||
curralign:=16
|
||||
else
|
||||
curralign:=aktalignment.procalign;
|
||||
|
||||
{ add the procedure to the al_procedures }
|
||||
maybe_new_object_file(asmlist[al_procedures]);
|
||||
new_section(asmlist[al_procedures],sec_code,lower(procdef.mangledname),curralign);
|
||||
new_section(asmlist[al_procedures],sec_code,lower(procdef.mangledname),getprocalign);
|
||||
asmlist[al_procedures].concatlist(aktproccode);
|
||||
{ save local data (casetable) also in the same file }
|
||||
if assigned(aktlocaldata) and
|
||||
|
@ -55,6 +55,7 @@ unit cgx86;
|
||||
procedure a_call_name(list : taasmoutput;const s : string);override;
|
||||
procedure a_call_reg(list : taasmoutput;reg : tregister);override;
|
||||
procedure a_call_ref(list : taasmoutput;ref : treference);override;
|
||||
procedure a_call_name_static(list : taasmoutput;const s : string);override;
|
||||
|
||||
procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
|
||||
procedure a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: aint; const ref: TReference); override;
|
||||
@ -153,7 +154,8 @@ unit cgx86;
|
||||
uses
|
||||
globals,verbose,systems,cutils,
|
||||
dwarf,
|
||||
symdef,defutil,paramgr,procinfo;
|
||||
symdef,defutil,paramgr,procinfo,
|
||||
fmodule;
|
||||
|
||||
const
|
||||
TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
|
||||
@ -400,6 +402,7 @@ unit cgx86;
|
||||
hreg:=getaddressregister(list);
|
||||
href.refaddr:=addr_pic;
|
||||
href.base:=current_procinfo.got;
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,hreg));
|
||||
|
||||
ref.symbol:=nil;
|
||||
@ -544,13 +547,30 @@ unit cgx86;
|
||||
sym:=objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION);
|
||||
reference_reset_symbol(r,sym,0);
|
||||
if cs_create_pic in aktmoduleswitches then
|
||||
r.refaddr:=addr_pic
|
||||
begin
|
||||
{$ifdef i386}
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
{$endif i386}
|
||||
r.refaddr:=addr_pic
|
||||
end
|
||||
else
|
||||
r.refaddr:=addr_full;
|
||||
list.concat(taicpu.op_ref(A_CALL,S_NO,r));
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.a_call_name_static(list : taasmoutput;const s : string);
|
||||
var
|
||||
sym : tasmsymbol;
|
||||
r : treference;
|
||||
begin
|
||||
sym:=objectlibrary.newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION);
|
||||
reference_reset_symbol(r,sym,0);
|
||||
r.refaddr:=addr_full;
|
||||
list.concat(taicpu.op_ref(A_CALL,S_NO,r));
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.a_call_reg(list : taasmoutput;reg : tregister);
|
||||
begin
|
||||
list.concat(taicpu.op_reg(A_CALL,S_NO,reg));
|
||||
@ -718,6 +738,7 @@ unit cgx86;
|
||||
reference_reset_symbol(tmpref,ref.symbol,0);
|
||||
tmpref.refaddr:=addr_pic;
|
||||
tmpref.base:=current_procinfo.got;
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
|
||||
{$endif x86_64}
|
||||
if offset<>0 then
|
||||
@ -1817,16 +1838,6 @@ unit cgx86;
|
||||
cg.g_stackpointer_alloc(list,localsize);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ allocate PIC register }
|
||||
if (cs_create_pic in aktmoduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) then
|
||||
begin
|
||||
a_call_name(list,'FPC_GETEIPINEBX');
|
||||
list.concat(taicpu.op_sym_ofs_reg(A_ADD,tcgsize2opsize[OS_ADDR],objectlibrary.newasmsymbol('_GLOBAL_OFFSET_TABLE_',AB_EXTERNAL,AT_DATA),0,NR_PIC_OFFSET_REG));
|
||||
list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
|
||||
current_procinfo.got:=NR_PIC_OFFSET_REG;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -28,20 +28,22 @@ function cpuid_support : boolean;assembler;
|
||||
Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
|
||||
}
|
||||
asm
|
||||
pushf
|
||||
pushf
|
||||
pop eax
|
||||
mov ebx,eax
|
||||
xor eax,200000h
|
||||
push ebx
|
||||
pushf
|
||||
pushf
|
||||
pop eax
|
||||
mov ebx,eax
|
||||
xor eax,200000h
|
||||
push eax
|
||||
popf
|
||||
pushf
|
||||
pop eax
|
||||
popf
|
||||
and eax,200000h
|
||||
and ebx,200000h
|
||||
cmp eax,ebx
|
||||
setnz al
|
||||
popf
|
||||
pushf
|
||||
pop eax
|
||||
popf
|
||||
and eax,200000h
|
||||
and ebx,200000h
|
||||
cmp eax,ebx
|
||||
setnz al
|
||||
pop ebx
|
||||
end;
|
||||
|
||||
{$asmmode ATT}
|
||||
@ -53,9 +55,9 @@ function sse_support : boolean;
|
||||
if cpuid_support then
|
||||
begin
|
||||
asm
|
||||
movl $1,%eax
|
||||
cpuid
|
||||
movl %edx,_edx
|
||||
movl $1,%eax
|
||||
cpuid
|
||||
movl %edx,_edx
|
||||
end;
|
||||
sse_support:=(_edx and $2000000)<>0;
|
||||
end
|
||||
@ -96,12 +98,6 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
function geteipasebx : pointer;assembler;[public,alias:'FPC_GETEIPINEBX'];
|
||||
asm
|
||||
movl (%esp),%ebx
|
||||
ret
|
||||
end;
|
||||
|
||||
{$ifndef FPC_SYSTEM_HAS_MOVE}
|
||||
{$define FPC_SYSTEM_HAS_MOVE}
|
||||
procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;
|
||||
|
Loading…
Reference in New Issue
Block a user