ReXGlue SDK
Loading...
Searching...
No Matches
rex::xenos::ucode Namespace Reference

Classes

struct  ControlFlowExecInstruction
struct  ControlFlowCondExecInstruction
struct  ControlFlowCondExecPredInstruction
struct  ControlFlowLoopStartInstruction
struct  ControlFlowLoopEndInstruction
struct  ControlFlowCondCallInstruction
struct  ControlFlowReturnInstruction
struct  ControlFlowCondJmpInstruction
struct  ControlFlowAllocInstruction
union  ControlFlowInstruction
struct  VertexFetchInstruction
struct  TextureFetchInstruction
union  FetchInstruction
struct  AluScalarOpcodeTraits
struct  AluVectorOpcodeTraits
struct  AluInstruction

Enumerations

enum class  ControlFlowOpcode : u32 {
  kNop = 0 , kExec = 1 , kExecEnd = 2 , kCondExec = 3 ,
  kCondExecEnd = 4 , kCondExecPred = 5 , kCondExecPredEnd = 6 , kLoopStart = 7 ,
  kLoopEnd = 8 , kCondCall = 9 , kReturn = 10 , kCondJmp = 11 ,
  kAlloc = 12 , kCondExecPredClean = 13 , kCondExecPredCleanEnd = 14 , kMarkVSFetchDone = 15
}
enum class  AddressingMode : u32 { kRelative = 0 , kAbsolute = 1 }
enum class  AllocType : u32 {
  kNone = 0 , kVsPosition = 1 , kVsInterpolators = 2 , kPsColors = 2 ,
  kMemory = 3
}
enum class  FetchOpcode : u32 {
  kVertexFetch = 0 , kTextureFetch = 1 , kGetTextureBorderColorFrac = 16 , kGetTextureComputedLOD = 17 ,
  kGetTextureGradients = 18 , kGetTextureWeights = 19 , kSetTextureLOD = 24 , kSetTextureGradientsHorz = 25 ,
  kSetTextureGradientsVert = 26
}
enum class  FetchDestinationSwizzle : u8 {
  kX = 0 , kY = 1 , kZ = 2 , kW = 3 ,
  k0 = 4 , k1 = 5 , kKeep = 7
}
enum  AluOpChangedState : u8 { kAluOpChangedStateNone = 0 , kAluOpChangedStateAddressRegister = 1 << 0 , kAluOpChangedStatePredicate = 1 << 1 , kAluOpChangedStatePixelKill = 1 << 2 }
enum class  AluScalarOpcode : u32 {
  kAdds = 0 , kAddsPrev = 1 , kMuls = 2 , kMulsPrev = 3 ,
  kMulsPrev2 = 4 , kMaxs = 5 , kMins = 6 , kSeqs = 7 ,
  kSgts = 8 , kSges = 9 , kSnes = 10 , kFrcs = 11 ,
  kTruncs = 12 , kFloors = 13 , kExp = 14 , kLogc = 15 ,
  kLog = 16 , kRcpc = 17 , kRcpf = 18 , kRcp = 19 ,
  kRsqc = 20 , kRsqf = 21 , kRsq = 22 , kMaxAs = 23 ,
  kMaxAsf = 24 , kSubs = 25 , kSubsPrev = 26 , kSetpEq = 27 ,
  kSetpNe = 28 , kSetpGt = 29 , kSetpGe = 30 , kSetpInv = 31 ,
  kSetpPop = 32 , kSetpClr = 33 , kSetpRstr = 34 , kKillsEq = 35 ,
  kKillsGt = 36 , kKillsGe = 37 , kKillsNe = 38 , kKillsOne = 39 ,
  kSqrt = 40 , kMulsc0 = 42 , kMulsc1 = 43 , kAddsc0 = 44 ,
  kAddsc1 = 45 , kSubsc0 = 46 , kSubsc1 = 47 , kSin = 48 ,
  kCos = 49 , kRetainPrev = 50
}
enum class  AluVectorOpcode : u32 {
  kAdd = 0 , kMul = 1 , kMax = 2 , kMin = 3 ,
  kSeq = 4 , kSgt = 5 , kSge = 6 , kSne = 7 ,
  kFrc = 8 , kTrunc = 9 , kFloor = 10 , kMad = 11 ,
  kCndEq = 12 , kCndGe = 13 , kCndGt = 14 , kDp4 = 15 ,
  kDp3 = 16 , kDp2Add = 17 , kCube = 18 , kMax4 = 19 ,
  kSetpEqPush = 20 , kSetpNePush = 21 , kSetpGtPush = 22 , kSetpGePush = 23 ,
  kKillEq = 24 , kKillGt = 25 , kKillGe = 26 , kKillNe = 27 ,
  kDst = 28 , kMaxA = 29
}
enum class  ExportRegister : u8 {
  Vertex shader interpolators 0 to 15, export registers 0 to 15. , kVSInterpolator0 = 0 , kVSInterpolator1 , kVSInterpolator2 ,
  kVSInterpolator3 , kVSInterpolator4 , kVSInterpolator5 , kVSInterpolator6 ,
  kVSInterpolator7 , kVSInterpolator8 , kVSInterpolator9 , kVSInterpolator10 ,
  kVSInterpolator11 , kVSInterpolator12 , kVSInterpolator13 , kVSInterpolator14 ,
  kVSInterpolator15 , kVSPosition = 62 , kVSPointSizeEdgeFlagKillVertex = 63 , Pixel shader color outputs for render targets 0 to 3. ,
  kPSColor0 = 0 , kPSColor1 , kPSColor2 , kPSColor3 ,
  kPSDepth = 61 , kExportAddress = 32 , Memory export values for texels[index+0] to[index+4], 1 register each. , kExportData0 = 33 ,
  kExportData1 , kExportData2 , kExportData3 , kExportData4
}

