+ support for handling OS_128/OS_S128 on 64 Bit CPUs as far as needed for method pointers in registers

git-svn-id: trunk@22344 -
This commit is contained in:
florian 2012-09-06 15:12:12 +00:00
parent 4514a55ec6
commit 7361e19799
11 changed files with 345 additions and 40 deletions

View File

@ -738,6 +738,9 @@ interface
varsym : tsym; varsym : tsym;
constructor create(sym : tsym;loc : tregister); constructor create(sym : tsym;loc : tregister);
constructor create64(sym : tsym;loc,lochi : tregister); constructor create64(sym : tsym;loc,lochi : tregister);
{$ifdef cpu64bitalu}
constructor create128(sym : tsym;loc,lochi : tregister);
{$endif cpu64bitalu}
constructor ppuload(t:taitype;ppufile:tcompilerppufile);override; constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
procedure ppuwrite(ppufile:tcompilerppufile);override; procedure ppuwrite(ppufile:tcompilerppufile);override;
procedure buildderefimpl;override; procedure buildderefimpl;override;
@ -917,7 +920,7 @@ implementation
end; end;
constructor tai_varloc.create64(sym: tsym; loc: tregister;lochi : tregister); constructor tai_varloc.create64(sym: tsym; loc, lochi: tregister);
begin begin
inherited Create; inherited Create;
typ:=ait_varloc; typ:=ait_varloc;
@ -927,6 +930,18 @@ implementation
end; end;
{$ifdef cpu64bitalu}
constructor tai_varloc.create128(sym: tsym; loc, lochi: tregister);
begin
inherited Create;
typ:=ait_varloc;
newlocation:=loc;
newlocationhi:=lochi;
varsym:=sym;
end;
{$endif cpu64bitalu}
constructor tai_varloc.ppuload(t: taitype; ppufile: tcompilerppufile); constructor tai_varloc.ppuload(t: taitype; ppufile: tcompilerppufile);
begin begin
inherited ppuload(t, ppufile); inherited ppuload(t, ppufile);

View File

@ -162,6 +162,7 @@ end;
procedure create_codegen; procedure create_codegen;
begin begin
cg:=tcgalpha.create; cg:=tcgalpha.create;
cg128:=tcg128.create;
end; end;
end. end.

View File

@ -61,7 +61,6 @@ unit cg64f32;
procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override; procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override; procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override; procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override; procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
@ -366,8 +365,6 @@ unit cg64f32;
end; end;
procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference); procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
var var

View File

@ -209,6 +209,9 @@ interface
{ A type to store register locations for 64 Bit values. } { A type to store register locations for 64 Bit values. }
{$ifdef cpu64bitalu} {$ifdef cpu64bitalu}
tregister64 = tregister; tregister64 = tregister;
tregister128 = record
reglo,reghi : tregister;
end;
{$else cpu64bitalu} {$else cpu64bitalu}
tregister64 = record tregister64 = record
reglo,reghi : tregister; reglo,reghi : tregister;
@ -594,6 +597,11 @@ implementation
OS_NO,OS_8,OS_16,OS_NO,OS_32,OS_NO,OS_NO,OS_NO,OS_64 OS_NO,OS_8,OS_16,OS_NO,OS_32,OS_NO,OS_NO,OS_NO,OS_64
); );
begin begin
{$ifdef cpu64bitalu}
if a=16 then
result:=OS_128
else
{$endif cpu64bitalu}
if a>8 then if a>8 then
result:=OS_NO result:=OS_NO
else else

View File

