mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-27 08:31:07 +00:00
470 lines
8.7 KiB
ObjectPascal
470 lines
8.7 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);
|
|
function AsConst:PsrConst;
|
|
function AsOp:Pointer;
|
|
function AsReg:Pointer;
|
|
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;
|
|
|
|
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:Pointer;
|
|
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.
|
|
|