mirror of
https://github.com/tiagovignatti/intel-gpu-tools.git
synced 2025-06-09 17:06:14 +00:00
assembler: Make explicit that labels are part of the instructions list
The output of the parsing is a list of struct brw_program_instruction. These instructions can be either GEN instructions aka struct brw_instruction or labels. To make this more explicit we now have a type to test to determine which instruction we are dealing with. This will also allow to to pull the relocation bits into struct brw_program_instruction instead of having them in the structure representing the opcodes. Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
This commit is contained in:
parent
73d58edab9
commit
a45a47183a
@ -167,6 +167,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
for (inst = program->first; inst; inst = inst->next)
|
||||
brw_disasm (output, &inst->instruction, gen);
|
||||
brw_disasm (output, &inst->instruction.gen, gen);
|
||||
exit (0);
|
||||
}
|
||||
|
@ -30,6 +30,8 @@
|
||||
#define __GEN4ASM_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef unsigned char GLubyte;
|
||||
typedef short GLshort;
|
||||
@ -133,18 +135,40 @@ typedef struct {
|
||||
} u;
|
||||
} imm32_t;
|
||||
|
||||
enum assembler_instruction_type {
|
||||
GEN4ASM_INSTRUCTION_GEN,
|
||||
GEN4ASM_INSTRUCTION_LABEL,
|
||||
};
|
||||
|
||||
struct label_instruction {
|
||||
char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure is just the list container for instructions accumulated by
|
||||
* the parser and labels.
|
||||
*/
|
||||
struct brw_program_instruction {
|
||||
struct brw_instruction instruction;
|
||||
struct brw_program_instruction *next;
|
||||
GLuint islabel;
|
||||
GLuint inst_offset;
|
||||
char *string;
|
||||
enum assembler_instruction_type type;
|
||||
unsigned inst_offset;
|
||||
union {
|
||||
struct brw_instruction gen;
|
||||
struct label_instruction label;
|
||||
} instruction;
|
||||
struct brw_program_instruction *next;
|
||||
};
|
||||
|
||||
static inline bool is_label(struct brw_program_instruction *instruction)
|
||||
{
|
||||
return instruction->type == GEN4ASM_INSTRUCTION_LABEL;
|
||||
}
|
||||
|
||||
static inline char *label_name(struct brw_program_instruction *i)
|
||||
{
|
||||
assert(is_label(i));
|
||||
return i->instruction.label.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This structure is a list of instructions. It is the final output of the
|
||||
* parser.
|
||||
@ -188,7 +212,7 @@ struct declared_register {
|
||||
};
|
||||
struct declared_register *find_register(char *name);
|
||||
void insert_register(struct declared_register *reg);
|
||||
void add_label(char *name, int addr);
|
||||
void add_label(struct brw_program_instruction *instruction);
|
||||
int label_to_addr(char *name, int start_addr);
|
||||
|
||||
int yyparse(void);
|
||||
|
@ -119,7 +119,8 @@ static void brw_program_add_instruction(struct brw_program *p,
|
||||
struct brw_program_instruction *list_entry;
|
||||
|
||||
list_entry = calloc(sizeof(struct brw_program_instruction), 1);
|
||||
list_entry->instruction = *instruction;
|
||||
list_entry->type = GEN4ASM_INSTRUCTION_GEN;
|
||||
list_entry->instruction.gen = *instruction;
|
||||
brw_program_append_entry(p, list_entry);
|
||||
}
|
||||
|
||||
@ -128,8 +129,8 @@ static void brw_program_add_label(struct brw_program *p, const char *label)
|
||||
struct brw_program_instruction *list_entry;
|
||||
|
||||
list_entry = calloc(sizeof(struct brw_program_instruction), 1);
|
||||
list_entry->string = strdup(label);
|
||||
list_entry->islabel = 1;
|
||||
list_entry->type = GEN4ASM_INSTRUCTION_LABEL;
|
||||
list_entry->instruction.label.name = strdup(label);
|
||||
brw_program_append_entry(p, list_entry);
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gen4asm.h"
|
||||
|
||||
@ -154,14 +155,17 @@ void insert_register(struct declared_register *reg)
|
||||
insert_hash_item(declared_register_table, reg->name, reg);
|
||||
}
|
||||
|
||||
void add_label(char *name, int addr)
|
||||
void add_label(struct brw_program_instruction *i)
|
||||
{
|
||||
struct label_item **p = &label_table;
|
||||
|
||||
assert(is_label(i));
|
||||
|
||||
while(*p)
|
||||
p = &((*p)->next);
|
||||
*p = calloc(1, sizeof(**p));
|
||||
(*p)->name = name;
|
||||
(*p)->addr = addr;
|
||||
(*p)->name = label_name(i);
|
||||
(*p)->addr = i->inst_offset;
|
||||
}
|
||||
|
||||
/* Some assembly code have duplicated labels.
|
||||
@ -220,11 +224,14 @@ static int read_entry_file(char *fn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_entry_point(char *s)
|
||||
static int is_entry_point(struct brw_program_instruction *i)
|
||||
{
|
||||
struct entry_point_item *p;
|
||||
|
||||
assert(i->type == GEN4ASM_INSTRUCTION_LABEL);
|
||||
|
||||
for (p = entry_point_table; p; p = p->next) {
|
||||
if (strcmp(p->str, s) == 0)
|
||||
if (strcmp(p->str, i->instruction.label.name) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -379,24 +386,24 @@ int main(int argc, char **argv)
|
||||
entry != NULL; entry = entry->next) {
|
||||
entry->inst_offset = inst_offset;
|
||||
entry1 = entry->next;
|
||||
if (entry1 && entry1->islabel && is_entry_point(entry1->string)) {
|
||||
if (entry1 && is_label(entry1) && is_entry_point(entry1)) {
|
||||
// insert NOP instructions until (inst_offset+1) % 4 == 0
|
||||
while (((inst_offset+1) % 4) != 0) {
|
||||
tmp_entry = calloc(sizeof(*tmp_entry), 1);
|
||||
tmp_entry->instruction.header.opcode = BRW_OPCODE_NOP;
|
||||
tmp_entry->instruction.gen.header.opcode = BRW_OPCODE_NOP;
|
||||
entry->next = tmp_entry;
|
||||
tmp_entry->next = entry1;
|
||||
entry = tmp_entry;
|
||||
tmp_entry->inst_offset = ++inst_offset;
|
||||
}
|
||||
}
|
||||
if (!entry->islabel)
|
||||
if (!is_label(entry))
|
||||
inst_offset++;
|
||||
}
|
||||
|
||||
for (entry = compiled_program.first; entry; entry = entry->next)
|
||||
if (entry->islabel)
|
||||
add_label(entry->string, entry->inst_offset);
|
||||
if (is_label(entry))
|
||||
add_label(entry);
|
||||
|
||||
if (need_export) {
|
||||
if (export_filename) {
|
||||
@ -406,15 +413,18 @@ int main(int argc, char **argv)
|
||||
}
|
||||
for (entry = compiled_program.first;
|
||||
entry != NULL; entry = entry->next) {
|
||||
if (entry->islabel)
|
||||
if (is_label(entry))
|
||||
fprintf(export_file, "#define %s_IP %d\n",
|
||||
entry->string, (IS_GENx(5) ? 2 : 1)*(entry->inst_offset));
|
||||
label_name(entry), (IS_GENx(5) ? 2 : 1)*(entry->inst_offset));
|
||||
}
|
||||
fclose(export_file);
|
||||
}
|
||||
|
||||
for (entry = compiled_program.first; entry; entry = entry->next) {
|
||||
struct brw_instruction *inst = & entry->instruction;
|
||||
struct brw_instruction *inst = & entry->instruction.gen;
|
||||
|
||||
if (is_label(entry))
|
||||
continue;
|
||||
|
||||
if (inst->first_reloc_target)
|
||||
inst->first_reloc_offset = label_to_addr(inst->first_reloc_target, entry->inst_offset) - entry->inst_offset;
|
||||
@ -424,14 +434,14 @@ int main(int argc, char **argv)
|
||||
|
||||
if (inst->second_reloc_offset) {
|
||||
// this is a branch instruction with two offset arguments
|
||||
entry->instruction.bits3.break_cont.jip = jump_distance(inst->first_reloc_offset);
|
||||
entry->instruction.bits3.break_cont.uip = jump_distance(inst->second_reloc_offset);
|
||||
inst->bits3.break_cont.jip = jump_distance(inst->first_reloc_offset);
|
||||
inst->bits3.break_cont.uip = jump_distance(inst->second_reloc_offset);
|
||||
} else if (inst->first_reloc_offset) {
|
||||
// this is a branch instruction with one offset argument
|
||||
int offset = inst->first_reloc_offset;
|
||||
/* bspec: Unlike other flow control instructions, the offset used by JMPI is relative to the incremented instruction pointer rather than the IP value for the instruction itself. */
|
||||
|
||||
int is_jmpi = entry->instruction.header.opcode == BRW_OPCODE_JMPI; // target relative to the post-incremented IP, so delta == 1 if JMPI
|
||||
int is_jmpi = inst->header.opcode == BRW_OPCODE_JMPI; // target relative to the post-incremented IP, so delta == 1 if JMPI
|
||||
if(is_jmpi)
|
||||
offset --;
|
||||
offset = jump_distance(offset);
|
||||
@ -439,25 +449,25 @@ int main(int argc, char **argv)
|
||||
offset = offset * 8;
|
||||
|
||||
if(!IS_GENp(6)) {
|
||||
entry->instruction.bits3.JIP = offset;
|
||||
if(entry->instruction.header.opcode == BRW_OPCODE_ELSE)
|
||||
entry->instruction.bits3.break_cont.uip = 1; /* Set the istack pop count, which must always be 1. */
|
||||
inst->bits3.JIP = offset;
|
||||
if(inst->header.opcode == BRW_OPCODE_ELSE)
|
||||
inst->bits3.break_cont.uip = 1; /* Set the istack pop count, which must always be 1. */
|
||||
} else if(IS_GENx(6)) {
|
||||
/* TODO: endif JIP pos is not in Gen6 spec. may be bits1 */
|
||||
int opcode = entry->instruction.header.opcode;
|
||||
int opcode = inst->header.opcode;
|
||||
if(opcode == BRW_OPCODE_CALL || opcode == BRW_OPCODE_JMPI)
|
||||
entry->instruction.bits3.JIP = offset; // for CALL, JMPI
|
||||
inst->bits3.JIP = offset; // for CALL, JMPI
|
||||
else
|
||||
entry->instruction.bits1.branch_gen6.jump_count = offset; // for CASE,ELSE,FORK,IF,WHILE
|
||||
inst->bits1.branch_gen6.jump_count = offset; // for CASE,ELSE,FORK,IF,WHILE
|
||||
} else if(IS_GENp(7)) {
|
||||
int opcode = entry->instruction.header.opcode;
|
||||
int opcode = inst->header.opcode;
|
||||
/* Gen7 JMPI Restrictions in bspec:
|
||||
* The JIP data type must be Signed DWord
|
||||
*/
|
||||
if(opcode == BRW_OPCODE_JMPI)
|
||||
entry->instruction.bits3.JIP = offset;
|
||||
inst->bits3.JIP = offset;
|
||||
else
|
||||
entry->instruction.bits3.break_cont.jip = offset;
|
||||
inst->bits3.break_cont.jip = offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -469,10 +479,10 @@ int main(int argc, char **argv)
|
||||
entry != NULL;
|
||||
entry = entry1) {
|
||||
entry1 = entry->next;
|
||||
if (!entry->islabel)
|
||||
print_instruction(output, &entry->instruction);
|
||||
if (!is_label(entry))
|
||||
print_instruction(output, &entry->instruction.gen);
|
||||
else
|
||||
free(entry->string);
|
||||
free(entry->instruction.label.name);
|
||||
free(entry);
|
||||
}
|
||||
if (binary_like_output)
|
||||
|
Loading…
x
Reference in New Issue
Block a user