Compare commits

..

No commits in common. "c8ae311e60f0a92dceeba978176b712e705fd941" and "f3f1969f4a9b336536f5fb23d246f7103c41e20d" have entirely different histories.

33 changed files with 828 additions and 84593 deletions

View File

@ -1,4 +0,0 @@
OUT TEX_SEM_WAIT
:
out[0].a = MAX src0.1 src0.1 ,
out[0].rgb = MAX src0.000 src0.000 ;

View File

@ -1,7 +0,0 @@
0x00078005,
0x08020080,
0x08020080,
0x00920490,
0x00c18003,
0x00000005,

View File

@ -1,58 +0,0 @@
-- CONST[0] = {theta1, theta2, 0.159155, 0.5}
-- CONST[1] = {6.283185, -3.141593, 0.2, 0.5}
-- ME_SIN and ME_COS clamp their inputs to [-π,+π] prior to the sin/cos
-- calculation.
--
-- This 3-instruction sequence remaps the range [-,+] to [-π,+π]
temp[0].xy = VE_MAD const[0].xy__ const[0].zz__ const[0].ww__ ;
temp[0].xy = VE_FRC temp[0].xy__ ;
temp[0].xy = VE_MAD temp[0].xy__ const[1].xx__ const[1].yy__ ;
-- sin and cos
temp[3].x = ME_SIN temp[0].___x ;
temp[3].y = ME_COS temp[0].___x ;
alt_temp[3].z = ME_SIN temp[0].___y ;
-- temp[3] now contains:
-- temp[3] = {sin(theta1), cos(theta1), sin(theta2), cos(theta2)}
-------------------------------------------------------------------------
-- first rotation: X-axis rotation:
-------------------------------------------------------------------------
-- y_ = (-z0 * st1)
-- z_ = ( z0 * ct1)
temp[1].yz = VE_MUL input[0]._-zz_ temp[3]._xy_ ,
alt_temp[3].w = ME_COS temp[0].y_ ;
-- x1 = (x0 * 1 + 0)
-- y1 = (y0 * ct1 + nz0st1)
-- z1 = (y0 * st1 + z0ct1)
temp[1].xyz = VE_MAD input[0].xyy_ temp[3].1yx_ temp[1].0yz_ ;
-------------------------------------------------------------------------
-- second rotation: Y-axis rotation:
-------------------------------------------------------------------------
-- x_ = (-z1 * st2)
-- z_ = ( z1 * ct2)
temp[2].xz = VE_MUL temp[1].-z_z_ alt_temp[3].z_w_ ;
-- x2 = (x1 * ct2 + nz1st2)
-- y2 = (y1 * 1 + 0)
-- z2 = (x1 * st2 + z1ct2)
temp[2].xyz = VE_MAD temp[1].xyx_ alt_temp[3].w1z_ temp[2].x0z_ ;
-------------------------------------------------------------------------
-- scale
-------------------------------------------------------------------------
temp[3].xyz = VE_MAD temp[2].xyz_ const[1].zzz_ const[1].00w_ ;
-------------------------------------------------------------------------
-- output
-------------------------------------------------------------------------
out[0].xyzw = VE_MUL temp[3].xyzz temp[3].11-z1 ;
out[1].xyzw = VE_ADD input[1].xyzw input[1].0000 ;

View File

@ -1,13 +0,0 @@
0x00300004, 0x01f90002, 0x01fa4002, 0x01fb6002,
0x00300006, 0x01f90000, 0x01ffe000, 0x01ffe000,
0x00300004, 0x01f90000, 0x01f80022, 0x01f92022,
0x00106050, 0x003fe000, 0x01ffe000, 0x01ffe000,
0x00206051, 0x003fe000, 0x01ffe000, 0x01ffe000,
0x00806451, 0x007fe000, 0x01ffe000, 0x01ffe000,
0x10602002, 0x05d2e001, 0x01c8e060, 0x10192004,
0x00702004, 0x01c90001, 0x01c1a060, 0x01d18020,
0x00504002, 0x03d74020, 0x01df4063, 0x01ffe063,
0x00704080, 0x01c10020, 0x01d56060, 0x01d40040,
0x00706004, 0x01d10040, 0x01d24022, 0x01dc8022,
0x00f00202, 0x00910060, 0x0955a060, 0x01ffe060,
0x00f02203, 0x00d10021, 0x01248021, 0x01ffe021,

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +0,0 @@
-- CONST[0] = {0.159155, 0.5, 6.283185, -3.141593}
-- CONST[1] = {theta1, theta2, 0.2, 0.5}
-- CONST[2] = {1.33333, 0, 0, 0}
-- each instruction is only allowed to use a single unique `const` address
--
-- instructions may use multiple `temp` addresses, so const[1] is moved to
-- temp[0]:
--
temp[0].xy = VE_ADD const[1].xy__ const[1].00__ ;
-- ME_SIN and ME_COS clamp their inputs to [-π,+π] prior to the sin/cos
-- calculation.
--
-- This 3-instruction sequence remaps the range [-,+] to [-π,+π]
temp[0].xy = VE_MAD temp[0].xy__ const[0].xx__ const[0].yy__ ;
temp[0].xy = VE_FRC temp[0].xy__ ;
temp[0].xy = VE_MAD temp[0].xy__ const[0].zz__ const[0].ww__ ;
-- sin and cos
temp[3].x = ME_SIN temp[0].___x ;
temp[3].y = ME_COS temp[0].___x ;
temp[3].z = ME_SIN temp[0].___y ;
temp[3].w = ME_COS temp[0].___y ;
-- temp[3] now contains:
-- temp[3] = {sin(theta1), cos(theta1), sin(theta2), cos(theta2)}
-------------------------------------------------------------------------
-- first rotation: X-axis rotation:
-------------------------------------------------------------------------
-- y_ = (-z0 * st1)
-- z_ = ( z0 * ct1)
temp[1].yz = VE_MUL input[0]._-zz_ temp[3]._xy_ ;
-- x1 = (x0 * 1 + 0)
-- y1 = (y0 * ct1 + nz0st1)
-- z1 = (y0 * st1 + z0ct1)
temp[1].xyz = VE_MAD input[0].xyy_ temp[3].1yx_ temp[1].0yz_ ;
-------------------------------------------------------------------------
-- second rotation: Y-axis rotation:
-------------------------------------------------------------------------
-- x_ = (-z1 * st2)
-- z_ = ( z1 * ct2)
temp[2].xz = VE_MUL temp[1].-z_z_ temp[3].z_w_ ;
-- x2 = (x1 * ct2 + nz1st2)
-- y2 = (y1 * 1 + 0)
-- z2 = (x1 * st2 + z1ct2)
temp[2].xyz = VE_MAD temp[1].xyx_ temp[3].w1z_ temp[2].x0z_ ;
-------------------------------------------------------------------------
-- scale
-------------------------------------------------------------------------
temp[3].xyz = VE_MAD temp[2].xyz_ const[1].zzz_ const[1].00w_ ;
temp[3].x = VE_MUL temp[3].x___ const[2].x___;
-------------------------------------------------------------------------
-- output
-------------------------------------------------------------------------
out[0].xyzw = VE_MUL temp[3].xyzz temp[3].11-z1 ;
out[1].xyzw = VE_ADD input[1].xyzw input[1].0000 ;

View File

@ -1,16 +0,0 @@
0x00300003, 0x01f90022, 0x01fc8022, 0x01ffe022,
0x00300004, 0x01f90000, 0x01f80002, 0x01f92002,
0x00300006, 0x01f90000, 0x01ffe000, 0x01ffe000,
0x00300004, 0x01f90000, 0x01fa4002, 0x01fb6002,
0x00106050, 0x003fe000, 0x01ffe000, 0x01ffe000,
0x00206051, 0x003fe000, 0x01ffe000, 0x01ffe000,
0x00406050, 0x007fe000, 0x01ffe000, 0x01ffe000,
0x00806051, 0x007fe000, 0x01ffe000, 0x01ffe000,
0x00602002, 0x05d2e001, 0x01c8e060, 0x01ffe060,
0x00702004, 0x01c90001, 0x01c1a060, 0x01d18020,
0x00504002, 0x03d74020, 0x01df4060, 0x01ffe060,
0x00704080, 0x01c10020, 0x01d56060, 0x01d40040,
0x00706004, 0x01d10040, 0x01d24022, 0x01dc8022,
0x00106002, 0x01ff0060, 0x01ff0042, 0x01ffe042,
0x00f02203, 0x00d10021, 0x01248021, 0x01ffe021,
0x00f00202, 0x00910060, 0x0955a060, 0x01ffe060,

View File

@ -50,3 +50,4 @@ src0.a = temp[0] ,
src0.rgb = temp[0] :
out[0].a = MAX src0.1 src0.1 ,
out[0].rgb = MAX src0.rgb src0.rgb ;
,

View File

@ -20,11 +20,11 @@
0x00000000,
0x00004000,
0x10320080,
0x08020080,
0x0802f400,
0x00000000,
0x0068c000,
0x04000000,
0x20000000,
0x00004000,
0x08020080,

View File

@ -1,7 +0,0 @@
TEX TEX_SEM_WAIT TEX_SEM_ACQUIRE
temp[0].argb = LD tex[0].rgba temp[0].rgaa ;
OUT TEX_SEM_WAIT
src0.a = temp[0], src0.rgb = temp[0] :
out[0].a = MAX src0.a src0.a ,
out[0].rgb = MAX src0.rgb src0.rgb ;

View File

@ -1,14 +0,0 @@
0x00007807,
0x02400000,
0xe400f400,
0x00000000,
0x00000000,
0x00000000,
0x00078005,
0x08020000,
0x08020000,
0x00440220,
0x0060c003,
0x00000005,

View File

