mirror of https://github.com/red-prig/fpPS4.git
1121 lines
22 KiB
Plaintext
1121 lines
22 KiB
Plaintext
unit srReg;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
//TypInfo,
|
|
ginodes,
|
|
srNode,
|
|
srRefId,
|
|
srType,
|
|
srConst;
|
|
|
|
const
|
|
RegCount =366;
|
|
LaneCount=64;
|
|
|
|
type
|
|
PPsrRegSlot=^PsrRegSlot;
|
|
PsrRegSlot=^TsrRegSlot;
|
|
|
|
TsrRegNode=class;
|
|
|
|
PPsrRegNode=^TsrRegNode;
|
|
|
|
TsrRegNode=class(TsrNode)
|
|
private
|
|
ID:TsrRefId; //post id
|
|
F:bitpacked record
|
|
dtype:TsrDataType;
|
|
dweak:Boolean;
|
|
end;
|
|
FSlot:PsrRegSlot;
|
|
FWriter:TsrNode; //ntReg,ntConst,ntOp,ntVolatile
|
|
FCustomLine:TsrNode; //PspirvOp;
|
|
function GetDtype:TsrDataType;
|
|
Procedure SetDtype(t:TsrDataType);
|
|
function GetWeak:Boolean;
|
|
Procedure SetWeak(t:Boolean);
|
|
Procedure SetWriter(t:TsrNode);
|
|
Function GetWriter:TsrNode;
|
|
public
|
|
function pLine:TsrNode;
|
|
property CustomLine:TsrNode read FCustomLine write FCustomLine;
|
|
//
|
|
Function _GetPline :TsrNode; override;
|
|
Procedure _SetWriter (w,line:TsrNode); override;
|
|
Procedure _ResetWriter (w:TsrNode); override;
|
|
function _Down :TsrNode; override;
|
|
Procedure _PrepType (node:PPrepTypeNode); override;
|
|
function _GetPrintName:RawByteString; override;
|
|
function _GetRef :Pointer; override;
|
|
//
|
|
property pSlot :PsrRegSlot read FSlot write FSlot;
|
|
property dtype :TsrDataType read GetDtype write SetDtype;
|
|
property dweak :Boolean read GetWeak write SetWeak;
|
|
property pWriter:TsrNode read GetWriter write SetWriter;
|
|
function GetName:RawByteString;
|
|
function AsConst:TsrConst;
|
|
function AsReg:TsrRegNode;
|
|
function is_const:Boolean;
|
|
function is_bool:Boolean;
|
|
function is_bool_or_const_bool:Boolean;
|
|
function is_unknow:Boolean;
|
|
function GetPrintName:RawByteString;
|
|
end;
|
|
|
|
ntReg=TsrRegNode;
|
|
|
|
TsrRegPair=class(TsrNode)
|
|
private
|
|
FWriter:TsrNode;
|
|
FDst0:TsrNode;
|
|
FDst1:TsrNode;
|
|
Procedure SetWriter(t:TsrNode);
|
|
Procedure SetDst0(r:TsrNode);
|
|
Procedure SetDst1(r:TsrNode);
|
|
public
|
|
//
|
|
function _Down:TsrNode; override;
|
|
Procedure _SetWriter (w,line:TsrNode); override;
|
|
Procedure _ResetWriter(w:TsrNode); override;
|
|
Function _GetPline:TsrNode; override;
|
|
//
|
|
property pLine:TsrNode read FWriter;
|
|
property pWriter:TsrNode read FWriter write SetWriter;
|
|
property pDst0:TsrNode read FDst0 write SetDst0;
|
|
property pDst1:TsrNode read FDst1 write SetDst1;
|
|
end;
|
|
|
|
ntRegPair=TsrRegPair;
|
|
|
|
TsrRegSampledImage=class(TsrRegNode)
|
|
Tgrp :TsrNode;
|
|
Sgrp :TsrNode;
|
|
etype:TsrDataType;
|
|
info :TsrTypeImageInfo;
|
|
end;
|
|
|
|
TsrVectorArray=class(TsrRegNode)
|
|
FLanes:array[0..LaneCount-1] of TsrRegNode; //[0..63]
|
|
end;
|
|
|
|
TString7=string[7];
|
|
|
|
TSlotCategory=(cNone,cUnattach,cScalar,cScc,cVector,cVectorArray,cLane);
|
|
|
|
PsrBitKey=^TsrBitKey;
|
|
TsrBitKey=bitpacked record
|
|
id :0..RegCount-1;
|
|
Category:TSlotCategory;
|
|
LaneId :0..LaneCount-1;
|
|
align :Byte;
|
|
end;
|
|
|
|
TsrRegSlot=object
|
|
private
|
|
FEmit :TCustomEmit;
|
|
FCurrent:TsrRegNode;
|
|
pLanes :PsrRegSlot; //[0..63]
|
|
FName :TString7;
|
|
FBits :TsrBitKey;
|
|
procedure set_current(c:TsrRegNode);
|
|
public
|
|
FPrivate:TsrNode;
|
|
property Emit :TCustomEmit read FEmit;
|
|
property current :TsrRegNode read FCurrent write set_current;
|
|
property Name :TString7 read FName;
|
|
property Category:TSlotCategory read FBits.Category;
|
|
property id :SmallInt read FBits.id;
|
|
property LaneId :ShortInt read FBits.LaneId;
|
|
function Lanes(i:Byte):PsrRegSlot;
|
|
Procedure Init(e:TCustomEmit;const n:TString7;c:TSlotCategory;i:Word=0;l:Byte=0);
|
|
function ConvertToVectorArray :Boolean;
|
|
function ConvertToVectorGeneral:Boolean;
|
|
function isBoolOnly:Boolean;
|
|
function isScalar:Boolean;
|
|
function iUnattach:Boolean;
|
|
function _New(rtype:TsrDataType;pLine:TsrRegNode):TsrRegNode;
|
|
function New(rtype:TsrDataType;pLine:TsrRegNode=nil):TsrRegNode;
|
|
end;
|
|
|
|
PsrRegsSnapshot=^TsrRegsSnapshot;
|
|
TsrRegsSnapshot=record
|
|
//366
|
|
case Byte of
|
|
0:(REGS:array[0..365] of TsrRegNode;);
|
|
1:(
|
|
SGRP:array[0..103] of TsrRegNode; //104
|
|
VCC :array[0..1] of TsrRegNode; //2
|
|
M0 :TsrRegNode; //1
|
|
EXEC:array[0..1] of TsrRegNode; //2
|
|
SCC :TsrRegNode; //1
|
|
VGRP:array[0..255] of TsrRegNode; //256
|
|
);
|
|
end;
|
|
|
|
TsrVolatileNode=class
|
|
pPrev,pNext:TsrVolatileNode;
|
|
//
|
|
V:TsrNode;
|
|
N:TsrNode;
|
|
end;
|
|
TsrVolatileNodeList=specialize TNodeListClass<TsrVolatileNode>;
|
|
|
|
TsrVolatileContext=object
|
|
Emit:TCustomEmit;
|
|
//
|
|
befor:TsrNode;
|
|
after:TsrNode;
|
|
block:TsrNode;
|
|
//
|
|
FList:TsrVolatileNodeList;
|
|
//
|
|
Procedure AddVolatile(V,N:TsrNode);
|
|
end;
|
|
|
|
TForEachSlot=procedure(pSlot:PsrRegSlot) of object;
|
|
TForEachSnp1=procedure(pSlot:PsrRegSlot;var orig:TsrRegNode) of object;
|
|
TForEachSnp3=procedure(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,next:TsrRegNode) of object;
|
|
|
|
PsrRegsStory=^TsrRegsStory;
|
|
TsrRegsStory=object
|
|
//366
|
|
SGRP:array[0..103] of TsrRegSlot; //104
|
|
VCC :array[0..1] of TsrRegSlot; //2
|
|
M0 :TsrRegSlot; //1
|
|
EXEC:array[0..1] of TsrRegSlot; //2
|
|
SCC :TsrRegSlot; //1
|
|
VGRP:array[0..255] of TsrRegSlot; //256
|
|
FUnattach:TsrRegSlot;
|
|
//
|
|
Procedure Init(Emit:TCustomEmit);
|
|
Function SLOT:PsrRegSlot; inline;
|
|
//
|
|
function get_sdst7(SDST:Byte):PsrRegSlot;
|
|
function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
|
function get_sdst8(SDST:Word):PsrRegSlot;
|
|
function get_ssrc8(SSRC:Byte):PsrRegSlot;
|
|
function get_ssrc9(SSRC:Word):PsrRegSlot;
|
|
function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
|
function get_vsrc8(VSRC:Byte):PsrRegSlot;
|
|
function get_vdst8(VDST:Byte):PsrRegSlot;
|
|
function get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean;
|
|
function get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean;
|
|
//
|
|
function get_snapshot:TsrRegsSnapshot;
|
|
procedure ForEachSlot(cb:TForEachSlot);
|
|
procedure ForEachSnap(cb:TForEachSnp1;orig:PsrRegsSnapshot);
|
|
procedure ForEachSnap(cb:TForEachSnp3;var ctx:TsrVolatileContext;orig,prev,next:PsrRegsSnapshot);
|
|
end;
|
|
|
|
function RegDown(node:TsrRegNode):TsrRegNode;
|
|
function RegDownSlot(node:TsrRegNode):TsrRegNode;
|
|
function CompareReg(r1,r2:TsrRegNode):Boolean;
|
|
|
|
operator := (i:TsrNode):TsrRegNode; inline;
|
|
|
|
implementation
|
|
|
|
operator := (i:TsrNode):TsrRegNode; inline;
|
|
begin
|
|
Result:=TsrRegNode(Pointer(i)); //typecast hack
|
|
end;
|
|
|
|
//
|
|
|
|
Procedure TsrVolatileContext.AddVolatile(V,N:TsrNode);
|
|
var
|
|
node:TsrVolatileNode;
|
|
begin
|
|
node:=Emit.specialize New<TsrVolatileNode>;
|
|
node.V:=V;
|
|
node.N:=N;
|
|
//
|
|
FList.Push_tail(node);
|
|
end;
|
|
|
|
//
|
|
|
|
Function TsrRegNode._GetPline:TsrNode;
|
|
var
|
|
tmp:TsrRegNode;
|
|
begin
|
|
Result:=nil;
|
|
//
|
|
if (FCustomLine<>nil) then
|
|
begin
|
|
Exit(FCustomLine);
|
|
end;
|
|
//
|
|
tmp:=FWriter;
|
|
while (tmp<>nil) do
|
|
begin
|
|
if tmp.IsType(ntReg) then
|
|
begin
|
|
if (tmp.FCustomLine<>nil) then
|
|
begin
|
|
Exit(tmp.FCustomLine);
|
|
end;
|
|
end else
|
|
begin
|
|
Exit(tmp._GetPline);
|
|
end;
|
|
tmp:=tmp._Down;
|
|
end;
|
|
end;
|
|
|
|
function TsrRegNode.pLine:TsrNode;
|
|
begin
|
|
if (Self=nil) then Exit(nil);
|
|
Result:=_GetPline;
|
|
end;
|
|
|
|
Procedure TsrRegNode._SetWriter(w,line:TsrNode);
|
|
begin
|
|
SetWriter(w);
|
|
end;
|
|
|
|
Procedure TsrRegNode._ResetWriter(w:TsrNode);
|
|
begin
|
|
if (FWriter=w) then
|
|
begin
|
|
SetWriter(nil);
|
|
end;
|
|
end;
|
|
|
|
function TsrRegNode._Down:TsrNode;
|
|
begin
|
|
Result:=FWriter;
|
|
end;
|
|
|
|
Procedure TsrRegNode._PrepType(node:PPrepTypeNode);
|
|
var
|
|
new:TsrDataType;
|
|
pConstList:PsrConstList;
|
|
begin
|
|
new:=TsrDataType(node^.rtype);
|
|
if (new=dtUnknow) then
|
|
begin
|
|
node^.dnode:=nil;
|
|
Exit;
|
|
end;
|
|
|
|
if FSlot^.isBoolOnly then
|
|
begin
|
|
//next
|
|
node^.rtype:=ord(dtBool);
|
|
node^.dnode:=pWriter;
|
|
Exit;
|
|
end else
|
|
if is_unprep_type(dtype,new,dweak) then
|
|
begin
|
|
dtype:=new;
|
|
dweak:=True;
|
|
if is_const then
|
|
begin
|
|
pConstList:=FSlot^.FEmit.GetConstList;
|
|
pWriter:=pConstList^.Bitcast(new,pWriter.specialize AsType<ntConst>);
|
|
end else
|
|
begin
|
|
//next
|
|
node^.dnode:=pWriter;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
node^.dnode:=nil;
|
|
end;
|
|
|
|
function TsrRegNode._GetPrintName:RawByteString;
|
|
begin
|
|
Result:=GetPrintName;
|
|
end;
|
|
|
|
function TsrRegNode._GetRef:Pointer;
|
|
begin
|
|
if is_const then
|
|
begin
|
|
Result:=AsConst.GetRef;
|
|
end else
|
|
begin
|
|
Result:=@ID;
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
function TsrRegPair._Down:TsrNode;
|
|
begin
|
|
Result:=FWriter;
|
|
end;
|
|
|
|
Procedure TsrRegPair._SetWriter(w,line:TsrNode);
|
|
begin
|
|
SetWriter(w);
|
|
end;
|
|
|
|
Procedure TsrRegPair._ResetWriter(w:TsrNode);
|
|
begin
|
|
if (FWriter=w) then
|
|
begin
|
|
SetWriter(nil);
|
|
end;
|
|
end;
|
|
|
|
Function TsrRegPair._GetPline:TsrNode;
|
|
begin
|
|
Result:=FWriter;
|
|
end;
|
|
|
|
//
|
|
|
|
Procedure TsrRegsStory.Init(Emit:TCustomEmit);
|
|
var
|
|
i:Word;
|
|
n:TString7;
|
|
begin
|
|
FillChar(Self,SizeOf(TsrRegsStory),0);
|
|
For i:=0 to 103 do
|
|
begin
|
|
Str(i,n);
|
|
SGRP[i].Init(Emit,'S'+n,cScalar,i);
|
|
end;
|
|
VCC[0].Init(Emit,'VCCL',cScalar);
|
|
VCC[1].Init(Emit,'VCCH',cScalar);
|
|
M0.Init(Emit,'M0',cScalar);
|
|
EXEC[0].Init(Emit,'EXECL',cScalar);
|
|
EXEC[1].Init(Emit,'EXECH',cScalar);
|
|
SCC.Init(Emit,'SCC',cScc);
|
|
For i:=0 to 255 do
|
|
begin
|
|
Str(i,n);
|
|
n:='V'+n;
|
|
VGRP[i].Init(Emit,n,cVector);
|
|
end;
|
|
FUnattach.Init(Emit,'UNATT',cUnattach);
|
|
//init order
|
|
For i:=0 to RegCount-1 do
|
|
begin
|
|
SLOT[i].FBits.id:=i;
|
|
end;
|
|
//init order
|
|
end;
|
|
|
|
Function TsrRegsStory.SLOT:PsrRegSlot; inline;
|
|
begin
|
|
Result:=@Self;
|
|
end;
|
|
|
|
function TsrRegsStory.get_sdst7(SDST:Byte):PsrRegSlot;
|
|
begin
|
|
Case SDST of
|
|
0..103:Result:=@SGRP[SDST];
|
|
106:Result:=@VCC[0];
|
|
107:Result:=@VCC[1];
|
|
124:Result:=@M0;
|
|
126:Result:=@EXEC[0];
|
|
127:Result:=@EXEC[1];
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
end;
|
|
|
|
function TsrRegsStory.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
|
begin
|
|
Result:=True;
|
|
if (dst=nil) then Exit(false);
|
|
Case SDST of
|
|
0..102:
|
|
begin
|
|
dst[0]:=@SGRP[SDST];
|
|
dst[1]:=@SGRP[SDST+1];
|
|
end;
|
|
106:
|
|
begin
|
|
dst[0]:=@VCC[0];
|
|
dst[1]:=@VCC[1];
|
|
end;
|
|
126:
|
|
begin
|
|
dst[0]:=@EXEC[0];
|
|
dst[1]:=@EXEC[1];
|
|
end;
|
|
else
|
|
Result:=False;
|
|
end;
|
|
end;
|
|
|
|
function TsrRegsStory.get_sdst8(SDST:Word):PsrRegSlot;
|
|
begin
|
|
Result:=get_ssrc8(SDST);
|
|
end;
|
|
|
|
function TsrRegsStory.get_ssrc8(SSRC:Byte):PsrRegSlot;
|
|
begin
|
|
Case SSRC of
|
|
0..103:Result:=@SGRP[SSRC];
|
|
106:Result:=@VCC[0];
|
|
107:Result:=@VCC[1];
|
|
124:Result:=@M0;
|
|
126:Result:=@EXEC[0];
|
|
127:Result:=@EXEC[1];
|
|
|
|
//251:Result:=@VCC[0]; //VCCZ
|
|
//252:Result:=@EXEC[0]; //EXECZ
|
|
|
|
253:Result:=@SCC;
|
|
//254:Write('LDS_DIRECT');
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
end;
|
|
|
|
function TsrRegsStory.get_ssrc9(SSRC:Word):PsrRegSlot;
|
|
begin
|
|
Case SSRC of
|
|
0..103:Result:=@SGRP[SSRC];
|
|
106:Result:=@VCC[0];
|
|
107:Result:=@VCC[1];
|
|
124:Result:=@M0;
|
|
126:Result:=@EXEC[0];
|
|
127:Result:=@EXEC[1];
|
|
|
|
//251:Result:=@VCC[0]; //VCCZ
|
|
//252:Result:=@EXEC[0]; //EXECZ
|
|
|
|
253:Result:=@SCC;
|
|
//254:Write('LDS_DIRECT');
|
|
256..511:Result:=@VGRP[SSRC-256];
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
end;
|
|
|
|
function TsrRegsStory.get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
|
begin
|
|
Result:=True;
|
|
if (src=nil) then Exit(False);
|
|
Case SSRC of
|
|
0..102:
|
|
begin
|
|
src[0]:=@SGRP[SSRC];
|
|
src[1]:=@SGRP[SSRC+1];
|
|
end;
|
|
106:
|
|
begin
|
|
src[0]:=@VCC[0];
|
|
src[1]:=@VCC[1];
|
|
end;
|
|
126:
|
|
begin
|
|
src[0]:=@EXEC[0];
|
|
src[1]:=@EXEC[1];
|
|
end;
|
|
256..510:
|
|
begin
|
|
src[0]:=@VGRP[SSRC-256];
|
|
src[1]:=@VGRP[SSRC-255];
|
|
//
|
|
Assert(src[0]^.Category<>cVectorArray,'TODO:fetch_ssrc9_pair cVectorArray');
|
|
Assert(src[1]^.Category<>cVectorArray,'TODO:fetch_ssrc9_pair cVectorArray');
|
|
end;
|
|
else
|
|
Result:=False;
|
|
end;
|
|
end;
|
|
|
|
function TsrRegsStory.get_vsrc8(VSRC:Byte):PsrRegSlot;
|
|
begin
|
|
Result:=@VGRP[VSRC];
|
|
end;
|
|
|
|
function TsrRegsStory.get_vdst8(VDST:Byte):PsrRegSlot;
|
|
begin
|
|
Result:=@VGRP[VDST];
|
|
end;
|
|
|
|
//SBASE 0..63
|
|
//SGRP:array[0..103] of TpsslRegSlot;
|
|
function TsrRegsStory.get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean;
|
|
var
|
|
i,p:Byte;
|
|
begin
|
|
Result:=True;
|
|
if (SBASE>63) or (count=0) or (src=nil) then Exit(False);
|
|
p:=SBASE*2;
|
|
if ((p+count)>104) then Exit(False);
|
|
For i:=0 to count-1 do
|
|
begin
|
|
src[i]:=@SGRP[p+i];
|
|
end;
|
|
end;
|
|
|
|
//SRSRC 0..31
|
|
function TsrRegsStory.get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean;
|
|
var
|
|
i,p:Byte;
|
|
begin
|
|
Result:=True;
|
|
if (SRSRC>31) or (count=0) or (src=nil) then Exit(False);
|
|
p:=SRSRC*4;
|
|
if ((p+count)>104) then Exit(False);
|
|
For i:=0 to count-1 do
|
|
begin
|
|
src[i]:=@SGRP[p+i];
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
function TsrRegsStory.get_snapshot:TsrRegsSnapshot;
|
|
var
|
|
PTR :PsrRegSlot;
|
|
Emit:TCustomEmit;
|
|
node:TsrVectorArray;
|
|
i,p:Word;
|
|
begin
|
|
Emit:=SLOT[0].Emit;
|
|
//
|
|
For i:=0 to RegCount-1 do
|
|
begin
|
|
PTR:=@PsrRegSlot(SLOT)[i];
|
|
|
|
if (PTR^.pLanes<>nil) and
|
|
(PTR^.Category=cVectorArray) then
|
|
begin
|
|
node:=Emit.specialize New<TsrVectorArray>;
|
|
//fill lanes
|
|
For p:=0 to LaneCount-1 do
|
|
begin
|
|
node.FLanes[p]:=PTR^.pLanes[p].current;
|
|
end;
|
|
//
|
|
Result.REGS[i]:=node;
|
|
end else
|
|
begin
|
|
Result.REGS[i]:=PTR^.current;
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TsrRegsStory.ForEachSlot(cb:TForEachSlot);
|
|
var
|
|
i:Word;
|
|
PTR:PsrRegSlot;
|
|
begin
|
|
if (cb=nil) then Exit;
|
|
//
|
|
PTR:=SLOT;
|
|
For i:=0 to RegCount-1 do
|
|
begin
|
|
cb(@PTR[i]);
|
|
end;
|
|
end;
|
|
|
|
procedure TsrRegsStory.ForEachSnap(cb:TForEachSnp1;orig:PsrRegsSnapshot);
|
|
var
|
|
i,p:Word;
|
|
PTR:PsrRegSlot;
|
|
nodes:record
|
|
orig:TsrVectorArray;
|
|
end;
|
|
regs:record
|
|
orig:TsrRegNode;
|
|
end;
|
|
begin
|
|
if (cb=nil) then Exit;
|
|
//
|
|
For i:=0 to RegCount-1 do
|
|
begin
|
|
PTR:=@PsrRegSlot(SLOT)[i];
|
|
|
|
if ((orig^.REGS[i]=nil) or (orig^.REGS[i].IsType(TsrVectorArray))) and
|
|
(PTR^.Category=cVectorArray) then
|
|
begin
|
|
nodes.orig:=orig^.REGS[i].specialize AsType<TsrVectorArray>;
|
|
|
|
For p:=0 to LaneCount-1 do
|
|
begin
|
|
|
|
if (nodes.orig<>nil) then
|
|
begin
|
|
regs.orig:=nodes.orig.FLanes[p];
|
|
end else
|
|
begin
|
|
regs.orig:=nil;
|
|
end;
|
|
|
|
cb(@PTR^.pLanes[p],regs.orig);
|
|
|
|
if (nodes.orig=nil) and (regs.orig<>nil) then
|
|
begin
|
|
nodes.orig:=SLOT[0].Emit.specialize New<TsrVectorArray>;
|
|
orig^.REGS[i]:=nodes.orig;
|
|
end;
|
|
|
|
if (nodes.orig<>nil) then
|
|
begin
|
|
nodes.orig.FLanes[p]:=regs.orig;
|
|
end;
|
|
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
cb(PTR,orig^.REGS[i]);
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TsrRegsStory.ForEachSnap(cb:TForEachSnp3;var ctx:TsrVolatileContext;orig,prev,next:PsrRegsSnapshot);
|
|
var
|
|
i,p:Word;
|
|
PTR:PsrRegSlot;
|
|
nodes:record
|
|
orig:TsrVectorArray;
|
|
prev:TsrVectorArray;
|
|
next:TsrVectorArray;
|
|
end;
|
|
regs:record
|
|
orig:TsrRegNode;
|
|
prev:TsrRegNode;
|
|
next:TsrRegNode;
|
|
end;
|
|
begin
|
|
if (cb=nil) then Exit;
|
|
//
|
|
For i:=0 to RegCount-1 do
|
|
begin
|
|
PTR:=@PsrRegSlot(SLOT)[i];
|
|
|
|
if ((orig^.REGS[i]=nil) or (orig^.REGS[i].IsType(TsrVectorArray))) and
|
|
((prev^.REGS[i]=nil) or (prev^.REGS[i].IsType(TsrVectorArray))) and
|
|
((next^.REGS[i]=nil) or (next^.REGS[i].IsType(TsrVectorArray))) and
|
|
(PTR^.Category=cVectorArray) then
|
|
begin
|
|
nodes.orig:=orig^.REGS[i].specialize AsType<TsrVectorArray>;
|
|
nodes.prev:=prev^.REGS[i].specialize AsType<TsrVectorArray>;
|
|
nodes.next:=next^.REGS[i].specialize AsType<TsrVectorArray>;
|
|
|
|
For p:=0 to LaneCount-1 do
|
|
begin
|
|
|
|
if (nodes.orig<>nil) then
|
|
begin
|
|
regs.orig:=nodes.orig.FLanes[p];
|
|
end else
|
|
begin
|
|
regs.orig:=nil;
|
|
end;
|
|
|
|
if (nodes.prev<>nil) then
|
|
begin
|
|
regs.prev:=nodes.prev.FLanes[p];
|
|
end else
|
|
begin
|
|
regs.prev:=nil;
|
|
end;
|
|
|
|
if (nodes.next<>nil) then
|
|
begin
|
|
regs.next:=nodes.next.FLanes[p];
|
|
end else
|
|
begin
|
|
regs.next:=nil;
|
|
end;
|
|
|
|
cb(ctx,@PTR^.pLanes[p],regs.orig,regs.prev,regs.next);
|
|
|
|
if (nodes.orig=nil) and (regs.orig<>nil) then
|
|
begin
|
|
nodes.orig:=SLOT[0].Emit.specialize New<TsrVectorArray>;
|
|
orig^.REGS[i]:=nodes.orig;
|
|
end;
|
|
|
|
if (nodes.prev=nil) and (regs.prev<>nil) then
|
|
begin
|
|
nodes.prev:=SLOT[0].Emit.specialize New<TsrVectorArray>;
|
|
prev^.REGS[i]:=nodes.prev;
|
|
end;
|
|
|
|
if (nodes.next=nil) and (regs.next<>nil) then
|
|
begin
|
|
nodes.next:=SLOT[0].Emit.specialize New<TsrVectorArray>;
|
|
next^.REGS[i]:=nodes.next;
|
|
end;
|
|
|
|
if (nodes.orig<>nil) then
|
|
begin
|
|
nodes.orig.FLanes[p]:=regs.orig;
|
|
end;
|
|
|
|
if (nodes.prev<>nil) then
|
|
begin
|
|
nodes.prev.FLanes[p]:=regs.prev;
|
|
end;
|
|
|
|
if (nodes.next<>nil) then
|
|
begin
|
|
nodes.next.FLanes[p]:=regs.next;
|
|
end;
|
|
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
cb(ctx,PTR,orig^.REGS[i],prev^.REGS[i],next^.REGS[i]);
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
//--
|
|
|
|
function TsrRegNode.GetName:RawByteString;
|
|
begin
|
|
Result:='';
|
|
if (FSlot<>nil) then Result:=FSlot^.Name;
|
|
end;
|
|
|
|
function TsrRegNode.GetDtype:TsrDataType;
|
|
begin
|
|
Result:=F.dtype;
|
|
end;
|
|
|
|
Procedure TsrRegNode.SetDtype(t:TsrDataType);
|
|
begin
|
|
F.dtype:=t;
|
|
end;
|
|
|
|
function TsrRegNode.GetWeak:Boolean;
|
|
begin
|
|
Result:=F.dweak;
|
|
end;
|
|
|
|
Procedure TsrRegNode.SetWeak(t:Boolean);
|
|
begin
|
|
F.dweak:=t;
|
|
end;
|
|
|
|
Procedure TsrRegNode.SetWriter(t:TsrNode);
|
|
begin
|
|
if (Self=nil) then Exit;
|
|
if (FWriter=t) then Exit;
|
|
|
|
Assert(RegDown(t.specialize AsType<ntReg>)<>Self,'Circular reference');
|
|
|
|
if isUsed then
|
|
begin
|
|
t.mark_read (Self);
|
|
FWriter.mark_unread(Self);
|
|
end;
|
|
FWriter:=t;
|
|
|
|
//update
|
|
if (FWriter=nil) then
|
|
begin
|
|
FCustomLine:=nil;
|
|
end else
|
|
if (FWriter._GetPline<>nil) then
|
|
begin
|
|
FCustomLine:=nil;
|
|
end;
|
|
end;
|
|
|
|
Function TsrRegNode.GetWriter:TsrNode;
|
|
begin
|
|
Result:=nil;
|
|
if (Self=nil) then Exit;
|
|
Result:=FWriter;
|
|
end;
|
|
|
|
function TsrRegNode.AsConst:TsrConst;
|
|
begin
|
|
if (Self=nil) then Exit(nil);
|
|
Result:=FWriter.specialize AsType<ntConst>;
|
|
end;
|
|
|
|
function TsrRegNode.AsReg:TsrRegNode;
|
|
begin
|
|
if (Self=nil) then Exit(nil);
|
|
Result:=FWriter.specialize AsType<ntReg>;
|
|
end;
|
|
|
|
function TsrRegNode.is_const:Boolean;
|
|
begin
|
|
if (Self=nil) then Exit(False);
|
|
Result:=FWriter.IsType(ntConst);
|
|
end;
|
|
|
|
function TsrRegNode.is_bool:Boolean;
|
|
begin
|
|
if (Self=nil) then Exit(False);
|
|
Result:=(dtype=dtBool);
|
|
end;
|
|
|
|
function TsrRegNode.is_bool_or_const_bool:Boolean;
|
|
begin
|
|
if (Self=nil) then Exit(False);
|
|
Result:=is_bool or
|
|
(is_const and AsConst.isBoolVal);
|
|
end;
|
|
|
|
function TsrRegNode.is_unknow:Boolean;
|
|
begin
|
|
if (Self=nil) then Exit(True);
|
|
Result:=(dtype=dtUnknow);
|
|
end;
|
|
|
|
function TsrRegNode.GetPrintName:RawByteString;
|
|
begin
|
|
if is_const then
|
|
begin
|
|
Result:=AsConst.GetPrintName;
|
|
end else
|
|
begin
|
|
Assert(ID.Alloc);
|
|
Result:='r'+IntToStr(ID.ID){+'_'+GetEnumName(typeInfo(TsrDataType), Ord(dtype))};
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
|
|
Procedure TsrRegPair.SetWriter(t:TsrNode);
|
|
begin
|
|
if (FWriter=t) then Exit;
|
|
if isUsed then
|
|
begin
|
|
t.mark_read (Self);
|
|
FWriter.mark_unread(Self);
|
|
end;
|
|
FWriter:=t;
|
|
end;
|
|
|
|
Procedure TsrRegPair.SetDst0(r:TsrNode);
|
|
begin
|
|
if (FDst0=r) then Exit;
|
|
FDst0.ResetWriter(Self);
|
|
FDst0:=r;
|
|
FDst0.SetWriter(Self,pLine);
|
|
end;
|
|
|
|
Procedure TsrRegPair.SetDst1(r:TsrNode);
|
|
begin
|
|
if (FDst1=r) then Exit;
|
|
FDst1.ResetWriter(Self);
|
|
FDst1:=r;
|
|
FDst1.SetWriter(Self,pLine);
|
|
end;
|
|
|
|
//--
|
|
|
|
procedure TsrRegSlot.set_current(c:TsrRegNode);
|
|
var
|
|
p:Word;
|
|
node:TsrVectorArray;
|
|
begin
|
|
if c.IsType(TsrVectorArray) then
|
|
begin
|
|
ConvertToVectorArray;
|
|
//
|
|
node:=c.specialize AsType<TsrVectorArray>;
|
|
//
|
|
For p:=0 to LaneCount-1 do
|
|
begin
|
|
pLanes[p].FCurrent:=node.FLanes[p];
|
|
end;
|
|
//
|
|
Exit;
|
|
end else
|
|
if (FBits.Category=cVectorArray) then
|
|
begin
|
|
if (c=nil) then
|
|
begin
|
|
//
|
|
For p:=0 to LaneCount-1 do
|
|
begin
|
|
pLanes[p].FCurrent:=nil;
|
|
end;
|
|
//
|
|
Exit;
|
|
end;
|
|
ConvertToVectorGeneral;
|
|
end;
|
|
//
|
|
FCurrent:=c;
|
|
end;
|
|
|
|
function TsrRegSlot.Lanes(i:Byte):PsrRegSlot;
|
|
begin
|
|
if (pLanes<>nil) and
|
|
(FBits.Category=cVectorArray) then
|
|
begin
|
|
Result:=@pLanes[i and (LaneCount-1)];
|
|
end else
|
|
begin
|
|
Result:=nil;
|
|
end;
|
|
end;
|
|
|
|
Procedure TsrRegSlot.Init(e:TCustomEmit;const n:TString7;c:TSlotCategory;i:Word=0;l:Byte=0);
|
|
begin
|
|
FEmit:=e;
|
|
FName:=n;
|
|
FBits.Category:=c;
|
|
FBits.id :=i;
|
|
FBits.LaneId :=l;
|
|
end;
|
|
|
|
function TsrRegSlot.ConvertToVectorArray:Boolean;
|
|
var
|
|
i:Byte;
|
|
n:TString7;
|
|
begin
|
|
case FBits.Category of
|
|
cVector:
|
|
begin
|
|
FBits.Category:=cVectorArray;
|
|
//
|
|
if (pLanes=nil) then
|
|
begin
|
|
pLanes:=FEmit.Alloc(SizeOf(TsrRegSlot)*LaneCount);
|
|
//
|
|
For i:=0 to LaneCount-1 do
|
|
begin
|
|
Str(i,n);
|
|
n:=Self.Name+'.'+n;
|
|
pLanes[i].Init(Emit,n,cLane,Self.id,i);
|
|
end;
|
|
end;
|
|
//
|
|
For i:=0 to LaneCount-1 do
|
|
begin
|
|
pLanes[i].FCurrent:=current;
|
|
end;
|
|
//
|
|
FCurrent:=nil;
|
|
Exit(True);
|
|
end;
|
|
cVectorArray:
|
|
Exit(True);
|
|
else
|
|
Exit(False);
|
|
end;
|
|
end;
|
|
|
|
function TsrRegSlot.ConvertToVectorGeneral:Boolean;
|
|
var
|
|
i:Byte;
|
|
begin
|
|
case FBits.Category of
|
|
cVectorArray:
|
|
begin
|
|
FBits.Category:=cVector;
|
|
//
|
|
For i:=0 to LaneCount-1 do
|
|
begin
|
|
pLanes[i].FCurrent:=nil;
|
|
end;
|
|
//
|
|
Exit(True);
|
|
end;
|
|
cVector:
|
|
Exit(True);
|
|
else
|
|
Exit(False);
|
|
end;
|
|
end;
|
|
|
|
function TsrRegSlot.isBoolOnly:Boolean;
|
|
begin
|
|
Result:=(FBits.Category=cScc);
|
|
end;
|
|
|
|
function TsrRegSlot.isScalar:Boolean;
|
|
begin
|
|
Result:=(FBits.Category in [cScalar,cScc]);
|
|
end;
|
|
|
|
function TsrRegSlot.iUnattach:Boolean;
|
|
begin
|
|
Result:=(FBits.Category=cUnattach);
|
|
end;
|
|
|
|
function TsrRegSlot._New(rtype:TsrDataType;pLine:TsrRegNode):TsrRegNode;
|
|
var
|
|
node:TsrRegNode;
|
|
begin
|
|
if isBoolOnly then
|
|
begin
|
|
rtype:=dtBool;
|
|
end;
|
|
node:=FEmit.specialize New<TsrRegNode>;
|
|
node.FSlot:=@Self;
|
|
node.dtype:=rtype;
|
|
node.CustomLine:=pLine;
|
|
Result:=node;
|
|
end;
|
|
|
|
function TsrRegSlot.New(rtype:TsrDataType;pLine:TsrRegNode=nil):TsrRegNode;
|
|
begin
|
|
Result:=_New(rtype,pLine);
|
|
//update
|
|
current:=Result;
|
|
end;
|
|
|
|
//
|
|
|
|
function RegDown(node:TsrRegNode):TsrRegNode;
|
|
var
|
|
tmp:TsrRegNode;
|
|
begin
|
|
//backtrace
|
|
Result:=node;
|
|
While (Result<>nil) do
|
|
begin
|
|
tmp:=Result.AsReg; //next
|
|
if (tmp=nil) then Break;
|
|
Assert(tmp<>Result);
|
|
Result:=tmp;
|
|
end;
|
|
end;
|
|
|
|
function RegDownSlot(node:TsrRegNode):TsrRegNode;
|
|
var
|
|
tmp:TsrRegNode;
|
|
begin
|
|
Exit(RegDown(node));
|
|
|
|
//backtrace
|
|
Result:=node;
|
|
While (Result<>nil) do
|
|
begin
|
|
tmp:=Result.AsReg; //next
|
|
if (tmp=nil) then Break;
|
|
Assert(tmp<>Result);
|
|
if (tmp.pSlot<>Result.pSlot) then Break;
|
|
Result:=tmp;
|
|
end;
|
|
end;
|
|
|
|
function CompareReg(r1,r2:TsrRegNode):Boolean;
|
|
begin
|
|
r1:=RegDownSlot(r1);
|
|
r2:=RegDownSlot(r2);
|
|
Result:=(r1=r2);
|
|
if not Result then
|
|
begin
|
|
Result:=CompareConst(r1.AsConst,r2.AsConst);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|