@ -458,7 +458,25 @@ unit cgobj;
function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual; function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual;
end; end;
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
{ This class implements an abstract code generator class
for 128 Bit operations, it applies currently only to 64 Bit CPUs and supports only simple operations
}
tcg128 = class
procedure a_load128_reg_reg(list : TAsmList;regsrc,regdst : tregister128);virtual;
procedure a_load128_reg_ref(list : TAsmList;reg : tregister128;const ref : treference);virtual;
procedure a_load128_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);virtual;
procedure a_load128_reg_loc(list : TAsmList;reg : tregister128;const l : tlocation);virtual;
procedure a_load128_loc_cgpara(list : TAsmList;const l : tlocation;const paraloc : TCGPara);virtual;
procedure a_load128_ref_cgpara(list: TAsmList; const r: treference;const paraloc: tcgpara);
procedure a_load128_reg_cgpara(list: TAsmList; reg: tregister128;const paraloc: tcgpara);
end;
{ Creates a tregister128 record from 2 64 Bit registers. }
function joinreg128(reglo,reghi : tregister) : tregister128;
{$else cpu64bitalu}
{# @abstract(Abstract code generator for 64 Bit operations) {# @abstract(Abstract code generator for 64 Bit operations)
This class implements an abstract code generator class This class implements an abstract code generator class
for 64 Bit operations. for 64 Bit operations.
@ -474,7 +492,6 @@ unit cgobj;
procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);virtual;abstract; procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);virtual;abstract;
procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);virtual;abstract; procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);virtual;abstract;
procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);virtual;abstract; procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);virtual;abstract;
procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);virtual;abstract; procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);virtual;abstract;
procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);virtual;abstract; procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);virtual;abstract;
@ -537,10 +554,13 @@ unit cgobj;
{$endif cpu64bitalu} {$endif cpu64bitalu}
var var
{# Main code generator class } { Main code generator class }
cg : tcg; cg : tcg;
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
{# Code generator class for all operations working with 64-Bit operands } { Code generator class for all operations working with 128-Bit operands }
cg128 : tcg128;
{$else cpu64bitalu}
{ Code generator class for all operations working with 64-Bit operands }
cg64 : tcg64; cg64 : tcg64;
{$endif cpu64bitalu} {$endif cpu64bitalu}
@ -556,7 +576,6 @@ implementation
tgobj,cutils,procinfo, tgobj,cutils,procinfo,
ncgrtti; ncgrtti;
{***************************************************************************** {*****************************************************************************
basic functionallity basic functionallity
******************************************************************************} ******************************************************************************}
@ -2508,6 +2527,204 @@ implementation
internalerror(2006082211); internalerror(2006082211);
end; end;
end; end;
{$else cpu64bitalu}
function joinreg128(reglo, reghi: tregister): tregister128;
begin
result.reglo:=reglo;
result.reghi:=reghi;
end;
procedure splitparaloc128(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
var
paraloclo,
paralochi : pcgparalocation;
begin
if not(cgpara.size in [OS_128,OS_S128]) then
internalerror(2012090604);
if not assigned(cgpara.location) then
internalerror(2012090605);
{ init lo/hi para }
cgparahi.reset;
if cgpara.size=OS_S128 then
cgparahi.size:=OS_S64
else
cgparahi.size:=OS_64;
cgparahi.intsize:=8;
cgparahi.alignment:=cgpara.alignment;
paralochi:=cgparahi.add_location;
cgparalo.reset;
cgparalo.size:=OS_64;
cgparalo.intsize:=8;
cgparalo.alignment:=cgpara.alignment;
paraloclo:=cgparalo.add_location;
{ 2 parameter fields? }
if assigned(cgpara.location^.next) then
begin
{ Order for multiple locations is always
paraloc^ -> high
paraloc^.next -> low }
if (target_info.endian=ENDIAN_BIG) then
begin
{ paraloc^ -> high
paraloc^.next -> low }
move(cgpara.location^,paralochi^,sizeof(paralochi^));
move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
end
else
begin
{ paraloc^ -> low
paraloc^.next -> high }
move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
end;
end
else
begin
{ single parameter, this can only be in memory }
if cgpara.location^.loc<>LOC_REFERENCE then
internalerror(2012090606);
move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
move(cgpara.location^,paralochi^,sizeof(paralochi^));
{ for big endian low is at +8, for little endian high }
if target_info.endian = endian_big then
begin
inc(cgparalo.location^.reference.offset,8);
cgparalo.alignment:=newalignment(cgparalo.alignment,8);
end
else
begin
inc(cgparahi.location^.reference.offset,8);
cgparahi.alignment:=newalignment(cgparahi.alignment,8);
end;
end;
{ fix size }
paraloclo^.size:=cgparalo.size;
paraloclo^.next:=nil;
paralochi^.size:=cgparahi.size;
paralochi^.next:=nil;
end;
procedure tcg128.a_load128_reg_reg(list: TAsmList; regsrc,
regdst: tregister128);
begin
cg.a_load_reg_reg(list,OS_64,OS_64,regsrc.reglo,regdst.reglo);
cg.a_load_reg_reg(list,OS_64,OS_64,regsrc.reghi,regdst.reghi);
end;
procedure tcg128.a_load128_reg_ref(list: TAsmList; reg: tregister128;
const ref: treference);
var
tmpreg: tregister;
tmpref: treference;
begin
if target_info.endian = endian_big then
begin
tmpreg:=reg.reglo;
reg.reglo:=reg.reghi;
reg.reghi:=tmpreg;
end;
cg.a_load_reg_ref(list,OS_64,OS_64,reg.reglo,ref);
tmpref := ref;
inc(tmpref.offset,8);
cg.a_load_reg_ref(list,OS_64,OS_64,reg.reghi,tmpref);
end;
procedure tcg128.a_load128_loc_ref(list: TAsmList; const l: tlocation;
const ref: treference);
begin
case l.loc of
LOC_REGISTER,LOC_CREGISTER:
a_load128_reg_ref(list,l.register128,ref);
{ not yet implemented:
LOC_CONSTANT :
a_load128_const_ref(list,l.value128,ref);
LOC_SUBSETREF, LOC_CSUBSETREF:
a_load64_subsetref_ref(list,l.sref,ref); }
else
internalerror(201209061);
end;
end;
procedure tcg128.a_load128_reg_loc(list: TAsmList; reg: tregister128;
const l: tlocation);
begin
case l.loc of
LOC_REFERENCE, LOC_CREFERENCE:
a_load128_reg_ref(list,reg,l.reference);
LOC_REGISTER,LOC_CREGISTER:
a_load128_reg_reg(list,reg,l.register128);
{ not yet implemented:
LOC_SUBSETREF, LOC_CSUBSETREF:
a_load64_reg_subsetref(list,reg,l.sref);
LOC_MMREGISTER, LOC_CMMREGISTER:
a_loadmm_intreg64_reg(list,l.size,reg,l.register); }
else
internalerror(201209062);
end;
end;
procedure tcg128.a_load128_loc_cgpara(list: TAsmList; const l: tlocation;
const paraloc: TCGPara);
begin
case l.loc of
LOC_REGISTER,
LOC_CREGISTER :
a_load128_reg_cgpara(list,l.register128,paraloc);
{not yet implemented:
LOC_CONSTANT :
a_load128_const_cgpara(list,l.value64,paraloc);
}
LOC_CREFERENCE,
LOC_REFERENCE :
a_load128_ref_cgpara(list,l.reference,paraloc);
else
internalerror(2012090603);
end;
end;
procedure tcg128.a_load128_reg_cgpara(list : TAsmList;reg : tregister128;const paraloc : tcgpara);
var
tmplochi,tmploclo: tcgpara;
begin
tmploclo.init;
tmplochi.init;
splitparaloc128(paraloc,tmploclo,tmplochi);
cg.a_load_reg_cgpara(list,OS_64,reg.reghi,tmplochi);
cg.a_load_reg_cgpara(list,OS_64,reg.reglo,tmploclo);
tmploclo.done;
tmplochi.done;
end;
procedure tcg128.a_load128_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
var
tmprefhi,tmpreflo : treference;
tmploclo,tmplochi : tcgpara;
begin
tmploclo.init;
tmplochi.init;
splitparaloc128(paraloc,tmploclo,tmplochi);
tmprefhi:=r;
tmpreflo:=r;
if target_info.endian=endian_big then
inc(tmpreflo.offset,8)
else
inc(tmprefhi.offset,8);
cg.a_load_ref_cgpara(list,OS_64,tmprefhi,tmplochi);
cg.a_load_ref_cgpara(list,OS_64,tmpreflo,tmploclo);
tmploclo.done;
tmplochi.done;
end;
{$endif cpu64bitalu} {$endif cpu64bitalu}
function asmsym2indsymflags(sym: TAsmSymbol): tindsymflags; function asmsym2indsymflags(sym: TAsmSymbol): tindsymflags;
@ -2523,7 +2740,10 @@ implementation
begin begin
cg.free; cg.free;
cg:=nil; cg:=nil;
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
cg128.free;
cg128:=nil;
{$else cpu64bitalu}
cg64.free; cg64.free;
cg64:=nil; cg64:=nil;
{$endif cpu64bitalu} {$endif cpu64bitalu}

View File

@ -127,7 +127,10 @@ unit cgutils;
registeralias : tregister; registeralias : tregister;
{$endif m68k} {$endif m68k}
); );
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
{ overlay a 128 Bit register type }
2 : (register128 : tregister128);
{$else cpu64bitalu}
{ overlay a 64 Bit register type } { overlay a 64 Bit register type }
2 : (register64 : tregister64); 2 : (register64 : tregister64);
{$endif cpu64bitalu} {$endif cpu64bitalu}

View File

@ -1200,11 +1200,15 @@ implementation
LOC_CREGISTER : LOC_CREGISTER :
begin begin
tg.gethltemp(list,size,size.size,tt_normal,r); tg.gethltemp(list,size,size.size,tt_normal,r);
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if l.size in [OS_128,OS_S128] then
cg128.a_load128_loc_ref(list,l,r)
else
{$else cpu64bitalu}
if l.size in [OS_64,OS_S64] then if l.size in [OS_64,OS_S64] then
cg64.a_load64_loc_ref(list,l,r) cg64.a_load64_loc_ref(list,l,r)
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
a_load_loc_ref(list,size,size,l,r); a_load_loc_ref(list,size,size,l,r);
location_reset_ref(l,LOC_REFERENCE,l.size,0); location_reset_ref(l,LOC_REFERENCE,l.size,0);
l.reference:=r; l.reference:=r;
@ -1329,10 +1333,8 @@ implementation
end; end;
procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
{$ifndef cpu64bitalu}
var var
tmploc: tlocation; tmploc: tlocation;
{$endif not cpu64bitalu}
begin begin
{ Handle Floating point types differently { Handle Floating point types differently
@ -1355,19 +1357,28 @@ implementation
LOC_REFERENCE, LOC_REFERENCE,
LOC_CREFERENCE : LOC_CREFERENCE :
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
{ use cg128 only if no "chained" location is used }
if (l.size in [OS_128,OS_S128]) and (cgpara.Size in [OS_128,OS_S128]) then
cg128.a_load128_loc_cgpara(list,l,cgpara)
else
{$else cpu64bitalu}
{ use cg64 only for int64, not for 8 byte records } { use cg64 only for int64, not for 8 byte records }
if (l.size in [OS_64,OS_S64]) and (cgpara.Size in [OS_64,OS_S64]) then if (l.size in [OS_64,OS_S64]) and (cgpara.Size in [OS_64,OS_S64]) then
cg64.a_load64_loc_cgpara(list,l,cgpara) cg64.a_load64_loc_cgpara(list,l,cgpara)
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
begin begin
{$ifndef cpu64bitalu}
{ Only a_load_ref_cgpara supports multiple locations, when the { Only a_load_ref_cgpara supports multiple locations, when the
value is still a const or in a register then write it value is still a const or in a register then write it
to a reference first. This situation can be triggered to a reference first. This situation can be triggered
by typecasting an int64 constant to a record of 8 bytes } by typecasting an int64 constant to a record of 8 bytes }
{$ifdef cpu64bitalu}
if l.size in [OS_128,OS_S128] then
{$else cpu64bitalu}
if l.size in [OS_64,OS_S64] then if l.size in [OS_64,OS_S64] then
{$endif cpu64bitalu}
begin begin
tmploc:=l; tmploc:=l;
location_force_mem(list,tmploc,vardef); location_force_mem(list,tmploc,vardef);
@ -1379,7 +1390,6 @@ implementation
location_freetemp(list,tmploc); location_freetemp(list,tmploc);
end end
else else
{$endif not cpu64bitalu}
a_load_loc_cgpara(list,vardef,l,cgpara); a_load_loc_cgpara(list,vardef,l,cgpara);
end; end;
end; end;

View File

@ -842,13 +842,18 @@ implementation
LOC_REGISTER, LOC_REGISTER,
LOC_CREGISTER : LOC_CREGISTER :
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if left.location.size in [OS_128,OS_S128] then
cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
right.location.register128,left.location)
else
{$else cpu64bitalu}
{ also OS_F64 in case of mmreg -> intreg } { also OS_F64 in case of mmreg -> intreg }
if left.location.size in [OS_64,OS_S64,OS_F64] then if left.location.size in [OS_64,OS_S64,OS_F64] then
cg64.a_load64_reg_loc(current_asmdata.CurrAsmList, cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
right.location.register64,left.location) right.location.register64,left.location)
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location); hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
end; end;
LOC_FPUREGISTER, LOC_FPUREGISTER,
@ -1274,11 +1279,15 @@ implementation
end; end;
else else
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if hp.left.location.size in [OS_128,OS_S128] then
cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
else
{$else cpu64bitalu}
if hp.left.location.size in [OS_64,OS_S64] then if hp.left.location.size in [OS_64,OS_S64] then
cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href) cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href); hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
end; end;
end; end;

