mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 05:59:28 +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
|
||||
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
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user