Functions

constexpr bool IsControlFlowOpcodeExec (ControlFlowOpcode opcode)
constexpr bool IsControlFlowOpcodeEnd (ControlFlowOpcode opcode)
constexpr bool HasControlFlowCondExecCleanPredicate (ControlFlowOpcode opcode)
void UnpackControlFlowInstructions (const u32 *dwords, ControlFlowInstruction *out_ab)
constexpr FetchDestinationSwizzle GetFetchDestinationComponentSwizzle (u32 swizzle, u32 component)
const AluScalarOpcodeTraits & GetAluScalarOpcodeTraits (AluScalarOpcode opcode)
const AluVectorOpcodeTraits & GetAluVectorOpcodeTraits (AluVectorOpcode opcode)
u32 GetAluVectorOpNeededSourceComponents (AluVectorOpcode vector_opcode, u32 src_index, u32 used_result_components)

Variables

const AluScalarOpcodeTraits kAluScalarOpcodeTraits [64]
const AluVectorOpcodeTraits kAluVectorOpcodeTraits [32]
constexpr u32 kMaxMemExportElementCount = 5

Detailed Description

Xenia : Xbox 360 Emulator Research Project *

Copyright 2022 Ben Vanik. All rights reserved. * Released under the BSD license - see LICENSE in the root for more details. *

Modified
Tom Clay, 2026 - Adapted for ReXGlue runtime Microcode instruction layouts. Bit fields use only 32 bit types because MSVC restarts packing when the alignment changes.

Enumeration Type Documentation

◆ AddressingMode

enum class rex::xenos::ucode::AddressingMode : u32
strong

Selects whether addressing is based on a0 or aL.

Enumerator
kRelative 

Indexing into register sets is based on aL, allowing forms like c[aL + 5].

kAbsolute 

Indexing into register sets is based on a0, allowing forms like c[a0 + 5].

◆ AllocType

enum class rex::xenos::ucode::AllocType : u32
strong
Enumerator
kNone 

Type of a shader before any alloc instruction sets one.

◆ AluOpChangedState

State changes of an ALU operation, used to analyze shaders and skip instructions that write nothing.

Enumerator
kAluOpChangedStateAddressRegister 

The operation writes the address register, set for maxas and maxasf.

kAluOpChangedStatePredicate 

The operation writes the predicate, set for the setp opcodes.

kAluOpChangedStatePixelKill 

The operation can kill the pixel, set for the kills opcodes.

◆ AluScalarOpcode

enum class rex::xenos::ucode::AluScalarOpcode : u32
strong

Scalar ALU opcodes.

The scalar and vector opcode descriptions follow these conventions.

  • All temporary registers are vec4s.
  • Most scalar operations read components a (W) and b (X) of the source register or of the float constant passed as the third operand of the co issued ALU instruction.
  • mulsc, addsc and subsc take a float constant as the left operand and a temporary register as the right operand. The two variants of each opcode are the same instruction, with 1 bit of the register index stored in the opcode field.
  • Scalar operations replicate the result into all masked components.
  • ps is the previous scalar result. It is not modified when the instruction fails its predication check.
  • Multiplication follows Direct3D 9 rules (as GCN v_*_legacy_f32), so a zero or denormal operand makes the product +0 and +0 * -0 is +0. NaN handling in min and max follows the same rules.
  • Multiply add is not fused. The DXBC translator emits separate mul and add, and the SPIR-V translator marks them NoContraction.
Enumerator
kAdds 

Floating Point Add.

adds/ADDs dest, src0.ab
dest.xyzw = src0.a + src0.b;
kAddsPrev 

Floating Point Add (with Previous).

adds_prev/ADD_PREVs dest, src0.a
dest.xyzw = src0.a + ps;
kMuls 

Floating Point Multiply.

