From d1a8976facb28d18ef9d3a29de5bd1bd721f3394 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Sep 2010 17:42:39 +0200 Subject: [PATCH] assembler: Add support for raw output format Signed-off-by: Michael Buesch --- assembler/args.c | 17 +++++++- assembler/args.h | 7 ++++ assembler/main.c | 99 +++++++++++++++++++++++++++++---------------- assembler/main.h | 2 +- disassembler/args.c | 2 +- 5 files changed, 89 insertions(+), 38 deletions(-) diff --git a/assembler/args.c b/assembler/args.c index b2a8ddf..42d9c18 100644 --- a/assembler/args.c +++ b/assembler/args.c @@ -26,6 +26,7 @@ int _debug; bool arg_print_sizes; const char *initvals_fn_extension = ".initvals"; static const char *real_infile_name; +enum fwformat output_format = FMT_B43; #define ARG_MATCH 0 @@ -97,17 +98,20 @@ static int cmp_arg(char **argv, int *pos, static void usage(int argc, char **argv) { printf("Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]); - printf(" -h|--help Print this help\n"); + printf(" -f|--format FMT Output file format. FMT must be one of:\n"); + printf(" raw-le32, raw-be32, b43\n"); printf(" -d|--debug Print verbose debugging info\n"); printf(" Repeat for more verbose debugging\n"); printf(" -s|--psize Print the size of the code after assembling\n"); printf(" -e|--ivalext EXT Filename extension for the initvals\n"); + printf(" -h|--help Print this help\n"); } int parse_args(int argc, char **argv) { int i; int res; + const char *param; if (argc < 3) goto out_usage; @@ -118,6 +122,17 @@ int parse_args(int argc, char **argv) if ((res = cmp_arg(argv, &i, "--help", "-h", NULL)) == ARG_MATCH) { usage(argc, argv); return 1; + } else if ((res = cmp_arg(argv, &i, "--format", "-f", ¶m)) == ARG_MATCH) { + if (strcasecmp(param, "raw-le32") == 0) + output_format = FMT_RAW_LE32; + else if (strcasecmp(param, "raw-be32") == 0) + output_format = FMT_RAW_BE32; + else if (strcasecmp(param, "b43") == 0) + output_format = FMT_B43; + else { + fprintf(stderr, "Invalid -f|--format\n\n"); + goto out_usage; + } } else if ((res = cmp_arg(argv, &i, "--debug", "-d", NULL)) == ARG_MATCH) { _debug++; } else if ((res = cmp_arg(argv, &i, "--psize", "-s", NULL)) == ARG_MATCH) { diff --git a/assembler/args.h b/assembler/args.h index 06f8ca3..fc3abc1 100644 --- a/assembler/args.h +++ b/assembler/args.h @@ -4,6 +4,12 @@ #include "util.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. */ +}; + int parse_args(int argc, char **argv); int open_input_file(void); void close_input_file(void); @@ -11,6 +17,7 @@ void close_input_file(void); extern int _debug; extern bool arg_print_sizes; extern const char *initvals_fn_extension; +extern enum fwformat output_format; #define IS_DEBUG (_debug > 0) #define IS_VERBOSE_DEBUG (_debug > 1) diff --git a/assembler/main.c b/assembler/main.c index 309d7c5..6b294a4 100644 --- a/assembler/main.c +++ b/assembler/main.c @@ -1048,7 +1048,7 @@ static void emit_code(struct assembler_context *ctx) struct code_output *c; uint64_t code; unsigned char outbuf[8]; - unsigned int insn_count = 0; + unsigned int insn_count = 0, insn_count_limit; struct fw_header hdr; fn = outfile_name; @@ -1070,19 +1070,37 @@ static void emit_code(struct assembler_context *ctx) } } - memset(&hdr, 0, sizeof(hdr)); - hdr.type = FW_TYPE_UCODE; - hdr.ver = FW_HDR_VER; - hdr.size = cpu_to_be32(8 * insn_count); - if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) { - fprintf(stderr, "Could not write microcode outfile\n"); - exit(1); + switch (output_format) { + case FMT_RAW_LE32: + case FMT_RAW_BE32: + /* Nothing */ + break; + case FMT_B43: + memset(&hdr, 0, sizeof(hdr)); + hdr.type = FW_TYPE_UCODE; + hdr.ver = FW_HDR_VER; + hdr.size = cpu_to_be32(8 * insn_count); + if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) { + fprintf(stderr, "Could not write microcode outfile\n"); + exit(1); + } + break; } - if (insn_count > NUM_INSN_LIMIT) - asm_warn(ctx, "Generating more than %d instructions. This " + switch (ctx->arch) { + case 5: + insn_count_limit = NUM_INSN_LIMIT_R5; + break; + case 15: + insn_count_limit = ~0; //FIXME limit currently unknown. + break; + default: + asm_error(ctx, "Internal error: emit_code unknown arch\n"); + } + if (insn_count > insn_count_limit) + asm_warn(ctx, "Generating more than %u instructions. This " "will overflow the device microcode memory.", - NUM_INSN_LIMIT); + insn_count_limit); list_for_each_entry(c, &ctx->output, list) { switch (c->type) { @@ -1094,41 +1112,52 @@ static void emit_code(struct assembler_context *ctx) c->operands[1].u.operand, c->operands[2].u.operand); } - code = 0; - - if (ctx->arch == 5) { - /* Instruction binary format is: xxyyyzzz0000oooX - * byte-0-^ byte-7-^ - * ooo is the opcode - * Xxx is the first operand - * yyy is the second operand - * zzz is the third operand - */ + + switch (ctx->arch) { + case 5: + code = 0; code |= ((uint64_t)c->operands[2].u.operand); code |= ((uint64_t)c->operands[1].u.operand) << 12; code |= ((uint64_t)c->operands[0].u.operand) << 24; code |= ((uint64_t)c->opcode) << 36; - code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) | - ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32); - } else if (ctx->arch == 15) { + break; + case 15: + code = 0; code |= ((uint64_t)c->operands[2].u.operand); code |= ((uint64_t)c->operands[1].u.operand) << 13; code |= ((uint64_t)c->operands[0].u.operand) << 26; code |= ((uint64_t)c->opcode) << 39; - code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) | - ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32); - } else { + break; + default: asm_error(ctx, "No emit format for arch %u", ctx->arch); } - outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56; - outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48; - outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40; - outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32; - outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24; - outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16; - outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8; - outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0; + + switch (output_format) { + case FMT_B43: + case FMT_RAW_BE32: + code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) | + ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32); + outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56; + outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48; + outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40; + outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32; + outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24; + outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16; + outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8; + outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0; + break; + case FMT_RAW_LE32: + outbuf[7] = (code & (uint64_t)0xFF00000000000000ULL) >> 56; + outbuf[6] = (code & (uint64_t)0x00FF000000000000ULL) >> 48; + outbuf[5] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40; + outbuf[4] = (code & (uint64_t)0x000000FF00000000ULL) >> 32; + outbuf[3] = (code & (uint64_t)0x00000000FF000000ULL) >> 24; + outbuf[2] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16; + outbuf[1] = (code & (uint64_t)0x000000000000FF00ULL) >> 8; + outbuf[0] = (code & (uint64_t)0x00000000000000FFULL) >> 0; + break; + } if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) { fprintf(stderr, "Could not write microcode outfile\n"); diff --git a/assembler/main.h b/assembler/main.h index e325f03..f5c2234 100644 --- a/assembler/main.h +++ b/assembler/main.h @@ -30,7 +30,7 @@ struct fw_header { /* Maximum number of allowed instructions in the code output. * This is what device memory can hold at maximum. */ -#define NUM_INSN_LIMIT 4096 +#define NUM_INSN_LIMIT_R5 4096 struct lineinfo { diff --git a/disassembler/args.c b/disassembler/args.c index 3663c59..7fc2978 100644 --- a/disassembler/args.c +++ b/disassembler/args.c @@ -100,7 +100,7 @@ static void usage(FILE *fd, int argc, char **argv) { 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, " -f|--format FMT Input file format. FMT must 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"); -- 2.31.1