@ -121,13 +121,43 @@ const face faces[] = {
static const int faces_length = (sizeof (faces)) / (sizeof (faces[0]));
static const uint32_t fragment_shader[] = {
#include "texture_cube.fs.inc"
#include "clear.fs.inc"
#include "../shader_examples/mesa/texture_cube.fs.txt"
// clear shader
US_CMN_INST__TYPE__US_INST_TYPE_OUT
| US_CMN_INST__TEX_SEM_WAIT(1)
| US_CMN_INST__RGB_OMASK__RGB
| US_CMN_INST__ALPHA_OMASK__A
, US_ALU_RGB_ADDR__ADDR0(128)
| US_ALU_RGB_ADDR__ADDR1(128)
| US_ALU_RGB_ADDR__ADDR2(128)
, US_ALU_ALPHA_ADDR__ADDR0(128)
| US_ALU_ALPHA_ADDR__ADDR1(128)
| US_ALU_ALPHA_ADDR__ADDR2(128)
, US_ALU_RGB_INST__RED_SWIZ_A__ZERO
| US_ALU_RGB_INST__GREEN_SWIZ_A__ZERO
| US_ALU_RGB_INST__BLUE_SWIZ_A__ZERO
| US_ALU_RGB_INST__RED_SWIZ_B__ZERO
| US_ALU_RGB_INST__GREEN_SWIZ_B__ZERO
| US_ALU_RGB_INST__BLUE_SWIZ_B__ZERO
| US_ALU_RGB_INST__OMOD(7)
| US_ALU_RGB_INST__TARGET__A
, US_ALU_ALPHA_INST__ALPHA_OP__OP_MAX
| US_ALU_ALPHA_INST__ALPHA_SWIZ_A__ONE
| US_ALU_ALPHA_INST__ALPHA_SWIZ_B__ONE
| US_ALU_ALPHA_INST__OMOD(7)
| US_ALU_ALPHA_INST__TARGET__A
, US_ALU_RGBA_INST__RGB_OP__OP_MAX
};
static const int fragment_shader_length = (sizeof (fragment_shader)) / (sizeof (fragment_shader[0]));
static const int fragment_shader_instructions = (fragment_shader_length / 6) - 1;
static const uint32_t vertex_shader[] = {
//#include "../shader_examples/mesa/texture_cube.vs.txt"
#include "cube_rotate.vs.inc"
#include "clear_nop.vs.inc"
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -347,26 +347,30 @@ int indirect_buffer()
// );
T0V(VAP_PROG_STREAM_CNTL_0
, VAP_PROG_STREAM_CNTL__DATA_TYPE_0__FLOAT_3
, VAP_PROG_STREAM_CNTL__DATA_TYPE_0(2)
| VAP_PROG_STREAM_CNTL__SKIP_DWORDS_0(0)
| VAP_PROG_STREAM_CNTL__DST_VEC_LOC_0(0)
| VAP_PROG_STREAM_CNTL__LAST_VEC_0(0)
| VAP_PROG_STREAM_CNTL__DATA_TYPE_1__FLOAT_3
| VAP_PROG_STREAM_CNTL__SIGNED_0(0)
| VAP_PROG_STREAM_CNTL__NORMALIZE_0(0)
| VAP_PROG_STREAM_CNTL__DATA_TYPE_1(2)
| VAP_PROG_STREAM_CNTL__SKIP_DWORDS_1(0)
| VAP_PROG_STREAM_CNTL__DST_VEC_LOC_1(1)
| VAP_PROG_STREAM_CNTL__LAST_VEC_1(1)
| VAP_PROG_STREAM_CNTL__SIGNED_1(0)
| VAP_PROG_STREAM_CNTL__NORMALIZE_1(0)
);
T0V(VAP_PROG_STREAM_CNTL_EXT_0
, VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_X_0__SELECT_X
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Y_0__SELECT_Y
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Z_0__SELECT_Z
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_W_0__SELECT_FP_ONE
| VAP_PROG_STREAM_CNTL_EXT__WRITE_ENA_0(0b1111)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_X_1__SELECT_X
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Y_1__SELECT_Y
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Z_1__SELECT_Z
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_W_1__SELECT_FP_ONE
| VAP_PROG_STREAM_CNTL_EXT__WRITE_ENA_1(0b1111)
, VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_X_0(0)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Y_0(1)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Z_0(2)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_W_0(5)
| VAP_PROG_STREAM_CNTL_EXT__WRITE_ENA_0(15)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_X_1(0)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Y_1(1)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_Z_1(2)
| VAP_PROG_STREAM_CNTL_EXT__SWIZZLE_SELECT_W_1(5)
| VAP_PROG_STREAM_CNTL_EXT__WRITE_ENA_1(15)
);
T0V(VAP_VSM_VTX_ASSM, 0x00000005); // undocumented

View File

@ -1,66 +0,0 @@
#pragma once
struct vec3 {
float x;
float y;
float z;
};
struct vec2 {
float x;
float y;
};
typedef struct vec3 vertex_position;
typedef struct vec2 vertex_texture;
typedef struct vec3 vertex_normal;
struct index_ptn {
uint16_t position;
uint16_t texture;
uint16_t normal;
};
union triangle {
struct {
struct index_ptn a;
struct index_ptn b;
struct index_ptn c;
};
struct index_ptn v[3];
};
union quadrilateral {
struct {
struct index_ptn a;
struct index_ptn b;
struct index_ptn c;
struct index_ptn d;
};
struct index_ptn v[4];
};
union line {
struct {
int a;
int b;
};
int v[2];
};
struct object {
const union triangle * triangle;
const union quadrilateral * quadrilateral;
const union line * line;
const int triangle_count;
const int quadrilateral_count;
const int line_count;
const int material;
};
struct model {
const vertex_position * position;
const vertex_texture * texture;
const vertex_normal * normal;
const struct object ** object;
const int object_count;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,115 +0,0 @@
from assembler.fs.keywords import KW
from assembler.fs.alu_validator import SrcAddrType, InstructionType
from assembler.fs.common_emitter import US_CMN_INST, US_ALU_RGB_ADDR, US_ALU_ALPHA_ADDR
from assembler.fs.common_emitter import US_ALU_RGB_INST, US_ALU_ALPHA_INST, US_ALU_RGBA_INST
def emit_alpha_op(code, alpha_op):
# dest
if alpha_op.dest.wmask is not None:
US_CMN_INST.ALPHA_WMASK(code, alpha_op.dest.wmask.value)
if alpha_op.dest.omask is not None:
US_CMN_INST.ALPHA_OMASK(code, alpha_op.dest.omask.value)
assert type(alpha_op.dest.addrd) is int
US_ALU_ALPHA_INST.ALPHA_ADDRD(code, alpha_op.dest.addrd)
# opcode
US_ALU_ALPHA_INST.ALPHA_OP(code, alpha_op.opcode.value)
# sels
srcs = [
US_ALU_ALPHA_INST.ALPHA_SEL_A,
US_ALU_ALPHA_INST.ALPHA_SEL_B,
US_ALU_RGBA_INST.ALPHA_SEL_C,
]
swizzles = [
[US_ALU_ALPHA_INST.ALPHA_SWIZ_A],
[US_ALU_ALPHA_INST.ALPHA_SWIZ_B],
[US_ALU_RGBA_INST.ALPHA_SWIZ_C],
]
mods = [
US_ALU_ALPHA_INST.ALPHA_MOD_A,
US_ALU_ALPHA_INST.ALPHA_MOD_B,
US_ALU_RGBA_INST.ALPHA_MOD_C,
]
for sel, src_func, swizzle_funcs, mod_func in zip(alpha_op.sels,
srcs, swizzles, mods):
src_func(code, sel.src.value)
assert len(sel.swizzle) == 1
assert len(swizzle_funcs) == 1
for swizzle_func, swizzle in zip(swizzle_funcs, sel.swizzle):
swizzle_func(code, swizzle.value)
mod_func(code, sel.mod.value)
def emit_rgb_op(code, rgb_op):
# dest
if rgb_op.dest.wmask is not None:
US_CMN_INST.RGB_WMASK(code, rgb_op.dest.wmask.value)
if rgb_op.dest.omask is not None:
US_CMN_INST.RGB_OMASK(code, rgb_op.dest.omask.value)
assert type(rgb_op.dest.addrd) is int
US_ALU_RGBA_INST.RGB_ADDRD(code, rgb_op.dest.addrd)
# opcode
US_ALU_RGBA_INST.RGB_OP(code, rgb_op.opcode.value)
# sels
srcs = [
US_ALU_RGB_INST.RGB_SEL_A,
US_ALU_RGB_INST.RGB_SEL_B,
US_ALU_RGBA_INST.RGB_SEL_C,
]
swizzles = [
[US_ALU_RGB_INST.RED_SWIZ_A, US_ALU_RGB_INST.GREEN_SWIZ_A, US_ALU_RGB_INST.BLUE_SWIZ_A],
[US_ALU_RGB_INST.RED_SWIZ_B, US_ALU_RGB_INST.GREEN_SWIZ_B, US_ALU_RGB_INST.BLUE_SWIZ_B],
[US_ALU_RGBA_INST.RED_SWIZ_C, US_ALU_RGBA_INST.GREEN_SWIZ_C, US_ALU_RGBA_INST.BLUE_SWIZ_C],
]
mods = [
US_ALU_RGB_INST.RGB_MOD_A,
US_ALU_RGB_INST.RGB_MOD_B,
US_ALU_RGBA_INST.RGB_MOD_C,
]
for sel, src_func, swizzle_funcs, mod_func in zip(rgb_op.sels,
srcs, swizzles, mods):
src_func(code, sel.src.value)
assert len(sel.swizzle) == 3
assert len(swizzle_funcs) == 3
for swizzle_func, swizzle in zip(swizzle_funcs, sel.swizzle):
swizzle_func(code, swizzle.value)
mod_func(code, sel.mod)
def emit_addr(code, addr):
srcs = [
(addr.alpha.src0 , US_ALU_ALPHA_ADDR.ADDR0 , US_ALU_ALPHA_ADDR.ADDR0_CONST),
(addr.alpha.src1 , US_ALU_ALPHA_ADDR.ADDR1 , US_ALU_ALPHA_ADDR.ADDR1_CONST),
(addr.alpha.src2 , US_ALU_ALPHA_ADDR.ADDR2 , US_ALU_ALPHA_ADDR.ADDR2_CONST),
(addr.rgb.src0 , US_ALU_RGB_ADDR.ADDR0 , US_ALU_RGB_ADDR.ADDR0_CONST),
(addr.rgb.src1 , US_ALU_RGB_ADDR.ADDR1 , US_ALU_RGB_ADDR.ADDR1_CONST),
(addr.rgb.src2 , US_ALU_RGB_ADDR.ADDR2 , US_ALU_RGB_ADDR.ADDR2_CONST),
]
for src, ADDR, ADDR_CONST in srcs:
if src is not None:
is_const = int(src.type is SrcAddrType.const)
is_float = int(src.type is SrcAddrType.float)
ADDR(code, (is_float << 7) | src.value)
ADDR_CONST(code, is_const)
else:
ADDR(code, (1 << 7) | 0)
if addr.alpha.srcp is not None:
US_ALU_ALPHA_ADDR.SRCP_OP(code, addr.alpha.srcp.value)
if addr.rgb.srcp is not None:
US_ALU_RGB_ADDR.SRCP_OP(code, addr.rgb.srcp.value)
def emit_instruction(code, ins):
US_CMN_INST.TYPE(code, InstructionType.OUT if KW.OUT in ins.tags else InstructionType.ALU)
US_CMN_INST.TEX_SEM_WAIT(code, int(KW.TEX_SEM_WAIT in ins.tags))
US_CMN_INST.LAST(code, int(KW.LAST in ins.tags))
US_CMN_INST.NOP(code, int(KW.NOP in ins.tags))
US_CMN_INST.ALU_WAIT(code, int(KW.ALU_WAIT in ins.tags))
emit_addr(code, ins.addr)
if ins.alpha_op is not None:
emit_alpha_op(code, ins.alpha_op)
if ins.rgb_op is not None:
emit_rgb_op(code, ins.rgb_op)

View File

@ -1,490 +0,0 @@
from pprint import pprint
from dataclasses import dataclass
from enum import Enum, IntEnum, auto
from collections import OrderedDict
from typing import Union
from assembler.fs.parser import ALUMod
from assembler.fs.keywords import _keyword_to_string, KW
from assembler.error import print_error
from assembler.validator import ValidatorError
from assembler.fs.common_validator import RGBMask, AlphaMask, InstructionType
from assembler.fs.common_validator import validate_identifier_number, validate_dest_keyword, keywords_to_string
class SrcAddrType(Enum):
temp = auto()
const = auto()
float = auto()
@dataclass
class SrcAddr:
type: SrcAddrType
value: int
class SrcMod(IntEnum):
nop = 0
neg = 1
abs = 2
nab = 3
class SrcpOp(IntEnum):
neg2 = 0
sub = 1
add = 2
neg = 3
@dataclass
class Addr:
src0: SrcAddr = None
src1: SrcAddr = None
src2: SrcAddr = None
srcp: SrcpOp = None
@dataclass
class AddrRGBAlpha:
alpha: Addr
rgb: Addr
class Unit(Enum):
alpha = auto()
rgb = auto()
class RGBOp(IntEnum):
MAD = 0
DP3 = 1
DP4 = 2
D2A = 3
MIN = 4
MAX = 5
CND = 7
CMP = 8
FRC = 9
SOP = 10
MDH = 11
MDV = 12
class AlphaOp(IntEnum):
MAD = 0
DP = 1
MIN = 2
MAX = 3
CND = 5
CMP = 6
FRC = 7
EX2 = 8
LN2 = 9
RCP = 10
RSQ = 11
SIN = 12
COS = 13
MDH = 14
MDV = 15
@dataclass
class RGBDest:
addrd: int
wmask: RGBMask
omask: RGBMask
@dataclass
class AlphaDest:
addrd: int
wmask: AlphaMask
omask: AlphaMask
class SwizzleSelSrc(IntEnum):
src0 = 0
src1 = 1
src2 = 2
srcp = 3
class Swizzle(IntEnum):
r = 0
g = 1
b = 2
a = 3
zero = 4
half = 5
one = 6
unused = 7
@dataclass
class SwizzleSel:
src: SwizzleSelSrc
swizzle: list[Swizzle]
mod: ALUMod
@dataclass
class AlphaOperation:
dest: AlphaDest
opcode: AlphaOp
sels: list[SwizzleSel]
@dataclass
class RGBOperation:
dest: RGBDest
opcode: RGBOp
sels: list[SwizzleSel]
@dataclass
class Instruction:
tags: set[Union[KW.OUT, KW.TEX_SEM_WAIT, KW.NOP]]
addr: Addr
alpha_op: AlphaOperation
rgb_op: RGBOperation
def validate_instruction_let_expressions(let_expressions):
src_keywords = [KW.SRC0, KW.SRC1, KW.SRC2, KW.SRCP]
src_keyword_strs = keywords_to_string(src_keywords)
rgb_alpha_swizzles = [b"rgb", b"a"]
addr_rgb_alpha = AddrRGBAlpha(Addr(), Addr())
def set_src_by_keyword(addr, keyword, value):
if keyword == KW.SRC0:
addr.src0 = value
elif keyword == KW.SRC1:
addr.src1 = value
elif keyword == KW.SRC2:
addr.src2 = value
elif keyword == KW.SRCP:
addr.srcp = value
else:
assert False, keyword
def src_value(expr, src):
if src in {KW.SRC0, KW.SRC1, KW.SRC2}:
keyword_to_src_addr_type = OrderedDict([
(KW.TEMP, SrcAddrType.temp),
(KW.CONST, SrcAddrType.const),
(KW.FLOAT, SrcAddrType.float),
])
src_addr_type_strs = keywords_to_string(keyword_to_src_addr_type.keys())
type_kw = expr.addr_keyword.keyword
if type_kw not in keyword_to_src_addr_type:
raise ValidatorError(f"invalid src addr type, expected one of {src_addr_type_strs}", expr.addr_keyword)
type = keyword_to_src_addr_type[type_kw]
value = validate_identifier_number(expr.addr_value_identifier)
if type is SrcAddrType.float:
if value >= 128:
raise ValidatorError(f"invalid float value", expr.addr_value_identifier)
elif type is SrcAddrType.temp:
if value >= 128:
raise ValidatorError(f"invalid temp value", expr.addr_value_identifier)
elif type is SrcAddrType.const:
if value >= 256:
raise ValidatorError(f"invalid const value", expr.addr_value_identifier)
else:
assert False, (id(type), id(SrcAddrType.float))
return SrcAddr(
type,
value,
)
elif src == KW.SRCP:
keyword_to_srcp_op = OrderedDict([
(KW.NEG2, SrcpOp.neg2),
(KW.SUB, SrcpOp.sub),
(KW.ADD, SrcpOp.add),
(KW.NEG, SrcpOp.neg),
])
srcp_op_strs = keywords_to_string(keyword_to_srcp_op.keys())
op = expr.addr_keyword.keyword
if op not in keyword_to_srcp_op:
raise ValidatorError(f"invalid srcp op, expected one of {srcp_op_strs}", expr.addr_keyword)
return keyword_to_srcp_op[op]
else:
assert False, src
sources = set()
for expr in let_expressions:
src = expr.src_keyword.keyword
if src not in src_keywords:
raise ValidatorError(f"invalid src keyword, expected one of {src_keyword_strs}", expr.src_keyword)
src_swizzle = expr.src_swizzle_identifier.lexeme.lower()
if src_swizzle not in rgb_alpha_swizzles:
raise ValidatorError(f"invalid src swizzle, expected one of {rgb_alpha_swizzles}", expr.src_swizzle_identifier)
source = (_keyword_to_string[src].lower(), src_swizzle)
if source in sources:
raise ValidatorError(f"duplicate source/swizzle in let expressions", expr.src_swizzle_identifier)
sources.add(source)
value = src_value(expr, src)
if src_swizzle == b"a":
set_src_by_keyword(addr_rgb_alpha.alpha, src, value)
elif src_swizzle == b"rgb":
set_src_by_keyword(addr_rgb_alpha.rgb, src, value)
else:
assert False, src_swizzle
return addr_rgb_alpha
def prevalidate_mask(dest_addr_swizzle, valid_masks):
# we don't know yet whether this is an Alpha operation or an RGB operation
swizzle_str = dest_addr_swizzle.swizzle_identifier.lexeme
if swizzle_str.lower() not in valid_masks:
raise ValidatorError(f"invalid write mask, expected one of {valid_masks}", dest_addr_swizzle.swizzle_identifier)
mask = swizzle_str.lower()
return mask
rgb_op_kws = OrderedDict([
(KW.MAD, RGBOp.MAD),
(KW.DP3, RGBOp.DP3),
(KW.DP4, RGBOp.DP4),
(KW.D2A, RGBOp.D2A),
(KW.MIN, RGBOp.MIN),
(KW.MAX, RGBOp.MAX),
(KW.CND, RGBOp.CND),
(KW.CMP, RGBOp.CMP),
(KW.FRC, RGBOp.FRC),
(KW.SOP, RGBOp.SOP),
(KW.MDH, RGBOp.MDH),
(KW.MDV, RGBOp.MDV)
])
alpha_op_kws = OrderedDict([
(KW.MAD, AlphaOp.MAD),
(KW.DP, AlphaOp.DP),
(KW.MIN, AlphaOp.MIN),
(KW.MAX, AlphaOp.MAX),
(KW.CND, AlphaOp.CND),
(KW.CMP, AlphaOp.CMP),
(KW.FRC, AlphaOp.FRC),
(KW.EX2, AlphaOp.EX2),
(KW.LN2, AlphaOp.LN2),
(KW.RCP, AlphaOp.RCP),
(KW.RSQ, AlphaOp.RSQ),
(KW.SIN, AlphaOp.SIN),
(KW.COS, AlphaOp.COS),
(KW.MDH, AlphaOp.MDH),
(KW.MDV, AlphaOp.MDV)
])
rgb_masks = OrderedDict([
(b"none" , RGBMask.NONE),
(b"r" , RGBMask.R),
(b"g" , RGBMask.G),
(b"rg" , RGBMask.RG),
(b"b" , RGBMask.B),
(b"rb" , RGBMask.RB),
(b"gb" , RGBMask.GB),
(b"rgb" , RGBMask.RGB),
])
alpha_masks = OrderedDict([
(b"none" , AlphaMask.NONE),
(b"a" , AlphaMask.A),
])
alpha_only_ops = set(alpha_op_kws.keys()) - set(rgb_op_kws.keys())
rgb_only_ops = set(rgb_op_kws.keys()) - set(alpha_op_kws.keys())
all_ops = set(rgb_op_kws.keys()) | set(alpha_op_kws.keys())
alpha_only_masks = set(alpha_masks.keys()) - set(rgb_masks.keys())
rgb_only_masks = set(rgb_masks.keys()) - set(alpha_masks.keys())
all_masks = set(rgb_masks.keys()) | set(alpha_masks.keys())
def infer_operation_units(operations):
if len(operations) > 2:
raise ValidatorError("too many operations in instruction", operations[-1].opcode_keyword)
units = [None, None]
for i, operation in enumerate(operations):
opcode = operation.opcode_keyword.keyword
if opcode not in all_ops:
raise ValidatorError(f"invalid opcode keyword, expected one of {all_ops}", operation.opcode_keyword)
if len(operation.dest_addr_swizzles) > 2:
raise ValidationError("too many destinations in instruction", operation.dest_addr_swizzles[-1])
masks = set(prevalidate_mask(dest_addr_swizzle, all_masks) for dest_addr_swizzle in operation.dest_addr_swizzles)
def infer_opcode_unit():
if opcode in alpha_only_ops:
return Unit.alpha
if opcode in rgb_only_ops:
return Unit.rgb
return None
def infer_mask_unit():
if any(mask in alpha_only_masks for mask in masks):
return Unit.alpha
if any(mask in rgb_only_masks for mask in masks):
return Unit.rgb
return None
opcode_unit = infer_opcode_unit()
mask_unit = infer_mask_unit()
if opcode_unit is not None and mask_unit is not None and opcode_unit != mask_unit:
raise ValidatorError(f"contradictory {mask_unit.name} write mask for {opcode_unit.name} opcode", operation.opcode_keyword)
units[i] = opcode_unit or mask_unit
if units[0] == units[1]:
raise ValidatorError(f"invalid duplicate use of {units[1].name} unit", operations[1].opcode_keyword)
other_unit = {
Unit.alpha: Unit.rgb,
Unit.rgb: Unit.alpha,
}
if units[0] is None:
units[0] = other_unit[units[1]]
if units[1] is None:
units[1] = other_unit[units[0]]
assert units[0] is not None
assert units[1] is not None
assert units[0] != units[1]
for i, operation in enumerate(operations):
yield units[i], operation
def validate_instruction_operation_dest(dest_addr_swizzles, mask_lookup, type_cls):
addrs = set()
wmask = None
omask = None
for dest_addr_swizzle in dest_addr_swizzles:
dest = validate_dest_keyword(dest_addr_swizzle.dest_keyword)
addr = validate_identifier_number(dest_addr_swizzle.addr_identifier)
mask = mask_lookup[dest_addr_swizzle.swizzle_identifier.lexeme.lower()]
addrs.add(addr)
if dest == KW.OUT:
omask = mask
elif dest == KW.TEMP:
wmask = mask
else:
assert False, dest
if len(addrs) > 1:
raise ValidatorError(f"too many destination addresses", operation.dest_addr_swizzles[-1].addr_identifier)
addrd, = addrs if addrs else [0]
return type_cls(
addrd=addrd,
wmask=wmask,
omask=omask
)
swizzle_sel_src_kws = OrderedDict([
(KW.SRC0, SwizzleSelSrc.src0),
(KW.SRC1, SwizzleSelSrc.src1),
(KW.SRC2, SwizzleSelSrc.src2),
(KW.SRCP, SwizzleSelSrc.srcp),
])
swizzle_kws = OrderedDict([
(ord("r"), Swizzle.r),
(ord("g"), Swizzle.g),
(ord("b"), Swizzle.b),
(ord("a"), Swizzle.a),
(ord("0"), Swizzle.zero),
(ord("h"), Swizzle.half),
(ord("1"), Swizzle.one),
(ord("_"), Swizzle.unused),
])
def validate_instruction_operation_sels(swizzle_sels, is_alpha):
if len(swizzle_sels) > 3:
raise ValidatorError("too many swizzle sels", swizzle_sels[-1].sel_keyword)
sels = []
for swizzle_sel in swizzle_sels:
if swizzle_sel.sel_keyword.keyword not in swizzle_sel_src_kws:
raise ValidatorError("invalid swizzle src", swizzle_sel.sel_keyword.keyword)
src = swizzle_sel_src_kws[swizzle_sel.sel_keyword.keyword]
swizzle_lexeme = swizzle_sel.swizzle_identifier.lexeme.lower()
swizzles_length = 1 if is_alpha else 3
if len(swizzle_lexeme) != swizzles_length:
raise ValidatorError("invalid swizzle length", swizzle_sel.swizzle_identifier)
if not all(c in swizzle_kws for c in swizzle_lexeme):
raise ValidatorError("invalid swizzle characters", swizzle_sel.swizzle_identifier)
swizzle = [
swizzle_kws[c] for c in swizzle_lexeme
]
mod = swizzle_sel.mod
sels.append(SwizzleSel(src, swizzle, mod))
return sels
def validate_alpha_instruction_operation(operation):
dest = validate_instruction_operation_dest(operation.dest_addr_swizzles,
mask_lookup=alpha_masks,
type_cls=AlphaDest)
opcode = alpha_op_kws[operation.opcode_keyword.keyword]
sels = validate_instruction_operation_sels(operation.swizzle_sels, is_alpha=True)
return AlphaOperation(
dest,
opcode,
sels
)
def validate_rgb_instruction_operation(operation):
dest = validate_instruction_operation_dest(operation.dest_addr_swizzles,
mask_lookup=rgb_masks,
type_cls=RGBDest)
opcode = rgb_op_kws[operation.opcode_keyword.keyword]
sels = validate_instruction_operation_sels(operation.swizzle_sels, is_alpha=False)
return RGBOperation(
dest,
opcode,
sels
)
def validate_instruction_operations(operations):
for unit, operation in infer_operation_units(operations):
if unit is Unit.alpha:
yield validate_alpha_instruction_operation(operation)
elif unit is Unit.rgb:
yield validate_rgb_instruction_operation(operation)
else:
assert False, unit
def validate_instruction(ins):
addr_rgb_alpha = validate_instruction_let_expressions(ins.let_expressions)
tags = set([tag.keyword for tag in ins.tags])
instruction = Instruction(
tags,
addr_rgb_alpha,
None,
None
)
for op in validate_instruction_operations(ins.operations):
if type(op) is RGBOperation:
instruction.rgb_op = op
elif type(op) is AlphaOperation:
instruction.alpha_op = op
else:
assert False, op
return instruction
if __name__ == "__main__":
from assembler.lexer import Lexer, LexerError
from assembler.fs.parser import Parser, ParserError
from assembler.fs.keywords import find_keyword
buf = b"""
src0.a = float(0), src0.rgb = temp[0] , srcp.a = neg :
out[0].none = temp[0].none = MAD src0.r src0.r src0.r ,
out[0].none = temp[0].r = DP3 src0.rg0 src0.rg0 ;
"""
lexer = Lexer(buf, find_keyword, emit_newlines=False, minus_is_token=True)
tokens = list(lexer.lex_tokens())
parser = Parser(tokens)
try:
ins_ast = parser.instruction()
pprint(validate_instruction(ins_ast))
except LexerError as e:
print_error(None, buf, e)
raise
except ParserError as e:
print_error(None, buf, e)
raise
except ValidatorError as e:
print_error(None, buf, e)
raise

View File

@ -1,69 +0,0 @@
from os import path
from functools import partial
import parse_bits
class BaseRegister:
def set(self, code, value, *, code_ix, descriptor):
if type(descriptor.bits) is int:
mask = 1
low = descriptor.bits
else:
high, low = descriptor.bits
assert high > low
mask_length = (high - low) + 1
mask = (1 << mask_length) - 1
code_value = code[code_ix]
assert (code_value >> low) & mask == 0
assert value & mask == value
code[code_ix] |= (value & mask) << low
_descriptor_indicies = {
"US_CMN_INST": 0,
"US_ALU_RGB_ADDR": 1,
"US_ALU_ALPHA_ADDR": 2,
"US_ALU_RGB_INST": 3,
"US_ALU_ALPHA_INST": 4,
"US_ALU_RGBA_INST": 5,
"US_TEX_INST": 1,
"US_TEX_ADDR": 2,
"US_TEX_ADDR_DXDY": 3,
"US_FC_INST": 2,
"US_FC_ADDR": 3,
}
def parse_register(register_name):
base = path.dirname(__file__)
filename = path.join(base, "..", "..", "bits", register_name.lower() + ".txt")
l = list(parse_bits.parse_file_fields(filename))
cls = type(register_name, (BaseRegister,), {})
instance = cls()
descriptors = list(parse_bits.aggregate(l))
code_ix = _descriptor_indicies[register_name]
for descriptor in descriptors:
setattr(instance, descriptor.field_name,
partial(instance.set, code_ix=code_ix, descriptor=descriptor))
func = getattr(instance, descriptor.field_name)
for pv_value, (pv_name, _) in descriptor.possible_values.items():
if pv_name is not None:
setattr(func, pv_name, pv_value)
assert getattr(instance, "descriptors", None) is None
instance.descriptors = descriptors
return instance
US_CMN_INST = parse_register("US_CMN_INST")
US_ALU_RGB_ADDR = parse_register("US_ALU_RGB_ADDR")
US_ALU_ALPHA_ADDR = parse_register("US_ALU_ALPHA_ADDR")
US_ALU_RGB_INST = parse_register("US_ALU_RGB_INST")
US_ALU_ALPHA_INST = parse_register("US_ALU_ALPHA_INST")
US_ALU_RGBA_INST = parse_register("US_ALU_RGBA_INST")
US_TEX_INST = parse_register("US_TEX_INST")
US_TEX_ADDR = parse_register("US_TEX_ADDR")
US_TEX_ADDR_DXDY = parse_register("US_TEX_ADDR_DXDY")
US_FC_INST = parse_register("US_FC_INST")
US_FC_ADDR = parse_register("US_FC_ADDR")

View File

@ -1,43 +0,0 @@
from enum import IntEnum
from collections import OrderedDict
from assembler.fs.keywords import _keyword_to_string
from assembler.fs.keywords import KW
from assembler.validator import ValidatorError
class InstructionType(IntEnum):
ALU = 0
OUT = 1
FC = 2
TEX = 3
class RGBMask(IntEnum):
NONE = 0
R = 1
G = 2
RG = 3
B = 4
RB = 5
GB = 6
RGB = 7
class AlphaMask(IntEnum):
NONE = 0
A = 1
def validate_identifier_number(token):
try:
return int(token.lexeme, 10)
except ValueError:
raise ValidatorError("invalid number", token)
def validate_dest_keyword(dest_keyword):
dest_keywords = [KW.OUT, KW.TEMP]
dest_keyword_strs = keywords_to_string(dest_keywords)
dest = dest_keyword.keyword
if dest not in dest_keywords:
raise ValidatorError(f"invalid dest keyword, expected one of {dest_keyword_strs}", dest_addr_swizzle.dest_keyword)
return dest
def keywords_to_string(keywords):
return [_keyword_to_string[s].decode("utf-8") for s in keywords]

View File

@ -1,12 +1,180 @@
from assembler.fs import alu_emitter
from assembler.fs import tex_emitter
from assembler.fs import alu_validator
from assembler.fs import tex_validator
from os import path
from pprint import pprint
from functools import partial
import parse_bits
from assembler.fs.validator import SrcAddrType
class BaseRegister:
def set(self, code, value, *, code_ix, descriptor):
if type(descriptor.bits) is int:
mask = 1
low = descriptor.bits
else:
high, low = descriptor.bits
assert high > low
mask_length = (high - low) + 1
mask = (1 << mask_length) - 1
code_value = code[code_ix]
assert (code_value >> low) & mask == 0
assert value & mask == value
code[code_ix] |= (value & mask) << low
_descriptor_indicies = {
"US_CMN_INST": 0,
"US_ALU_RGB_ADDR": 1,
"US_ALU_ALPHA_ADDR": 2,
"US_ALU_RGB_INST": 3,
"US_ALU_ALPHA_INST": 4,
"US_ALU_RGBA_INST": 5,
"US_TEX_INST": 1,
"US_TEX_ADDR": 2,
"US_TEX_ADDR_DXDY": 3,
"US_FC_INST": 2,
"US_FC_ADDR": 3,
}
def parse_register(register_name):
base = path.dirname(__file__)
filename = path.join(base, "..", "..", "bits", register_name.lower() + ".txt")
l = list(parse_bits.parse_file_fields(filename))
cls = type(register_name, (BaseRegister,), {})
instance = cls()
descriptors = list(parse_bits.aggregate(l))
code_ix = _descriptor_indicies[register_name]
for descriptor in descriptors:
setattr(instance, descriptor.field_name,
partial(instance.set, code_ix=code_ix, descriptor=descriptor))
func = getattr(instance, descriptor.field_name)
for pv_value, (pv_name, _) in descriptor.possible_values.items():
if pv_name is not None:
setattr(func, pv_name, pv_value)
assert getattr(instance, "descriptors", None) is None
instance.descriptors = descriptors
return instance
US_CMN_INST = parse_register("US_CMN_INST")
US_ALU_RGB_ADDR = parse_register("US_ALU_RGB_ADDR")
US_ALU_ALPHA_ADDR = parse_register("US_ALU_ALPHA_ADDR")
US_ALU_RGB_INST = parse_register("US_ALU_RGB_INST")
US_ALU_ALPHA_INST = parse_register("US_ALU_ALPHA_INST")
US_ALU_RGBA_INST = parse_register("US_ALU_RGBA_INST")
US_TEX_INST = parse_register("US_TEX_INST")
US_TEX_ADDR = parse_register("US_TEX_ADDR")
US_TEX_ADDR_DXDY = parse_register("US_TEX_ADDR_DXDY")
US_FC_INST = parse_register("US_FC_INST")
US_FC_ADDR = parse_register("US_FC_ADDR")
def emit_alpha_op(code, alpha_op):
# dest
if alpha_op.dest.wmask is not None:
US_CMN_INST.ALPHA_WMASK(code, alpha_op.dest.wmask.value)
if alpha_op.dest.omask is not None:
US_CMN_INST.ALPHA_OMASK(code, alpha_op.dest.omask.value)
assert type(alpha_op.dest.addrd) is int
US_ALU_ALPHA_INST.ALPHA_ADDRD(code, alpha_op.dest.addrd)
# opcode
US_ALU_ALPHA_INST.ALPHA_OP(code, alpha_op.opcode.value)
# sels
srcs = [
US_ALU_ALPHA_INST.ALPHA_SEL_A,
US_ALU_ALPHA_INST.ALPHA_SEL_B,
US_ALU_RGBA_INST.ALPHA_SEL_C,
]
swizzles = [
[US_ALU_ALPHA_INST.ALPHA_SWIZ_A],
[US_ALU_ALPHA_INST.ALPHA_SWIZ_B],
[US_ALU_RGBA_INST.ALPHA_SWIZ_C],
]
mods = [
US_ALU_ALPHA_INST.ALPHA_MOD_A,
US_ALU_ALPHA_INST.ALPHA_MOD_B,
US_ALU_RGBA_INST.ALPHA_MOD_C,
]
for sel, src_func, swizzle_funcs, mod_func in zip(alpha_op.sels,
srcs, swizzles, mods):
src_func(code, sel.src.value)
assert len(sel.swizzle) == 1
assert len(swizzle_funcs) == 1
for swizzle_func, swizzle in zip(swizzle_funcs, sel.swizzle):
swizzle_func(code, swizzle.value)
mod_func(code, sel.mod.value)
def emit_rgb_op(code, rgb_op):
# dest
if rgb_op.dest.wmask is not None:
US_CMN_INST.RGB_WMASK(code, rgb_op.dest.wmask.value)
if rgb_op.dest.omask is not None:
US_CMN_INST.RGB_OMASK(code, rgb_op.dest.omask.value)
assert type(rgb_op.dest.addrd) is int
US_ALU_RGBA_INST.RGB_ADDRD(code, rgb_op.dest.addrd)
# opcode
US_ALU_RGBA_INST.RGB_OP(code, rgb_op.opcode.value)
# sels
srcs = [
US_ALU_RGB_INST.RGB_SEL_A,
US_ALU_RGB_INST.RGB_SEL_B,
US_ALU_RGBA_INST.RGB_SEL_C,
]
swizzles = [
[US_ALU_RGB_INST.RED_SWIZ_A, US_ALU_RGB_INST.GREEN_SWIZ_A, US_ALU_RGB_INST.BLUE_SWIZ_A],
[US_ALU_RGB_INST.RED_SWIZ_B, US_ALU_RGB_INST.GREEN_SWIZ_B, US_ALU_RGB_INST.BLUE_SWIZ_B],
[US_ALU_RGBA_INST.RED_SWIZ_C, US_ALU_RGBA_INST.GREEN_SWIZ_C, US_ALU_RGBA_INST.BLUE_SWIZ_C],
]
mods = [
US_ALU_RGB_INST.RGB_MOD_A,
US_ALU_RGB_INST.RGB_MOD_B,
US_ALU_RGBA_INST.RGB_MOD_C,
]
for sel, src_func, swizzle_funcs, mod_func in zip(rgb_op.sels,
srcs, swizzles, mods):
src_func(code, sel.src.value)
assert len(sel.swizzle) == 3
assert len(swizzle_funcs) == 3
for swizzle_func, swizzle in zip(swizzle_funcs, sel.swizzle):
swizzle_func(code, swizzle.value)
mod_func(code, sel.mod)
def emit_addr(code, addr):
srcs = [
(addr.alpha.src0 , US_ALU_ALPHA_ADDR.ADDR0 , US_ALU_ALPHA_ADDR.ADDR0_CONST),
(addr.alpha.src1 , US_ALU_ALPHA_ADDR.ADDR1 , US_ALU_ALPHA_ADDR.ADDR1_CONST),
(addr.alpha.src2 , US_ALU_ALPHA_ADDR.ADDR2 , US_ALU_ALPHA_ADDR.ADDR2_CONST),
(addr.rgb.src0 , US_ALU_RGB_ADDR.ADDR0 , US_ALU_RGB_ADDR.ADDR0_CONST),
(addr.rgb.src1 , US_ALU_RGB_ADDR.ADDR1 , US_ALU_RGB_ADDR.ADDR1_CONST),
(addr.rgb.src2 , US_ALU_RGB_ADDR.ADDR2 , US_ALU_RGB_ADDR.ADDR2_CONST),
]
for src, ADDR, ADDR_CONST in srcs:
if src is not None:
is_const = int(src.type is SrcAddrType.const)
is_float = int(src.type is SrcAddrType.float)
ADDR(code, (is_float << 7) | src.value)
ADDR_CONST(code, is_const)
else:
ADDR(code, (1 << 7) | 0)
if addr.alpha.srcp is not None:
US_ALU_ALPHA_ADDR.SRCP_OP(code, addr.alpha.srcp.value)
if addr.rgb.srcp is not None:
US_ALU_RGB_ADDR.SRCP_OP(code, addr.rgb.srcp.value)
def emit_instruction(code, ins):
if type(ins) is alu_validator.Instruction:
return alu_emitter.emit_instruction(code, ins)
elif type(ins) is tex_validator.Instruction:
return tex_emitter.emit_instruction(code, ins)
else:
assert False, type(ins)
US_CMN_INST.TYPE(code, ins.type.value)
US_CMN_INST.TEX_SEM_WAIT(code, int(ins.tex_sem_wait))
US_CMN_INST.NOP(code, int(ins.nop))
emit_addr(code, ins.addr)
if ins.alpha_op is not None:
emit_alpha_op(code, ins.alpha_op)
if ins.rgb_op is not None:
emit_rgb_op(code, ins.rgb_op)

View File

@ -41,18 +41,6 @@ class KW(Enum):
# modifiers
NOP = auto()
TEX_SEM_WAIT = auto()
TEX = auto()
TEX_SEM_ACQUIRE = auto()
ALU_WAIT = auto()
LAST = auto()
# tex opcodes
LD = auto()
TEXKILL = auto()
PROJ = auto()
LODBIAS = auto()
LOD = auto()
DXDY = auto()
_string_to_keyword = {
b"CMP": KW.CMP,
@ -88,16 +76,6 @@ _string_to_keyword = {
b"NEG": KW.NEG,
b"NOP": KW.NOP,
b"TEX_SEM_WAIT": KW.TEX_SEM_WAIT,
b"TEX": KW.TEX,
b"TEX_SEM_ACQUIRE": KW.TEX_SEM_ACQUIRE,
b"ALU_WAIT": KW.ALU_WAIT,
b"LAST": KW.LAST,
b"LD": KW.LD,
b"TEXKILL": KW.TEXKILL,
b"PROJ": KW.PROJ,
b"LODBIAS": KW.LODBIAS,
b"LOD": KW.LOD,
b"DXDY": KW.DXDY,
}
_keyword_to_string = {v:k for k,v in _string_to_keyword.items()}

View File

@ -7,14 +7,14 @@ from assembler.lexer import TT, Token
from assembler.fs.keywords import KW, find_keyword
from assembler.error import print_error
class ALUMod(IntEnum):
class Mod(IntEnum):
nop = 0
neg = 1
abs = 2
nab = 3
@dataclass
class ALULetExpression:
class LetExpression:
src_keyword: Token
src_swizzle_identifier: Token
addr_keyword: Token
@ -27,39 +27,27 @@ class DestAddrSwizzle:
swizzle_identifier: Token
@dataclass
class ALUSwizzleSel:
class SwizzleSel:
sel_keyword: Token
swizzle_identifier: Token
mod: ALUMod
mod: Mod
@dataclass
class ALUOperation:
class Operation:
dest_addr_swizzles: list[DestAddrSwizzle]
opcode_keyword: Token
swizzle_sels: list[ALUSwizzleSel]
swizzle_sels: list[SwizzleSel]
@dataclass
class ALUInstruction:
tags: set[Token]
let_expressions: list[ALULetExpression]
operations: list[ALUOperation]
@dataclass
class TEXOperation:
dest_addr_swizzles: list[DestAddrSwizzle]
opcode_keyword: Token
tex_id_identifier: Token
tex_dst_swizzle_identifier: Token
tex_src_address_identifier: Token
tex_src_swizzle_identifier: Token
@dataclass
class TEXInstruction:
tags: set[Token]
operation: TEXOperation
class Instruction:
out: bool
tex_sem_wait: bool
nop: bool
let_expressions: list[LetExpression]
operations: list[Operation]
class Parser(BaseParser):
def alu_let_expression(self):
def let_expression(self):
src_keyword = self.consume(TT.keyword, "expected src keyword")
self.consume(TT.dot, "expected dot")
src_swizzle_identifier = self.consume(TT.identifier, "expected src swizzle identifier")
@ -81,7 +69,7 @@ class Parser(BaseParser):
else:
self.consume(TT.right_square, "expected right square")
return ALULetExpression(
return LetExpression(
src_keyword,
src_swizzle_identifier,
addr_keyword,
@ -102,7 +90,7 @@ class Parser(BaseParser):
swizzle_identifier,
)
def alu_is_opcode(self):
def is_opcode(self):
opcode_keywords = {
KW.CMP, KW.CND, KW.COS, KW.D2A,
KW.DP , KW.DP3, KW.DP4, KW.EX2,
@ -115,21 +103,21 @@ class Parser(BaseParser):
return token.keyword in opcode_keywords
return False
def alu_is_neg(self):
def is_neg(self):
result = self.match(TT.minus)
if result:
self.advance()
return result
def alu_is_abs(self):
def is_abs(self):
result = self.match(TT.bar)
if result:
self.advance()
return result
def alu_swizzle_sel(self):
neg = self.alu_is_neg()
abs = self.alu_is_abs()
def swizzle_sel(self):
neg = self.is_neg()
abs = self.is_abs()
sel_keyword = self.consume(TT.keyword, "expected sel keyword")
self.consume(TT.dot, "expected dot")
@ -140,51 +128,52 @@ class Parser(BaseParser):
mod_table = {
# (neg, abs)
(False, False): ALUMod.nop,
(False, True): ALUMod.abs,
(True, False): ALUMod.neg,
(True, True): ALUMod.nab,
(False, False): Mod.nop,
(False, True): Mod.abs,
(True, False): Mod.neg,
(True, True): Mod.nab,
}
mod = mod_table[(neg, abs)]
return ALUSwizzleSel(
return SwizzleSel(
sel_keyword,
swizzle_identifier,
mod,
)
def alu_operation(self):
def operation(self):
dest_addr_swizzles = []
while not self.alu_is_opcode():
while not self.is_opcode():
dest_addr_swizzles.append(self.dest_addr_swizzle())
opcode_keyword = self.consume(TT.keyword, "expected opcode keyword")
swizzle_sels = []
while not (self.match(TT.comma) or self.match(TT.semicolon)):
swizzle_sels.append(self.alu_swizzle_sel())
swizzle_sels.append(self.swizzle_sel())
return ALUOperation(
return Operation(
dest_addr_swizzles,
opcode_keyword,
swizzle_sels
)
def alu_instruction(self, out: bool):
tags = list()
tag_keywords = set([KW.OUT, KW.TEX_SEM_WAIT, KW.NOP, KW.LAST, KW.ALU_WAIT])
while True:
if self.match(TT.keyword):
token = self.peek()
if token.keyword in tag_keywords:
self.advance()
tag_keywords.remove(token.keyword)
tags.append(token)
continue
break
def instruction(self):
out = False
if self.match_keyword(KW.OUT):
self.advance()
out = True
tex_sem_wait = False
if self.match_keyword(KW.TEX_SEM_WAIT):
self.advance()
tex_sem_wait = True
nop = False
if self.match_keyword(KW.NOP):
self.advance()
nop = True
let_expressions = []
while not self.match(TT.colon):
let_expressions.append(self.alu_let_expression())
let_expressions.append(self.let_expression())
if not self.match(TT.colon):
self.consume(TT.comma, "expected comma")
@ -192,87 +181,20 @@ class Parser(BaseParser):
operations = []
while not self.match(TT.semicolon):
operations.append(self.alu_operation())
operations.append(self.operation())
if not self.match(TT.semicolon):
self.consume(TT.comma, "expected comma")
self.consume(TT.semicolon, "expected semicolon")
return ALUInstruction(
tags,
return Instruction(
out,
tex_sem_wait,
nop,
let_expressions,
operations,
)
def tex_is_opcode(self):
opcode_keywords = {
KW.NOP, KW.LD, KW.TEXKILL, KW.PROJ,
KW.LODBIAS, KW.LOD, KW.DXDY,
}
if self.match(TT.keyword):
token = self.peek()
return token.keyword in opcode_keywords
return False
def tex_operation(self):
dest_addr_swizzles = []
while not self.tex_is_opcode():
dest_addr_swizzles.append(self.dest_addr_swizzle())
opcode_keyword = self.consume(TT.keyword, "expected tex opcode keyword")
self.consume_keyword(KW.TEX, "expected tex keyword")
self.consume(TT.left_square, "expected left square")
tex_id_identifier = self.consume(TT.identifier, "expected tex ID identifier")
self.consume(TT.right_square, "expected left square")
self.consume(TT.dot, "expected dot")
tex_dst_swizzle_identifier = self.consume(TT.identifier, "expected src swizzle")
self.consume_keyword(KW.TEMP, "expected temp keyword")
self.consume(TT.left_square, "expected left square")
tex_src_address_identifier = self.consume(TT.identifier, "expected tex address identifier")
self.consume(TT.right_square, "expected left square")
self.consume(TT.dot, "expected dot")
tex_src_swizzle_identifier = self.consume(TT.identifier, "expected dst swizzle")
return TEXOperation(
dest_addr_swizzles,
opcode_keyword,
tex_id_identifier,
tex_dst_swizzle_identifier,
tex_src_address_identifier,
tex_src_swizzle_identifier,
)
def tex_instruction(self):
tags = list()
tag_keywords = set([KW.OUT, KW.TEX_SEM_WAIT, KW.TEX_SEM_ACQUIRE, KW.NOP, KW.ALU_WAIT, KW.LAST])
while True:
if self.match(TT.keyword):
token = self.peek()
if token.keyword in tag_keywords:
self.advance()
tag_keywords.remove(token.keyword)
tags.append(token)
continue
break
operation = self.tex_operation()
self.consume(TT.semicolon, "expected semicolon")
return TEXInstruction(
tags,
operation,
)
def instruction(self):
out = False
if self.match_keyword(KW.TEX):
self.advance()
return self.tex_instruction()
else:
return self.alu_instruction(out=False)
def instructions(self):
while not self.match(TT.eof):
yield self.instruction()

View File

@ -1,36 +0,0 @@
from assembler.fs.common_validator import InstructionType
from assembler.fs.keywords import KW
from assembler.fs.common_emitter import US_CMN_INST
from assembler.fs.common_emitter import US_TEX_INST
from assembler.fs.common_emitter import US_TEX_ADDR
from assembler.fs.common_emitter import US_TEX_ADDR_DXDY
def emit_instruction(code, ins):
US_CMN_INST.TYPE(code, InstructionType.TEX)
US_CMN_INST.TEX_SEM_WAIT(code, int(KW.TEX_SEM_WAIT in ins.tags))
US_CMN_INST.LAST(code, int(KW.LAST in ins.tags))
US_CMN_INST.NOP(code, int(KW.NOP in ins.tags))
US_CMN_INST.ALU_WAIT(code, int(KW.ALU_WAIT in ins.tags))
US_CMN_INST.RGB_WMASK(code, ins.masks.rgb_wmask.value)
US_CMN_INST.ALPHA_WMASK(code, ins.masks.alpha_wmask.value)
US_CMN_INST.RGB_OMASK(code, ins.masks.rgb_omask.value)
US_CMN_INST.ALPHA_OMASK(code, ins.masks.alpha_omask.value)
US_TEX_INST.TEX_ID(code, ins.tex_id)
US_TEX_INST.INST(code, ins.opcode.value)
US_TEX_INST.TEX_SEM_ACQUIRE(code, int(KW.TEX_SEM_ACQUIRE in ins.tags))
US_TEX_INST.IGNORE_UNCOVERED(code, 0)
US_TEX_INST.UNSCALED(code, 0)
US_TEX_ADDR.SRC_ADDR(code, ins.src_addr)
US_TEX_ADDR.SRC_S_SWIZ(code, ins.src_swizzle[0].value)
US_TEX_ADDR.SRC_T_SWIZ(code, ins.src_swizzle[1].value)
US_TEX_ADDR.SRC_R_SWIZ(code, ins.src_swizzle[2].value)
US_TEX_ADDR.SRC_Q_SWIZ(code, ins.src_swizzle[3].value)
US_TEX_ADDR.DST_ADDR(code, ins.dst_addr)
US_TEX_ADDR.DST_R_SWIZ(code, ins.dst_swizzle[0].value)
US_TEX_ADDR.DST_G_SWIZ(code, ins.dst_swizzle[1].value)
US_TEX_ADDR.DST_B_SWIZ(code, ins.dst_swizzle[2].value)
US_TEX_ADDR.DST_A_SWIZ(code, ins.dst_swizzle[3].value)

View File

@ -1,159 +0,0 @@
from dataclasses import dataclass
from typing import Union
from collections import OrderedDict
from enum import IntEnum
from assembler.validator import ValidatorError
from assembler.fs import parser
from assembler.fs.keywords import KW
from assembler.fs.common_validator import RGBMask, AlphaMask
from assembler.fs.common_validator import validate_identifier_number, validate_dest_keyword
from assembler.fs.common_validator import keywords_to_string
@dataclass
class Masks:
alpha_wmask: AlphaMask
rgb_wmask: RGBMask
alpha_omask: AlphaMask
rgb_omask: RGBMask
class TEXOp(IntEnum):
NOP = 0
LD = 1
TEXKILL = 2
PROJ = 3
LODBIAS = 4
LOD = 5
DXDY = 6
class Swizzle(IntEnum):
R = 0
G = 1
B = 2
A = 3
@dataclass
class Instruction:
tags: set[Union[KW.TEX_SEM_WAIT, KW.TEX_SEM_ACQUIRE, KW.OUT]]
masks: Masks
opcode: TEXOp
tex_id: int
src_addr: int
src_swizzle: tuple[Swizzle, Swizzle, Swizzle, Swizzle]
dst_addr: int
dst_swizzle: tuple[Swizzle, Swizzle, Swizzle, Swizzle]
def validate_swizzle(token):
if len(token.lexeme) != 4:
raise ValidatorError("invalid swizzle identifier", token)
swizzles = OrderedDict([
(ord(b"r"), Swizzle.R),
(ord(b"g"), Swizzle.G),
(ord(b"b"), Swizzle.B),
(ord(b"a"), Swizzle.A),
])
if not all(c in swizzles for c in token.lexeme):
raise ValidatorError("invalid swizzle identifier", token)
return tuple(swizzles[c] for c in token.lexeme)
def validate_mask_swizzle(token) -> tuple[AlphaMask, RGBMask]:
argb_masks = OrderedDict([
(b"none" , (AlphaMask.NONE, RGBMask.NONE)),
(b"r" , (AlphaMask.NONE, RGBMask.R)),
(b"g" , (AlphaMask.NONE, RGBMask.G)),
(b"rg" , (AlphaMask.NONE, RGBMask.RG)),
(b"b" , (AlphaMask.NONE, RGBMask.B)),
(b"rb" , (AlphaMask.NONE, RGBMask.RB)),
(b"gb" , (AlphaMask.NONE, RGBMask.GB)),
(b"rgb" , (AlphaMask.NONE, RGBMask.RGB)),
(b"ar" , (AlphaMask.A, RGBMask.R)),
(b"ag" , (AlphaMask.A, RGBMask.G)),
(b"arg" , (AlphaMask.A, RGBMask.RG)),
(b"ab" , (AlphaMask.A, RGBMask.B)),
(b"arb" , (AlphaMask.A, RGBMask.RB)),
(b"agb" , (AlphaMask.A, RGBMask.GB)),
(b"argb" , (AlphaMask.A, RGBMask.RGB)),
])
if token.lexeme not in argb_masks:
raise ValidatorError("invalid destination mask", token)
return argb_masks[token.lexeme]
def validate_masks(ins_ast: parser.TEXInstruction):
addresses = set()
dests = set()
masks = Masks(
alpha_wmask = AlphaMask.NONE,
rgb_wmask = RGBMask.NONE,
alpha_omask = AlphaMask.NONE,
rgb_omask = RGBMask.NONE,
)
for dest_addr_swizzle in ins_ast.operation.dest_addr_swizzles:
dest_keyword = dest_addr_swizzle.dest_keyword
dest = validate_dest_keyword(dest_keyword)
if dest in dests:
raise ValidatorError(f"duplicate destination keyword {dest}", dest_keyword)
dests.add(dest)
addr_identifier = dest_addr_swizzle.addr_identifier
addr = validate_identifier_number(addr_identifier)
addresses.add(addr)
swizzle_identifier = dest_addr_swizzle.swizzle_identifier
alpha_mask, rgb_mask = validate_mask_swizzle(swizzle_identifier)
if dest is KW.OUT:
masks.alpha_omask = alpha_mask
masks.rgb_omask = rgb_mask
elif dest is KW.TEMP:
masks.alpha_wmask = alpha_mask
masks.rgb_wmask = rgb_mask
else:
assert False, type(dest)
if len(addresses) > 1:
raise ValidatorError("contradictory destination address", ins_ast.operation.dest_addr_swizzles[-1].addr_identifier)
address, = addresses
return masks, address
op_kws = OrderedDict([
(KW.NOP, TEXOp.NOP),
(KW.LD, TEXOp.LD),
(KW.TEXKILL, TEXOp.TEXKILL),
(KW.PROJ, TEXOp.PROJ),
(KW.LODBIAS, TEXOp.LODBIAS),
(KW.LOD, TEXOp.LOD),
(KW.DXDY, TEXOp.DXDY),
])
def validate_opcode(token):
if token.keyword not in op_kws:
raise ValidatorError("invalid tex opcode keyword", token)
return op_kws[token.keyword]
def validate_instruction(ins_ast: parser.TEXInstruction):
tags = set([tag.keyword for tag in ins_ast.tags])
masks, dst_addr = validate_masks(ins_ast)
opcode = validate_opcode(ins_ast.operation.opcode_keyword)
tex_id = validate_identifier_number(ins_ast.operation.tex_id_identifier)
dst_swizzle = validate_swizzle(ins_ast.operation.tex_dst_swizzle_identifier)
src_address = validate_identifier_number(ins_ast.operation.tex_src_address_identifier)
src_swizzle = validate_swizzle(ins_ast.operation.tex_src_swizzle_identifier)
return Instruction(
tags = tags,
masks = masks,
opcode = opcode,
tex_id = tex_id,
src_addr = src_address, # texture coordinate address
src_swizzle = src_swizzle, # texture coordinate swizzle
dst_addr = dst_addr, # temp address
dst_swizzle = dst_swizzle, # texture value swizzle
)

View File

@ -1,11 +1,530 @@
from assembler.fs import alu_validator
from assembler.fs import tex_validator
from assembler.fs.parser import TEXInstruction, ALUInstruction
from pprint import pprint
from dataclasses import dataclass
from enum import Enum, IntEnum, auto
from collections import OrderedDict
from assembler.fs.parser import Mod
from assembler.fs.keywords import _keyword_to_string, KW
from assembler.error import print_error
from assembler.validator import ValidatorError
class SrcAddrType(Enum):
temp = auto()
const = auto()
float = auto()
@dataclass
class SrcAddr:
type: SrcAddrType
value: int
class SrcMod(IntEnum):
nop = 0
neg = 1
abs = 2
nab = 3
class SrcpOp(IntEnum):
neg2 = 0
sub = 1
add = 2
neg = 3
@dataclass
class Addr:
src0: SrcAddr = None
src1: SrcAddr = None
src2: SrcAddr = None
srcp: SrcpOp = None
@dataclass
class AddrRGBAlpha:
alpha: Addr
rgb: Addr
class RGBMask(IntEnum):
NONE = 0
R = 1
G = 2
RG = 3
B = 4
RB = 5
GB = 6
RGB = 7
class AlphaMask(IntEnum):
NONE = 0
A = 1
class Unit(Enum):
alpha = auto()
rgb = auto()
class RGBOp(IntEnum):
MAD = 0
DP3 = 1
DP4 = 2
D2A = 3
MIN = 4
MAX = 5
CND = 7
CMP = 8
FRC = 9
SOP = 10
MDH = 11
MDV = 12
class AlphaOp(IntEnum):
MAD = 0
DP = 1
MIN = 2
MAX = 3
CND = 5
CMP = 6
FRC = 7
EX2 = 8
LN2 = 9
RCP = 10
RSQ = 11
SIN = 12
COS = 13
MDH = 14
MDV = 15
@dataclass
class RGBDest:
addrd: int
wmask: RGBMask
omask: RGBMask
@dataclass
class AlphaDest:
addrd: int
wmask: AlphaMask
omask: AlphaMask
class SwizzleSelSrc(IntEnum):
src0 = 0
src1 = 1
src2 = 2
srcp = 3
class Swizzle(IntEnum):
r = 0
g = 1
b = 2
a = 3
zero = 4
half = 5
one = 6
unused = 7
@dataclass
class SwizzleSel:
src: SwizzleSelSrc
swizzle: list[Swizzle]
mod: Mod
@dataclass
class AlphaOperation:
dest: AlphaDest
opcode: AlphaOp
sels: list[SwizzleSel]
@dataclass
class RGBOperation:
dest: RGBDest
opcode: RGBOp
sels: list[SwizzleSel]
class InstructionType(IntEnum):
ALU = 0
OUT = 1
FC = 2
TEX = 3
@dataclass
class Instruction:
type: InstructionType
tex_sem_wait: bool
nop: bool
addr: Addr
alpha_op: AlphaOperation
rgb_op: RGBOperation
def validate_identifier_number(token):
try:
return int(token.lexeme, 10)
except ValueError:
raise ValidatorError("invalid number", token)
def keywords_to_string(keywords):
return [_keyword_to_string[s].decode("utf-8") for s in keywords]
def validate_instruction_let_expressions(let_expressions):
src_keywords = [KW.SRC0, KW.SRC1, KW.SRC2, KW.SRCP]
src_keyword_strs = keywords_to_string(src_keywords)
rgb_alpha_swizzles = [b"rgb", b"a"]
addr_rgb_alpha = AddrRGBAlpha(Addr(), Addr())
def set_src_by_keyword(addr, keyword, value):
if keyword == KW.SRC0:
addr.src0 = value
elif keyword == KW.SRC1:
addr.src1 = value
elif keyword == KW.SRC2:
addr.src2 = value
elif keyword == KW.SRCP:
addr.srcp = value
else:
assert False, keyword
def src_value(expr, src):
if src in {KW.SRC0, KW.SRC1, KW.SRC2}:
keyword_to_src_addr_type = OrderedDict([
(KW.TEMP, SrcAddrType.temp),
(KW.CONST, SrcAddrType.const),
(KW.FLOAT, SrcAddrType.float),
])
src_addr_type_strs = keywords_to_string(keyword_to_src_addr_type.keys())
type_kw = expr.addr_keyword.keyword
if type_kw not in keyword_to_src_addr_type:
raise ValidatorError(f"invalid src addr type, expected one of {src_addr_type_strs}", expr.addr_keyword)
type = keyword_to_src_addr_type[type_kw]
value = validate_identifier_number(expr.addr_value_identifier)
if type is SrcAddrType.float:
if value >= 128:
raise ValidatorError(f"invalid float value", expr.addr_value_identifier)
elif type is SrcAddrType.temp:
if value >= 128:
raise ValidatorError(f"invalid temp value", expr.addr_value_identifier)
elif type is SrcAddrType.const:
if value >= 256:
raise ValidatorError(f"invalid const value", expr.addr_value_identifier)
else:
assert False, (id(type), id(SrcAddrType.float))
return SrcAddr(
type,
value,
)
elif src == KW.SRCP:
keyword_to_srcp_op = OrderedDict([
(KW.NEG2, SrcpOp.neg2),
(KW.SUB, SrcpOp.sub),
(KW.ADD, SrcpOp.add),
(KW.NEG, SrcpOp.neg),
])
srcp_op_strs = keywords_to_string(keyword_to_srcp_op.keys())
op = expr.addr_keyword.keyword
if op not in keyword_to_srcp_op:
raise ValidatorError(f"invalid srcp op, expected one of {srcp_op_strs}", expr.addr_keyword)
return keyword_to_srcp_op[op]
else:
assert False, src
sources = set()
for expr in let_expressions:
src = expr.src_keyword.keyword
if src not in src_keywords:
raise ValidatorError(f"invalid src keyword, expected one of {src_keyword_strs}", expr.src_keyword)
src_swizzle = expr.src_swizzle_identifier.lexeme.lower()
if src_swizzle not in rgb_alpha_swizzles:
raise ValidatorError(f"invalid src swizzle, expected one of {rgb_alpha_swizzles}", expr.src_swizzle_identifier)
source = (_keyword_to_string[src].lower(), src_swizzle)
if source in sources:
raise ValidatorError(f"duplicate source/swizzle in let expressions", expr.src_swizzle_identifier)
sources.add(source)
value = src_value(expr, src)
if src_swizzle == b"a":
set_src_by_keyword(addr_rgb_alpha.alpha, src, value)
elif src_swizzle == b"rgb":
set_src_by_keyword(addr_rgb_alpha.rgb, src, value)
else:
assert False, src_swizzle
return addr_rgb_alpha
def prevalidate_mask(dest_addr_swizzle, valid_masks):
# we don't know yet whether this is an Alpha operation or an RGB operation
swizzle_str = dest_addr_swizzle.swizzle_identifier.lexeme
if swizzle_str.lower() not in valid_masks:
raise ValidatorError(f"invalid write mask, expected one of {valid_masks}", dest_addr_swizzle.swizzle_identifier)
mask = swizzle_str.lower()
return mask
rgb_op_kws = OrderedDict([
(KW.MAD, RGBOp.MAD),
(KW.DP3, RGBOp.DP3),
(KW.DP4, RGBOp.DP4),
(KW.D2A, RGBOp.D2A),
(KW.MIN, RGBOp.MIN),
(KW.MAX, RGBOp.MAX),
(KW.CND, RGBOp.CND),
(KW.CMP, RGBOp.CMP),
(KW.FRC, RGBOp.FRC),
(KW.SOP, RGBOp.SOP),
(KW.MDH, RGBOp.MDH),
(KW.MDV, RGBOp.MDV)
])
alpha_op_kws = OrderedDict([
(KW.MAD, AlphaOp.MAD),
(KW.DP, AlphaOp.DP),
(KW.MIN, AlphaOp.MIN),
(KW.MAX, AlphaOp.MAX),
(KW.CND, AlphaOp.CND),
(KW.CMP, AlphaOp.CMP),
(KW.FRC, AlphaOp.FRC),
(KW.EX2, AlphaOp.EX2),
(KW.LN2, AlphaOp.LN2),
(KW.RCP, AlphaOp.RCP),
(KW.RSQ, AlphaOp.RSQ),
(KW.SIN, AlphaOp.SIN),
(KW.COS, AlphaOp.COS),
(KW.MDH, AlphaOp.MDH),
(KW.MDV, AlphaOp.MDV)
])
rgb_masks = OrderedDict([
(b"none" , RGBMask.NONE),
(b"r" , RGBMask.R),
(b"g" , RGBMask.G),
(b"rg" , RGBMask.RG),
(b"b" , RGBMask.B),
(b"rb" , RGBMask.RB),
(b"gb" , RGBMask.GB),
(b"rgb" , RGBMask.RGB),
])
alpha_masks = OrderedDict([
(b"none" , AlphaMask.NONE),
(b"a" , AlphaMask.A),
])
alpha_only_ops = set(alpha_op_kws.keys()) - set(rgb_op_kws.keys())
rgb_only_ops = set(rgb_op_kws.keys()) - set(alpha_op_kws.keys())
all_ops = set(rgb_op_kws.keys()) | set(alpha_op_kws.keys())
alpha_only_masks = set(alpha_masks.keys()) - set(rgb_masks.keys())
rgb_only_masks = set(rgb_masks.keys()) - set(alpha_masks.keys())
all_masks = set(rgb_masks.keys()) | set(alpha_masks.keys())
def infer_operation_units(operations):
if len(operations) > 2:
raise ValidatorError("too many operations in instruction", operations[-1].opcode_keyword)
units = [None, None]
for i, operation in enumerate(operations):
opcode = operation.opcode_keyword.keyword
if opcode not in all_ops:
raise ValidatorError(f"invalid opcode keyword, expected one of {all_ops}", operation.opcode_keyword)
if len(operation.dest_addr_swizzles) > 2:
raise ValidationError("too many destinations in instruction", operation.dest_addr_swizzles[-1])
masks = set(prevalidate_mask(dest_addr_swizzle, all_masks) for dest_addr_swizzle in operation.dest_addr_swizzles)
def infer_opcode_unit():
if opcode in alpha_only_ops:
return Unit.alpha
if opcode in rgb_only_ops:
return Unit.rgb
return None
def infer_mask_unit():
if any(mask in alpha_only_masks for mask in masks):
return Unit.alpha
if any(mask in rgb_only_masks for mask in masks):
return Unit.rgb
return None
opcode_unit = infer_opcode_unit()
mask_unit = infer_mask_unit()
if opcode_unit is not None and mask_unit is not None and opcode_unit != mask_unit:
raise ValidatorError(f"contradictory {mask_unit.name} write mask for {opcode_unit.name} opcode", operation.opcode_keyword)
units[i] = opcode_unit or mask_unit
if units[0] == units[1]:
raise ValidatorError(f"invalid duplicate use of {units[1].name} unit", operations[1].opcode_keyword)
other_unit = {
Unit.alpha: Unit.rgb,
Unit.rgb: Unit.alpha,
}
if units[0] is None:
units[0] = other_unit[units[1]]
if units[1] is None:
units[1] = other_unit[units[0]]
assert units[0] is not None
assert units[1] is not None
assert units[0] != units[1]
for i, operation in enumerate(operations):
yield units[i], operation
def validate_dest_keyword(dest_keyword):
dest_keywords = [KW.OUT, KW.TEMP]
dest_keyword_strs = keywords_to_string(dest_keywords)
dest = dest_keyword.keyword
if dest not in dest_keywords:
raise ValidatorError(f"invalid dest keyword, expected one of {dest_keyword_strs}", dest_addr_swizzle.dest_keyword)
return dest
def validate_instruction_operation_dest(dest_addr_swizzles, mask_lookup, type_cls):
addrs = set()
wmask = None
omask = None
for dest_addr_swizzle in dest_addr_swizzles:
dest = validate_dest_keyword(dest_addr_swizzle.dest_keyword)
addr = validate_identifier_number(dest_addr_swizzle.addr_identifier)
mask = mask_lookup[dest_addr_swizzle.swizzle_identifier.lexeme.lower()]
addrs.add(addr)
if dest == KW.OUT:
omask = mask
elif dest == KW.TEMP:
wmask = mask
else:
assert False, dest
if len(addrs) > 1:
raise ValidatorError(f"too many destination addresses", operation.dest_addr_swizzles[-1].addr_identifier)
addrd, = addrs if addrs else [0]
return type_cls(
addrd=addrd,
wmask=wmask,
omask=omask
)
swizzle_sel_src_kws = OrderedDict([
(KW.SRC0, SwizzleSelSrc.src0),
(KW.SRC1, SwizzleSelSrc.src1),
(KW.SRC2, SwizzleSelSrc.src2),
(KW.SRCP, SwizzleSelSrc.srcp),
])
swizzle_kws = OrderedDict([
(ord("r"), Swizzle.r),
(ord("g"), Swizzle.g),
(ord("b"), Swizzle.b),
(ord("a"), Swizzle.a),
(ord("0"), Swizzle.zero),
(ord("h"), Swizzle.half),
(ord("1"), Swizzle.one),
(ord("_"), Swizzle.unused),
])
def validate_instruction_operation_sels(swizzle_sels, is_alpha):
if len(swizzle_sels) > 3:
raise ValidatorError("too many swizzle sels", swizzle_sels[-1].sel_keyword)
sels = []
for swizzle_sel in swizzle_sels:
if swizzle_sel.sel_keyword.keyword not in swizzle_sel_src_kws:
raise ValidatorError("invalid swizzle src", swizzle_sel.sel_keyword.keyword)
src = swizzle_sel_src_kws[swizzle_sel.sel_keyword.keyword]
swizzle_lexeme = swizzle_sel.swizzle_identifier.lexeme.lower()
swizzles_length = 1 if is_alpha else 3
if len(swizzle_lexeme) != swizzles_length:
raise ValidatorError("invalid swizzle length", swizzle_sel.swizzle_identifier)
if not all(c in swizzle_kws for c in swizzle_lexeme):
raise ValidatorError("invalid swizzle characters", swizzle_sel.swizzle_identifier)
swizzle = [
swizzle_kws[c] for c in swizzle_lexeme
]
mod = swizzle_sel.mod
sels.append(SwizzleSel(src, swizzle, mod))
return sels
def validate_alpha_instruction_operation(operation):
dest = validate_instruction_operation_dest(operation.dest_addr_swizzles,
mask_lookup=alpha_masks,
type_cls=AlphaDest)
opcode = alpha_op_kws[operation.opcode_keyword.keyword]
sels = validate_instruction_operation_sels(operation.swizzle_sels, is_alpha=True)
return AlphaOperation(
dest,
opcode,
sels
)
def validate_rgb_instruction_operation(operation):
dest = validate_instruction_operation_dest(operation.dest_addr_swizzles,
mask_lookup=rgb_masks,
type_cls=RGBDest)
opcode = rgb_op_kws[operation.opcode_keyword.keyword]
sels = validate_instruction_operation_sels(operation.swizzle_sels, is_alpha=False)
return RGBOperation(
dest,
opcode,
sels
)
def validate_instruction_operations(operations):
for unit, operation in infer_operation_units(operations):
if unit is Unit.alpha:
yield validate_alpha_instruction_operation(operation)
elif unit is Unit.rgb:
yield validate_rgb_instruction_operation(operation)
else:
assert False, unit
def validate_instruction(ins):
if type(ins) is TEXInstruction:
return tex_validator.validate_instruction(ins)
elif type(ins) is ALUInstruction:
return alu_validator.validate_instruction(ins)
else:
assert False, type(ins)
addr_rgb_alpha = validate_instruction_let_expressions(ins.let_expressions)
instruction_type = InstructionType.OUT if ins.out else InstructionType.ALU
tex_sem_wait = ins.tex_sem_wait
nop = ins.nop
instruction = Instruction(
instruction_type,
tex_sem_wait,
nop,
addr_rgb_alpha,
None,
None
)
for op in validate_instruction_operations(ins.operations):
if type(op) is RGBOperation:
instruction.rgb_op = op
elif type(op) is AlphaOperation:
instruction.alpha_op = op
else:
assert False, op
return instruction
if __name__ == "__main__":
from assembler.lexer import Lexer, LexerError
from assembler.fs.parser import Parser, ParserError
from assembler.fs.keywords import find_keyword
buf = b"""
src0.a = float(0), src0.rgb = temp[0] , srcp.a = neg :
out[0].none = temp[0].none = MAD src0.r src0.r src0.r ,
out[0].none = temp[0].r = DP3 src0.rg0 src0.rg0 ;
"""
lexer = Lexer(buf, find_keyword, emit_newlines=False, minus_is_token=True)
tokens = list(lexer.lex_tokens())
parser = Parser(tokens)
try:
ins_ast = parser.instruction()
pprint(validate_instruction(ins_ast))
except LexerError as e:
print_error(None, buf, e)
raise
except ParserError as e:
print_error(None, buf, e)
raise
except ValidatorError as e:
print_error(None, buf, e)
raise

View File

@ -44,11 +44,3 @@ class BaseParser:
if token.type != token_type1 and token.type != token_type2:
raise ParserError(message, token)
return token
def consume_keyword(self, keyword, message):
if self.match_keyword(keyword):
token = self.advance()
return token
else:
token = self.advance()
raise ParserError(message, token)

View File

@ -1,7 +1,6 @@
import sys
from assembler.lexer import Lexer, LexerError
from assembler.validator import ValidatorError
from assembler.vs.keywords import find_keyword
from assembler.vs.parser import Parser, ParserError
from assembler.vs.emitter import emit_instruction, emit_dual_math_instruction
@ -43,9 +42,6 @@ def frontend(filename, buf):
except LexerError as e:
print_error(input_filename, buf, e)
raise
except ValidatorError as e:
print_error(filename, buf, e)
raise
if __name__ == "__main__":
input_filename = sys.argv[1]

View File

@ -131,7 +131,6 @@ def disassemble(code, ix):
print('\n'.join(inner2(i, register_name)))
inner = inner_rows
#inner = inner_columns
inst_type = get_field_pv_name(us_cmn_inst, US_CMN_INST["TYPE"])
if inst_type in {"US_INST_TYPE_OUT", "US_INST_TYPE_ALU"}:

View File

@ -88,8 +88,8 @@ def disassemble_addr_inner(register_const, address, const, rel):
assert False, const
alu_swizzle_strs = ['r', 'g', 'b', 'a', '0', 'h', '1', '_']
alu_sel_strs = ['0', '1', '2', 'p']
swizzle_strs = ['r', 'g', 'b', 'a', '0', 'h', '1', '_']
sel_strs = ['0', '1', '2', 'p']
def disassemble_addr(register, code, suffix):
addr0 = register.ADDR0(code)
@ -108,7 +108,7 @@ def disassemble_addr(register, code, suffix):
s2 = disassemble_addr_inner(register.ADDR2_CONST, addr2, addr2_const, addr2_rel)
sp = srcp_op.lower()
return [
f"src{alu_sel_strs[i]}.{suffix} = {s}"
f"src{sel_strs[i]}.{suffix} = {s}"
for i, s in enumerate([s0, s1, s2, sp])
]
@ -143,15 +143,15 @@ def disassemble_rgb_swizzle_sel(code):
blue_swiz_c = US_ALU_RGBA_INST.BLUE_SWIZ_C(code)
rgb_mod_c = US_ALU_RGBA_INST.RGB_MOD_C(code)
rgb_swiz_a = ''.join(alu_swizzle_strs[n] for n in [red_swiz_a, green_swiz_a, blue_swiz_a])
rgb_swiz_b = ''.join(alu_swizzle_strs[n] for n in [red_swiz_b, green_swiz_b, blue_swiz_b])
rgb_swiz_c = ''.join(alu_swizzle_strs[n] for n in [red_swiz_c, green_swiz_c, blue_swiz_c])
rgb_swiz_a = ''.join(swizzle_strs[n] for n in [red_swiz_a, green_swiz_a, blue_swiz_a])
rgb_swiz_b = ''.join(swizzle_strs[n] for n in [red_swiz_b, green_swiz_b, blue_swiz_b])
rgb_swiz_c = ''.join(swizzle_strs[n] for n in [red_swiz_c, green_swiz_c, blue_swiz_c])
rgb_swiz = [rgb_swiz_a, rgb_swiz_b, rgb_swiz_c]
rgb_sels = [rgb_sel_a, rgb_sel_b, rgb_sel_c]
rgb_mods = [rgb_mod_a, rgb_mod_b, rgb_mod_c]
return [mod_str(f"src{alu_sel_strs[sel]}.{swiz}", mod)
return [mod_str(f"src{sel_strs[sel]}.{swiz}", mod)
for swiz, sel, mod in zip(rgb_swiz, rgb_sels, rgb_mods)], rgb_sels
def disassemble_a_swizzle_sel(code):
@ -167,11 +167,11 @@ def disassemble_a_swizzle_sel(code):
alpha_swiz_c = US_ALU_RGBA_INST.ALPHA_SWIZ_C(code)
alpha_mod_c = US_ALU_RGBA_INST.ALPHA_MOD_C(code)
a_swiz = [alu_swizzle_strs[n] for n in [alpha_swiz_a, alpha_swiz_b, alpha_swiz_c]]
a_swiz = [swizzle_strs[n] for n in [alpha_swiz_a, alpha_swiz_b, alpha_swiz_c]]
a_sels = [alpha_sel_a, alpha_sel_b, alpha_sel_c]
a_mods = [alpha_mod_a, alpha_mod_b, alpha_mod_c]
return [mod_str(f"src{alu_sel_strs[sel]}.{swiz}", mod)
return [mod_str(f"src{sel_strs[sel]}.{swiz}", mod)
for swiz, sel, mod in zip(a_swiz, a_sels, a_mods)], a_sels
def omod_str(s, mod):
@ -201,21 +201,21 @@ def disassemble_alu_dest(code):
rgb_addrd_rel = US_ALU_RGBA_INST.RGB_ADDRD_REL(code)
assert rgb_addrd_rel == 0
rgb_wmask, rgb_wmask_str, _ = US_CMN_INST._RGB_WMASK(code)
a_wmask, a_wmask_str, _ = US_CMN_INST._ALPHA_WMASK(code)
_, rgb_wmask, _ = US_CMN_INST._RGB_WMASK(code)
_, a_wmask, _ = US_CMN_INST._ALPHA_WMASK(code)
rgb_omask, rgb_omask_str, _ = US_CMN_INST._RGB_OMASK(code)
a_omask, a_omask_str, _ = US_CMN_INST._ALPHA_OMASK(code)
_, rgb_omask, _ = US_CMN_INST._RGB_OMASK(code)
_, a_omask, _ = US_CMN_INST._ALPHA_OMASK(code)
a_out_str = f"out[{a_addrd}].{a_omask_str.lower().ljust(4)} = " if a_omask != 0 else ""
a_temp_str = f"temp[{a_addrd}].{a_wmask_str.lower().ljust(4)} = " if a_wmask != 0 else ""
a_out_str = f"out[{a_addrd}].{a_omask.lower().ljust(4)}"
a_temp_str = f"temp[{a_addrd}].{a_wmask.lower().ljust(4)}"
rgb_out_str = f"out[{rgb_addrd}].{rgb_omask_str.lower().ljust(4)} = " if rgb_omask != 0 else ""
rgb_temp_str = f"temp[{rgb_addrd}].{rgb_wmask_str.lower().ljust(4)} = " if rgb_wmask != 0 else ""
rgb_out_str = f"out[{rgb_addrd}].{rgb_omask.lower().ljust(4)}"
rgb_temp_str = f"temp[{rgb_addrd}].{rgb_wmask.lower().ljust(4)}"
return (a_out_str, a_temp_str), (rgb_out_str, rgb_temp_str)
def assert_zeros_common(code):
def assert_zeros(code):
rgb_pred_sel = US_CMN_INST.RGB_PRED_SEL(code)
assert rgb_pred_sel == 0
rgb_pred_inv = US_CMN_INST.RGB_PRED_INV(code)
@ -237,7 +237,6 @@ def assert_zeros_common(code):
stat_we = US_CMN_INST.STAT_WE(code)
assert stat_we == 0
def assert_zeros_alu(code):
rgb_omod = US_ALU_RGB_INST.OMOD(code)
rgb_target = US_ALU_RGB_INST.TARGET(code)
alu_wmask = US_ALU_RGB_INST.ALU_WMASK(code)
@ -252,47 +251,6 @@ def assert_zeros_alu(code):
assert a_target == 0
assert w_omask == 0
def assert_zeros_tex(code):
dx_addr = US_TEX_ADDR_DXDY.DX_ADDR(code)
dx_addr_rel = US_TEX_ADDR_DXDY.DX_ADDR_REL(code)
dx_s_swiz = US_TEX_ADDR_DXDY.DX_S_SWIZ(code)
dx_t_swiz = US_TEX_ADDR_DXDY.DX_T_SWIZ(code)
dx_r_swiz = US_TEX_ADDR_DXDY.DX_R_SWIZ(code)
dx_q_swiz = US_TEX_ADDR_DXDY.DX_Q_SWIZ(code)
assert dx_addr == 0, dx_addr
assert dx_addr_rel == 0, dx_addr_rel
assert dx_s_swiz == 0, dx_s_swiz
assert dx_t_swiz == 0, dx_t_swiz
assert dx_r_swiz == 0, dx_r_swiz
assert dx_q_swiz == 0, dx_q_swiz
dy_addr = US_TEX_ADDR_DXDY.DY_ADDR(code)
dy_addr_rel = US_TEX_ADDR_DXDY.DY_ADDR_REL(code)
dy_s_swiz = US_TEX_ADDR_DXDY.DY_S_SWIZ(code)
dy_t_swiz = US_TEX_ADDR_DXDY.DY_T_SWIZ(code)
dy_r_swiz = US_TEX_ADDR_DXDY.DY_R_SWIZ(code)
dy_q_swiz = US_TEX_ADDR_DXDY.DY_Q_SWIZ(code)
assert dy_addr == 0, dy_addr
assert dy_addr_rel == 0, dy_addr_rel
assert dy_s_swiz == 0, dy_s_swiz
assert dy_t_swiz == 0, dy_t_swiz
assert dy_r_swiz == 0, dy_r_swiz
assert dy_q_swiz == 0, dy_q_swiz
src_addr_rel = US_TEX_ADDR.SRC_ADDR_REL(code)
assert src_addr_rel == 0, src_addr_rel
dst_addr_rel = US_TEX_ADDR.DST_ADDR_REL(code)
assert dst_addr_rel == 0, dst_addr_rel
ignore_uncovered = US_TEX_INST.IGNORE_UNCOVERED(code)
assert ignore_uncovered == 0, ignore_uncovered
unscaled = US_TEX_INST.UNSCALED(code)
assert unscaled == 0, unscaled
_rgb_op_operands = {
"OP_MAD": 3,
"OP_DP3": 2,
@ -326,8 +284,7 @@ _a_op_operands = {
}
def disassemble_alu(code, is_output):
assert_zeros_common(code)
assert_zeros_alu(code)
assert_zeros(code)
a_addr_strs = disassemble_addr(US_ALU_ALPHA_ADDR, code, "a")
rgb_addr_strs = disassemble_addr(US_ALU_RGB_ADDR, code, "rgb")
@ -376,80 +333,15 @@ def disassemble_alu(code, is_output):
rgb_clamp = US_CMN_INST.RGB_CLAMP(code)
alpha_clamp = US_CMN_INST.ALPHA_CLAMP(code)
rgb_clamp_str = ".SAT" if rgb_clamp != 0 else ""
a_clamp_str = ".SAT" if alpha_clamp != 0 else ""
rgb_clamp_str = ".CLAMP" if rgb_clamp != 0 else ""
a_clamp_str = ".CLAMP" if alpha_clamp != 0 else ""
print(", ".join([*a_addr_strs, *rgb_addr_strs]), ":")
#print(", ".join(a_addr_strs), ":")
print(f" {a_out_str}{a_temp_str}{a_op.removeprefix('OP_').ljust(3)}{a_clamp_str} {' '.join(a_swizzle_sel)}", ",")
print(f" {a_out_str} = {a_temp_str} = {a_op.removeprefix('OP_').ljust(3)}{a_clamp_str} {' '.join(a_swizzle_sel)}", ",")
#print(", ".join(rgb_addr_strs), ":")
print(f" {rgb_out_str}{rgb_temp_str}{rgb_op.removeprefix('OP_').ljust(3)}{rgb_clamp_str} {' '.join(rgb_swizzle_sel)}", ";")
def disassemble_tex_swizzle_str(code):
tex_swiz_strs = ["r", "g", "b", "a"]
src_s_swiz = US_TEX_ADDR.SRC_S_SWIZ(code)
src_t_swiz = US_TEX_ADDR.SRC_T_SWIZ(code)
src_r_swiz = US_TEX_ADDR.SRC_R_SWIZ(code)
src_q_swiz = US_TEX_ADDR.SRC_Q_SWIZ(code)
src_swiz = ''.join(tex_swiz_strs[n] for n in [src_s_swiz, src_t_swiz, src_r_swiz, src_q_swiz])
dst_r_swiz = US_TEX_ADDR.DST_R_SWIZ(code)
dst_g_swiz = US_TEX_ADDR.DST_G_SWIZ(code)
dst_b_swiz = US_TEX_ADDR.DST_B_SWIZ(code)
dst_a_swiz = US_TEX_ADDR.DST_A_SWIZ(code)
dst_swiz = ''.join(tex_swiz_strs[n] for n in [dst_r_swiz, dst_g_swiz, dst_b_swiz, dst_a_swiz])
return src_swiz, dst_swiz
def disassemble_tex_dest(code):
dst_addr = US_TEX_ADDR.DST_ADDR(code)
rgb_wmask, rgb_wmask_str, _ = US_CMN_INST._RGB_WMASK(code)
a_wmask, a_wmask_str, _ = US_CMN_INST._ALPHA_WMASK(code)
wmask_bool = rgb_wmask != 0 or a_wmask != 0
rgba_wmask = (a_wmask_str if a_wmask else "") + (rgb_wmask_str if rgb_wmask else "")
temp_str = f"temp[{dst_addr}].{rgba_wmask.lower().ljust(4)} = " if wmask_bool else ""
rgb_omask, rgb_omask_str, _ = US_CMN_INST._RGB_OMASK(code)
a_omask, a_omask_str, _ = US_CMN_INST._ALPHA_OMASK(code)
omask_bool = rgb_omask != 0 or a_omask != 0
rgba_omask = (a_omask_str if a_omask else "") + (rgb_omask_str if rgb_omask else "")
out_str = f"out[{dst_addr}].{rgba_omask.lower().ljust(4)} = " if omask_bool else ""
return out_str, temp_str
def disassemble_tex(code):
assert_zeros_common(code)
assert_zeros_tex(code)
_, inst, _ = US_TEX_INST._INST(code)
tex_id = US_TEX_INST.TEX_ID(code)
src_addr = US_TEX_ADDR.SRC_ADDR(code)
src_swiz, dst_swiz = disassemble_tex_swizzle_str(code)
out_str, temp_str = disassemble_tex_dest(code)
temp_out_str = ''.join([out_str, temp_str])
tags = ["TEX"]
if US_CMN_INST.TEX_SEM_WAIT(code):
tags.append("TEX_SEM_WAIT")
if US_TEX_INST.TEX_SEM_ACQUIRE(code):
tags.append("TEX_SEM_ACQUIRE")
if US_CMN_INST.ALU_WAIT(code):
tags.append("ALU_WAIT")
print(" ".join(tags))
print(f" {temp_out_str}{inst} tex[{tex_id}].{dst_swiz} temp[{src_addr}].{src_swiz} ;")
print(f" {rgb_out_str} = {rgb_temp_str} = {rgb_op.removeprefix('OP_').ljust(3)}{rgb_clamp_str} {' '.join(rgb_swizzle_sel)}", ";")
def disassemble(code):
assert len(code) == 6, len(code)
@ -458,8 +350,6 @@ def disassemble(code):
disassemble_alu(code, is_output=True)
elif type == US_CMN_INST.TYPE.US_INST_TYPE_ALU:
disassemble_alu(code, is_output=False)
elif type == US_CMN_INST.TYPE.US_INST_TYPE_TEX:
disassemble_tex(code)
else:
print("[TYPE]", type)
#assert False, US_CMN_INST._TYPE(code)

View File

@ -4,14 +4,12 @@
0x00000000,
0x00000000,
0x00000000,
0x00007807,
0x02410000,
0xe402f400,
0x00000000,
0x00000000,
0x00000000,
0x00078005,
0x40000801,
0x48000801,

View File

@ -1,12 +0,0 @@
0x00003807,
0x02400000,
0xe400f400,
0x00000000,
0x00000000,
0x00000000,
0x00078005,
0x08020000,
0x08020080,
0x1c280140,
0x1c204003,
0x00000005,