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 <string.h>
27 #include <getopt.h>
28
29 #include "util/ralloc.h"
30 #include "compiler/brw_eu_inst.h"
31 #include "dev/intel_device_info.h"
32
33 #include "brw_asm.h"
34
35 enum opt_output_type {
36 OPT_OUTPUT_HEX,
37 OPT_OUTPUT_C_LITERAL,
38 OPT_OUTPUT_BIN,
39 };
40
41 static enum opt_output_type output_type = OPT_OUTPUT_BIN;
42
43 static void
print_help(const char * progname,FILE * file)44 print_help(const char *progname, FILE *file)
45 {
46 fprintf(file,
47 "Usage: %s [OPTION] inputfile\n"
48 "Assemble i965 instructions from input file.\n\n"
49 " -h, --help display this help and exit\n"
50 " -t, --type=OUTPUT_TYPE OUTPUT_TYPE can be 'bin' (default if omitted),\n"
51 " 'c_literal', or 'hex'\n"
52 " -o, --output specify output file\n"
53 " --compact print compacted instructions\n"
54 " -g, --gen=platform assemble instructions for given \n"
55 " platform (3 letter platform name)\n"
56 "Example:\n"
57 " i965_asm -g kbl input.asm -t hex -o output\n",
58 progname);
59 }
60
61 static uint32_t
get_dword(const brw_eu_inst * inst,int idx)62 get_dword(const brw_eu_inst *inst, int idx)
63 {
64 uint32_t dword;
65 memcpy(&dword, (char *)inst + 4 * idx, sizeof(dword));
66 return dword;
67 }
68
69 static void
print_instruction(FILE * output,bool compact,const brw_eu_inst * instruction)70 print_instruction(FILE *output, bool compact, const brw_eu_inst *instruction)
71 {
72 int byte_limit;
73
74 byte_limit = (compact == true) ? 8 : 16;
75
76 switch (output_type) {
77 case OPT_OUTPUT_HEX: {
78 fprintf(output, "%02x", ((unsigned char *)instruction)[0]);
79
80 for (unsigned i = 1; i < byte_limit; i++) {
81 fprintf(output, " %02x", ((unsigned char *)instruction)[i]);
82 }
83 break;
84 }
85 case OPT_OUTPUT_C_LITERAL: {
86 fprintf(output, "\t0x%08x,", get_dword(instruction, 0));
87
88 for (unsigned i = 1; i < byte_limit / 4; i++)
89 fprintf(output, " 0x%08x,", get_dword(instruction, i));
90
91 break;
92 }
93 case OPT_OUTPUT_BIN:
94 fwrite(instruction, 1, byte_limit, output);
95 break;
96 }
97
98 if (output_type != OPT_OUTPUT_BIN) {
99 fprintf(output, "\n");
100 }
101 }
102
103 static struct intel_device_info *
i965_asm_init(uint16_t pci_id)104 i965_asm_init(uint16_t pci_id)
105 {
106 struct intel_device_info *devinfo;
107
108 devinfo = malloc(sizeof *devinfo);
109 if (devinfo == NULL)
110 return NULL;
111
112 if (!intel_get_device_info_from_pci_id(pci_id, devinfo)) {
113 fprintf(stderr, "can't find device information: pci_id=0x%x\n",
114 pci_id);
115 free(devinfo);
116 return NULL;
117 }
118
119 if (devinfo->ver < 9) {
120 fprintf(stderr, "device has gfx version %d but must be >= 9, try elk_asm instead",
121 devinfo->ver);
122 exit(EXIT_FAILURE);
123 }
124
125 return devinfo;
126 }
127
128
129
main(int argc,char ** argv)130 int main(int argc, char **argv)
131 {
132 void *mem_ctx = ralloc_context(NULL);
133 FILE *input_file = NULL;
134 char *output_file = NULL;
135 char c;
136 FILE *output = stdout;
137 bool help = false, compact = false;
138 uint64_t pci_id = 0;
139 struct intel_device_info *devinfo = NULL;
140 int result = EXIT_FAILURE;
141
142 const struct option i965_asm_opts[] = {
143 { "help", no_argument, (int *) &help, true },
144 { "type", required_argument, NULL, 't' },
145 { "gen", required_argument, NULL, 'g' },
146 { "output", required_argument, NULL, 'o' },
147 { "compact", no_argument, (int *) &compact, true },
148 { NULL, 0, NULL, 0 }
149 };
150
151 while ((c = getopt_long(argc, argv, ":t:g:o:h", i965_asm_opts, NULL)) != -1) {
152 switch (c) {
153 case 'g': {
154 const int id = intel_device_name_to_pci_device_id(optarg);
155 if (id < 0) {
156 fprintf(stderr, "can't parse gen: '%s', expected 3 letter "
157 "platform name\n", optarg);
158 goto end;
159 } else {
160 pci_id = id;
161 }
162 break;
163 }
164 case 'h':
165 help = true;
166 print_help(argv[0], stderr);
167 goto end;
168 case 't': {
169 if (strcmp(optarg, "hex") == 0) {
170 output_type = OPT_OUTPUT_HEX;
171 } else if (strcmp(optarg, "c_literal") == 0) {
172 output_type = OPT_OUTPUT_C_LITERAL;
173 } else if (strcmp(optarg, "bin") == 0) {
174 output_type = OPT_OUTPUT_BIN;
175 } else {
176 fprintf(stderr, "invalid value for --type: %s\n", optarg);
177 goto end;
178 }
179 break;
180 }
181 case 'o':
182 output_file = strdup(optarg);
183 break;
184 case 0:
185 break;
186 case ':':
187 fprintf(stderr, "%s: option `-%c' requires an argument\n",
188 argv[0], optopt);
189 goto end;
190 case '?':
191 default:
192 fprintf(stderr, "%s: option `-%c' is invalid: ignored\n",
193 argv[0], optopt);
194 goto end;
195 }
196 }
197
198 if (help || !pci_id) {
199 print_help(argv[0], stderr);
200 goto end;
201 }
202
203 if (!argv[optind]) {
204 fprintf(stderr, "Please specify input file\n");
205 goto end;
206 }
207
208 const char *filename = argv[optind];
209 input_file = fopen(filename, "r");
210 if (!input_file) {
211 fprintf(stderr, "Unable to read input file : %s\n",
212 filename);
213 goto end;
214 }
215
216 if (output_file) {
217 output = fopen(output_file, "w");
218 if (!output) {
219 fprintf(stderr, "Couldn't open output file\n");
220 goto end;
221 }
222 }
223
224 devinfo = i965_asm_init(pci_id);
225 if (!devinfo) {
226 fprintf(stderr, "Unable to allocate memory for "
227 "intel_device_info struct instance.\n");
228 goto end;
229 }
230
231 brw_assemble_result r = brw_assemble(mem_ctx, devinfo, input_file, filename,
232 compact ? BRW_ASSEMBLE_COMPACT : 0);
233 if (!r.bin)
234 goto end;
235
236 if (output_type == OPT_OUTPUT_C_LITERAL)
237 fprintf(output, "{\n");
238
239 for (int offset = 0; offset < r.bin_size;) {
240 const brw_eu_inst *insn = r.bin + offset;
241 bool compacted = false;
242
243 if (compact && brw_eu_inst_cmpt_control(devinfo, insn)) {
244 offset += 8;
245 compacted = true;
246 } else {
247 offset += 16;
248 }
249
250 print_instruction(output, compacted, insn);
251 }
252
253 if (output_type == OPT_OUTPUT_C_LITERAL)
254 fprintf(output, "}");
255
256 result = EXIT_SUCCESS;
257 goto end;
258
259 end:
260 free(output_file);
261
262 if (input_file)
263 fclose(input_file);
264
265 if (output)
266 fclose(output);
267
268 ralloc_free(mem_ctx);
269
270 if (devinfo)
271 free(devinfo);
272
273 exit(result);
274 }
275