diff mbox

[38/90] assembler: Make explicit that labels are part of the instructions list

Message ID 1359991705-5254-39-git-send-email-damien.lespiau@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lespiau, Damien Feb. 4, 2013, 3:27 p.m. UTC
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>
---
 assembler/disasm-main.c |    2 +-
 assembler/gen4asm.h     |   36 +++++++++++++++++++++----
 assembler/gram.y        |    7 +++--
 assembler/main.c        |   66 +++++++++++++++++++++++++++--------------------
 4 files changed, 73 insertions(+), 38 deletions(-)
diff mbox

Patch

diff --git a/assembler/disasm-main.c b/assembler/disasm-main.c
index b900e91..fbb6ae3 100644
--- a/assembler/disasm-main.c
+++ b/assembler/disasm-main.c
@@ -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);
 }
diff --git a/assembler/gen4asm.h b/assembler/gen4asm.h
index a2ab5e8..aa380e1 100644
--- a/assembler/gen4asm.h
+++ b/assembler/gen4asm.h
@@ -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);
diff --git a/assembler/gram.y b/assembler/gram.y
index a1c09f7..cf65f9f 100644
--- a/assembler/gram.y
+++ b/assembler/gram.y
@@ -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);
 }
 
diff --git a/assembler/main.c b/assembler/main.c
index 28daf3e..eb75230 100644
--- a/assembler/main.c
+++ b/assembler/main.c
@@ -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)