* first implementation of pic for i386

git-svn-id: trunk@2107 -
This commit is contained in:
florian 2006-01-01 20:14:48 +00:00
parent 2aa9653a61
commit fb4557d71e
8 changed files with 151 additions and 56 deletions

View File

@ -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
*****************************************************************************}

View File

@ -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,

View File

@ -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

View File

@ -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
@ -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.

View File

@ -371,7 +371,6 @@ implementation
end;
procedure AddUnit(const s:string);
var
hp : tppumodule;
@ -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;

View File

@ -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

View File

@ -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
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;

View File

@ -28,6 +28,7 @@ function cpuid_support : boolean;assembler;
Tested under go32v1 and Linux on c6x86 with CpuID enabled and disabled (PFV)
}
asm
push ebx
pushf
pushf
pop eax
@ -42,6 +43,7 @@ function cpuid_support : boolean;assembler;
and ebx,200000h
cmp eax,ebx
setnz al
pop ebx
end;
{$asmmode ATT}
@ -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;