muls/MULs dest, src0.ab
dest.xyzw = src0.a * src0.b;
kMulsPrev 

Floating Point Multiply (with Previous).

muls_prev/MUL_PREVs dest, src0.a
dest.xyzw = src0.a * ps;
kMulsPrev2 

Scalar Multiply Emulating LIT Operation.

muls_prev2/MUL_PREV2s dest, src0.ab
dest.xyzw =
ps == -FLT_MAX || !isfinite(ps) || !isfinite(src0.b) || src0.b <= 0
? -FLT_MAX : src0.a * ps;
kMaxs 

Floating Point Maximum.

maxs/MAXs dest, src0.ab
dest.xyzw = src0.a >= src0.b ? src0.a : src0.b;
kMins 

Floating Point Minimum.

mins/MINs dest, src0.ab
dest.xyzw = src0.a < src0.b ? src0.a : src0.b;
kSeqs 

Floating Point Set If Equal.

seqs/SETEs dest, src0.a
dest.xyzw = src0.a == 0.0 ? 1.0 : 0.0;
kSgts 

Floating Point Set If Greater Than.

sgts/SETGTs dest, src0.a
dest.xyzw = src0.a > 0.0 ? 1.0 : 0.0;
kSges 

Floating Point Set If Greater Than Or Equal.

sges/SETGTEs dest, src0.a
dest.xyzw = src0.a >= 0.0 ? 1.0 : 0.0;
kSnes 

Floating Point Set If Not Equal.

snes/SETNEs dest, src0.a
dest.xyzw = src0.a != 0.0 ? 1.0 : 0.0;
kFrcs 

Floating Point Fractional.

frcs/FRACs dest, src0.a
dest.xyzw = src0.a - floor(src0.a);
kTruncs 

Floating Point Truncate.

truncs/TRUNCs dest, src0.a
dest.xyzw = src0.a >= 0 ? floor(src0.a) : -floor(-src0.a);
kFloors 

Floating Point Floor.

floors/FLOORs dest, src0.a
dest.xyzw = floor(src0.a);
kExp 

Scalar Base 2 Exponent, IEEE.

exp/EXP_IEEE dest, src0.a
dest.xyzw = src0.a == 0.0 ? 1.0 : pow(2, src0.a);
kLogc 

Scalar Base 2 Log.

logc/LOG_CLAMP dest, src0.a
float t = src0.a == 1.0 ? 0.0 : log(src0.a) / log(2.0);
dest.xyzw = t == -INF ? -FLT_MAX : t;
Definition log_category.h:29
kLog 

Scalar Base 2 IEEE Log.

log/LOG_IEEE dest, src0.a
dest.xyzw = src0.a == 1.0 ? 0.0 : log(src0.a) / log(2.0);
kRcpc 

Scalar Reciprocal, Clamp to Maximum.

rcpc/RECIP_CLAMP dest, src0.a
float t = src0.a == 1.0 ? 1.0 : 1.0 / src0.a;
if (t == -INF) t = -FLT_MAX;
else if (t == INF) t = FLT_MAX;
dest.xyzw = t;
kRcpf 

Scalar Reciprocal, Clamp to Zero.

Mimics the fixed function pipeline.

rcpf/RECIP_FF dest, src0.a
float t = src0.a == 1.0 ? 1.0 : 1.0 / src0.a;
if (t == -INF) t = -0.0;
else if (t == INF) t = 0.0;
dest.xyzw = t;
kRcp 

Scalar Reciprocal, IEEE Approximation.

rcp/RECIP_IEEE dest, src0.a
dest.xyzw = src0.a == 1.0 ? 1.0 : 1.0 / src0.a;
kRsqc 

Scalar Reciprocal Square Root, Clamp to Maximum.

rsqc/RECIPSQ_CLAMP dest, src0.a
float t = src0.a == 1.0 ? 1.0 : 1.0 / sqrt(src0.a);
if (t == -INF) t = -FLT_MAX;
else if (t == INF) t = FLT_MAX;
dest.xyzw = t;
kRsqf 

Scalar Reciprocal Square Root, Clamp to Zero.

rsqf/RECIPSQ_FF dest, src0.a
float t = src0.a == 1.0 ? 1.0 : 1.0 / sqrt(src0.a);
if (t == -INF) t = -0.0;
else if (t == INF) t = 0.0;
dest.xyzw = t;
kRsq 

Scalar Reciprocal Square Root, IEEE Approximation.

rsq/RECIPSQ_IEEE dest, src0.a
dest.xyzw = src0.a == 1.0 ? 1.0 : 1.0 / sqrt(src0.a);
kMaxAs 

Floating Point Maximum with Copy To Integer in AR.

maxas dest, src0.ab
movas/MOVAs dest, src0.aa
a0 = (int)clamp(floor(src0.a + 0.5), -256.0, 255.0);
dest.xyzw = src0.a >= src0.b ? src0.a : src0.b;
kMaxAsf 

