+ 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:
sergei 2014-01-15 15:31:53 +00:00
parent dd78cd5811
commit c673c32ad9
2 changed files with 39 additions and 27 deletions

View File

@ -86,7 +86,11 @@ implementation
begin
result:='';
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
result:=result+tostr(ref.offset)
else if (ref.offset>0) then

View File

@ -37,8 +37,6 @@ unit ncpuset;
procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
function has_jumptable : boolean;override;
procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
public
function pass_1:tnode;override;
end;
@ -65,18 +63,9 @@ unit ncpuset;
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);
var
base,
table : tasmlabel;
last : TConstExprInt;
indexreg,jmpreg,basereg : tregister;
@ -91,9 +80,9 @@ unit ncpuset;
genitem(list,t^.less);
{ fill possible hole }
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
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;
if assigned(t^.greater) then
genitem(list,t^.greater);
@ -112,26 +101,45 @@ unit ncpuset;
indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,hregister,indexreg);
{ create reference }
reference_reset_symbol(href,table,0,sizeof(pint));
href.offset:=(-aint(min_))*4;
current_asmdata.getjumplabel(base);
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);
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);
reference_reset(href,sizeof(pint));
href.index:=indexreg;
href.base:=basereg;
reference_reset_base(href,NR_O7,0,sizeof(pint));
href.index:=basereg;
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,jmpreg);
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JMP,jmpreg));
href.index:=jmpreg;
href.refaddr:=addr_full;
current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_JMP,href));
{ Delay slot }
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_O7);
{ 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_;
genitem(current_procinfo.aktlocaldata,hp);
cg.a_label(current_asmdata.CurrAsmList,table);
genitem(current_asmdata.CurrAsmList,hp);
end;