xref: /aosp_15_r20/external/igt-gpu-tools/assembler/main.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /* -*- c-basic-offset: 8 -*- */
2*d83cc019SAndroid Build Coastguard Worker /*
3*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2006 Intel Corporation
4*d83cc019SAndroid Build Coastguard Worker  *
5*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
6*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
7*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
8*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
10*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
11*d83cc019SAndroid Build Coastguard Worker  *
12*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
13*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
14*d83cc019SAndroid Build Coastguard Worker  * Software.
15*d83cc019SAndroid Build Coastguard Worker  *
16*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*d83cc019SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*d83cc019SAndroid Build Coastguard Worker  * SOFTWARE.
23*d83cc019SAndroid Build Coastguard Worker  *
24*d83cc019SAndroid Build Coastguard Worker  * Authors:
25*d83cc019SAndroid Build Coastguard Worker  *    Eric Anholt <[email protected]>
26*d83cc019SAndroid Build Coastguard Worker  *
27*d83cc019SAndroid Build Coastguard Worker  */
28*d83cc019SAndroid Build Coastguard Worker 
29*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
30*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
31*d83cc019SAndroid Build Coastguard Worker #include <string.h>
32*d83cc019SAndroid Build Coastguard Worker #include <getopt.h>
33*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
34*d83cc019SAndroid Build Coastguard Worker #include <assert.h>
35*d83cc019SAndroid Build Coastguard Worker 
36*d83cc019SAndroid Build Coastguard Worker #include "ralloc.h"
37*d83cc019SAndroid Build Coastguard Worker #include "gen4asm.h"
38*d83cc019SAndroid Build Coastguard Worker #include "brw_eu.h"
39*d83cc019SAndroid Build Coastguard Worker 
40*d83cc019SAndroid Build Coastguard Worker extern FILE *yyin;
41*d83cc019SAndroid Build Coastguard Worker extern void set_branch_two_offsets(struct brw_program_instruction *insn, int jip_offset, int uip_offset);
42*d83cc019SAndroid Build Coastguard Worker extern void set_branch_one_offset(struct brw_program_instruction *insn, int jip_offset);
43*d83cc019SAndroid Build Coastguard Worker 
44*d83cc019SAndroid Build Coastguard Worker long int gen_level = 40;
45*d83cc019SAndroid Build Coastguard Worker int advanced_flag = 0; /* 0: in unit of byte, 1: in unit of data element size */
46*d83cc019SAndroid Build Coastguard Worker unsigned int warning_flags = WARN_ALWAYS;
47*d83cc019SAndroid Build Coastguard Worker int need_export = 0;
48*d83cc019SAndroid Build Coastguard Worker char *input_filename = "<stdin>";
49*d83cc019SAndroid Build Coastguard Worker int errors;
50*d83cc019SAndroid Build Coastguard Worker 
51*d83cc019SAndroid Build Coastguard Worker struct brw_context genasm_brw_context;
52*d83cc019SAndroid Build Coastguard Worker struct brw_compile genasm_compile;
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker struct brw_program compiled_program;
55*d83cc019SAndroid Build Coastguard Worker struct program_defaults program_defaults = {.register_type = BRW_REGISTER_TYPE_F};
56*d83cc019SAndroid Build Coastguard Worker 
57*d83cc019SAndroid Build Coastguard Worker /* 0: default output style, 1: nice C-style output */
58*d83cc019SAndroid Build Coastguard Worker static int binary_like_output = 0;
59*d83cc019SAndroid Build Coastguard Worker static char *export_filename = NULL;
60*d83cc019SAndroid Build Coastguard Worker static const char binary_prepend[] = "static const char gen_eu_bytes[] = {\n";
61*d83cc019SAndroid Build Coastguard Worker 
62*d83cc019SAndroid Build Coastguard Worker #define HASH_SIZE 37
63*d83cc019SAndroid Build Coastguard Worker 
64*d83cc019SAndroid Build Coastguard Worker struct hash_item {
65*d83cc019SAndroid Build Coastguard Worker 	char *key;
66*d83cc019SAndroid Build Coastguard Worker 	void *value;
67*d83cc019SAndroid Build Coastguard Worker 	struct hash_item *next;
68*d83cc019SAndroid Build Coastguard Worker };
69*d83cc019SAndroid Build Coastguard Worker 
70*d83cc019SAndroid Build Coastguard Worker typedef struct hash_item *hash_table[HASH_SIZE];
71*d83cc019SAndroid Build Coastguard Worker 
72*d83cc019SAndroid Build Coastguard Worker static hash_table declared_register_table;
73*d83cc019SAndroid Build Coastguard Worker 
74*d83cc019SAndroid Build Coastguard Worker struct label_item {
75*d83cc019SAndroid Build Coastguard Worker 	char *name;
76*d83cc019SAndroid Build Coastguard Worker 	int addr;
77*d83cc019SAndroid Build Coastguard Worker 	struct label_item *next;
78*d83cc019SAndroid Build Coastguard Worker };
79*d83cc019SAndroid Build Coastguard Worker static struct label_item *label_table;
80*d83cc019SAndroid Build Coastguard Worker 
81*d83cc019SAndroid Build Coastguard Worker static const struct option longopts[] = {
82*d83cc019SAndroid Build Coastguard Worker 	{"advanced", no_argument, 0, 'a'},
83*d83cc019SAndroid Build Coastguard Worker 	{"binary", no_argument, 0, 'b'},
84*d83cc019SAndroid Build Coastguard Worker 	{"export", required_argument, 0, 'e'},
85*d83cc019SAndroid Build Coastguard Worker 	{"input_list", required_argument, 0, 'l'},
86*d83cc019SAndroid Build Coastguard Worker 	{"output", required_argument, 0, 'o'},
87*d83cc019SAndroid Build Coastguard Worker 	{"gen", required_argument, 0, 'g'},
88*d83cc019SAndroid Build Coastguard Worker 	{ NULL, 0, NULL, 0 }
89*d83cc019SAndroid Build Coastguard Worker };
90*d83cc019SAndroid Build Coastguard Worker 
usage(void)91*d83cc019SAndroid Build Coastguard Worker static void usage(void)
92*d83cc019SAndroid Build Coastguard Worker {
93*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "usage: intel-gen4asm [options] inputfile\n");
94*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "OPTIONS:\n");
95*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-a, --advanced                       Set advanced flag\n");
96*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-b, --binary                         C style binary output\n");
97*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-e, --export {exportfile}            Export label file\n");
98*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-l, --input_list {entrytablefile}    Input entry_table_list file\n");
99*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-o, --output {outputfile}            Specify output file\n");
100*d83cc019SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-g, --gen <4|5|6|7|8|9>              Specify GPU generation\n");
101*d83cc019SAndroid Build Coastguard Worker }
102*d83cc019SAndroid Build Coastguard Worker 
hash(char * key)103*d83cc019SAndroid Build Coastguard Worker static int hash(char *key)
104*d83cc019SAndroid Build Coastguard Worker {
105*d83cc019SAndroid Build Coastguard Worker     unsigned ret = 0;
106*d83cc019SAndroid Build Coastguard Worker     while(*key)
107*d83cc019SAndroid Build Coastguard Worker         ret = (ret << 1) + (*key++);
108*d83cc019SAndroid Build Coastguard Worker     return ret % HASH_SIZE;
109*d83cc019SAndroid Build Coastguard Worker }
110*d83cc019SAndroid Build Coastguard Worker 
find_hash_item(hash_table t,char * key)111*d83cc019SAndroid Build Coastguard Worker static void *find_hash_item(hash_table t, char *key)
112*d83cc019SAndroid Build Coastguard Worker {
113*d83cc019SAndroid Build Coastguard Worker     struct hash_item *p;
114*d83cc019SAndroid Build Coastguard Worker     for(p = t[hash(key)]; p; p = p->next)
115*d83cc019SAndroid Build Coastguard Worker 	if(strcasecmp(p->key, key) == 0)
116*d83cc019SAndroid Build Coastguard Worker 	    return p->value;
117*d83cc019SAndroid Build Coastguard Worker     return NULL;
118*d83cc019SAndroid Build Coastguard Worker }
119*d83cc019SAndroid Build Coastguard Worker 
insert_hash_item(hash_table t,char * key,void * v)120*d83cc019SAndroid Build Coastguard Worker static void insert_hash_item(hash_table t, char *key, void *v)
121*d83cc019SAndroid Build Coastguard Worker {
122*d83cc019SAndroid Build Coastguard Worker     int index = hash(key);
123*d83cc019SAndroid Build Coastguard Worker     struct hash_item *p = malloc(sizeof(*p));
124*d83cc019SAndroid Build Coastguard Worker     p->key = key;
125*d83cc019SAndroid Build Coastguard Worker     p->value = v;
126*d83cc019SAndroid Build Coastguard Worker     p->next = t[index];
127*d83cc019SAndroid Build Coastguard Worker     t[index] = p;
128*d83cc019SAndroid Build Coastguard Worker }
129*d83cc019SAndroid Build Coastguard Worker 
free_hash_table(hash_table t)130*d83cc019SAndroid Build Coastguard Worker static void free_hash_table(hash_table t)
131*d83cc019SAndroid Build Coastguard Worker {
132*d83cc019SAndroid Build Coastguard Worker     struct hash_item *p, *next;
133*d83cc019SAndroid Build Coastguard Worker     int i;
134*d83cc019SAndroid Build Coastguard Worker     for (i = 0; i < HASH_SIZE; i++) {
135*d83cc019SAndroid Build Coastguard Worker 	p = t[i];
136*d83cc019SAndroid Build Coastguard Worker 	while(p) {
137*d83cc019SAndroid Build Coastguard Worker 	    next = p->next;
138*d83cc019SAndroid Build Coastguard Worker 	    free(p->key);
139*d83cc019SAndroid Build Coastguard Worker 	    free(p->value);
140*d83cc019SAndroid Build Coastguard Worker 	    free(p);
141*d83cc019SAndroid Build Coastguard Worker 	    p = next;
142*d83cc019SAndroid Build Coastguard Worker 	}
143*d83cc019SAndroid Build Coastguard Worker     }
144*d83cc019SAndroid Build Coastguard Worker }
145*d83cc019SAndroid Build Coastguard Worker 
find_register(char * name)146*d83cc019SAndroid Build Coastguard Worker struct declared_register *find_register(char *name)
147*d83cc019SAndroid Build Coastguard Worker {
148*d83cc019SAndroid Build Coastguard Worker     return find_hash_item(declared_register_table, name);
149*d83cc019SAndroid Build Coastguard Worker }
150*d83cc019SAndroid Build Coastguard Worker 
insert_register(struct declared_register * reg)151*d83cc019SAndroid Build Coastguard Worker void insert_register(struct declared_register *reg)
152*d83cc019SAndroid Build Coastguard Worker {
153*d83cc019SAndroid Build Coastguard Worker     insert_hash_item(declared_register_table, reg->name, reg);
154*d83cc019SAndroid Build Coastguard Worker }
155*d83cc019SAndroid Build Coastguard Worker 
add_label(struct brw_program_instruction * i)156*d83cc019SAndroid Build Coastguard Worker static void add_label(struct brw_program_instruction *i)
157*d83cc019SAndroid Build Coastguard Worker {
158*d83cc019SAndroid Build Coastguard Worker     struct label_item **p = &label_table;
159*d83cc019SAndroid Build Coastguard Worker 
160*d83cc019SAndroid Build Coastguard Worker     assert(is_label(i));
161*d83cc019SAndroid Build Coastguard Worker 
162*d83cc019SAndroid Build Coastguard Worker     while(*p)
163*d83cc019SAndroid Build Coastguard Worker         p = &((*p)->next);
164*d83cc019SAndroid Build Coastguard Worker     *p = calloc(1, sizeof(**p));
165*d83cc019SAndroid Build Coastguard Worker     (*p)->name = label_name(i);
166*d83cc019SAndroid Build Coastguard Worker     (*p)->addr = i->inst_offset;
167*d83cc019SAndroid Build Coastguard Worker }
168*d83cc019SAndroid Build Coastguard Worker 
169*d83cc019SAndroid Build Coastguard Worker /* Some assembly code have duplicated labels.
170*d83cc019SAndroid Build Coastguard Worker    Start from start_addr. Search as a loop. Return the first label found. */
label_to_addr(char * name,int start_addr)171*d83cc019SAndroid Build Coastguard Worker static int label_to_addr(char *name, int start_addr)
172*d83cc019SAndroid Build Coastguard Worker {
173*d83cc019SAndroid Build Coastguard Worker     /* return the first label just after start_addr, or the first label from the head */
174*d83cc019SAndroid Build Coastguard Worker     struct label_item *p;
175*d83cc019SAndroid Build Coastguard Worker     int r = -1;
176*d83cc019SAndroid Build Coastguard Worker     for(p = label_table; p; p = p->next) {
177*d83cc019SAndroid Build Coastguard Worker         if(strcmp(p->name, name) == 0) {
178*d83cc019SAndroid Build Coastguard Worker             if(p->addr >= start_addr) // the first label just after start_addr
179*d83cc019SAndroid Build Coastguard Worker                 return p->addr;
180*d83cc019SAndroid Build Coastguard Worker             else if(r == -1) // the first label from the head
181*d83cc019SAndroid Build Coastguard Worker                 r = p->addr;
182*d83cc019SAndroid Build Coastguard Worker         }
183*d83cc019SAndroid Build Coastguard Worker     }
184*d83cc019SAndroid Build Coastguard Worker     if(r == -1) {
185*d83cc019SAndroid Build Coastguard Worker         fprintf(stderr, "Can't find label %s\n", name);
186*d83cc019SAndroid Build Coastguard Worker         exit(1);
187*d83cc019SAndroid Build Coastguard Worker     }
188*d83cc019SAndroid Build Coastguard Worker     return r;
189*d83cc019SAndroid Build Coastguard Worker }
190*d83cc019SAndroid Build Coastguard Worker 
free_label_table(struct label_item * p)191*d83cc019SAndroid Build Coastguard Worker static void free_label_table(struct label_item *p)
192*d83cc019SAndroid Build Coastguard Worker {
193*d83cc019SAndroid Build Coastguard Worker     if(p) {
194*d83cc019SAndroid Build Coastguard Worker         free_label_table(p->next);
195*d83cc019SAndroid Build Coastguard Worker         free(p);
196*d83cc019SAndroid Build Coastguard Worker     }
197*d83cc019SAndroid Build Coastguard Worker }
198*d83cc019SAndroid Build Coastguard Worker 
199*d83cc019SAndroid Build Coastguard Worker struct entry_point_item {
200*d83cc019SAndroid Build Coastguard Worker 	char *str;
201*d83cc019SAndroid Build Coastguard Worker 	struct entry_point_item *next;
202*d83cc019SAndroid Build Coastguard Worker } *entry_point_table;
203*d83cc019SAndroid Build Coastguard Worker 
read_entry_file(char * fn)204*d83cc019SAndroid Build Coastguard Worker static int read_entry_file(char *fn)
205*d83cc019SAndroid Build Coastguard Worker {
206*d83cc019SAndroid Build Coastguard Worker 	FILE *entry_table_file;
207*d83cc019SAndroid Build Coastguard Worker 	char buf[2048];
208*d83cc019SAndroid Build Coastguard Worker 	struct entry_point_item **p = &entry_point_table;
209*d83cc019SAndroid Build Coastguard Worker 	if (!fn)
210*d83cc019SAndroid Build Coastguard Worker 		return 0;
211*d83cc019SAndroid Build Coastguard Worker 	if ((entry_table_file = fopen(fn, "r")) == NULL)
212*d83cc019SAndroid Build Coastguard Worker 		return -1;
213*d83cc019SAndroid Build Coastguard Worker 	while (fgets(buf, sizeof(buf)-1, entry_table_file) != NULL) {
214*d83cc019SAndroid Build Coastguard Worker 		// drop the final char '\n'
215*d83cc019SAndroid Build Coastguard Worker 		if(buf[strlen(buf)-1] == '\n')
216*d83cc019SAndroid Build Coastguard Worker 			buf[strlen(buf)-1] = 0;
217*d83cc019SAndroid Build Coastguard Worker 		*p = calloc(1, sizeof(struct entry_point_item));
218*d83cc019SAndroid Build Coastguard Worker 		(*p)->str = strdup(buf);
219*d83cc019SAndroid Build Coastguard Worker 		p = &((*p)->next);
220*d83cc019SAndroid Build Coastguard Worker 	}
221*d83cc019SAndroid Build Coastguard Worker 	fclose(entry_table_file);
222*d83cc019SAndroid Build Coastguard Worker 	return 0;
223*d83cc019SAndroid Build Coastguard Worker }
224*d83cc019SAndroid Build Coastguard Worker 
is_entry_point(struct brw_program_instruction * i)225*d83cc019SAndroid Build Coastguard Worker static int is_entry_point(struct brw_program_instruction *i)
226*d83cc019SAndroid Build Coastguard Worker {
227*d83cc019SAndroid Build Coastguard Worker 	struct entry_point_item *p;
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 	assert(i->type == GEN4ASM_INSTRUCTION_LABEL);
230*d83cc019SAndroid Build Coastguard Worker 
231*d83cc019SAndroid Build Coastguard Worker 	for (p = entry_point_table; p; p = p->next) {
232*d83cc019SAndroid Build Coastguard Worker 	    if (strcmp(p->str, i->insn.label.name) == 0)
233*d83cc019SAndroid Build Coastguard Worker 		return 1;
234*d83cc019SAndroid Build Coastguard Worker 	}
235*d83cc019SAndroid Build Coastguard Worker 	return 0;
236*d83cc019SAndroid Build Coastguard Worker }
237*d83cc019SAndroid Build Coastguard Worker 
free_entry_point_table(struct entry_point_item * p)238*d83cc019SAndroid Build Coastguard Worker static void free_entry_point_table(struct entry_point_item *p) {
239*d83cc019SAndroid Build Coastguard Worker 	if (p) {
240*d83cc019SAndroid Build Coastguard Worker 		free_entry_point_table(p->next);
241*d83cc019SAndroid Build Coastguard Worker 		free(p->str);
242*d83cc019SAndroid Build Coastguard Worker 		free(p);
243*d83cc019SAndroid Build Coastguard Worker 	}
244*d83cc019SAndroid Build Coastguard Worker }
245*d83cc019SAndroid Build Coastguard Worker 
246*d83cc019SAndroid Build Coastguard Worker static void
print_instruction(FILE * output,struct brw_instruction * instruction)247*d83cc019SAndroid Build Coastguard Worker print_instruction(FILE *output, struct brw_instruction *instruction)
248*d83cc019SAndroid Build Coastguard Worker {
249*d83cc019SAndroid Build Coastguard Worker 	if (binary_like_output) {
250*d83cc019SAndroid Build Coastguard Worker 		fprintf(output, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x, "
251*d83cc019SAndroid Build Coastguard Worker 				"0x%02x, 0x%02x, 0x%02x, 0x%02x,\n"
252*d83cc019SAndroid Build Coastguard Worker 				"\t0x%02x, 0x%02x, 0x%02x, 0x%02x, "
253*d83cc019SAndroid Build Coastguard Worker 				"0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
254*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[0],
255*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[1],
256*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[2],
257*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[3],
258*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[4],
259*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[5],
260*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[6],
261*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[7],
262*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[8],
263*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[9],
264*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[10],
265*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[11],
266*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[12],
267*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[13],
268*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[14],
269*d83cc019SAndroid Build Coastguard Worker 			((unsigned char *)instruction)[15]);
270*d83cc019SAndroid Build Coastguard Worker 	} else {
271*d83cc019SAndroid Build Coastguard Worker 		fprintf(output, "   { 0x%08x, 0x%08x, 0x%08x, 0x%08x },\n",
272*d83cc019SAndroid Build Coastguard Worker 			((int *)instruction)[0],
273*d83cc019SAndroid Build Coastguard Worker 			((int *)instruction)[1],
274*d83cc019SAndroid Build Coastguard Worker 			((int *)instruction)[2],
275*d83cc019SAndroid Build Coastguard Worker 			((int *)instruction)[3]);
276*d83cc019SAndroid Build Coastguard Worker 	}
277*d83cc019SAndroid Build Coastguard Worker }
main(int argc,char ** argv)278*d83cc019SAndroid Build Coastguard Worker int main(int argc, char **argv)
279*d83cc019SAndroid Build Coastguard Worker {
280*d83cc019SAndroid Build Coastguard Worker 	char *output_file = NULL;
281*d83cc019SAndroid Build Coastguard Worker 	char *entry_table_file = NULL;
282*d83cc019SAndroid Build Coastguard Worker 	FILE *output = stdout;
283*d83cc019SAndroid Build Coastguard Worker 	FILE *export_file;
284*d83cc019SAndroid Build Coastguard Worker 	struct brw_program_instruction *entry, *entry1, *tmp_entry;
285*d83cc019SAndroid Build Coastguard Worker 	int err, inst_offset;
286*d83cc019SAndroid Build Coastguard Worker 	char o;
287*d83cc019SAndroid Build Coastguard Worker 	void *mem_ctx;
288*d83cc019SAndroid Build Coastguard Worker 
289*d83cc019SAndroid Build Coastguard Worker 	while ((o = getopt_long(argc, argv, "e:l:o:g:abW", longopts, NULL)) != -1) {
290*d83cc019SAndroid Build Coastguard Worker 		switch (o) {
291*d83cc019SAndroid Build Coastguard Worker 		case 'o':
292*d83cc019SAndroid Build Coastguard Worker 			if (strcmp(optarg, "-") != 0)
293*d83cc019SAndroid Build Coastguard Worker 				output_file = optarg;
294*d83cc019SAndroid Build Coastguard Worker 
295*d83cc019SAndroid Build Coastguard Worker 			break;
296*d83cc019SAndroid Build Coastguard Worker 
297*d83cc019SAndroid Build Coastguard Worker 		case 'g': {
298*d83cc019SAndroid Build Coastguard Worker 			char *dec_ptr, *end_ptr;
299*d83cc019SAndroid Build Coastguard Worker 			unsigned long decimal;
300*d83cc019SAndroid Build Coastguard Worker 
301*d83cc019SAndroid Build Coastguard Worker 			gen_level = strtol(optarg, &dec_ptr, 10) * 10;
302*d83cc019SAndroid Build Coastguard Worker 
303*d83cc019SAndroid Build Coastguard Worker 			if (*dec_ptr == '.') {
304*d83cc019SAndroid Build Coastguard Worker 				decimal = strtoul(++dec_ptr, &end_ptr, 10);
305*d83cc019SAndroid Build Coastguard Worker 				if (end_ptr != dec_ptr && *end_ptr == '\0') {
306*d83cc019SAndroid Build Coastguard Worker 					if (decimal > 10) {
307*d83cc019SAndroid Build Coastguard Worker 						fprintf(stderr, "Invalid Gen X decimal version\n");
308*d83cc019SAndroid Build Coastguard Worker 						exit(1);
309*d83cc019SAndroid Build Coastguard Worker 					}
310*d83cc019SAndroid Build Coastguard Worker 					gen_level += decimal;
311*d83cc019SAndroid Build Coastguard Worker 				}
312*d83cc019SAndroid Build Coastguard Worker 			}
313*d83cc019SAndroid Build Coastguard Worker 
314*d83cc019SAndroid Build Coastguard Worker 			if (gen_level < 40 || gen_level > 90) {
315*d83cc019SAndroid Build Coastguard Worker 				usage();
316*d83cc019SAndroid Build Coastguard Worker 				exit(1);
317*d83cc019SAndroid Build Coastguard Worker 			}
318*d83cc019SAndroid Build Coastguard Worker 
319*d83cc019SAndroid Build Coastguard Worker 			break;
320*d83cc019SAndroid Build Coastguard Worker 		}
321*d83cc019SAndroid Build Coastguard Worker 
322*d83cc019SAndroid Build Coastguard Worker 		case 'a':
323*d83cc019SAndroid Build Coastguard Worker 			advanced_flag = 1;
324*d83cc019SAndroid Build Coastguard Worker 			break;
325*d83cc019SAndroid Build Coastguard Worker 		case 'b':
326*d83cc019SAndroid Build Coastguard Worker 			binary_like_output = 1;
327*d83cc019SAndroid Build Coastguard Worker 			break;
328*d83cc019SAndroid Build Coastguard Worker 
329*d83cc019SAndroid Build Coastguard Worker 		case 'e':
330*d83cc019SAndroid Build Coastguard Worker 			need_export = 1;
331*d83cc019SAndroid Build Coastguard Worker 			if (strcmp(optarg, "-") != 0)
332*d83cc019SAndroid Build Coastguard Worker 				export_filename = optarg;
333*d83cc019SAndroid Build Coastguard Worker 			break;
334*d83cc019SAndroid Build Coastguard Worker 
335*d83cc019SAndroid Build Coastguard Worker 		case 'l':
336*d83cc019SAndroid Build Coastguard Worker 			if (strcmp(optarg, "-") != 0)
337*d83cc019SAndroid Build Coastguard Worker 				entry_table_file = optarg;
338*d83cc019SAndroid Build Coastguard Worker 			break;
339*d83cc019SAndroid Build Coastguard Worker 
340*d83cc019SAndroid Build Coastguard Worker 		case 'W':
341*d83cc019SAndroid Build Coastguard Worker 			warning_flags |= WARN_ALL;
342*d83cc019SAndroid Build Coastguard Worker 			break;
343*d83cc019SAndroid Build Coastguard Worker 
344*d83cc019SAndroid Build Coastguard Worker 		default:
345*d83cc019SAndroid Build Coastguard Worker 			usage();
346*d83cc019SAndroid Build Coastguard Worker 			exit(1);
347*d83cc019SAndroid Build Coastguard Worker 		}
348*d83cc019SAndroid Build Coastguard Worker 	}
349*d83cc019SAndroid Build Coastguard Worker 	argc -= optind;
350*d83cc019SAndroid Build Coastguard Worker 	argv += optind;
351*d83cc019SAndroid Build Coastguard Worker 	if (argc != 1) {
352*d83cc019SAndroid Build Coastguard Worker 		usage();
353*d83cc019SAndroid Build Coastguard Worker 		exit(1);
354*d83cc019SAndroid Build Coastguard Worker 	}
355*d83cc019SAndroid Build Coastguard Worker 
356*d83cc019SAndroid Build Coastguard Worker 	if (strcmp(argv[0], "-") != 0) {
357*d83cc019SAndroid Build Coastguard Worker 		input_filename = argv[0];
358*d83cc019SAndroid Build Coastguard Worker 		yyin = fopen(input_filename, "r");
359*d83cc019SAndroid Build Coastguard Worker 		if (yyin == NULL) {
360*d83cc019SAndroid Build Coastguard Worker 			perror("Couldn't open input file");
361*d83cc019SAndroid Build Coastguard Worker 			exit(1);
362*d83cc019SAndroid Build Coastguard Worker 		}
363*d83cc019SAndroid Build Coastguard Worker 	}
364*d83cc019SAndroid Build Coastguard Worker 
365*d83cc019SAndroid Build Coastguard Worker 	brw_init_context(&genasm_brw_context, gen_level);
366*d83cc019SAndroid Build Coastguard Worker 	mem_ctx = ralloc_context(NULL);
367*d83cc019SAndroid Build Coastguard Worker 	brw_init_compile(&genasm_brw_context, &genasm_compile, mem_ctx);
368*d83cc019SAndroid Build Coastguard Worker 
369*d83cc019SAndroid Build Coastguard Worker 	err = yyparse();
370*d83cc019SAndroid Build Coastguard Worker 
371*d83cc019SAndroid Build Coastguard Worker 	if (strcmp(argv[0], "-"))
372*d83cc019SAndroid Build Coastguard Worker 		fclose(yyin);
373*d83cc019SAndroid Build Coastguard Worker 
374*d83cc019SAndroid Build Coastguard Worker 	yylex_destroy();
375*d83cc019SAndroid Build Coastguard Worker 
376*d83cc019SAndroid Build Coastguard Worker 	if (err || errors)
377*d83cc019SAndroid Build Coastguard Worker 		exit (1);
378*d83cc019SAndroid Build Coastguard Worker 
379*d83cc019SAndroid Build Coastguard Worker 	if (output_file) {
380*d83cc019SAndroid Build Coastguard Worker 		output = fopen(output_file, "w");
381*d83cc019SAndroid Build Coastguard Worker 		if (output == NULL) {
382*d83cc019SAndroid Build Coastguard Worker 			perror("Couldn't open output file");
383*d83cc019SAndroid Build Coastguard Worker 			exit(1);
384*d83cc019SAndroid Build Coastguard Worker 		}
385*d83cc019SAndroid Build Coastguard Worker 
386*d83cc019SAndroid Build Coastguard Worker 	}
387*d83cc019SAndroid Build Coastguard Worker 
388*d83cc019SAndroid Build Coastguard Worker 	if (read_entry_file(entry_table_file)) {
389*d83cc019SAndroid Build Coastguard Worker 		fprintf(stderr, "Read entry file error\n");
390*d83cc019SAndroid Build Coastguard Worker 		exit(1);
391*d83cc019SAndroid Build Coastguard Worker 	}
392*d83cc019SAndroid Build Coastguard Worker 	inst_offset = 0 ;
393*d83cc019SAndroid Build Coastguard Worker 	for (entry = compiled_program.first;
394*d83cc019SAndroid Build Coastguard Worker 		entry != NULL; entry = entry->next) {
395*d83cc019SAndroid Build Coastguard Worker 	    entry->inst_offset = inst_offset;
396*d83cc019SAndroid Build Coastguard Worker 	    entry1 = entry->next;
397*d83cc019SAndroid Build Coastguard Worker 	    if (entry1 && is_label(entry1) && is_entry_point(entry1)) {
398*d83cc019SAndroid Build Coastguard Worker 		// insert NOP instructions until (inst_offset+1) % 4 == 0
399*d83cc019SAndroid Build Coastguard Worker 		while (((inst_offset+1) % 4) != 0) {
400*d83cc019SAndroid Build Coastguard Worker 		    tmp_entry = calloc(sizeof(*tmp_entry), 1);
401*d83cc019SAndroid Build Coastguard Worker 		    tmp_entry->insn.gen.header.opcode = BRW_OPCODE_NOP;
402*d83cc019SAndroid Build Coastguard Worker 		    entry->next = tmp_entry;
403*d83cc019SAndroid Build Coastguard Worker 		    tmp_entry->next = entry1;
404*d83cc019SAndroid Build Coastguard Worker 		    entry = tmp_entry;
405*d83cc019SAndroid Build Coastguard Worker 		    tmp_entry->inst_offset = ++inst_offset;
406*d83cc019SAndroid Build Coastguard Worker 		}
407*d83cc019SAndroid Build Coastguard Worker 	    }
408*d83cc019SAndroid Build Coastguard Worker 	    if (!is_label(entry))
409*d83cc019SAndroid Build Coastguard Worker               inst_offset++;
410*d83cc019SAndroid Build Coastguard Worker 	}
411*d83cc019SAndroid Build Coastguard Worker 
412*d83cc019SAndroid Build Coastguard Worker 	for (entry = compiled_program.first; entry; entry = entry->next)
413*d83cc019SAndroid Build Coastguard Worker 	    if (is_label(entry))
414*d83cc019SAndroid Build Coastguard Worker 		add_label(entry);
415*d83cc019SAndroid Build Coastguard Worker 
416*d83cc019SAndroid Build Coastguard Worker 	if (need_export) {
417*d83cc019SAndroid Build Coastguard Worker 		if (export_filename) {
418*d83cc019SAndroid Build Coastguard Worker 			export_file = fopen(export_filename, "w");
419*d83cc019SAndroid Build Coastguard Worker 		} else {
420*d83cc019SAndroid Build Coastguard Worker 			export_file = fopen("export.inc", "w");
421*d83cc019SAndroid Build Coastguard Worker 		}
422*d83cc019SAndroid Build Coastguard Worker 		for (entry = compiled_program.first;
423*d83cc019SAndroid Build Coastguard Worker 			entry != NULL; entry = entry->next) {
424*d83cc019SAndroid Build Coastguard Worker 		    if (is_label(entry))
425*d83cc019SAndroid Build Coastguard Worker 			fprintf(export_file, "#define %s_IP %d\n",
426*d83cc019SAndroid Build Coastguard Worker 				label_name(entry), (IS_GENx(5) ? 2 : 1)*(entry->inst_offset));
427*d83cc019SAndroid Build Coastguard Worker 		}
428*d83cc019SAndroid Build Coastguard Worker 		fclose(export_file);
429*d83cc019SAndroid Build Coastguard Worker 	}
430*d83cc019SAndroid Build Coastguard Worker 
431*d83cc019SAndroid Build Coastguard Worker 	for (entry = compiled_program.first; entry; entry = entry->next) {
432*d83cc019SAndroid Build Coastguard Worker 	    struct relocation *reloc = &entry->reloc;
433*d83cc019SAndroid Build Coastguard Worker 
434*d83cc019SAndroid Build Coastguard Worker 	    if (!is_relocatable(entry))
435*d83cc019SAndroid Build Coastguard Worker 		continue;
436*d83cc019SAndroid Build Coastguard Worker 
437*d83cc019SAndroid Build Coastguard Worker 	    if (reloc->first_reloc_target)
438*d83cc019SAndroid Build Coastguard Worker 		reloc->first_reloc_offset = label_to_addr(reloc->first_reloc_target, entry->inst_offset) - entry->inst_offset;
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 	    if (reloc->second_reloc_target)
441*d83cc019SAndroid Build Coastguard Worker 		reloc->second_reloc_offset = label_to_addr(reloc->second_reloc_target, entry->inst_offset) - entry->inst_offset;
442*d83cc019SAndroid Build Coastguard Worker 
443*d83cc019SAndroid Build Coastguard Worker 	    if (reloc->second_reloc_offset) { // this is a branch instruction with two offset arguments
444*d83cc019SAndroid Build Coastguard Worker                 set_branch_two_offsets(entry, reloc->first_reloc_offset, reloc->second_reloc_offset);
445*d83cc019SAndroid Build Coastguard Worker 	    } else if (reloc->first_reloc_offset) {
446*d83cc019SAndroid Build Coastguard Worker                 set_branch_one_offset(entry, reloc->first_reloc_offset);
447*d83cc019SAndroid Build Coastguard Worker 	    }
448*d83cc019SAndroid Build Coastguard Worker 	}
449*d83cc019SAndroid Build Coastguard Worker 
450*d83cc019SAndroid Build Coastguard Worker 	if (binary_like_output)
451*d83cc019SAndroid Build Coastguard Worker 		fprintf(output, "%s", binary_prepend);
452*d83cc019SAndroid Build Coastguard Worker 
453*d83cc019SAndroid Build Coastguard Worker 	for (entry = compiled_program.first;
454*d83cc019SAndroid Build Coastguard Worker 		entry != NULL;
455*d83cc019SAndroid Build Coastguard Worker 		entry = entry1) {
456*d83cc019SAndroid Build Coastguard Worker 	    entry1 = entry->next;
457*d83cc019SAndroid Build Coastguard Worker 	    if (!is_label(entry))
458*d83cc019SAndroid Build Coastguard Worker 		print_instruction(output, &entry->insn.gen);
459*d83cc019SAndroid Build Coastguard Worker 	    else
460*d83cc019SAndroid Build Coastguard Worker 		free(entry->insn.label.name);
461*d83cc019SAndroid Build Coastguard Worker 	    free(entry);
462*d83cc019SAndroid Build Coastguard Worker 	}
463*d83cc019SAndroid Build Coastguard Worker 	if (binary_like_output)
464*d83cc019SAndroid Build Coastguard Worker 		fprintf(output, "};");
465*d83cc019SAndroid Build Coastguard Worker 
466*d83cc019SAndroid Build Coastguard Worker 	free_entry_point_table(entry_point_table);
467*d83cc019SAndroid Build Coastguard Worker 	free_hash_table(declared_register_table);
468*d83cc019SAndroid Build Coastguard Worker 	free_label_table(label_table);
469*d83cc019SAndroid Build Coastguard Worker 
470*d83cc019SAndroid Build Coastguard Worker 	fflush (output);
471*d83cc019SAndroid Build Coastguard Worker 	if (ferror (output)) {
472*d83cc019SAndroid Build Coastguard Worker 	    perror ("Could not flush output file");
473*d83cc019SAndroid Build Coastguard Worker 	    if (output_file)
474*d83cc019SAndroid Build Coastguard Worker 		unlink (output_file);
475*d83cc019SAndroid Build Coastguard Worker 	    err = 1;
476*d83cc019SAndroid Build Coastguard Worker 	}
477*d83cc019SAndroid Build Coastguard Worker 	return err;
478*d83cc019SAndroid Build Coastguard Worker }
479