mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 17:49:07 +02:00
+ SPARC: generate position-independent case jump tables, as specified by ABI.
Generate them also for non-PIC mode: absolute code is just 2 instructions shorter, trying to save them is probably not worth the effort. git-svn-id: trunk@26468 -
This commit is contained in:
parent
dd78cd5811
commit
c673c32ad9
@ -86,7 +86,11 @@ implementation
|
|||||||
begin
|
begin
|
||||||
result:='';
|
result:='';
|
||||||
if assigned(ref.symbol) then
|
if assigned(ref.symbol) then
|
||||||
result:=ref.symbol.name;
|
begin
|
||||||
|
result:=ref.symbol.name;
|
||||||
|
if assigned(ref.relsymbol) then
|
||||||
|
result:=result+'-'+ref.relsymbol.name;
|
||||||
|
end;
|
||||||
if (ref.offset<0) then
|
if (ref.offset<0) then
|
||||||
result:=result+tostr(ref.offset)
|
result:=result+tostr(ref.offset)
|
||||||
else if (ref.offset>0) then
|
else if (ref.offset>0) then
|
||||||
|
@ -37,8 +37,6 @@ unit ncpuset;
|
|||||||
procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
|
procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
|
||||||
function has_jumptable : boolean;override;
|
function has_jumptable : boolean;override;
|
||||||
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
|
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
|
||||||
public
|
|
||||||
function pass_1:tnode;override;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -65,18 +63,9 @@ unit ncpuset;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tcpucasenode.pass_1:tnode;
|
|
||||||
begin
|
|
||||||
result:=inherited pass_1;
|
|
||||||
{ TODO: ABI-compliant position-independent case code does not involve GOT }
|
|
||||||
if (cs_create_pic in current_settings.moduleswitches) and
|
|
||||||
(tf_pic_uses_got in target_info.flags) then
|
|
||||||
include(current_procinfo.flags,pi_needs_got);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure tcpucasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
|
procedure tcpucasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
|
||||||
var
|
var
|
||||||
|
base,
|
||||||
table : tasmlabel;
|
table : tasmlabel;
|
||||||
last : TConstExprInt;
|
last : TConstExprInt;
|
||||||
indexreg,jmpreg,basereg : tregister;
|
indexreg,jmpreg,basereg : tregister;
|
||||||
@ -91,9 +80,9 @@ unit ncpuset;
|
|||||||
genitem(list,t^.less);
|
genitem(list,t^.less);
|
||||||
{ fill possible hole }
|
{ fill possible hole }
|
||||||
for i:=last.svalue+1 to t^._low.svalue-1 do
|
for i:=last.svalue+1 to t^._low.svalue-1 do
|
||||||
list.concat(Tai_const.Create_sym(elselabel));
|
list.concat(Tai_const.Create_rel_sym(aitconst_ptr,base,elselabel));
|
||||||
for i:=t^._low.svalue to t^._high.svalue do
|
for i:=t^._low.svalue to t^._high.svalue do
|
||||||
list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
|
list.concat(Tai_const.Create_rel_sym(aitconst_ptr,base,blocklabel(t^.blockid)));
|
||||||
last:=t^._high;
|
last:=t^._high;
|
||||||
if assigned(t^.greater) then
|
if assigned(t^.greater) then
|
||||||
genitem(list,t^.greater);
|
genitem(list,t^.greater);
|
||||||
@ -112,26 +101,45 @@ unit ncpuset;
|
|||||||
indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,hregister,indexreg);
|
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,hregister,indexreg);
|
||||||
{ create reference }
|
{ create reference }
|
||||||
reference_reset_symbol(href,table,0,sizeof(pint));
|
current_asmdata.getjumplabel(base);
|
||||||
href.offset:=(-aint(min_))*4;
|
cg.a_label(current_asmdata.CurrAsmList,base);
|
||||||
|
reference_reset_symbol(href,table,(-aint(min_))*4,sizeof(pint));
|
||||||
|
href.relsymbol:=base;
|
||||||
|
{ Generate the following code:
|
||||||
|
.Lbase:
|
||||||
|
call .+8 # mov %pc,%o7
|
||||||
|
sethi %hi(.LTable-.Lbase),%basereg
|
||||||
|
or %basereg,%lo(.LTable-.Lbase),%basereg
|
||||||
|
add %indexreg,%basereg%,%basereg
|
||||||
|
ld [%o7+%basereg],%jmpreg
|
||||||
|
jmp %o7+%jmpreg }
|
||||||
|
{ CALL overwrites %o7, tell reg.allocator about that }
|
||||||
|
cg.getcpuregister(current_asmdata.CurrAsmList,NR_O7);
|
||||||
|
current_asmdata.CurrAsmList.concat(taicpu.op_sym_ofs(A_CALL,base,8));
|
||||||
|
|
||||||
basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
|
{ TODO: incorporate handling such references into cg.a_loadaddr_ref_reg? }
|
||||||
|
href.refaddr:=addr_high;
|
||||||
|
current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_SETHI,href,basereg));
|
||||||
|
href.refaddr:=addr_low;
|
||||||
|
current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref_reg(A_OR,basereg,href,basereg));
|
||||||
|
{ add index }
|
||||||
|
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,basereg,indexreg,basereg);
|
||||||
|
|
||||||
jmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
jmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||||
|
reference_reset_base(href,NR_O7,0,sizeof(pint));
|
||||||
reference_reset(href,sizeof(pint));
|
href.index:=basereg;
|
||||||
href.index:=indexreg;
|
|
||||||
href.base:=basereg;
|
|
||||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,jmpreg);
|
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,jmpreg);
|
||||||
|
href.index:=jmpreg;
|
||||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JMP,jmpreg));
|
href.refaddr:=addr_full;
|
||||||
|
current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_JMP,href));
|
||||||
{ Delay slot }
|
{ Delay slot }
|
||||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
|
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_O7);
|
||||||
{ generate jump table }
|
{ generate jump table }
|
||||||
new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(pint));
|
|
||||||
current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
|
|
||||||
last:=min_;
|
last:=min_;
|
||||||
genitem(current_procinfo.aktlocaldata,hp);
|
cg.a_label(current_asmdata.CurrAsmList,table);
|
||||||
|
genitem(current_asmdata.CurrAsmList,hp);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user