| /* |
| * 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" |
| |
| enum opt_output_type { |
| OPT_OUTPUT_HEX, |
| OPT_OUTPUT_C_LITERAL, |
| OPT_OUTPUT_BIN, |
| }; |
| |
| extern FILE *yyin; |
| struct brw_codegen *p; |
| static enum opt_output_type output_type = OPT_OUTPUT_BIN; |
| char *input_filename = NULL; |
| 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" |
| " -t, --type=OUTPUT_TYPE OUTPUT_TYPE can be 'bin' (default if omitted),\n" |
| " 'c_literal', or 'hex'\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 -t hex -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; |
| |
| switch (output_type) { |
| case OPT_OUTPUT_HEX: { |
| fprintf(output, "%02x", ((unsigned char *)instruction)[0]); |
| |
| for (unsigned i = 1; i < byte_limit; i++) { |
| fprintf(output, " %02x", ((unsigned char *)instruction)[i]); |
| } |
| break; |
| } |
| case OPT_OUTPUT_C_LITERAL: { |
| fprintf(output, "\t0x%02x,", ((unsigned char *)instruction)[0]); |
| |
| for (unsigned i = 1; i < byte_limit; i++) { |
| fprintf(output, " 0x%02x,", ((unsigned char *)instruction)[i]); |
| } |
| break; |
| } |
| case OPT_OUTPUT_BIN: |
| fwrite(instruction, 1, byte_limit, output); |
| break; |
| } |
| |
| if (output_type != OPT_OUTPUT_BIN) { |
| 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_from_pci_id(pci_id, devinfo)) { |
| fprintf(stderr, "can't find device information: pci_id=0x%x\n", |
| pci_id); |
| free(devinfo); |
| 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 = 0, err; |
| int start_offset = 0; |
| struct disasm_info *disasm_info; |
| struct gen_device_info *devinfo = NULL; |
| int result = EXIT_FAILURE; |
| |
| const struct option i965_asm_opts[] = { |
| { "help", no_argument, (int *) &help, true }, |
| { "type", required_argument, NULL, 't' }, |
| { "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, ":t:g:o:h", 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 't': { |
| if (strcmp(optarg, "hex") == 0) { |
| output_type = OPT_OUTPUT_HEX; |
| } else if (strcmp(optarg, "c_literal") == 0) { |
| output_type = OPT_OUTPUT_C_LITERAL; |
| } else if (strcmp(optarg, "bin") == 0) { |
| output_type = OPT_OUTPUT_BIN; |
| } else { |
| fprintf(stderr, "invalid value for --type: %s\n", optarg); |
| goto end; |
| } |
| 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 (output_type == OPT_OUTPUT_C_LITERAL) |
| fprintf(output, "static const char gen_eu_bytes[] = {\n"); |
| |
| brw_validate_instructions(p->devinfo, p->store, 0, |
| p->next_insn_offset, disasm_info); |
| |
| const int nr_insn = (p->next_insn_offset - start_offset) / 16; |
| |
| if (compact) |
| brw_compact_instructions(p, start_offset, 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); |
| } |
| |
| ralloc_free(disasm_info); |
| |
| if (output_type == OPT_OUTPUT_C_LITERAL) |
| fprintf(output, "}"); |
| |
| result = EXIT_SUCCESS; |
| goto end; |
| |
| end: |
| free(input_filename); |
| free(output_file); |
| |
| if (yyin) |
| fclose(yyin); |
| |
| if (output) |
| fclose(output); |
| |
| if (p) |
| ralloc_free(p); |
| |
| if (devinfo) |
| free(devinfo); |
| |
| exit(result); |
| } |