2 * Copyright (C) 2006-2010 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 #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_std_operand(struct statement *stmt,
211 unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
216 switch (cmdargs.arch) {
218 if (!(operand & 0x800)) {
219 stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
221 } else if ((operand & 0xC00) == 0xC00) {
222 stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
224 } else if ((operand & 0xFC0) == 0xBC0) {
225 stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
227 } else if ((operand & 0xE00) == 0x800) {
228 stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
230 } else if ((operand & 0xE00) == 0xA00) {
231 stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
236 if (!(operand & 0x1000)) {
237 stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
239 } else if ((operand & 0x1800) == 0x1800) {
240 stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
242 } else if ((operand & 0x1F80) == 0x1780) {
243 stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
245 } else if ((operand & 0x1C00) == 0x1000) {
246 stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
248 } else if ((operand & 0x1C00) == 0x1400) {
249 stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
254 dasm_int_error("disasm_std_operand invalid arch");
257 stmt->u.insn.operands[out_idx] = gen_raw_code(operand);
260 static void disasm_opcode_raw(struct disassembler_context *ctx,
261 struct statement *stmt)
263 stmt->u.insn.name = gen_raw_code(stmt->u.insn.bin->opcode);
264 disasm_std_operand(stmt, 0, 0, 1);
265 disasm_std_operand(stmt, 1, 1, 1);
266 disasm_std_operand(stmt, 2, 2, 1);
269 static void disasm_constant_opcodes(struct disassembler_context *ctx,
270 struct statement *stmt)
272 struct bin_instruction *bin = stmt->u.insn.bin;
274 switch (bin->opcode) {
276 stmt->u.insn.name = "add";
277 disasm_std_operand(stmt, 0, 0, 0);
278 disasm_std_operand(stmt, 1, 1, 0);
279 disasm_std_operand(stmt, 2, 2, 0);
282 stmt->u.insn.name = "add.";
283 disasm_std_operand(stmt, 0, 0, 0);
284 disasm_std_operand(stmt, 1, 1, 0);
285 disasm_std_operand(stmt, 2, 2, 0);
288 stmt->u.insn.name = "addc";
289 disasm_std_operand(stmt, 0, 0, 0);
290 disasm_std_operand(stmt, 1, 1, 0);
291 disasm_std_operand(stmt, 2, 2, 0);
294 stmt->u.insn.name = "addc.";
295 disasm_std_operand(stmt, 0, 0, 0);
296 disasm_std_operand(stmt, 1, 1, 0);
297 disasm_std_operand(stmt, 2, 2, 0);
300 stmt->u.insn.name = "sub";
301 disasm_std_operand(stmt, 0, 0, 0);
302 disasm_std_operand(stmt, 1, 1, 0);
303 disasm_std_operand(stmt, 2, 2, 0);
306 stmt->u.insn.name = "sub.";
307 disasm_std_operand(stmt, 0, 0, 0);
308 disasm_std_operand(stmt, 1, 1, 0);
309 disasm_std_operand(stmt, 2, 2, 0);
312 stmt->u.insn.name = "subc";
313 disasm_std_operand(stmt, 0, 0, 0);
314 disasm_std_operand(stmt, 1, 1, 0);
315 disasm_std_operand(stmt, 2, 2, 0);
318 stmt->u.insn.name = "subc.";
319 disasm_std_operand(stmt, 0, 0, 0);
320 disasm_std_operand(stmt, 1, 1, 0);
321 disasm_std_operand(stmt, 2, 2, 0);
324 stmt->u.insn.name = "sra";
325 disasm_std_operand(stmt, 0, 0, 0);
326 disasm_std_operand(stmt, 1, 1, 0);
327 disasm_std_operand(stmt, 2, 2, 0);
330 stmt->u.insn.name = "or";
331 disasm_std_operand(stmt, 0, 0, 0);
332 disasm_std_operand(stmt, 1, 1, 0);
333 disasm_std_operand(stmt, 2, 2, 0);
336 stmt->u.insn.name = "and";
337 disasm_std_operand(stmt, 0, 0, 0);
338 disasm_std_operand(stmt, 1, 1, 0);
339 disasm_std_operand(stmt, 2, 2, 0);
342 stmt->u.insn.name = "xor";
343 disasm_std_operand(stmt, 0, 0, 0);
344 disasm_std_operand(stmt, 1, 1, 0);
345 disasm_std_operand(stmt, 2, 2, 0);
348 stmt->u.insn.name = "sr";
349 disasm_std_operand(stmt, 0, 0, 0);
350 disasm_std_operand(stmt, 1, 1, 0);
351 disasm_std_operand(stmt, 2, 2, 0);
354 stmt->u.insn.name = "sl";
355 disasm_std_operand(stmt, 0, 0, 0);
356 disasm_std_operand(stmt, 1, 1, 0);
357 disasm_std_operand(stmt, 2, 2, 0);
360 stmt->u.insn.name = "rl";
361 disasm_std_operand(stmt, 0, 0, 0);
362 disasm_std_operand(stmt, 1, 1, 0);
363 disasm_std_operand(stmt, 2, 2, 0);
366 stmt->u.insn.name = "rr";
367 disasm_std_operand(stmt, 0, 0, 0);
368 disasm_std_operand(stmt, 1, 1, 0);
369 disasm_std_operand(stmt, 2, 2, 0);
372 stmt->u.insn.name = "nand";
373 disasm_std_operand(stmt, 0, 0, 0);
374 disasm_std_operand(stmt, 1, 1, 0);
375 disasm_std_operand(stmt, 2, 2, 0);
378 stmt->u.insn.name = "jand";
379 stmt->u.insn.is_labelref = 2;
380 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
381 disasm_std_operand(stmt, 0, 0, 0);
382 disasm_std_operand(stmt, 1, 1, 0);
385 stmt->u.insn.name = "jnand";
386 stmt->u.insn.is_labelref = 2;
387 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
388 disasm_std_operand(stmt, 0, 0, 0);
389 disasm_std_operand(stmt, 1, 1, 0);
392 stmt->u.insn.name = "js";
393 stmt->u.insn.is_labelref = 2;
394 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
395 disasm_std_operand(stmt, 0, 0, 0);
396 disasm_std_operand(stmt, 1, 1, 0);
399 stmt->u.insn.name = "jns";
400 stmt->u.insn.is_labelref = 2;
401 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
402 disasm_std_operand(stmt, 0, 0, 0);
403 disasm_std_operand(stmt, 1, 1, 0);
406 stmt->u.insn.name = "je";
407 stmt->u.insn.is_labelref = 2;
408 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
409 disasm_std_operand(stmt, 0, 0, 0);
410 disasm_std_operand(stmt, 1, 1, 0);
413 stmt->u.insn.name = "jne";
414 stmt->u.insn.is_labelref = 2;
415 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
416 disasm_std_operand(stmt, 0, 0, 0);
417 disasm_std_operand(stmt, 1, 1, 0);
420 stmt->u.insn.name = "jls";
421 stmt->u.insn.is_labelref = 2;
422 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
423 disasm_std_operand(stmt, 0, 0, 0);
424 disasm_std_operand(stmt, 1, 1, 0);
427 stmt->u.insn.name = "jges";
428 stmt->u.insn.is_labelref = 2;
429 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
430 disasm_std_operand(stmt, 0, 0, 0);
431 disasm_std_operand(stmt, 1, 1, 0);
434 stmt->u.insn.name = "jgs";
435 stmt->u.insn.is_labelref = 2;
436 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
437 disasm_std_operand(stmt, 0, 0, 0);
438 disasm_std_operand(stmt, 1, 1, 0);
441 stmt->u.insn.name = "jles";
442 stmt->u.insn.is_labelref = 2;
443 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
444 disasm_std_operand(stmt, 0, 0, 0);
445 disasm_std_operand(stmt, 1, 1, 0);
448 stmt->u.insn.name = "jl";
449 stmt->u.insn.is_labelref = 2;
450 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
451 disasm_std_operand(stmt, 0, 0, 0);
452 disasm_std_operand(stmt, 1, 1, 0);
455 stmt->u.insn.name = "jge";
456 stmt->u.insn.is_labelref = 2;
457 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
458 disasm_std_operand(stmt, 0, 0, 0);
459 disasm_std_operand(stmt, 1, 1, 0);
462 stmt->u.insn.name = "jg";
463 stmt->u.insn.is_labelref = 2;
464 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
465 disasm_std_operand(stmt, 0, 0, 0);
466 disasm_std_operand(stmt, 1, 1, 0);
469 stmt->u.insn.name = "jle";
470 stmt->u.insn.is_labelref = 2;
471 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
472 disasm_std_operand(stmt, 0, 0, 0);
473 disasm_std_operand(stmt, 1, 1, 0);
478 switch (cmdargs.arch) {
480 stmt->u.insn.name = "call";
481 stmt->u.insn.is_labelref = 1;
482 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
484 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
485 stmt->u.insn.operands[0] = str;
488 //FIXME: This opcode is different on r15. Decode raw for now.
489 disasm_opcode_raw(ctx, stmt);
497 stmt->u.insn.name = "ret";
499 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
500 stmt->u.insn.operands[0] = str;
502 snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[2]);
503 stmt->u.insn.operands[2] = str;
506 //TODO also implement it in the assembler
509 if (cmdargs.arch != 15) {
510 dasm_error("arch 15 call instruction found in arch %d binary",
513 stmt->u.insn.name = "call";
514 stmt->u.insn.is_labelref = 0;
515 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
516 if (stmt->u.insn.bin->operands[0] != 0x1780 ||
517 stmt->u.insn.bin->operands[1] != 0x1780)
518 dasm_warn("r15 call: Invalid first or second argument");
522 if (cmdargs.arch != 15) {
523 dasm_error("arch 15 ret instruction found in arch %d binary",
526 stmt->u.insn.name = "ret";
531 unsigned int flags, mask;
533 switch (cmdargs.arch) {
541 dasm_int_error("TKIP invalid arch");
544 flags = stmt->u.insn.bin->operands[1];
545 switch (flags & mask) {
547 stmt->u.insn.name = "tkiph";
550 stmt->u.insn.name = "tkiphs";
553 stmt->u.insn.name = "tkipl";
556 stmt->u.insn.name = "tkipls";
559 dasm_error("Invalid TKIP flags %X", flags);
561 disasm_std_operand(stmt, 0, 0, 0);
562 disasm_std_operand(stmt, 2, 2, 0);
568 stmt->u.insn.name = "nap";
569 switch (cmdargs.arch) {
577 dasm_int_error("NAP invalid arch");
579 if (stmt->u.insn.bin->operands[0] != mask) {
580 dasm_warn("NAP: invalid first argument 0x%04X\n",
581 stmt->u.insn.bin->operands[0]);
583 if (stmt->u.insn.bin->operands[1] != mask) {
584 dasm_warn("NAP: invalid second argument 0x%04X\n",
585 stmt->u.insn.bin->operands[1]);
587 if (stmt->u.insn.bin->operands[2] != 0) {
588 dasm_warn("NAP: invalid third argument 0x%04X\n",
589 stmt->u.insn.bin->operands[2]);
594 disasm_opcode_raw(ctx, stmt);
599 static void disasm_opcodes(struct disassembler_context *ctx)
601 struct bin_instruction *bin;
603 struct statement *stmt;
606 for (i = 0; i < ctx->nr_insns; i++) {
607 bin = &(ctx->code[i]);
609 stmt = xmalloc(sizeof(struct statement));
610 stmt->type = STMT_INSN;
611 INIT_LIST_HEAD(&stmt->list);
612 stmt->u.insn.bin = bin;
613 stmt->u.insn.is_labelref = -1;
615 switch (bin->opcode & 0xF00) {
617 stmt->u.insn.name = "srx";
620 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
621 stmt->u.insn.operands[0] = str;
623 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
624 stmt->u.insn.operands[1] = str;
626 disasm_std_operand(stmt, 0, 2, 0);
627 disasm_std_operand(stmt, 1, 3, 0);
628 disasm_std_operand(stmt, 2, 4, 0);
631 stmt->u.insn.name = "orx";
634 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
635 stmt->u.insn.operands[0] = str;
637 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
638 stmt->u.insn.operands[1] = str;
640 disasm_std_operand(stmt, 0, 2, 0);
641 disasm_std_operand(stmt, 1, 3, 0);
642 disasm_std_operand(stmt, 2, 4, 0);
645 stmt->u.insn.name = "jzx";
648 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
649 stmt->u.insn.operands[0] = str;
651 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
652 stmt->u.insn.operands[1] = str;
654 disasm_std_operand(stmt, 0, 2, 0);
655 disasm_std_operand(stmt, 1, 3, 0);
656 stmt->u.insn.is_labelref = 4;
657 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
660 stmt->u.insn.name = "jnzx";
663 snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
664 stmt->u.insn.operands[0] = str;
666 snprintf(str, 3, "%d", (bin->opcode & 0x00F));
667 stmt->u.insn.operands[1] = str;
669 disasm_std_operand(stmt, 0, 2, 0);
670 disasm_std_operand(stmt, 1, 3, 0);
671 stmt->u.insn.is_labelref = 4;
672 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
675 stmt->u.insn.name = "jnext";
678 snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
679 stmt->u.insn.operands[0] = str;
681 /* We don't disassemble the first and second operand, as
682 * that always is a dummy r0 operand.
683 * disasm_std_operand(stmt, 0, 1, 0);
684 * disasm_std_operand(stmt, 1, 2, 0);
685 * stmt->u.insn.is_labelref = 3;
687 stmt->u.insn.is_labelref = 1;
688 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
691 stmt->u.insn.name = "jext";
694 snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
695 stmt->u.insn.operands[0] = str;
697 /* We don't disassemble the first and second operand, as
698 * that always is a dummy r0 operand.
699 * disasm_std_operand(stmt, 0, 1, 0);
700 * disasm_std_operand(stmt, 1, 2, 0);
701 * stmt->u.insn.is_labelref = 3;
703 stmt->u.insn.is_labelref = 1;
704 stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
707 disasm_constant_opcodes(ctx, stmt);
711 list_add_tail(&stmt->list, &ctx->stmt_list);
715 static struct statement * get_label_at(struct disassembler_context *ctx,
718 unsigned int addrcnt = 0;
719 struct statement *stmt, *ret, *prev;
721 list_for_each_entry(stmt, &ctx->stmt_list, list) {
722 if (stmt->type != STMT_INSN)
724 if (addrcnt == addr) {
725 prev = list_entry(stmt->list.prev, struct statement, list);
726 if (prev->type == STMT_LABEL)
728 ret = xmalloc(sizeof(struct statement));
729 INIT_LIST_HEAD(&ret->list);
730 ret->type = STMT_LABEL;
731 list_add(&ret->list, &prev->list);
741 static void resolve_labels(struct disassembler_context *ctx)
743 struct statement *stmt;
744 struct statement *label;
746 unsigned int labeladdr;
747 unsigned int namecnt = 0;
749 /* Resolve label references */
750 list_for_each_entry_safe(stmt, n, &ctx->stmt_list, list) {
751 if (stmt->type != STMT_INSN)
753 if (stmt->u.insn.is_labelref == -1)
755 labeladdr = stmt->u.insn.labeladdr;
756 label = get_label_at(ctx, labeladdr);
758 dasm_error("Labeladdress %X out of bounds", labeladdr);
759 stmt->u.insn.labelref = label;
762 /* Name the labels */
763 list_for_each_entry(stmt, &ctx->stmt_list, list) {
764 if (stmt->type != STMT_LABEL)
766 stmt->u.label.name = xmalloc(20);
767 snprintf(stmt->u.label.name, 20, "L%u", namecnt);
772 static void emit_asm(struct disassembler_context *ctx)
774 struct statement *stmt;
777 unsigned int addr = 0;
779 err = open_output_file();
783 fprintf(outfile, "%%arch %u\n", ctx->arch);
784 fprintf(outfile, "%%start entry\n\n");
785 fprintf(outfile, "entry:\n");
786 list_for_each_entry(stmt, &ctx->stmt_list, list) {
787 switch (stmt->type) {
789 if (cmdargs.print_addresses)
790 fprintf(outfile, "/* %03X */", addr);
791 fprintf(outfile, "\t%s", stmt->u.insn.name);
793 for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) {
794 if (!stmt->u.insn.operands[i] &&
795 stmt->u.insn.is_labelref != i)
798 fprintf(outfile, "\t");
800 fprintf(outfile, ", ");
802 if (stmt->u.insn.is_labelref == i) {
803 fprintf(outfile, "%s",
804 stmt->u.insn.labelref->u.label.name);
806 fprintf(outfile, "%s",
807 stmt->u.insn.operands[i]);
810 fprintf(outfile, "\n");
814 fprintf(outfile, "%s:\n", stmt->u.label.name);
822 static int read_input(struct disassembler_context *ctx)
824 size_t size = 0, pos = 0;
826 struct bin_instruction *code = NULL;
827 unsigned char tmp[sizeof(uint64_t)];
829 struct fw_header hdr;
832 err = open_input_file();
836 switch (cmdargs.informat) {
842 ret = fread(&hdr, 1, sizeof(hdr), infile);
843 if (ret != sizeof(hdr)) {
844 fprintf(stderr, "Corrupt input file (not fwcutter output)\n");
847 if (hdr.type != FW_TYPE_UCODE) {
848 fprintf(stderr, "Corrupt input file. Not a microcode image.\n");
851 if (hdr.ver != FW_HDR_VER) {
852 fprintf(stderr, "Invalid input file header version.\n");
861 code = xrealloc(code, size * sizeof(struct bin_instruction));
863 ret = fread(tmp, 1, sizeof(uint64_t), infile);
866 if (ret != sizeof(uint64_t)) {
867 fprintf(stderr, "Corrupt input file (not 8 byte aligned)\n");
871 switch (cmdargs.informat) {
875 codeword |= ((uint64_t)tmp[0]) << 56;
876 codeword |= ((uint64_t)tmp[1]) << 48;
877 codeword |= ((uint64_t)tmp[2]) << 40;
878 codeword |= ((uint64_t)tmp[3]) << 32;
879 codeword |= ((uint64_t)tmp[4]) << 24;
880 codeword |= ((uint64_t)tmp[5]) << 16;
881 codeword |= ((uint64_t)tmp[6]) << 8;
882 codeword |= ((uint64_t)tmp[7]);
883 codeword = ((codeword & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
884 ((codeword & (uint64_t)0x00000000FFFFFFFFULL) << 32);
888 codeword |= ((uint64_t)tmp[7]) << 56;
889 codeword |= ((uint64_t)tmp[6]) << 48;
890 codeword |= ((uint64_t)tmp[5]) << 40;
891 codeword |= ((uint64_t)tmp[4]) << 32;
892 codeword |= ((uint64_t)tmp[3]) << 24;
893 codeword |= ((uint64_t)tmp[2]) << 16;
894 codeword |= ((uint64_t)tmp[1]) << 8;
895 codeword |= ((uint64_t)tmp[0]);
899 switch (cmdargs.arch) {
901 if (codeword >> 48) {
902 fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
903 "Wrong input format or architecture?\n", (unsigned int)pos);
906 code[pos].opcode = (codeword >> 36) & 0xFFF;
907 code[pos].operands[2] = codeword & 0xFFF;
908 code[pos].operands[1] = (codeword >> 12) & 0xFFF;
909 code[pos].operands[0] = (codeword >> 24) & 0xFFF;
912 if (codeword >> 51) {
913 fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
914 "Wrong input format or architecture?\n", (unsigned int)pos);
917 code[pos].opcode = (codeword >> 39) & 0xFFF;
918 code[pos].operands[2] = codeword & 0x1FFF;
919 code[pos].operands[1] = (codeword >> 13) & 0x1FFF;
920 code[pos].operands[0] = (codeword >> 26) & 0x1FFF;
923 fprintf(stderr, "Internal error: read_input unknown arch %u\n",
946 static void disassemble(void)
948 struct disassembler_context ctx;
951 memset(&ctx, 0, sizeof(ctx));
952 INIT_LIST_HEAD(&ctx.stmt_list);
953 ctx.arch = cmdargs.arch;
955 err = read_input(&ctx);
958 disasm_opcodes(&ctx);
959 resolve_labels(&ctx);
963 int main(int argc, char **argv)
967 err = parse_args(argc, argv);
977 /* Lazyman simply leaks all allocated memory. */