fpPS4/spirv/emit_sopp.pas

392 lines
8.1 KiB
ObjectPascal
Raw Normal View History

2022-05-31 07:17:14 +00:00
unit emit_SOPP;
{$mode objfpc}{$H+}
interface
uses
sysutils,
ps4_pssl,
2022-09-05 13:30:24 +00:00
srType,
srCFGParser,
srCFGLabel,
srCFGCursor,
srFlow,
2022-05-31 07:17:14 +00:00
srReg,
srOp,
srOpUtils,
spirv,
2022-09-05 13:30:24 +00:00
emit_fetch;
2022-05-31 07:17:14 +00:00
type
2022-09-05 13:30:24 +00:00
TEmit_SOPP=class(TEmitFetch)
procedure emit_SOPP;
procedure emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
procedure emit_S_BRANCH;
procedure mark_end_of;
2022-05-31 07:17:14 +00:00
function IsBegLoop(Adr:TSrcAdr):Boolean;
function IsEndLoop(Adr:TSrcAdr):Boolean;
2022-06-30 09:59:08 +00:00
function IsUnknow(Adr:TSrcAdr):Boolean;
2022-05-31 07:17:14 +00:00
procedure emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
2022-06-30 09:59:08 +00:00
procedure emit_block_unknow(adr:TSrcAdr);
2022-05-31 07:17:14 +00:00
procedure UpBuildVol(last:PsrOpBlock);
procedure emit_loop(adr:TSrcAdr);
2022-07-01 12:53:39 +00:00
procedure emit_loop_cond(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
2022-05-31 07:17:14 +00:00
end;
implementation
procedure TEmit_SOPP.emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
var
src:PsrRegNode;
pOpBlock:PsrOpBlock;
pOpChild:PsrOpBlock;
pOpLabel:array[0..1] of PspirvOp;
pLBlock:PsrCFGBlock;
Info:array[0..1] of TsrBlockInfo;
begin
src:=MakeRead(pSlot,dtBool); //get before OpBranchConditional
2022-09-05 13:30:24 +00:00
pOpLabel[0]:=NewLabelOp(False);
pOpLabel[1]:=NewLabelOp(False);
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
pLBlock:=Cursor.pCode^.FTop.DownBlock(adr);
Assert(pLBlock<>@Cursor.pCode^.FTop,'not found');
2022-05-31 07:17:14 +00:00
Info[0]:=Default(TsrBlockInfo);
Info[1]:=Default(TsrBlockInfo);
Case pLBlock^.bType of
btAdr: //set new adr
begin
2022-09-05 13:30:24 +00:00
Info[0].b_adr:=Cursor.Adr;
Info[0].e_adr:=Cursor.Adr;
2022-05-31 07:17:14 +00:00
Info[0].bType:=btCond;
//
Info[1].b_adr:=pLBlock^.pBLabel^.Adr;
Info[1].e_adr:=pLBlock^.pELabel^.Adr;
Info[1].bType:=btAdr;
end;
btCond: //normal cond
begin
Info[0].b_adr:=pLBlock^.pBLabel^.Adr;
Info[0].e_adr:=pLBlock^.pELabel^.Adr;
Info[0].bType:=btCond;
//
Info[1].b_adr:=Info[0].b_adr;
Info[1].e_adr:=Info[0].e_adr;
Info[1].bType:=btOther;
end;
else
Assert(false,'emit_cond_block');
end;
pOpLabel[0]^.Adr:=Info[0].b_adr;
pOpLabel[1]^.Adr:=Info[0].e_adr;
2022-09-05 13:30:24 +00:00
pOpBlock:=NewBlockOp(get_snapshot);
2022-05-31 07:17:14 +00:00
pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],nil);
pOpBlock^.SetInfo(Info[0]);
pOpBlock^.SetCond(src,not n);
PushBlockOp(line,pOpBlock,pLBlock);
2022-09-05 13:30:24 +00:00
OpCondMerge(line,pOpLabel[1]);
2022-05-31 07:17:14 +00:00
Case n of
2022-09-05 13:30:24 +00:00
True :OpBranchCond(line,pOpLabel[1],pOpLabel[0],src);
False:OpBranchCond(line,pOpLabel[0],pOpLabel[1],src);
2022-05-31 07:17:14 +00:00
end;
AddSpirvOp(line,pOpLabel[0]);
//down group
pOpChild:=AllocBlockOp;
pOpChild^.SetInfo(Info[1]);
PushBlockOp(line,pOpChild,nil);
if (pLBlock^.bType=btAdr) then //set new adr
begin
SetPtr(adr.get_pc,btAdr);
end;
end;
procedure TEmit_SOPP.UpBuildVol(last:PsrOpBlock);
var
node:PsrOpBlock;
begin
2022-09-05 13:30:24 +00:00
node:=Main^.pBlock;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
Case node^.Block.bType of
2022-11-05 14:48:13 +00:00
btCond:PrivateList.build_volatile_cur(node^.Regs.pSnap_cur);
btLoop:PrivateList.build_volatile_brk(node^.Regs.pSnap_cur);
2022-05-31 07:17:14 +00:00
else;
end;
if (node=last) then Break;
2022-09-05 13:30:24 +00:00
node:=node^.Parent;
2022-05-31 07:17:14 +00:00
end;
end;
procedure TEmit_SOPP.emit_loop(adr:TSrcAdr);
var
node,pOpBlock:PsrOpBlock;
2022-09-05 13:30:24 +00:00
pOpLabel:PspirvOp;
2022-05-31 07:17:14 +00:00
FVolMark:TsrVolMark;
bnew:Boolean;
begin
2022-09-05 13:30:24 +00:00
node:=Main^.pBlock;
2022-05-31 07:17:14 +00:00
pOpBlock:=node^.FindUpLoop;
Assert(pOpBlock<>nil,'not found');
2022-09-05 13:30:24 +00:00
pOpLabel:=nil;
2022-05-31 07:17:14 +00:00
FVolMark:=vmNone;
if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is continue?
begin
2022-09-05 13:30:24 +00:00
pOpLabel:=pOpBlock^.Labels.pMrgOp; //-> OpLoopMerge end -> OpLoopMerge before
2022-05-31 07:17:14 +00:00
pOpBlock^.Cond.FUseCont:=True;
FVolMark:=vmCont;
end else
if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is break?
begin
2022-09-05 13:30:24 +00:00
pOpLabel:=pOpBlock^.Labels.pEndOp;
2022-05-31 07:17:14 +00:00
FVolMark:=vmBreak;
end else
begin
Assert(false,'emit_loop');
end;
2022-09-05 13:30:24 +00:00
Assert(pOpLabel<>nil);
2022-05-31 07:17:14 +00:00
bnew:=true;
2022-09-05 13:30:24 +00:00
if Cursor.pBlock^.IsEndOf(Cursor.Adr) then //is last
2022-05-31 07:17:14 +00:00
begin
2022-10-12 14:00:49 +00:00
//Assert(node^.Block.e_adr.get_pc=Cursor.Adr.get_pc);
2022-05-31 07:17:14 +00:00
Case node^.Block.bType of
btSetpc:;
else
begin
bnew:=false;
end;
end;
end;
UpBuildVol(pOpBlock);
node^.Regs.FVolMark:=FVolMark; //mark end of
2022-09-05 13:30:24 +00:00
OpBranch(line,pOpLabel);
2022-05-31 07:17:14 +00:00
if bnew then
begin
2022-09-05 13:30:24 +00:00
AddSpirvOp(line,NewLabelOp(True));
2022-05-31 07:17:14 +00:00
end;
end;
2022-07-01 12:53:39 +00:00
procedure TEmit_SOPP.emit_loop_cond(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
var
src:PsrRegNode;
node,pOpBlock:PsrOpBlock;
pOpLabel:array[0..1] of PspirvOp;
FVolMark:TsrVolMark;
begin
src:=MakeRead(pSlot,dtBool);
2022-09-05 13:30:24 +00:00
node:=Main^.pBlock;
2022-07-01 12:53:39 +00:00
pOpBlock:=node^.FindUpLoop;
Assert(pOpBlock<>nil,'not found');
pOpLabel[0]:=nil;
FVolMark:=vmNone;
if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is continue?
begin
pOpLabel[0]:=pOpBlock^.Labels.pMrgOp; //-> OpLoopMerge end -> OpLoopMerge before
pOpBlock^.Cond.FUseCont:=True;
FVolMark:=vmCont;
end else
if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is break?
begin
pOpLabel[0]:=pOpBlock^.Labels.pEndOp;
FVolMark:=vmBreak;
end else
begin
Assert(false,'emit_loop');
end;
Assert(pOpLabel[0]<>nil);
2022-09-05 13:30:24 +00:00
pOpLabel[1]:=NewLabelOp(False);
2022-07-01 12:53:39 +00:00
UpBuildVol(pOpBlock);
node^.Regs.FVolMark:=FVolMark; //mark end of
2022-09-05 13:30:24 +00:00
OpCondMerge(line,pOpLabel[1]);
2022-07-01 12:53:39 +00:00
Case n of
2022-09-05 13:30:24 +00:00
True :OpBranchCond(line,pOpLabel[0],pOpLabel[1],src);
False:OpBranchCond(line,pOpLabel[1],pOpLabel[0],src);
2022-07-01 12:53:39 +00:00
end;
AddSpirvOp(line,pOpLabel[1]);
end;
2022-05-31 07:17:14 +00:00
function TEmit_SOPP.IsBegLoop(Adr:TSrcAdr):Boolean;
var
node:PsrCFGBlock;
begin
Result:=false;
2022-09-05 13:30:24 +00:00
node:=Cursor.pBlock^.FindUpLoop;
2022-05-31 07:17:14 +00:00
if (node<>nil) then
begin
Result:=node^.pBLabel^.Adr.get_pc=Adr.get_pc;
end;
end;
function TEmit_SOPP.IsEndLoop(Adr:TSrcAdr):Boolean;
var
node:PsrCFGBlock;
begin
Result:=false;
2022-09-05 13:30:24 +00:00
node:=Cursor.pBlock^.FindUpLoop;
2022-05-31 07:17:14 +00:00
if (node<>nil) then
begin
Result:=node^.pELabel^.Adr.get_pc=Adr.get_pc;
end;
end;
2022-06-30 09:59:08 +00:00
function TEmit_SOPP.IsUnknow(Adr:TSrcAdr):Boolean;
var
pLabel:PsrLabel;
begin
pLabel:=FindLabel(Adr);
Assert(pLabel<>nil);
Result:=pLabel^.IsType(ltUnknow);
end;
2022-09-05 13:30:24 +00:00
procedure TEmit_SOPP.emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
2022-05-31 07:17:14 +00:00
var
c_adr,b_adr:TSrcAdr;
pLabel:PsrLabel;
begin
2022-09-05 13:30:24 +00:00
c_adr:=Cursor.Adr;
2022-05-31 07:17:14 +00:00
b_adr:=c_adr;
b_adr.Offdw:=get_branch_offset(FSPI);
pLabel:=FindLabel(b_adr);
Assert(pLabel<>nil);
2022-10-12 14:00:49 +00:00
//Assert(not pLabel^.IsType(ltUnknow));
2022-05-31 07:17:14 +00:00
if pLabel^.IsType(ltBegAdr) then //adr
begin
emit_cond_block(pSlot,n,b_adr);
end else
if (SmallInt(FSPI.SOPP.SIMM)<0) then //up
begin //continue?
if not IsBegLoop(b_adr) then Assert(false,'Unknow');
2022-07-01 12:53:39 +00:00
emit_loop_cond(pSlot,n,b_adr);
2022-05-31 07:17:14 +00:00
end else
begin //down
2022-09-05 13:30:24 +00:00
if Cursor.pBlock^.IsBigOf(b_adr) then
2022-05-31 07:17:14 +00:00
begin //break?
if not IsEndLoop(b_adr) then Assert(false,'Unknow');
2022-07-01 12:53:39 +00:00
emit_loop_cond(pSlot,n,b_adr);
2022-05-31 07:17:14 +00:00
end else
begin //cond
emit_cond_block(pSlot,n,c_adr);
end;
end;
end;
2022-06-30 09:59:08 +00:00
procedure TEmit_SOPP.emit_block_unknow(adr:TSrcAdr);
var
c_adr:TSrcAdr;
e_adr:TSrcAdr;
pOpChild:PsrOpBlock;
Info:TsrBlockInfo;
begin
Info:=Default(TsrBlockInfo);
2022-09-05 13:30:24 +00:00
c_adr:=Cursor.Adr; //get current
2022-07-15 10:12:45 +00:00
SetPtr(adr.get_pc,btAdrBranch); //set new
2022-09-05 13:30:24 +00:00
e_adr:=Cursor.pCode^.FTop.pELabel^.Adr; //get end of code
2022-06-30 09:59:08 +00:00
SetPtr(c_adr.get_pc,btMain); //ret current
Info.b_adr:=adr;
Info.e_adr:=e_adr;
2022-07-15 10:12:45 +00:00
Info.bType:=btAdrBranch;
2022-06-30 09:59:08 +00:00
//down group
pOpChild:=AllocBlockOp;
pOpChild^.SetInfo(Info);
PushBlockOp(line,pOpChild,nil);
2022-07-15 10:12:45 +00:00
SetPtr(adr.get_pc,btAdrBranch);
2022-06-30 09:59:08 +00:00
end;
2022-09-05 13:30:24 +00:00
procedure TEmit_SOPP.emit_S_BRANCH;
2022-05-31 07:17:14 +00:00
var
c_adr,b_adr:TSrcAdr;
begin
2022-09-05 13:30:24 +00:00
c_adr:=Cursor.Adr;
2022-05-31 07:17:14 +00:00
b_adr:=c_adr;
b_adr.Offdw:=get_branch_offset(FSPI);
2022-06-30 09:59:08 +00:00
if IsUnknow(b_adr) then
begin
emit_block_unknow(b_adr);
end else
2022-05-31 07:17:14 +00:00
if (SmallInt(FSPI.SOPP.SIMM)<0) then //up
begin //continue?
if not IsBegLoop(b_adr) then Assert(false,'Unknow');
emit_loop(b_adr);
end else //down
begin //break?
if not IsEndLoop(b_adr) then Assert(false,'Unknow');
emit_loop(b_adr);
end;
end;
2022-09-05 13:30:24 +00:00
procedure TEmit_SOPP.mark_end_of;
begin
Main^.pBlock^.Regs.FVolMark:=vmEnd; //mark end of
end;
procedure TEmit_SOPP.emit_SOPP;
2022-05-31 07:17:14 +00:00
begin
Case FSPI.SOPP.OP of
S_NOP,
S_WAITCNT:;
2022-11-13 18:02:13 +00:00
S_TTRACEDATA:; //write_thread_trace_data(M0[31:0])
2022-05-31 07:17:14 +00:00
S_ENDPGM:
begin
if not is_term_op(line) then
begin
AddSpirvOp(Op.OpReturn);
end;
2022-09-05 13:30:24 +00:00
mark_end_of;
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
S_CBRANCH_SCC0 :emit_S_BRANCH_COND(get_scc ,false);
S_CBRANCH_SCC1 :emit_S_BRANCH_COND(get_scc ,true);
S_CBRANCH_VCCZ :emit_S_BRANCH_COND(get_vcc0 ,false);
S_CBRANCH_VCCNZ :emit_S_BRANCH_COND(get_vcc0 ,true);
S_CBRANCH_EXECZ :emit_S_BRANCH_COND(get_exec0,false);
S_CBRANCH_EXECNZ:emit_S_BRANCH_COND(get_exec0,true);
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
S_BRANCH :emit_S_BRANCH;
2022-05-31 07:17:14 +00:00
else
Assert(false,'SOPP?'+IntToStr(FSPI.SOPP.OP));
end;
end;
end.