2 * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
25 struct bin_instruction {
27 unsigned int operands[3];
38 struct bin_instruction *bin;
40 const char *operands[5];
43 unsigned int labeladdr;
44 struct statement *labelref;
51 struct list_head list;
54 struct disassembler_context {
55 /* The architecture of the input file. */
58 struct bin_instruction *code;
61 struct list_head stmt_list;
67 const char *infile_name;
68 const char *outfile_name;
71 static const char * gen_raw_code(unsigned int operand)
76 snprintf(ret, 5, "@%03X", operand);
81 static const char * disasm_mem_operand(unsigned int operand)
86 snprintf(ret, 9, "[0x%X]", operand);
91 static const char * disasm_indirect_mem_operand(unsigned int operand)
96 snprintf(ret, 12, "[0x%02X,off%u]",
97 (operand & 0x3F), ((operand >> 6) & 0x7)); //FIXME r15?
102 static const char * disasm_imm_operand(unsigned int operand)
105 unsigned int signmask;
108 switch (cmdargs.arch) {
114 signmask = (1 << 10);
118 fprintf(stderr, "Internal error: disasm_imm_operand invalid arch\n");
125 if (operand & signmask)
126 operand = (operand | (~mask & 0xFFFF));
127 snprintf(ret, 7, "0x%X", operand);
132 static const char * disasm_spr_operand(unsigned int operand)
137 switch (cmdargs.arch) {
145 fprintf(stderr, "Internal error: disasm_spr_operand invalid arch\n");
150 snprintf(ret, 8, "spr%X", (operand & mask));
155 static const char * disasm_gpr_operand(unsigned int operand)
160 switch (cmdargs.arch) {
168 fprintf(stderr, "Internal error: disasm_gpr_operand invalid arch\n");
173 snprintf(ret, 5, "r%u", (operand & mask));
178 static void disasm_std_operand(struct statement *stmt,
183 unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
188 switch (cmdargs.arch) {
190 if (!(operand & 0x800)) {
191 stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
193 } else if ((operand & 0xC00) == 0xC00) {
194 stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
196 } else if ((operand & 0xFC0) == 0xBC0) {
197 stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
199 } else if ((operand & 0xE00) == 0x800) {
200 stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
202 } else if ((operand & 0xE00) == 0xA00) {
203 stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
208 if (!(operand & 0x1000)) {
209 stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
211 } else if ((operand & 0x1800) == 0x1800) {
212 stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
214 } else if ((operand & 0x1F80) == 0x1780) {
215 stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
217 } else if ((operand & 0x1C00) == 0x1000) {
218 stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
220 } else if ((operand & 0x1C00) == 0x1400) {
221 stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
226 fprintf(stderr, "Internal error: disasm_std_operand invalid arch\n");
230 stmt->u.insn.operands[out_idx] = gen_raw_code(operand);
233 static void disasm_opcode_raw(struct disassembler_context *ctx,
234 struct statement *stmt)
236 stmt->u.insn.name = gen_raw_code(stmt->u.insn.bin->opcode);
237 disasm_std_operand(stmt, 0, 0, 1);
238 disasm_std_operand(stmt, 1, 1, 1);
239 disasm_std_operand(stmt, 2, 2, 1);
242 static void disasm_constant_opcodes(struct disassembler_context *ctx,
243 struct statement *stmt)
245 struct bin_instruction *bin = stmt->u.insn.bin;
247 switch (bin->opcode) {
249 stmt->u.insn.name = "add";
250 disasm_std_operand(stmt, 0, 0, 0);
251 disasm_std_operand(stmt, 1, 1, 0);
252 disasm_std_operand(stmt, 2, 2, 0);
255 stmt->u.insn.name = "add.";
256 disasm_std_operand(stmt, 0, 0, 0);
257 disasm_std_operand(stmt, 1, 1, 0);
258 disasm_std_operand(stmt, 2, 2, 0);
261 stmt->u.insn.name = "addc";
262 disasm_std_operand(stmt, 0, 0, 0);
263 disasm_std_operand(stmt, 1, 1, 0);
264 disasm_std_operand(stmt, 2, 2, 0);
267 stmt->u.insn.name = "addc.";
268 disasm_std_operand(stmt, 0, 0, 0);
269 disasm_std_operand(stmt, 1, 1, 0);
270 disasm_std_operand(stmt, 2, 2, 0);
273 stmt->u.insn.name = "sub";
274 disasm_std_operand(stmt, 0, 0, 0);
275 disasm_std_operand(stmt, 1, 1, 0);
276 disasm_std_operand(stmt, 2, 2, 0);
279 stmt->u.insn.name = "sub.";
280 disasm_std_operand(stmt, 0, 0, 0);
281 disasm_std_operand(stmt, 1, 1, 0);
282 disasm_std_operand(stmt, 2, 2, 0);
285 stmt->u.insn.name = "subc";
286 disasm_std_operand(stmt, 0, 0, 0);
287 disasm_std_operand(stmt, 1, 1, 0);
288 disasm_std_operand(stmt, 2, 2, 0);
291 stmt->u.insn.name = "subc.";
292 disasm_std_operand(stmt, 0, 0, 0);
293 disasm_std_operand(stmt, 1, 1, 0);
294 disasm_std_operand(stmt, 2, 2, 0);
297 stmt->u.insn.name = "sra";
298 disasm_std_operand(stmt, 0, 0, 0);
299 disasm_std_operand(stmt, 1, 1, 0);
300 disasm_std_operand(stmt, 2, 2, 0);
303 stmt->u.insn.name = "or";
304 disasm_std_operand(stmt, 0, 0, 0);
305 disasm_std_operand(stmt, 1, 1, 0);
306 disasm_std_operand(stmt, 2, 2, 0);
309 stmt->u.insn.name = "and";
310 disasm_std_operand(stmt, 0, 0, 0);
311 disasm_std_operand(stmt, 1, 1, 0);
312 disasm_std_operand(stmt, 2, 2, 0);
315 stmt->u.insn.name = "xor";
316 disasm_std_operand(stmt, 0, 0, 0);
317 disasm_std_operand(stmt, 1, 1, 0);
318 disasm_std_operand(stmt, 2, 2, 0);
321 stmt->u.insn.name = "sr";
322 disasm_std_operand(stmt, 0, 0, 0);
323 disasm_std_operand(stmt, 1, 1, 0);
324 disasm_std_operand(stmt, 2, 2, 0);
327 stmt->u.insn.name = "sl";
328 disasm_std_operand(stmt, 0, 0, 0);
329 disasm_std_operand(stmt, 1, 1, 0);
330 disasm_std_operand(stmt, 2, 2, 0);
333 stmt->u.insn.name = "rl";
334 disasm_std_operand(stmt, 0, 0, 0);
335 disasm_std_operand(stmt, 1, 1, 0);
336 disasm_std_operand(stmt, 2, 2, 0);
339 stmt->u.insn.name = "rr";
340 disasm_std_operand(stmt, 0, 0, 0);
341 disasm_std_operand(stmt, 1, 1, 0);
342 disasm_std_operand(stmt, 2, 2, 0);
345 stmt->u.insn.name = "nand";
346 disasm_std_operand(stmt, 0, 0, 0);
347 disasm_std_operand(stmt, 1, 1, 0);
348 disasm_std_operand(stmt, 2, 2, 0);
351 stmt->u.insn.name = "jand";
352 stmt->u.insn.is_labelref = 2;
353 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
354 disasm_std_operand(stmt, 0, 0, 0);
355 disasm_std_operand(stmt, 1, 1, 0);
358 stmt->u.insn.name = "jnand";
359 stmt->u.insn.is_labelref = 2;
360 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
361 disasm_std_operand(stmt, 0, 0, 0);
362 disasm_std_operand(stmt, 1, 1, 0);
365 stmt->u.insn.name = "js";
366 stmt->u.insn.is_labelref = 2;
367 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
368 disasm_std_operand(stmt, 0, 0, 0);
369 disasm_std_operand(stmt, 1, 1, 0);
372 stmt->u.insn.name = "jns";
373 stmt->u.insn.is_labelref = 2;
374 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
375 disasm_std_operand(stmt, 0, 0, 0);
376 disasm_std_operand(stmt, 1, 1, 0);
379 stmt->u.insn.name = "je";
380 stmt->u.insn.is_labelref = 2;
381 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
382 disasm_std_operand(stmt, 0, 0, 0);
383 disasm_std_operand(stmt, 1, 1, 0);
386 stmt->u.insn.name = "jne";
387 stmt->u.insn.is_labelref = 2;
388 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
389 disasm_std_operand(stmt, 0, 0, 0);
390 disasm_std_operand(stmt, 1, 1, 0);
393 stmt->u.insn.name = "jls";
394 stmt->u.insn.is_labelref = 2;
395 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
396 disasm_std_operand(stmt, 0, 0, 0);
397 disasm_std_operand(stmt, 1, 1, 0);
400 stmt->u.insn.name = "jges";
401 stmt->u.insn.is_labelref = 2;
402 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
403 disasm_std_operand(stmt, 0, 0, 0);
404 disasm_std_operand(stmt, 1, 1, 0);
407 stmt->u.insn.name = "jgs";
408 stmt->u.insn.is_labelref = 2;
409 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
410 disasm_std_operand(stmt, 0, 0, 0);
411 disasm_std_operand(stmt, 1, 1, 0);
414 stmt->u.insn.name = "jles";
415 stmt->u.insn.is_labelref = 2;
416 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
417 disasm_std_operand(stmt, 0, 0, 0);
418 disasm_std_operand(stmt, 1, 1, 0);
421 stmt->u.insn.name = "jl";
422 stmt->u.insn.is_labelref = 2;
423 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
424 disasm_std_operand(stmt, 0, 0, 0);
425 disasm_std_operand(stmt, 1, 1, 0);
428 stmt->u.insn.name = "jge";
429 stmt->u.insn.is_labelref = 2;
430 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
431 disasm_std_operand(stmt, 0, 0, 0);
432 disasm_std_operand(stmt, 1, 1, 0);
435 stmt->u.insn.name = "jg";
436 stmt->u.insn.is_labelref = 2;
437 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
438 disasm_std_operand(stmt, 0, 0, 0);
439 disasm_std_operand(stmt, 1, 1, 0);
442 stmt->u.insn.name = "jle";
443 stmt->u.insn.is_labelref = 2;
444 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
445 disasm_std_operand(stmt, 0, 0, 0);
446 disasm_std_operand(stmt, 1, 1, 0);
451 switch (cmdargs.arch) {
453 stmt->u.insn.name = "call";
454 stmt->u.insn.is_labelref = 1;
455 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
457 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
458 stmt->u.insn.operands[0] = str;
461 //FIXME: This opcode is different on r15. Decode raw for now.
462 disasm_opcode_raw(ctx, stmt);
470 stmt->u.insn.name = "ret";
472 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
473 stmt->u.insn.operands[0] = str;
475 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[2]);
476 stmt->u.insn.operands[2] = str;
480 unsigned int flags, mask;
482 switch (cmdargs.arch) {
490 fprintf(stderr, "Internal error: TKIP invalid arch\n");
494 flags = stmt->u.insn.bin->operands[1];
495 switch (flags & mask) {
497 stmt->u.insn.name = "tkiph";
500 stmt->u.insn.name = "tkiphs";
503 stmt->u.insn.name = "tkipl";
506 stmt->u.insn.name = "tkipls";
509 fprintf(stderr, "Invalid TKIP flags %X\n",
513 disasm_std_operand(stmt, 0, 0, 0);
514 disasm_std_operand(stmt, 2, 2, 0);
520 stmt->u.insn.name = "nap";
521 switch (cmdargs.arch) {
529 fprintf(stderr, "Internal error: NAP invalid arch\n");
532 if (stmt->u.insn.bin->operands[0] != mask) {
533 fprintf(stderr, "NAP: invalid first argument 0x%04X\n",
534 stmt->u.insn.bin->operands[0]);
536 if (stmt->u.insn.bin->operands[1] != mask) {
537 fprintf(stderr, "NAP: invalid second argument 0x%04X\n",
538 stmt->u.insn.bin->operands[1]);
540 if (stmt->u.insn.bin->operands[2] != 0) {
541 fprintf(stderr, "NAP: invalid third argument 0x%04X\n",
542 stmt->u.insn.bin->operands[2]);
547 disasm_opcode_raw(ctx, stmt);
552 static void disasm_opcodes(struct disassembler_context *ctx)
554 struct bin_instruction *bin;
556 struct statement *stmt;
559 for (i = 0; i < ctx->nr_insns; i++) {
560 bin = &(ctx->code[i]);
562 stmt = xmalloc(sizeof(struct statement));
563 stmt->type = STMT_INSN;
564 INIT_LIST_HEAD(&stmt->list);
565 stmt->u.insn.bin = bin;
566 stmt->u.insn.is_labelref = -1;
568 switch (bin->opcode & 0xF00) {
570 stmt->u.insn.name = "srx";
573 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
574 stmt->u.insn.operands[0] = str;
576 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
577 stmt->u.insn.operands[1] = str;
579 disasm_std_operand(stmt, 0, 2, 0);
580 disasm_std_operand(stmt, 1, 3, 0);
581 disasm_std_operand(stmt, 2, 4, 0);
584 stmt->u.insn.name = "orx";
587 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
588 stmt->u.insn.operands[0] = str;
590 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
591 stmt->u.insn.operands[1] = str;
593 disasm_std_operand(stmt, 0, 2, 0);
594 disasm_std_operand(stmt, 1, 3, 0);
595 disasm_std_operand(stmt, 2, 4, 0);
598 stmt->u.insn.name = "jzx";
601 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
602 stmt->u.insn.operands[0] = str;
604 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
605 stmt->u.insn.operands[1] = str;
607 disasm_std_operand(stmt, 0, 2, 0);
608 disasm_std_operand(stmt, 1, 3, 0);
609 stmt->u.insn.is_labelref = 4;
610 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
613 stmt->u.insn.name = "jnzx";
616 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
617 stmt->u.insn.operands[0] = str;
619 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
620 stmt->u.insn.operands[1] = str;
622 disasm_std_operand(stmt, 0, 2, 0);
623 disasm_std_operand(stmt, 1, 3, 0);
624 stmt->u.insn.is_labelref = 4;
625 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
628 stmt->u.insn.name = "jnext";
631 snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
632 stmt->u.insn.operands[0] = str;
634 /* We don't disassemble the first and second operand, as
635 * that always is a dummy r0 operand.
636 * disasm_std_operand(stmt, 0, 1, 0);
637 * disasm_std_operand(stmt, 1, 2, 0);
638 * stmt->u.insn.is_labelref = 3;
640 stmt->u.insn.is_labelref = 1;
641 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
644 stmt->u.insn.name = "jext";
647 snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
648 stmt->u.insn.operands[0] = str;
650 /* We don't disassemble the first and second operand, as
651 * that always is a dummy r0 operand.
652 * disasm_std_operand(stmt, 0, 1, 0);
653 * disasm_std_operand(stmt, 1, 2, 0);
654 * stmt->u.insn.is_labelref = 3;
656 stmt->u.insn.is_labelref = 1;
657 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
660 disasm_constant_opcodes(ctx, stmt);
664 list_add_tail(&stmt->list, &ctx->stmt_list);
668 static struct statement * get_label_at(struct disassembler_context *ctx,
671 unsigned int addrcnt = 0;
672 struct statement *stmt, *ret, *prev;
674 list_for_each_entry(stmt, &ctx->stmt_list, list) {
675 if (stmt->type != STMT_INSN)
677 if (addrcnt == addr) {
678 prev = list_entry(stmt->list.prev, struct statement, list);
679 if (prev->type == STMT_LABEL)
681 ret = xmalloc(sizeof(struct statement));
682 INIT_LIST_HEAD(&ret->list);
683 ret->type = STMT_LABEL;
684 list_add(&ret->list, &prev->list);
694 static void resolve_labels(struct disassembler_context *ctx)
696 struct statement *stmt;
697 struct statement *label;
699 unsigned int labeladdr;
700 unsigned int namecnt = 0;
702 /* Resolve label references */
703 list_for_each_entry_safe(stmt, n, &ctx->stmt_list, list) {
704 if (stmt->type != STMT_INSN)
706 if (stmt->u.insn.is_labelref == -1)
708 labeladdr = stmt->u.insn.labeladdr;
709 label = get_label_at(ctx, labeladdr);
711 fprintf(stderr, "Labeladdress %X out of bounds\n",
715 stmt->u.insn.labelref = label;
718 /* Name the labels */
719 list_for_each_entry(stmt, &ctx->stmt_list, list) {
720 if (stmt->type != STMT_LABEL)
722 stmt->u.label.name = xmalloc(20);
723 snprintf(stmt->u.label.name, 20, "L%u", namecnt);
728 static void emit_asm(struct disassembler_context *ctx)
730 struct statement *stmt;
733 unsigned int addr = 0;
735 err = open_output_file();
739 fprintf(outfile, "%%arch %u\n\n", ctx->arch);
740 list_for_each_entry(stmt, &ctx->stmt_list, list) {
741 switch (stmt->type) {
743 if (cmdargs.print_addresses)
744 fprintf(outfile, "/* %03X */", addr);
745 fprintf(outfile, "\t%s", stmt->u.insn.name);
747 for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) {
748 if (stmt->u.insn.is_labelref == i) {
749 fprintf(outfile, ", %s",
750 stmt->u.insn.labelref->u.label.name);
752 if (!stmt->u.insn.operands[i])
755 fprintf(outfile, "\t");
757 fprintf(outfile, ", ");
759 fprintf(outfile, "%s",
760 stmt->u.insn.operands[i]);
762 fprintf(outfile, "\n");
766 fprintf(outfile, "%s:\n", stmt->u.label.name);
774 static int read_input(struct disassembler_context *ctx)
776 size_t size = 0, pos = 0;
778 struct bin_instruction *code = NULL;
779 unsigned char tmp[sizeof(uint64_t)];
781 struct fw_header hdr;
784 err = open_input_file();
788 switch (cmdargs.informat) {
794 ret = fread(&hdr, 1, sizeof(hdr), infile);
795 if (ret != sizeof(hdr)) {
796 fprintf(stderr, "Corrupt input file (not fwcutter output)\n");
799 if (hdr.type != FW_TYPE_UCODE) {
800 fprintf(stderr, "Corrupt input file. Not a microcode image.\n");
803 if (hdr.ver != FW_HDR_VER) {
804 fprintf(stderr, "Invalid input file header version.\n");
813 code = xrealloc(code, size * sizeof(struct bin_instruction));
815 ret = fread(tmp, 1, sizeof(uint64_t), infile);
818 if (ret != sizeof(uint64_t)) {
819 fprintf(stderr, "Corrupt input file (not 8 byte aligned)\n");
823 switch (cmdargs.informat) {
827 codeword |= ((uint64_t)tmp[0]) << 56;
828 codeword |= ((uint64_t)tmp[1]) << 48;
829 codeword |= ((uint64_t)tmp[2]) << 40;
830 codeword |= ((uint64_t)tmp[3]) << 32;
831 codeword |= ((uint64_t)tmp[4]) << 24;
832 codeword |= ((uint64_t)tmp[5]) << 16;
833 codeword |= ((uint64_t)tmp[6]) << 8;
834 codeword |= ((uint64_t)tmp[7]);
835 codeword = ((codeword & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
836 ((codeword & (uint64_t)0x00000000FFFFFFFFULL) << 32);
840 codeword |= ((uint64_t)tmp[7]) << 56;
841 codeword |= ((uint64_t)tmp[6]) << 48;
842 codeword |= ((uint64_t)tmp[5]) << 40;
843 codeword |= ((uint64_t)tmp[4]) << 32;
844 codeword |= ((uint64_t)tmp[3]) << 24;
845 codeword |= ((uint64_t)tmp[2]) << 16;
846 codeword |= ((uint64_t)tmp[1]) << 8;
847 codeword |= ((uint64_t)tmp[0]);
851 switch (cmdargs.arch) {
853 if (codeword >> 48) {
854 fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
855 "Wrong input format or architecture?\n", (unsigned int)pos);
858 code[pos].opcode = (codeword >> 36) & 0xFFF;
859 code[pos].operands[2] = codeword & 0xFFF;
860 code[pos].operands[1] = (codeword >> 12) & 0xFFF;
861 code[pos].operands[0] = (codeword >> 24) & 0xFFF;
864 if (codeword >> 51) {
865 fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
866 "Wrong input format or architecture?\n", (unsigned int)pos);
869 code[pos].opcode = (codeword >> 39) & 0xFFF;
870 code[pos].operands[2] = codeword & 0x1FFF;
871 code[pos].operands[1] = (codeword >> 13) & 0x1FFF;
872 code[pos].operands[0] = (codeword >> 26) & 0x1FFF;
875 fprintf(stderr, "Internal error: read_input unknown arch %u\n",
898 static void disassemble(void)
900 struct disassembler_context ctx;
903 memset(&ctx, 0, sizeof(ctx));
904 INIT_LIST_HEAD(&ctx.stmt_list);
905 ctx.arch = cmdargs.arch;
907 err = read_input(&ctx);
910 disasm_opcodes(&ctx);
911 resolve_labels(&ctx);
915 int main(int argc, char **argv)
919 err = parse_args(argc, argv);
929 /* Lazyman simply leaks all allocated memory. */