Floating Point Maximum with Copy Truncated To Integer in AR.

maxasf dest, src0.ab
movasf/MOVA_FLOORs dest, src0.aa
a0 = (int)clamp(floor(src0.a), -256.0, 255.0);
dest.xyzw = src0.a >= src0.b ? src0.a : src0.b;
kSubs 

Floating Point Subtract.

subs/SUBs dest, src0.ab
dest.xyzw = src0.a - src0.b;
kSubsPrev 

Floating Point Subtract (with Previous).

subs_prev/SUB_PREVs dest, src0.a
dest.xyzw = src0.a - ps;
kSetpEq 

Floating Point Predicate Set If Equal.

setp_eq/PRED_SETEs dest, src0.a
if (src0.a == 0.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
dest.xyzw = 1.0;
p0 = 0;
}
kSetpNe 

Floating Point Predicate Set If Not Equal.

setp_ne/PRED_SETNEs dest, src0.a
if (src0.a != 0.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
dest.xyzw = 1.0;
p0 = 0;
}
kSetpGt 

Floating Point Predicate Set If Greater Than.

setp_gt/PRED_SETGTs dest, src0.a
if (src0.a > 0.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
dest.xyzw = 1.0;
p0 = 0;
}
kSetpGe 

Floating Point Predicate Set If Greater Than Or Equal.

setp_ge/PRED_SETGTEs dest, src0.a
if (src0.a >= 0.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
dest.xyzw = 1.0;
p0 = 0;
}
kSetpInv 

Predicate Counter Invert.

setp_inv/PRED_SET_INVs dest, src0.a
if (src0.a == 1.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
if (src0.a == 0.0) {
dest.xyzw = 1.0;
} else {
dest.xyzw = src0.a;
}
p0 = 0;
}
kSetpPop 

Predicate Counter Pop.

setp_pop/PRED_SET_POPs dest, src0.a
if (src0.a - 1.0 <= 0.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
dest.xyzw = src0.a - 1.0;
p0 = 0;
}
kSetpClr 

Predicate Counter Clear.

setp_clr/PRED_SET_CLRs dest
dest.xyzw = FLT_MAX;
p0 = 0;
kSetpRstr 

Predicate Counter Restore.

setp_rstr/PRED_SET_RESTOREs dest, src0.a
if (src0.a == 0.0) {
dest.xyzw = 0.0;
p0 = 1;
} else {
dest.xyzw = src0.a;
p0 = 0;
}
kKillsEq 

Floating Point Pixel Kill If Equal.

kills_eq/KILLEs dest, src0.a
if (src0.a == 0.0) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillsGt 

Floating Point Pixel Kill If Greater Than.

kills_gt/KILLGTs dest, src0.a
if (src0.a > 0.0) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillsGe 

Floating Point Pixel Kill If Greater Than Or Equal.

kills_ge/KILLGTEs dest, src0.a
if (src0.a >= 0.0) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillsNe 

Floating Point Pixel Kill If Not Equal.

kills_ne/KILLNEs dest, src0.a
if (src0.a != 0.0) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillsOne 

Floating Point Pixel Kill If One.

kills_one/KILLONEs dest, src0.a
if (src0.a == 1.0) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kSqrt 

Scalar Square Root, IEEE Approximation.

sqrt/SQRT_IEEE dest, src0.a
dest.xyzw = sqrt(src0.a);
kMulsc0 

mulsc/MUL_CONST_0 dest, src0.a, src1.a

kMulsc1 

mulsc/MUL_CONST_1 dest, src0.a, src1.a

kAddsc0 

addsc/ADD_CONST_0 dest, src0.a, src1.a

kAddsc1 

addsc/ADD_CONST_1 dest, src0.a, src1.a

kSubsc0 

subsc/SUB_CONST_0 dest, src0.a, src1.a

kSubsc1 

subsc/SUB_CONST_1 dest, src0.a, src1.a

kSin 

Scalar Sin.

sin/SIN dest, src0.a
dest.xyzw = sin(src0.a);
kCos 

Scalar Cos.

cos/COS dest, src0.a
dest.xyzw = cos(src0.a);
kRetainPrev 

retain_prev/RETAIN_PREV dest

dest.xyzw = ps;

◆ AluVectorOpcode

enum class rex::xenos::ucode::AluVectorOpcode : u32
strong
Enumerator
kAdd 

Per Component Floating Point Add.

add/ADDv dest, src0, src1
dest.x = src0.x + src1.x;
dest.y = src0.y + src1.y;
dest.z = src0.z + src1.z;
dest.w = src0.w + src1.w;
kMul 

Per Component Floating Point Multiply.

