anv: simplify push constant emissions
[mesa.git] / src / intel / tools / i965_asm.c
1 /*
2 * Copyright © 2018 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 */
24
25 #include <stdio.h>
26 #include <getopt.h>
27 #include "i965_asm.h"
28
29 enum opt_output_type {
30 OPT_OUTPUT_HEX,
31 OPT_OUTPUT_C_LITERAL,
32 OPT_OUTPUT_BIN,
33 };
34
35 extern FILE *yyin;
36 struct brw_codegen *p;
37 static enum opt_output_type output_type = OPT_OUTPUT_BIN;
38 char *input_filename = NULL;
39 int errors;
40
41 static void
42 print_help(const char *progname, FILE *file)
43 {
44 fprintf(file,
45 "Usage: %s [OPTION] inputfile\n"
46 "Assemble i965 instructions from input file.\n\n"
47 " -h, --help display this help and exit\n"
48 " -t, --type=OUTPUT_TYPE OUTPUT_TYPE can be 'bin' (default if omitted),\n"
49 " 'c_literal', or 'hex'\n"
50 " -o, --output specify output file\n"
51 " --compact print compacted instructions\n"
52 " -g, --gen=platform assemble instructions for given \n"
53 " platform (3 letter platform name)\n"
54 "Example:\n"
55 " i965_asm -g kbl input.asm -t hex -o output\n",
56 progname);
57 }
58
59 static uint32_t
60 get_dword(const brw_inst *inst, int idx)
61 {
62 uint32_t dword;
63 memcpy(&dword, (char *)inst + 4 * idx, sizeof(dword));
64 return dword;
65 }
66
67 static void
68 print_instruction(FILE *output, bool compact, const brw_inst *instruction)
69 {
70 int byte_limit;
71
72 byte_limit = (compact == true) ? 8 : 16;
73
74 switch (output_type) {
75 case OPT_OUTPUT_HEX: {
76 fprintf(output, "%02x", ((unsigned char *)instruction)[0]);
77
78 for (unsigned i = 1; i < byte_limit; i++) {
79 fprintf(output, " %02x", ((unsigned char *)instruction)[i]);
80 }
81 break;
82 }
83 case OPT_OUTPUT_C_LITERAL: {
84 fprintf(output, "\t0x%08x,", get_dword(instruction, 0));
85
86 for (unsigned i = 1; i < byte_limit / 4; i++)
87 fprintf(output, " 0x%08x,", get_dword(instruction, i));
88
89 break;
90 }
91 case OPT_OUTPUT_BIN:
92 fwrite(instruction, 1, byte_limit, output);
93 break;
94 }
95
96 if (output_type != OPT_OUTPUT_BIN) {
97 fprintf(output, "\n");
98 }
99 }
100
101 static struct gen_device_info *
102 i965_disasm_init(uint16_t pci_id)
103 {
104 struct gen_device_info *devinfo;
105
106 devinfo = malloc(sizeof *devinfo);
107 if (devinfo == NULL)
108 return NULL;
109
110 if (!gen_get_device_info_from_pci_id(pci_id, devinfo)) {
111 fprintf(stderr, "can't find device information: pci_id=0x%x\n",
112 pci_id);
113 free(devinfo);
114 return NULL;
115 }
116
117 brw_init_compaction_tables(devinfo);
118
119 return devinfo;
120 }
121
122 int main(int argc, char **argv)
123 {
124 char *output_file = NULL;
125 char c;
126 FILE *output = stdout;
127 bool help = false, compact = false;
128 void *store;
129 uint64_t pci_id = 0;
130 int offset = 0, err;
131 int start_offset = 0;
132 struct disasm_info *disasm_info;
133 struct gen_device_info *devinfo = NULL;
134 int result = EXIT_FAILURE;
135
136 const struct option i965_asm_opts[] = {
137 { "help", no_argument, (int *) &help, true },
138 { "type", required_argument, NULL, 't' },
139 { "gen", required_argument, NULL, 'g' },
140 { "output", required_argument, NULL, 'o' },
141 { "compact", no_argument, (int *) &compact, true },
142 { NULL, 0, NULL, 0 }
143 };
144
145 while ((c = getopt_long(argc, argv, ":t:g:o:h", i965_asm_opts, NULL)) != -1) {
146 switch (c) {
147 case 'g': {
148 const int id = gen_device_name_to_pci_device_id(optarg);
149 if (id < 0) {
150 fprintf(stderr, "can't parse gen: '%s', expected 3 letter "
151 "platform name\n", optarg);
152 goto end;
153 } else {
154 pci_id = id;
155 }
156 break;
157 }
158 case 'h':
159 help = true;
160 print_help(argv[0], stderr);
161 goto end;
162 case 't': {
163 if (strcmp(optarg, "hex") == 0) {
164 output_type = OPT_OUTPUT_HEX;
165 } else if (strcmp(optarg, "c_literal") == 0) {
166 output_type = OPT_OUTPUT_C_LITERAL;
167 } else if (strcmp(optarg, "bin") == 0) {
168 output_type = OPT_OUTPUT_BIN;
169 } else {
170 fprintf(stderr, "invalid value for --type: %s\n", optarg);
171 goto end;
172 }
173 break;
174 }
175 case 'o':
176 output_file = strdup(optarg);
177 break;
178 case 0:
179 break;
180 case ':':
181 fprintf(stderr, "%s: option `-%c' requires an argument\n",
182 argv[0], optopt);
183 goto end;
184 case '?':
185 default:
186 fprintf(stderr, "%s: option `-%c' is invalid: ignored\n",
187 argv[0], optopt);
188 goto end;
189 }
190 }
191
192 if (help || !pci_id) {
193 print_help(argv[0], stderr);
194 goto end;
195 }
196
197 if (!argv[optind]) {
198 fprintf(stderr, "Please specify input file\n");
199 goto end;
200 }
201
202 input_filename = strdup(argv[optind]);
203 yyin = fopen(input_filename, "r");
204 if (!yyin) {
205 fprintf(stderr, "Unable to read input file : %s\n",
206 input_filename);
207 goto end;
208 }
209
210 if (output_file) {
211 output = fopen(output_file, "w");
212 if (!output) {
213 fprintf(stderr, "Couldn't open output file\n");
214 goto end;
215 }
216 }
217
218 devinfo = i965_disasm_init(pci_id);
219 if (!devinfo) {
220 fprintf(stderr, "Unable to allocate memory for "
221 "gen_device_info struct instance.\n");
222 goto end;
223 }
224
225 p = rzalloc(NULL, struct brw_codegen);
226 brw_init_codegen(devinfo, p, p);
227 p->automatic_exec_sizes = false;
228
229 err = yyparse();
230 if (err || errors)
231 goto end;
232
233 store = p->store;
234
235 disasm_info = disasm_initialize(p->devinfo, NULL);
236 if (!disasm_info) {
237 fprintf(stderr, "Unable to initialize disasm_info struct instance\n");
238 goto end;
239 }
240
241 if (output_type == OPT_OUTPUT_C_LITERAL)
242 fprintf(output, "{\n");
243
244 brw_validate_instructions(p->devinfo, p->store, 0,
245 p->next_insn_offset, disasm_info);
246
247 const int nr_insn = (p->next_insn_offset - start_offset) / 16;
248
249 if (compact)
250 brw_compact_instructions(p, start_offset, disasm_info);
251
252 for (int i = 0; i < nr_insn; i++) {
253 const brw_inst *insn = store + offset;
254 bool compacted = false;
255
256 if (compact && brw_inst_cmpt_control(p->devinfo, insn)) {
257 offset += 8;
258 compacted = true;
259 } else {
260 offset += 16;
261 }
262
263 print_instruction(output, compacted, insn);
264 }
265
266 ralloc_free(disasm_info);
267
268 if (output_type == OPT_OUTPUT_C_LITERAL)
269 fprintf(output, "}");
270
271 result = EXIT_SUCCESS;
272 goto end;
273
274 end:
275 free(input_filename);
276 free(output_file);
277
278 if (yyin)
279 fclose(yyin);
280
281 if (output)
282 fclose(output);
283
284 if (p)
285 ralloc_free(p);
286
287 if (devinfo)
288 free(devinfo);
289
290 exit(result);
291 }