#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 int c_literal_output = 0;
+static enum opt_output_type output_type = OPT_OUTPUT_BIN;
char *input_filename = NULL;
int errors;
+struct list_head instr_labels;
+struct list_head target_labels;
+
static void
print_help(const char *progname, FILE *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"
+ " -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 -o output\n",
+ " i965_asm -g kbl input.asm -t hex -o output\n",
progname);
}
+static uint32_t
+get_dword(const brw_inst *inst, int idx)
+{
+ uint32_t dword;
+ memcpy(&dword, (char *)inst + 4 * idx, sizeof(dword));
+ return dword;
+}
+
static void
print_instruction(FILE *output, bool compact, const brw_inst *instruction)
{
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 {
+ switch (output_type) {
+ case OPT_OUTPUT_HEX: {
fprintf(output, "%02x", ((unsigned char *)instruction)[0]);
- for (unsigned i = 1; i < byte_limit; i++)
+ for (unsigned i = 1; i < byte_limit; i++) {
fprintf(output, " %02x", ((unsigned char *)instruction)[i]);
+ }
+ break;
+ }
+ case OPT_OUTPUT_C_LITERAL: {
+ fprintf(output, "\t0x%08x,", get_dword(instruction, 0));
+
+ for (unsigned i = 1; i < byte_limit / 4; i++)
+ fprintf(output, " 0x%08x,", get_dword(instruction, i));
+
+ break;
+ }
+ case OPT_OUTPUT_BIN:
+ fwrite(instruction, 1, byte_limit, output);
+ break;
+ }
+
+ if (output_type != OPT_OUTPUT_BIN) {
+ fprintf(output, "\n");
}
- fprintf(output, "\n");
}
static struct gen_device_info *
if (devinfo == NULL)
return NULL;
- if (!gen_get_device_info(pci_id, devinfo)) {
+ 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;
}
+static bool
+i965_postprocess_labels()
+{
+ if (p->devinfo->gen < 6) {
+ return true;
+ }
+
+ void *store = p->store;
+
+ struct target_label *tlabel;
+ struct instr_label *ilabel, *s;
+
+ const unsigned to_bytes_scale = brw_jump_scale(p->devinfo);
+
+ LIST_FOR_EACH_ENTRY(tlabel, &target_labels, link) {
+ LIST_FOR_EACH_ENTRY_SAFE(ilabel, s, &instr_labels, link) {
+ if (!strcmp(tlabel->name, ilabel->name)) {
+ brw_inst *inst = store + ilabel->offset;
+
+ int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst);
+ relative_offset *= to_bytes_scale;
+
+ unsigned opcode = brw_inst_opcode(p->devinfo, inst);
+
+ if (ilabel->type == INSTR_LABEL_JIP) {
+ switch (opcode) {
+ case BRW_OPCODE_IF:
+ case BRW_OPCODE_ELSE:
+ case BRW_OPCODE_ENDIF:
+ case BRW_OPCODE_WHILE:
+ if (p->devinfo->gen >= 7) {
+ brw_inst_set_jip(p->devinfo, inst, relative_offset);
+ } else if (p->devinfo->gen == 6) {
+ brw_inst_set_gen6_jump_count(p->devinfo, inst, relative_offset);
+ }
+ break;
+ case BRW_OPCODE_BREAK:
+ case BRW_OPCODE_HALT:
+ case BRW_OPCODE_CONTINUE:
+ brw_inst_set_jip(p->devinfo, inst, relative_offset);
+ break;
+ default:
+ fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode);
+ return false;
+ }
+ } else {
+ switch (opcode) {
+ case BRW_OPCODE_IF:
+ case BRW_OPCODE_ELSE:
+ if (p->devinfo->gen > 7) {
+ brw_inst_set_uip(p->devinfo, inst, relative_offset);
+ } else if (p->devinfo->gen == 7) {
+ brw_inst_set_uip(p->devinfo, inst, relative_offset);
+ } else if (p->devinfo->gen == 6) {
+ // Nothing
+ }
+ break;
+ case BRW_OPCODE_WHILE:
+ case BRW_OPCODE_ENDIF:
+ fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n");
+ return false;
+ case BRW_OPCODE_BREAK:
+ case BRW_OPCODE_CONTINUE:
+ case BRW_OPCODE_HALT:
+ brw_inst_set_uip(p->devinfo, inst, relative_offset);
+ break;
+ default:
+ fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode);
+ return false;
+ }
+ }
+
+ list_del(&ilabel->link);
+ }
+ }
+ }
+
+ LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) {
+ fprintf(stderr, "Unknown label '%s'\n", ilabel->name);
+ }
+
+ return list_is_empty(&instr_labels);
+}
+
int main(int argc, char **argv)
{
char *output_file = NULL;
int offset = 0, err;
int start_offset = 0;
struct disasm_info *disasm_info;
- struct gen_device_info *devinfo;
+ struct gen_device_info *devinfo = NULL;
int result = EXIT_FAILURE;
+ list_inithead(&instr_labels);
+ list_inithead(&target_labels);
const struct option i965_asm_opts[] = {
{ "help", no_argument, (int *) &help, true },
- { "c-literal", no_argument, NULL, 'c' },
+ { "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, ":g:o:lh", i965_asm_opts, NULL)) != -1) {
+ 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);
help = true;
print_help(argv[0], stderr);
goto end;
- case 'l':
- c_literal_output = 1;
+ 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;
if (err || errors)
goto end;
+ if (!i965_postprocess_labels())
+ goto end;
+
store = p->store;
disasm_info = disasm_initialize(p->devinfo, NULL);
goto end;
}
- if (c_literal_output)
- fprintf(output, "static const char gen_eu_bytes[] = {\n");
+ if (output_type == OPT_OUTPUT_C_LITERAL)
+ fprintf(output, "{\n");
brw_validate_instructions(p->devinfo, p->store, 0,
p->next_insn_offset, disasm_info);
ralloc_free(disasm_info);
- if (c_literal_output)
+ if (output_type == OPT_OUTPUT_C_LITERAL)
fprintf(output, "}");
result = EXIT_SUCCESS;