\_pp {return MOD_PP; }
\_centroid {return MOD_CENTROID; }
+{IMMVAL} {
+ asmshader_lval.immval.val = atof(yytext);
+ asmshader_lval.immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL));
+ return IMMVAL;
+ }
+
{COMMA} {return yytext[0]; }
- {return yytext[0]; }
\( {return yytext[0]; }
\) {return yytext[0]; }
+ /* for relative addressing */
+\[|\]|\+ {return yytext[0]; }
+
\_abs {return SMOD_ABS; }
{PREPROCESSORDIRECTIVE} {
int asmshader_lex(void);
void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
- reg->rel_reg = NULL;
+ /* We can have an additional offset without true relative addressing
+ * ex. c2[ 4 ] */
+ reg->regnum += rel->additional_offset;
+ if(!rel->has_rel_reg) {
+ reg->rel_reg = NULL;
+ } else {
+ reg->rel_reg = asm_alloc(sizeof(*reg->rel_reg));
+ if(!reg->rel_reg) {
+ return;
+ }
+ reg->rel_reg->type = rel->type;
+ reg->rel_reg->swizzle = rel->swizzle;
+ reg->rel_reg->regnum = rel->rel_regnum;
+ }
}
%}
%union {
+ struct {
+ float val;
+ BOOL integer;
+ } immval;
unsigned int regnum;
struct shader_reg reg;
DWORD srcmod;
/* Misc stuff */
%token <component> COMPONENT
+%token <immval> IMMVAL
%type <reg> dreg_name
%type <reg> dreg
%type <reg> sreg_name
+%type <reg> relreg_name
%type <reg> sreg
%type <srcmod> smod
%type <writemask> writemask
%type <modshift> omods
%type <modshift> omodifier
%type <rel_reg> rel_reg
+%type <immval> immsum
%type <sregs> sregs
%%
$$.has_rel_reg = FALSE;
$$.additional_offset = 0;
}
+ | '[' immsum ']'
+ {
+ $$.has_rel_reg = FALSE;
+ $$.additional_offset = $2.val;
+ }
+ | '[' relreg_name swizzle ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $2.type;
+ $$.additional_offset = 0;
+ $$.rel_regnum = $2.regnum;
+ $$.swizzle = $3;
+ }
+ | '[' immsum '+' relreg_name swizzle ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $4.type;
+ $$.additional_offset = $2.val;
+ $$.rel_regnum = $4.regnum;
+ $$.swizzle = $5;
+ }
+ | '[' relreg_name swizzle '+' immsum ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $2.type;
+ $$.additional_offset = $5.val;
+ $$.rel_regnum = $2.regnum;
+ $$.swizzle = $3;
+ }
+ | '[' immsum '+' relreg_name swizzle '+' immsum ']'
+ {
+ $$.has_rel_reg = TRUE;
+ $$.type = $4.type;
+ $$.additional_offset = $2.val + $7.val;
+ $$.rel_regnum = $4.regnum;
+ $$.swizzle = $5;
+ }
+
+immsum: IMMVAL
+ {
+ if(!$1.integer) {
+ asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
+ asm_ctx.line_no, $1.val);
+ set_parse_status(&asm_ctx, PARSE_ERR);
+ }
+ $$.val = $1.val;
+ }
+ | immsum '+' IMMVAL
+ {
+ if(!$3.integer) {
+ asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n",
+ asm_ctx.line_no, $3.val);
+ set_parse_status(&asm_ctx, PARSE_ERR);
+ }
+ $$.val = $1.val + $3.val;
+ }
smod: SMOD_ABS
{
$$ = BWRITERSPSM_ABS;
}
+relreg_name: REG_ADDRESS
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_ADDR;
+ }
+ | REG_LOOP
+ {
+ $$.regnum = 0; $$.type = BWRITERSPR_LOOP;
+ }
+
sreg_name: REG_TEMP
{
$$.regnum = $1; $$.type = BWRITERSPR_TEMP;
return wine_dbg_sprintf("%s", ret);
}
+const char *debug_print_relarg(const struct shader_reg *reg) {
+ const char *short_swizzle;
+ if(!reg->rel_reg) return "";
+
+ short_swizzle = debug_print_swizzle(reg->rel_reg->swizzle);
+
+ if(reg->rel_reg->type == BWRITERSPR_ADDR) {
+ return wine_dbg_sprintf("[a%u%s]", reg->rel_reg->regnum, short_swizzle);
+ } else if(reg->rel_reg->type == BWRITERSPR_LOOP && reg->rel_reg->regnum == 0) {
+ return wine_dbg_sprintf("[aL%s]", short_swizzle);
+ } else {
+ return "Unexpected relative addressing argument";
+ }
+}
+
const char *debug_print_dstreg(const struct shader_reg *reg, shader_type st) {
- return wine_dbg_sprintf("%s%s", get_regname(reg, st),
+ return wine_dbg_sprintf("%s%s%s", get_regname(reg, st),
+ debug_print_relarg(reg),
debug_print_writemask(reg->writemask));
}
const char *debug_print_srcreg(const struct shader_reg *reg, shader_type st) {
switch(reg->srcmod) {
case BWRITERSPSM_NONE:
- return wine_dbg_sprintf("%s%s", get_regname(reg, st),
+ return wine_dbg_sprintf("%s%s%s", get_regname(reg, st),
+ debug_print_relarg(reg),
debug_print_swizzle(reg->swizzle));
case BWRITERSPSM_NEG:
- return wine_dbg_sprintf("-%s%s", get_regname(reg, st),
+ return wine_dbg_sprintf("-%s%s%s", get_regname(reg, st),
+ debug_print_relarg(reg),
debug_print_swizzle(reg->swizzle));
case BWRITERSPSM_ABS:
- return wine_dbg_sprintf("%s_abs%s", get_regname(reg, st),
+ return wine_dbg_sprintf("%s%s_abs%s", get_regname(reg, st),
+ debug_print_relarg(reg),
debug_print_swizzle(reg->swizzle));
case BWRITERSPSM_ABSNEG:
- return wine_dbg_sprintf("-%s_abs%s", get_regname(reg, st),
+ return wine_dbg_sprintf("-%s%s_abs%s", get_regname(reg, st),
+ debug_print_relarg(reg),
debug_print_swizzle(reg->swizzle));
}
return "Unknown modifier";
token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK;
token |= d3d9_srcmod(reg->srcmod);
+ if(reg->rel_reg) {
+ if(reg->type == BWRITERSPR_CONST && This->version == BWRITERPS_VERSION(3, 0)) {
+ WARN("c%u[...] is unsupported in ps_3_0\n", reg->regnum);
+ This->state = E_INVALIDARG;
+ return;
+ }
+ if(((reg->rel_reg->type == BWRITERSPR_ADDR && This->version == BWRITERVS_VERSION(3, 0)) ||
+ reg->rel_reg->type == BWRITERSPR_LOOP) &&
+ reg->rel_reg->regnum == 0) {
+ token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
+ } else {
+ WARN("Unsupported relative addressing register\n");
+ This->state = E_INVALIDARG;
+ return;
+ }
+ }
+
put_dword(buffer, token);
+
+ /* vs_2_0 and newer write the register containing the index explicitly in the
+ * binary code
+ */
+ if(token & D3DVS_ADDRMODE_RELATIVE) {
+ sm_3_srcreg(This, reg->rel_reg, buffer);
+ }
}
static void sm_3_dstreg(struct bc_writer *This,
DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
DWORD d3d9reg;
+ if(reg->rel_reg) {
+ if(This->version == BWRITERVS_VERSION(3, 0) &&
+ reg->type == BWRITERSPR_OUTPUT) {
+ token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
+ } else {
+ WARN("Relative addressing not supported for this shader type or register type\n");
+ This->state = E_INVALIDARG;
+ return;
+ }
+ }
+
d3d9reg = d3d9_register(reg->type);
token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
token |= d3d9_writemask(reg->writemask);
put_dword(buffer, token);
+
+ /* vs_2_0 and newer write the register containing the index explicitly in the
+ * binary code
+ */
+ if(token & D3DVS_ADDRMODE_RELATIVE) {
+ sm_3_srcreg(This, reg->rel_reg, buffer);
+ }
}
static const struct instr_handler_table vs_3_handlers[] = {
"texldl r0, v0, s0\n",
{0xfffe0300, 0x0300005f, 0x800f0000, 0x90e40000, 0xa0e40800, 0x0000ffff}
},*/
-/* {*/ /* shader 5 */
-/* "vs_3_0\n"
+ { /* shader 5 */
+ "vs_3_0\n"
"mov r0, c0[aL]\n",
{0xfffe0300, 0x03000001, 0x800f0000, 0xa0e42000, 0xf0e40800, 0x0000ffff}
- },*/
-/* {*/ /* shader 6 */
-/* "vs_3_0\n"
+ },
+ { /* shader 6 */
+ "vs_3_0\n"
"mov o[ a0.x + 12 ], r0\n",
{0xfffe0300, 0x03000001, 0xe00f200c, 0xb0000000, 0x80e40000, 0x0000ffff}
- },*/
+ },
/* {*/ /* shader 7 */
/* "vs_3_0\n"
"add_sat r0, r0, r1\n",