diff --git a/src/libgrate/fragment_asm.h b/src/libgrate/fragment_asm.h index 4483375..ee628d0 100644 --- a/src/libgrate/fragment_asm.h +++ b/src/libgrate/fragment_asm.h @@ -252,6 +252,18 @@ typedef union fragment_alu_instruction_x4 { } alu_instr; typedef union fragment_pseq_instruction { + struct __attribute__((packed)) { + unsigned unk_0:1; + unsigned dst_regs_select:1; + unsigned unk_2:1; + unsigned enable0:1; + unsigned unk_4_15:12; + unsigned rt_select:4; + unsigned unk_20_22:3; + unsigned enable1:1; + unsigned unk_24_31:8; + }; + uint32_t data; } pseq_instr; diff --git a/src/libgrate/fragment_asm.l b/src/libgrate/fragment_asm.l index cb741ec..061dacf 100644 --- a/src/libgrate/fragment_asm.l +++ b/src/libgrate/fragment_asm.l @@ -39,7 +39,14 @@ int yywrap(void) %% [ \t]+ /* skip */; -"/*"([^*]|(\*+[^*/]))*\*+\/ /* multi line comment */; +"/*"([^*]|(\*+[^*/]))*\*+\/ { + /* multi line comment */ + unsigned i; + + for (i = 0; i < strlen(yytext); i++) + if (yytext[i] == '\n') + yylineno++; + } "//".* /* single line comment */; [\n] yylineno++; @@ -209,10 +216,12 @@ TXB return T_TXB_OPCODE; rt[0-9]{1,2} { fragment_asmlval.u = atoi(yytext + 2); - return T_DW_RENDER_TARGET; + return T_RENDER_TARGET; } "stencil" return T_DW_STENCIL; +FETCH return T_FETCH; + . return T_SYNTAX_ERROR; %% diff --git a/src/libgrate/fragment_asm.y b/src/libgrate/fragment_asm.y index 9736cf5..44a6550 100644 --- a/src/libgrate/fragment_asm.y +++ b/src/libgrate/fragment_asm.y @@ -21,6 +21,7 @@ */ %{ +#include #include #include #include @@ -65,6 +66,8 @@ unsigned asm_pseq_to_dw_exec_nb; int asm_discards_fragment; +static bool asm_alu_used[4]; + static void reset_fragment_asm_parser_state(void) { int i, k; @@ -94,6 +97,8 @@ static void reset_fragment_asm_parser_state(void) asm_discards_fragment = 0; fragment_asmlineno = 1; + + memset(asm_alu_used, 0, sizeof(asm_alu_used)); } static uint32_t float_to_fp20(float f) @@ -228,7 +233,7 @@ static uint32_t float_to_fx10(float f) %token T_DW_STORE %token T_DW_STENCIL -%token T_DW_RENDER_TARGET +%token T_RENDER_TARGET %token T_HEX %token T_FLOAT @@ -263,6 +268,8 @@ static uint32_t float_to_fx10(float f) %token T_ALU_BUFFER_SIZE %token T_PSEQ_DW_EXEC_NB +%token T_FETCH + %union { char c; float f; @@ -481,6 +488,27 @@ PSEQ_INSTRUCTION: asm_pseq_instructions[asm_fs_instructions_nb].data = $2; } | + T_PSEQ T_FETCH T_ROW_REGISTER ',' T_ROW_REGISTER ',' T_RENDER_TARGET + { + if ($3 == 0 && $5 == 1) { + asm_pseq_instructions[asm_fs_instructions_nb].dst_regs_select = 0; + } + else if ($3 == 2 && $5 == 3) { + asm_pseq_instructions[asm_fs_instructions_nb].dst_regs_select = 1; + } + else { + PARSE_ERROR("PSEQ destination registers should be either \"r0,r1\" or \"r2,r3\""); + } + + if ($7 > 15) { + PARSE_ERROR("Invalid PSEQ render target, 15 is maximum"); + } + + asm_pseq_instructions[asm_fs_instructions_nb].rt_select = $7; + asm_pseq_instructions[asm_fs_instructions_nb].enable0 = 1; + asm_pseq_instructions[asm_fs_instructions_nb].enable1 = 1; + } + | T_PSEQ T_OPCODE_NOP | ; @@ -831,6 +859,8 @@ ALU_INSTRUCTION: T_ALU ALUX_INSTRUCTIONS asm_alu_sched[asm_fs_instructions_nb].instructions_nb++; asm_alu_sched[asm_fs_instructions_nb].address = address; asm_alu_instructions_nb++; + + memset(asm_alu_used, 0, sizeof(asm_alu_used)); } ; @@ -848,6 +878,12 @@ ALUX_INSTRUCTIONS: ALUX_INSTRUCTION: T_ALUX ALU_OPERATION { + if (asm_alu_used[$1]) { + PARSE_ERROR("ALU has been overridden"); + } else { + asm_alu_used[$1] = true; + } + asm_alu_instructions[asm_alu_instructions_nb].a[$1] = $2; } | @@ -855,6 +891,12 @@ ALUX_INSTRUCTION: { uint32_t swap = asm_alu_instructions[asm_alu_instructions_nb].part7; + if (asm_alu_used[$1]) { + PARSE_ERROR("ALU has been overridden"); + } else { + asm_alu_used[$1] = true; + } + if ($1 != 3) { PARSE_ERROR("ALU immediates can override ALU3 only"); } @@ -1488,7 +1530,7 @@ DW_INSTRUCTION: asm_dw_instructions[asm_fs_instructions_nb].data = $2; } | - T_DW T_DW_STORE T_DW_RENDER_TARGET ',' T_ROW_REGISTER ',' T_ROW_REGISTER + T_DW T_DW_STORE T_RENDER_TARGET ',' T_ROW_REGISTER ',' T_ROW_REGISTER { asm_dw_instructions[asm_fs_instructions_nb].enable = 1; diff --git a/src/libgrate/fragment_disasm.c b/src/libgrate/fragment_disasm.c index 22547a5..52b4c78 100644 --- a/src/libgrate/fragment_disasm.c +++ b/src/libgrate/fragment_disasm.c @@ -704,6 +704,29 @@ static const char * disassemble_dw(const dw_instr *dw) return ret; } +static const char * disassemble_pseq(const pseq_instr *pseq) +{ + static char ret[64]; + char *buf = ret; + + buf += sprintf(buf, "fetch "); + + if (pseq->dst_regs_select) { + buf += sprintf(buf, "r2, r3, "); + } else { + buf += sprintf(buf, "r0, r1, "); + } + + buf += sprintf(buf, "rt%u", pseq->rt_select); + + if (pseq->unk_0 || pseq->unk_2 || pseq->unk_4_15 || + pseq->unk_20_22 || pseq->unk_24_31) { + sprintf(buf, " // 0x%08X", pseq->data); + } + + return ret; +} + const char * fragment_pipeline_disassemble( const pseq_instr *pseq, const mfu_instr *mfu, unsigned mfu_nb, @@ -726,7 +749,7 @@ const char * fragment_pipeline_disassemble( buf += sprintf(buf, "EXEC\n"); if (pseq->data != 0x00000000) { - buf += sprintf(buf, "\tPSEQ:\t0x%08X\n", pseq->data); + buf += sprintf(buf, "\tPSEQ:\t%s\n", disassemble_pseq(pseq)); } for (i = 0; i < mfu_nb; i++) { diff --git a/src/libgrate/linker_asm.l b/src/libgrate/linker_asm.l index 29330ff..a182d17 100644 --- a/src/libgrate/linker_asm.l +++ b/src/libgrate/linker_asm.l @@ -39,7 +39,14 @@ int yywrap(void) %% [ \t]+ /* skip */; -"/*"([^*]|(\*+[^*/]))*\*+\/ /* multi line comment */; +"/*"([^*]|(\*+[^*/]))*\*+\/ { + /* multi line comment */ + unsigned i; + + for (i = 0; i < strlen(yytext); i++) + if (yytext[i] == '\n') + yylineno++; + } "//".* /* single line comment */; [\n] yylineno++; "." return '.'; diff --git a/src/libgrate/vertex_asm.l b/src/libgrate/vertex_asm.l index a09ed4d..b56e35d 100644 --- a/src/libgrate/vertex_asm.l +++ b/src/libgrate/vertex_asm.l @@ -38,7 +38,14 @@ int yywrap(void) %% [ \t]+ /* skip */; -"/*"([^*]|(\*+[^*/]))*\*+\/ /* multi line comment */; +"/*"([^*]|(\*+[^*/]))*\*+\/ { + /* multi line comment */ + unsigned i; + + for (i = 0; i < strlen(yytext); i++) + if (yytext[i] == '\n') + yylineno++; + } "//".* /* single line comment */; [\n] yylineno++;