summaryrefslogtreecommitdiffstats
path: root/src/intel/tools/i965_asm.c
diff options
context:
space:
mode:
authorSagar Ghuge <[email protected]>2018-12-10 16:12:07 -0800
committerMatt Turner <[email protected]>2019-05-07 14:33:38 -0700
commit70308a5a8a801a960bb9f45fb597f80b77c51014 (patch)
tree567aad915f6c9bbd77c2571be21425a6aab4bb90 /src/intel/tools/i965_asm.c
parenta232aa5c50226a744dfbcd46057f84d5d82e5c82 (diff)
intel/tools: New i965 instruction assembler tool
Tool is inspired from igt's assembler tool. Thanks to Matt Turner, who mentored me through out this project. v2: Fix memory leaks and naming convention (Caio) v3: Fix meson changes (Dylan Baker) v4: Fix usage options (Matt Turner) Signed-off-by: Sagar Ghuge <[email protected]> Reviewed-by: Dylan Baker <[email protected]> Reviewed-by: Matt Turner <[email protected]> Closes: https://gitlab.freedesktop.org/mesa/mesa/merge_requests/141
Diffstat (limited to 'src/intel/tools/i965_asm.c')
-rw-r--r--src/intel/tools/i965_asm.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/intel/tools/i965_asm.c b/src/intel/tools/i965_asm.c
new file mode 100644
index 00000000000..667f43da0d7
--- /dev/null
+++ b/src/intel/tools/i965_asm.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright © 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include "i965_asm.h"
+
+extern FILE *yyin;
+struct brw_codegen *p;
+static int c_literal_output = 0;
+char *input_filename;
+int errors;
+
+static void
+print_help(const char *progname, FILE *file)
+{
+ fprintf(file,
+ "Usage: %s [OPTION] inputfile\n"
+ "Assemble i965 instructions from input file.\n\n"
+ " -h, --help display this help and exit\n"
+ " -l, --c-literal C literal\n"
+ " -o, --output specify output file\n"
+ " --compact print compacted instructions\n"
+ " -g, --gen=platform assemble instructions for given \n"
+ " platform (3 letter platform name)\n"
+ "Example:\n"
+ " i965_asm -g kbl input.asm -o output\n",
+ progname);
+}
+
+static void
+print_instruction(FILE *output, bool compact, const brw_inst *instruction)
+{
+ int byte_limit;
+
+ byte_limit = (compact == true) ? 8 : 16;
+
+ if (c_literal_output) {
+ fprintf(output, "\t0x%02x,", ((unsigned char *)instruction)[0]);
+
+ for (unsigned i = 1; i < byte_limit; i++)
+ fprintf(output, " 0x%02x,", ((unsigned char *)instruction)[i]);
+ } else {
+ fprintf(output, "%02x", ((unsigned char *)instruction)[0]);
+
+ for (unsigned i = 1; i < byte_limit; i++)
+ fprintf(output, " %02x", ((unsigned char *)instruction)[i]);
+ }
+ fprintf(output, "\n");
+}
+
+static struct gen_device_info *
+i965_disasm_init(uint16_t pci_id)
+{
+ struct gen_device_info *devinfo;
+
+ devinfo = malloc(sizeof *devinfo);
+ if (devinfo == NULL)
+ return NULL;
+
+ if (!gen_get_device_info(pci_id, devinfo)) {
+ fprintf(stderr, "can't find device information: pci_id=0x%x\n",
+ pci_id);
+ return NULL;
+ }
+
+ brw_init_compaction_tables(devinfo);
+
+ return devinfo;
+}
+
+int main(int argc, char **argv)
+{
+ char *output_file = NULL;
+ char c;
+ FILE *output = stdout;
+ bool help = false, compact = false;
+ void *store;
+ uint64_t pci_id = 0;
+ int offset, err;
+ int start_offset = 0;
+ struct disasm_info *disasm_info;
+ struct gen_device_info *devinfo;
+ int result = EXIT_FAILURE;
+
+ const struct option i965_asm_opts[] = {
+ { "help", no_argument, (int *) &help, true },
+ { "c-literal", no_argument, NULL, 'c' },
+ { "gen", required_argument, NULL, 'g' },
+ { "output", required_argument, NULL, 'o' },
+ { "compact", no_argument, (int *) &compact, true },
+ { NULL, 0, NULL, 0 }
+ };
+
+ while ((c = getopt_long(argc, argv, ":g:o:lh", i965_asm_opts, NULL)) != -1) {
+ switch (c) {
+ case 'g': {
+ const int id = gen_device_name_to_pci_device_id(optarg);
+ if (id < 0) {
+ fprintf(stderr, "can't parse gen: '%s', expected 3 letter "
+ "platform name\n", optarg);
+ goto end;
+ } else {
+ pci_id = id;
+ }
+ break;
+ }
+ case 'h':
+ help = true;
+ print_help(argv[0], stderr);
+ goto end;
+ case 'l':
+ c_literal_output = 1;
+ break;
+ case 'o':
+ output_file = strdup(optarg);
+ break;
+ case 0:
+ break;
+ case ':':
+ fprintf(stderr, "%s: option `-%c' requires an argument\n",
+ argv[0], optopt);
+ goto end;
+ case '?':
+ default:
+ fprintf(stderr, "%s: option `-%c' is invalid: ignored\n",
+ argv[0], optopt);
+ goto end;
+ }
+ }
+
+ if (help || !pci_id) {
+ print_help(argv[0], stderr);
+ goto end;
+ }
+
+ if (!argv[optind]) {
+ fprintf(stderr, "Please specify input file\n");
+ goto end;
+ }
+
+ input_filename = strdup(argv[optind]);
+ yyin = fopen(input_filename, "r");
+ if (!yyin) {
+ fprintf(stderr, "Unable to read input file : %s\n",
+ input_filename);
+ goto end;
+ }
+
+ if (output_file) {
+ output = fopen(output_file, "w");
+ if (!output) {
+ fprintf(stderr, "Couldn't open output file\n");
+ goto end;
+ }
+ }
+
+ devinfo = i965_disasm_init(pci_id);
+ if (!devinfo) {
+ fprintf(stderr, "Unable to allocate memory for "
+ "gen_device_info struct instance.\n");
+ goto end;
+ }
+
+ p = rzalloc(NULL, struct brw_codegen);
+ brw_init_codegen(devinfo, p, p);
+ p->automatic_exec_sizes = false;
+
+ err = yyparse();
+ if (err || errors)
+ goto end;
+
+ store = p->store;
+
+ disasm_info = disasm_initialize(p->devinfo, NULL);
+ if (!disasm_info) {
+ fprintf(stderr, "Unable to initialize disasm_info struct instance\n");
+ goto end;
+ }
+
+ if (c_literal_output)
+ fprintf(output, "static const char gen_eu_bytes[] = {\n");
+
+ brw_validate_instructions(p->devinfo, p->store, 0,
+ p->next_insn_offset, disasm_info);
+
+ int nr_insn = (p->next_insn_offset - start_offset) / 16;
+
+ if (compact)
+ brw_compact_instructions(p, start_offset, disasm_info);
+
+ ralloc_free(disasm_info);
+
+ for (int i = 0; i < nr_insn; i++) {
+ const brw_inst *insn = store + offset;
+ bool compacted = false;
+
+ if (compact && brw_inst_cmpt_control(p->devinfo, insn)) {
+ offset += 8;
+ compacted = true;
+ } else {
+ offset += 16;
+ }
+
+ print_instruction(output, compacted, insn);
+ }
+
+ if (c_literal_output)
+ fprintf(output, "}");
+
+ result = EXIT_SUCCESS;
+ goto end;
+
+end:
+ if (input_filename)
+ free(input_filename);
+
+ if (output_file)
+ free(output_file);
+
+ if (yyin)
+ fclose(yyin);
+
+ if (output)
+ fclose(output);
+
+ if (p)
+ ralloc_free(p);
+
+ if (devinfo)
+ free(devinfo);
+
+ exit(result);
+}