2 * Copyright (C) 2006-2010 Michael Buesch <m@bues.ch>
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 #define _msg_helper(type, msg, x...) do { \
72 fprintf(stderr, "Disassembler " type \
73 ":\n " msg "\n" ,##x); \
76 #define dasm_error(msg, x...) do { \
77 _msg_helper("ERROR", msg ,##x); \
81 #define dasm_int_error(msg, x...) \
82 dasm_error("Internal error (bug): " msg ,##x)
84 #define dasm_warn(msg, x...) \
85 _msg_helper("warning", msg ,##x)
87 #define asm_info(msg, x...) \
88 _msg_helper("info", msg ,##x)
90 static const char * gen_raw_code(unsigned int operand)
95 snprintf(ret, 6, "@%X", operand);
100 static const char * disasm_mem_operand(unsigned int operand)
105 snprintf(ret, 9, "[0x%X]", operand);
110 static const char * disasm_indirect_mem_operand(unsigned int operand)
113 unsigned int offset, reg;
115 switch (cmdargs.arch) {
117 offset = (operand & 0x3F);
118 reg = ((operand >> 6) & 0x7);
121 offset = (operand & 0x7F);
122 reg = ((operand >> 7) & 0x7);
125 dasm_int_error("disasm_indirect_mem_operand invalid arch");
128 snprintf(ret, 12, "[0x%02X,off%u]", offset, reg);
133 static const char * disasm_imm_operand(unsigned int operand)
136 unsigned int signmask;
139 switch (cmdargs.arch) {
145 signmask = (1 << 10);
149 dasm_int_error("disasm_imm_operand invalid arch");
155 if (operand & signmask)
156 operand = (operand | (~mask & 0xFFFF));
157 snprintf(ret, 7, "0x%X", operand);
162 static const char * disasm_spr_operand(unsigned int operand)
167 switch (cmdargs.arch) {
175 dasm_int_error("disasm_spr_operand invalid arch");
179 snprintf(ret, 8, "spr%X", (operand & mask));
184 static const char * disasm_gpr_operand(unsigned int operand)
189 switch (cmdargs.arch) {
197 dasm_int_error("disasm_gpr_operand invalid arch");
201 snprintf(ret, 5, "r%u", (operand & mask));
206 static void disasm_raw_operand(struct statement *stmt,
210 unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
212 stmt->u.insn.operands[out_idx] = gen_raw_code(operand);
215 static void disasm_std_operand(struct statement *stmt,
219 unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
221 switch (cmdargs.arch) {
223 if (!(operand & 0x800)) {
224 stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
226 } else if ((operand & 0xC00) == 0xC00) {
227 stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
229 } else if ((operand & 0xFC0) == 0xBC0) {
230 stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
232 } else if ((operand & 0xE00) == 0x800) {
233 stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
235 } else if ((operand & 0xE00) == 0xA00) {
236 stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
241 if (!(operand & 0x1000)) {
242 stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
244 } else if ((operand & 0x1800) == 0x1800) {
245 stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
247 } else if ((operand & 0x1F80) == 0x1780) {
248 stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
250 } else if ((operand & 0x1C00) == 0x1000) {
251 stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
253 } else if ((operand & 0x1C00) == 0x1400) {
254 stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
259 dasm_int_error("disasm_std_operand invalid arch");
261 /* No luck. Disassemble to raw operand. */
262 disasm_raw_operand(stmt, oper_idx, out_idx);
265 static void disasm_opcode_raw(struct disassembler_context *ctx,
266 struct statement *stmt,
269 stmt->u.insn.name = gen_raw_code(stmt->u.insn.bin->opcode);
271 disasm_raw_operand(stmt, 0, 0);
272 disasm_raw_operand(stmt, 1, 1);
273 disasm_raw_operand(stmt, 2, 2);
275 disasm_std_operand(stmt, 0, 0);
276 disasm_std_operand(stmt, 1, 1);
277 disasm_std_operand(stmt, 2, 2);
281 static void disasm_constant_opcodes(struct disassembler_context *ctx,
282 struct statement *stmt)
284 struct bin_instruction *bin = stmt->u.insn.bin;
286 switch (bin->opcode) {
288 stmt->u.insn.name = "mul";
289 disasm_std_operand(stmt, 0, 0);
290 disasm_std_operand(stmt, 1, 1);
291 disasm_std_operand(stmt, 2, 2);
294 stmt->u.insn.name = "add";
295 disasm_std_operand(stmt, 0, 0);
296 disasm_std_operand(stmt, 1, 1);
297 disasm_std_operand(stmt, 2, 2);
300 stmt->u.insn.name = "add.";
301 disasm_std_operand(stmt, 0, 0);
302 disasm_std_operand(stmt, 1, 1);
303 disasm_std_operand(stmt, 2, 2);
306 stmt->u.insn.name = "addc";
307 disasm_std_operand(stmt, 0, 0);
308 disasm_std_operand(stmt, 1, 1);
309 disasm_std_operand(stmt, 2, 2);
312 stmt->u.insn.name = "addc.";
313 disasm_std_operand(stmt, 0, 0);
314 disasm_std_operand(stmt, 1, 1);
315 disasm_std_operand(stmt, 2, 2);
318 stmt->u.insn.name = "sub";
319 disasm_std_operand(stmt, 0, 0);
320 disasm_std_operand(stmt, 1, 1);
321 disasm_std_operand(stmt, 2, 2);
324 stmt->u.insn.name = "sub.";
325 disasm_std_operand(stmt, 0, 0);
326 disasm_std_operand(stmt, 1, 1);
327 disasm_std_operand(stmt, 2, 2);
330 stmt->u.insn.name = "subc";
331 disasm_std_operand(stmt, 0, 0);
332 disasm_std_operand(stmt, 1, 1);
333 disasm_std_operand(stmt, 2, 2);
336 stmt->u.insn.name = "subc.";
337 disasm_std_operand(stmt, 0, 0);
338 disasm_std_operand(stmt, 1, 1);
339 disasm_std_operand(stmt, 2, 2);
342 stmt->u.insn.name = "sra";
343 disasm_std_operand(stmt, 0, 0);
344 disasm_std_operand(stmt, 1, 1);
345 disasm_std_operand(stmt, 2, 2);
348 stmt->u.insn.name = "or";
349 disasm_std_operand(stmt, 0, 0);
350 disasm_std_operand(stmt, 1, 1);
351 disasm_std_operand(stmt, 2, 2);
354 stmt->u.insn.name = "and";
355 disasm_std_operand(stmt, 0, 0);
356 disasm_std_operand(stmt, 1, 1);
357 disasm_std_operand(stmt, 2, 2);
360 stmt->u.insn.name = "xor";
361 disasm_std_operand(stmt, 0, 0);
362 disasm_std_operand(stmt, 1, 1);
363 disasm_std_operand(stmt, 2, 2);
366 stmt->u.insn.name = "sr";
367 disasm_std_operand(stmt, 0, 0);
368 disasm_std_operand(stmt, 1, 1);
369 disasm_std_operand(stmt, 2, 2);
372 stmt->u.insn.name = "sl";
373 disasm_std_operand(stmt, 0, 0);
374 disasm_std_operand(stmt, 1, 1);
375 disasm_std_operand(stmt, 2, 2);
378 stmt->u.insn.name = "rl";
379 disasm_std_operand(stmt, 0, 0);
380 disasm_std_operand(stmt, 1, 1);
381 disasm_std_operand(stmt, 2, 2);
384 stmt->u.insn.name = "rr";
385 disasm_std_operand(stmt, 0, 0);
386 disasm_std_operand(stmt, 1, 1);
387 disasm_std_operand(stmt, 2, 2);
390 stmt->u.insn.name = "nand";
391 disasm_std_operand(stmt, 0, 0);
392 disasm_std_operand(stmt, 1, 1);
393 disasm_std_operand(stmt, 2, 2);
396 stmt->u.insn.name = "jand";
397 stmt->u.insn.labelref_operand = 2;
398 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
399 disasm_std_operand(stmt, 0, 0);
400 disasm_std_operand(stmt, 1, 1);
403 stmt->u.insn.name = "jnand";
404 stmt->u.insn.labelref_operand = 2;
405 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
406 disasm_std_operand(stmt, 0, 0);
407 disasm_std_operand(stmt, 1, 1);
410 stmt->u.insn.name = "js";
411 stmt->u.insn.labelref_operand = 2;
412 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
413 disasm_std_operand(stmt, 0, 0);
414 disasm_std_operand(stmt, 1, 1);
417 stmt->u.insn.name = "jns";
418 stmt->u.insn.labelref_operand = 2;
419 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
420 disasm_std_operand(stmt, 0, 0);
421 disasm_std_operand(stmt, 1, 1);
424 stmt->u.insn.name = "je";
425 stmt->u.insn.labelref_operand = 2;
426 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
427 disasm_std_operand(stmt, 0, 0);
428 disasm_std_operand(stmt, 1, 1);
431 stmt->u.insn.name = "jne";
432 stmt->u.insn.labelref_operand = 2;
433 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
434 disasm_std_operand(stmt, 0, 0);
435 disasm_std_operand(stmt, 1, 1);
438 stmt->u.insn.name = "jls";
439 stmt->u.insn.labelref_operand = 2;
440 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
441 disasm_std_operand(stmt, 0, 0);
442 disasm_std_operand(stmt, 1, 1);
445 stmt->u.insn.name = "jges";
446 stmt->u.insn.labelref_operand = 2;
447 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
448 disasm_std_operand(stmt, 0, 0);
449 disasm_std_operand(stmt, 1, 1);
452 stmt->u.insn.name = "jgs";
453 stmt->u.insn.labelref_operand = 2;
454 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
455 disasm_std_operand(stmt, 0, 0);
456 disasm_std_operand(stmt, 1, 1);
459 stmt->u.insn.name = "jles";
460 stmt->u.insn.labelref_operand = 2;
461 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
462 disasm_std_operand(stmt, 0, 0);
463 disasm_std_operand(stmt, 1, 1);
466 stmt->u.insn.name = "jdn";
467 stmt->u.insn.labelref_operand = 2;
468 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
469 disasm_std_operand(stmt, 0, 0);
470 disasm_std_operand(stmt, 1, 1);
473 stmt->u.insn.name = "jdpz";
474 stmt->u.insn.labelref_operand = 2;
475 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
476 disasm_std_operand(stmt, 0, 0);
477 disasm_std_operand(stmt, 1, 1);
480 stmt->u.insn.name = "jdp";
481 stmt->u.insn.labelref_operand = 2;
482 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
483 disasm_std_operand(stmt, 0, 0);
484 disasm_std_operand(stmt, 1, 1);
487 stmt->u.insn.name = "jdnz";
488 stmt->u.insn.labelref_operand = 2;
489 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
490 disasm_std_operand(stmt, 0, 0);
491 disasm_std_operand(stmt, 1, 1);
494 stmt->u.insn.name = "jl";
495 stmt->u.insn.labelref_operand = 2;
496 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
497 disasm_std_operand(stmt, 0, 0);
498 disasm_std_operand(stmt, 1, 1);
501 stmt->u.insn.name = "jge";
502 stmt->u.insn.labelref_operand = 2;
503 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
504 disasm_std_operand(stmt, 0, 0);
505 disasm_std_operand(stmt, 1, 1);
508 stmt->u.insn.name = "jg";
509 stmt->u.insn.labelref_operand = 2;
510 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
511 disasm_std_operand(stmt, 0, 0);
512 disasm_std_operand(stmt, 1, 1);
515 stmt->u.insn.name = "jle";
516 stmt->u.insn.labelref_operand = 2;
517 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
518 disasm_std_operand(stmt, 0, 0);
519 disasm_std_operand(stmt, 1, 1);
524 switch (cmdargs.arch) {
526 stmt->u.insn.name = "call";
527 stmt->u.insn.labelref_operand = 1;
528 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
530 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
531 stmt->u.insn.operands[0] = str;
534 //FIXME: This opcode is different on r15. Decode raw for now.
535 disasm_opcode_raw(ctx, stmt, 1);
543 stmt->u.insn.name = "ret";
545 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
546 stmt->u.insn.operands[0] = str;
548 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[2]);
549 stmt->u.insn.operands[2] = str;
553 if (cmdargs.arch != 15) {
554 dasm_error("arch 15 'calls' instruction found in arch %d binary",
557 stmt->u.insn.name = "calls";
558 stmt->u.insn.labelref_operand = 0;
559 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
560 if (stmt->u.insn.bin->operands[0] != 0x1780 ||
561 stmt->u.insn.bin->operands[1] != 0x1780)
562 dasm_warn("r15 calls: Invalid first or second argument");
566 if (cmdargs.arch != 15) {
567 dasm_error("arch 15 'rets' instruction found in arch %d binary",
570 stmt->u.insn.name = "rets";
571 if (stmt->u.insn.bin->operands[0] != 0x1780 ||
572 stmt->u.insn.bin->operands[1] != 0x1780 ||
573 stmt->u.insn.bin->operands[2] != 0)
574 dasm_warn("r15 rets: Invalid argument(s)");
578 unsigned int flags, mask;
580 switch (cmdargs.arch) {
588 dasm_int_error("TKIP invalid arch");
591 flags = stmt->u.insn.bin->operands[1];
592 switch (flags & mask) {
594 stmt->u.insn.name = "tkiph";
597 stmt->u.insn.name = "tkiphs";
600 stmt->u.insn.name = "tkipl";
603 stmt->u.insn.name = "tkipls";
606 dasm_error("Invalid TKIP flags %X", flags);
608 disasm_std_operand(stmt, 0, 0);
609 disasm_std_operand(stmt, 2, 2);
615 stmt->u.insn.name = "nap";
616 switch (cmdargs.arch) {
624 dasm_int_error("NAP invalid arch");
626 if (stmt->u.insn.bin->operands[0] != mask) {
627 dasm_warn("NAP: invalid first argument 0x%04X\n",
628 stmt->u.insn.bin->operands[0]);
630 if (stmt->u.insn.bin->operands[1] != mask) {
631 dasm_warn("NAP: invalid second argument 0x%04X\n",
632 stmt->u.insn.bin->operands[1]);
634 if (stmt->u.insn.bin->operands[2] != 0) {
635 dasm_warn("NAP: invalid third argument 0x%04X\n",
636 stmt->u.insn.bin->operands[2]);
641 disasm_opcode_raw(ctx, stmt, 1);
644 disasm_opcode_raw(ctx, stmt, (cmdargs.unknown_decode == 0));
649 static void disasm_opcodes(struct disassembler_context *ctx)
651 struct bin_instruction *bin;
653 struct statement *stmt;
656 for (i = 0; i < ctx->nr_insns; i++) {
657 bin = &(ctx->code[i]);
659 stmt = xmalloc(sizeof(struct statement));
660 stmt->type = STMT_INSN;
661 INIT_LIST_HEAD(&stmt->list);
662 stmt->u.insn.bin = bin;
663 stmt->u.insn.labelref_operand = -1; /* none */
665 switch (bin->opcode & 0xF00) {
667 stmt->u.insn.name = "srx";
670 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
671 stmt->u.insn.operands[0] = str;
673 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
674 stmt->u.insn.operands[1] = str;
676 disasm_std_operand(stmt, 0, 2);
677 disasm_std_operand(stmt, 1, 3);
678 disasm_std_operand(stmt, 2, 4);
681 stmt->u.insn.name = "orx";
684 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
685 stmt->u.insn.operands[0] = str;
687 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
688 stmt->u.insn.operands[1] = str;
690 disasm_std_operand(stmt, 0, 2);
691 disasm_std_operand(stmt, 1, 3);
692 disasm_std_operand(stmt, 2, 4);
695 stmt->u.insn.name = "jzx";
698 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
699 stmt->u.insn.operands[0] = str;
701 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
702 stmt->u.insn.operands[1] = str;
704 disasm_std_operand(stmt, 0, 2);
705 disasm_std_operand(stmt, 1, 3);
706 stmt->u.insn.labelref_operand = 4;
707 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
710 stmt->u.insn.name = "jnzx";
713 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
714 stmt->u.insn.operands[0] = str;
716 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
717 stmt->u.insn.operands[1] = str;
719 disasm_std_operand(stmt, 0, 2);
720 disasm_std_operand(stmt, 1, 3);
721 stmt->u.insn.labelref_operand = 4;
722 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
725 stmt->u.insn.name = "jnext";
728 snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
729 stmt->u.insn.operands[0] = str;
731 /* We don't disassemble the first and second operand, as
732 * that always is a dummy r0 operand.
733 * disasm_std_operand(stmt, 0, 1);
734 * disasm_std_operand(stmt, 1, 2);
735 * stmt->u.insn.labelref_operand = 3;
737 stmt->u.insn.labelref_operand = 1;
738 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
741 stmt->u.insn.name = "jext";
744 snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
745 stmt->u.insn.operands[0] = str;
747 /* We don't disassemble the first and second operand, as
748 * that always is a dummy r0 operand.
749 * disasm_std_operand(stmt, 0, 1);
750 * disasm_std_operand(stmt, 1, 2);
751 * stmt->u.insn.labelref_operand = 3;
753 stmt->u.insn.labelref_operand = 1;
754 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
757 disasm_constant_opcodes(ctx, stmt);
761 list_add_tail(&stmt->list, &ctx->stmt_list);
765 static struct statement * get_label_at(struct disassembler_context *ctx,
768 unsigned int addrcnt = 0;
769 struct statement *stmt, *ret, *prev;
771 list_for_each_entry(stmt, &ctx->stmt_list, list) {
772 if (stmt->type != STMT_INSN)
774 if (addrcnt == addr) {
775 prev = list_entry(stmt->list.prev, struct statement, list);
776 if (prev->type == STMT_LABEL)
778 ret = xmalloc(sizeof(struct statement));
779 INIT_LIST_HEAD(&ret->list);
780 ret->type = STMT_LABEL;
781 list_add(&ret->list, &prev->list);
791 static void resolve_labels(struct disassembler_context *ctx)
793 struct statement *stmt;
794 struct statement *label;
796 unsigned int labeladdr;
797 unsigned int namecnt = 0;
799 /* Resolve label references */
800 list_for_each_entry_safe(stmt, n, &ctx->stmt_list, list) {
801 if (stmt->type != STMT_INSN)
803 if (stmt->u.insn.labelref_operand < 0)
804 continue; /* Doesn't have label reference operand. */
805 labeladdr = stmt->u.insn.labeladdr;
806 label = get_label_at(ctx, labeladdr);
808 dasm_error("Labeladdress %X out of bounds", labeladdr);
809 stmt->u.insn.labelref = label;
812 /* Name the labels */
813 list_for_each_entry(stmt, &ctx->stmt_list, list) {
814 if (stmt->type != STMT_LABEL)
816 stmt->u.label.name = xmalloc(20);
817 snprintf(stmt->u.label.name, 20, "L%u", namecnt);
822 static void emit_asm(struct disassembler_context *ctx)
824 struct statement *stmt;
827 unsigned int i, addr = 0;
829 err = open_output_file();
833 fprintf(outfile, "%%arch %u\n", ctx->arch);
834 fprintf(outfile, "%%start entry\n\n");
835 fprintf(outfile, "entry:\n");
836 list_for_each_entry(stmt, &ctx->stmt_list, list) {
837 switch (stmt->type) {
839 if (cmdargs.print_addresses)
840 fprintf(outfile, "/* %04X */", addr);
841 fprintf(outfile, "\t%s", stmt->u.insn.name);
843 for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) {
844 if (!stmt->u.insn.operands[i] &&
845 (stmt->u.insn.labelref_operand < 0 ||
846 (unsigned int)stmt->u.insn.labelref_operand != i))
849 fprintf(outfile, "\t");
851 fprintf(outfile, ", ");
853 if (stmt->u.insn.labelref_operand >= 0 &&
854 (unsigned int)stmt->u.insn.labelref_operand == i) {
855 fprintf(outfile, "%s",
856 stmt->u.insn.labelref->u.label.name);
858 fprintf(outfile, "%s",
859 stmt->u.insn.operands[i]);
862 fprintf(outfile, "\n");
866 fprintf(outfile, "%s:\n", stmt->u.label.name);
874 static int read_input(struct disassembler_context *ctx)
876 size_t size = 0, pos = 0;
878 struct bin_instruction *code = NULL;
879 unsigned char tmp[sizeof(uint64_t)];
880 uint64_t codeword = 0;
881 struct fw_header hdr;
884 err = open_input_file();
888 switch (cmdargs.informat) {
894 ret = fread(&hdr, 1, sizeof(hdr), infile);
895 if (ret != sizeof(hdr)) {
896 fprintf(stderr, "Corrupt input file (no b43 header found)\n");
899 if (hdr.type != FW_TYPE_UCODE) {
900 fprintf(stderr, "Corrupt input file. Not a b43 microcode image.\n");
903 if (hdr.ver != FW_HDR_VER) {
904 fprintf(stderr, "Invalid input file header version.\n");
913 code = xrealloc(code, size * sizeof(struct bin_instruction));
915 ret = fread(tmp, 1, sizeof(uint64_t), infile);
918 if (ret != sizeof(uint64_t)) {
919 fprintf(stderr, "Corrupt input file (not 8 byte aligned)\n");
923 switch (cmdargs.informat) {
927 codeword |= ((uint64_t)tmp[0]) << 56;
928 codeword |= ((uint64_t)tmp[1]) << 48;
929 codeword |= ((uint64_t)tmp[2]) << 40;
930 codeword |= ((uint64_t)tmp[3]) << 32;
931 codeword |= ((uint64_t)tmp[4]) << 24;
932 codeword |= ((uint64_t)tmp[5]) << 16;
933 codeword |= ((uint64_t)tmp[6]) << 8;
934 codeword |= ((uint64_t)tmp[7]);
935 codeword = ((codeword & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
936 ((codeword & (uint64_t)0x00000000FFFFFFFFULL) << 32);
940 codeword |= ((uint64_t)tmp[7]) << 56;
941 codeword |= ((uint64_t)tmp[6]) << 48;
942 codeword |= ((uint64_t)tmp[5]) << 40;
943 codeword |= ((uint64_t)tmp[4]) << 32;
944 codeword |= ((uint64_t)tmp[3]) << 24;
945 codeword |= ((uint64_t)tmp[2]) << 16;
946 codeword |= ((uint64_t)tmp[1]) << 8;
947 codeword |= ((uint64_t)tmp[0]);
951 switch (cmdargs.arch) {
953 if (codeword >> 48) {
954 fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
955 "Wrong input format or architecture?\n", (unsigned int)pos);
958 code[pos].opcode = (codeword >> 36) & 0xFFF;
959 code[pos].operands[2] = codeword & 0xFFF;
960 code[pos].operands[1] = (codeword >> 12) & 0xFFF;
961 code[pos].operands[0] = (codeword >> 24) & 0xFFF;
964 if (codeword >> 51) {
965 fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
966 "Wrong input format or architecture?\n", (unsigned int)pos);
969 code[pos].opcode = (codeword >> 39) & 0xFFF;
970 code[pos].operands[2] = codeword & 0x1FFF;
971 code[pos].operands[1] = (codeword >> 13) & 0x1FFF;
972 code[pos].operands[0] = (codeword >> 26) & 0x1FFF;
975 fprintf(stderr, "Internal error: read_input unknown arch %u\n",
998 static void disassemble(void)
1000 struct disassembler_context ctx;
1003 memset(&ctx, 0, sizeof(ctx));
1004 INIT_LIST_HEAD(&ctx.stmt_list);
1005 ctx.arch = cmdargs.arch;
1007 err = read_input(&ctx);
1010 disasm_opcodes(&ctx);
1011 resolve_labels(&ctx);
1015 int main(int argc, char **argv)
1019 err = parse_args(argc, argv);
1029 /* Lazyman simply leaks all allocated memory. */