Add support for labeled and conditional branches

Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Zou Nanhai 2008-12-09 18:38:54 -08:00 committed by Damien Lespiau
parent 5a2ec836e1
commit be9bcee15f
5 changed files with 112 additions and 21 deletions

View File

@ -1336,6 +1336,7 @@ struct brw_instruction
GLint id;
GLfloat fd;
} bits3;
char *reloc_target;
};

View File

@ -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;
};
/**

View File

@ -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> INTEGER
%token <string> STRING
%token <number> NUMBER
%token <integer> 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 <instruction> breakinstruction syncinstruction specialinstruction
%type <instruction> msgtarget
%type <instruction> instoptions instoption_list predicate
%type <string> label
%type <program> instrseq
%type <integer> instoption
%type <integer> 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;
}
;

View File

@ -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;

View File

@ -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;
}