From b75f4ed26a43f748ac007955a06d47ffa2b5468a Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Mon, 26 May 2025 14:43:31 +0300 Subject: [PATCH] + --- spirv/emit_fetch.pas | 130 +++++++++++++++++++++++++++++++++++++++++++ spirv/emit_vop3.pas | 36 ++++++++++-- spirv/emit_vopc.pas | 31 +++++++++-- 3 files changed, 189 insertions(+), 8 deletions(-) diff --git a/spirv/emit_fetch.pas b/spirv/emit_fetch.pas index e6eef43e..4e8c40c3 100644 --- a/spirv/emit_fetch.pas +++ b/spirv/emit_fetch.pas @@ -55,6 +55,7 @@ type function fetch_vdst8_64(VDST:Word;rtype:TsrDataType):TsrRegNode; // procedure OpCmpV(OpId:DWORD;dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); + procedure OpCmpClass(dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); procedure OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); procedure OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:TsrRegNode); // @@ -550,6 +551,135 @@ begin SetThreadBit(dst0,dst1,exc); end; +const + fcSignalingNan = 1 shl 0; + fcQuietNan = 1 shl 1; + fcNegativeInfinity = 1 shl 2; + fcNegativeNormal = 1 shl 3; + fcNegativeDenorm = 1 shl 4; + fcNegativeZero = 1 shl 5; + fcPositiveZero = 1 shl 6; + fcPositiveDenorm = 1 shl 7; + fcPositiveNormal = 1 shl 8; + fcPositiveInfinity = 1 shl 9; + fcAny = (1 shl 10)-1; + + fcNaN = fcSignalingNan or fcQuietNan; + fcInfinity = fcPositiveInfinity or fcNegativeInfinity; + fcNegative = fcNegativeInfinity or fcNegativeNormal or fcNegativeDenorm or fcNegativeZero; + fcPositive = fcPositiveZero or fcPositiveDenorm or fcPositiveNormal or fcPositiveInfinity; + +procedure TEmitFetch.OpCmpClass(dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); +var + rsl:TsrRegNode; + ror:TsrRegNode; + exc:TsrRegNode; + + msk:TsrConst; + val:DWORD; + + function _test_group(val,mask:DWORD):Boolean; inline; + var + i:DWORD; + begin + i:=(val and mask); + Result:=(i=0) or (i=mask); + end; + +begin + + msk:=src1.AsConst; + + if (msk<>nil) then + begin + + val:=msk.AsUint32; + + if (val and fcAny)=fcAny then + begin + ror:=NewImm_b(True); + end else + if _test_group(val,fcNaN ) or + _test_group(val,fcInfinity) or + _test_group(val,fcNegative) or + _test_group(val,fcPositive) then + begin + ror:=nil; + + if (val and fcNaN)=fcNaN then + begin + rsl:=NewReg(dtBool); + _Op1(line,Op.OpIsNan,rsl,src0); + ror:=rsl; + end; + + if (val and fcInfinity)=fcInfinity then + begin + rsl:=NewReg(dtBool); + _Op1(line,Op.OpIsInf,rsl,src0); + // + if (ror=nil) then + begin + ror:=rsl; + end else + begin + ror:=OpLogicalOrTo(ror,rsl); + end; + // + end; + + if (val and fcNegative)=fcNegative then + begin + rsl:=NewReg(dtBool); + _Op2(line,Op.OpFOrdLessThanEqual,rsl,src0,NewImm_s(dtFloat32,-0.0)); + // + if (ror=nil) then + begin + ror:=rsl; + end else + begin + ror:=OpLogicalOrTo(ror,rsl); + end; + // + end; + + if (val and fcPositive)=fcPositive then + begin + rsl:=NewReg(dtBool); + _Op2(line,Op.OpFOrdGreaterThanEqual,rsl,src0,NewImm_s(dtFloat32,+0.0)); + // + if (ror=nil) then + begin + ror:=rsl; + end else + begin + ror:=OpLogicalOrTo(ror,rsl); + end; + // + end; + + if (ror=nil) then + begin + ror:=NewImm_b(False); + end; + + end else + begin + Assert(false,'TODO: Unhandled mask V_CMP_CLASS_32:0x'+HexStr(val,2)); + end; + + end else + begin + Assert(false,'TODO: Non const V_CMP_CLASS_32'); + end; + + exc:=GetThreadBit(get_exec0,get_exec1,dtBool); + + exc:=OpLogicalAndTo(ror,exc); + + SetThreadBit(dst0,dst1,exc); +end; + procedure TEmitFetch.OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); begin Op2(OpId,dtBool,dst,src0,src1); diff --git a/spirv/emit_vop3.pas b/spirv/emit_vop3.pas index 93898b4c..7a2f4301 100644 --- a/spirv/emit_vop3.pas +++ b/spirv/emit_vop3.pas @@ -20,6 +20,7 @@ type procedure emit_VOP3a; procedure emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); procedure emit_V_CMP_C (r,x:Boolean); + procedure emit_V_CMP_CLASS_32(x:Boolean); procedure emit_src_neg_bit(src:PPsrRegNode;count:Byte;rtype:TsrDataType); procedure emit_src_abs_bit(src:PPsrRegNode;count:Byte;rtype:TsrDataType); @@ -111,13 +112,37 @@ begin Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG'); - SetConst_b(dst[0],r); - SetConst_q(dst[1],dtUnknow,0); //set zero + SetThreadBit(dst[0],dst[1],NewImm_b(r)); if x then begin - MakeCopy (get_exec0,dst[0]^.current); - SetConst_q(get_exec1,dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + MakeCopy(get_exec1,dst[1]^.current); + end; +end; + +procedure TEmit_VOP3.emit_V_CMP_CLASS_32(x:Boolean); +Var + dst:array[0..1] of PsrRegSlot; + src:array[0..1] of TsrRegNode; +begin + if not get_sdst7_pair(FSPI.VOP3a.VDST,@dst) then Exit; + + Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); + Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); + + src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32); + + emit_src_abs_bit(@src,1,dtFloat32); + emit_src_neg_bit(@src,1,dtFloat32); + + OpCmpClass(dst[0],dst[1],src[0],src[1]); + + if x then + begin + MakeCopy(get_exec0,dst[0]^.current); + MakeCopy(get_exec1,dst[1]^.current); end; end; @@ -1253,6 +1278,9 @@ begin V_CMPX_LG_U32 :emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true); V_CMPX_GE_U32 :emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true); + V_CMP_CLASS_F32 :emit_V_CMP_CLASS_32(false); + V_CMPX_CLASS_F32:emit_V_CMP_CLASS_32(true ); + else Assert(false,'VOP3c?'+IntToStr(FSPI.VOP3a.OP)+' '+get_str_spi(FSPI)); end; diff --git a/spirv/emit_vopc.pas b/spirv/emit_vopc.pas index e135c7ca..b3215ce7 100644 --- a/spirv/emit_vopc.pas +++ b/spirv/emit_vopc.pas @@ -17,6 +17,7 @@ type procedure emit_VOPC; procedure emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); procedure emit_V_CMP_C (r,x:Boolean); + procedure emit_V_CMP_CLASS_32(x:Boolean); end; implementation @@ -48,13 +49,32 @@ begin dst[0]:=get_vcc0; dst[1]:=get_vcc1; - SetConst_b(dst[0],r); - SetConst_q(dst[1],dtUnknow,0); //set zero + SetThreadBit(dst[0],dst[1],NewImm_b(r)); if x then begin - MakeCopy (get_exec0,dst[0]^.current); - SetConst_q(get_exec1,dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + MakeCopy(get_exec1,dst[1]^.current); + end; +end; + +procedure TEmit_VOPC.emit_V_CMP_CLASS_32(x:Boolean); +Var + dst:array[0..1] of PsrRegSlot; + src:array[0..1] of TsrRegNode; +begin + dst[0]:=get_vcc0; + dst[1]:=get_vcc1; + + src[0]:=fetch_ssrc9(FSPI.VOPC.SRC0 ,dtFloat32); + src[1]:=fetch_vsrc8(FSPI.VOPC.VSRC1,dtUInt32); + + OpCmpClass(dst[0],dst[1],src[0],src[1]); + + if x then + begin + MakeCopy(get_exec0,dst[0]^.current); + MakeCopy(get_exec1,dst[1]^.current); end; end; @@ -193,6 +213,9 @@ begin V_CMPX_LG_U32 :emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true); V_CMPX_GE_U32 :emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true); + V_CMP_CLASS_F32 :emit_V_CMP_CLASS_32(false); + V_CMPX_CLASS_F32:emit_V_CMP_CLASS_32(true ); + else Assert(false,'VOPC?'+IntToStr(FSPI.VOPC.OP)+' '+get_str_spi(FSPI)); end;