From 88eca946bfdcb1ec27b2bae849152bc2a7b6872a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Sep 2010 18:30:59 +0200 Subject: [PATCH] assembler/disassembler: Fix indirect mem addressing for r15 Signed-off-by: Michael Buesch --- assembler/main.c | 65 ++++++++++++++++++++++++++------------------- assembler/scanner.l | 2 +- disassembler/main.c | 21 ++++++++++++--- 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/assembler/main.c b/assembler/main.c index 6b294a4..c4cad33 100644 --- a/assembler/main.c +++ b/assembler/main.c @@ -169,6 +169,17 @@ static bool is_possible_imm(unsigned int imm) return 1; } +static unsigned int immediate_nr_bits(struct assembler_context *ctx) +{ + switch (ctx->arch) { + case 5: + return 10; /* 10 bits */ + case 15: + return 11; /* 11 bits */ + } + asm_error(ctx, "Internal error: immediate_nr_bits unknown arch\n"); +} + static bool is_valid_imm(struct assembler_context *ctx, unsigned int imm) { @@ -189,14 +200,7 @@ static bool is_valid_imm(struct assembler_context *ctx, return 0; imm &= 0xFFFF; - if (ctx->arch == 5) { - immediate_size = 10; /* 10bit */ - } else if (ctx->arch == 15) { - immediate_size = 11; /* 11bit */ - } else { - asm_error(ctx, "Unknown immediate size for arch %u", - ctx->arch); - } + immediate_size = immediate_nr_bits(ctx); /* First create a mask with all possible bits for * an immediate value unset. */ @@ -253,8 +257,6 @@ static unsigned int generate_imm_operand(struct assembler_context *ctx, unsigned int val, tmp; unsigned int mask; - /* format: 0b11ii iiii iiii */ - val = 0xC00; if (ctx->arch == 15) val <<= 1; @@ -262,9 +264,9 @@ static unsigned int generate_imm_operand(struct assembler_context *ctx, if (!is_valid_imm(ctx, tmp)) { asm_warn(ctx, "IMMEDIATE 0x%X (%d) too long " - "(> 9 bits + sign). Did you intend to " + "(> %u bits + sign). Did you intend to " "use implicit sign extension?", - tmp, (int)tmp); + tmp, (int)tmp, immediate_nr_bits(ctx) - 1); } if (ctx->arch == 15) @@ -283,16 +285,14 @@ static unsigned int generate_reg_operand(struct assembler_context *ctx, switch (reg->type) { case GPR: - /* format: 0b1011 11rr rrrr */ val |= 0xBC0; if (ctx->arch == 15) val <<= 1; - if (reg->nr & ~0x3F) //FIXME 128 regs for v15 arch possible? + if (reg->nr & ~0x3F) /* REVISIT: 128 regs for v15 arch possible? Probably not... */ asm_error(ctx, "GPR-nr too big"); val |= reg->nr; break; case SPR: - /* format: 0b100. .... .... */ val |= 0x800; if (ctx->arch == 15) val <<= 1; @@ -301,7 +301,6 @@ static unsigned int generate_reg_operand(struct assembler_context *ctx, val |= reg->nr; break; case OFFR: - /* format: 0b1000 0110 0rrr */ val |= 0x860; if (ctx->arch == 15) val <<= 1; @@ -319,11 +318,10 @@ static unsigned int generate_reg_operand(struct assembler_context *ctx, static unsigned int generate_mem_operand(struct assembler_context *ctx, const struct memory *mem) { - unsigned int val = 0, off, reg; + unsigned int val = 0, off, reg, off_mask, reg_shift; switch (mem->type) { case MEM_DIRECT: - /* format: 0b0mmm mmmm mmmm */ off = mem->offset; switch (ctx->arch) { case 5: @@ -344,25 +342,38 @@ static unsigned int generate_mem_operand(struct assembler_context *ctx, val |= off; break; case MEM_INDIRECT: - /* format: 0b101r rroo oooo */ + switch (ctx->arch) { + case 5: + val = 0xA00; + off_mask = 0x3F; + reg_shift = 6; + break; + case 15: + val = 0x1400; + off_mask = 0x7F; + reg_shift = 7; + break; + default: + asm_error(ctx, "Internal error: MEM_INDIRECT invalid arch\n"); + } + off = mem->offset; reg = mem->offr_nr; - val |= 0xA00; - //FIXME what about v15 arch? - if (off & ~0x3F) { - asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> 6 bits)", off); - off &= 0x3F; + if (off & ~off_mask) { + asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> %u bits)", + off, reg_shift); + off &= off_mask; } if (reg > 6) { /* Assembler bug. The parser shouldn't pass this value. */ asm_error(ctx, "OFFR-nr too big"); } - if (reg == 6 && ctx->arch == 5) { + if (reg == 6) { asm_warn(ctx, "Using offset register 6. This register is broken " - "on architecture 5 devices. Use off0 to off5 only."); + "on certain devices. Use off0 to off5 only."); } val |= off; - val |= (reg << 6); + val |= (reg << reg_shift); break; default: asm_error(ctx, "generate_mem_operand() memtype"); diff --git a/assembler/scanner.l b/assembler/scanner.l index a9928da..80b204f 100644 --- a/assembler/scanner.l +++ b/assembler/scanner.l @@ -144,7 +144,7 @@ shm16 { update_lineinfo(); return IVAL_SHM16; } shm32 { update_lineinfo(); return IVAL_SHM32; } tram { update_lineinfo(); return IVAL_TRAM; } -@[0-9a-fA-F]{3,3} { update_lineinfo(); return RAW_CODE; } +@[0-9a-fA-F]{1,4} { update_lineinfo(); return RAW_CODE; } 0x[0-9a-fA-F]+ { update_lineinfo(); return HEXNUM; } -?[0-9]+ { update_lineinfo(); return DECNUM; } diff --git a/disassembler/main.c b/disassembler/main.c index 43415a1..869a629 100644 --- a/disassembler/main.c +++ b/disassembler/main.c @@ -72,8 +72,8 @@ static const char * gen_raw_code(unsigned int operand) { char *ret; - ret = xmalloc(5); - snprintf(ret, 5, "@%03X", operand); + ret = xmalloc(6); + snprintf(ret, 6, "@%X", operand); return ret; } @@ -91,10 +91,23 @@ static const char * disasm_mem_operand(unsigned int operand) static const char * disasm_indirect_mem_operand(unsigned int operand) { char *ret; + unsigned int offset, reg; + switch (cmdargs.arch) { + case 5: + offset = (operand & 0x3F); + reg = ((operand >> 6) & 0x7); + break; + case 15: + offset = (operand & 0x7F); + reg = ((operand >> 7) & 0x7); + break; + default: + fprintf(stderr, "Internal error: disasm_indirect_mem_operand invalid arch\n"); + exit(1); + } ret = xmalloc(12); - snprintf(ret, 12, "[0x%02X,off%u]", - (operand & 0x3F), ((operand >> 6) & 0x7)); //FIXME r15? + snprintf(ret, 12, "[0x%02X,off%u]", offset, reg); return ret; } -- 2.31.1