From: Michael Buesch Date: Sun, 19 Sep 2010 14:56:34 +0000 (+0200) Subject: Disassembler: Fixes for r15 architecture X-Git-Tag: b43-fwcutter-014~47 X-Git-Url: https://jxself.org/git/?p=b43-tools.git;a=commitdiff_plain;h=f85d6d1ed19b4307c330e8c85eac3bc04a8d8f5a Disassembler: Fixes for r15 architecture Signed-off-by: Michael Buesch --- diff --git a/disassembler/args.c b/disassembler/args.c index 67ba2fc..3663c59 100644 --- a/disassembler/args.c +++ b/disassembler/args.c @@ -26,7 +26,7 @@ int _debug; struct cmdline_args cmdargs = { .arch = 5, /* Default to v5 architecture. */ - .no_header = 0, /* Input file does not have a header. */ + .informat = FMT_B43, /* Input file format */ .print_addresses = 0, /* Print the code addresses in the output. */ }; @@ -96,15 +96,16 @@ static int cmp_arg(char **argv, int *pos, return err; } -static void usage(int argc, char **argv) +static void usage(FILE *fd, int argc, char **argv) { - fprintf(stderr, "Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]); - fprintf(stderr, " -a|--arch ARCH The architecture type of the input file\n"); - fprintf(stderr, " -h|--help Print this help\n"); - fprintf(stderr, " --nohdr The input file does not have a header\n"); - fprintf(stderr, " --paddr Print the code addresses\n"); - fprintf(stderr, " -d|--debug Print verbose debugging info\n"); - fprintf(stderr, " Repeat for more verbose debugging\n"); + fprintf(fd, "Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]); + fprintf(fd, " -a|--arch ARCH The architecture type of the input file (5 or 15)\n"); + fprintf(fd, " -f|--format FMT Input file format. FMT may be one of:\n"); + fprintf(fd, " raw-le32, raw-be32, b43\n"); + fprintf(fd, " --paddr Print the code addresses\n"); + fprintf(fd, " -d|--debug Print verbose debugging info\n"); + fprintf(fd, " Repeat for more verbose debugging\n"); + fprintf(fd, " -h|--help Print this help\n"); } int parse_args(int argc, char **argv) @@ -118,10 +119,19 @@ int parse_args(int argc, char **argv) for (i = 1; i < argc; i++) { if ((res = cmp_arg(argv, &i, "--help", "-h", NULL)) == ARG_MATCH) { - usage(argc, argv); + usage(stdout, argc, argv); return 1; - } else if ((res = cmp_arg(argv, &i, "--nohdr", NULL, NULL)) == ARG_MATCH) { - cmdargs.no_header = 1; + } else if ((res = cmp_arg(argv, &i, "--format", "-f", ¶m)) == ARG_MATCH) { + if (strcasecmp(param, "raw-le32") == 0) + cmdargs.informat = FMT_RAW_LE32; + else if (strcasecmp(param, "raw-be32") == 0) + cmdargs.informat = FMT_RAW_BE32; + else if (strcasecmp(param, "b43") == 0) + cmdargs.informat = FMT_B43; + else { + fprintf(stderr, "Invalid -f|--format\n"); + return -1; + } } else if ((res = cmp_arg(argv, &i, "--paddr", NULL, NULL)) == ARG_MATCH) { cmdargs.print_addresses = 1; } else if ((res = cmp_arg(argv, &i, "--debug", "-d", NULL)) == ARG_MATCH) { @@ -131,7 +141,7 @@ int parse_args(int argc, char **argv) char *tail; arch = strtol(param, &tail, 0); - if (strlen(tail) || (arch != 5)) { + if (strlen(tail) || (arch != 5 && arch != 15)) { fprintf(stderr, "Unsupported architecture \"%s\"\n", param); return -1; @@ -155,7 +165,7 @@ int parse_args(int argc, char **argv) return 0; out_usage: - usage(argc, argv); + usage(stderr, argc, argv); return -1; } diff --git a/disassembler/args.h b/disassembler/args.h index 8dc69f2..0cb372c 100644 --- a/disassembler/args.h +++ b/disassembler/args.h @@ -1,9 +1,15 @@ #ifndef B43_DASM_ARGS_H_ #define B43_DASM_ARGS_H_ +enum fwformat { + FMT_RAW_LE32, /* Raw microcode. No headers. 32bit little endian chunks. */ + FMT_RAW_BE32, /* Raw microcode. No headers. 32bit big endian chunks. */ + FMT_B43, /* b43/b43legacy headers. */ +}; + struct cmdline_args { unsigned int arch; - int no_header; + enum fwformat informat; int print_addresses; }; diff --git a/disassembler/main.c b/disassembler/main.c index dbd2b5f..b3ba686 100644 --- a/disassembler/main.c +++ b/disassembler/main.c @@ -82,8 +82,8 @@ static const char * disasm_mem_operand(unsigned int operand) { char *ret; - ret = xmalloc(8); - snprintf(ret, 8, "[0x%03X]", operand); + ret = xmalloc(9); + snprintf(ret, 9, "[0x%X]", operand); return ret; } @@ -102,14 +102,29 @@ static const char * disasm_indirect_mem_operand(unsigned int operand) static const char * disasm_imm_operand(unsigned int operand) { char *ret; + unsigned int signmask; + unsigned int mask; + + switch (cmdargs.arch) { + case 5: + signmask = (1 << 9); + mask = 0x3FF; + break; + case 15: + signmask = (1 << 10); + mask = 0x7FF; + break; + default: + fprintf(stderr, "Internal error: disasm_imm_operand invalid arch\n"); + exit(1); + } - operand &= ~0xC00; + operand &= mask; ret = xmalloc(7); - if (operand & (1 << 9)) - snprintf(ret, 7, "0x%04X", (operand | 0xFC00)); - else - snprintf(ret, 7, "0x%03X", operand); + if (operand & signmask) + operand = (operand | (~mask & 0xFFFF)); + snprintf(ret, 7, "0x%X", operand); return ret; } @@ -117,9 +132,22 @@ static const char * disasm_imm_operand(unsigned int operand) static const char * disasm_spr_operand(unsigned int operand) { char *ret; + unsigned int mask; - ret = xmalloc(7); - snprintf(ret, 7, "spr%03X", (operand & 0x1FF)); + switch (cmdargs.arch) { + case 5: + mask = 0x1FF; + break; + case 15: + mask = 0x7FF; + break; + default: + fprintf(stderr, "Internal error: disasm_spr_operand invalid arch\n"); + exit(1); + } + + ret = xmalloc(8); + snprintf(ret, 8, "spr%X", (operand & mask)); return ret; } @@ -127,19 +155,22 @@ static const char * disasm_spr_operand(unsigned int operand) static const char * disasm_gpr_operand(unsigned int operand) { char *ret; + unsigned int mask; - ret = xmalloc(4); - snprintf(ret, 4, "r%u", (operand & 0x3F)); - - return ret; -} - -static const char * disasm_offr_operand(unsigned int operand) -{ - char *ret; + switch (cmdargs.arch) { + case 5: + mask = 0x3F; + break; + case 15: + mask = 0x7F; + break; + default: + fprintf(stderr, "Internal error: disasm_gpr_operand invalid arch\n"); + exit(1); + } ret = xmalloc(5); - snprintf(ret, 5, "off%u", (operand & 0x7)); + snprintf(ret, 5, "r%u", (operand & mask)); return ret; } @@ -154,24 +185,46 @@ static void disasm_std_operand(struct statement *stmt, if (forceraw) goto raw; - if (!(operand & 0x800)) { - stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand); - return; - } else if ((operand & 0xC00) == 0xC00) { - stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand); - return; - } else if ((operand & 0xFC0) == 0xBC0) { - stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand); - return; - } else if ((operand & 0xE00) == 0x800) { - stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand); - return; - } else if ((operand & 0xFF8) == 0x860) { - stmt->u.insn.operands[out_idx] = disasm_offr_operand(operand); - return; - } else if ((operand & 0xE00) == 0xA00) { - stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand); - return; + switch (cmdargs.arch) { + case 5: + if (!(operand & 0x800)) { + stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand); + return; + } else if ((operand & 0xC00) == 0xC00) { + stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand); + return; + } else if ((operand & 0xFC0) == 0xBC0) { + stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand); + return; + } else if ((operand & 0xE00) == 0x800) { + stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand); + return; + } else if ((operand & 0xE00) == 0xA00) { + stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand); + return; + } + break; + case 15: + if (!(operand & 0x1000)) { + stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand); + return; + } else if ((operand & 0x1800) == 0x1800) { + stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand); + return; + } else if ((operand & 0x1F80) == 0x1780) { + stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand); + return; + } else if ((operand & 0x1C00) == 0x1000) { + stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand); + return; + } else if ((operand & 0x1C00) == 0x1400) { + stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand); + return; + } + break; + default: + fprintf(stderr, "Internal error: disasm_std_operand invalid arch\n"); + exit(1); } raw: stmt->u.insn.operands[out_idx] = gen_raw_code(operand); @@ -386,8 +439,10 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, case 0x002: { char *str; + //FIXME: Broken for r15 stmt->u.insn.name = "call"; stmt->u.insn.is_labelref = 1; +//printf("CALL 0x%X 0x%X 0x%X\n", stmt->u.insn.bin->operands[0], stmt->u.insn.bin->operands[1], stmt->u.insn.bin->operands[2]); stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2]; str = xmalloc(4); snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]); @@ -407,10 +462,22 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, break; } case 0x1E0: { - unsigned int flags; + unsigned int flags, mask; + + switch (cmdargs.arch) { + case 5: + mask = 0x3FF; + break; + case 15: + mask = 0x7FF; + break; + default: + fprintf(stderr, "Internal error: TKIP invalid arch\n"); + exit(1); + } flags = stmt->u.insn.bin->operands[1]; - switch (flags & ~0xC00) { + switch (flags & mask) { case 0x1: stmt->u.insn.name = "tkiph"; break; @@ -433,17 +500,30 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, break; } case 0x001: { + unsigned int mask; + stmt->u.insn.name = "nap"; - if (stmt->u.insn.bin->operands[0] != 0xBC0) { - fprintf(stderr, "NAP: invalid first argument 0x%03X\n", + switch (cmdargs.arch) { + case 5: + mask = 0xBC0; + break; + case 15: + mask = 0x1780; + break; + default: + fprintf(stderr, "Internal error: NAP invalid arch\n"); + exit(1); + } + if (stmt->u.insn.bin->operands[0] != mask) { + fprintf(stderr, "NAP: invalid first argument 0x%04X\n", stmt->u.insn.bin->operands[0]); } - if (stmt->u.insn.bin->operands[1] != 0xBC0) { - fprintf(stderr, "NAP: invalid second argument 0x%03X\n", + if (stmt->u.insn.bin->operands[1] != mask) { + fprintf(stderr, "NAP: invalid second argument 0x%04X\n", stmt->u.insn.bin->operands[1]); } - if (stmt->u.insn.bin->operands[2] != 0x000) { - fprintf(stderr, "NAP: invalid third argument 0x%03X\n", + if (stmt->u.insn.bin->operands[2] != 0) { + fprintf(stderr, "NAP: invalid third argument 0x%04X\n", stmt->u.insn.bin->operands[2]); } break; @@ -693,7 +773,12 @@ static int read_input(struct disassembler_context *ctx) if (err) goto error; - if (!cmdargs.no_header) { + switch (cmdargs.informat) { + case FMT_RAW_LE32: + case FMT_RAW_BE32: + /* Nothing */ + break; + case FMT_B43: ret = fread(&hdr, 1, sizeof(hdr), infile); if (ret != sizeof(hdr)) { fprintf(stderr, "Corrupt input file (not fwcutter output)\n"); @@ -707,6 +792,7 @@ static int read_input(struct disassembler_context *ctx) fprintf(stderr, "Invalid input file header version.\n"); goto err_close; } + break; } while (1) { @@ -722,21 +808,62 @@ static int read_input(struct disassembler_context *ctx) goto err_free_code; } - codeword = 0; - codeword |= ((uint64_t)tmp[0]) << 56; - codeword |= ((uint64_t)tmp[1]) << 48; - codeword |= ((uint64_t)tmp[2]) << 40; - codeword |= ((uint64_t)tmp[3]) << 32; - codeword |= ((uint64_t)tmp[4]) << 24; - codeword |= ((uint64_t)tmp[5]) << 16; - codeword |= ((uint64_t)tmp[6]) << 8; - codeword |= ((uint64_t)tmp[7]); - - code[pos].opcode = (codeword >> 4) & 0xFFF; - code[pos].operands[0] = (codeword & 0xF) << 8; - code[pos].operands[0] |= (codeword >> 56) & 0xFF; - code[pos].operands[1] = (codeword >> 44) & 0xFFF; - code[pos].operands[2] = (codeword >> 32) & 0xFFF; + switch (cmdargs.informat) { + case FMT_B43: + case FMT_RAW_BE32: + codeword = 0; + codeword |= ((uint64_t)tmp[0]) << 56; + codeword |= ((uint64_t)tmp[1]) << 48; + codeword |= ((uint64_t)tmp[2]) << 40; + codeword |= ((uint64_t)tmp[3]) << 32; + codeword |= ((uint64_t)tmp[4]) << 24; + codeword |= ((uint64_t)tmp[5]) << 16; + codeword |= ((uint64_t)tmp[6]) << 8; + codeword |= ((uint64_t)tmp[7]); + codeword = ((codeword & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) | + ((codeword & (uint64_t)0x00000000FFFFFFFFULL) << 32); + break; + case FMT_RAW_LE32: + codeword = 0; + codeword |= ((uint64_t)tmp[7]) << 56; + codeword |= ((uint64_t)tmp[6]) << 48; + codeword |= ((uint64_t)tmp[5]) << 40; + codeword |= ((uint64_t)tmp[4]) << 32; + codeword |= ((uint64_t)tmp[3]) << 24; + codeword |= ((uint64_t)tmp[2]) << 16; + codeword |= ((uint64_t)tmp[1]) << 8; + codeword |= ((uint64_t)tmp[0]); + break; + } + + switch (cmdargs.arch) { + case 5: + if (codeword >> 48) { + fprintf(stderr, "Instruction format error at 0x%X (upper not clear). " + "Wrong input format or architecture?\n", (unsigned int)pos); + goto err_free_code; + } + code[pos].opcode = (codeword >> 36) & 0xFFF; + code[pos].operands[2] = codeword & 0xFFF; + code[pos].operands[1] = (codeword >> 12) & 0xFFF; + code[pos].operands[0] = (codeword >> 24) & 0xFFF; + break; + case 15: + if (codeword >> 51) { + fprintf(stderr, "Instruction format error at 0x%X (upper not clear). " + "Wrong input format or architecture?\n", (unsigned int)pos); + goto err_free_code; + } + code[pos].opcode = (codeword >> 39) & 0xFFF; + code[pos].operands[2] = codeword & 0x1FFF; + code[pos].operands[1] = (codeword >> 13) & 0x1FFF; + code[pos].operands[0] = (codeword >> 26) & 0x1FFF; + break; + default: + fprintf(stderr, "Internal error: read_input unknown arch %u\n", + cmdargs.arch); + goto err_free_code; + } pos++; }