View File

@ -1638,9 +1638,7 @@ implementation
preplaceregrec = ^treplaceregrec; preplaceregrec = ^treplaceregrec;
treplaceregrec = record treplaceregrec = record
old, new: tregister; old, new: tregister;
{$ifndef cpu64bitalu}
oldhi, newhi: tregister; oldhi, newhi: tregister;
{$endif not cpu64bitalu}
ressym: tsym; ressym: tsym;
{ moved sym } { moved sym }
sym : tsym; sym : tsym;
@ -1665,7 +1663,15 @@ implementation
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
{ it's possible a 128 bit location was shifted and/xor typecasted }
{ in a 64 bit value, so only 1 register was left in the location }
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_128,OS_S128]) then
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi = rr^.oldhi) then
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register128.reghi := rr^.newhi
else
exit;
{$else cpu64bitalu}
{ it's possible a 64 bit location was shifted and/xor typecasted } { it's possible a 64 bit location was shifted and/xor typecasted }
{ in a 32 bit value, so only 1 register was left in the location } { in a 32 bit value, so only 1 register was left in the location }
if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
@ -1673,7 +1679,7 @@ implementation
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
else else
exit; exit;
{$endif not cpu64bitalu} {$endif cpu64bitalu}
tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new; tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry); rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
result := fen_norecurse_true; result := fen_norecurse_true;
@ -1685,7 +1691,15 @@ implementation
(ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
(ttemprefnode(n).tempinfo^.location.register = rr^.old) then (ttemprefnode(n).tempinfo^.location.register = rr^.old) then
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
{ it's possible a 128 bit location was shifted and/xor typecasted }
{ in a 64 bit value, so only 1 register was left in the location }
if (ttemprefnode(n).tempinfo^.location.size in [OS_128,OS_S128]) then
if (ttemprefnode(n).tempinfo^.location.register128.reghi = rr^.oldhi) then
ttemprefnode(n).tempinfo^.location.register128.reghi := rr^.newhi
else
exit;
{$else cpu64bitalu}
{ it's possible a 64 bit location was shifted and/xor typecasted } { it's possible a 64 bit location was shifted and/xor typecasted }
{ in a 32 bit value, so only 1 register was left in the location } { in a 32 bit value, so only 1 register was left in the location }
if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
@ -1693,7 +1707,7 @@ implementation
ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
else else
exit; exit;
{$endif not cpu64bitalu} {$endif cpu64bitalu}
ttemprefnode(n).tempinfo^.location.register := rr^.new; ttemprefnode(n).tempinfo^.location.register := rr^.new;
result := fen_norecurse_true; result := fen_norecurse_true;
end; end;
@ -1725,13 +1739,19 @@ implementation
rr.old := n.location.register; rr.old := n.location.register;
rr.ressym := nil; rr.ressym := nil;
rr.sym := nil; rr.sym := nil;
{$ifndef cpu64bitalu}
rr.oldhi := NR_NO; rr.oldhi := NR_NO;
{$endif not cpu64bitalu}
case n.location.loc of case n.location.loc of
LOC_CREGISTER: LOC_CREGISTER:
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if (n.location.size in [OS_128,OS_S128]) then
begin
rr.oldhi := n.location.register128.reghi;
rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
end
else
{$else cpu64bitalu}
if (n.location.size in [OS_64,OS_S64]) then if (n.location.size in [OS_64,OS_S64]) then
begin begin
rr.oldhi := n.location.register64.reghi; rr.oldhi := n.location.register64.reghi;
@ -1739,7 +1759,7 @@ implementation
rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
end end
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size); rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
end; end;
LOC_CFPUREGISTER: LOC_CFPUREGISTER:
@ -1769,11 +1789,15 @@ implementation
case n.location.loc of case n.location.loc of
LOC_CREGISTER: LOC_CREGISTER:
begin begin
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if (n.location.size in [OS_128,OS_S128]) then
cg128.a_load128_reg_reg(list,n.location.register128,joinreg128(rr.new,rr.newhi))
else
{$else cpu64bitalu}
if (n.location.size in [OS_64,OS_S64]) then if (n.location.size in [OS_64,OS_S64]) then
cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi)) cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new); cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
end; end;
LOC_CFPUREGISTER: LOC_CFPUREGISTER:
@ -1789,7 +1813,16 @@ implementation
end; end;
{ now that we've change the loadn/temp, also change the node result location } { now that we've change the loadn/temp, also change the node result location }
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if (n.location.size in [OS_128,OS_S128]) then
begin
n.location.register128.reglo := rr.new;
n.location.register128.reghi := rr.newhi;
if assigned(rr.sym) then
list.concat(tai_varloc.create128(rr.sym,rr.new,rr.newhi));
end
else
{$else cpu64bitalu}
if (n.location.size in [OS_64,OS_S64]) then if (n.location.size in [OS_64,OS_S64]) then
begin begin
n.location.register64.reglo := rr.new; n.location.register64.reglo := rr.new;
@ -1798,7 +1831,7 @@ implementation
list.concat(tai_varloc.create64(rr.sym,rr.new,rr.newhi)); list.concat(tai_varloc.create64(rr.sym,rr.new,rr.newhi));
end end
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
begin begin
n.location.register := rr.new; n.location.register := rr.new;
if assigned(rr.sym) then if assigned(rr.sym) then
@ -1825,14 +1858,21 @@ implementation
case localloc.loc of case localloc.loc of
LOC_CREGISTER : LOC_CREGISTER :
if (pi_has_label in current_procinfo.flags) then if (pi_has_label in current_procinfo.flags) then
{$ifndef cpu64bitalu} {$ifdef cpu64bitalu}
if def_cgsize(vardef) in [OS_128,OS_S128] then
begin
cg.a_reg_sync(list,localloc.register128.reglo);
cg.a_reg_sync(list,localloc.register128.reghi);
end
else
{$else cpu64bitalu}
if def_cgsize(vardef) in [OS_64,OS_S64] then if def_cgsize(vardef) in [OS_64,OS_S64] then
begin begin
cg.a_reg_sync(list,localloc.register64.reglo); cg.a_reg_sync(list,localloc.register64.reglo);
cg.a_reg_sync(list,localloc.register64.reghi); cg.a_reg_sync(list,localloc.register64.reghi);
end end
else else
{$endif not cpu64bitalu} {$endif cpu64bitalu}
cg.a_reg_sync(list,localloc.register); cg.a_reg_sync(list,localloc.register);
LOC_CFPUREGISTER, LOC_CFPUREGISTER,
LOC_CMMREGISTER: LOC_CMMREGISTER:

View File

@ -1987,6 +1987,7 @@ end;
procedure create_codegen; procedure create_codegen;
begin begin
cg := tcgppc.create; cg := tcgppc.create;
cg128:=tcg128.create;
end; end;
end. end.

View File

@ -363,6 +363,7 @@ unit cgcpu;
procedure create_codegen; procedure create_codegen;
begin begin
cg:=tcgx86_64.create; cg:=tcgx86_64.create;
cg128:=tcg128.create;
end; end;
end. end.