blob: a1eca52513946bd8971b13bf41546041a3e7d5d3 [file] [log] [blame]
Eric Anholt22a10632006-08-22 10:15:33 -07001/* -*- c-basic-offset: 8 -*- */
2/*
3 * Copyright © 2006 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 * Eric Anholt <eric@anholt.net>
26 *
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
Eric Anholt5fbc3992006-08-30 10:22:56 -070031#include <string.h>
32#include <getopt.h>
Keith Packardb81aca42008-03-30 00:58:40 -070033#include <unistd.h>
Damien Lespiaua45a4712013-01-21 19:28:41 +000034#include <assert.h>
Eric Anholt22a10632006-08-22 10:15:33 -070035
Damien Lespiau9fcc1bd2013-01-24 16:16:35 +000036#include "ralloc.h"
Eric Anholt22a10632006-08-22 10:15:33 -070037#include "gen4asm.h"
Damien Lespiau9fcc1bd2013-01-24 16:16:35 +000038#include "brw_eu.h"
Eric Anholt22a10632006-08-22 10:15:33 -070039
40extern FILE *yyin;
Xiang, Haihao216163b2013-02-22 11:14:06 +080041extern void set_branch_two_offsets(struct brw_program_instruction *insn, int jip_offset, int uip_offset);
42extern void set_branch_one_offset(struct brw_program_instruction *insn, int jip_offset);
Eric Anholt22a10632006-08-22 10:15:33 -070043
Gwenole Beauchesnea5e5d942012-10-22 16:13:51 -040044long int gen_level = 40;
Homer Hsing73ab2f62012-09-14 10:50:09 +080045int advanced_flag = 0; /* 0: in unit of byte, 1: in unit of data element size */
Damien Lespiaud70e9f82013-01-26 23:09:42 +000046unsigned int warning_flags = WARN_ALWAYS;
Xiang, Haihao27b43032010-12-13 16:07:16 +080047int need_export = 0;
Keith Packardb81aca42008-03-30 00:58:40 -070048char *input_filename = "<stdin>";
Damien Lespiau1d53e182013-01-27 11:05:50 +000049int errors;
Ben Widawskycbfab5f2011-03-17 18:57:59 -070050
Damien Lespiau9fcc1bd2013-01-24 16:16:35 +000051struct brw_context genasm_brw_context;
52struct brw_compile genasm_compile;
53
Eric Anholt22a10632006-08-22 10:15:33 -070054struct brw_program compiled_program;
Homer Hsing94052252012-09-14 10:02:53 +080055struct program_defaults program_defaults = {.register_type = BRW_REGISTER_TYPE_F};
Xiang, Haihao27b43032010-12-13 16:07:16 +080056
Damien Lespiau1d53e182013-01-27 11:05:50 +000057/* 0: default output style, 1: nice C-style output */
58static int binary_like_output = 0;
59static char *export_filename = NULL;
60static const char binary_prepend[] = "static const char gen_eu_bytes[] = {\n";
61
Homer Hsing868cbf72012-09-18 16:32:39 +080062#define HASH_SIZE 37
Xiang, Haihao27b43032010-12-13 16:07:16 +080063
Homer Hsing868cbf72012-09-18 16:32:39 +080064struct hash_item {
65 char *key;
66 void *value;
67 struct hash_item *next;
68};
69
70typedef struct hash_item *hash_table[HASH_SIZE];
71
72static hash_table declared_register_table;
Eric Anholt22a10632006-08-22 10:15:33 -070073
Homer Hsingccd17212012-09-21 09:37:06 +080074struct label_item {
75 char *name;
76 int addr;
77 struct label_item *next;
78};
79static struct label_item *label_table;
80
Eric Anholt5fbc3992006-08-30 10:22:56 -070081static const struct option longopts[] = {
Xiang, Haihao27b43032010-12-13 16:07:16 +080082 {"advanced", no_argument, 0, 'a'},
Ben Widawskycbfab5f2011-03-17 18:57:59 -070083 {"binary", no_argument, 0, 'b'},
Xiang, Haihao27b43032010-12-13 16:07:16 +080084 {"export", required_argument, 0, 'e'},
85 {"input_list", required_argument, 0, 'l'},
86 {"output", required_argument, 0, 'o'},
87 {"gen", required_argument, 0, 'g'},
Eric Anholt5fbc3992006-08-30 10:22:56 -070088 { NULL, 0, NULL, 0 }
89};
90
Keith Packardb81aca42008-03-30 00:58:40 -070091static void usage(void)
Eric Anholt5fbc3992006-08-30 10:22:56 -070092{
Xiang, Haihao27b43032010-12-13 16:07:16 +080093 fprintf(stderr, "usage: intel-gen4asm [options] inputfile\n");
94 fprintf(stderr, "OPTIONS:\n");
95 fprintf(stderr, "\t-a, --advanced Set advanced flag\n");
Ben Widawskycbfab5f2011-03-17 18:57:59 -070096 fprintf(stderr, "\t-b, --binary C style binary output\n");
Xiang, Haihao27b43032010-12-13 16:07:16 +080097 fprintf(stderr, "\t-e, --export {exportfile} Export label file\n");
98 fprintf(stderr, "\t-l, --input_list {entrytablefile} Input entry_table_list file\n");
99 fprintf(stderr, "\t-o, --output {outputfile} Specify output file\n");
Damien Lespiau2149d6e2013-02-05 12:10:44 +0000100 fprintf(stderr, "\t-g, --gen <4|5|6|7|8|9> Specify GPU generation\n");
Xiang, Haihao27b43032010-12-13 16:07:16 +0800101}
102
Homer Hsing868cbf72012-09-18 16:32:39 +0800103static int hash(char *key)
Xiang, Haihao27b43032010-12-13 16:07:16 +0800104{
Homer Hsing71867232012-09-14 10:06:39 +0800105 unsigned ret = 0;
Homer Hsing868cbf72012-09-18 16:32:39 +0800106 while(*key)
107 ret = (ret << 1) + (*key++);
108 return ret % HASH_SIZE;
109}
110
111static void *find_hash_item(hash_table t, char *key)
112{
113 struct hash_item *p;
114 for(p = t[hash(key)]; p; p = p->next)
115 if(strcasecmp(p->key, key) == 0)
116 return p->value;
117 return NULL;
118}
119
120static void insert_hash_item(hash_table t, char *key, void *v)
121{
122 int index = hash(key);
123 struct hash_item *p = malloc(sizeof(*p));
124 p->key = key;
125 p->value = v;
126 p->next = t[index];
127 t[index] = p;
128}
129
130static void free_hash_table(hash_table t)
131{
132 struct hash_item *p, *next;
133 int i;
134 for (i = 0; i < HASH_SIZE; i++) {
135 p = t[i];
136 while(p) {
137 next = p->next;
138 free(p->key);
139 free(p->value);
140 free(p);
141 p = next;
142 }
143 }
Xiang, Haihao27b43032010-12-13 16:07:16 +0800144}
145
146struct declared_register *find_register(char *name)
147{
Homer Hsing868cbf72012-09-18 16:32:39 +0800148 return find_hash_item(declared_register_table, name);
Xiang, Haihao27b43032010-12-13 16:07:16 +0800149}
150
151void insert_register(struct declared_register *reg)
152{
Homer Hsing868cbf72012-09-18 16:32:39 +0800153 insert_hash_item(declared_register_table, reg->name, reg);
Xiang, Haihao27b43032010-12-13 16:07:16 +0800154}
155
Damien Lespiau6b568042013-01-21 22:17:54 +0000156static void add_label(struct brw_program_instruction *i)
Homer Hsingccd17212012-09-21 09:37:06 +0800157{
158 struct label_item **p = &label_table;
Damien Lespiaua45a4712013-01-21 19:28:41 +0000159
160 assert(is_label(i));
161
Homer Hsingccd17212012-09-21 09:37:06 +0800162 while(*p)
163 p = &((*p)->next);
164 *p = calloc(1, sizeof(**p));
Damien Lespiaua45a4712013-01-21 19:28:41 +0000165 (*p)->name = label_name(i);
166 (*p)->addr = i->inst_offset;
Homer Hsingccd17212012-09-21 09:37:06 +0800167}
168
169/* Some assembly code have duplicated labels.
170 Start from start_addr. Search as a loop. Return the first label found. */
Damien Lespiau6b568042013-01-21 22:17:54 +0000171static int label_to_addr(char *name, int start_addr)
Homer Hsingccd17212012-09-21 09:37:06 +0800172{
173 /* return the first label just after start_addr, or the first label from the head */
174 struct label_item *p;
175 int r = -1;
176 for(p = label_table; p; p = p->next) {
177 if(strcmp(p->name, name) == 0) {
178 if(p->addr >= start_addr) // the first label just after start_addr
179 return p->addr;
180 else if(r == -1) // the first label from the head
181 r = p->addr;
182 }
183 }
Homer Hsing88dfdf32012-09-24 10:06:35 +0800184 if(r == -1) {
185 fprintf(stderr, "Can't find label %s\n", name);
186 exit(1);
187 }
Homer Hsingccd17212012-09-21 09:37:06 +0800188 return r;
189}
190
191static void free_label_table(struct label_item *p)
192{
193 if(p) {
194 free_label_table(p->next);
195 free(p);
196 }
197}
198
Homer Hsingc19f8332012-09-14 15:27:19 +0800199struct entry_point_item {
200 char *str;
201 struct entry_point_item *next;
202} *entry_point_table;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800203
Xiang, Haihao27b43032010-12-13 16:07:16 +0800204static int read_entry_file(char *fn)
205{
206 FILE *entry_table_file;
Homer Hsingc19f8332012-09-14 15:27:19 +0800207 char buf[2048];
208 struct entry_point_item **p = &entry_point_table;
209 if (!fn)
Xiang, Haihao27b43032010-12-13 16:07:16 +0800210 return 0;
Homer Hsingc19f8332012-09-14 15:27:19 +0800211 if ((entry_table_file = fopen(fn, "r")) == NULL)
212 return -1;
213 while (fgets(buf, sizeof(buf)-1, entry_table_file) != NULL) {
214 // drop the final char '\n'
215 if(buf[strlen(buf)-1] == '\n')
216 buf[strlen(buf)-1] = 0;
217 *p = calloc(1, sizeof(struct entry_point_item));
218 (*p)->str = strdup(buf);
219 p = &((*p)->next);
Xiang, Haihao27b43032010-12-13 16:07:16 +0800220 }
221 fclose(entry_table_file);
222 return 0;
223}
224
Damien Lespiaua45a4712013-01-21 19:28:41 +0000225static int is_entry_point(struct brw_program_instruction *i)
Xiang, Haihao27b43032010-12-13 16:07:16 +0800226{
Homer Hsingc19f8332012-09-14 15:27:19 +0800227 struct entry_point_item *p;
Damien Lespiaua45a4712013-01-21 19:28:41 +0000228
229 assert(i->type == GEN4ASM_INSTRUCTION_LABEL);
230
Homer Hsingc19f8332012-09-14 15:27:19 +0800231 for (p = entry_point_table; p; p = p->next) {
Damien Lespiaud0080642013-01-30 12:31:45 +0000232 if (strcmp(p->str, i->insn.label.name) == 0)
Xiang, Haihao27b43032010-12-13 16:07:16 +0800233 return 1;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800234 }
235 return 0;
Eric Anholt5fbc3992006-08-30 10:22:56 -0700236}
237
Homer Hsingc19f8332012-09-14 15:27:19 +0800238static void free_entry_point_table(struct entry_point_item *p) {
239 if (p) {
240 free_entry_point_table(p->next);
241 free(p->str);
242 free(p);
243 }
244}
245
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700246static void
Damien Lespiau5e586112013-01-21 15:10:01 +0000247print_instruction(FILE *output, struct brw_instruction *instruction)
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700248{
249 if (binary_like_output) {
250 fprintf(output, "\t0x%02x, 0x%02x, 0x%02x, 0x%02x, "
251 "0x%02x, 0x%02x, 0x%02x, 0x%02x,\n"
252 "\t0x%02x, 0x%02x, 0x%02x, 0x%02x, "
253 "0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
Damien Lespiau5e586112013-01-21 15:10:01 +0000254 ((unsigned char *)instruction)[0],
255 ((unsigned char *)instruction)[1],
256 ((unsigned char *)instruction)[2],
257 ((unsigned char *)instruction)[3],
258 ((unsigned char *)instruction)[4],
259 ((unsigned char *)instruction)[5],
260 ((unsigned char *)instruction)[6],
261 ((unsigned char *)instruction)[7],
262 ((unsigned char *)instruction)[8],
263 ((unsigned char *)instruction)[9],
264 ((unsigned char *)instruction)[10],
265 ((unsigned char *)instruction)[11],
266 ((unsigned char *)instruction)[12],
267 ((unsigned char *)instruction)[13],
268 ((unsigned char *)instruction)[14],
269 ((unsigned char *)instruction)[15]);
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700270 } else {
271 fprintf(output, " { 0x%08x, 0x%08x, 0x%08x, 0x%08x },\n",
Damien Lespiau5e586112013-01-21 15:10:01 +0000272 ((int *)instruction)[0],
273 ((int *)instruction)[1],
274 ((int *)instruction)[2],
275 ((int *)instruction)[3]);
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700276 }
277}
Eric Anholt22a10632006-08-22 10:15:33 -0700278int main(int argc, char **argv)
279{
Keith Packardb81aca42008-03-30 00:58:40 -0700280 char *output_file = NULL;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800281 char *entry_table_file = NULL;
Eric Anholt5fbc3992006-08-30 10:22:56 -0700282 FILE *output = stdout;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800283 FILE *export_file;
284 struct brw_program_instruction *entry, *entry1, *tmp_entry;
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800285 int err, inst_offset;
Eric Anholt5fbc3992006-08-30 10:22:56 -0700286 char o;
Damien Lespiau9fcc1bd2013-01-24 16:16:35 +0000287 void *mem_ctx;
288
Damien Lespiaud70e9f82013-01-26 23:09:42 +0000289 while ((o = getopt_long(argc, argv, "e:l:o:g:abW", longopts, NULL)) != -1) {
Eric Anholt5fbc3992006-08-30 10:22:56 -0700290 switch (o) {
291 case 'o':
Keith Packardb81aca42008-03-30 00:58:40 -0700292 if (strcmp(optarg, "-") != 0)
293 output_file = optarg;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800294
Eric Anholt5fbc3992006-08-30 10:22:56 -0700295 break;
Xiang Haihao549b7512009-06-30 10:02:33 +0800296
Gwenole Beauchesne0c32e252012-10-22 16:13:51 -0400297 case 'g': {
298 char *dec_ptr, *end_ptr;
299 unsigned long decimal;
300
301 gen_level = strtol(optarg, &dec_ptr, 10) * 10;
302
303 if (*dec_ptr == '.') {
304 decimal = strtoul(++dec_ptr, &end_ptr, 10);
305 if (end_ptr != dec_ptr && *end_ptr == '\0') {
306 if (decimal > 10) {
307 fprintf(stderr, "Invalid Gen X decimal version\n");
308 exit(1);
309 }
310 gen_level += decimal;
311 }
312 }
Xiang Haihao549b7512009-06-30 10:02:33 +0800313
Damien Lespiau2149d6e2013-02-05 12:10:44 +0000314 if (gen_level < 40 || gen_level > 90) {
Xiang Haihao549b7512009-06-30 10:02:33 +0800315 usage();
316 exit(1);
317 }
318
319 break;
Gwenole Beauchesne0c32e252012-10-22 16:13:51 -0400320 }
Xiang Haihao549b7512009-06-30 10:02:33 +0800321
Xiang, Haihao27b43032010-12-13 16:07:16 +0800322 case 'a':
323 advanced_flag = 1;
324 break;
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700325 case 'b':
326 binary_like_output = 1;
327 break;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800328
329 case 'e':
330 need_export = 1;
331 if (strcmp(optarg, "-") != 0)
332 export_filename = optarg;
333 break;
334
335 case 'l':
336 if (strcmp(optarg, "-") != 0)
337 entry_table_file = optarg;
338 break;
339
Damien Lespiaud70e9f82013-01-26 23:09:42 +0000340 case 'W':
341 warning_flags |= WARN_ALL;
342 break;
343
Eric Anholt5fbc3992006-08-30 10:22:56 -0700344 default:
345 usage();
346 exit(1);
347 }
348 }
349 argc -= optind;
350 argv += optind;
351 if (argc != 1) {
352 usage();
353 exit(1);
354 }
355
356 if (strcmp(argv[0], "-") != 0) {
Keith Packardb81aca42008-03-30 00:58:40 -0700357 input_filename = argv[0];
358 yyin = fopen(input_filename, "r");
Eric Anholt5fbc3992006-08-30 10:22:56 -0700359 if (yyin == NULL) {
360 perror("Couldn't open input file");
361 exit(1);
362 }
363 }
Eric Anholt22a10632006-08-22 10:15:33 -0700364
Damien Lespiau9fcc1bd2013-01-24 16:16:35 +0000365 brw_init_context(&genasm_brw_context, gen_level);
366 mem_ctx = ralloc_context(NULL);
367 brw_init_compile(&genasm_brw_context, &genasm_compile, mem_ctx);
368
Eric Anholt22a10632006-08-22 10:15:33 -0700369 err = yyparse();
370
Homer Hsingaab7cd52012-09-06 16:12:08 +0800371 if (strcmp(argv[0], "-"))
Homer Hsing302ca732012-09-06 15:33:41 +0800372 fclose(yyin);
373
Homer Hsingaab7cd52012-09-06 16:12:08 +0800374 yylex_destroy();
375
Keith Packardb81aca42008-03-30 00:58:40 -0700376 if (err || errors)
377 exit (1);
378
379 if (output_file) {
380 output = fopen(output_file, "w");
381 if (output == NULL) {
382 perror("Couldn't open output file");
383 exit(1);
384 }
Xiang, Haihao27b43032010-12-13 16:07:16 +0800385
386 }
387
388 if (read_entry_file(entry_table_file)) {
389 fprintf(stderr, "Read entry file error\n");
390 exit(1);
Keith Packardb81aca42008-03-30 00:58:40 -0700391 }
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800392 inst_offset = 0 ;
Eric Anholt22a10632006-08-22 10:15:33 -0700393 for (entry = compiled_program.first;
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800394 entry != NULL; entry = entry->next) {
395 entry->inst_offset = inst_offset;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800396 entry1 = entry->next;
Damien Lespiaua45a4712013-01-21 19:28:41 +0000397 if (entry1 && is_label(entry1) && is_entry_point(entry1)) {
Homer Hsing5defbd32012-09-17 16:01:16 +0800398 // insert NOP instructions until (inst_offset+1) % 4 == 0
Homer Hsingf02a1ed2012-09-14 13:40:08 +0800399 while (((inst_offset+1) % 4) != 0) {
Xiang, Haihao27b43032010-12-13 16:07:16 +0800400 tmp_entry = calloc(sizeof(*tmp_entry), 1);
Damien Lespiaud0080642013-01-30 12:31:45 +0000401 tmp_entry->insn.gen.header.opcode = BRW_OPCODE_NOP;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800402 entry->next = tmp_entry;
403 tmp_entry->next = entry1;
404 entry = tmp_entry;
405 tmp_entry->inst_offset = ++inst_offset;
406 }
407 }
Damien Lespiaua45a4712013-01-21 19:28:41 +0000408 if (!is_label(entry))
Xiang, Haihao27b43032010-12-13 16:07:16 +0800409 inst_offset++;
410 }
411
Homer Hsingccd17212012-09-21 09:37:06 +0800412 for (entry = compiled_program.first; entry; entry = entry->next)
Damien Lespiaua45a4712013-01-21 19:28:41 +0000413 if (is_label(entry))
414 add_label(entry);
Homer Hsingccd17212012-09-21 09:37:06 +0800415
Xiang, Haihao27b43032010-12-13 16:07:16 +0800416 if (need_export) {
417 if (export_filename) {
418 export_file = fopen(export_filename, "w");
419 } else {
420 export_file = fopen("export.inc", "w");
421 }
422 for (entry = compiled_program.first;
423 entry != NULL; entry = entry->next) {
Damien Lespiaua45a4712013-01-21 19:28:41 +0000424 if (is_label(entry))
Xiang, Haihao27b43032010-12-13 16:07:16 +0800425 fprintf(export_file, "#define %s_IP %d\n",
Damien Lespiaua45a4712013-01-21 19:28:41 +0000426 label_name(entry), (IS_GENx(5) ? 2 : 1)*(entry->inst_offset));
Xiang, Haihao27b43032010-12-13 16:07:16 +0800427 }
428 fclose(export_file);
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800429 }
430
Homer Hsingccd17212012-09-21 09:37:06 +0800431 for (entry = compiled_program.first; entry; entry = entry->next) {
Damien Lespiau9b78f742013-01-30 17:09:17 +0000432 struct relocation *reloc = &entry->reloc;
Damien Lespiaua45a4712013-01-21 19:28:41 +0000433
Damien Lespiau79c62f12013-01-21 21:41:36 +0000434 if (!is_relocatable(entry))
Damien Lespiaua45a4712013-01-21 19:28:41 +0000435 continue;
Homer Hsing88dfdf32012-09-24 10:06:35 +0800436
Damien Lespiau79c62f12013-01-21 21:41:36 +0000437 if (reloc->first_reloc_target)
438 reloc->first_reloc_offset = label_to_addr(reloc->first_reloc_target, entry->inst_offset) - entry->inst_offset;
Homer Hsing88dfdf32012-09-24 10:06:35 +0800439
Damien Lespiau79c62f12013-01-21 21:41:36 +0000440 if (reloc->second_reloc_target)
441 reloc->second_reloc_offset = label_to_addr(reloc->second_reloc_target, entry->inst_offset) - entry->inst_offset;
Homer Hsing88dfdf32012-09-24 10:06:35 +0800442
Xiang, Haihao216163b2013-02-22 11:14:06 +0800443 if (reloc->second_reloc_offset) { // this is a branch instruction with two offset arguments
444 set_branch_two_offsets(entry, reloc->first_reloc_offset, reloc->second_reloc_offset);
Damien Lespiau79c62f12013-01-21 21:41:36 +0000445 } else if (reloc->first_reloc_offset) {
Xiang, Haihao216163b2013-02-22 11:14:06 +0800446 set_branch_one_offset(entry, reloc->first_reloc_offset);
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800447 }
448 }
449
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700450 if (binary_like_output)
451 fprintf(output, "%s", binary_prepend);
452
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800453 for (entry = compiled_program.first;
454 entry != NULL;
Xiang, Haihao27b43032010-12-13 16:07:16 +0800455 entry = entry1) {
456 entry1 = entry->next;
Damien Lespiaua45a4712013-01-21 19:28:41 +0000457 if (!is_label(entry))
Damien Lespiaud0080642013-01-30 12:31:45 +0000458 print_instruction(output, &entry->insn.gen);
Xiang, Haihao27b43032010-12-13 16:07:16 +0800459 else
Damien Lespiaud0080642013-01-30 12:31:45 +0000460 free(entry->insn.label.name);
Xiang, Haihao27b43032010-12-13 16:07:16 +0800461 free(entry);
Eric Anholt22a10632006-08-22 10:15:33 -0700462 }
Ben Widawskycbfab5f2011-03-17 18:57:59 -0700463 if (binary_like_output)
464 fprintf(output, "};");
Eric Anholt22a10632006-08-22 10:15:33 -0700465
Homer Hsingc19f8332012-09-14 15:27:19 +0800466 free_entry_point_table(entry_point_table);
Homer Hsing868cbf72012-09-18 16:32:39 +0800467 free_hash_table(declared_register_table);
Homer Hsingccd17212012-09-21 09:37:06 +0800468 free_label_table(label_table);
469
Keith Packardb81aca42008-03-30 00:58:40 -0700470 fflush (output);
471 if (ferror (output)) {
Zou Nanhaibe9bcee2008-12-09 18:38:54 -0800472 perror ("Could not flush output file");
473 if (output_file)
474 unlink (output_file);
475 err = 1;
Keith Packardb81aca42008-03-30 00:58:40 -0700476 }
Eric Anholt22a10632006-08-22 10:15:33 -0700477 return err;
478}