mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 01:09:06 +02:00
* basic code generation for dynamic linking code for ppc64
git-svn-id: trunk@2214 -
This commit is contained in:
parent
5e9db609e3
commit
6313a9be7b
@ -61,6 +61,11 @@ interface
|
|||||||
sec_debug_frame,
|
sec_debug_frame,
|
||||||
{ ELF resources }
|
{ ELF resources }
|
||||||
sec_fpc
|
sec_fpc
|
||||||
|
{$IFDEF POWERPC64}
|
||||||
|
,
|
||||||
|
{ PPC64/Linux Table of contents section }
|
||||||
|
sec_toc
|
||||||
|
{$ENDIF POWERPC64}
|
||||||
);
|
);
|
||||||
|
|
||||||
TAsmSectionOption = (aso_alloconly,aso_executable);
|
TAsmSectionOption = (aso_alloconly,aso_executable);
|
||||||
@ -589,6 +594,9 @@ implementation
|
|||||||
'eh_frame',
|
'eh_frame',
|
||||||
'debug_frame',
|
'debug_frame',
|
||||||
'fpc'
|
'fpc'
|
||||||
|
{$IFDEF POWERPC64}
|
||||||
|
, 'toc'
|
||||||
|
{$ENDIF POWERPC64}
|
||||||
);
|
);
|
||||||
begin
|
begin
|
||||||
if aname<>'' then
|
if aname<>'' then
|
||||||
|
@ -301,7 +301,7 @@ interface
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
tasmdirective=(asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer,
|
tasmdirective=(asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer,
|
||||||
asd_extern,asd_nasm_import);
|
asd_extern,asd_nasm_import{$IFDEF POWERPC64}, asd_toc_entry{$ENDIF POWERPC64});
|
||||||
|
|
||||||
tai_directive = class(tailineinfo)
|
tai_directive = class(tailineinfo)
|
||||||
name : pstring;
|
name : pstring;
|
||||||
@ -633,7 +633,7 @@ interface
|
|||||||
stabtypestr : array[tstabtype] of string[5]=('stabs','stabn','stabd');
|
stabtypestr : array[tstabtype] of string[5]=('stabs','stabn','stabd');
|
||||||
directivestr : array[tasmdirective] of string[24]=(
|
directivestr : array[tasmdirective] of string[24]=(
|
||||||
'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer',
|
'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer',
|
||||||
'extern','nasm_import'
|
'extern','nasm_import'{$IFDEF POWERPC64}, 'tc'{$ENDIF POWERPC64}
|
||||||
);
|
);
|
||||||
|
|
||||||
var
|
var
|
||||||
|
@ -214,6 +214,9 @@ implementation
|
|||||||
'.eh_frame',
|
'.eh_frame',
|
||||||
'.debug_frame',
|
'.debug_frame',
|
||||||
'fpc.resptrs'
|
'fpc.resptrs'
|
||||||
|
{$IFDEF POWERPC64}
|
||||||
|
, '.toc'
|
||||||
|
{$ENDIF}
|
||||||
);
|
);
|
||||||
secnames_pic : array[tasmsectiontype] of string[12] = ('',
|
secnames_pic : array[tasmsectiontype] of string[12] = ('',
|
||||||
'.text','.data.rel','.data.rel','.bss','.threadvar',
|
'.text','.data.rel','.data.rel','.bss','.threadvar',
|
||||||
@ -225,6 +228,9 @@ implementation
|
|||||||
'.eh_frame',
|
'.eh_frame',
|
||||||
'.debug_frame',
|
'.debug_frame',
|
||||||
'fpc.resptrs'
|
'fpc.resptrs'
|
||||||
|
{$IFDEF POWERPC64}
|
||||||
|
, '.toc'
|
||||||
|
{$ENDIF}
|
||||||
);
|
);
|
||||||
var
|
var
|
||||||
secname : string;
|
secname : string;
|
||||||
@ -806,7 +812,7 @@ implementation
|
|||||||
AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
|
AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
|
||||||
AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
|
AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
|
||||||
AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
|
AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
|
||||||
{ the dotted name is the name of the actual function }
|
{ the dotted name is the name of the actual function entry }
|
||||||
AsmWrite('.');
|
AsmWrite('.');
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -848,15 +854,11 @@ implementation
|
|||||||
AsmWriteLn(s+':');
|
AsmWriteLn(s+':');
|
||||||
AsmWrite(#9'.size'#9);
|
AsmWrite(#9'.size'#9);
|
||||||
if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
|
if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
|
||||||
begin
|
|
||||||
AsmWrite('.');
|
AsmWrite('.');
|
||||||
end;
|
|
||||||
AsmWrite(tai_symbol_end(hp).sym.name);
|
AsmWrite(tai_symbol_end(hp).sym.name);
|
||||||
AsmWrite(', '+s+' - ');
|
AsmWrite(', '+s+' - ');
|
||||||
if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
|
if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
|
||||||
begin
|
|
||||||
AsmWrite('.');
|
AsmWrite('.');
|
||||||
end;
|
|
||||||
AsmWriteLn(tai_symbol_end(hp).sym.name);
|
AsmWriteLn(tai_symbol_end(hp).sym.name);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -56,7 +56,7 @@ unit parabase;
|
|||||||
E.g. the value $5544433 is passed in bits 40-63 of the register (others are zero),
|
E.g. the value $5544433 is passed in bits 40-63 of the register (others are zero),
|
||||||
but they should actually be stored in the first bits of the stack location reserved
|
but they should actually be stored in the first bits of the stack location reserved
|
||||||
for this value. So they have to be shifted left by this amount of bits before. }
|
for this value. So they have to be shifted left by this amount of bits before. }
|
||||||
{$IFDEF CPUPOWERPC64}shiftval : byte;{$ENDIF CPUPOWERPC64}
|
{$IFDEF POWERPC64}shiftval : byte;{$ENDIF POWERPC64}
|
||||||
register : tregister);
|
register : tregister);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ begin
|
|||||||
if (target_info.system <> system_powerpc_darwin) then
|
if (target_info.system <> system_powerpc_darwin) then
|
||||||
s := s + refaddr2str[refaddr];
|
s := s + refaddr2str[refaddr];
|
||||||
end;
|
end;
|
||||||
|
if (refaddr = addr_pic) then s := s + ')';
|
||||||
|
|
||||||
if (index = NR_NO) and (base <> NR_NO) then
|
if (index = NR_NO) and (base <> NR_NO) then
|
||||||
begin
|
begin
|
||||||
|
@ -174,6 +174,14 @@ uses
|
|||||||
symconst, symsym, fmodule,
|
symconst, symsym, fmodule,
|
||||||
rgobj, tgobj, cpupi, procinfo, paramgr;
|
rgobj, tgobj, cpupi, procinfo, paramgr;
|
||||||
|
|
||||||
|
function ref2string(const ref : treference) : string;
|
||||||
|
begin
|
||||||
|
result := 'base : ' + inttostr(ord(ref.base)) + ' index : ' + inttostr(ord(ref.index)) + ' refaddr : ' + inttostr(ord(ref.refaddr)) + ' offset : ' + inttostr(ref.offset) + ' symbol : ';
|
||||||
|
if (assigned(ref.symbol)) then
|
||||||
|
result := result + ref.symbol.name;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ helper function which calculate "magic" values for replacement of unsigned
|
{ helper function which calculate "magic" values for replacement of unsigned
|
||||||
division by constant operation by multiplication. See the PowerPC compiler
|
division by constant operation by multiplication. See the PowerPC compiler
|
||||||
developer manual for more information }
|
developer manual for more information }
|
||||||
@ -694,6 +702,10 @@ var
|
|||||||
ref2: treference;
|
ref2: treference;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('a_load_ref_reg ' + ref2string(ref))));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
|
|
||||||
if not (fromsize in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then
|
if not (fromsize in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then
|
||||||
internalerror(2002090902);
|
internalerror(2002090902);
|
||||||
ref2 := ref;
|
ref2 := ref;
|
||||||
@ -874,7 +886,7 @@ var
|
|||||||
internalerror(2005061701);
|
internalerror(2005061701);
|
||||||
end else if (a = 1) then begin
|
end else if (a = 1) then begin
|
||||||
cg.a_load_reg_reg(exprasmlist, OS_INT, OS_INT, src, dst);
|
cg.a_load_reg_reg(exprasmlist, OS_INT, OS_INT, src, dst);
|
||||||
end else if (a = -1) then begin
|
end else if (a = -1) and (signed) then begin
|
||||||
{ note: only in the signed case possible..., may overflow }
|
{ note: only in the signed case possible..., may overflow }
|
||||||
exprasmlist.concat(taicpu.op_reg_reg(negops[cs_check_overflow in aktlocalswitches], dst, src));
|
exprasmlist.concat(taicpu.op_reg_reg(negops[cs_check_overflow in aktlocalswitches], dst, src));
|
||||||
end else if (ispowerof2(a, power, isNegPower)) then begin
|
end else if (ispowerof2(a, power, isNegPower)) then begin
|
||||||
@ -1498,7 +1510,7 @@ begin
|
|||||||
ref2 := ref;
|
ref2 := ref;
|
||||||
fixref(list, ref2, OS_64);
|
fixref(list, ref2, OS_64);
|
||||||
{ load a symbol }
|
{ load a symbol }
|
||||||
if assigned(ref2.symbol) or (hasLargeOffset(ref2)) then begin
|
if (assigned(ref2.symbol) or (hasLargeOffset(ref2))) then begin
|
||||||
{ add the symbol's value to the base of the reference, and if the }
|
{ add the symbol's value to the base of the reference, and if the }
|
||||||
{ reference doesn't have a base, create one }
|
{ reference doesn't have a base, create one }
|
||||||
reference_reset(tmpref);
|
reference_reset(tmpref);
|
||||||
@ -1523,6 +1535,10 @@ begin
|
|||||||
oris rX,rX,SYM@h
|
oris rX,rX,SYM@h
|
||||||
ori rX,rX,SYM@l
|
ori rX,rX,SYM@l
|
||||||
*)
|
*)
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('loadaddr_ref_reg ')));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
|
if (assigned(tmpref.symbol)) then begin
|
||||||
tmpref.refaddr := addr_highest;
|
tmpref.refaddr := addr_highest;
|
||||||
list.concat(taicpu.op_reg_ref(A_LIS, tempreg, tmpref));
|
list.concat(taicpu.op_reg_ref(A_LIS, tempreg, tmpref));
|
||||||
tmpref.refaddr := addr_higher;
|
tmpref.refaddr := addr_higher;
|
||||||
@ -1532,27 +1548,30 @@ begin
|
|||||||
list.concat(taicpu.op_reg_reg_ref(A_ORIS, tempreg, tempreg, tmpref));
|
list.concat(taicpu.op_reg_reg_ref(A_ORIS, tempreg, tempreg, tmpref));
|
||||||
tmpref.refaddr := addr_low;
|
tmpref.refaddr := addr_low;
|
||||||
list.concat(taicpu.op_reg_reg_ref(A_ORI, tempreg, tempreg, tmpref));
|
list.concat(taicpu.op_reg_reg_ref(A_ORI, tempreg, tempreg, tmpref));
|
||||||
|
end else
|
||||||
|
a_load_const_reg(list, OS_ADDR, tmpref.offset, tempreg);
|
||||||
|
|
||||||
{ if there's already a base register, add the temp register contents to
|
{ if there's already a base register, add the temp register contents to
|
||||||
the base register }
|
the base register }
|
||||||
if (ref2.base <> NR_NO) then begin
|
if (ref2.base <> NR_NO) then begin
|
||||||
list.concat(taicpu.op_reg_reg_reg(A_ADD, r, tempreg, ref2.base));
|
list.concat(taicpu.op_reg_reg_reg(A_ADD, r, tempreg, ref2.base));
|
||||||
end;
|
end;
|
||||||
end else if ref2.offset <> 0 then begin
|
end else if (ref2.offset <> 0) then begin
|
||||||
{ no symbol, but offset <> 0 }
|
{ no symbol, but offset <> 0 }
|
||||||
if ref2.base <> NR_NO then begin
|
if (ref2.base <> NR_NO) then begin
|
||||||
a_op_const_reg_reg(list, OP_ADD, OS_64, ref2.offset, ref2.base, r)
|
a_op_const_reg_reg(list, OP_ADD, OS_64, ref2.offset, ref2.base, r)
|
||||||
{ FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never
|
{ FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never
|
||||||
occurs, so now only ref.offset has to be loaded }
|
occurs, so now only ref.offset has to be loaded }
|
||||||
end else begin
|
end else begin
|
||||||
a_load_const_reg(list, OS_64, ref2.offset, r)
|
a_load_const_reg(list, OS_64, ref2.offset, r);
|
||||||
end;
|
end;
|
||||||
end else if ref.index <> NR_NO then
|
end else if (ref2.index <> NR_NO) then begin
|
||||||
list.concat(taicpu.op_reg_reg_reg(A_ADD, r, ref2.base, ref2.index))
|
list.concat(taicpu.op_reg_reg_reg(A_ADD, r, ref2.base, ref2.index))
|
||||||
else if (ref2.base <> NR_NO) and
|
end else if (ref2.base <> NR_NO) and
|
||||||
(r <> ref2.base) then
|
(r <> ref2.base) then begin
|
||||||
a_load_reg_reg(list, OS_ADDR, OS_ADDR, ref2.base, r)
|
a_load_reg_reg(list, OS_ADDR, OS_ADDR, ref2.base, r)
|
||||||
else begin
|
//list.concat(taicpu.op_reg_reg(A_MR, ref2.base, r));
|
||||||
|
end else begin
|
||||||
list.concat(taicpu.op_reg_const(A_LI, r, 0));
|
list.concat(taicpu.op_reg_const(A_LI, r, 0));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1577,7 +1596,7 @@ begin
|
|||||||
{$IFDEF extdebug}
|
{$IFDEF extdebug}
|
||||||
if len > high(aint) then
|
if len > high(aint) then
|
||||||
internalerror(2002072704);
|
internalerror(2002072704);
|
||||||
list.concat(tai_comment.create(strpnew('g_concatcopy')));
|
list.concat(tai_comment.create(strpnew('g_concatcopy1 ' + inttostr(len) + ' bytes left ')));
|
||||||
{$ENDIF extdebug}
|
{$ENDIF extdebug}
|
||||||
{ make sure short loads are handled as optimally as possible;
|
{ make sure short loads are handled as optimally as possible;
|
||||||
note that the data here never overlaps, so we can do a forward
|
note that the data here never overlaps, so we can do a forward
|
||||||
@ -1587,6 +1606,7 @@ begin
|
|||||||
|
|
||||||
if (len <= maxmoveunit) then begin
|
if (len <= maxmoveunit) then begin
|
||||||
src := source; dst := dest;
|
src := source; dst := dest;
|
||||||
|
list.concat(tai_comment.create(strpnew('g_concatcopy3 ' + inttostr(src.offset) + ' ' + inttostr(dst.offset))));
|
||||||
while (len <> 0) do begin
|
while (len <> 0) do begin
|
||||||
if (len = 8) then begin
|
if (len = 8) then begin
|
||||||
a_load_ref_ref(list, OS_64, OS_64, src, dst);
|
a_load_ref_ref(list, OS_64, OS_64, src, dst);
|
||||||
@ -1607,6 +1627,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
{$IFDEF extdebug}
|
||||||
|
list.concat(tai_comment.create(strpnew('g_concatcopy2 ' + inttostr(len) + ' bytes left ')));
|
||||||
|
{$ENDIF extdebug}
|
||||||
|
|
||||||
|
|
||||||
count := len div maxmoveunit;
|
count := len div maxmoveunit;
|
||||||
|
|
||||||
@ -1830,33 +1854,51 @@ var
|
|||||||
begin
|
begin
|
||||||
l:=objectlibrary.getasmsymbol(symbol+'$got');
|
l:=objectlibrary.getasmsymbol(symbol+'$got');
|
||||||
if not(assigned(l)) then begin
|
if not(assigned(l)) then begin
|
||||||
l:=objectlibrary.newasmsymbol(symbol+'$got',AB_COMMON,AT_DATA);
|
l:=objectlibrary.newasmsymbol(symbol+'$got',AB_LOCAL, AT_LABEL);
|
||||||
|
asmlist[al_picdata].concat(tai_section.create(sec_toc, '.toc', 8));
|
||||||
asmlist[al_picdata].concat(tai_symbol.create(l,0));
|
asmlist[al_picdata].concat(tai_symbol.create(l,0));
|
||||||
asmlist[al_picdata].concat(tai_const.create_indirect_sym(objectlibrary.newasmsymbol(symbol,AB_EXTERNAL,AT_DATA)));
|
asmlist[al_picdata].concat(tai_directive.create(asd_toc_entry, symbol + '[TC], ' + symbol));
|
||||||
asmlist[al_picdata].concat(tai_const.create_32bit(0));
|
|
||||||
end;
|
end;
|
||||||
reference_reset_symbol(ref,l,0);
|
reference_reset_symbol(ref,l,0);
|
||||||
ref.base := NR_R2;
|
ref.base := NR_R2;
|
||||||
result := cg.rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
ref.refaddr := addr_pic;
|
||||||
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
|
|
||||||
|
result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol)));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
|
// cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
|
||||||
|
list.concat(taicpu.op_reg_ref(A_LD, result, ref));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
|
function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
|
||||||
var
|
var
|
||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
name : string;
|
name : string;
|
||||||
begin
|
begin
|
||||||
result := false;
|
result := false;
|
||||||
if (cs_create_pic in aktmoduleswitches) and (assigned(ref.symbol)) and (ref.symbol.defbind = AB_EXTERNAL) then begin
|
{ Avoids recursion. }
|
||||||
if (length(name) > 100) then internalerror(123456);
|
if (ref.refaddr = addr_pic) then exit;
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
|
|
||||||
|
{ if we have to create PIC, add the symbol to the TOC/GOT }
|
||||||
|
if (cs_create_pic in aktmoduleswitches) and (assigned(ref.symbol)) then begin
|
||||||
tmpreg := load_got_symbol(list, ref.symbol.name);
|
tmpreg := load_got_symbol(list, ref.symbol.name);
|
||||||
if (ref.base = NR_NO) then
|
if (ref.base = NR_NO) then
|
||||||
ref.base := tmpreg
|
ref.base := tmpreg
|
||||||
else if (ref.index = NR_NO) then
|
else if (ref.index = NR_NO) then
|
||||||
ref.index := tmpreg
|
ref.index := tmpreg
|
||||||
else
|
else begin
|
||||||
list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.base,tmpreg));
|
a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg);
|
||||||
|
ref.base := tmpreg;
|
||||||
|
end;
|
||||||
ref.symbol := nil;
|
ref.symbol := nil;
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref))));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (ref.base = NR_NO) then begin
|
if (ref.base = NR_NO) then begin
|
||||||
@ -1868,9 +1910,14 @@ begin
|
|||||||
result := true;
|
result := true;
|
||||||
tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
||||||
a_op_reg_reg_reg(list, OP_ADD, size, ref.base, ref.index, tmpreg);
|
a_op_reg_reg_reg(list, OP_ADD, size, ref.base, ref.index, tmpreg);
|
||||||
ref.index := NR_NO;
|
|
||||||
ref.base := tmpreg;
|
ref.base := tmpreg;
|
||||||
|
ref.index := NR_NO;
|
||||||
end;
|
end;
|
||||||
|
if (ref.index <> NR_NO) and (assigned(ref.symbol) or (ref.offset <> 0)) then
|
||||||
|
internalerror(2006010506);
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref))));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcgppc.a_load_store(list: taasmoutput; op: tasmop; reg: tregister;
|
procedure tcgppc.a_load_store(list: taasmoutput; op: tasmop; reg: tregister;
|
||||||
@ -1885,6 +1932,18 @@ begin
|
|||||||
if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then
|
if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then
|
||||||
internalerror(200310131);
|
internalerror(200310131);
|
||||||
|
|
||||||
|
{ if this is a PIC'ed address, handle it and exit }
|
||||||
|
if (ref.refaddr = addr_pic) then begin
|
||||||
|
if (ref.offset <> 0) then
|
||||||
|
internalerror(2006010501);
|
||||||
|
if (ref.index <> NR_NO) then
|
||||||
|
internalerror(2006010502);
|
||||||
|
if (not assigned(ref.symbol)) then
|
||||||
|
internalerror(200601050);
|
||||||
|
list.concat(taicpu.op_reg_ref(op, reg, ref));
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
{ for some instructions we need to check that the offset is divisible by at
|
{ for some instructions we need to check that the offset is divisible by at
|
||||||
least four. If not, add the bytes which are "off" to the base register and
|
least four. If not, add the bytes which are "off" to the base register and
|
||||||
adjust the offset accordingly }
|
adjust the offset accordingly }
|
||||||
@ -1903,10 +1962,12 @@ begin
|
|||||||
ref.offset := (ref.offset div 4) * 4;
|
ref.offset := (ref.offset div 4) * 4;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{$IFDEF EXTDEBUG}
|
||||||
|
list.concat(tai_comment.create(strpnew('a_load_store1 ' + BoolToStr(ref.refaddr = addr_pic))));
|
||||||
|
{$ENDIF EXTDEBUG}
|
||||||
{ if we have to load/store from a symbol or large addresses, use a temporary register
|
{ if we have to load/store from a symbol or large addresses, use a temporary register
|
||||||
containing the address }
|
containing the address }
|
||||||
if assigned(ref.symbol) or (hasLargeOffset(ref)) then begin
|
if (assigned(ref.symbol) or (hasLargeOffset(ref))) then begin
|
||||||
tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
||||||
|
|
||||||
if (hasLargeOffset(ref) and (ref.base = NR_NO)) then begin
|
if (hasLargeOffset(ref) and (ref.base = NR_NO)) then begin
|
||||||
@ -1936,6 +1997,7 @@ begin
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmpreg2 := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
tmpreg2 := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
|
||||||
|
if (assigned(tmpref.symbol)) then begin
|
||||||
tmpref.refaddr := addr_highest;
|
tmpref.refaddr := addr_highest;
|
||||||
list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
|
list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
|
||||||
tmpref.refaddr := addr_higher;
|
tmpref.refaddr := addr_higher;
|
||||||
@ -1947,6 +2009,8 @@ begin
|
|||||||
list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg2, tmpreg2, tmpref));
|
list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg2, tmpreg2, tmpref));
|
||||||
|
|
||||||
list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, tmpreg2, tmpreg, 32, 0));
|
list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, tmpreg2, tmpreg, 32, 0));
|
||||||
|
end else
|
||||||
|
a_load_const_reg(list, OS_ADDR, tmpref.offset, tmpreg2);
|
||||||
|
|
||||||
reference_reset(tmpref);
|
reference_reset(tmpref);
|
||||||
tmpref.base := ref.base;
|
tmpref.base := ref.base;
|
||||||
|
Loading…
Reference in New Issue
Block a user