101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2018 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include <stdio.h> 2501e04c3fSmrg#include <stdlib.h> 2601e04c3fSmrg#include <string.h> 2701e04c3fSmrg#include <getopt.h> 2801e04c3fSmrg 2901e04c3fSmrg#include "compiler/brw_eu.h" 307ec681f3Smrg#include "dev/intel_device_info.h" 317ec681f3Smrg#include "util/u_dynarray.h" 327ec681f3Smrg 337ec681f3Smrgenum opt_input_type { 347ec681f3Smrg OPT_INPUT_BINARY, 357ec681f3Smrg OPT_INPUT_C_LITERAL, 367ec681f3Smrg}; 377ec681f3Smrg 387ec681f3Smrgstatic enum opt_input_type input_type = OPT_INPUT_BINARY; 3901e04c3fSmrg 4001e04c3fSmrg/* Return size of file in bytes pointed by fp */ 417ec681f3Smrgstatic long 4201e04c3fSmrgi965_disasm_get_file_size(FILE *fp) 4301e04c3fSmrg{ 447ec681f3Smrg long size; 4501e04c3fSmrg 4601e04c3fSmrg fseek(fp, 0L, SEEK_END); 4701e04c3fSmrg size = ftell(fp); 4801e04c3fSmrg fseek(fp, 0L, SEEK_SET); 4901e04c3fSmrg 5001e04c3fSmrg return size; 5101e04c3fSmrg} 5201e04c3fSmrg 537ec681f3Smrg/* Read hex file which should be in following format: 547ec681f3Smrg * for example : 557ec681f3Smrg * { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } 567ec681f3Smrg */ 577ec681f3Smrgstatic void * 587ec681f3Smrgi965_disasm_read_c_literal_file(FILE *fp, size_t *end) 597ec681f3Smrg{ 607ec681f3Smrg struct util_dynarray assembly = {}; 617ec681f3Smrg uint32_t temp[2]; 627ec681f3Smrg 637ec681f3Smrg if (fscanf(fp, " { ") == EOF) { 647ec681f3Smrg fprintf(stderr, "Couldn't find opening `{`\n"); 657ec681f3Smrg return NULL; 667ec681f3Smrg } 677ec681f3Smrg 687ec681f3Smrg if (fscanf(fp, "0x%x , 0x%x", &temp[0], &temp[1]) == 2) { 697ec681f3Smrg util_dynarray_append(&assembly, uint32_t, temp[0]); 707ec681f3Smrg util_dynarray_append(&assembly, uint32_t, temp[1]); 717ec681f3Smrg } else { 727ec681f3Smrg fprintf(stderr, "Couldn't read hex values\n"); 737ec681f3Smrg return NULL; 747ec681f3Smrg } 757ec681f3Smrg 767ec681f3Smrg while (fscanf(fp, " , 0x%x , 0x%x ", &temp[0], &temp[1]) == 2) { 777ec681f3Smrg util_dynarray_append(&assembly, uint32_t, temp[0]); 787ec681f3Smrg util_dynarray_append(&assembly, uint32_t, temp[1]); 797ec681f3Smrg } 807ec681f3Smrg 817ec681f3Smrg if (fscanf(fp, "}") == EOF) { 827ec681f3Smrg fprintf(stderr, "Couldn't find closing `}`\n"); 837ec681f3Smrg return NULL; 847ec681f3Smrg } 857ec681f3Smrg 867ec681f3Smrg *end = assembly.size; 877ec681f3Smrg return assembly.data; 887ec681f3Smrg} 897ec681f3Smrg 9001e04c3fSmrgstatic void * 9101e04c3fSmrgi965_disasm_read_binary(FILE *fp, size_t *end) 9201e04c3fSmrg{ 939f464c52Smaya size_t size; 9401e04c3fSmrg void *assembly; 9501e04c3fSmrg 967ec681f3Smrg long sz = i965_disasm_get_file_size(fp); 977ec681f3Smrg if (sz < 0) 987ec681f3Smrg return NULL; 997ec681f3Smrg 1007ec681f3Smrg *end = (size_t)sz; 1019f464c52Smaya if (!*end) 1029f464c52Smaya return NULL; 10301e04c3fSmrg 10401e04c3fSmrg assembly = malloc(*end + 1); 10501e04c3fSmrg if (assembly == NULL) 10601e04c3fSmrg return NULL; 10701e04c3fSmrg 1089f464c52Smaya size = fread(assembly, *end, 1, fp); 1099f464c52Smaya if (!size) { 1109f464c52Smaya free(assembly); 1119f464c52Smaya return NULL; 1129f464c52Smaya } 11301e04c3fSmrg return assembly; 11401e04c3fSmrg} 11501e04c3fSmrg 1167ec681f3Smrgstatic struct intel_device_info * 11701e04c3fSmrgi965_disasm_init(uint16_t pci_id) 11801e04c3fSmrg{ 1197ec681f3Smrg struct intel_device_info *devinfo; 12001e04c3fSmrg 12101e04c3fSmrg devinfo = malloc(sizeof *devinfo); 12201e04c3fSmrg if (devinfo == NULL) 12301e04c3fSmrg return NULL; 12401e04c3fSmrg 1257ec681f3Smrg if (!intel_get_device_info_from_pci_id(pci_id, devinfo)) { 12601e04c3fSmrg fprintf(stderr, "can't find device information: pci_id=0x%x\n", 12701e04c3fSmrg pci_id); 12801e04c3fSmrg exit(EXIT_FAILURE); 12901e04c3fSmrg } 13001e04c3fSmrg 13101e04c3fSmrg return devinfo; 13201e04c3fSmrg} 13301e04c3fSmrg 13401e04c3fSmrgstatic void 13501e04c3fSmrgprint_help(const char *progname, FILE *file) 13601e04c3fSmrg{ 13701e04c3fSmrg fprintf(file, 13801e04c3fSmrg "Usage: %s [OPTION]...\n" 13901e04c3fSmrg "Disassemble i965 instructions from binary file.\n\n" 14001e04c3fSmrg " --help display this help and exit\n" 1417ec681f3Smrg " --input-path=PATH read binary file from binary file PATH\n" 1427ec681f3Smrg " --type=INPUT_TYPE INPUT_TYPE can be 'bin' (default if omitted),\n" 1437ec681f3Smrg " 'c_literal'.\n" 14401e04c3fSmrg " --gen=platform disassemble instructions for given \n" 14501e04c3fSmrg " platform (3 letter platform name)\n", 14601e04c3fSmrg progname); 14701e04c3fSmrg} 14801e04c3fSmrg 14901e04c3fSmrgint main(int argc, char *argv[]) 15001e04c3fSmrg{ 15101e04c3fSmrg FILE *fp = NULL; 15201e04c3fSmrg void *assembly = NULL; 1537ec681f3Smrg char *file_path = NULL; 15401e04c3fSmrg size_t start = 0, end = 0; 15501e04c3fSmrg uint16_t pci_id = 0; 1567ec681f3Smrg int c; 1577ec681f3Smrg struct intel_device_info *devinfo = NULL; 1587ec681f3Smrg int result = EXIT_FAILURE; 15901e04c3fSmrg 16001e04c3fSmrg bool help = false; 16101e04c3fSmrg const struct option i965_disasm_opts[] = { 16201e04c3fSmrg { "help", no_argument, (int *) &help, true }, 1637ec681f3Smrg { "input-path", required_argument, NULL, 'i' }, 1647ec681f3Smrg { "type", required_argument, NULL, 't' }, 16501e04c3fSmrg { "gen", required_argument, NULL, 'g'}, 16601e04c3fSmrg { NULL, 0, NULL, 0 } 16701e04c3fSmrg }; 16801e04c3fSmrg 1697ec681f3Smrg while ((c = getopt_long(argc, argv, ":i:t:g:h", i965_disasm_opts, NULL)) != -1) { 17001e04c3fSmrg switch (c) { 17101e04c3fSmrg case 'g': { 1727ec681f3Smrg const int id = intel_device_name_to_pci_device_id(optarg); 17301e04c3fSmrg if (id < 0) { 17401e04c3fSmrg fprintf(stderr, "can't parse gen: '%s', expected 3 letter " 17501e04c3fSmrg "platform name\n", optarg); 1767ec681f3Smrg goto end; 17701e04c3fSmrg } else { 17801e04c3fSmrg pci_id = id; 17901e04c3fSmrg } 18001e04c3fSmrg break; 18101e04c3fSmrg } 1827ec681f3Smrg case 'i': 1837ec681f3Smrg file_path = strdup(optarg); 1847ec681f3Smrg fp = fopen(file_path, "r"); 18501e04c3fSmrg if (!fp) { 1867ec681f3Smrg fprintf(stderr, "Unable to read input file : %s\n", 1877ec681f3Smrg file_path); 1887ec681f3Smrg goto end; 18901e04c3fSmrg } 19001e04c3fSmrg break; 1917ec681f3Smrg case 't': 1927ec681f3Smrg if (strcmp(optarg, "c_literal") == 0) { 1937ec681f3Smrg input_type = OPT_INPUT_C_LITERAL; 1947ec681f3Smrg } else if (strcmp(optarg, "bin") == 0) { 1957ec681f3Smrg input_type = OPT_INPUT_BINARY; 1967ec681f3Smrg } else { 1977ec681f3Smrg fprintf(stderr, "invalid value for --type: %s\n", optarg); 1987ec681f3Smrg goto end; 19901e04c3fSmrg } 20001e04c3fSmrg break; 2017ec681f3Smrg case 'h': 2027ec681f3Smrg help = true; 2037ec681f3Smrg print_help(argv[0], stderr); 2047ec681f3Smrg goto end; 2057ec681f3Smrg case 0: 2067ec681f3Smrg break; 2077ec681f3Smrg case ':': 2087ec681f3Smrg fprintf(stderr, "%s: option `-%c' requires an argument\n", 2097ec681f3Smrg argv[0], optopt); 2107ec681f3Smrg goto end; 2117ec681f3Smrg case '?': 2127ec681f3Smrg default: 2137ec681f3Smrg fprintf(stderr, "%s: option `-%c' is invalid: ignored\n", 2147ec681f3Smrg argv[0], optopt); 2157ec681f3Smrg goto end; 21601e04c3fSmrg } 21701e04c3fSmrg } 21801e04c3fSmrg 2197ec681f3Smrg if (help || !file_path || !pci_id) { 22001e04c3fSmrg print_help(argv[0], stderr); 22101e04c3fSmrg exit(0); 22201e04c3fSmrg } 22301e04c3fSmrg 22401e04c3fSmrg devinfo = i965_disasm_init(pci_id); 22501e04c3fSmrg if (!devinfo) { 22601e04c3fSmrg fprintf(stderr, "Unable to allocate memory for " 2277ec681f3Smrg "intel_device_info struct instance.\n"); 2287ec681f3Smrg goto end; 22901e04c3fSmrg } 23001e04c3fSmrg 2317ec681f3Smrg if (input_type == OPT_INPUT_BINARY) 2327ec681f3Smrg assembly = i965_disasm_read_binary(fp, &end); 2337ec681f3Smrg else if (input_type == OPT_INPUT_C_LITERAL) 2347ec681f3Smrg assembly = i965_disasm_read_c_literal_file(fp, &end); 2357ec681f3Smrg 23601e04c3fSmrg if (!assembly) { 2379f464c52Smaya if (end) 2387ec681f3Smrg fprintf(stderr, "Unable to allocate buffer to read input file\n"); 2399f464c52Smaya else 2407ec681f3Smrg fprintf(stderr, "Failed to read input file\n"); 2419f464c52Smaya 2427ec681f3Smrg goto end; 24301e04c3fSmrg } 24401e04c3fSmrg 24501e04c3fSmrg /* Disassemble i965 instructions from buffer assembly */ 2467ec681f3Smrg brw_disassemble_with_labels(devinfo, assembly, start, end, stdout); 2477ec681f3Smrg 2487ec681f3Smrg result = EXIT_SUCCESS; 2497ec681f3Smrg 2507ec681f3Smrgend: 2517ec681f3Smrg if (fp) 2527ec681f3Smrg fclose(fp); 25301e04c3fSmrg 2547ec681f3Smrg free(file_path); 25501e04c3fSmrg free(assembly); 25601e04c3fSmrg free(devinfo); 25701e04c3fSmrg 2587ec681f3Smrg exit(result); 25901e04c3fSmrg} 260