diff --git a/assembler/src/brw_structs.h b/assembler/src/brw_structs.h index dcc47fdd..61f7b34b 100644 --- a/assembler/src/brw_structs.h +++ b/assembler/src/brw_structs.h @@ -1336,6 +1336,7 @@ struct brw_instruction GLint id; GLfloat fd; } bits3; + char *reloc_target; }; diff --git a/assembler/src/gen4asm.h b/assembler/src/gen4asm.h index 696e3ab6..a965d112 100644 --- a/assembler/src/gen4asm.h +++ b/assembler/src/gen4asm.h @@ -106,11 +106,14 @@ typedef struct { /** * This structure is just the list container for instructions accumulated by - * the parser. + * the parser and labels. */ struct brw_program_instruction { struct brw_instruction instruction; struct brw_program_instruction *next; + GLuint islabel; + GLuint inst_offset; + char *string; }; /** diff --git a/assembler/src/gram.y b/assembler/src/gram.y index 7be3f11a..15f28afc 100644 --- a/assembler/src/gram.y +++ b/assembler/src/gram.y @@ -54,7 +54,7 @@ void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, %start ROOT %union { - char *s; + char *string; int integer; double number; struct brw_instruction instruction; @@ -71,6 +71,7 @@ void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, struct src_operand src_operand; } +%token COLON %token SEMICOLON %token LPAREN RPAREN %token LANGLE RANGLE @@ -108,6 +109,7 @@ void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, %token SATURATE %token INTEGER +%token STRING %token NUMBER %token INV LOG EXP SQRT RSQ POW SIN COS SINCOS INTDIV INTMOD @@ -122,6 +124,7 @@ void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, %type breakinstruction syncinstruction specialinstruction %type msgtarget %type instoptions instoption_list predicate +%type label %type instrseq %type instoption %type unaryop binaryop binaryaccop branchloopop breakop @@ -155,6 +158,13 @@ ROOT: instrseq } ; + +label: STRING COLON + { + $$ = $1; + } +; + instrseq: instruction SEMICOLON instrseq { struct brw_program_instruction *list_entry = @@ -176,6 +186,16 @@ instrseq: instruction SEMICOLON instrseq $$.first = list_entry; } + | label instrseq + { + struct brw_program_instruction *list_entry = + calloc(sizeof(struct brw_program_instruction), 1); + list_entry->string = $1; + list_entry->islabel = 1; + list_entry->next = $2.first; + $2.first = list_entry; + $$ = $2; + } | error SEMICOLON instrseq { $$ = $3; @@ -296,10 +316,7 @@ sendinstruction: predicate SEND execsize INTEGER post_dst payload msgtarget } ; -/* XXX: This should probably allow predication (i.e. be a branchloopop), - * though the BNF didn't specify it. - */ -jumpinstruction: JMPI relativelocation2 +jumpinstruction: predicate JMPI relativelocation2 { struct direct_reg dst; struct dst_operand ip_dst; @@ -315,12 +332,43 @@ jumpinstruction: JMPI relativelocation2 dst.subreg_nr = 0; bzero(&$$, sizeof($$)); - $$.header.opcode = $1; + $$.header.opcode = $2; set_direct_dst_operand(&ip_dst, &dst, BRW_REGISTER_TYPE_UD); + set_instruction_predicate(&$$, &$1); set_instruction_dest(&$$, &ip_dst); set_direct_src_operand(&ip_src, &dst, BRW_REGISTER_TYPE_UD); set_instruction_src0(&$$, &ip_src); - set_instruction_src1(&$$, &$2); + set_instruction_src1(&$$, &$3); + } + | predicate JMPI STRING + { + struct direct_reg dst; + struct dst_operand ip_dst; + struct src_operand ip_src; + struct src_operand imm; + + /* The jump instruction requires that the IP register + * be the destination and first source operand, while the + * offset is the second source operand. The next instruction + is the post-incremented IP plus the offset. + */ + dst.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + dst.reg_nr = BRW_ARF_IP; + dst.subreg_nr = 0; + memset (&imm, '\0', sizeof (imm)); + imm.reg_file = BRW_IMMEDIATE_VALUE; + imm.reg_type = BRW_REGISTER_TYPE_D; + imm.imm32 = 0; + + bzero(&$$, sizeof($$)); + $$.header.opcode = $2; + set_direct_dst_operand(&ip_dst, &dst, BRW_REGISTER_TYPE_UD); + set_instruction_dest(&$$, &ip_dst); + set_instruction_predicate(&$$, &$1); + set_direct_src_operand(&ip_src, &dst, BRW_REGISTER_TYPE_UD); + set_instruction_src0(&$$, &ip_src); + set_instruction_src1(&$$, &imm); + $$.reloc_target = $3; } ; diff --git a/assembler/src/lex.l b/assembler/src/lex.l index 17bb2339..c74d5b2a 100644 --- a/assembler/src/lex.l +++ b/assembler/src/lex.l @@ -5,6 +5,7 @@ #include "gram.h" #include "brw_defines.h" +#include "string.h" int saved_state = 0; extern char *input_filename; @@ -112,6 +113,7 @@ extern char *input_filename; "transpose" { return TRANSPOSE; } "interleave" { return INTERLEAVE; } +":" { return COLON; } ";" { return SEMICOLON; } "(" { return LPAREN; } ")" { return RPAREN; } @@ -171,7 +173,7 @@ extern char *input_filename; * rather than the reg number, to avoid a shift/reduce conflict in the * predicate control. */ -"f0.[0-9]+" { +"f0."[0-9]+ { yylval.integer = atoi(yytext + 3); return FLAGREG; } @@ -326,6 +328,11 @@ extern char *input_filename; return W; } +[a-zA-Z_][0-9a-zA-Z_]* { + yylval.string = strdup(yytext); + return STRING; +} + 0x[0-9a-fA-F][0-9a-fA-F]* { yylval.integer = strtoul(yytext + 2, NULL, 16); return INTEGER; diff --git a/assembler/src/main.c b/assembler/src/main.c index 1376ffa7..bfaef0e5 100644 --- a/assembler/src/main.c +++ b/assembler/src/main.c @@ -55,8 +55,8 @@ int main(int argc, char **argv) { char *output_file = NULL; FILE *output = stdout; - struct brw_program_instruction *entry; - int err; + struct brw_program_instruction *entry, *entry1; + int err, inst_offset; char o; while ((o = getopt_long(argc, argv, "o:", longopts, NULL)) != -1) { @@ -98,22 +98,54 @@ int main(int argc, char **argv) exit(1); } } + inst_offset = 0 ; for (entry = compiled_program.first; - entry != NULL; - entry = entry->next) { + entry != NULL; entry = entry->next) { + entry->inst_offset = inst_offset; + if (!entry->islabel) + inst_offset++; + } + + for (entry = compiled_program.first; + entry != NULL; entry = entry->next) { + if (!entry->islabel) { + if (entry->instruction.reloc_target) { + for (entry1 = entry; + entry1 != NULL; entry1 = entry1->next) { + if (entry1->islabel && + strcmp(entry1->string, + entry->instruction.reloc_target) == 0) { + int offset = + entry1->inst_offset - entry->inst_offset; + entry->instruction.bits3.ud = offset - 1; + break; + } + } + if (entry1 == NULL) + fprintf(stderr, "can not find lable %s\n", + entry->instruction.reloc_target); + } + } + } + + + for (entry = compiled_program.first; + entry != NULL; + entry = entry->next) { + if (!entry->islabel) fprintf(output, " { 0x%08x, 0x%08x, 0x%08x, 0x%08x },\n", - ((int *)(&entry->instruction))[0], - ((int *)(&entry->instruction))[1], - ((int *)(&entry->instruction))[2], - ((int *)(&entry->instruction))[3]); + ((int *)(&entry->instruction))[0], + ((int *)(&entry->instruction))[1], + ((int *)(&entry->instruction))[2], + ((int *)(&entry->instruction))[3]); } fflush (output); if (ferror (output)) { - perror ("Could not flush output file"); - if (output_file) - unlink (output_file); - err = 1; + perror ("Could not flush output file"); + if (output_file) + unlink (output_file); + err = 1; } return err; }