mul/MULv dest, src0, src1
dest.x = src0.x * src1.x;
dest.y = src0.y * src1.y;
dest.z = src0.z * src1.z;
dest.w = src0.w * src1.w;
kMax 

Per Component Floating Point Maximum.

max/MAXv dest, src0, src1
dest.x = src0.x >= src1.x ? src0.x : src1.x;
dest.y = src0.y >= src1.y ? src0.y : src1.y;
dest.z = src0.z >= src1.z ? src0.z : src1.z;
dest.w = src0.w >= src1.w ? src0.w : src1.w;
kMin 

Per Component Floating Point Minimum.

min/MINv dest, src0, src1
dest.x = src0.x < src1.x ? src0.x : src1.x;
dest.y = src0.y < src1.y ? src0.y : src1.y;
dest.z = src0.z < src1.z ? src0.z : src1.z;
dest.w = src0.w < src1.w ? src0.w : src1.w;
kSeq 

Per Component Floating Point Set If Equal.

seq/SETEv dest, src0, src1
dest.x = src0.x == src1.x ? 1.0 : 0.0;
dest.y = src0.y == src1.y ? 1.0 : 0.0;
dest.z = src0.z == src1.z ? 1.0 : 0.0;
dest.w = src0.w == src1.w ? 1.0 : 0.0;
kSgt 

Per Component Floating Point Set If Greater Than.

sgt/SETGTv dest, src0, src1
dest.x = src0.x > src1.x ? 1.0 : 0.0;
dest.y = src0.y > src1.y ? 1.0 : 0.0;
dest.z = src0.z > src1.z ? 1.0 : 0.0;
dest.w = src0.w > src1.w ? 1.0 : 0.0;
kSge 

Per Component Floating Point Set If Greater Than Or Equal.

sge/SETGTEv dest, src0, src1
dest.x = src0.x >= src1.x ? 1.0 : 0.0;
dest.y = src0.y >= src1.y ? 1.0 : 0.0;
dest.z = src0.z >= src1.z ? 1.0 : 0.0;
dest.w = src0.w >= src1.w ? 1.0 : 0.0;
kSne 

Per Component Floating Point Set If Not Equal.

sne/SETNEv dest, src0, src1
dest.x = src0.x != src1.x ? 1.0 : 0.0;
dest.y = src0.y != src1.y ? 1.0 : 0.0;
dest.z = src0.z != src1.z ? 1.0 : 0.0;
dest.w = src0.w != src1.w ? 1.0 : 0.0;
kFrc 

Per Component Floating Point Fractional.

frc/FRACv dest, src0
dest.x = src0.x - floor(src0.x);
dest.y = src0.y - floor(src0.y);
dest.z = src0.z - floor(src0.z);
dest.w = src0.w - floor(src0.w);
kTrunc 

Per Component Floating Point Truncate.

trunc/TRUNCv dest, src0
dest.x = src0.x >= 0 ? floor(src0.x) : -floor(-src0.x);
dest.y = src0.y >= 0 ? floor(src0.y) : -floor(-src0.y);
dest.z = src0.z >= 0 ? floor(src0.z) : -floor(-src0.z);
dest.w = src0.w >= 0 ? floor(src0.w) : -floor(-src0.w);
kFloor 

Per Component Floating Point Floor.

floor/FLOORv dest, src0
dest.x = floor(src0.x);
dest.y = floor(src0.y);
dest.z = floor(src0.z);
dest.w = floor(src0.w);
kMad 

Per Component Floating Point Multiply Add.

mad/MULADDv dest, src0, src1, src2
dest.x = src0.x * src1.x + src2.x;
dest.y = src0.y * src1.y + src2.y;
dest.z = src0.z * src1.z + src2.z;
dest.w = src0.w * src1.w + src2.w;
kCndEq 

Per Component Floating Point Conditional Move If Equal.

cndeq/CNDEv dest, src0, src1, src2
dest.x = src0.x == 0.0 ? src1.x : src2.x;
dest.y = src0.y == 0.0 ? src1.y : src2.y;
dest.z = src0.z == 0.0 ? src1.z : src2.z;
dest.w = src0.w == 0.0 ? src1.w : src2.w;
kCndGe 

Per Component Floating Point Conditional Move If Greater Than Or Equal.

cndge/CNDGTEv dest, src0, src1, src2
dest.x = src0.x >= 0.0 ? src1.x : src2.x;
dest.y = src0.y >= 0.0 ? src1.y : src2.y;
dest.z = src0.z >= 0.0 ? src1.z : src2.z;
dest.w = src0.w >= 0.0 ? src1.w : src2.w;
kCndGt 

Per Component Floating Point Conditional Move If Greater Than.

