[2/3] d3dx9: Add relative addressing support to the shader assembler.

Matteo Bruni matteo.mystral at gmail.com
Wed May 5 14:00:37 CDT 2010


-------------- next part --------------
From 36d8aa46b1f7413f53053495214238c73d51e6a7 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Wed, 5 May 2010 19:55:26 +0200
Subject: d3dx9: Add relative addressing support to the shader assembler.

---
 dlls/d3dx9_36/asmshader.l      |    9 ++++
 dlls/d3dx9_36/asmshader.y      |   87 +++++++++++++++++++++++++++++++++++++++-
 dlls/d3dx9_36/asmutils.c       |   30 +++++++++++--
 dlls/d3dx9_36/bytecodewriter.c |   42 +++++++++++++++++++
 dlls/d3dx9_36/tests/asm.c      |   12 +++---
 5 files changed, 168 insertions(+), 12 deletions(-)

diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
index b0a1e9e..1d0e4b6 100644
--- a/dlls/d3dx9_36/asmshader.l
+++ b/dlls/d3dx9_36/asmshader.l
@@ -194,11 +194,20 @@ ps_3_0                  {return VER_PS30;       }
 \_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} {
diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y
index 3f65fb3..a6d2db6 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -37,12 +37,29 @@ void asmshader_error(const char *s);
 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;
@@ -118,10 +135,12 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
 
 /* 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
@@ -131,6 +150,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
 %type <modshift> omods
 %type <modshift> omodifier
 %type <rel_reg> rel_reg
+%type <immval> immsum
 %type <sregs> sregs
 
 %%
@@ -523,12 +543,77 @@ rel_reg:               /* empty */
                             $$.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;
diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c
index 87f948b..725931c 100644
--- a/dlls/d3dx9_36/asmutils.c
+++ b/dlls/d3dx9_36/asmutils.c
@@ -231,8 +231,24 @@ const char *debug_print_writemask(DWORD mask) {
     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));
 }
 
@@ -275,16 +291,20 @@ const char *debug_print_swizzle(DWORD arg) {
 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";
diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c
index caf2c4b..0081576 100644
--- a/dlls/d3dx9_36/bytecodewriter.c
+++ b/dlls/d3dx9_36/bytecodewriter.c
@@ -219,7 +219,31 @@ static void sm_3_srcreg(struct bc_writer *This,
     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,
@@ -229,6 +253,17 @@ 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;
@@ -238,6 +273,13 @@ static void sm_3_dstreg(struct bc_writer *This,
 
     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[] = {
diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c
index 7056ef5..14b1e9c 100644
--- a/dlls/d3dx9_36/tests/asm.c
+++ b/dlls/d3dx9_36/tests/asm.c
@@ -1038,16 +1038,16 @@ static void vs_3_0_test(void) {
             "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",
-- 
1.6.4.4


More information about the wine-patches mailing list