Path: blob/21.2-virgl/src/intel/tools/i965_asm.c
4547 views
/*1* Copyright © 2018 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22*/2324#include <stdio.h>25#include <getopt.h>26#include "i965_asm.h"2728enum opt_output_type {29OPT_OUTPUT_HEX,30OPT_OUTPUT_C_LITERAL,31OPT_OUTPUT_BIN,32};3334extern FILE *yyin;35struct brw_codegen *p;36static enum opt_output_type output_type = OPT_OUTPUT_BIN;37char *input_filename = NULL;38int errors;3940struct list_head instr_labels;41struct list_head target_labels;4243static void44print_help(const char *progname, FILE *file)45{46fprintf(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",58progname);59}6061static uint32_t62get_dword(const brw_inst *inst, int idx)63{64uint32_t dword;65memcpy(&dword, (char *)inst + 4 * idx, sizeof(dword));66return dword;67}6869static void70print_instruction(FILE *output, bool compact, const brw_inst *instruction)71{72int byte_limit;7374byte_limit = (compact == true) ? 8 : 16;7576switch (output_type) {77case OPT_OUTPUT_HEX: {78fprintf(output, "%02x", ((unsigned char *)instruction)[0]);7980for (unsigned i = 1; i < byte_limit; i++) {81fprintf(output, " %02x", ((unsigned char *)instruction)[i]);82}83break;84}85case OPT_OUTPUT_C_LITERAL: {86fprintf(output, "\t0x%08x,", get_dword(instruction, 0));8788for (unsigned i = 1; i < byte_limit / 4; i++)89fprintf(output, " 0x%08x,", get_dword(instruction, i));9091break;92}93case OPT_OUTPUT_BIN:94fwrite(instruction, 1, byte_limit, output);95break;96}9798if (output_type != OPT_OUTPUT_BIN) {99fprintf(output, "\n");100}101}102103static struct intel_device_info *104i965_disasm_init(uint16_t pci_id)105{106struct intel_device_info *devinfo;107108devinfo = malloc(sizeof *devinfo);109if (devinfo == NULL)110return NULL;111112if (!intel_get_device_info_from_pci_id(pci_id, devinfo)) {113fprintf(stderr, "can't find device information: pci_id=0x%x\n",114pci_id);115free(devinfo);116return NULL;117}118119return devinfo;120}121122static bool123i965_postprocess_labels()124{125if (p->devinfo->ver < 6) {126return true;127}128129void *store = p->store;130131struct target_label *tlabel;132struct instr_label *ilabel, *s;133134const unsigned to_bytes_scale = brw_jump_scale(p->devinfo);135136LIST_FOR_EACH_ENTRY(tlabel, &target_labels, link) {137LIST_FOR_EACH_ENTRY_SAFE(ilabel, s, &instr_labels, link) {138if (!strcmp(tlabel->name, ilabel->name)) {139brw_inst *inst = store + ilabel->offset;140141int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst);142relative_offset *= to_bytes_scale;143144unsigned opcode = brw_inst_opcode(p->devinfo, inst);145146if (ilabel->type == INSTR_LABEL_JIP) {147switch (opcode) {148case BRW_OPCODE_IF:149case BRW_OPCODE_ELSE:150case BRW_OPCODE_ENDIF:151case BRW_OPCODE_WHILE:152if (p->devinfo->ver >= 7) {153brw_inst_set_jip(p->devinfo, inst, relative_offset);154} else if (p->devinfo->ver == 6) {155brw_inst_set_gfx6_jump_count(p->devinfo, inst, relative_offset);156}157break;158case BRW_OPCODE_BREAK:159case BRW_OPCODE_HALT:160case BRW_OPCODE_CONTINUE:161brw_inst_set_jip(p->devinfo, inst, relative_offset);162break;163default:164fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode);165return false;166}167} else {168switch (opcode) {169case BRW_OPCODE_IF:170case BRW_OPCODE_ELSE:171if (p->devinfo->ver > 7) {172brw_inst_set_uip(p->devinfo, inst, relative_offset);173} else if (p->devinfo->ver == 7) {174brw_inst_set_uip(p->devinfo, inst, relative_offset);175} else if (p->devinfo->ver == 6) {176// Nothing177}178break;179case BRW_OPCODE_WHILE:180case BRW_OPCODE_ENDIF:181fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n");182return false;183case BRW_OPCODE_BREAK:184case BRW_OPCODE_CONTINUE:185case BRW_OPCODE_HALT:186brw_inst_set_uip(p->devinfo, inst, relative_offset);187break;188default:189fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode);190return false;191}192}193194list_del(&ilabel->link);195}196}197}198199LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) {200fprintf(stderr, "Unknown label '%s'\n", ilabel->name);201}202203return list_is_empty(&instr_labels);204}205206int main(int argc, char **argv)207{208char *output_file = NULL;209char c;210FILE *output = stdout;211bool help = false, compact = false;212void *store;213uint64_t pci_id = 0;214int offset = 0, err;215int start_offset = 0;216struct disasm_info *disasm_info;217struct intel_device_info *devinfo = NULL;218int result = EXIT_FAILURE;219list_inithead(&instr_labels);220list_inithead(&target_labels);221222const struct option i965_asm_opts[] = {223{ "help", no_argument, (int *) &help, true },224{ "type", required_argument, NULL, 't' },225{ "gen", required_argument, NULL, 'g' },226{ "output", required_argument, NULL, 'o' },227{ "compact", no_argument, (int *) &compact, true },228{ NULL, 0, NULL, 0 }229};230231while ((c = getopt_long(argc, argv, ":t:g:o:h", i965_asm_opts, NULL)) != -1) {232switch (c) {233case 'g': {234const int id = intel_device_name_to_pci_device_id(optarg);235if (id < 0) {236fprintf(stderr, "can't parse gen: '%s', expected 3 letter "237"platform name\n", optarg);238goto end;239} else {240pci_id = id;241}242break;243}244case 'h':245help = true;246print_help(argv[0], stderr);247goto end;248case 't': {249if (strcmp(optarg, "hex") == 0) {250output_type = OPT_OUTPUT_HEX;251} else if (strcmp(optarg, "c_literal") == 0) {252output_type = OPT_OUTPUT_C_LITERAL;253} else if (strcmp(optarg, "bin") == 0) {254output_type = OPT_OUTPUT_BIN;255} else {256fprintf(stderr, "invalid value for --type: %s\n", optarg);257goto end;258}259break;260}261case 'o':262output_file = strdup(optarg);263break;264case 0:265break;266case ':':267fprintf(stderr, "%s: option `-%c' requires an argument\n",268argv[0], optopt);269goto end;270case '?':271default:272fprintf(stderr, "%s: option `-%c' is invalid: ignored\n",273argv[0], optopt);274goto end;275}276}277278if (help || !pci_id) {279print_help(argv[0], stderr);280goto end;281}282283if (!argv[optind]) {284fprintf(stderr, "Please specify input file\n");285goto end;286}287288input_filename = strdup(argv[optind]);289yyin = fopen(input_filename, "r");290if (!yyin) {291fprintf(stderr, "Unable to read input file : %s\n",292input_filename);293goto end;294}295296if (output_file) {297output = fopen(output_file, "w");298if (!output) {299fprintf(stderr, "Couldn't open output file\n");300goto end;301}302}303304devinfo = i965_disasm_init(pci_id);305if (!devinfo) {306fprintf(stderr, "Unable to allocate memory for "307"intel_device_info struct instance.\n");308goto end;309}310311p = rzalloc(NULL, struct brw_codegen);312brw_init_codegen(devinfo, p, p);313p->automatic_exec_sizes = false;314315err = yyparse();316if (err || errors)317goto end;318319if (!i965_postprocess_labels())320goto end;321322store = p->store;323324disasm_info = disasm_initialize(p->devinfo, NULL);325if (!disasm_info) {326fprintf(stderr, "Unable to initialize disasm_info struct instance\n");327goto end;328}329330if (output_type == OPT_OUTPUT_C_LITERAL)331fprintf(output, "{\n");332333brw_validate_instructions(p->devinfo, p->store, 0,334p->next_insn_offset, disasm_info);335336const int nr_insn = (p->next_insn_offset - start_offset) / 16;337338if (compact)339brw_compact_instructions(p, start_offset, disasm_info);340341for (int i = 0; i < nr_insn; i++) {342const brw_inst *insn = store + offset;343bool compacted = false;344345if (compact && brw_inst_cmpt_control(p->devinfo, insn)) {346offset += 8;347compacted = true;348} else {349offset += 16;350}351352print_instruction(output, compacted, insn);353}354355ralloc_free(disasm_info);356357if (output_type == OPT_OUTPUT_C_LITERAL)358fprintf(output, "}");359360result = EXIT_SUCCESS;361goto end;362363end:364free(input_filename);365free(output_file);366367if (yyin)368fclose(yyin);369370if (output)371fclose(output);372373if (p)374ralloc_free(p);375376if (devinfo)377free(devinfo);378379exit(result);380}381382383