diff options
author | Tom Stellard <[email protected]> | 2013-03-10 20:55:26 -0400 |
---|---|---|
committer | Tom Stellard <[email protected]> | 2013-06-30 21:38:57 -0700 |
commit | e2c3640540dbe423d2c75d89615854aeb9f560f3 (patch) | |
tree | a2866c2cf8be3363db308171d3f5abd492433064 /src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c | |
parent | ab40d8d56f1cd6868a90fedd1dfaa87a3087bfa3 (diff) |
r300g/compiler/tests: Add an assembly parser
The assembly parser can be used to load r300 assembly dumps
and run them through any of the r300 compiler passes.
Reviewed-by: Alex Deucher <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c')
-rw-r--r-- | src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c | 161 |
1 files changed, 155 insertions, 6 deletions
diff --git a/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c b/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c index 551fe05ece2..af7b3cee48f 100644 --- a/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c +++ b/src/gallium/drivers/r300/compiler/tests/rc_test_helpers.c @@ -42,6 +42,7 @@ #include "radeon_program.h" #include "radeon_regalloc.h" #include "radeon_swizzle.h" +#include "util/u_math.h" #include "rc_test_helpers.h" @@ -61,6 +62,16 @@ struct match_info { int Length; }; +static int is_whitespace(const char *str) +{ + regex_t regex; + if (regcomp(®ex, "^[ \n]+$", REG_EXTENDED)) { + fprintf(stderr, "Failed to compile whitespace regex\n"); + return 0; + } + return regexec(®ex, str, 0, NULL, 0) != REG_NOMATCH; +} + static int match_length(regmatch_t * matches, int index) { return matches[index].rm_eo - matches[index].rm_so; @@ -124,7 +135,7 @@ int init_rc_normal_src( unsigned int src_index, const char * src_str) { - const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[([[:digit:]])\\](\\.*[[:lower:]-]*)"; + const char * regex_str = "(-*)(\\|*)([[:lower:]]*)\\[*([[:digit:]]*)\\]*(\\.*[[:lower:]_]*)"; regmatch_t matches[REGEX_SRC_MATCHES]; struct src_tokens tokens; struct rc_src_register * src_reg = &inst->U.I.SrcReg[src_index]; @@ -187,7 +198,8 @@ int init_rc_normal_src( fprintf(stderr, "First char of swizzle is not valid.\n"); return 0; } - for (i = 0; i < 4; i++, str_index++) { + for (i = 0; i < 4 && str_index < tokens.Swizzle.Length; + i++, str_index++) { if (tokens.Swizzle.String[str_index] == '-') { src_reg->Negate |= (1 << i); str_index++; @@ -218,7 +230,8 @@ int init_rc_normal_src( SET_SWZ(src_reg->Swizzle, i, RC_SWIZZLE_UNUSED); break; default: - fprintf(stderr, "Unknown src register swizzle.\n"); + fprintf(stderr, "Unknown src register swizzle: %c\n", + tokens.Swizzle.String[str_index]); return 0; } } @@ -251,7 +264,7 @@ int init_rc_normal_dst( struct rc_instruction * inst, const char * dst_str) { - const char * regex_str = "([[:lower:]]*)\\[([[:digit:]]*)\\](\\.*[[:lower:]]*)"; + const char * regex_str = "([[:lower:]]*)\\[*([[:digit:]]*)\\]*(\\.*[[:lower:]]*)"; regmatch_t matches[REGEX_DST_MATCHES]; struct dst_tokens tokens; unsigned int i; @@ -275,6 +288,9 @@ int init_rc_normal_dst( inst->U.I.DstReg.File = RC_FILE_TEMPORARY; } else if (!strncmp(tokens.File.String, "output", tokens.File.Length)) { inst->U.I.DstReg.File = RC_FILE_OUTPUT; + } else if (!strncmp(tokens.File.String, "none", tokens.File.Length)) { + inst->U.I.DstReg.File = RC_FILE_NONE; + return 1; } else { fprintf(stderr, "Unknown dst register file type.\n"); return 0; @@ -314,7 +330,8 @@ int init_rc_normal_dst( inst->U.I.DstReg.WriteMask |= RC_MASK_W; break; default: - fprintf(stderr, "Unknown swizzle in writemask.\n"); + fprintf(stderr, "Unknown swizzle in writemask: %c\n", + tokens.WriteMask.String[i]); return 0; } } @@ -327,6 +344,7 @@ int init_rc_normal_dst( } #define REGEX_INST_MATCHES 7 +#define REGEX_CONST_MATCHES 5 struct inst_tokens { struct match_info Opcode; @@ -351,7 +369,7 @@ int parse_rc_normal_instruction( struct rc_instruction * inst, const char * inst_str) { - const char * regex_str = "([[:upper:]]+)(_SAT)* ([^,]*)[, ]*([^,]*)[, ]*([^,]*)[, ]*([^;]*)"; + const char * regex_str = "[[:digit:]: ]*([[:upper:][:digit:]]+)(_SAT)*[ ]*([^,;]*)[, ]*([^,;]*)[, ]*([^,;]*)[, ]*([^;]*)"; int i; regmatch_t matches[REGEX_INST_MATCHES]; struct inst_tokens tokens; @@ -408,11 +426,24 @@ int parse_rc_normal_instruction( src_str[tokens.Srcs[j].Length] = '\0'; init_rc_normal_src(inst, j, src_str); } + if (info->HasTexture) { + /* XXX: Will this always be XYZW ? */ + inst->U.I.TexSwizzle = RC_SWIZZLE_XYZW; + } break; } return 1; } +#define INDEX_TOKEN_LEN 4 +#define FLOAT_TOKEN_LEN 50 +int parse_constant(unsigned *index, float *data, const char *const_str) +{ + int matched = sscanf(const_str, "const[%d] {%f, %f, %f, %f}", index, + &data[0], &data[1], &data[2], &data[3]); + return matched == 5; +} + int init_rc_normal_instruction( struct rc_instruction * inst, const char * inst_str) @@ -432,6 +463,44 @@ void add_instruction(struct radeon_compiler *c, const char * inst_string) } +int add_constant(struct radeon_compiler *c, const char *const_str) +{ + float data[4]; + unsigned index; + struct rc_constant_list *constants; + struct rc_constant constant; + + if (!parse_constant(&index, data, const_str)) { + return 0; + } + + constants = &c->Program.Constants; + if (constants->_Reserved < index) { + struct rc_constant * newlist; + + constants->_Reserved = index + 100; + + newlist = malloc(sizeof(struct rc_constant) * constants->_Reserved); + if (constants->Constants) { + memcpy(newlist, constants->Constants, + sizeof(struct rc_constant) * + constants->_Reserved); + free(constants->Constants); + } + + constants->Constants = newlist; + } + + memset(&constant, 0, sizeof(constant)); + constant.Type = RC_CONSTANT_IMMEDIATE; + constant.Size = 4; + memcpy(constant.u.Immediate, data, sizeof(float) * 4); + constants->Constants[index] = constant; + constants->Count = MAX2(constants->Count, index + 1); + + return 1; +} + void init_compiler( struct radeon_compiler *c, enum rc_program_type program_type, @@ -439,6 +508,7 @@ void init_compiler( unsigned is_r400) { struct rc_regalloc_state *rs = malloc(sizeof(struct rc_regalloc_state)); + rc_init_regalloc_state(rs); rc_init(c, rs); c->is_r500 = is_r500; @@ -456,3 +526,82 @@ void init_compiler( c->SwizzleCaps = &r300_vertprog_swizzle_caps; } } + +#define MAX_LINE_LENGTH 100 +#define MAX_PATH_LENGTH 100 + +unsigned load_program( + struct radeon_compiler *c, + struct rc_test_file *test, + const char *filename) +{ + char line[MAX_LINE_LENGTH]; + char path[MAX_PATH_LENGTH]; + FILE *file; + unsigned *count; + char **string_store; + unsigned i = 0; + + snprintf(path, MAX_PATH_LENGTH, "compiler/tests/%s", filename); + file = fopen(path, "r"); + if (!file) { + return 0; + } + memset(test, 0, sizeof(struct rc_test_file)); + + count = &test->num_input_lines; + + while (fgets(line, MAX_LINE_LENGTH, file)){ + if (line[MAX_LINE_LENGTH - 2] == '\n') { + fprintf(stderr, "Error line cannot be longer than 100 " + "characters:\n%s\n", line); + return 0; + } + + // Comment + if (line[0] == '#' || is_whitespace(line)) { + continue; + } + + if (line[0] == '=') { + count = &test->num_expected_lines; + continue; + } + + (*count)++; + } + + test->input = malloc(sizeof(char *) * test->num_input_lines); + test->expected = malloc(sizeof(char *) * test->num_expected_lines); + + rewind(file); + string_store = test->input; + + while(fgets(line, MAX_LINE_LENGTH, file)) { + // Comment + char * dst; + if (line[0] == '#' || is_whitespace(line)) { + continue; + } + + if (line[0] == '=') { + i = 0; + string_store = test->expected; + continue; + } + + dst = string_store[i++] = malloc((strlen(line) + 1) * + sizeof (char)); + strcpy(dst, line); + } + + for (i = 0; i < test->num_input_lines; i++) { + if (test->input[i][0] == 'c') { + add_constant(c, test->input[i]); + continue; + } + // XXX: Parse immediates from the file. + add_instruction(c, test->input[i]); + } + return 1; +} |