cndgt/CNDGTv dest, src0, src1, src2
dest.x = src0.x > 0.0 ? src1.x : src2.x;
dest.y = src0.y > 0.0 ? src1.y : src2.y;
dest.z = src0.z > 0.0 ? src1.z : src2.z;
dest.w = src0.w > 0.0 ? src1.w : src2.w;
kDp4 

4 Element Dot Product.

dp4/DOT4v dest, src0, src1
dest.xyzw = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z +
src0.w * src1.w;
kDp3 

3 Element Dot Product.

dp3/DOT3v dest, src0, src1
dest.xyzw = src0.x * src1.x + src0.y * src1.y + src0.z * src1.z;
kDp2Add 

2 Element Dot Product and Add.

dp2add/DOT2ADDv dest, src0, src1, src2
dest.xyzw = src0.x * src1.x + src0.y * src1.y + src2.x;
kCube 

Cube Map.

cube/CUBEv dest, src0, src1
dest.x = T cube coordinate;
dest.y = S cube coordinate;
dest.z = 2.0 * major axis;
dest.w = FaceID;

The coordinates are computed as follows.

if (abs(z) >= abs(x) && abs(z) >= abs(y)) {
tc = -y;
sc = z < 0.0 ? -x : x;
ma = 2.0 * z;
id = z < 0.0 ? 5.0 : 4.0;
} else if (abs(y) >= abs(x)) {
tc = y < 0.0 ? -z : z;
sc = x;
ma = 2.0 * y;
id = y < 0.0 ? 3.0 : 2.0;
} else {
tc = -y;
sc = x < 0.0 ? z : -z;
ma = 2.0 * x;
id = x < 0.0 ? 1.0 : 0.0;
}

Expects src0.zzxy and src1.yxzz swizzles. FaceID is D3DCUBEMAP_FACES. Used like the following.

cube r0, source.zzxy, source.yxz
rcp r0.z, r0_abs.z
mad r0.xy, r0, r0.zzzw, 1.5f
tfetchCube r0, r0.yxw, tf0

The 1.5 constant keeps the face coordinate in [1.0, 2.0). To get texture array ST, subtract 1 from the XY inputs of tfetchCube.

kMax4 

4 Element Maximum.

max4/MAX4v dest, src0
if (src0.x > src0.y && src0.x > src0.z && src0.x > src0.w) {
dest.xyzw = src0.x;
} else if (src0.y > src0.z && src0.y > src0.w) {
dest.xyzw = src0.y;
} else if (src0.z > src0.w) {
dest.xyzw = src0.z;
} else {
dest.xyzw = src0.w;
}
kSetpEqPush 

Floating Point Predicate Counter Increment If Equal.

setp_eq_push/PRED_SETE_PUSHv dest, src0, src1
if (src0.w == 0.0 && src1.w == 0.0) {
p0 = 1;
} else {
p0 = 0;
}
if (src0.x == 0.0 && src1.x == 0.0) {
dest.xyzw = 0.0;
} else {
dest.xyzw = src0.x + 1.0;
}
kSetpNePush 

Floating Point Predicate Counter Increment If Not Equal.

setp_ne_push/PRED_SETNE_PUSHv dest, src0, src1
if (src0.w == 0.0 && src1.w != 0.0) {
p0 = 1;
} else {
p0 = 0;
}
if (src0.x == 0.0 && src1.x != 0.0) {
dest.xyzw = 0.0;
} else {
dest.xyzw = src0.x + 1.0;
}
kSetpGtPush 

Floating Point Predicate Counter Increment If Greater Than.

setp_gt_push/PRED_SETGT_PUSHv dest, src0, src1
if (src0.w == 0.0 && src1.w > 0.0) {
p0 = 1;
} else {
p0 = 0;
}
if (src0.x == 0.0 && src1.x > 0.0) {
dest.xyzw = 0.0;
} else {
dest.xyzw = src0.x + 1.0;
}
kSetpGePush 

Floating Point Predicate Counter Increment If Greater Than Or Equal.

setp_ge_push/PRED_SETGTE_PUSHv dest, src0, src1
if (src0.w == 0.0 && src1.w >= 0.0) {
p0 = 1;
} else {
p0 = 0;
}
if (src0.x == 0.0 && src1.x >= 0.0) {
dest.xyzw = 0.0;
} else {
dest.xyzw = src0.x + 1.0;
}
kKillEq 

Floating Point Pixel Kill If Equal.

kill_eq/KILLEv dest, src0, src1
if (src0.x == src1.x ||
src0.y == src1.y ||
src0.z == src1.z ||
src0.w == src1.w) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillGt 

Floating Point Pixel Kill If Greater Than.

kill_gt/KILLGTv dest, src0, src1
if (src0.x > src1.x ||
src0.y > src1.y ||
src0.z > src1.z ||
src0.w > src1.w) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillGe 

Floating Point Pixel Kill If Greater Than Or Equal.

