mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 23:20:29 +02:00
* SPARC: completely rewrote PIC-related code, got it twice shorter in source lines and much less instructions in generated code.
+ Enable registers %i0..%i5 and %o7 for use by reg.allocator. Some notable properties of this implementation are: o pi_needs_got flag can be safely set during pass 2, so not setting it occasionally in pass 1 does not result in internal error. o Reg.allocator configuration is independent from PIC. If procedure requires GOT, register %l7 is allocated at the prologue, making it unavailable to RA. o GOT is stored in fixed %l7 register, but it is trivial to switch over to virtual register. git-svn-id: trunk@26293 -
This commit is contained in:
parent
1a3b46967e
commit
176d8434e4
@ -43,7 +43,6 @@ interface
|
||||
function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override;
|
||||
{ sparc special, needed by cg64 }
|
||||
procedure make_simple_ref(list:TAsmList;var ref: treference);
|
||||
procedure make_simple_ref_sparc(list:TAsmList;var ref: treference;loadaddr : boolean;addrreg : tregister);
|
||||
procedure handle_load_store(list:TAsmList;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
|
||||
procedure handle_reg_const_reg(list:TAsmList;op:Tasmop;src:tregister;a:tcgint;dst:tregister);
|
||||
{ parameter }
|
||||
@ -142,8 +141,6 @@ implementation
|
||||
|
||||
function TCgSparc.IsSimpleRef(const ref:treference):boolean;
|
||||
begin
|
||||
if (ref.base=NR_NO) and (ref.index<>NR_NO) then
|
||||
InternalError(2002100804);
|
||||
result :=not(assigned(ref.symbol))and
|
||||
(((ref.index = NR_NO) and
|
||||
(ref.offset >= simm13lo) and
|
||||
@ -154,181 +151,113 @@ implementation
|
||||
|
||||
|
||||
procedure tcgsparc.make_simple_ref(list:TAsmList;var ref: treference);
|
||||
begin
|
||||
make_simple_ref_sparc(list,ref,false,NR_NO);
|
||||
end;
|
||||
|
||||
procedure tcgsparc.make_simple_ref_sparc(list:TAsmList;var ref: treference;loadaddr : boolean;addrreg : tregister);
|
||||
var
|
||||
tmpreg,tmpreg2 : tregister;
|
||||
tmpref : treference;
|
||||
need_add_got,need_got_load : boolean;
|
||||
href: treference;
|
||||
hreg,hreg2: tregister;
|
||||
begin
|
||||
if loadaddr then
|
||||
tmpreg:=addrreg
|
||||
else
|
||||
tmpreg:=NR_NO;
|
||||
need_add_got:=false;
|
||||
need_got_load:=false;
|
||||
{ Be sure to have a base register }
|
||||
if (ref.refaddr<>addr_no) then
|
||||
InternalError(2013022802);
|
||||
|
||||
if (ref.base=NR_NO) then
|
||||
begin
|
||||
ref.base:=ref.index;
|
||||
ref.index:=NR_NO;
|
||||
end;
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) and
|
||||
use_unlimited_pic_mode and
|
||||
assigned(ref.symbol) then
|
||||
|
||||
if IsSimpleRef(ref) then
|
||||
exit;
|
||||
|
||||
if (ref.symbol=nil) then
|
||||
begin
|
||||
if not(pi_needs_got in current_procinfo.flags) then
|
||||
begin
|
||||
{$ifdef CHECK_PIC}
|
||||
internalerror(200501161);
|
||||
{$endif CHECK_PIC}
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
end;
|
||||
if current_procinfo.got=NR_NO then
|
||||
current_procinfo.got:=NR_L7;
|
||||
need_got_load:=true;
|
||||
need_add_got:=true;
|
||||
end;
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) and
|
||||
not use_unlimited_pic_mode and
|
||||
assigned(ref.symbol) then
|
||||
begin
|
||||
if tmpreg=NR_NO then
|
||||
tmpreg:=GetIntRegister(list,OS_INT);
|
||||
reference_reset(tmpref,ref.alignment);
|
||||
tmpref.symbol:=ref.symbol;
|
||||
tmpref.refaddr:=addr_pic;
|
||||
if not(pi_needs_got in current_procinfo.flags) then
|
||||
begin
|
||||
{$ifdef CHECK_PIC}
|
||||
internalerror(200501161);
|
||||
{$endif CHECK_PIC}
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
end;
|
||||
if current_procinfo.got=NR_NO then
|
||||
current_procinfo.got:=NR_L7;
|
||||
tmpref.index:=current_procinfo.got;
|
||||
list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
|
||||
ref.symbol:=nil;
|
||||
if (ref.index<>NR_NO) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
|
||||
ref.index:=tmpreg;
|
||||
end
|
||||
hreg:=getintregister(list,OS_INT);
|
||||
if (ref.index=NR_NO) then
|
||||
a_load_const_reg(list,OS_INT,ref.offset,hreg)
|
||||
else
|
||||
begin
|
||||
if ref.base<>NR_NO then
|
||||
ref.index:=tmpreg
|
||||
else
|
||||
ref.base:=tmpreg;
|
||||
end;
|
||||
end;
|
||||
{ When need to use SETHI, do it first }
|
||||
if assigned(ref.symbol) or
|
||||
(ref.offset<simm13lo) or
|
||||
(ref.offset>simm13hi) then
|
||||
begin
|
||||
if tmpreg=NR_NO then
|
||||
tmpreg:=GetIntRegister(list,OS_INT);
|
||||
reference_reset(tmpref,ref.alignment);
|
||||
tmpref.symbol:=ref.symbol;
|
||||
if not need_got_load then
|
||||
tmpref.offset:=ref.offset;
|
||||
tmpref.refaddr:=addr_high;
|
||||
list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
|
||||
if (ref.offset=0) and (ref.index=NR_NO) and
|
||||
(ref.base=NR_NO) and not need_add_got then
|
||||
begin
|
||||
ref.refaddr:=addr_low;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ Load the low part is left }
|
||||
tmpref.refaddr:=addr_low;
|
||||
list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
|
||||
if not need_got_load then
|
||||
ref.offset:=0;
|
||||
{ symbol is loaded }
|
||||
ref.symbol:=nil;
|
||||
end;
|
||||
if need_add_got then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,current_procinfo.got,tmpreg));
|
||||
need_add_got:=false;
|
||||
end;
|
||||
if need_got_load then
|
||||
begin
|
||||
tmpref.refaddr:=addr_no;
|
||||
tmpref.base:=tmpreg;
|
||||
tmpref.symbol:=nil;
|
||||
list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
|
||||
need_got_load:=false;
|
||||
if (ref.offset<simm13lo) or
|
||||
(ref.offset>simm13hi) then
|
||||
if (ref.offset<simm13lo) or (ref.offset>simm13hi-sizeof(pint)) then
|
||||
begin
|
||||
tmpref.symbol:=nil;
|
||||
tmpref.offset:=ref.offset;
|
||||
tmpref.base:=tmpreg;
|
||||
tmpref.refaddr := addr_high;
|
||||
tmpreg2:=GetIntRegister(list,OS_INT);
|
||||
a_load_const_reg(list,OS_INT,ref.offset,tmpreg2);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg2,tmpreg));
|
||||
a_load_const_reg(list,OS_INT,ref.offset,hreg);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,hreg));
|
||||
end
|
||||
else
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,ref.index,ref.offset,hreg));
|
||||
end;
|
||||
if (ref.base=NR_NO) then
|
||||
ref.base:=hreg
|
||||
else
|
||||
ref.index:=hreg;
|
||||
ref.offset:=0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
|
||||
hreg:=getintregister(list,OS_INT);
|
||||
if not (cs_create_pic in current_settings.moduleswitches) then
|
||||
begin
|
||||
{ absolute loads allow any offset to be encoded into relocation }
|
||||
href.refaddr:=addr_high;
|
||||
list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
|
||||
if (ref.base=NR_NO) and (ref.index=NR_NO) then
|
||||
begin
|
||||
ref.base:=hreg;
|
||||
ref.refaddr:=addr_low;
|
||||
exit;
|
||||
end;
|
||||
{ base present -> load the entire address and use it as index }
|
||||
href.refaddr:=addr_low;
|
||||
list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
|
||||
ref.symbol:=nil;
|
||||
ref.offset:=0;
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.index,hreg,hreg));
|
||||
ref.index:=hreg;
|
||||
end
|
||||
else
|
||||
begin
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
href.offset:=0;
|
||||
if use_unlimited_pic_mode then
|
||||
begin
|
||||
href.refaddr:=addr_high;
|
||||
list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
|
||||
href.refaddr:=addr_low;
|
||||
list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
|
||||
reference_reset_base(href,hreg,0,sizeof(pint));
|
||||
href.index:=current_procinfo.got;
|
||||
end
|
||||
else
|
||||
begin
|
||||
href.base:=current_procinfo.got;
|
||||
href.refaddr:=addr_pic;
|
||||
end;
|
||||
list.concat(taicpu.op_ref_reg(A_LD,href,hreg));
|
||||
ref.symbol:=nil;
|
||||
{ hreg now holds symbol address. Add remaining members. }
|
||||
if (ref.offset>=simm13lo) and (ref.offset<=simm13hi-sizeof(pint)) then
|
||||
begin
|
||||
if (ref.base=NR_NO) then
|
||||
ref.base:=hreg
|
||||
else
|
||||
begin
|
||||
if (ref.offset<>0) then
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,hreg,ref.offset,hreg));
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,hreg));
|
||||
ref.index:=hreg;
|
||||
ref.offset:=0;
|
||||
end;
|
||||
end;
|
||||
if (ref.index<>NR_NO) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
|
||||
ref.index:=tmpreg;
|
||||
end
|
||||
else
|
||||
else { large offset, need another register to deal with it }
|
||||
begin
|
||||
if ref.base<>NR_NO then
|
||||
ref.index:=tmpreg
|
||||
else
|
||||
ref.base:=tmpreg;
|
||||
end;
|
||||
end;
|
||||
if need_add_got then
|
||||
begin
|
||||
if tmpreg=NR_NO then
|
||||
tmpreg:=GetIntRegister(list,OS_INT);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,current_procinfo.got,tmpreg));
|
||||
ref.base:=tmpreg;
|
||||
ref.index:=NR_NO;
|
||||
end;
|
||||
if need_got_load then
|
||||
begin
|
||||
if tmpreg=NR_NO then
|
||||
tmpreg:=GetIntRegister(list,OS_INT);
|
||||
list.concat(taicpu.op_ref_reg(A_LD,ref,tmpreg));
|
||||
ref.base:=tmpreg;
|
||||
ref.index:=NR_NO;
|
||||
end;
|
||||
if (ref.base<>NR_NO) or loadaddr then
|
||||
begin
|
||||
if loadaddr then
|
||||
begin
|
||||
if ref.index<>NR_NO then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
|
||||
ref.base:=tmpreg;
|
||||
ref.index:=NR_NO;
|
||||
if ref.offset<>0 then
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,tmpreg));
|
||||
end
|
||||
else if (ref.index<>NR_NO) and
|
||||
((ref.offset<>0) or assigned(ref.symbol)) then
|
||||
begin
|
||||
if tmpreg=NR_NO then
|
||||
tmpreg:=GetIntRegister(list,OS_INT);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
|
||||
ref.base:=tmpreg;
|
||||
ref.index:=NR_NO;
|
||||
hreg2:=getintregister(list,OS_INT);
|
||||
a_load_const_reg(list,OS_INT,ref.offset,hreg2);
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg2,ref.index,hreg2));
|
||||
if (ref.base<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg2,ref.base,hreg2));
|
||||
ref.base:=hreg;
|
||||
ref.index:=hreg2;
|
||||
ref.offset:=0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -376,21 +305,11 @@ implementation
|
||||
begin
|
||||
inherited init_register_allocators;
|
||||
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
assigned(current_procinfo) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
begin
|
||||
current_procinfo.got:=NR_L7;
|
||||
rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
|
||||
[RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
|
||||
RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6],
|
||||
first_int_imreg,[]);
|
||||
end
|
||||
else
|
||||
rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
|
||||
[RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
|
||||
RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7],
|
||||
first_int_imreg,[]);
|
||||
rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
|
||||
[RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,RS_O7,
|
||||
RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7,
|
||||
RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5],
|
||||
first_int_imreg,[]);
|
||||
|
||||
rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBFS,
|
||||
[RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
|
||||
@ -739,164 +658,89 @@ implementation
|
||||
|
||||
procedure TCgSparc.a_loadaddr_ref_reg(list : TAsmList;const ref : TReference;r : tregister);
|
||||
var
|
||||
tmpref,href : treference;
|
||||
hreg,tmpreg,hreg2 : tregister;
|
||||
need_got,need_got_load : boolean;
|
||||
href: treference;
|
||||
hreg: tregister;
|
||||
begin
|
||||
href:=ref;
|
||||
{$ifdef TEST_SIMPLE_SPARC}
|
||||
make_simple_ref_sparc(list,href,true,r);
|
||||
{$else}
|
||||
need_got:=false;
|
||||
need_got_load:=false;
|
||||
if (href.base=NR_NO) and (href.index<>NR_NO) then
|
||||
if (ref.base=NR_NO) and (ref.index<>NR_NO) then
|
||||
internalerror(200306171);
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) and
|
||||
use_unlimited_pic_mode and
|
||||
assigned(ref.symbol) then
|
||||
|
||||
if (ref.symbol=nil) then
|
||||
begin
|
||||
if not(pi_needs_got in current_procinfo.flags) then
|
||||
if (ref.base<>NR_NO) then
|
||||
begin
|
||||
{$ifdef CHECK_PIC}
|
||||
internalerror(200501161);
|
||||
{$endif CHECK_PIC}
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
end;
|
||||
if current_procinfo.got=NR_NO then
|
||||
current_procinfo.got:=NR_L7;
|
||||
need_got_load:=true;
|
||||
need_got:=true;
|
||||
if (ref.offset<simm13lo) or (ref.offset>simm13hi) then
|
||||
begin
|
||||
hreg:=getintregister(list,OS_INT);
|
||||
a_load_const_reg(list,OS_INT,ref.offset,hreg);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,r));
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
|
||||
end
|
||||
else if (ref.offset<>0) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,r));
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
|
||||
end
|
||||
else if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,r))
|
||||
else
|
||||
a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r); { (try to) emit optimizable move }
|
||||
end
|
||||
else
|
||||
a_load_const_reg(list,OS_INT,ref.offset,r);
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(tf_pic_uses_got in target_info.flags) and
|
||||
not use_unlimited_pic_mode and
|
||||
assigned(href.symbol) then
|
||||
reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
|
||||
if (cs_create_pic in current_settings.moduleswitches) then
|
||||
begin
|
||||
tmpreg:=GetIntRegister(list,OS_ADDR);
|
||||
reference_reset(tmpref,href.alignment);
|
||||
tmpref.symbol:=href.symbol;
|
||||
tmpref.refaddr:=addr_pic;
|
||||
if not(pi_needs_got in current_procinfo.flags) then
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
href.offset:=0;
|
||||
if use_unlimited_pic_mode then
|
||||
begin
|
||||
{$ifdef CHECK_PIC}
|
||||
internalerror(200501161);
|
||||
{$endif CHECK_PIC}
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
end;
|
||||
if current_procinfo.got=NR_NO then
|
||||
current_procinfo.got:=NR_L7;
|
||||
tmpref.base:=current_procinfo.got;
|
||||
list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
|
||||
href.symbol:=nil;
|
||||
if (href.index<>NR_NO) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,href.index,tmpreg));
|
||||
href.index:=tmpreg;
|
||||
href.refaddr:=addr_high;
|
||||
list.concat(taicpu.op_ref_reg(A_SETHI,href,r));
|
||||
href.refaddr:=addr_low;
|
||||
list.concat(taicpu.op_reg_ref_reg(A_OR,r,href,r));
|
||||
reference_reset_base(href,r,0,sizeof(pint));
|
||||
href.index:=current_procinfo.got;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if href.base<>NR_NO then
|
||||
href.index:=tmpreg
|
||||
else
|
||||
href.base:=tmpreg;
|
||||
href.base:=current_procinfo.got;
|
||||
href.refaddr:=addr_pic; { should it be done THAT way?? }
|
||||
end;
|
||||
end;
|
||||
|
||||
{ At least big offset (need SETHI), maybe base and maybe index }
|
||||
if assigned(href.symbol) or
|
||||
(href.offset<simm13lo) or
|
||||
(href.offset>simm13hi) then
|
||||
begin
|
||||
hreg:=GetAddressRegister(list);
|
||||
reference_reset(tmpref,href.alignment);
|
||||
tmpref.symbol := href.symbol;
|
||||
if not need_got_load then
|
||||
tmpref.offset := href.offset;
|
||||
tmpref.refaddr := addr_high;
|
||||
list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
|
||||
{ Only the low part is left }
|
||||
tmpref.refaddr:=addr_low;
|
||||
list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
|
||||
if need_got then
|
||||
{ load contents of GOT slot }
|
||||
list.concat(taicpu.op_ref_reg(A_LD,href,r));
|
||||
{ add original base/index, if any }
|
||||
if (ref.base<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.base,r));
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
|
||||
{ finally, add offset }
|
||||
if (ref.offset<simm13lo) or (ref.offset>simm13hi) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,current_procinfo.got,hreg));
|
||||
need_got:=false;
|
||||
end;
|
||||
if need_got_load then
|
||||
begin
|
||||
tmpref.symbol:=nil;
|
||||
tmpref.base:=hreg;
|
||||
tmpref.refaddr:=addr_no;
|
||||
list.concat(taicpu.op_ref_reg(A_LD,tmpref,hreg));
|
||||
need_got_load:=false;
|
||||
if (href.offset<simm13lo) or
|
||||
(href.offset>simm13hi) then
|
||||
begin
|
||||
tmpref.symbol:=nil;
|
||||
tmpref.offset:=href.offset;
|
||||
tmpref.refaddr := addr_high;
|
||||
hreg2:=GetIntRegister(list,OS_INT);
|
||||
a_load_const_reg(list,OS_INT,href.offset,hreg2);
|
||||
{ Only the low part is left }
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,hreg2,hreg));
|
||||
end
|
||||
else if (href.offset<>0) then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,hreg,href.offset,hreg));
|
||||
end;
|
||||
end;
|
||||
if href.base<>NR_NO then
|
||||
begin
|
||||
if href.index<>NR_NO then
|
||||
begin
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,hreg));
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
|
||||
end
|
||||
else
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,r));
|
||||
hreg:=getintregister(list,OS_INT);
|
||||
a_load_const_reg(list,OS_INT,ref.offset,hreg);
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,r,r));
|
||||
end
|
||||
else
|
||||
begin
|
||||
if hreg<>r then
|
||||
a_load_reg_reg(list,OS_ADDR,OS_ADDR,hreg,r);
|
||||
end;
|
||||
else if (ref.offset<>0) then
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,r,ref.offset,r));
|
||||
end
|
||||
else
|
||||
{ At least small offset, maybe base and maybe index }
|
||||
if href.offset<>0 then
|
||||
begin
|
||||
if href.base<>NR_NO then
|
||||
begin
|
||||
if href.index<>NR_NO then
|
||||
begin
|
||||
hreg:=GetAddressRegister(list);
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,hreg));
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
|
||||
end
|
||||
else
|
||||
list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,r));
|
||||
end
|
||||
else
|
||||
list.concat(taicpu.op_const_reg(A_MOV,href.offset,r));
|
||||
end
|
||||
else
|
||||
{ Both base and index }
|
||||
if href.index<>NR_NO then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,href.base,href.index,r))
|
||||
else
|
||||
{ Only base }
|
||||
if href.base<>NR_NO then
|
||||
a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
|
||||
else
|
||||
{ only offset, can be generated by absolute }
|
||||
a_load_const_reg(list,OS_ADDR,href.offset,r);
|
||||
if need_got then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,current_procinfo.got,r));
|
||||
if need_got_load then
|
||||
list.concat(taicpu.op_reg_reg(A_LD,r,r));
|
||||
{$endif}
|
||||
begin
|
||||
{ load symbol+offset }
|
||||
href.refaddr:=addr_high;
|
||||
list.concat(taicpu.op_ref_reg(A_SETHI,href,r));
|
||||
href.refaddr:=addr_low;
|
||||
list.concat(taicpu.op_reg_ref_reg(A_OR,r,href,r));
|
||||
{ add original base/index, if any }
|
||||
if (ref.base<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.base,r));
|
||||
if (ref.index<>NR_NO) then
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -1261,9 +1105,9 @@ implementation
|
||||
hl : tasmlabel;
|
||||
begin
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
((pi_needs_got in current_procinfo.flags) or
|
||||
(current_procinfo.procdef.proctypeoption=potype_unitfinalize)) then
|
||||
begin
|
||||
current_procinfo.got:=NR_L7;
|
||||
current_asmdata.getjumplabel(hl);
|
||||
list.concat(taicpu.op_sym(A_CALL,hl));
|
||||
{ ABI recommends the following sequence:
|
||||
@ -1279,6 +1123,8 @@ implementation
|
||||
ref.offset:=8;
|
||||
list.concat(Taicpu.Op_reg_ref_reg(A_OR,NR_L7,ref,NR_L7));
|
||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_L7,NR_O7,NR_L7));
|
||||
{ allocate NR_L7, so reg.allocator does not see it as available }
|
||||
list.concat(tai_regalloc.alloc(NR_L7,nil));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -83,91 +83,53 @@ implementation
|
||||
|
||||
|
||||
function TSPARCInstrWriter.GetReferenceString(var ref:TReference):string;
|
||||
var
|
||||
asm_comment : string;
|
||||
begin
|
||||
GetReferenceString:='';
|
||||
asm_comment:='';
|
||||
with ref do
|
||||
result:='';
|
||||
if assigned(ref.symbol) then
|
||||
result:=ref.symbol.name;
|
||||
if (ref.offset<0) then
|
||||
result:=result+tostr(ref.offset)
|
||||
else if (ref.offset>0) then
|
||||
begin
|
||||
if (base=NR_NO) and (index=NR_NO) then
|
||||
if assigned(ref.symbol) then
|
||||
result:=result+'+';
|
||||
result:=result+tostr(ref.offset);
|
||||
end
|
||||
{ asmreader appears to treat literal numbers as references }
|
||||
else if (ref.symbol=nil) and (ref.base=NR_NO) and (ref.index=NR_NO) then
|
||||
result:='0';
|
||||
|
||||
case ref.refaddr of
|
||||
addr_high:
|
||||
result:='%hi('+result+')';
|
||||
addr_low:
|
||||
result:='%lo('+result+')';
|
||||
end;
|
||||
|
||||
if assigned(ref.symbol) or (ref.offset<>0) then
|
||||
begin
|
||||
if (ref.base<>NR_NO) then
|
||||
begin
|
||||
if assigned(symbol) then
|
||||
GetReferenceString:=symbol.name;
|
||||
if offset>0 then
|
||||
GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
|
||||
else if offset<0 then
|
||||
GetReferenceString:=GetReferenceString+ToStr(offset);
|
||||
case refaddr of
|
||||
addr_high:
|
||||
GetReferenceString:='%hi('+GetReferenceString+')';
|
||||
addr_low:
|
||||
GetReferenceString:='%lo('+GetReferenceString+')';
|
||||
addr_pic:
|
||||
begin
|
||||
asm_comment:='addr_pic should use %l7 register as base or index: '+GetReferenceString;
|
||||
Comment(V_Warning,asm_comment);
|
||||
GetReferenceString:='%l7+'+GetReferenceString;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (base=NR_NO) and (index<>NR_NO) then
|
||||
begin
|
||||
base:=index;
|
||||
index:=NR_NO;
|
||||
end;
|
||||
{$ifdef extdebug}
|
||||
if assigned(symbol) and
|
||||
not(refaddr in [addr_pic,addr_low]) then
|
||||
internalerror(2003052601);
|
||||
{$endif extdebug}
|
||||
GetReferenceString:=GetReferenceString+gas_regname(base);
|
||||
if index=NR_NO then
|
||||
begin
|
||||
{ if (Offset<simm13lo) or (Offset>simm13hi) then
|
||||
internalerror(2003053008); }
|
||||
if offset>0 then
|
||||
GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
|
||||
else if offset<0 then
|
||||
GetReferenceString:=GetReferenceString+ToStr(offset);
|
||||
{
|
||||
else if (offset=0) and not(assigned(symbol)) then
|
||||
GetReferenceString:=GetReferenceString+ToStr(offset);
|
||||
}
|
||||
if assigned(symbol) then
|
||||
begin
|
||||
if refaddr=addr_low then
|
||||
GetReferenceString:='%lo('+symbol.name+')+'+GetReferenceString
|
||||
else if refaddr=addr_pic then
|
||||
begin
|
||||
if assigned(current_procinfo) and (base <> current_procinfo.got) then
|
||||
begin
|
||||
asm_comment:=' pic address should use %l7 register: '+GetReferenceString;
|
||||
Comment(V_Warning,asm_comment);
|
||||
end;
|
||||
GetReferenceString:=GetReferenceString+'+'+symbol.name;
|
||||
end
|
||||
else
|
||||
GetReferenceString:=symbol.name+'+'+GetReferenceString;
|
||||
end;
|
||||
end
|
||||
if (ref.index<>NR_NO) then
|
||||
InternalError(2013013001);
|
||||
if (result[1]='-') then
|
||||
result:=gas_regname(ref.base)+result
|
||||
else
|
||||
begin
|
||||
{$ifdef extdebug}
|
||||
if (Offset<>0) or assigned(symbol) then
|
||||
internalerror(2003052603);
|
||||
{$endif extdebug}
|
||||
GetReferenceString:=GetReferenceString+'+'+gas_regname(index);
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if asm_comment <> '' then
|
||||
result:=gas_regname(ref.base)+'+'+result;
|
||||
end
|
||||
else if (ref.index<>NR_NO) then
|
||||
InternalError(2013122501);
|
||||
end
|
||||
else
|
||||
begin
|
||||
owner.AsmWrite(target_asm.comment+' '+asm_comment);
|
||||
owner.AsmLn;
|
||||
if (ref.base<>NR_NO) then
|
||||
begin
|
||||
result:=gas_regname(ref.base);
|
||||
if (ref.index<>NR_NO) then
|
||||
result:=result+'+'+gas_regname(ref.index);
|
||||
end
|
||||
else if (ref.index<>NR_NO) then
|
||||
result:=gas_regname(ref.index);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -41,12 +41,14 @@ implementation
|
||||
|
||||
uses
|
||||
systems,globals,
|
||||
cpubase,cgbase,
|
||||
tgobj,paramgr,symconst;
|
||||
|
||||
constructor tsparcprocinfo.create(aparent:tprocinfo);
|
||||
begin
|
||||
inherited create(aparent);
|
||||
maxpushedparasize:=0;
|
||||
got:=NR_L7;
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user