fpPS4/spirv/srReg.pas
2022-07-15 13:12:45 +03:00

477 lines
8.9 KiB
ObjectPascal

unit srReg;
{$mode objfpc}{$H+}
interface
uses
srNodes,
srRefId,
srTypes,
srConst;
type
PPsrRegSlot=^PsrRegSlot;
PsrRegSlot=^TsrRegSlot;
PPsrRegNode=^PsrRegNode;
PsrRegNode=^TsrRegNode;
TsrRegNode=packed object
pPrev,pNext:PsrRegNode;
//----
read_count:DWORD;
ID:TsrRefId; //post id
pSlot:PsrRegSlot;
pWriter:TOpParamSingle; //ntReg,ntConst,ntOp,ntVolatile
pLine:Pointer; //PspirvOp;
dtype:TsrDataType;
function GetName:RawByteString;
Procedure mark_read;
Procedure mark_unread;
procedure SetConst(pConst:PsrConst);
procedure SetReg(pReg:PsrRegNode);
function AsConst:PsrConst;
function AsOp:Pointer;
function AsReg:PsrRegNode;
function is_const:Boolean;
function is_bool:Boolean;
function is_bool_or_const_bool:Boolean;
function is_unknow:Boolean;
end;
TRegStory=specialize TNodeList<PsrRegNode>;
TString5=string[5];
TsrRegSlot=object
Alloc:TfnAlloc;
pVar:Pointer;
pStory:TRegStory;
rid:TString5;
Procedure Init(a:TfnAlloc;const n:TString5);
function first:PsrRegNode;
function current:PsrRegNode;
function New(pLine:Pointer;rtype:TsrDataType):PsrRegNode;
function NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
procedure Remove(r:PsrRegNode);
end;
PsrRegsSnapshot=^TsrRegsSnapshot;
TsrRegsSnapshot=object
SGRP:array[0..103] of PsrRegNode;
VCC:array[0..1] of PsrRegNode;
M0:PsrRegNode;
EXEC:array[0..1] of PsrRegNode;
SCC:PsrRegNode;
VGRP:array[0..255] of PsrRegNode;
end;
TForEachSlot=procedure(pSlot:PsrRegSlot) of object;
TForEachSnap=procedure(pSlot:PsrRegSlot;var old:PsrRegNode) of object;
TsrRegsStory=object
SGRP:array[0..103] of TsrRegSlot;
VCC:array[0..1] of TsrRegSlot;
M0:TsrRegSlot;
EXEC:array[0..1] of TsrRegSlot;
SCC:TsrRegSlot;
VGRP:array[0..255] of TsrRegSlot;
FUnattach:TsrRegSlot;
Procedure Init(Alloc:TfnAlloc);
function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
function get_sdst7(SDST:Byte):PsrRegSlot;
function get_ssrc8(SSRC:Byte):PsrRegSlot;
function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
function get_ssrc9(SSRC:Word):PsrRegSlot;
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:TForEachSnap;old:PsrRegsSnapshot);
end;
implementation
Procedure TsrRegsStory.Init(Alloc:TfnAlloc);
var
i:Word;
n:TString5;
begin
FillChar(Self,SizeOf(TsrRegsStory),0);
For i:=0 to 103 do
begin
Str(i,n);
SGRP[i].Init(Alloc,'S'+n);
end;
VCC[0].Init(Alloc,'VCCL');
VCC[1].Init(Alloc,'VCCH');
M0.Init(Alloc,'M0');
EXEC[0].Init(Alloc,'EXECL');
EXEC[1].Init(Alloc,'EXECH');
SCC.Init(Alloc,'SCC');
For i:=0 to 255 do
begin
Str(i,n);
VGRP[i].Init(Alloc,'V'+n);
end;
FUnattach.Init(Alloc,'UNATT');
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_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_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_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];
end;
else
Result:=False;
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_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
i:Word;
begin
Result:=Default(TsrRegsSnapshot);
For i:=0 to 103 do
begin
Result.SGRP[i]:=SGRP[i].current;
end;
For i:=0 to 1 do
begin
Result.VCC[i] :=VCC[i].current;
end;
Result.M0 :=M0.current;
For i:=0 to 1 do
begin
Result.EXEC[i]:=EXEC[i].current;
end;
Result.SCC :=SCC.current;
For i:=0 to 255 do
begin
Result.VGRP[i]:=VGRP[i].current;
end;
end;
procedure TsrRegsStory.ForEachSlot(cb:TForEachSlot);
var
i:Word;
begin
if (cb=nil) then Exit;
For i:=0 to 103 do
begin
cb(@SGRP[i]);
end;
For i:=0 to 1 do
begin
cb(@VCC[i]);
end;
cb(@M0);
For i:=0 to 1 do
begin
cb(@EXEC[i]);
end;
cb(@SCC);
For i:=0 to 255 do
begin
cb(@VGRP[i]);
end;
end;
procedure TsrRegsStory.ForEachSnap(cb:TForEachSnap;old:PsrRegsSnapshot);
var
i:Word;
begin
if (cb=nil) or (old=nil) then Exit;
For i:=0 to 103 do
begin
cb(@SGRP[i],Old^.SGRP[i]);
end;
For i:=0 to 1 do
begin
cb(@VCC[i],Old^.VCC[i]);
end;
cb(@M0,Old^.M0);
For i:=0 to 1 do
begin
cb(@EXEC[i],Old^.EXEC[i]);
end;
cb(@SCC,Old^.SCC);
For i:=0 to 255 do
begin
cb(@VGRP[i],Old^.VGRP[i]);
end;
end;
//--
function TsrRegNode.GetName:RawByteString;
begin
Result:='';
if (pSlot<>nil) then Result:=pSlot^.rid;
end;
Procedure TsrRegNode.mark_read;
begin
Inc(read_count);
end;
Procedure TsrRegNode.mark_unread;
begin
Assert(read_count<>0);
if (read_count<>0) then Dec(read_count);
end;
procedure TsrRegNode.SetConst(pConst:PsrConst);
begin
pWriter.SetParam(ntConst,pConst);
dtype:=pConst^.key.dtype;
end;
procedure TsrRegNode.SetReg(pReg:PsrRegNode);
begin
Assert(@Self<>pReg);
pWriter.SetParam(ntReg,pReg);
end;
function TsrRegNode.AsConst:PsrConst;
begin
Result:=nil;
if (@Self=nil) then Exit;
if (pWriter.ntype<>ntConst) then Exit;
Result:=pWriter.pData;
end;
function TsrRegNode.AsOp:Pointer;
begin
Result:=nil;
if (@Self=nil) then Exit;
if (pWriter.ntype<>ntOp) then Exit;
Result:=pWriter.pData;
end;
function TsrRegNode.AsReg:PsrRegNode;
begin
Result:=nil;
if (@Self=nil) then Exit;
if (pWriter.ntype<>ntReg) then Exit;
Result:=pWriter.pData;
end;
function TsrRegNode.is_const:Boolean;
begin
Result:=(pWriter.ntype=ntConst);
end;
function TsrRegNode.is_bool:Boolean;
begin
Result:=(dtype=dtBool);
end;
function TsrRegNode.is_bool_or_const_bool:Boolean;
begin
Result:=is_bool or
(is_const and (AsConst<>nil) and AsConst^.isBoolVal);
end;
function TsrRegNode.is_unknow:Boolean;
begin
Result:=(dtype=dtUnknow);
end;
//--
Procedure TsrRegSlot.Init(a:TfnAlloc;const n:TString5);
begin
Alloc:=a;
rid :=n;
end;
function TsrRegSlot.first:PsrRegNode;
begin
Result:=pStory.pHead;
end;
function TsrRegSlot.current:PsrRegNode;
begin
Result:=pStory.pTail;
end;
function TsrRegSlot.New(pLine:Pointer;rtype:TsrDataType):PsrRegNode;
var
node:PsrRegNode;
begin
node:=Alloc(SizeOf(TsrRegNode));
node^.pSlot:=@Self;
node^.dtype:=rtype;
node^.pLine:=pLine;
pStory.Push_tail(node);
Result:=node;
end;
function TsrRegSlot.NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
var
node:PsrRegNode;
begin
node:=Alloc(SizeOf(TsrRegNode));
node^.pSlot:=@Self;
node^.dtype:=rtype;
node^.pLine:=r^.pLine;
pStory.InsertAfter(r,node);
Result:=node;
end;
procedure TsrRegSlot.Remove(r:PsrRegNode);
begin
if (r=nil) then Exit;
pStory.Remove(r);
end;
end.