kill_ge/KILLGTEv dest, src0, src1
if (src0.x >= src1.x ||
src0.y >= src1.y ||
src0.z >= src1.z ||
src0.w >= src1.w) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kKillNe 

Floating Point Pixel Kill If Not Equal.

kill_ne/KILLNEv dest, src0, src1
if (src0.x != src1.x ||
src0.y != src1.y ||
src0.z != src1.z ||
src0.w != src1.w) {
dest.xyzw = 1.0;
discard;
} else {
dest.xyzw = 0.0;
}
kDst 

dst/DSTv dest, src0, src1

dest.x = 1.0;
dest.y = src0.y * src1.y;
dest.z = src0.z;
dest.w = src1.w;
kMaxA 

Per Component Floating Point Maximum with Copy To Integer in AR.

This is a combined max + mova/MOVAv.

maxa dest, src0, src1
a0 = (int)clamp(floor(src0.w + 0.5), -256.0, 255.0);
dest.x = src0.x >= src1.x ? src0.x : src1.x;
dest.y = src0.y >= src1.y ? src0.y : src1.y;
dest.z = src0.z >= src1.z ? src0.z : src1.z;
dest.w = src0.w >= src1.w ? src0.w : src1.w;

◆ ControlFlowOpcode

enum class rex::xenos::ucode::ControlFlowOpcode : u32
strong
Enumerator
kExecEnd 

Executes fetch or ALU instructions, then ends execution.

kCondExec 

Executes conditionally on a bool constant. PredicateClean is false.

kCondExecEnd 

Executes conditionally on a bool constant, then ends execution. PredicateClean is false.

Execution ends only if the condition is met, unlike on R600 where it always ends.

kCondExecPred 

Executes conditionally on the current predicate.

The condition is the AND (for !p0) or OR (for p0) of the predicate of all active invocations in the 64 per sequencer, so the compiler predicates the instructions inside the exec.

kCondExecPredEnd 

Executes conditionally on the current predicate, then ends execution.

Execution ends only if the condition is met for any invocation, unlike on R600 where it always ends.

kLoopStart 

Starts a loop that must be terminated with kLoopEnd, with a depth of up to 4.

kLoopEnd 

Continues or breaks out of a loop. The iteration is incremented before the break checks.

kCondCall 

Conditionally calls a function, with a depth of up to 4.

kReturn 

Returns from the current function. No operation outside a function.

kCondExecPredClean 

Executes conditionally on a bool constant. PredicateClean is true.

Like kCondExec, which has no predicate clean field because the bool constant index occupies it.

kCondExecPredCleanEnd 

Executes conditionally on a bool constant, then ends execution. PredicateClean is true.

kMarkVSFetchDone 

Hints that no more vertex fetches will be performed.

◆ ExportRegister

enum class rex::xenos::ucode::ExportRegister : u8
strong

Destination of an export ALU instruction. Vertex and pixel shaders use different subsets.

Enumerator
Vertex shader interpolators 0 to 15, export registers 0 to 15. 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator0 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator1 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator2 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator3 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator4 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator5 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator6 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator7 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator8 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator9 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator10 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator11 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator12 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator13 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator14 

Vertex shader position output, mapped to the position storage target by the translator.

kVSInterpolator15 

Vertex shader position output, mapped to the position storage target by the translator.

kVSPosition 

Vertex shader position output, mapped to the position storage target by the translator.

kVSPointSizeEdgeFlagKillVertex 

Vertex shader miscellaneous export.

  • X is PSIZE, the point sprite size, clamped to PA_SU_POINT_MINMAX as a signed integer. Negative values, -0 and +0 give min, +Infinity and +NaN give max.
  • Y is EDGEFLAG for PrimitiveType::kPolygon wireframe or point drawing.
  • Z is the KILLVERTEX flag, set when bits 0 to 30 are not zero, which kills primitives based on PA_CL_CLIP_CNTL::VTX_KILL_OR.
Pixel shader color outputs for render targets 0 to 3. 

Exported in X.

kPSColor0 

Exported in X.

kPSColor1 

Exported in X.

kPSColor2 

Exported in X.

kPSColor3 

Exported in X.

kPSDepth 

Exported in X.

◆ FetchDestinationSwizzle

Fetch destination swizzle. Component indices are absolute, not component relative.

Enumerator
kKeep 

Keeps the current value of the destination register without writing.

◆ FetchOpcode

enum class rex::xenos::ucode::FetchOpcode : u32
strong
Enumerator
kTextureFetch 

Fetches a texture sample.

  • UnnormalizedTextureCoords applies only when all address modes are non wrapping and is required for 1D textures wider than 8192 texels.
  • LODBias is -4.0 to 3.9375 in 1/16 increments.
  • OffsetX, OffsetY and OffsetZ are -8.0 to 7.5 in 1/2 increments, applied in texels of the base level.
  • FetchValidOnly is true by default and must be false if the result is used for gradients.
  • Cube coordinates are SC, TC (1 to 2 when normalized) and face ID (0.0 to 5.0) from the cube vector ALU instruction, and register gradients are in cube space.

