17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2014 Intel Corporation
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
217ec681f3Smrg * IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include <stdlib.h>
257ec681f3Smrg
267ec681f3Smrg#include "compiler/brw_inst.h"
277ec681f3Smrg#include "compiler/brw_eu.h"
287ec681f3Smrg
297ec681f3Smrg#include "intel_disasm.h"
307ec681f3Smrg
317ec681f3Smrgstatic bool
327ec681f3Smrgis_send(uint32_t opcode)
337ec681f3Smrg{
347ec681f3Smrg   return (opcode == BRW_OPCODE_SEND  ||
357ec681f3Smrg           opcode == BRW_OPCODE_SENDC ||
367ec681f3Smrg           opcode == BRW_OPCODE_SENDS ||
377ec681f3Smrg           opcode == BRW_OPCODE_SENDSC );
387ec681f3Smrg}
397ec681f3Smrg
407ec681f3Smrgstatic int
417ec681f3Smrgintel_disasm_find_end(const struct intel_device_info *devinfo,
427ec681f3Smrg                      const void *assembly, int start)
437ec681f3Smrg{
447ec681f3Smrg   int offset = start;
457ec681f3Smrg
467ec681f3Smrg   /* This loop exits when send-with-EOT or when opcode is 0 */
477ec681f3Smrg   while (true) {
487ec681f3Smrg      const brw_inst *insn = assembly + offset;
497ec681f3Smrg
507ec681f3Smrg      if (brw_inst_cmpt_control(devinfo, insn)) {
517ec681f3Smrg         offset += 8;
527ec681f3Smrg      } else {
537ec681f3Smrg         offset += 16;
547ec681f3Smrg      }
557ec681f3Smrg
567ec681f3Smrg      /* Simplistic, but efficient way to terminate disasm */
577ec681f3Smrg      uint32_t opcode = brw_inst_opcode(devinfo, insn);
587ec681f3Smrg      if (opcode == 0 || (is_send(opcode) && brw_inst_eot(devinfo, insn))) {
597ec681f3Smrg         break;
607ec681f3Smrg      }
617ec681f3Smrg   }
627ec681f3Smrg
637ec681f3Smrg   return offset;
647ec681f3Smrg}
657ec681f3Smrg
667ec681f3Smrgvoid
677ec681f3Smrgintel_disassemble(const struct intel_device_info *devinfo,
687ec681f3Smrg                  const void *assembly, int start, FILE *out)
697ec681f3Smrg{
707ec681f3Smrg   int end = intel_disasm_find_end(devinfo, assembly, start);
717ec681f3Smrg
727ec681f3Smrg   /* Make a dummy disasm structure that brw_validate_instructions
737ec681f3Smrg    * can work from.
747ec681f3Smrg    */
757ec681f3Smrg   struct disasm_info *disasm_info = disasm_initialize(devinfo, NULL);
767ec681f3Smrg   disasm_new_inst_group(disasm_info, start);
777ec681f3Smrg   disasm_new_inst_group(disasm_info, end);
787ec681f3Smrg
797ec681f3Smrg   brw_validate_instructions(devinfo, assembly, start, end, disasm_info);
807ec681f3Smrg
817ec681f3Smrg   void *mem_ctx = ralloc_context(NULL);
827ec681f3Smrg   const struct brw_label *root_label =
837ec681f3Smrg      brw_label_assembly(devinfo, assembly, start, end, mem_ctx);
847ec681f3Smrg
857ec681f3Smrg   foreach_list_typed(struct inst_group, group, link,
867ec681f3Smrg                      &disasm_info->group_list) {
877ec681f3Smrg      struct exec_node *next_node = exec_node_get_next(&group->link);
887ec681f3Smrg      if (exec_node_is_tail_sentinel(next_node))
897ec681f3Smrg         break;
907ec681f3Smrg
917ec681f3Smrg      struct inst_group *next =
927ec681f3Smrg         exec_node_data(struct inst_group, next_node, link);
937ec681f3Smrg
947ec681f3Smrg      int start_offset = group->offset;
957ec681f3Smrg      int end_offset = next->offset;
967ec681f3Smrg
977ec681f3Smrg      brw_disassemble(devinfo, assembly, start_offset, end_offset,
987ec681f3Smrg                      root_label, out);
997ec681f3Smrg
1007ec681f3Smrg      if (group->error) {
1017ec681f3Smrg         fputs(group->error, out);
1027ec681f3Smrg      }
1037ec681f3Smrg   }
1047ec681f3Smrg
1057ec681f3Smrg   ralloc_free(mem_ctx);
1067ec681f3Smrg   ralloc_free(disasm_info);
1077ec681f3Smrg}
108