xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/brw_asm_tool.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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_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_inst * inst,int idx)62 get_dword(const brw_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_inst * instruction)70 print_instruction(FILE *output, bool compact, const brw_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    int offset = 0;
140    struct intel_device_info *devinfo = NULL;
141    int result = EXIT_FAILURE;
142 
143    const struct option i965_asm_opts[] = {
144       { "help",          no_argument,       (int *) &help,      true },
145       { "type",          required_argument, NULL,               't' },
146       { "gen",           required_argument, NULL,               'g' },
147       { "output",        required_argument, NULL,               'o' },
148       { "compact",       no_argument,       (int *) &compact,   true },
149       { NULL,            0,                 NULL,               0 }
150    };
151 
152    while ((c = getopt_long(argc, argv, ":t:g:o:h", i965_asm_opts, NULL)) != -1) {
153       switch (c) {
154       case 'g': {
155          const int id = intel_device_name_to_pci_device_id(optarg);
156          if (id < 0) {
157             fprintf(stderr, "can't parse gen: '%s', expected 3 letter "
158                             "platform name\n", optarg);
159             goto end;
160          } else {
161             pci_id = id;
162          }
163          break;
164       }
165       case 'h':
166          help = true;
167          print_help(argv[0], stderr);
168          goto end;
169       case 't': {
170          if (strcmp(optarg, "hex") == 0) {
171             output_type = OPT_OUTPUT_HEX;
172          } else if (strcmp(optarg, "c_literal") == 0) {
173             output_type = OPT_OUTPUT_C_LITERAL;
174          } else if (strcmp(optarg, "bin") == 0) {
175             output_type = OPT_OUTPUT_BIN;
176          } else {
177             fprintf(stderr, "invalid value for --type: %s\n", optarg);
178             goto end;
179          }
180          break;
181       }
182       case 'o':
183          output_file = strdup(optarg);
184          break;
185       case 0:
186          break;
187       case ':':
188          fprintf(stderr, "%s: option `-%c' requires an argument\n",
189                  argv[0], optopt);
190          goto end;
191       case '?':
192       default:
193          fprintf(stderr, "%s: option `-%c' is invalid: ignored\n",
194                  argv[0], optopt);
195          goto end;
196       }
197    }
198 
199    if (help || !pci_id) {
200       print_help(argv[0], stderr);
201       goto end;
202    }
203 
204    if (!argv[optind]) {
205       fprintf(stderr, "Please specify input file\n");
206       goto end;
207    }
208 
209    const char *filename = argv[optind];
210    input_file = fopen(filename, "r");
211    if (!input_file) {
212       fprintf(stderr, "Unable to read input file : %s\n",
213               filename);
214       goto end;
215    }
216 
217    if (output_file) {
218       output = fopen(output_file, "w");
219       if (!output) {
220          fprintf(stderr, "Couldn't open output file\n");
221          goto end;
222       }
223    }
224 
225    devinfo = i965_asm_init(pci_id);
226    if (!devinfo) {
227       fprintf(stderr, "Unable to allocate memory for "
228                       "intel_device_info struct instance.\n");
229       goto end;
230    }
231 
232    brw_assemble_result r = brw_assemble(mem_ctx, devinfo, input_file, filename,
233                                         compact ? BRW_ASSEMBLE_COMPACT : 0);
234    if (!r.bin)
235       goto end;
236 
237    if (output_type == OPT_OUTPUT_C_LITERAL)
238       fprintf(output, "{\n");
239 
240    for (int i = 0; i < r.inst_count; i++) {
241       const brw_inst *insn = r.bin + offset;
242       bool compacted = false;
243 
244       if (compact && brw_inst_cmpt_control(devinfo, insn)) {
245             offset += 8;
246             compacted = true;
247       } else {
248             offset += 16;
249       }
250 
251       print_instruction(output, compacted, insn);
252    }
253 
254    if (output_type == OPT_OUTPUT_C_LITERAL)
255       fprintf(output, "}");
256 
257    result = EXIT_SUCCESS;
258    goto end;
259 
260 end:
261    free(output_file);
262 
263    if (input_file)
264       fclose(input_file);
265 
266    if (output)
267       fclose(output);
268 
269    ralloc_free(mem_ctx);
270 
271    if (devinfo)
272       free(devinfo);
273 
274    exit(result);
275 }
276