Cube maps are sampled through host cube views, so filtering crosses faces unless the Vulkan vulkan_cube_map_edge_filtering_off option is set.

kGetTextureBorderColorFrac 

Writes the fraction of border color blended in at the coordinates to X of the destination.

May take all the parameters that tfetch takes.

kGetTextureComputedLOD 

Writes the LOD of the pixel quad at the coordinates to X of the destination.

Valid only in pixel shaders. The valid parameters are UnnormalizedTextureCoords, AnisoFilter, VolMagFilter and VolMinFilter. The translators query the LOD with a linear mip filter, ignore the LOD bias and grad_exp_adjust_h/v, return the unclamped LOD and report an error for UseRegisterGradients and explicit LOD.

kGetTextureGradients 

Source is 2 component. XZ = ddx(source.xy), YW = ddy(source.xy).

The translators use coarse derivatives.

kGetTextureWeights 

Writes the weights used in a bilinear fetch.

  • X is the horizontal lerp factor.
  • Y is the vertical lerp factor.
  • Z is the depth lerp factor.
  • W is the mip lerp factor.

May take all the parameters that tfetch takes. The translators compute the factors from the base level size, ignore the LOD and write 0 to W. For cube maps they compute X and Y in SC/TC space from the face size.

kSetTextureLOD 

Source is 1 component.

kSetTextureGradientsHorz 

Source is 3 components.

kSetTextureGradientsVert 

Source is 3 components.

Function Documentation

◆ GetAluScalarOpcodeTraits()

const AluScalarOpcodeTraits & rex::xenos::ucode::GetAluScalarOpcodeTraits ( AluScalarOpcode opcode)
inline

Looks up the description of a scalar ALU opcode.

◆ GetAluVectorOpcodeTraits()

const AluVectorOpcodeTraits & rex::xenos::ucode::GetAluVectorOpcodeTraits ( AluVectorOpcode opcode)
inline

Looks up the description of a vector ALU opcode.

◆ GetAluVectorOpNeededSourceComponents()

u32 rex::xenos::ucode::GetAluVectorOpNeededSourceComponents ( AluVectorOpcode vector_opcode,
u32 src_index,
u32 used_result_components )
inline

Returns the components of a source operand that the instruction needs for the given write mask.

Parameters
src_index1 based source operand index.
used_result_componentsWrite mask of the used result components.

◆ GetFetchDestinationComponentSwizzle()

FetchDestinationSwizzle rex::xenos::ucode::GetFetchDestinationComponentSwizzle ( u32 swizzle,
u32 component )
constexpr

Extracts the swizzle of one destination component from a packed destination swizzle.

Parameters
swizzlePacked destination swizzle, 3 bits per component.
componentDestination component index, 0 for X to 3 for W.

◆ HasControlFlowCondExecCleanPredicate()

bool rex::xenos::ucode::HasControlFlowCondExecCleanPredicate ( ControlFlowOpcode opcode)
constexpr

Reports whether a conditional exec opcode has a clean predicate, see ControlFlowOpcode::kCondExecPredClean.

◆ IsControlFlowOpcodeEnd()

bool rex::xenos::ucode::IsControlFlowOpcodeEnd ( ControlFlowOpcode opcode)
constexpr

Reports whether a control flow opcode terminates the shader after executing.

◆ IsControlFlowOpcodeExec()

bool rex::xenos::ucode::IsControlFlowOpcodeExec ( ControlFlowOpcode opcode)
constexpr

Reports whether a control flow opcode executes ALU or fetch instructions.

◆ UnpackControlFlowInstructions()

void rex::xenos::ucode::UnpackControlFlowInstructions ( const u32 * dwords,
ControlFlowInstruction * out_ab )
inline

Splits 3 dwords of microcode into the two control flow instructions packed in them.

Parameters
dwords3 dwords holding the pair.
out_abReceives the two instructions.

Variable Documentation

◆ kAluScalarOpcodeTraits

const AluScalarOpcodeTraits rex::xenos::ucode::kAluScalarOpcodeTraits[64]
extern

Indexed by the 6 bit scalar opcode, 64 entries.

◆ kAluVectorOpcodeTraits

const AluVectorOpcodeTraits rex::xenos::ucode::kAluVectorOpcodeTraits[32]
extern

Indexed by the 5 bit vector opcode, 32 entries.

◆ kMaxMemExportElementCount

u32 rex::xenos::ucode::kMaxMemExportElementCount = 5
constexpr

Number of memory export data registers, eM0 to eM4 (kExportData0 to kExportData4).